summaryrefslogtreecommitdiff
path: root/storage/ndb/src/kernel
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2014-08-21 18:11:46 +0200
committerSergei Golubchik <serg@mariadb.org>2014-10-11 18:53:06 +0200
commit7f5e51b940d65cf541403a50af74163b9aed5cb8 (patch)
treee540d3cd4d678cd276a9d496490ac5e527f30a78 /storage/ndb/src/kernel
parent57dd1f6f3fcbc7a46e1b3e71257987315f7aa687 (diff)
downloadmariadb-git-7f5e51b940d65cf541403a50af74163b9aed5cb8.tar.gz
MDEV-34 delete storage/ndb and sql/*ndb* (and collateral changes)
remove: * NDB from everywhere * IM from mtr-v1 * packaging/rpm-oel and packaging/rpm-uln * few unused spec files * plug.in file * .bzrignore
Diffstat (limited to 'storage/ndb/src/kernel')
-rw-r--r--storage/ndb/src/kernel/Makefile.am73
-rw-r--r--storage/ndb/src/kernel/SimBlockList.cpp136
-rw-r--r--storage/ndb/src/kernel/blocks/ERROR_codes.txt565
-rw-r--r--storage/ndb/src/kernel/blocks/Makefile.am68
-rw-r--r--storage/ndb/src/kernel/blocks/NodeRestart.new.txt82
-rw-r--r--storage/ndb/src/kernel/blocks/NodeRestart.txt80
-rw-r--r--storage/ndb/src/kernel/blocks/OptNR.txt49
-rw-r--r--storage/ndb/src/kernel/blocks/Start.txt97
-rw-r--r--storage/ndb/src/kernel/blocks/SystemRestart.new.txt61
-rw-r--r--storage/ndb/src/kernel/blocks/SystemRestart.txt61
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Backup.cpp5144
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Backup.hpp752
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Backup.txt427
-rw-r--r--storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp197
-rw-r--r--storage/ndb/src/kernel/blocks/backup/BackupInit.cpp259
-rw-r--r--storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp360
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Makefile.am26
-rw-r--r--storage/ndb/src/kernel/blocks/backup/read.cpp523
-rw-r--r--storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp1453
-rw-r--r--storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp118
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp1106
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp220
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp8549
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/CreateIndex.txt152
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/CreateTable.new.txt29
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/CreateTable.txt35
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp16702
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp2707
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.txt88
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/DictLock.txt98
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/DropTable.txt140
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Event.txt102
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Makefile.am33
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Master_AddTable.sfl765
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp90
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Slave_AddTable.sfl436
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp285
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp1673
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp333
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp15878
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/LCP.txt35
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/Makefile.am27
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp275
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp160
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/printSysfile/Makefile12
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/printSysfile/printSysfile.cpp158
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp3029
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp415
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp19357
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/Makefile.am29
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/redoLogReader/reader.cpp416
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp336
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp250
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp1978
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp378
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp13612
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp136
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp3070
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp423
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp275
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp749
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp450
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp1893
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp3205
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp285
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp749
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp737
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp1486
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp390
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp602
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp1687
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp1209
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp238
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp317
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp1291
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp420
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Makefile.am26
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Notes.txt198
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp116
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp57
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp297
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp480
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp266
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp1208
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp175
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp417
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp338
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp182
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp512
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp590
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp1123
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp432
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxStat.cpp159
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp717
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/Times.txt151
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/tuxstatus.html120
-rw-r--r--storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp2608
-rw-r--r--storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp485
-rw-r--r--storage/ndb/src/kernel/blocks/dbutil/DbUtil.txt68
-rw-r--r--storage/ndb/src/kernel/blocks/diskpage.cpp90
-rw-r--r--storage/ndb/src/kernel/blocks/diskpage.hpp242
-rw-r--r--storage/ndb/src/kernel/blocks/lgman.cpp3209
-rw-r--r--storage/ndb/src/kernel/blocks/lgman.hpp367
-rw-r--r--storage/ndb/src/kernel/blocks/mutexes.hpp39
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp388
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp121
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp3094
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrSysTable.cpp102
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp1387
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp252
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/AsyncFileTest.cpp695
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/Makefile27
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.cpp20
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp116
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp192
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp98
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.cpp18
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp179
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/Makefile13
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/MemoryChannelTest.cpp193
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp1109
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp131
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp120
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp261
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp215
-rw-r--r--storage/ndb/src/kernel/blocks/new-block.tar.gzbin1816 -> 0 bytes
-rw-r--r--storage/ndb/src/kernel/blocks/pgman.cpp2514
-rw-r--r--storage/ndb/src/kernel/blocks/pgman.hpp682
-rw-r--r--storage/ndb/src/kernel/blocks/print_file.cpp417
-rw-r--r--storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp471
-rw-r--r--storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp145
-rw-r--r--storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp5268
-rw-r--r--storage/ndb/src/kernel/blocks/qmgr/timer.hpp72
-rw-r--r--storage/ndb/src/kernel/blocks/record_types.hpp59
-rw-r--r--storage/ndb/src/kernel/blocks/restore.cpp1286
-rw-r--r--storage/ndb/src/kernel/blocks/restore.hpp159
-rw-r--r--storage/ndb/src/kernel/blocks/suma/Suma.cpp5202
-rw-r--r--storage/ndb/src/kernel/blocks/suma/Suma.hpp635
-rw-r--r--storage/ndb/src/kernel/blocks/suma/Suma.txt192
-rw-r--r--storage/ndb/src/kernel/blocks/suma/SumaInit.cpp136
-rw-r--r--storage/ndb/src/kernel/blocks/trix/Trix.cpp997
-rw-r--r--storage/ndb/src/kernel/blocks/trix/Trix.hpp189
-rw-r--r--storage/ndb/src/kernel/blocks/tsman.cpp2224
-rw-r--r--storage/ndb/src/kernel/blocks/tsman.hpp453
-rw-r--r--storage/ndb/src/kernel/error/ErrorHandlingMacros.hpp57
-rw-r--r--storage/ndb/src/kernel/error/ErrorReporter.cpp406
-rw-r--r--storage/ndb/src/kernel/error/ErrorReporter.hpp57
-rw-r--r--storage/ndb/src/kernel/error/Makefile.am38
-rw-r--r--storage/ndb/src/kernel/error/TimeModule.cpp109
-rw-r--r--storage/ndb/src/kernel/error/TimeModule.hpp46
-rw-r--r--storage/ndb/src/kernel/error/ndbd_exit_codes.c275
-rw-r--r--storage/ndb/src/kernel/main.cpp653
-rw-r--r--storage/ndb/src/kernel/vm/Array.hpp165
-rw-r--r--storage/ndb/src/kernel/vm/ArrayPool.hpp985
-rw-r--r--storage/ndb/src/kernel/vm/CArray.hpp149
-rw-r--r--storage/ndb/src/kernel/vm/Callback.hpp24
-rw-r--r--storage/ndb/src/kernel/vm/ClusterConfiguration.cpp484
-rw-r--r--storage/ndb/src/kernel/vm/ClusterConfiguration.hpp105
-rw-r--r--storage/ndb/src/kernel/vm/Configuration.cpp902
-rw-r--r--storage/ndb/src/kernel/vm/Configuration.hpp152
-rw-r--r--storage/ndb/src/kernel/vm/DLCFifoList.hpp119
-rw-r--r--storage/ndb/src/kernel/vm/DLCHashTable.hpp82
-rw-r--r--storage/ndb/src/kernel/vm/DLFifoList.hpp475
-rw-r--r--storage/ndb/src/kernel/vm/DLHashTable.hpp519
-rw-r--r--storage/ndb/src/kernel/vm/DLHashTable2.hpp515
-rw-r--r--storage/ndb/src/kernel/vm/DLList.hpp438
-rw-r--r--storage/ndb/src/kernel/vm/DataBuffer.hpp533
-rw-r--r--storage/ndb/src/kernel/vm/DynArr256.cpp1021
-rw-r--r--storage/ndb/src/kernel/vm/DynArr256.hpp85
-rw-r--r--storage/ndb/src/kernel/vm/Emulator.cpp292
-rw-r--r--storage/ndb/src/kernel/vm/Emulator.hpp109
-rw-r--r--storage/ndb/src/kernel/vm/FastScheduler.cpp500
-rw-r--r--storage/ndb/src/kernel/vm/FastScheduler.hpp345
-rw-r--r--storage/ndb/src/kernel/vm/GlobalData.hpp123
-rw-r--r--storage/ndb/src/kernel/vm/KeyDescriptor.hpp43
-rw-r--r--storage/ndb/src/kernel/vm/KeyTable.hpp52
-rw-r--r--storage/ndb/src/kernel/vm/KeyTable2.hpp115
-rw-r--r--storage/ndb/src/kernel/vm/KeyTable2Ref.hpp65
-rw-r--r--storage/ndb/src/kernel/vm/LinearPool.hpp656
-rw-r--r--storage/ndb/src/kernel/vm/LongSignal.hpp80
-rw-r--r--storage/ndb/src/kernel/vm/Makefile.am86
-rw-r--r--storage/ndb/src/kernel/vm/Mutex.cpp287
-rw-r--r--storage/ndb/src/kernel/vm/Mutex.hpp267
-rw-r--r--storage/ndb/src/kernel/vm/NdbdSuperPool.cpp228
-rw-r--r--storage/ndb/src/kernel/vm/NdbdSuperPool.hpp55
-rw-r--r--storage/ndb/src/kernel/vm/Pool.cpp44
-rw-r--r--storage/ndb/src/kernel/vm/Pool.hpp341
-rw-r--r--storage/ndb/src/kernel/vm/Prio.hpp32
-rw-r--r--storage/ndb/src/kernel/vm/RWPool.cpp230
-rw-r--r--storage/ndb/src/kernel/vm/RWPool.hpp78
-rw-r--r--storage/ndb/src/kernel/vm/RequestTracker.hpp58
-rw-r--r--storage/ndb/src/kernel/vm/Rope.cpp189
-rw-r--r--storage/ndb/src/kernel/vm/Rope.hpp117
-rw-r--r--storage/ndb/src/kernel/vm/SLFifoList.hpp343
-rw-r--r--storage/ndb/src/kernel/vm/SLList.hpp402
-rw-r--r--storage/ndb/src/kernel/vm/SafeCounter.cpp159
-rw-r--r--storage/ndb/src/kernel/vm/SafeCounter.hpp307
-rw-r--r--storage/ndb/src/kernel/vm/SectionReader.cpp143
-rw-r--r--storage/ndb/src/kernel/vm/SectionReader.hpp49
-rw-r--r--storage/ndb/src/kernel/vm/SignalCounter.hpp166
-rw-r--r--storage/ndb/src/kernel/vm/SimBlockList.hpp48
-rw-r--r--storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp223
-rw-r--r--storage/ndb/src/kernel/vm/SimulatedBlock.cpp2082
-rw-r--r--storage/ndb/src/kernel/vm/SimulatedBlock.hpp824
-rw-r--r--storage/ndb/src/kernel/vm/SuperPool.cpp750
-rw-r--r--storage/ndb/src/kernel/vm/SuperPool.hpp592
-rw-r--r--storage/ndb/src/kernel/vm/ThreadConfig.cpp183
-rw-r--r--storage/ndb/src/kernel/vm/ThreadConfig.hpp39
-rw-r--r--storage/ndb/src/kernel/vm/TimeQueue.cpp208
-rw-r--r--storage/ndb/src/kernel/vm/TimeQueue.hpp62
-rw-r--r--storage/ndb/src/kernel/vm/TransporterCallback.cpp512
-rw-r--r--storage/ndb/src/kernel/vm/VMSignal.cpp34
-rw-r--r--storage/ndb/src/kernel/vm/VMSignal.hpp208
-rw-r--r--storage/ndb/src/kernel/vm/WOPool.cpp137
-rw-r--r--storage/ndb/src/kernel/vm/WOPool.hpp123
-rw-r--r--storage/ndb/src/kernel/vm/WaitQueue.hpp35
-rw-r--r--storage/ndb/src/kernel/vm/WatchDog.cpp200
-rw-r--r--storage/ndb/src/kernel/vm/WatchDog.hpp56
-rw-r--r--storage/ndb/src/kernel/vm/al_test/Makefile12
-rw-r--r--storage/ndb/src/kernel/vm/al_test/arrayListTest.cpp317
-rw-r--r--storage/ndb/src/kernel/vm/al_test/arrayPoolTest.cpp298
-rw-r--r--storage/ndb/src/kernel/vm/al_test/main.cpp69
-rw-r--r--storage/ndb/src/kernel/vm/bench_pool.cpp608
-rw-r--r--storage/ndb/src/kernel/vm/mem.txt34
-rw-r--r--storage/ndb/src/kernel/vm/ndbd_malloc.cpp65
-rw-r--r--storage/ndb/src/kernel/vm/ndbd_malloc.hpp26
-rw-r--r--storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp1016
-rw-r--r--storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp200
-rw-r--r--storage/ndb/src/kernel/vm/pc.hpp237
-rw-r--r--storage/ndb/src/kernel/vm/testCopy/Makefile9
-rw-r--r--storage/ndb/src/kernel/vm/testCopy/rr.cpp32
-rw-r--r--storage/ndb/src/kernel/vm/testCopy/testCopy.cpp341
-rw-r--r--storage/ndb/src/kernel/vm/testDataBuffer/Makefile10
-rw-r--r--storage/ndb/src/kernel/vm/testDataBuffer/testDataBuffer.cpp188
-rw-r--r--storage/ndb/src/kernel/vm/testLongSig/Makefile9
-rw-r--r--storage/ndb/src/kernel/vm/testLongSig/testLongSig.cpp333
-rw-r--r--storage/ndb/src/kernel/vm/testSimplePropertiesSection/Makefile10
-rw-r--r--storage/ndb/src/kernel/vm/testSimplePropertiesSection/test.cpp171
-rw-r--r--storage/ndb/src/kernel/vm/testSuperPool.cpp364
239 files changed, 0 insertions, 189555 deletions
diff --git a/storage/ndb/src/kernel/Makefile.am b/storage/ndb/src/kernel/Makefile.am
deleted file mode 100644
index 7652c5f3ade..00000000000
--- a/storage/ndb/src/kernel/Makefile.am
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 2004-2006 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-SUBDIRS = vm error blocks
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-
-ndbbin_PROGRAMS = ndbd
-
-ndbd_SOURCES = main.cpp SimBlockList.cpp
-
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
-
-INCLUDES += \
- -I$(srcdir)/blocks/cmvmi \
- -I$(srcdir)/blocks/dbacc \
- -I$(srcdir)/blocks/dbdict \
- -I$(srcdir)/blocks/dbdih \
- -I$(srcdir)/blocks/dblqh \
- -I$(srcdir)/blocks/dbtc \
- -I$(srcdir)/blocks/dbtup \
- -I$(srcdir)/blocks/ndbfs \
- -I$(srcdir)/blocks/ndbcntr \
- -I$(srcdir)/blocks/qmgr \
- -I$(srcdir)/blocks/trix \
- -I$(srcdir)/blocks/backup \
- -I$(srcdir)/blocks/dbutil \
- -I$(srcdir)/blocks/suma \
- -I$(srcdir)/blocks/dbtux \
- -I$(srcdir)/blocks
-
-LDADD += \
- blocks/libblocks.a \
- vm/libkernel.a \
- error/liberror.a \
- $(top_builddir)/storage/ndb/src/common/transporter/libtransporter.la \
- $(top_builddir)/storage/ndb/src/common/debugger/libtrace.la \
- $(top_builddir)/storage/ndb/src/common/debugger/signaldata/libsignaldataprint.la \
- $(top_builddir)/storage/ndb/src/common/logger/liblogger.la \
- $(top_builddir)/storage/ndb/src/common/mgmcommon/libmgmsrvcommon.la \
- $(top_builddir)/storage/ndb/src/mgmapi/libmgmapi.la \
- $(top_builddir)/storage/ndb/src/common/portlib/libportlib.la \
- $(top_builddir)/storage/ndb/src/common/util/libgeneral.la \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
-
-windoze-dsp: ndbd.dsp
-
-storage/ndbd.dsp: Makefile \
- $(top_srcdir)/storage/ndb/config/win-prg.am \
- $(top_srcdir)/storage/ndb/config/win-name \
- $(top_srcdir)/storage/ndb/config/win-includes \
- $(top_srcdir)/storage/ndb/config/win-sources \
- $(top_srcdir)/storage/ndb/config/win-libraries
- cat $(top_srcdir)/storage/ndb/config/win-prg.am > $@
- @$(top_srcdir)/storage/ndb/config/win-name $@ $(ndbbin_PROGRAMS)
- @$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES)
- @$(top_srcdir)/storage/ndb/config/win-sources $@ $(ndbd_SOURCES)
- @$(top_srcdir)/storage/ndb/config/win-libraries $@ LINK $(LDADD)
diff --git a/storage/ndb/src/kernel/SimBlockList.cpp b/storage/ndb/src/kernel/SimBlockList.cpp
deleted file mode 100644
index 68c0b4a4642..00000000000
--- a/storage/ndb/src/kernel/SimBlockList.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "SimBlockList.hpp"
-#include <Emulator.hpp>
-#include <SimulatedBlock.hpp>
-#include <Cmvmi.hpp>
-#include <Ndbfs.hpp>
-#include <Dbacc.hpp>
-#include <Dbdict.hpp>
-#include <Dbdih.hpp>
-#include <Dblqh.hpp>
-#include <Dbtc.hpp>
-#include <Dbtup.hpp>
-#include <Ndbcntr.hpp>
-#include <Qmgr.hpp>
-#include <Trix.hpp>
-#include <Backup.hpp>
-#include <DbUtil.hpp>
-#include <Suma.hpp>
-#include <Dbtux.hpp>
-#include <tsman.hpp>
-#include <lgman.hpp>
-#include <pgman.hpp>
-#include <restore.hpp>
-#include <NdbEnv.h>
-
-#ifndef VM_TRACE
-#define NEW_BLOCK(B) new B
-#else
-enum SIMBLOCKLIST_DUMMY { A_VALUE = 0 };
-
-void * operator new (size_t sz, SIMBLOCKLIST_DUMMY dummy){
- char * tmp = (char *)malloc(sz);
-
-#ifndef NDB_PURIFY
-#ifdef VM_TRACE
- const int initValue = 0xf3;
-#else
- const int initValue = 0x0;
-#endif
-
- const int p = (sz / 4096);
- const int r = (sz % 4096);
-
- for(int i = 0; i<p; i++)
- memset(tmp+(i*4096), initValue, 4096);
-
- if(r > 0)
- memset(tmp+p*4096, initValue, r);
-
-#endif
-
- return tmp;
-}
-#define NEW_BLOCK(B) new(A_VALUE) B
-#endif
-
-void
-SimBlockList::load(EmulatorData& data){
- noOfBlocks = NO_OF_BLOCKS;
- theList = new SimulatedBlock * [noOfBlocks];
- Dbdict* dbdict = 0;
- Dbdih* dbdih = 0;
- Pgman* pg = 0;
- Lgman* lg = 0;
- Tsman* ts = 0;
-
- Block_context ctx(*data.theConfiguration, *data.m_mem_manager);
-
- SimulatedBlock * fs = 0;
- {
- Uint32 dl;
- const ndb_mgm_configuration_iterator * p =
- ctx.m_config.getOwnConfigIterator();
- if(p && !ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl){
- fs = NEW_BLOCK(VoidFs)(ctx);
- } else {
- fs = NEW_BLOCK(Ndbfs)(ctx);
- }
- }
-
- theList[0] = pg = NEW_BLOCK(Pgman)(ctx);
- theList[1] = lg = NEW_BLOCK(Lgman)(ctx);
- theList[2] = ts = NEW_BLOCK(Tsman)(ctx, pg, lg);
- theList[3] = NEW_BLOCK(Dbacc)(ctx);
- theList[4] = NEW_BLOCK(Cmvmi)(ctx);
- theList[5] = fs;
- theList[6] = dbdict = NEW_BLOCK(Dbdict)(ctx);
- theList[7] = dbdih = NEW_BLOCK(Dbdih)(ctx);
- theList[8] = NEW_BLOCK(Dblqh)(ctx);
- theList[9] = NEW_BLOCK(Dbtc)(ctx);
- theList[10] = NEW_BLOCK(Dbtup)(ctx, pg);
- theList[11] = NEW_BLOCK(Ndbcntr)(ctx);
- theList[12] = NEW_BLOCK(Qmgr)(ctx);
- theList[13] = NEW_BLOCK(Trix)(ctx);
- theList[14] = NEW_BLOCK(Backup)(ctx);
- theList[15] = NEW_BLOCK(DbUtil)(ctx);
- theList[16] = NEW_BLOCK(Suma)(ctx);
- theList[17] = NEW_BLOCK(Dbtux)(ctx);
- theList[18] = NEW_BLOCK(Restore)(ctx);
- assert(NO_OF_BLOCKS == 19);
-}
-
-void
-SimBlockList::unload(){
- if(theList != 0){
- for(int i = 0; i<noOfBlocks; i++){
- if(theList[i] != 0){
-#ifdef VM_TRACE
- theList[i]->~SimulatedBlock();
- free(theList[i]);
-#else
- delete(theList[i]);
-#endif
- theList[i] = 0;
- }
- }
- delete [] theList;
- theList = 0;
- noOfBlocks = 0;
- }
-}
diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt
deleted file mode 100644
index 150400b9deb..00000000000
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt
+++ /dev/null
@@ -1,565 +0,0 @@
-Next QMGR 1
-Next NDBCNTR 1002
-Next NDBFS 2000
-Next DBACC 3002
-Next DBTUP 4029
-Next DBLQH 5050
-Next DBDICT 6008
-Next DBDIH 7195
-Next DBTC 8058
-Next CMVMI 9000
-Next BACKUP 10038
-Next DBUTIL 11002
-Next DBTUX 12008
-Next SUMA 13034
-Next SUMA 13036
-Next LGMAN 15001
-Next TSMAN 16001
-
-TESTING NODE FAILURE, ARBITRATION
----------------------------------
-
-911 - 919:
-Crash president when he starts to run in ArbitState 1-9.
-
-910: Crash new president after node crash
-
-934 : Crash president in ALLOC_NODE_ID_REQ
-
-935 : Crash master on node failure (delayed)
- and skip sending GSN_COMMIT_FAILREQ to specified node
-
-ERROR CODES FOR TESTING NODE FAILURE, GLOBAL CHECKPOINT HANDLING:
------------------------------------------------------------------
-
-7000:
-Insert system error in master when global checkpoint is idle.
-
-7001:
-Insert system error in master after receiving GCP_PREPARE from
-all nodes in the cluster.
-
-7002:
-Insert system error in master after receiving GCP_NODEFINISH from
-all nodes in the cluster.
-
-7003:
-Insert system error in master after receiving GCP_SAVECONF from
-all nodes in the cluster.
-
-7004:
-Insert system error in master after completing global checkpoint with
-all nodes in the cluster.
-
-7005:
-Insert system error in GCP participant when receiving GCP_PREPARE.
-
-7006:
-Insert system error in GCP participant when receiving GCP_COMMIT.
-
-7007:
-Insert system error in GCP participant when receiving GCP_TCFINISHED.
-
-7008:
-Insert system error in GCP participant when receiving COPY_GCICONF.
-
-5000:
-Insert system error in GCP participant when receiving GCP_SAVEREQ.
-
-5007:
-Delay GCP_SAVEREQ by 10 secs
-
-7165: Delay INCL_NODE_REQ in starting node yeilding error in GCP_PREPARE
-
-7030: Delay in GCP_PREPARE until node has completed a node failure
-7031: Delay in GCP_PREPARE and die 3s later
-
-7177: Delay copying of sysfileData in execCOPY_GCIREQ
-
-7180: Crash master during master-take-over in execMASTER_LCPCONF
-
-7183: Crash when receiving COPY_GCIREQ
-
-7184: Crash before starting next GCP after a node failure
-
-7185: Dont reply to COPY_GCI_REQ where reason == GCP
-
-7193: Dont send LCP_FRAG_ORD to self, and crash when sending first
- LCP_FRAG_ORD(last)
-
-7194: Force removeNodeFromStored to complete in the middle of MASTER_LCPCONF
-
-ERROR CODES FOR TESTING NODE FAILURE, LOCAL CHECKPOINT HANDLING:
------------------------------------------------------------------
-
-7009:
-Insert system error in master when local checkpoint is idle.
-
-7010:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = CALCULATE_KEEP_GCI.
-
-7011:
-Stop local checkpoint in the state CALCULATE_KEEP_GCI.
-
-7012:
-Restart local checkpoint after stopping in CALCULATE_KEEP_GCI.
-
-Method:
-1) Error 7011 in master, wait until report of stopped.
-2) Error xxxx in participant to crash it.
-3) Error 7012 in master to start again.
-
-7013:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = COPY_GCI before sending COPY_GCIREQ.
-
-7014:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = TC_CLOPSIZE before sending TC_CLOPSIZEREQ.
-
-7015:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = START_LCP_ROUND before sending START_LCP_ROUND.
-
-7016:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = START_LCP_ROUND after receiving LCP_REPORT.
-
-7017:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = TAB_COMPLETED.
-
-7018:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = TAB_SAVED before sending DIH_LCPCOMPLETE.
-
-7019:
-Insert system error in master when local checkpoint is in the
-state clcpStatus = IDLE before sending CONTINUEB(ZCHECK_TC_COUNTER).
-
-7020:
-Insert system error in local checkpoint participant at reception of
-COPY_GCIREQ.
-
-7075: Master
-Don't send any LCP_FRAG_ORD(last=true)
-And crash when all have "not" been sent
-
-8000: Crash particpant when receiving TCGETOPSIZEREQ
-8001: Crash particpant when receiving TC_CLOPSIZEREQ
-5010: Crash any when receiving LCP_FRAGORD
-
-7021: Crash in master when receiving START_LCP_REQ
-7022: Crash in !master when receiving START_LCP_REQ
-
-7023: Crash in master when sending START_LCP_CONF
-7024: Crash in !master when sending START_LCP_CONF
-
-7025: Crash in master when receiving LCP_FRAG_REP
-7016: Crash in !master when receiving LCP_FRAG_REP
-
-7026: Crash in master when changing state to LCP_TAB_COMPLETED
-7017: Crash in !master when changing state to LCP_TAB_COMPLETED
-
-7027: Crash in master when changing state to LCP_TAB_SAVED
-7018: Crash in master when changing state to LCP_TAB_SAVED
-
-7191: Crash when receiving LCP_COMPLETE_REP
-7192: Crash in setLcpActiveStatusStart - when dead node missed to LCP's
-
-ERROR CODES FOR TESTING NODE FAILURE, FAILURE IN COPY FRAGMENT PROCESS:
------------------------------------------------------------------------
-
-5002:
-Insert node failure in starting node when receiving a tuple copied from the copy node
-as part of copy fragment process.
-5003:
-Insert node failure when receiving ABORT signal.
-
-5004:
-Insert node failure handling when receiving COMMITREQ.
-
-5005:
-Insert node failure handling when receiving COMPLETEREQ.
-
-5006:
-Insert node failure handling when receiving ABORTREQ.
-
-5042:
-As 5002, but with specified table (see DumpStateOrd)
-
-These error code can be combined with error codes for testing time-out
-handling in DBTC to ensure that node failures are also well handled in
-time-out handling. They can also be used to test multiple node failure
-handling.
-
-5045: Crash in PREPARE_COPY_FRAG_REQ
-5046: Crash if LQHKEYREQ (NrCopy) comes when frag-state is incorrect
-
-ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBLQH
--------------------------------------------------
-5011:
-Delay execution of COMMIT signal 2 seconds to generate time-out.
-
-5012 (use 5017):
-First delay execution of COMMIT signal 2 seconds to generate COMMITREQ.
-Delay execution of COMMITREQ signal 2 seconds to generate time-out.
-
-5013:
-Delay execution of COMPLETE signal 2 seconds to generate time-out.
-
-5014 (use 5018):
-First delay execution of COMPLETE signal 2 seconds to generate COMPLETEREQ.
-Delay execution of COMPLETEREQ signal 2 seconds to generate time-out.
-
-5015:
-Delay execution of ABORT signal 2 seconds to generate time-out.
-
-5016: (ABORTREQ only as part of take-over)
-Delay execution of ABORTREQ signal 2 seconds to generate time-out.
-
-5031: lqhKeyRef, ZNO_TC_CONNECT_ERROR
-5032: lqhKeyRef, ZTEMPORARY_REDO_LOG_FAILURE
-5033: lqhKeyRef, ZTAIL_PROBLEM_IN_LOG_ERROR
-
-5034: Don't pop scan queue
-
-5035: Delay ACC_CONTOPCONT
-
-5038: Drop LQHKEYREQ + set 5039
-5039: Drop ABORT + set 5003
-
-8048: Make TC not choose own node for simple/dirty read
-5041: Crash is receiving simple read from other TC on different node
-
-8050: Send TCKEYREF is operation is non local
-
-5100,5101: Drop ABORT req in primary replica
- Crash on "next" ABORT
-
-ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
--------------------------------------------------
-8040:
-Delay execution of ABORTED signal 2 seconds to generate time-out.
-
-8041:
-Delay execution of COMMITTED signal 2 seconds to generate time-out.
-8042 (use 8046):
-Delay execution of COMMITTED signal 2 seconds to generate COMMITCONF.
-Delay execution of COMMITCONF signal 2 seconds to generate time-out.
-
-8043:
-Delay execution of COMPLETED signal 2 seconds to generate time-out.
-
-8044 (use 8047):
-Delay execution of COMPLETED signal 2 seconds to generate COMPLETECONF.
-Delay execution of COMPLETECONF signal 2 seconds to generate time-out.
-
-8045: (ABORTCONF only as part of take-over)
-Delay execution of ABORTCONF signal 2 seconds to generate time-out.
-
-8050: Send ZABORT_TIMEOUT_BREAK delayed
-
-8053: Crash in timeOutFoundLab, state CS_WAIT_COMMIT_CONF
-
-5048: Crash in execCOMMIT
-5049: SET_ERROR_INSERT_VALUE(5048)
-
-ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
--------------------------------------------------
-
-8003: Throw away a LQHKEYCONF in state STARTED
-8004: Throw away a LQHKEYCONF in state RECEIVING
-8005: Throw away a LQHKEYCONF in state REC_COMMITTING
-8006: Throw away a LQHKEYCONF in state START_COMMITTING
-
-8007: Ignore send of LQHKEYREQ in state STARTED
-8008: Ignore send of LQHKEYREQ in state START_COMMITTING
-
-8009: Ignore send of LQHKEYREQ+ATTRINFO in state STARTED
-8010: Ignore send of LQHKEYREQ+ATTRINFO in state START_COMMITTING
-
-8011: Abort at send of CONTINUEB(ZSEND_ATTRINFO) in state STARTED
-8012: Abort at send of CONTINUEB(ZSEND_ATTRINFO) in state START_COMMITTING
-
-8013: Ignore send of CONTINUEB(ZSEND_COMPLETE_LOOP) (should crash eventually)
-8014: Ignore send of CONTINUEB(ZSEND_COMMIT_LOOP) (should crash eventually)
-
-8015: Ignore ATTRINFO signal in DBTC in state REC_COMMITTING
-8016: Ignore ATTRINFO signal in DBTC in state RECEIVING
-
-8017: Return immediately from DIVERIFYCONF (should crash eventually)
-8018: Throw away a COMMITTED signal
-8019: Throw away a COMPLETED signal
-
-TESTING TAKE-OVER FUNCTIONALITY IN DBTC
----------------------------------------
-
-8002: Crash when sending LQHKEYREQ
-8029: Crash when receiving LQHKEYCONF
-8030: Crash when receiving COMMITTED
-8031: Crash when receiving COMPLETED
-8020: Crash when all COMMITTED has arrived
-8021: Crash when all COMPLETED has arrived
-8022: Crash when all LQHKEYCONF has arrived
-
-COMBINATION OF TIME-OUT + CRASH
--------------------------------
-
-8023 (use 8024): Ignore LQHKEYCONF and crash when ABORTED signal arrives by setting 8024
-8025 (use 8026): Ignore COMMITTED and crash when COMMITCONF signal arrives by setting 8026
-8027 (use 8028): Ignore COMPLETED and crash when COMPLETECONF signal arrives by setting 8028
-
-ABORT OF TCKEYREQ
------------------
-
-8032: No free TC records any more
-
-8037 : Invalid schema version in TCINDXREQ
-
-------
-
-8038 : Simulate API disconnect just after SCAN_TAB_REQ
-
-8057 : Send only 1 COMMIT per timeslice
-
-8052 : Simulate failure of TransactionBufferMemory allocation for OI lookup
-
-8051 : Simulate failure of allocation for saveINDXKEYINFO
-
-
-CMVMI
------
-9000 Set RestartOnErrorInsert to restart -n
-9998 Enter endless loop (trigger watchdog)
-9999 Crash system immediatly
-
-Test Crashes in handling node restarts
---------------------------------------
-
-7121: Crash after receiving permission to start (START_PERMCONF) in starting
- node.
-7122: Crash master when receiving request for permission to start (START_PERMREQ).
-7123: Crash any non-starting node when receiving information about a starting node
- (START_INFOREQ)
-7124: Respond negatively on an info request (START_INFOREQ)
-7125: Stop an invalidate Node LCP process in the middle to test if START_INFOREQ
- stopped by long-running processes are handled in a correct manner.
-7126: Allow node restarts for all nodes (used in conjunction with 7025)
-7127: Crash when receiving a INCL_NODEREQ message.
-7128: Crash master after receiving all INCL_NODECONF from all nodes
-7129: Crash master after receiving all INCL_NODECONF from all nodes and releasing
- the lock on the dictionary
-7130: Crash starting node after receiving START_MECONF
-7131: Crash when receiving START_COPYREQ in master node
-7132: Crash when receiving START_COPYCONF in starting node
-
-7170: Crash when receiving START_PERMREF (InitialStartRequired)
-
-8039: DBTC delay INCL_NODECONF and kill starting node
-
-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
-6002 Crash during NR soon after sending GET_TABINFO_REQ
-
-LQH:
-5026 Crash when receiving COPY_ACTIVEREQ
-5027 Crash when receiving STAT_RECREQ
-
-5043 Crash starting node, when scan is finished on primary replica
-
-Test Crashes in handling take over
-----------------------------------
-
-7133: Crash when receiving START_TOREQ
-7134: Crash master after receiving all START_TOCONF
-7135: Crash master after copying table 0 to starting node
-7136: Crash master after completing copy of tables
-7137: Crash master after adding a fragment before copying it
-7138: Crash when receiving CREATE_FRAGREQ in prepare phase
-7139: Crash when receiving CREATE_FRAGREQ in commit phase
-7140: Crash master when receiving all CREATE_FRAGCONF in prepare phase
-7141: Crash master when receiving all CREATE_FRAGCONF in commit phase
-7142: Crash master when receiving COPY_FRAGCONF
-7143: Crash master when receiving COPY_ACTIVECONF
-7144: Crash when receiving END_TOREQ
-7145: Crash master after receiving first END_TOCONF
-7146: Crash master after receiving all END_TOCONF
-7147: Crash master after receiving first START_TOCONF
-7148: Crash master after receiving first CREATE_FRAGCONF
-7152: Crash master after receiving first UPDATE_TOCONF
-7153: Crash master after receiving all UPDATE_TOCONF
-7154: Crash when receiving UPDATE_TOREQ
-7155: Crash master when completing writing start take over info
-7156: Crash master when completing writing end take over info
-
-Test failures in various states in take over functionality
-----------------------------------------------------------
-7157: Block take over at start take over
-7158: Block take over at sending of START_TOREQ
-7159: Block take over at selecting next fragment
-7160: Block take over at creating new fragment
-7161: Block take over at sending of CREATE_FRAGREQ in prepare phase
-7162: Block take over at sending of CREATE_FRAGREQ in commit phase
-7163: Block take over at sending of UPDATE_TOREQ at end of copy frag
-7164: Block take over at sending of END_TOREQ
-7169: Block take over at sending of UPDATE_TOREQ at end of copy
-
-5008: Crash at reception of EMPTY_LCPREQ (at master take over after NF)
-5009: Crash at sending of EMPTY_LCPCONF (at master take over after NF)
-
-Test Crashes in Handling Graceful Shutdown
-------------------------------------------
-7065: Crash when receiving STOP_PERMREQ in master
-7066: Crash when receiving STOP_PERMREQ in slave
-7067: Crash when receiving DIH_SWITCH_REPLICA_REQ
-7068: Crash when receiving DIH_SWITCH_REPLICA_CONF
-
-
-Backup Stuff:
-------------------------------------------
-10001: Crash on NODE_FAILREP in Backup coordinator
-10002: Crash on NODE_FAILREP when coordinatorTakeOver
-10003: Crash on PREP_CREATE_TRIG_{CONF/REF} (only coordinator)
-10004: Crash on START_BACKUP_{CONF/REF} (only coordinator)
-10005: Crash on CREATE_TRIG_{CONF/REF} (only coordinator)
-10006: Crash on WAIT_GCP_REF (only coordinator)
-10007: Crash on WAIT_GCP_CONF (only coordinator)
-10008: Crash on WAIT_GCP_CONF during start of backup (only coordinator)
-10009: Crash on WAIT_GCP_CONF during stop of backup (only coordinator)
-10010: Crash on BACKUP_FRAGMENT_CONF (only coordinator)
-10011: Crash on BACKUP_FRAGMENT_REF (only coordinator)
-10012: Crash on DROP_TRIG_{CONF/REF} (only coordinator)
-10013: Crash on STOP_BACKUP_{CONF/REF} (only coordinator)
-10014: Crash on DEFINE_BACKUP_REQ (participant)
-10015: Crash on START_BACKUP_REQ (participant)
-10016: Crash on BACKUP_FRAGMENT_REQ (participant)
-10017: Crash on SCAN_FRAGCONF (participant)
-10018: Crash on FSAPPENDCONF (participant)
-10019: Crash on TRIG_ATTRINFO (participant)
-10020: Crash on STOP_BACKUP_REQ (participant)
-10021: Crash on NODE_FAILREP in participant not becoming coordinator
-
-10022: Fake no backup records at DEFINE_BACKUP_REQ (participant)
-10023: Abort backup by error at reception of UTIL_SEQUENCE_CONF (code 300)
-10024: Abort backup by error at reception of DEFINE_BACKUP_CONF (code 301)
-10025: Abort backup by error at reception of CREATE_TRIG_CONF last (code 302)
-10026: Abort backup by error at reception of START_BACKUP_CONF (code 303)
-10027: Abort backup by error at reception of DEFINE_BACKUP_REQ at master (code 304)
-10028: Abort backup by error at reception of BACKUP_FRAGMENT_CONF at master (code 305)
-10029: Abort backup by error at reception of FSAPPENDCONF in slave (FileOrScanError = 5)
-10030: Simulate buffer full from trigger execution => abort backup
-10031: Error 331 for dictCommitTableMutex_locked
-10032: backup checkscan
-10033: backup checkscan
-10034: define backup reply error
-10035: Fail to allocate buffers
-
-10036: Halt backup for table >= 2
-10037: Resume backup (from 10036)
-
-11001: Send UTIL_SEQUENCE_REF (in master)
-
-5028: Crash when receiving LQHKEYREQ (in non-master)
-
-Failed Create Table:
---------------------
-7173: Create table failed due to not sufficient number of fragment or
- replica records.
-3001: Fail create 1st fragment
-4007 12001: Fail create 1st fragment
-4008 12002: Fail create 2nd fragment
-4009 12003: Fail create 1st attribute in 1st fragment
-4010 12004: Fail create last attribute in 1st fragment
-4011 12005: Fail create 1st attribute in 2nd fragment
-4012 12006: Fail create last attribute in 2nd fragment
-
-Drop Table/Index:
------------------
-4001: Crash on REL_TABMEMREQ in TUP
-4002: Crash on DROP_TABFILEREQ in TUP
-4003: Fail next trigger create in TUP
-4004: Fail next trigger drop in TUP
-8033: Fail next trigger create in TC
-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
-
-System Restart:
----------------
-
-5020: Force system to read pages form file when executing prepare operation record
-3000: Delay writing of datapages in ACC when LCP is started
-4000: Delay writing of datapages in TUP when LCP is started
-7070: Set TimeBetweenLcp to min value
-7071: Set TimeBetweenLcp to max value
-7072: Split START_FRAGREQ into several log nodes
-7073: Don't include own node in START_FRAGREQ
-7074: 7072 + 7073
-
-Scan:
-------
-
-5021: Crash when receiving SCAN_NEXTREQ if sender is own node
-5022: Crash when receiving SCAN_NEXTREQ if sender is NOT own node
-5023: Drop SCAN_NEXTREQ if sender is own node
-5024: Drop SCAN_NEXTREQ if sender is NOT own node
-5025: Delay SCAN_NEXTREQ 1 second if sender is NOT own node
-5030: Drop all SCAN_NEXTREQ until node is shutdown with SYSTEM_ERROR
- because of scan fragment timeout
-
-Test routing of signals:
------------------------
-4006: Turn on routing of TRANSID_AI signals from TUP
-5029: Turn on routing of KEYINFO20 signals from LQH
-
-Ordered index:
---------------
-12007: Make next alloc node fail with no memory error
-
-Dbdict:
--------
-6003 Crash in participant @ CreateTabReq::Prepare
-6004 Crash in participant @ CreateTabReq::Commit
-6005 Crash in participant @ CreateTabReq::CreateDrop
-6007 Fail on readTableFile for READ_TAB_FILE1 (28770)
-
-Dbtup:
-4014 - handleInsert - Out of undo buffer
-4015 - handleInsert - Out of log space
-4016 - handleInsert - AI Inconsistency
-4017 - handleInsert - Out of memory
-4018 - handleInsert - Null check error
-4019 - handleInsert - Alloc rowid error
-4020 - handleInsert - Size change error
-4021 - handleInsert - Out of disk space
-
-4022 - addTuxEntries - fail before add of first entry
-4023 - addTuxEntries - fail add of last entry (the entry for last index)
-
-4025: Fail all inserts with out of memory
-4026: Fail one insert with oom
-4027: Fail inserts randomly with oom
-4028: Fail one random insert with oom
-
-NDBCNTR:
-
-1000: Crash insertion on SystemError::CopyFragRef
-1001: Delay sending NODE_FAILREP (to own node), until error is cleared
-
-LGMAN:
------
-15000: Fail to create log file
-
-TSMAN:
------
-16000: Fail to create data file
diff --git a/storage/ndb/src/kernel/blocks/Makefile.am b/storage/ndb/src/kernel/blocks/Makefile.am
deleted file mode 100644
index 9b806638837..00000000000
--- a/storage/ndb/src/kernel/blocks/Makefile.am
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (C) 2004-2006 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-SUBDIRS = \
- dbdict \
- dbdih \
- dblqh \
- dbtup \
- backup
-
-noinst_LIBRARIES = libblocks.a
-
-INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/kernel/blocks/dblqh
-libblocks_a_SOURCES = tsman.cpp lgman.cpp pgman.cpp diskpage.cpp restore.cpp\
- cmvmi/Cmvmi.cpp \
- dbacc/DbaccInit.cpp dbacc/DbaccMain.cpp \
- dbdict/Dbdict.cpp \
- dbdih/DbdihInit.cpp dbdih/DbdihMain.cpp \
- dblqh/DblqhInit.cpp dblqh/DblqhMain.cpp \
- dbtc/DbtcInit.cpp dbtc/DbtcMain.cpp \
- dbtup/DbtupExecQuery.cpp dbtup/DbtupBuffer.cpp \
- dbtup/DbtupRoutines.cpp dbtup/DbtupCommit.cpp \
- dbtup/DbtupFixAlloc.cpp dbtup/DbtupTrigger.cpp \
- dbtup/DbtupAbort.cpp dbtup/DbtupPageMap.cpp \
- dbtup/DbtupPagMan.cpp dbtup/DbtupStoredProcDef.cpp \
- dbtup/DbtupMeta.cpp dbtup/DbtupTabDesMan.cpp \
- dbtup/DbtupGen.cpp dbtup/DbtupIndex.cpp \
- dbtup/DbtupDebug.cpp dbtup/DbtupScan.cpp \
- dbtup/DbtupDiskAlloc.cpp dbtup/DbtupVarAlloc.cpp \
- dbtup/tuppage.cpp dbtup/Undo_buffer.cpp \
- ndbfs/AsyncFile.cpp ndbfs/Ndbfs.cpp ndbfs/VoidFs.cpp \
- ndbfs/Filename.cpp ndbfs/CircularIndex.cpp \
- ndbcntr/NdbcntrInit.cpp ndbcntr/NdbcntrSysTable.cpp ndbcntr/NdbcntrMain.cpp \
- qmgr/QmgrInit.cpp qmgr/QmgrMain.cpp \
- trix/Trix.cpp \
- backup/Backup.cpp backup/BackupInit.cpp \
- dbutil/DbUtil.cpp \
- suma/Suma.cpp suma/SumaInit.cpp \
- dbtux/DbtuxGen.cpp dbtux/DbtuxMeta.cpp dbtux/DbtuxMaint.cpp \
- dbtux/DbtuxNode.cpp dbtux/DbtuxTree.cpp dbtux/DbtuxScan.cpp \
- dbtux/DbtuxSearch.cpp dbtux/DbtuxCmp.cpp dbtux/DbtuxStat.cpp \
- dbtux/DbtuxDebug.cpp
-
-EXTRA_PROGRAMS = ndb_print_file
-ndb_print_file_SOURCES = print_file.cpp diskpage.cpp dbtup/tuppage.cpp
-ndb_print_file_LDFLAGS = @ndb_bin_am_ldflags@ \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
-
-windoze-dsp:
diff --git a/storage/ndb/src/kernel/blocks/NodeRestart.new.txt b/storage/ndb/src/kernel/blocks/NodeRestart.new.txt
deleted file mode 100644
index 00ab8f0c208..00000000000
--- a/storage/ndb/src/kernel/blocks/NodeRestart.new.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-
-Master DIH Starting DIH Starting DICT
----------------------- ---------------------- ---------------------
-
- Check for sysfile
- DIH_RESTARTCONF ->
-
-******************************************************************************
-* NDB_STTOR interal startphase = 1
-******************************************************************************
-
- Read schema file
-
-******************************************************************************
-* NDB_STTOR interal startphase = 2
-******************************************************************************
-
- <- START_PERMREQ
-
-XXX
-
-START_PERMCONF ->
-
-******************************************************************************
-* NDB_STTOR interal startphase = 3
-******************************************************************************
-
- <- START_MEREQ
-
-START_RECREQ -> starting LQH
- <- START_RECCONF
-
-For each table
- COPY_TABREQ -> starting DIH
-
-DICTSTARTREQ -> starting DICT
- GET_SCHEMA_INFOREQ
- (to master DICT)
-
- ->SCHEMA_INFO
- (schema file)
-
- 1) For each table
- If TableStatus OK
- ReadTableFile
- else
- GET_TABINFOREQ
- 2) DIADDTABREQ->DIH
-
- For each local frag
- ADD_FRAG_REQ -> local DICT
- DI_ADD_TAB_CONF
- <- DICTSTARTCONF
-
-INCL_NODEREQ -> all DIH
-
-START_MECONF -> starting DIH
- (including sysfile)
-
-******************************************************************************
-* NDB_STTOR interal startphase = 5
-******************************************************************************
-
- <- START_COPYREQ
-
-START_TOREQ -> all DIH
-
-For each fragment
- CREATE_FRAGREQ -> all DIH
-
- COPY-DATA (LQHKEYREQ++)
-
- UPDATE_TOREQ -> all DIH
-
- COPY_ACTIVEREQ -> starting LQH
-
- CREATE_FRAGREQ -> all DIH
-
-START_COPYCONF ->
-
-LOCAL CHECKPOINT
-
diff --git a/storage/ndb/src/kernel/blocks/NodeRestart.txt b/storage/ndb/src/kernel/blocks/NodeRestart.txt
deleted file mode 100644
index e9f277bb39e..00000000000
--- a/storage/ndb/src/kernel/blocks/NodeRestart.txt
+++ /dev/null
@@ -1,80 +0,0 @@
-
-Master DIH Starting DIH Starting DICT
----------------------- ---------------------- ---------------------
-
- Check for sysfile
- DIH_RESTARTCONF ->
-
-******************************************************************************
-* NDB_STTOR interal startphase = 1
-******************************************************************************
-
- Read schema file
-
-******************************************************************************
-* NDB_STTOR interal startphase = 2
-******************************************************************************
-
- <- START_PERMREQ
-
-XXX
-
-START_PERMCONF ->
-
-******************************************************************************
-* NDB_STTOR interal startphase = 3
-******************************************************************************
-
- <- START_MEREQ
-
-START_RECREQ -> starting LQH
- <- START_RECCONF
-
-DICTSTARTREQ -> starting DICT
- GET_SCHEMA_INFOREQ
- (to master DICT)
-
- ->SCHEMA_INFO
- (schema file)
-
- 1) For each table
- 1) If TableStatus match
- ReadTableFile
- else
- GET_TABINFOREQ
-
- <- DICTSTARTCONF
-
-For each table
- COPY_TABREQ -> starting DIH
-
-INCL_NODEREQ -> all DIH
-
-START_MECONF -> starting DIH
- (including sysfile)
-
-******************************************************************************
-* NDB_STTOR interal startphase = 5
-******************************************************************************
-
- <- START_COPYREQ
-
-START_TOREQ -> all DIH
-
-For each fragment
- ADD_FRAG_REQ -> local DICT -> LQHFRAGREQ -> starting LQH
-
- CREATE_FRAGREQ -> all DIH
-
- COPY-DATA (LQHKEYREQ++)
-
- UPDATE_TOREQ -> all DIH
-
- COPY_ACTIVEREQ -> starting LQH
-
- CREATE_FRAGREQ -> all DIH
-
-START_COPYCONF ->
-
-LOCAL CHECKPOINT
-
diff --git a/storage/ndb/src/kernel/blocks/OptNR.txt b/storage/ndb/src/kernel/blocks/OptNR.txt
deleted file mode 100644
index 17e9a62bb0e..00000000000
--- a/storage/ndb/src/kernel/blocks/OptNR.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-*** Copy thread
-
- Scan rowids with GCP > starting nodes GCP
- Cases for different ROWID combinations
-
-RI Primary Starting Result
-1 A A Update A
-2 B B* Delete B* + Insert B
-3 C C* Delete C* + Delete C + Insert C
- C
-4 Deleted D Delete D
-5 E Deleted Insert E
-6 F Deleted Delete F + Insert F
- F
-7 Deleted Deleted Update GCP
-
-*** Ordinary operations
-Op Starting Result
-Insert A@1 A@1 Update A
-Insert A@1 A@2 Delete A@2, Insert A@1
-Insert A@1 1 busy, A@2 Delete 1, Delete A@2, Insert A@1
-Insert A@1 1 busy Delete 1, Insert A@1
-
-Delete A@1 A@1 Delete A@1
-Delete A@1 else noop
-
-Update A@1 A@1 Update A
-Update A@1 else noop
-
-***
-
-Rationale:
-
-If copy has passed rowid,
- then no ordinary operation should be a noop
-
-If copy has not passed,
- then it's ok to do a noop as copy will get there sooner or later
-
-Copy may not end up in lock queue, as no lock is held on primary.
- therefore ordinary ops must be noops when rowid missmatch
-
-When not scanning in rowid order (e.g. disk order) one must
-1 make a second pass in rowid order
- - finding deletes and inserts (as 2)
-2 mark all inserts "earlier" than current scan pos
- so they will be found during second pass
-
-Note: Dealloc is performed first on backup then on primary
diff --git a/storage/ndb/src/kernel/blocks/Start.txt b/storage/ndb/src/kernel/blocks/Start.txt
deleted file mode 100644
index 3e805ebab55..00000000000
--- a/storage/ndb/src/kernel/blocks/Start.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-
---- Start phase 1 - Qmgr -------------------------------------------
-
-1) Set timer 1 - TimeToWaitAlive
-
-2) Send CM_REGREQ to all connected(and connecting) nodes
-
-3) Wait until -
-a) The precident answers CM_REGCONF
-b) All nodes has answered and I'm the candidate -> election won
-c) 30s has passed and I'm the candidate -> election won
-d) TimeToWaitAlive has passed -> Failure to start
-
-When receiving CM_REGCONF
-4) Send CM_NODEINFOREQ to all connected(and connecting) nodes
- reported in CM_REGCONF
-
-5) Wait until -
-a) All CM_NODEINFO_CONF has arrived
-b) TimeToWaitAlive has passed -> Failure to start
-
-6) Send CM_ACKADD to president
-
-7) Wait until -
-a) Receive CM_ADD(CommitNew) from president -> I'm in the qmgr cluster
-b) TimeToWaitAlive has passed -> Failure to start
-
-NOTE:
-30s is hardcoded in 3c.
-TimeToWaitAlive should be atleast X sec greater than 30s. i.e. 30+X sec
-to support "partial starts"
-
-NOTE:
-In 3b, a more correct number (instead of all) would be
-N-NG+1 where N is #nodes and NG is #node groups = (N/R where R is # replicas)
-But Qmgr has no notion about node groups or replicas
-
---- Start phase X - Qmgr -------------------------------------------
-
-President - When accepting a CM_REGREQ
-1) Send CM_REGCONF to starting node
-2) Send CM_ADD(Prepare) to all started nodes + starting node
-3) Send CM_ADD(AddCommit) to all started nodes
-4) Send CM_ADD(CommitNew) to starting node
-
-Cluster participant -
-1) Wait for both CM_NODEINFOREQ from starting and CM_ADD(Prepare) from pres.
-2) Send CM_ACKADD(Prepare)
-3) Wait for CM_ADD(AddCommit) from president
-4) Send CM_ACKADD(AddCommit)
-
---- Start phase 2 - NdbCntr ----------------------------------------
-
-- Use same TimeToWaitAliveTimer
-
-1) Check sysfile (DIH_RESTART_REQ)
-2) Read nodes (from Qmgr) P = qmgr president
-
-3) Send CNTR_MASTER_REQ to cntr(P)
- including info in DIH_RESTART_REF/CONF
-
-4) Wait until -
-b) Receiving CNTR_START_CONF -> continue
-b) Receiving CNTR_START_REF -> P = node specified in REF, goto 3
-c) TimeToWaitAlive has passed -> Failure to start
-
-4) Run ndb-startphase 1
-
---
-Initial start/System restart NdbCntr (on qmgr president node)
-
-1) Wait until -
-a) Receiving CNTR_START_REQ with GCI > than own GCI
- send CNTR_START_REF to all waiting nodes
-b) Receiving all CNTR_START_REQ (for all defined nodes)
-c) TimeToWait has passed and partition win
-d) TimeToWait has passed and partitioning
- and configuration "start with partition" = true
-
-2) Send CNTR_START_CONF to all nodes "with filesystem"
-
-3) Wait until -
- Receiving CNTR_START_REP for all starting nodes
-
-4) Start waiting nodes (if any)
-
-NOTE:
-1c) Partition win = 1 node in each node group and 1 full node group
-1d) Pattitioning = at least 1 node in each node group
---
-Running NdbCntr
-
-When receiving CNTR_MASTER_REQ
-1) If I'm not master send CNTR_MASTER_REF (including master node id)
-2) If I'm master
- Coordinate parallell node restarts
- send CNTR_MASTER_CONF (node restart)
diff --git a/storage/ndb/src/kernel/blocks/SystemRestart.new.txt b/storage/ndb/src/kernel/blocks/SystemRestart.new.txt
deleted file mode 100644
index 3738de28df8..00000000000
--- a/storage/ndb/src/kernel/blocks/SystemRestart.new.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-
-DIH DICT CNTR
----------------------- ---------------------- ---------------------
- <- DIHRESTARTREQ
-Check for sysfile
-DIH_RESTARTCONF ->
-
-NDB_STTORY -> DICT (sp=1)
- Read schema file
-
-******************************************************************************
-* Elect master
-******************************************************************************
-
--- Master DIH --
-
-Read sysfile
-
-COPY_GCIREQ -> all DIHs
-
-DICTSTARTREQ -> local DICT (master)
-
- master
- ======
- For each table (that should be started)
- 1) ReadTableFile
- 2) DI_ADD_TAB_REQ -> local DIH
-
-1) ReadTableFile (DIH)
-2) COPY_TABREQ -> all DIH (but self)
-3) For each local frag
- ADD_FRAG_REQ -> local DICT
-4) DI_ADD_TAB_CONF
-
- SCHEMA_INFO -> all DICTs
- Info = schema file
-
- Participant
- ===========
- 1) For each table
- 1) If TableStatus match
- ReadTableFile
- else
- GET_TABINFOREQ
- 2) WriteTableFile
- 3) Parse Table Data
- 4) DI_ADD_TAB_REQ -> local DIH
-
- <- SCHEMA_INFOCONF
-
-
- <- DICTSTARTCONF
-
-For each fragment
- IF Fragment is logged
- START_FRAGREQ -> LQH x
-
- START_RECREQ -> all LQH
- Note does not wait for START_FRAGCONF
-
-NDB_STARTCONF ->
diff --git a/storage/ndb/src/kernel/blocks/SystemRestart.txt b/storage/ndb/src/kernel/blocks/SystemRestart.txt
deleted file mode 100644
index 235dfb968fa..00000000000
--- a/storage/ndb/src/kernel/blocks/SystemRestart.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-
-NDBCNTR DIH DICT
----------------------- ---------------------- ---------------
-DIH_RESTARTREQ -> DIH
- Check for sysfile
- <- DIH_RESTARTCONF
-
-NDB_STTORY -> DICT
-sp = 1
- Read schema file
-
----- Master
-
-NDB_STARTREQ -> DIH
- Read sysfile
-
- COPY_GCIREQ -> all DIHs
-
- DICTSTARTREQ -> local DICT
- local
- ======
- SCHEMA_INFO -> all DICTs
- Info = schema file
-
- Participant
- ===========
- 1) For each table
- If TableStatus match
- ReadTableFile
- else
- GET_TABINFOREQ
-
- <- SCHEMA_INFOCONF
-
- local
- ======
- For each table
- DIHSTARTTABREQ -> DIH
-
- <- DICTSTARTCONF
-
- For each table (STARTED)
- Read table description
- from disk
-
- For each fragment
- IF Fragment dont have LCP
- ADD_FRAGREQ -> local DICT
- 1) LQHFRAGREQ -> LQH x
- 2) For each attribute
- LQHADDATTREQ
- IF Fragment is logged
- START_FRAGREQ -> LQH x
-
- START_RECREQ -> all LQH
- Note does not wait for START_FRAGCONF
-
- For each table
- COPY_TABREQ -> all DIH (but self)
-
- <- NDB_STARTCONF
diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.cpp b/storage/ndb/src/kernel/blocks/backup/Backup.cpp
deleted file mode 100644
index 3aa19644491..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp
+++ /dev/null
@@ -1,5144 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <my_config.h>
-#include "Backup.hpp"
-
-#include <ndb_version.h>
-
-#include <NdbTCP.h>
-#include <Bitmask.hpp>
-
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-
-#include <signaldata/DihFragCount.hpp>
-#include <signaldata/ScanFrag.hpp>
-
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/ListTables.hpp>
-
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsAppendReq.hpp>
-#include <signaldata/FsCloseReq.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsRemoveReq.hpp>
-
-#include <signaldata/BackupImpl.hpp>
-#include <signaldata/BackupSignalData.hpp>
-#include <signaldata/BackupContinueB.hpp>
-#include <signaldata/EventReport.hpp>
-
-#include <signaldata/UtilSequence.hpp>
-
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/AlterTrig.hpp>
-#include <signaldata/DropTrig.hpp>
-#include <signaldata/FireTrigOrd.hpp>
-#include <signaldata/TrigAttrInfo.hpp>
-#include <AttributeHeader.hpp>
-
-#include <signaldata/WaitGCP.hpp>
-#include <signaldata/LCP.hpp>
-
-#include <NdbTick.h>
-
-static NDB_TICKS startTime;
-
-static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
-
-#ifdef VM_TRACE
-#define DEBUG_OUT(x) ndbout << x << endl
-#else
-#define DEBUG_OUT(x)
-#endif
-
-//#define DEBUG_ABORT
-//#define dbg globalSignalLoggers.log
-
-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::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- const Uint32 startphase = signal->theData[1];
- const Uint32 typeOfStart = signal->theData[7];
-
- if (startphase == 1)
- {
- m_curr_disk_write_speed = c_defaults.m_disk_write_speed_sr;
- m_overflow_disk_write = 0;
- m_reset_disk_speed_time = NdbTick_CurrentMillisecond();
- m_reset_delay_used = Backup::DISK_SPEED_CHECK_DELAY;
- signal->theData[0] = BackupContinueB::RESET_DISK_SPEED_COUNTER;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal,
- Backup::DISK_SPEED_CHECK_DELAY, 1);
- }
- if (startphase == 3) {
- jam();
- g_TypeOfStart = typeOfStart;
- signal->theData[0] = reference();
- sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
- return;
- }//if
-
- if (startphase == 7)
- {
- m_curr_disk_write_speed = c_defaults.m_disk_write_speed;
- }
-
- if(startphase == 7 && g_TypeOfStart == NodeState::ST_INITIAL_START &&
- c_masterNodeId == getOwnNodeId()){
- jam();
- createSequence(signal);
- return;
- }//if
-
- sendSTTORRY(signal);
- return;
-}//Dbdict::execSTTOR()
-
-void
-Backup::execREAD_NODESCONF(Signal* signal)
-{
- jamEntry();
- ReadNodesConf * conf = (ReadNodesConf *)signal->getDataPtr();
-
- c_aliveNodes.clear();
-
- Uint32 count = 0;
- for (Uint32 i = 0; i<MAX_NDB_NODES; i++) {
- jam();
- if(NodeBitmask::get(conf->allNodes, i)){
- jam();
- count++;
-
- NodePtr node;
- ndbrequire(c_nodes.seize(node));
-
- node.p->nodeId = i;
- if(NodeBitmask::get(conf->inactiveNodes, i)) {
- jam();
- node.p->alive = 0;
- } else {
- jam();
- node.p->alive = 1;
- c_aliveNodes.set(i);
- }//if
- }//if
- }//for
- c_masterNodeId = conf->masterNodeId;
- ndbrequire(count == conf->noOfNodes);
- sendSTTORRY(signal);
-}
-
-void
-Backup::sendSTTORRY(Signal* signal)
-{
- signal->theData[0] = 0;
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 7;
- signal->theData[6] = 255; // No more start phases from missra
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
-}
-
-void
-Backup::createSequence(Signal* signal)
-{
- UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
-
- req->senderData = RNIL;
- req->sequenceId = BACKUP_SEQUENCE;
- req->requestType = UtilSequenceReq::Create;
-
- sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
- signal, UtilSequenceReq::SignalLength, JBB);
-}
-
-void
-Backup::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- const Uint32 Tdata0 = signal->theData[0];
- const Uint32 Tdata1 = signal->theData[1];
- const Uint32 Tdata2 = signal->theData[2];
-
- switch(Tdata0) {
- case BackupContinueB::RESET_DISK_SPEED_COUNTER:
- {
- /*
- Adjust for upto 10 millisecond delay of this signal. Longer
- delays will not be handled, in this case the system is most
- likely under too high load and it won't matter very much that
- we decrease the speed of checkpoints.
-
- We use a technique where we allow an overflow write in one
- period. This overflow will be removed from the next period
- such that the load will at average be as specified.
- */
- int delay_time = m_reset_delay_used;
- NDB_TICKS curr_time = NdbTick_CurrentMillisecond();
- int sig_delay = curr_time - m_reset_disk_speed_time;
-
- m_words_written_this_period = m_overflow_disk_write;
- m_overflow_disk_write = 0;
- m_reset_disk_speed_time = curr_time;
-
- if (sig_delay > delay_time + 10)
- delay_time = Backup::DISK_SPEED_CHECK_DELAY - 10;
- else if (sig_delay < delay_time - 10)
- delay_time = Backup::DISK_SPEED_CHECK_DELAY + 10;
- else
- delay_time = Backup::DISK_SPEED_CHECK_DELAY - (sig_delay - delay_time);
- m_reset_delay_used= delay_time;
- signal->theData[0] = BackupContinueB::RESET_DISK_SPEED_COUNTER;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, delay_time, 1);
-#if 0
- ndbout << "Signal delay was = " << sig_delay;
- ndbout << " Current time = " << curr_time << endl;
- ndbout << " Delay time will be = " << delay_time << endl << endl;
-#endif
- break;
- }
- case BackupContinueB::BACKUP_FRAGMENT_INFO:
- {
- jam();
- const Uint32 ptr_I = Tdata1;
- Uint32 tabPtr_I = Tdata2;
- Uint32 fragPtr_I = signal->theData[3];
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptr_I);
- TablePtr tabPtr;
- ptr.p->tables.getPtr(tabPtr, tabPtr_I);
-
- if (fragPtr_I != tabPtr.p->fragments.getSize())
- {
- jam();
- FragmentPtr fragPtr;
- tabPtr.p->fragments.getPtr(fragPtr, fragPtr_I);
-
- BackupFilePtr filePtr LINT_SET_PTR;
- 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);
- fragInfo->FilePosHigh = htonl(0);
-
- 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)
- {
- jam();
- 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:
- {
- jam();
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, Tdata1);
- checkFile(signal, filePtr);
- return;
- }
- break;
- case BackupContinueB::BUFFER_FULL_SCAN:
- {
- jam();
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, Tdata1);
- checkScan(signal, filePtr);
- return;
- }
- break;
- case BackupContinueB::BUFFER_FULL_FRAG_COMPLETE:
- {
- jam();
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, Tdata1);
- fragmentCompleted(signal, filePtr);
- return;
- }
- break;
- case BackupContinueB::BUFFER_FULL_META:
- {
- jam();
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, Tdata1);
-
- BackupFilePtr filePtr LINT_SET_PTR;
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
- FsBuffer & buf = filePtr.p->operation.dataBuffer;
-
- if(buf.getFreeSize() < buf.getMaxWrite()) {
- jam();
- TablePtr tabPtr LINT_SET_PTR;
- c_tablePool.getPtr(tabPtr, Tdata2);
-
- DEBUG_OUT("Backup - Buffer full - "
- << buf.getFreeSize()
- << " < " << buf.getMaxWrite()
- << " (sz: " << buf.getUsableSize()
- << " getMinRead: " << buf.getMinRead()
- << ") - tableId = " << tabPtr.p->tableId);
-
- signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
- signal->theData[1] = Tdata1;
- signal->theData[2] = Tdata2;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
- return;
- }//if
-
- TablePtr tabPtr LINT_SET_PTR;
- c_tablePool.getPtr(tabPtr, Tdata2);
- GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = ptr.i;
- req->requestType = GetTabInfoReq::RequestById |
- GetTabInfoReq::LongSignalConf;
- req->tableId = tabPtr.p->tableId;
- sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB);
- return;
- }
- case BackupContinueB::ZDELAY_SCAN_NEXT:
- if (ERROR_INSERTED(10036))
- {
- jam();
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 300,
- signal->getLength());
- return;
- }
- else
- {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- ndbout_c("Resuming backup");
- memmove(signal->theData, signal->theData + 1,
- 4*ScanFragNextReq::SignalLength);
- sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- return ;
- }
- default:
- ndbrequire(0);
- }//switch
-}
-
-void
-Backup::execDUMP_STATE_ORD(Signal* signal)
-{
- jamEntry();
-
- if(signal->theData[0] == 20){
- if(signal->length() > 1){
- c_defaults.m_dataBufferSize = (signal->theData[1] * 1024 * 1024);
- }
- if(signal->length() > 2){
- c_defaults.m_logBufferSize = (signal->theData[2] * 1024 * 1024);
- }
- if(signal->length() > 3){
- c_defaults.m_minWriteSize = signal->theData[3] * 1024;
- }
- if(signal->length() > 4){
- c_defaults.m_maxWriteSize = signal->theData[4] * 1024;
- }
-
- infoEvent("Backup: data: %d log: %d min: %d max: %d",
- c_defaults.m_dataBufferSize,
- c_defaults.m_logBufferSize,
- c_defaults.m_minWriteSize,
- c_defaults.m_maxWriteSize);
- return;
- }
- if(signal->theData[0] == 21){
- BackupReq * req = (BackupReq*)signal->getDataPtrSend();
- req->senderData = 23;
- req->backupDataLen = 0;
- sendSignal(BACKUP_REF, GSN_BACKUP_REQ,signal,BackupReq::SignalLength, JBB);
- startTime = NdbTick_CurrentMillisecond();
- return;
- }
-
- if(signal->theData[0] == 22){
- const Uint32 seq = signal->theData[1];
- FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
- req->userReference = reference();
- req->userPointer = 23;
- req->directory = 1;
- req->ownDirectory = 1;
- FsOpenReq::setVersion(req->fileNumber, 2);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
- FsOpenReq::v2_setSequence(req->fileNumber, seq);
- FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
- sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
- FsRemoveReq::SignalLength, JBA);
- return;
- }
-
- if(signal->theData[0] == 23){
- /**
- * Print records
- */
- BackupRecordPtr ptr LINT_SET_PTR;
- for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)){
- infoEvent("BackupRecord %d: BackupId: %d MasterRef: %x ClientRef: %x",
- ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef);
- infoEvent(" State: %d", ptr.p->slaveState.getState());
- BackupFilePtr filePtr;
- for(ptr.p->files.first(filePtr); filePtr.i != RNIL;
- ptr.p->files.next(filePtr)){
- jam();
- infoEvent(" file %d: type: %d flags: H'%x",
- filePtr.i, filePtr.p->fileType,
- filePtr.p->m_flags);
- }
- }
-
- ndbout_c("m_curr_disk_write_speed: %u m_words_written_this_period: %u m_overflow_disk_write: %u",
- m_curr_disk_write_speed, m_words_written_this_period, m_overflow_disk_write);
- ndbout_c("m_reset_delay_used: %u m_reset_disk_speed_time: %llu",
- m_reset_delay_used, (Uint64)m_reset_disk_speed_time);
- for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr))
- {
- ndbout_c("BackupRecord %u: BackupId: %u MasterRef: %x ClientRef: %x",
- ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef);
- ndbout_c(" State: %u", ptr.p->slaveState.getState());
- ndbout_c(" noOfByte: %llu noOfRecords: %llu",
- ptr.p->noOfBytes, ptr.p->noOfRecords);
- ndbout_c(" noOfLogBytes: %llu noOfLogRecords: %llu",
- ptr.p->noOfLogBytes, ptr.p->noOfLogRecords);
- ndbout_c(" errorCode: %u", ptr.p->errorCode);
- BackupFilePtr filePtr;
- for(ptr.p->files.first(filePtr); filePtr.i != RNIL;
- ptr.p->files.next(filePtr))
- {
- ndbout_c(" file %u: type: %u flags: H'%x tableId: %u fragmentId: %u",
- filePtr.i, filePtr.p->fileType, filePtr.p->m_flags,
- filePtr.p->tableId, filePtr.p->fragmentNo);
- }
- if (ptr.p->slaveState.getState() == SCANNING && ptr.p->dataFilePtr != RNIL)
- {
- c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
- OperationRecord & op = filePtr.p->operation;
- Uint32 *tmp = NULL;
- Uint32 sz = 0;
- bool eof = FALSE;
- bool ready = op.dataBuffer.getReadPtr(&tmp, &sz, &eof);
- ndbout_c("ready: %s eof: %s", ready ? "TRUE" : "FALSE", eof ? "TRUE" : "FALSE");
- }
- }
- return;
- }
- if(signal->theData[0] == 24){
- /**
- * Print size of records etc.
- */
- infoEvent("Backup - dump pool sizes");
- infoEvent("BackupPool: %d BackupFilePool: %d TablePool: %d",
- c_backupPool.getSize(), c_backupFilePool.getSize(),
- c_tablePool.getSize());
- infoEvent("AttrPool: %d TriggerPool: %d FragmentPool: %d",
- c_backupPool.getSize(), c_backupFilePool.getSize(),
- c_tablePool.getSize());
- infoEvent("PagePool: %d",
- c_pagePool.getSize());
-
-
- if(signal->getLength() == 2 && signal->theData[1] == 2424)
- {
- /**
- * Handle LCP
- */
- BackupRecordPtr lcp;
- ndbrequire(c_backups.first(lcp));
-
- ndbrequire(c_backupPool.getSize() == c_backupPool.getNoOfFree() + 1);
- if(lcp.p->tables.isEmpty())
- {
- ndbrequire(c_tablePool.getSize() == c_tablePool.getNoOfFree());
- ndbrequire(c_attributePool.getSize() == c_attributePool.getNoOfFree());
- ndbrequire(c_fragmentPool.getSize() == c_fragmentPool.getNoOfFree());
- ndbrequire(c_triggerPool.getSize() == c_triggerPool.getNoOfFree());
- }
- ndbrequire(c_backupFilePool.getSize() == c_backupFilePool.getNoOfFree() + 1);
- BackupFilePtr lcp_file;
- c_backupFilePool.getPtr(lcp_file, lcp.p->dataFilePtr);
- ndbrequire(c_pagePool.getSize() ==
- c_pagePool.getNoOfFree() +
- lcp_file.p->pages.getSize());
- }
- }
-}
-
-bool
-Backup::findTable(const BackupRecordPtr & ptr,
- TablePtr & tabPtr, Uint32 tableId) const
-{
- for(ptr.p->tables.first(tabPtr);
- tabPtr.i != RNIL;
- ptr.p->tables.next(tabPtr)) {
- jam();
- if(tabPtr.p->tableId == tableId){
- jam();
- return true;
- }//if
- }//for
- tabPtr.i = RNIL;
- tabPtr.p = 0;
- return false;
-}
-
-static Uint32 xps(Uint64 x, Uint64 ms)
-{
- float fx = x;
- float fs = ms;
-
- if(ms == 0 || x == 0) {
- jam();
- return 0;
- }//if
- jam();
- return ((Uint32)(1000.0f * (fx + fs/2.1f))) / ((Uint32)fs);
-}
-
-struct Number {
- Number(Uint64 r) { val = r;}
- Number & operator=(Uint64 r) { val = r; return * this; }
- Uint64 val;
-};
-
-NdbOut &
-operator<< (NdbOut & out, const Number & val){
- char p = 0;
- Uint32 loop = 1;
- while(val.val > loop){
- loop *= 1000;
- p += 3;
- }
- if(loop != 1){
- p -= 3;
- loop /= 1000;
- }
-
- switch(p){
- case 0:
- break;
- case 3:
- p = 'k';
- break;
- case 6:
- p = 'M';
- break;
- case 9:
- p = 'G';
- break;
- default:
- p = 0;
- }
- char str[2];
- str[0] = p;
- str[1] = 0;
- Uint32 tmp = (val.val + (loop >> 1)) / loop;
-#if 1
- if(p > 0)
- out << tmp << str;
- else
- out << tmp;
-#else
- out << val.val;
-#endif
-
- return out;
-}
-
-void
-Backup::execBACKUP_CONF(Signal* signal)
-{
- jamEntry();
- BackupConf * conf = (BackupConf*)signal->getDataPtr();
-
- ndbout_c("Backup %d has started", conf->backupId);
-}
-
-void
-Backup::execBACKUP_REF(Signal* signal)
-{
- jamEntry();
- BackupRef * ref = (BackupRef*)signal->getDataPtr();
-
- ndbout_c("Backup (%d) has NOT started %d", ref->senderData, ref->errorCode);
-}
-
-void
-Backup::execBACKUP_COMPLETE_REP(Signal* signal)
-{
- jamEntry();
- BackupCompleteRep* rep = (BackupCompleteRep*)signal->getDataPtr();
-
- startTime = NdbTick_CurrentMillisecond() - startTime;
-
- ndbout_c("Backup %d has completed", rep->backupId);
- 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);
-
- ndbout << " Data [ "
- << Number(records) << " rows "
- << Number(bytes) << " bytes " << startTime << " ms ] "
- << " => "
- << rps << " row/s & " << bps << "b/s" << endl;
-
- bps = xps(rep->noOfLogBytes, startTime);
- rps = xps(rep->noOfLogRecords, startTime);
-
- ndbout << " Log [ "
- << Number(rep->noOfLogRecords) << " log records "
- << Number(rep->noOfLogBytes) << " bytes " << startTime << " ms ] "
- << " => "
- << rps << " records/s & " << bps << "b/s" << endl;
-
-}
-
-void
-Backup::execBACKUP_ABORT_REP(Signal* signal)
-{
- jamEntry();
- BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtr();
-
- ndbout_c("Backup %d has been aborted %d", rep->backupId, rep->reason);
-}
-
-const TriggerEvent::Value triggerEventValues[] = {
- TriggerEvent::TE_INSERT,
- TriggerEvent::TE_UPDATE,
- TriggerEvent::TE_DELETE
-};
-
-const Backup::State
-Backup::validSlaveTransitions[] = {
- INITIAL, DEFINING,
- DEFINING, DEFINED,
- DEFINED, STARTED,
- STARTED, STARTED, // Several START_BACKUP_REQ is sent
- STARTED, SCANNING,
- SCANNING, STARTED,
- STARTED, STOPPING,
- STOPPING, CLEANING,
- CLEANING, INITIAL,
-
- INITIAL, ABORTING, // Node fail
- DEFINING, ABORTING,
- DEFINED, ABORTING,
- STARTED, ABORTING,
- SCANNING, ABORTING,
- STOPPING, ABORTING,
- CLEANING, ABORTING, // Node fail w/ master takeover
- ABORTING, ABORTING, // Slave who initiates ABORT should have this transition
-
- ABORTING, INITIAL,
- INITIAL, INITIAL
-};
-
-const Uint32
-Backup::validSlaveTransitionsCount =
-sizeof(Backup::validSlaveTransitions) / sizeof(Backup::State);
-
-void
-Backup::CompoundState::setState(State newState){
- bool found = false;
- const State currState = state;
- for(unsigned i = 0; i<noOfValidTransitions; i+= 2) {
- jam();
- if(validTransitions[i] == currState &&
- validTransitions[i+1] == newState){
- jam();
- found = true;
- break;
- }
- }
-
- //ndbrequire(found);
-
- if (newState == INITIAL)
- abortState = INITIAL;
- if(newState == ABORTING && currState != ABORTING) {
- jam();
- abortState = currState;
- }
- state = newState;
-#ifdef DEBUG_ABORT
- if (newState != currState) {
- ndbout_c("%u: Old state = %u, new state = %u, abort state = %u",
- id, currState, newState, abortState);
- }
-#endif
-}
-
-void
-Backup::CompoundState::forceState(State newState)
-{
- const State currState = state;
- if (newState == INITIAL)
- abortState = INITIAL;
- if(newState == ABORTING && currState != ABORTING) {
- jam();
- abortState = currState;
- }
- state = newState;
-#ifdef DEBUG_ABORT
- if (newState != currState) {
- ndbout_c("%u: FORCE: Old state = %u, new state = %u, abort state = %u",
- id, currState, newState, abortState);
- }
-#endif
-}
-
-Backup::Table::Table(ArrayPool<Attribute> & ah,
- ArrayPool<Fragment> & fh)
- : attributes(ah), fragments(fh)
-{
- triggerIds[0] = ILLEGAL_TRIGGER_ID;
- triggerIds[1] = ILLEGAL_TRIGGER_ID;
- triggerIds[2] = ILLEGAL_TRIGGER_ID;
- triggerAllocated[0] = false;
- triggerAllocated[1] = false;
- triggerAllocated[2] = false;
-}
-
-/*****************************************************************************
- *
- * Node state handling
- *
- *****************************************************************************/
-void
-Backup::execNODE_FAILREP(Signal* signal)
-{
- jamEntry();
-
- NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
-
- bool doStuff = false;
- /*
- Start by saving important signal data which will be destroyed before the
- process is completed.
- */
- NodeId new_master_node_id = rep->masterNodeId;
- Uint32 theFailedNodes[NodeBitmask::Size];
- for (Uint32 i = 0; i < NodeBitmask::Size; i++)
- theFailedNodes[i] = rep->theNodes[i];
-
- c_masterNodeId = new_master_node_id;
-
- NodePtr nodePtr;
- for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
- jam();
- if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)){
- if(nodePtr.p->alive){
- jam();
- ndbrequire(c_aliveNodes.get(nodePtr.p->nodeId));
- doStuff = true;
- } else {
- jam();
- ndbrequire(!c_aliveNodes.get(nodePtr.p->nodeId));
- }//if
- nodePtr.p->alive = 0;
- c_aliveNodes.clear(nodePtr.p->nodeId);
- }//if
- }//for
-
- if(!doStuff){
- jam();
- return;
- }//if
-
-#ifdef DEBUG_ABORT
- ndbout_c("****************** Node fail rep ******************");
-#endif
-
- NodeId newCoordinator = c_masterNodeId;
- BackupRecordPtr ptr;
- for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
- jam();
- checkNodeFail(signal, ptr, newCoordinator, theFailedNodes);
- }
-}
-
-bool
-Backup::verifyNodesAlive(BackupRecordPtr ptr,
- const NdbNodeBitmask& aNodeBitMask)
-{
- Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
- for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
- jam();
- if(aNodeBitMask.get(i)) {
- if(!c_aliveNodes.get(i)){
- jam();
- ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
- return false;
- }//if
- if(getNodeInfo(i).m_version != version)
- {
- jam();
- ptr.p->setErrorCode(AbortBackupOrd::IncompatibleVersions);
- return false;
- }
- }//if
- }//for
- return true;
-}
-
-void
-Backup::checkNodeFail(Signal* signal,
- BackupRecordPtr ptr,
- NodeId newCoord,
- Uint32 theFailedNodes[NodeBitmask::Size])
-{
- NdbNodeBitmask mask;
- mask.assign(2, theFailedNodes);
-
- /* Update ptr.p->nodes to be up to date with current alive nodes
- */
- NodePtr nodePtr;
- bool found = false;
- for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)) {
- jam();
- if(NodeBitmask::get(theFailedNodes, nodePtr.p->nodeId)) {
- jam();
- if (ptr.p->nodes.get(nodePtr.p->nodeId)) {
- jam();
- ptr.p->nodes.clear(nodePtr.p->nodeId);
- found = true;
- }
- }//if
- }//for
-
- if(!found) {
- jam();
- return; // failed node is not part of backup process, safe to continue
- }
-
- if(mask.get(refToNode(ptr.p->masterRef)))
- {
- /**
- * Master died...abort
- */
- ptr.p->masterRef = reference();
- ptr.p->nodes.clear();
- ptr.p->nodes.set(getOwnNodeId());
- ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
- switch(ptr.p->m_gsn){
- case GSN_DEFINE_BACKUP_REQ:
- case GSN_START_BACKUP_REQ:
- case GSN_BACKUP_FRAGMENT_REQ:
- case GSN_STOP_BACKUP_REQ:
- // I'm currently processing...reply to self and abort...
- ptr.p->masterData.gsn = ptr.p->m_gsn;
- ptr.p->masterData.sendCounter = ptr.p->nodes;
- return;
- case GSN_DEFINE_BACKUP_REF:
- case GSN_DEFINE_BACKUP_CONF:
- case GSN_START_BACKUP_REF:
- case GSN_START_BACKUP_CONF:
- case GSN_BACKUP_FRAGMENT_REF:
- case GSN_BACKUP_FRAGMENT_CONF:
- case GSN_STOP_BACKUP_REF:
- case GSN_STOP_BACKUP_CONF:
- ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
- masterAbort(signal, ptr);
- return;
- case GSN_ABORT_BACKUP_ORD:
- // Already aborting
- return;
- }
- }
- else if (newCoord == getOwnNodeId())
- {
- /**
- * I'm master for this backup
- */
- jam();
- CRASH_INSERTION((10001));
-#ifdef DEBUG_ABORT
- ndbout_c("**** Master: Node failed: Master id = %u",
- refToNode(ptr.p->masterRef));
-#endif
-
- Uint32 gsn, len, pos;
- LINT_INIT(gsn);
- LINT_INIT(len);
- LINT_INIT(pos);
- ptr.p->nodes.bitANDC(mask);
- switch(ptr.p->masterData.gsn){
- case GSN_DEFINE_BACKUP_REQ:
- {
- DefineBackupRef * ref = (DefineBackupRef*)signal->getDataPtr();
- ref->backupPtr = ptr.i;
- ref->backupId = ptr.p->backupId;
- ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
- gsn= GSN_DEFINE_BACKUP_REF;
- len= DefineBackupRef::SignalLength;
- pos= &ref->nodeId - signal->getDataPtr();
- break;
- }
- case GSN_START_BACKUP_REQ:
- {
- StartBackupRef * ref = (StartBackupRef*)signal->getDataPtr();
- ref->backupPtr = ptr.i;
- ref->backupId = ptr.p->backupId;
- ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
- gsn= GSN_START_BACKUP_REF;
- len= StartBackupRef::SignalLength;
- pos= &ref->nodeId - signal->getDataPtr();
- break;
- }
- case GSN_BACKUP_FRAGMENT_REQ:
- {
- BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
- ref->backupPtr = ptr.i;
- ref->backupId = ptr.p->backupId;
- ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
- gsn= GSN_BACKUP_FRAGMENT_REF;
- len= BackupFragmentRef::SignalLength;
- pos= &ref->nodeId - signal->getDataPtr();
- break;
- }
- case GSN_STOP_BACKUP_REQ:
- {
- StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr();
- ref->backupPtr = ptr.i;
- ref->backupId = ptr.p->backupId;
- ref->errorCode = AbortBackupOrd::BackupFailureDueToNodeFail;
- ref->nodeId = getOwnNodeId();
- gsn= GSN_STOP_BACKUP_REF;
- len= StopBackupRef::SignalLength;
- pos= &ref->nodeId - signal->getDataPtr();
- break;
- }
- case GSN_WAIT_GCP_REQ:
- case GSN_DROP_TRIG_REQ:
- case GSN_CREATE_TRIG_REQ:
- case GSN_ALTER_TRIG_REQ:
- ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail);
- return;
- case GSN_UTIL_SEQUENCE_REQ:
- case GSN_UTIL_LOCK_REQ:
- return;
- default:
- ndbrequire(false);
- }
-
- for(Uint32 i = 0; (i = mask.find(i+1)) != NdbNodeBitmask::NotFound; )
- {
- signal->theData[pos] = i;
- sendSignal(reference(), gsn, signal, len, JBB);
-#ifdef DEBUG_ABORT
- ndbout_c("sending %d to self from %d", gsn, i);
-#endif
- }
- return;
- }//if
-
- /**
- * I abort myself as slave if not master
- */
- CRASH_INSERTION((10021));
-}
-
-void
-Backup::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));
-
- node.p->alive = 1;
- c_aliveNodes.set(nodeId);
-
- break;
- }//if
- }//for
- signal->theData[0] = inclNode;
- signal->theData[1] = reference();
- sendSignal(senderRef, GSN_INCL_NODECONF, signal, 2, JBB);
-}
-
-/*****************************************************************************
- *
- * Master functionallity - Define backup
- *
- *****************************************************************************/
-
-void
-Backup::execBACKUP_REQ(Signal* signal)
-{
- jamEntry();
- BackupReq * req = (BackupReq*)signal->getDataPtr();
-
- const Uint32 senderData = req->senderData;
- const BlockReference senderRef = signal->senderBlockRef();
- const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
- const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
-
- if(getOwnNodeId() != getMasterNodeId()) {
- jam();
- sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
- return;
- }//if
-
- if (c_defaults.m_diskless)
- {
- sendBackupRef(senderRef, flags, signal, senderData,
- BackupRef::CannotBackupDiskless);
- return;
- }
-
- if(dataLen32 != 0) {
- jam();
- sendBackupRef(senderRef, flags, signal, senderData,
- BackupRef::BackupDefinitionNotImplemented);
- return;
- }//if
-
-#ifdef DEBUG_ABORT
- dumpUsedResources();
-#endif
- /**
- * Seize a backup record
- */
- BackupRecordPtr ptr;
- c_backups.seize(ptr);
- if(ptr.i == RNIL) {
- jam();
- sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
- return;
- }//if
-
- ndbrequire(ptr.p->tables.isEmpty());
-
- ptr.p->m_gsn = 0;
- ptr.p->errorCode = 0;
- ptr.p->clientRef = senderRef;
- ptr.p->clientData = senderData;
- ptr.p->flags = flags;
- ptr.p->masterRef = reference();
- ptr.p->nodes = c_aliveNodes;
- ptr.p->backupId = 0;
- ptr.p->backupKey[0] = 0;
- ptr.p->backupKey[1] = 0;
- ptr.p->backupDataLen = 0;
- ptr.p->masterData.errorCode = 0;
-
- UtilSequenceReq * utilReq = (UtilSequenceReq*)signal->getDataPtrSend();
-
- ptr.p->masterData.gsn = GSN_UTIL_SEQUENCE_REQ;
- utilReq->senderData = ptr.i;
- utilReq->sequenceId = BACKUP_SEQUENCE;
- utilReq->requestType = UtilSequenceReq::NextVal;
- sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
- signal, UtilSequenceReq::SignalLength, JBB);
-}
-
-void
-Backup::execUTIL_SEQUENCE_REF(Signal* signal)
-{
- BackupRecordPtr ptr LINT_SET_PTR;
- jamEntry();
- UtilSequenceRef * utilRef = (UtilSequenceRef*)signal->getDataPtr();
- ptr.i = utilRef->senderData;
- c_backupPool.getPtr(ptr);
- ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
- sendBackupRef(signal, ptr, BackupRef::SequenceFailure);
-}//execUTIL_SEQUENCE_REF()
-
-
-void
-Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
-{
- jam();
- sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
- cleanup(signal, ptr);
-}
-
-void
-Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
- Uint32 senderData, Uint32 errorCode)
-{
- jam();
- if (SEND_BACKUP_STARTED_FLAG(flags))
- {
- BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->errorCode = errorCode;
- ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
- sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
- }
-
- if(errorCode != BackupRef::IAmNotMaster){
- signal->theData[0] = NDB_LE_BackupFailedToStart;
- signal->theData[1] = senderRef;
- signal->theData[2] = errorCode;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
- }
-}
-
-void
-Backup::execUTIL_SEQUENCE_CONF(Signal* signal)
-{
- jamEntry();
-
- UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr();
-
- if(conf->requestType == UtilSequenceReq::Create)
- {
- jam();
- sendSTTORRY(signal); // At startup in NDB
- return;
- }
-
- BackupRecordPtr ptr LINT_SET_PTR;
- ptr.i = conf->senderData;
- c_backupPool.getPtr(ptr);
-
- ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_SEQUENCE_REQ);
-
- if (ptr.p->checkError())
- {
- jam();
- sendBackupRef(signal, ptr, ptr.p->errorCode);
- return;
- }//if
-
- if (ERROR_INSERTED(10023))
- {
- sendBackupRef(signal, ptr, 323);
- return;
- }//if
-
-
- {
- Uint64 backupId;
- memcpy(&backupId,conf->sequenceValue,8);
- ptr.p->backupId= (Uint32)backupId;
- }
- ptr.p->backupKey[0] = (getOwnNodeId() << 16) | (ptr.p->backupId & 0xFFFF);
- ptr.p->backupKey[1] = NdbTick_CurrentMillisecond();
-
- ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
- Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
- Callback c = { safe_cast(&Backup::defineBackupMutex_locked), ptr.i };
- ndbrequire(mutex.lock(c));
-
- return;
-}
-
-void
-Backup::defineBackupMutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){
- jamEntry();
- ndbrequire(retVal == 0);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- ptr.i = ptrI;
- c_backupPool.getPtr(ptr);
-
- ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
-
- ptr.p->masterData.gsn = GSN_UTIL_LOCK_REQ;
- Mutex mutex(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
- Callback c = { safe_cast(&Backup::dictCommitTableMutex_locked), ptr.i };
- ndbrequire(mutex.lock(c));
-}
-
-void
-Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal)
-{
- jamEntry();
- ndbrequire(retVal == 0);
-
- /**
- * We now have both the mutexes
- */
- BackupRecordPtr ptr LINT_SET_PTR;
- ptr.i = ptrI;
- c_backupPool.getPtr(ptr);
-
- ndbrequire(ptr.p->masterData.gsn == GSN_UTIL_LOCK_REQ);
-
- if (ERROR_INSERTED(10031)) {
- ptr.p->setErrorCode(331);
- }//if
-
- if (ptr.p->checkError())
- {
- jam();
-
- /**
- * Unlock mutexes
- */
- jam();
- Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
- jam();
- mutex1.unlock(); // ignore response
-
- jam();
- Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
- jam();
- mutex2.unlock(); // ignore response
-
- sendBackupRef(signal, ptr, ptr.p->errorCode);
- return;
- }//if
-
- sendDefineBackupReq(signal, ptr);
-}
-
-/*****************************************************************************
- *
- * Master functionallity - Define backup cont'd (from now on all slaves are in)
- *
- *****************************************************************************/
-
-bool
-Backup::haveAllSignals(BackupRecordPtr ptr, Uint32 gsn, Uint32 nodeId)
-{
- ndbrequire(ptr.p->masterRef == reference());
- ndbrequire(ptr.p->masterData.gsn == gsn);
- ndbrequire(!ptr.p->masterData.sendCounter.done());
- ndbrequire(ptr.p->masterData.sendCounter.isWaitingFor(nodeId));
-
- ptr.p->masterData.sendCounter.clearWaitingFor(nodeId);
- return ptr.p->masterData.sendCounter.done();
-}
-
-void
-Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
-{
- /**
- * Sending define backup to all participants
- */
- DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
- req->backupId = ptr.p->backupId;
- req->clientRef = ptr.p->clientRef;
- req->clientData = ptr.p->clientData;
- req->senderRef = reference();
- req->backupPtr = ptr.i;
- req->backupKey[0] = ptr.p->backupKey[0];
- req->backupKey[1] = ptr.p->backupKey[1];
- req->nodes = ptr.p->nodes;
- req->backupDataLen = ptr.p->backupDataLen;
- req->flags = ptr.p->flags;
-
- ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
- ptr.p->masterData.sendCounter = ptr.p->nodes;
- NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
- sendSignal(rg, GSN_DEFINE_BACKUP_REQ, signal,
- DefineBackupReq::SignalLength, JBB);
-
- /**
- * Now send backup data
- */
- const Uint32 len = ptr.p->backupDataLen;
- if(len == 0){
- /**
- * No data to send
- */
- jam();
- return;
- }//if
-
- /**
- * Not implemented
- */
- ndbrequire(0);
-}
-
-void
-Backup::execDEFINE_BACKUP_REF(Signal* signal)
-{
- jamEntry();
-
- DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtr();
-
- const Uint32 ptrI = ref->backupPtr;
- //const Uint32 backupId = ref->backupId;
- const Uint32 nodeId = ref->nodeId;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->setErrorCode(ref->errorCode);
- defineBackupReply(signal, ptr, nodeId);
-}
-
-void
-Backup::execDEFINE_BACKUP_CONF(Signal* signal)
-{
- jamEntry();
-
- DefineBackupConf* conf = (DefineBackupConf*)signal->getDataPtr();
- const Uint32 ptrI = conf->backupPtr;
- //const Uint32 backupId = conf->backupId;
- const Uint32 nodeId = refToNode(signal->senderBlockRef());
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- if (ERROR_INSERTED(10024))
- {
- ptr.p->setErrorCode(324);
- }
-
- defineBackupReply(signal, ptr, nodeId);
-}
-
-void
-Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
-{
- if (!haveAllSignals(ptr, GSN_DEFINE_BACKUP_REQ, nodeId)) {
- jam();
- return;
- }
-
- /**
- * Unlock mutexes
- */
- jam();
- Mutex mutex1(signal, c_mutexMgr, ptr.p->masterData.m_dictCommitTableMutex);
- jam();
- mutex1.unlock(); // ignore response
-
- jam();
- Mutex mutex2(signal, c_mutexMgr, ptr.p->masterData.m_defineBackupMutex);
- jam();
- mutex2.unlock(); // ignore response
-
- if(ptr.p->checkError())
- {
- jam();
- masterAbort(signal, ptr);
- return;
- }
-
- /**
- * Reply to client
- */
- CRASH_INSERTION((10034));
-
- if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
- {
- BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
- conf->backupId = ptr.p->backupId;
- conf->senderData = ptr.p->clientData;
- conf->nodes = ptr.p->nodes;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
- BackupConf::SignalLength, JBB);
- }
-
- 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);
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB);
-
- /**
- * We've received GSN_DEFINE_BACKUP_CONF from all participants.
- *
- * Our next step is to send START_BACKUP_REQ to all participants,
- * who will then send CREATE_TRIG_REQ for all tables to their local
- * DBTUP.
- */
- TablePtr tabPtr;
- ptr.p->tables.first(tabPtr);
-
- sendStartBackup(signal, ptr, tabPtr);
-}
-
-/*****************************************************************************
- *
- * Master functionallity - Prepare triggers
- *
- *****************************************************************************/
-void
-Backup::createAttributeMask(TablePtr tabPtr,
- Bitmask<MAXNROFATTRIBUTESINWORDS> & mask)
-{
- mask.clear();
- Table & table = * tabPtr.p;
- Ptr<Attribute> attrPtr;
- table.attributes.first(attrPtr);
- for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
- {
- jam();
- mask.set(attrPtr.p->data.attrId);
- }
-}
-
-void
-Backup::sendCreateTrig(Signal* signal,
- BackupRecordPtr ptr, TablePtr tabPtr)
-{
- CreateTrigReq * req =(CreateTrigReq *)signal->getDataPtrSend();
-
- /*
- * First, setup the structures
- */
- for(Uint32 j=0; j<3; j++) {
- jam();
-
- TriggerPtr trigPtr;
- if(!ptr.p->triggers.seize(trigPtr)) {
- jam();
- ptr.p->m_gsn = GSN_START_BACKUP_REF;
- StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
- ref->backupPtr = ptr.i;
- ref->backupId = ptr.p->backupId;
- ref->errorCode = StartBackupRef::FailedToAllocateTriggerRecord;
- ref->nodeId = getOwnNodeId();
- sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
- StartBackupRef::SignalLength, JBB);
- return;
- } // if
-
- const Uint32 triggerId= trigPtr.i;
- tabPtr.p->triggerIds[j] = triggerId;
- tabPtr.p->triggerAllocated[j] = true;
- trigPtr.p->backupPtr = ptr.i;
- trigPtr.p->tableId = tabPtr.p->tableId;
- trigPtr.p->tab_ptr_i = tabPtr.i;
- trigPtr.p->logEntry = 0;
- trigPtr.p->event = j;
- trigPtr.p->maxRecordSize = 4096;
- trigPtr.p->operation =
- &ptr.p->files.getPtr(ptr.p->logFilePtr)->operation;
- trigPtr.p->operation->noOfBytes = 0;
- trigPtr.p->operation->noOfRecords = 0;
- trigPtr.p->errorCode = 0;
- } // for
-
- /*
- * now ask DBTUP to create
- */
- ptr.p->slaveData.gsn = GSN_CREATE_TRIG_REQ;
- ptr.p->slaveData.trigSendCounter = 3;
- ptr.p->slaveData.createTrig.tableId = tabPtr.p->tableId;
-
- req->setUserRef(reference());
- req->setReceiverRef(reference());
- req->setConnectionPtr(ptr.i);
- req->setRequestType(CreateTrigReq::RT_USER);
-
- Bitmask<MAXNROFATTRIBUTESINWORDS> attrMask;
- createAttributeMask(tabPtr, attrMask);
- req->setAttributeMask(attrMask);
- req->setTableId(tabPtr.p->tableId);
- req->setIndexId(RNIL); // not used
- req->setTriggerType(TriggerType::SUBSCRIPTION);
- req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
- req->setMonitorReplicas(true);
- req->setMonitorAllAttributes(false);
- req->setOnline(true);
-
- for (int i=0; i < 3; i++) {
- req->setTriggerId(tabPtr.p->triggerIds[i]);
- req->setTriggerEvent(triggerEventValues[i]);
-
- sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB);
- }
-}
-
-void
-Backup::execCREATE_TRIG_CONF(Signal* signal)
-{
- jamEntry();
- CreateTrigConf * conf = (CreateTrigConf*)signal->getDataPtr();
-
- const Uint32 ptrI = conf->getConnectionPtr();
- const Uint32 tableId = conf->getTableId();
- const TriggerEvent::Value type = conf->getTriggerEvent();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- /**
- * Verify that I'm waiting for this conf
- *
- * ptr.p->masterRef != reference()
- * as slaves and masters have triggers now.
- */
- ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
- ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
- ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
-
- TablePtr tabPtr;
- ndbrequire(findTable(ptr, tabPtr, tableId));
- ndbrequire(type < 3); // if some decides to change the enums
-
- createTrigReply(signal, ptr);
-}
-
-void
-Backup::execCREATE_TRIG_REF(Signal* signal)
-{
- jamEntry();
- CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtr();
-
- const Uint32 ptrI = ref->getConnectionPtr();
- const Uint32 tableId = ref->getTableId();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- /**
- * Verify that I'm waiting for this ref
- *
- * ptr.p->masterRef != reference()
- * as slaves and masters have triggers now
- */
- ndbrequire(ptr.p->slaveData.gsn == GSN_CREATE_TRIG_REQ);
- ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
- ndbrequire(ptr.p->slaveData.createTrig.tableId == tableId);
-
- ptr.p->setErrorCode(ref->getErrorCode());
-
- createTrigReply(signal, ptr);
-}
-
-void
-Backup::createTrigReply(Signal* signal, BackupRecordPtr ptr)
-{
- CRASH_INSERTION(10003);
-
- /**
- * Check finished with table
- */
- ptr.p->slaveData.trigSendCounter--;
- if(ptr.p->slaveData.trigSendCounter.done() == false){
- jam();
- return;
- }//if
-
- if (ERROR_INSERTED(10025))
- {
- ptr.p->errorCode = 325;
- }
-
- if(ptr.p->checkError()) {
- jam();
- ptr.p->m_gsn = GSN_START_BACKUP_REF;
- StartBackupRef* ref = (StartBackupRef*)signal->getDataPtrSend();
- ref->backupPtr = ptr.i;
- ref->backupId = ptr.p->backupId;
- ref->errorCode = ptr.p->errorCode;
- ref->nodeId = getOwnNodeId();
- sendSignal(ptr.p->masterRef, GSN_START_BACKUP_REF, signal,
- StartBackupRef::SignalLength, JBB);
- return;
- }//if
-
- TablePtr tabPtr;
- ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.createTrig.tableId));
-
- /**
- * Next table
- */
- ptr.p->tables.next(tabPtr);
- if(tabPtr.i != RNIL){
- jam();
- sendCreateTrig(signal, ptr, tabPtr);
- return;
- }//if
-
- /**
- * We've finished creating triggers.
- *
- * send conf and wait
- */
- ptr.p->m_gsn = GSN_START_BACKUP_CONF;
- StartBackupConf* conf = (StartBackupConf*)signal->getDataPtrSend();
- conf->backupPtr = ptr.i;
- conf->backupId = ptr.p->backupId;
- sendSignal(ptr.p->masterRef, GSN_START_BACKUP_CONF, signal,
- StartBackupConf::SignalLength, JBB);
-}
-
-/*****************************************************************************
- *
- * Master functionallity - Start backup
- *
- *****************************************************************************/
-void
-Backup::sendStartBackup(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
-{
-
- ptr.p->masterData.startBackup.tablePtr = tabPtr.i;
-
- StartBackupReq* req = (StartBackupReq*)signal->getDataPtrSend();
- req->backupId = ptr.p->backupId;
- req->backupPtr = ptr.i;
-
- /**
- * We use trigger Ids that are unique to BACKUP.
- * These don't interfere with other triggers (e.g. from DBDICT)
- * as there is a special case in DBTUP.
- *
- * Consequently, backups during online upgrade won't work
- */
- ptr.p->masterData.gsn = GSN_START_BACKUP_REQ;
- ptr.p->masterData.sendCounter = ptr.p->nodes;
- NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
- sendSignal(rg, GSN_START_BACKUP_REQ, signal,
- StartBackupReq::SignalLength, JBB);
-}
-
-void
-Backup::execSTART_BACKUP_REF(Signal* signal)
-{
- jamEntry();
-
- StartBackupRef* ref = (StartBackupRef*)signal->getDataPtr();
- const Uint32 ptrI = ref->backupPtr;
- //const Uint32 backupId = ref->backupId;
- const Uint32 nodeId = ref->nodeId;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->setErrorCode(ref->errorCode);
- startBackupReply(signal, ptr, nodeId);
-}
-
-void
-Backup::execSTART_BACKUP_CONF(Signal* signal)
-{
- jamEntry();
-
- StartBackupConf* conf = (StartBackupConf*)signal->getDataPtr();
- const Uint32 ptrI = conf->backupPtr;
- //const Uint32 backupId = conf->backupId;
- const Uint32 nodeId = refToNode(signal->senderBlockRef());
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- startBackupReply(signal, ptr, nodeId);
-}
-
-void
-Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
-{
-
- CRASH_INSERTION((10004));
-
- if (!haveAllSignals(ptr, GSN_START_BACKUP_REQ, nodeId)) {
- jam();
- return;
- }
-
- if (ERROR_INSERTED(10026))
- {
- ptr.p->errorCode = 326;
- }
-
- if(ptr.p->checkError()){
- jam();
- masterAbort(signal, ptr);
- return;
- }
-
- /**
- * Wait for GCP
- */
- ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
- ptr.p->masterData.waitGCP.startBackup = true;
-
- WaitGCPReq * waitGCPReq = (WaitGCPReq*)signal->getDataPtrSend();
- waitGCPReq->senderRef = reference();
- waitGCPReq->senderData = ptr.i;
- waitGCPReq->requestType = WaitGCPReq::CompleteForceStart;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength,JBB);
-}
-
-void
-Backup::execWAIT_GCP_REF(Signal* signal)
-{
- jamEntry();
-
- CRASH_INSERTION((10006));
-
- WaitGCPRef * ref = (WaitGCPRef*)signal->getDataPtr();
- const Uint32 ptrI = ref->senderData;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ndbrequire(ptr.p->masterRef == reference());
- ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
-
- WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = ptr.i;
- req->requestType = WaitGCPReq::CompleteForceStart;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength,JBB);
-}
-
-void
-Backup::execWAIT_GCP_CONF(Signal* signal){
- jamEntry();
-
- CRASH_INSERTION((10007));
-
- WaitGCPConf * conf = (WaitGCPConf*)signal->getDataPtr();
- const Uint32 ptrI = conf->senderData;
- const Uint32 gcp = conf->gcp;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ndbrequire(ptr.p->masterRef == reference());
- ndbrequire(ptr.p->masterData.gsn == GSN_WAIT_GCP_REQ);
-
- if(ptr.p->checkError()) {
- jam();
- masterAbort(signal, ptr);
- return;
- }//if
-
- if(ptr.p->masterData.waitGCP.startBackup) {
- jam();
- CRASH_INSERTION((10008));
- ptr.p->startGCP = gcp;
- ptr.p->masterData.sendCounter= 0;
- ptr.p->masterData.gsn = GSN_BACKUP_FRAGMENT_REQ;
- nextFragment(signal, ptr);
- return;
- } else {
- jam();
- if(gcp >= ptr.p->startGCP + 3)
- {
- CRASH_INSERTION((10009));
- ptr.p->stopGCP = gcp;
- /**
- * Backup is complete - begin cleanup
- * STOP_BACKUP_REQ is sent to participants.
- * They then drop the local triggers
- */
- sendStopBackup(signal, ptr);
- return;
- }//if
-
- /**
- * Make sure that we got entire stopGCP
- */
- WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = ptr.i;
- req->requestType = WaitGCPReq::CompleteForceStart;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength,JBB);
- return;
- }
-}
-
-/*****************************************************************************
- *
- * Master functionallity - Backup fragment
- *
- *****************************************************************************/
-void
-Backup::nextFragment(Signal* signal, BackupRecordPtr ptr)
-{
- jam();
-
- BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtrSend();
- req->backupPtr = ptr.i;
- req->backupId = ptr.p->backupId;
-
- NodeBitmask nodes = ptr.p->nodes;
- Uint32 idleNodes = nodes.count();
- Uint32 saveIdleNodes = idleNodes;
- ndbrequire(idleNodes > 0);
-
- TablePtr tabPtr;
- ptr.p->tables.first(tabPtr);
- for(; tabPtr.i != RNIL && idleNodes > 0; ptr.p->tables.next(tabPtr)) {
- jam();
- FragmentPtr fragPtr;
- Array<Fragment> & frags = tabPtr.p->fragments;
- const Uint32 fragCount = frags.getSize();
-
- for(Uint32 i = 0; i<fragCount && idleNodes > 0; i++) {
- jam();
- tabPtr.p->fragments.getPtr(fragPtr, i);
- const Uint32 nodeId = fragPtr.p->node;
- if(fragPtr.p->scanning != 0) {
- jam();
- ndbrequire(nodes.get(nodeId));
- nodes.clear(nodeId);
- idleNodes--;
- } else if(fragPtr.p->scanned == 0 && nodes.get(nodeId)){
- jam();
- fragPtr.p->scanning = 1;
- nodes.clear(nodeId);
- idleNodes--;
-
- req->tableId = tabPtr.p->tableId;
- req->fragmentNo = i;
- req->count = 0;
-
- ptr.p->masterData.sendCounter++;
- const BlockReference ref = numberToRef(BACKUP, nodeId);
- sendSignal(ref, GSN_BACKUP_FRAGMENT_REQ, signal,
- BackupFragmentReq::SignalLength, JBB);
- }//if
- }//for
- }//for
-
- if(idleNodes != saveIdleNodes){
- jam();
- return;
- }//if
-
- /**
- * Finished with all tables
- */
- {
- ptr.p->masterData.gsn = GSN_WAIT_GCP_REQ;
- ptr.p->masterData.waitGCP.startBackup = false;
-
- WaitGCPReq * req = (WaitGCPReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = ptr.i;
- req->requestType = WaitGCPReq::CompleteForceStart;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBB);
- }
-}
-
-void
-Backup::execBACKUP_FRAGMENT_CONF(Signal* signal)
-{
- jamEntry();
-
- CRASH_INSERTION((10010));
-
- BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtr();
- const Uint32 ptrI = conf->backupPtr;
- //const Uint32 backupId = conf->backupId;
- const Uint32 tableId = conf->tableId;
- const Uint32 fragmentNo = conf->fragmentNo;
- const Uint32 nodeId = refToNode(signal->senderBlockRef());
- const Uint64 noOfBytes =
- conf->noOfBytesLow + (((Uint64)conf->noOfBytesHigh) << 32);
- const Uint64 noOfRecords =
- conf->noOfRecordsLow + (((Uint64)conf->noOfRecordsHigh) << 32);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->noOfBytes += noOfBytes;
- ptr.p->noOfRecords += noOfRecords;
- ptr.p->masterData.sendCounter--;
-
- 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);
-
- fragPtr.p->scanned = 1;
- fragPtr.p->scanning = 0;
-
- if (ERROR_INSERTED(10028))
- {
- ptr.p->errorCode = 328;
- }
-
- if(ptr.p->checkError())
- {
- if(ptr.p->masterData.sendCounter.done())
- {
- jam();
- masterAbort(signal, ptr);
- return;
- }//if
- }
- 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);
- }
-}
-
-void
-Backup::execBACKUP_FRAGMENT_REF(Signal* signal)
-{
- jamEntry();
-
- CRASH_INSERTION((10011));
-
- BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtr();
- const Uint32 ptrI = ref->backupPtr;
- //const Uint32 backupId = ref->backupId;
- const Uint32 nodeId = ref->nodeId;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- TablePtr tabPtr;
- ptr.p->tables.first(tabPtr);
- for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
- jam();
- FragmentPtr fragPtr;
- Array<Fragment> & frags = tabPtr.p->fragments;
- const Uint32 fragCount = frags.getSize();
-
- for(Uint32 i = 0; i<fragCount; i++) {
- jam();
- tabPtr.p->fragments.getPtr(fragPtr, i);
- if(fragPtr.p->scanning != 0 && nodeId == fragPtr.p->node)
- {
- jam();
- ndbrequire(fragPtr.p->scanned == 0);
- fragPtr.p->scanned = 1;
- fragPtr.p->scanning = 0;
- goto done;
- }
- }
- }
- goto err;
-
-done:
- ptr.p->masterData.sendCounter--;
- ptr.p->setErrorCode(ref->errorCode);
-
- if(ptr.p->masterData.sendCounter.done())
- {
- jam();
- masterAbort(signal, ptr);
- return;
- }//if
-
-err:
- AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
- ord->backupId = ptr.p->backupId;
- ord->backupPtr = ptr.i;
- ord->requestType = AbortBackupOrd::LogBufferFull;
- ord->senderData= ptr.i;
- execABORT_BACKUP_ORD(signal);
-}
-
-void
-Backup::execBACKUP_FRAGMENT_COMPLETE_REP(Signal* signal)
-{
- jamEntry();
- BackupFragmentCompleteRep * rep =
- (BackupFragmentCompleteRep*)signal->getDataPtr();
-
- BackupRecordPtr ptr LINT_SET_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);
-}
-
-/*****************************************************************************
- *
- * Slave functionallity - Drop triggers
- *
- *****************************************************************************/
-
-void
-Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr)
-{
- TablePtr tabPtr;
- ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
-
- if (ptr.p->slaveData.dropTrig.tableId == RNIL) {
- jam();
- if(ptr.p->tables.count())
- ptr.p->tables.first(tabPtr);
- else
- {
- // Early abort, go to close files
- jam();
- closeFiles(signal, ptr);
- return;
- }
- } else {
- jam();
- ndbrequire(findTable(ptr, tabPtr, ptr.p->slaveData.dropTrig.tableId));
- ptr.p->tables.next(tabPtr);
- }//if
- if (tabPtr.i != RNIL) {
- jam();
- sendDropTrig(signal, ptr, tabPtr);
- } else {
- /**
- * Insert footers
- */
- //if backup error, we needn't insert footers
- if(ptr.p->checkError())
- {
- jam();
- closeFiles(signal, ptr);
- ptr.p->errorCode = 0;
- return;
- }
-
- {
- BackupFilePtr filePtr LINT_SET_PTR;
- ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
- Uint32 * dst;
- LINT_INIT(dst);
- ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1));
- * dst = 0;
- filePtr.p->operation.dataBuffer.updateWritePtr(1);
- }
-
- {
- BackupFilePtr filePtr LINT_SET_PTR;
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
-
- const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2;
-
- Uint32 * dst;
- LINT_INIT(dst);
- ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz));
-
- BackupFormat::CtlFile::GCPEntry * gcp =
- (BackupFormat::CtlFile::GCPEntry*)dst;
-
- gcp->SectionType = htonl(BackupFormat::GCP_ENTRY);
- gcp->SectionLength = htonl(gcpSz);
- gcp->StartGCP = htonl(ptr.p->startGCP);
- gcp->StopGCP = htonl(ptr.p->stopGCP - 1);
- filePtr.p->operation.dataBuffer.updateWritePtr(gcpSz);
-
- {
- TablePtr tabPtr;
- if (ptr.p->tables.first(tabPtr))
- {
- jam();
- 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);
- }
- else
- {
- jam();
- closeFiles(signal, ptr);
- }
- }
- }
- }
-}
-
-void
-Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr)
-{
- jam();
- DropTrigReq * req = (DropTrigReq *)signal->getDataPtrSend();
-
- ptr.p->slaveData.gsn = GSN_DROP_TRIG_REQ;
- ptr.p->slaveData.trigSendCounter = 0;
- req->setConnectionPtr(ptr.i);
- req->setUserRef(reference()); // Sending to myself
- req->setRequestType(DropTrigReq::RT_USER);
- req->setIndexId(RNIL);
- req->setTriggerInfo(0); // not used on DROP
- req->setTriggerType(TriggerType::SUBSCRIPTION);
- req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
-
- ptr.p->slaveData.dropTrig.tableId = tabPtr.p->tableId;
- req->setTableId(tabPtr.p->tableId);
-
- for (int i = 0; i < 3; i++) {
- Uint32 id = tabPtr.p->triggerIds[i];
- req->setTriggerId(id);
- req->setTriggerEvent(triggerEventValues[i]);
- sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- ptr.p->slaveData.trigSendCounter ++;
- }
-}
-
-void
-Backup::execDROP_TRIG_REF(Signal* signal)
-{
- jamEntry();
-
- DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr();
- const Uint32 ptrI = ref->getConnectionPtr();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- if(ref->getConf()->getTriggerId() != ~(Uint32) 0)
- {
- ndbout << "ERROR DROPPING TRIGGER: " << ref->getConf()->getTriggerId();
- ndbout << " Err: " << (Uint32)ref->getErrorCode() << endl << endl;
- }
-
- dropTrigReply(signal, ptr);
-}
-
-void
-Backup::execDROP_TRIG_CONF(Signal* signal)
-{
- jamEntry();
-
- DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr();
- const Uint32 ptrI = conf->getConnectionPtr();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- dropTrigReply(signal, ptr);
-}
-
-void
-Backup::dropTrigReply(Signal* signal, BackupRecordPtr ptr)
-{
- CRASH_INSERTION((10012));
-
- ndbrequire(ptr.p->slaveData.gsn == GSN_DROP_TRIG_REQ);
- ndbrequire(ptr.p->slaveData.trigSendCounter.done() == false);
-
- // move from .masterData to .slaveData
- ptr.p->slaveData.trigSendCounter--;
- if(ptr.p->slaveData.trigSendCounter.done() == false){
- jam();
- return;
- }//if
-
- sendDropTrig(signal, ptr); // recursive next
-}
-
-/*****************************************************************************
- *
- * Master functionallity - Stop backup
- *
- *****************************************************************************/
-void
-Backup::execSTOP_BACKUP_REF(Signal* signal)
-{
- jamEntry();
-
- StopBackupRef* ref = (StopBackupRef*)signal->getDataPtr();
- const Uint32 ptrI = ref->backupPtr;
- //const Uint32 backupId = ref->backupId;
- const Uint32 nodeId = ref->nodeId;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->setErrorCode(ref->errorCode);
- stopBackupReply(signal, ptr, nodeId);
-}
-
-void
-Backup::sendStopBackup(Signal* signal, BackupRecordPtr ptr)
-{
- jam();
-
- StopBackupReq* stop = (StopBackupReq*)signal->getDataPtrSend();
- stop->backupPtr = ptr.i;
- stop->backupId = ptr.p->backupId;
- stop->startGCP = ptr.p->startGCP;
- stop->stopGCP = ptr.p->stopGCP;
-
- ptr.p->masterData.gsn = GSN_STOP_BACKUP_REQ;
- ptr.p->masterData.sendCounter = ptr.p->nodes;
- NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
- sendSignal(rg, GSN_STOP_BACKUP_REQ, signal,
- StopBackupReq::SignalLength, JBB);
-}
-
-void
-Backup::execSTOP_BACKUP_CONF(Signal* signal)
-{
- jamEntry();
-
- StopBackupConf* conf = (StopBackupConf*)signal->getDataPtr();
- const Uint32 ptrI = conf->backupPtr;
- //const Uint32 backupId = conf->backupId;
- const Uint32 nodeId = refToNode(signal->senderBlockRef());
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->noOfLogBytes += conf->noOfLogBytes;
- ptr.p->noOfLogRecords += conf->noOfLogRecords;
-
- stopBackupReply(signal, ptr, nodeId);
-}
-
-void
-Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
-{
- CRASH_INSERTION((10013));
-
- if (!haveAllSignals(ptr, GSN_STOP_BACKUP_REQ, nodeId)) {
- jam();
- return;
- }
-
- sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupComplete);
-
- if(!ptr.p->checkError())
- {
- if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
- {
- BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
- rep->backupId = ptr.p->backupId;
- rep->senderData = ptr.p->clientData;
- rep->startGCP = ptr.p->startGCP;
- rep->stopGCP = ptr.p->stopGCP;
- 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;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
- BackupCompleteRep::SignalLength, JBB);
- }
-
- 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] = (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);
- 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
- {
- masterAbort(signal, ptr);
- }
-}
-
-/*****************************************************************************
- *
- * Master functionallity - Abort backup
- *
- *****************************************************************************/
-void
-Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
-{
- jam();
-#ifdef DEBUG_ABORT
- ndbout_c("************ masterAbort");
-#endif
-
- ndbassert(ptr.p->masterRef == reference());
-
- if(ptr.p->masterData.errorCode != 0)
- {
- jam();
- return;
- }
-
- if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
- {
- BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
- rep->backupId = ptr.p->backupId;
- rep->senderData = ptr.p->clientData;
- rep->reason = ptr.p->errorCode;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
- BackupAbortRep::SignalLength, JBB);
- }
- signal->theData[0] = NDB_LE_BackupAborted;
- signal->theData[1] = ptr.p->clientRef;
- signal->theData[2] = ptr.p->backupId;
- signal->theData[3] = ptr.p->errorCode;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
-
- ndbrequire(ptr.p->errorCode);
- ptr.p->masterData.errorCode = ptr.p->errorCode;
-
- AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
- ord->backupId = ptr.p->backupId;
- ord->backupPtr = ptr.i;
- ord->senderData= ptr.i;
- NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
-
- switch(ptr.p->masterData.gsn){
- case GSN_DEFINE_BACKUP_REQ:
- ord->requestType = AbortBackupOrd::BackupFailure;
- sendSignal(rg, GSN_ABORT_BACKUP_ORD, signal,
- AbortBackupOrd::SignalLength, JBB);
- return;
- case GSN_CREATE_TRIG_REQ:
- case GSN_START_BACKUP_REQ:
- case GSN_ALTER_TRIG_REQ:
- case GSN_WAIT_GCP_REQ:
- case GSN_BACKUP_FRAGMENT_REQ:
- jam();
- ptr.p->stopGCP= ptr.p->startGCP + 1;
- sendStopBackup(signal, ptr); // dropping due to error
- return;
- case GSN_UTIL_SEQUENCE_REQ:
- case GSN_UTIL_LOCK_REQ:
- ndbrequire(false);
- return;
- case GSN_DROP_TRIG_REQ:
- case GSN_STOP_BACKUP_REQ:
- return;
- }
-}
-
-void
-Backup::abort_scan(Signal * signal, BackupRecordPtr ptr)
-{
- AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
- ord->backupId = ptr.p->backupId;
- ord->backupPtr = ptr.i;
- ord->senderData= ptr.i;
- ord->requestType = AbortBackupOrd::AbortScan;
-
- TablePtr tabPtr;
- ptr.p->tables.first(tabPtr);
- for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
- jam();
- FragmentPtr fragPtr;
- Array<Fragment> & frags = tabPtr.p->fragments;
- const Uint32 fragCount = frags.getSize();
-
- for(Uint32 i = 0; i<fragCount; i++) {
- jam();
- tabPtr.p->fragments.getPtr(fragPtr, i);
- const Uint32 nodeId = fragPtr.p->node;
- if(fragPtr.p->scanning != 0 && ptr.p->nodes.get(nodeId)) {
- jam();
-
- const BlockReference ref = numberToRef(BACKUP, nodeId);
- sendSignal(ref, GSN_ABORT_BACKUP_ORD, signal,
- AbortBackupOrd::SignalLength, JBB);
-
- }
- }
- }
-}
-
-/*****************************************************************************
- *
- * Slave functionallity: Define Backup
- *
- *****************************************************************************/
-void
-Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode)
-{
- jam();
- ptr.p->setErrorCode(errCode);
- if(ptr.p->is_lcp())
- {
- jam();
- if (ptr.p->ctlFilePtr == RNIL) {
- ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF;
- ndbrequire(ptr.p->errorCode != 0);
- DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
- ref->backupId = ptr.p->backupId;
- ref->backupPtr = ptr.i;
- ref->errorCode = ptr.p->errorCode;
- ref->nodeId = getOwnNodeId();
- sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal,
- DefineBackupRef::SignalLength, JBB);
- return;
- }
-
- BackupFilePtr filePtr LINT_SET_PTR;
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
- if (filePtr.p->m_flags & BackupFile::BF_LCP_META)
- {
- jam();
- ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_FILE_THREAD));
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_LCP_META;
- if (filePtr.p->m_flags & BackupFile::BF_OPEN)
- {
- closeFile(signal, ptr, filePtr);
- return;
- }
- }
-
- ndbrequire(filePtr.p->m_flags == 0);
-
- TablePtr tabPtr;
- FragmentPtr fragPtr;
-
- ndbrequire(ptr.p->tables.first(tabPtr));
- tabPtr.p->fragments.getPtr(fragPtr, 0);
-
- LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtrSend();
- ref->senderData = ptr.p->clientData;
- ref->senderRef = reference();
- ref->tableId = tabPtr.p->tableId;
- ref->fragmentId = fragPtr.p->fragmentId;
- ref->errorCode = errCode;
- sendSignal(ptr.p->masterRef, GSN_LCP_PREPARE_REF,
- signal, LcpPrepareRef::SignalLength, JBB);
- return;
- }
-
- ptr.p->m_gsn = GSN_DEFINE_BACKUP_REF;
- ndbrequire(ptr.p->errorCode != 0);
-
- DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
- ref->backupId = ptr.p->backupId;
- ref->backupPtr = ptr.i;
- ref->errorCode = ptr.p->errorCode;
- ref->nodeId = getOwnNodeId();
- sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_REF, signal,
- DefineBackupRef::SignalLength, JBB);
-}
-
-void
-Backup::execDEFINE_BACKUP_REQ(Signal* signal)
-{
- jamEntry();
-
- DefineBackupReq* req = (DefineBackupReq*)signal->getDataPtr();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- const Uint32 ptrI = req->backupPtr;
- const Uint32 backupId = req->backupId;
- const BlockReference senderRef = req->senderRef;
-
- if(senderRef == reference()){
- /**
- * Signal sent from myself -> record already seized
- */
- jam();
- c_backupPool.getPtr(ptr, ptrI);
- } else { // from other node
- jam();
-#ifdef DEBUG_ABORT
- dumpUsedResources();
-#endif
- if(!c_backups.seizeId(ptr, ptrI)) {
- jam();
- ndbrequire(false); // If master has succeeded slave should succed
- }//if
- }//if
-
- CRASH_INSERTION((10014));
-
- ptr.p->m_gsn = GSN_DEFINE_BACKUP_REQ;
- ptr.p->slaveState.forceState(INITIAL);
- ptr.p->slaveState.setState(DEFINING);
- ptr.p->slaveData.dropTrig.tableId = RNIL;
- ptr.p->errorCode = 0;
- ptr.p->clientRef = req->clientRef;
- ptr.p->clientData = req->clientData;
- if(senderRef == reference())
- ptr.p->flags = req->flags;
- else
- ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
- * as non master should never
- * reply
- */
- ptr.p->masterRef = senderRef;
- ptr.p->nodes = req->nodes;
- ptr.p->backupId = backupId;
- ptr.p->backupKey[0] = req->backupKey[0];
- ptr.p->backupKey[1] = req->backupKey[1];
- ptr.p->backupDataLen = req->backupDataLen;
- ptr.p->masterData.errorCode = 0;
- ptr.p->noOfBytes = 0;
- ptr.p->noOfRecords = 0;
- ptr.p->noOfLogBytes = 0;
- ptr.p->noOfLogRecords = 0;
- ptr.p->currGCP = 0;
- ptr.p->startGCP = 0;
- ptr.p->stopGCP = 0;
-
- /**
- * Allocate files
- */
- BackupFilePtr files[3];
- Uint32 noOfPages[] = {
- NO_OF_PAGES_META_FILE,
- 2, // 32k
- 0 // 3M
- };
- const Uint32 maxInsert[] = {
- MAX_WORDS_META_FILE,
- 4096, // 16k
- 16*3000, // Max 16 tuples
- };
- Uint32 minWrite[] = {
- 8192,
- 8192,
- 32768
- };
- Uint32 maxWrite[] = {
- 8192,
- 8192,
- 32768
- };
-
- minWrite[1] = c_defaults.m_minWriteSize;
- maxWrite[1] = c_defaults.m_maxWriteSize;
- noOfPages[1] = (c_defaults.m_logBufferSize + sizeof(Page32) - 1) /
- sizeof(Page32);
- minWrite[2] = c_defaults.m_minWriteSize;
- maxWrite[2] = c_defaults.m_maxWriteSize;
- noOfPages[2] = (c_defaults.m_dataBufferSize + sizeof(Page32) - 1) /
- sizeof(Page32);
-
- if (ptr.p->is_lcp())
- {
- noOfPages[2] = (c_defaults.m_lcp_buffer_size + sizeof(Page32) - 1) /
- sizeof(Page32);
- }
-
- ptr.p->ctlFilePtr = ptr.p->logFilePtr = ptr.p->dataFilePtr = RNIL;
-
- for(Uint32 i = 0; i<3; i++) {
- jam();
- if(ptr.p->is_lcp() && i != 2)
- {
- files[i].i = RNIL;
- continue;
- }
- if(!ptr.p->files.seize(files[i])) {
- jam();
- defineBackupRef(signal, ptr,
- DefineBackupRef::FailedToAllocateFileRecord);
- return;
- }//if
-
- files[i].p->tableId = RNIL;
- files[i].p->backupPtr = ptr.i;
- files[i].p->filePointer = RNIL;
- files[i].p->m_flags = 0;
- files[i].p->errorCode = 0;
-
- if(ERROR_INSERTED(10035) || files[i].p->pages.seize(noOfPages[i]) == false)
- {
- jam();
- DEBUG_OUT("Failed to seize " << noOfPages[i] << " pages");
- defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateBuffers);
- return;
- }//if
- Page32Ptr pagePtr;
- files[i].p->pages.getPtr(pagePtr, 0);
-
- const char * msg = files[i].p->
- operation.dataBuffer.setup((Uint32*)pagePtr.p,
- noOfPages[i] * (sizeof(Page32) >> 2),
- 128,
- minWrite[i] >> 2,
- maxWrite[i] >> 2,
- maxInsert[i]);
- if(msg != 0) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::FailedToSetupFsBuffers);
- return;
- }//if
-
- switch(i){
- case 0:
- files[i].p->fileType = BackupFormat::CTL_FILE;
- ptr.p->ctlFilePtr = files[i].i;
- break;
- case 1:
- files[i].p->fileType = BackupFormat::LOG_FILE;
- ptr.p->logFilePtr = files[i].i;
- break;
- case 2:
- files[i].p->fileType = BackupFormat::DATA_FILE;
- ptr.p->dataFilePtr = files[i].i;
- }
- }//for
-
- if (!verifyNodesAlive(ptr, ptr.p->nodes)) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::Undefined);
- return;
- }//if
- if (ERROR_INSERTED(10027)) {
- jam();
- defineBackupRef(signal, ptr, 327);
- return;
- }//if
-
- if(ptr.p->backupDataLen == 0) {
- jam();
- backupAllData(signal, ptr);
- return;
- }//if
-
- if(ptr.p->is_lcp())
- {
- jam();
- getFragmentInfoDone(signal, ptr);
- return;
- }
-
- /**
- * Not implemented
- */
- ndbrequire(0);
-}
-
-void
-Backup::backupAllData(Signal* signal, BackupRecordPtr ptr)
-{
- /**
- * Get all tables from dict
- */
- ListTablesReq * req = (ListTablesReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = ptr.i;
- req->requestData = 0;
- sendSignal(DBDICT_REF, GSN_LIST_TABLES_REQ, signal,
- ListTablesReq::SignalLength, JBB);
-}
-
-void
-Backup::execLIST_TABLES_CONF(Signal* signal)
-{
- jamEntry();
-
- ListTablesConf* conf = (ListTablesConf*)signal->getDataPtr();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, conf->senderData);
-
- const Uint32 len = signal->length() - ListTablesConf::HeaderLength;
- for(unsigned int i = 0; i<len; i++) {
- jam();
- Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]);
- Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]);
- Uint32 state= ListTablesConf::getTableState(conf->tableData[i]);
-
- if (! (DictTabInfo::isTable(tableType) ||
- DictTabInfo::isIndex(tableType) ||
- DictTabInfo::isFilegroup(tableType) ||
- DictTabInfo::isFile(tableType)))
- {
- jam();
- continue;
- }
-
- if (state != DictTabInfo::StateOnline)
- {
- jam();
- continue;
- }
-
- TablePtr tabPtr;
- ptr.p->tables.seize(tabPtr);
- if(tabPtr.i == RNIL) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::FailedToAllocateTables);
- return;
- }//if
- tabPtr.p->tableId = tableId;
- tabPtr.p->tableType = tableType;
- }//for
-
- if(len == ListTablesConf::DataLength) {
- jam();
- /**
- * Not finished...
- */
- return;
- }//if
-
- /**
- * All tables fetched
- */
- openFiles(signal, ptr);
-}
-
-void
-Backup::openFiles(Signal* signal, BackupRecordPtr ptr)
-{
- jam();
-
- BackupFilePtr filePtr LINT_SET_PTR;
-
- FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
- req->userReference = reference();
- req->fileFlags =
- FsOpenReq::OM_WRITEONLY |
- FsOpenReq::OM_TRUNCATE |
- FsOpenReq::OM_CREATE |
- FsOpenReq::OM_APPEND |
- FsOpenReq::OM_AUTOSYNC;
- FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
- req->auto_sync_size = c_defaults.m_disk_synch_size;
- /**
- * Ctl file
- */
- c_backupFilePool.getPtr(filePtr, ptr.p->ctlFilePtr);
- filePtr.p->m_flags |= BackupFile::BF_OPENING;
-
- req->userPointer = filePtr.i;
- FsOpenReq::setVersion(req->fileNumber, 2);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
- FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
- FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-
- /**
- * Log file
- */
- c_backupFilePool.getPtr(filePtr, ptr.p->logFilePtr);
- filePtr.p->m_flags |= BackupFile::BF_OPENING;
-
- req->userPointer = filePtr.i;
- FsOpenReq::setVersion(req->fileNumber, 2);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_LOG);
- FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
- FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-
- /**
- * Data file
- */
- c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
- filePtr.p->m_flags |= BackupFile::BF_OPENING;
-
- if (c_defaults.m_o_direct)
- req->fileFlags |= FsOpenReq::OM_DIRECT;
- req->userPointer = filePtr.i;
- FsOpenReq::setVersion(req->fileNumber, 2);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
- FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
- FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
- FsOpenReq::v2_setCount(req->fileNumber, 0);
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-}
-
-void
-Backup::execFSOPENREF(Signal* signal)
-{
- jamEntry();
-
- FsRef * ref = (FsRef *)signal->getDataPtr();
-
- const Uint32 userPtr = ref->userPointer;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, userPtr);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
- ptr.p->setErrorCode(ref->errorCode);
- openFilesReply(signal, ptr, filePtr);
-}
-
-void
-Backup::execFSOPENCONF(Signal* signal)
-{
- jamEntry();
-
- FsConf * conf = (FsConf *)signal->getDataPtr();
-
- const Uint32 userPtr = conf->userPointer;
- const Uint32 filePointer = conf->filePointer;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, userPtr);
- filePtr.p->filePointer = filePointer;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
-
- ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_OPEN));
- filePtr.p->m_flags |= BackupFile::BF_OPEN;
- openFilesReply(signal, ptr, filePtr);
-}
-
-void
-Backup::openFilesReply(Signal* signal,
- BackupRecordPtr ptr, BackupFilePtr filePtr)
-{
- jam();
-
- /**
- * Mark files as "opened"
- */
- ndbrequire(filePtr.p->m_flags & BackupFile::BF_OPENING);
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_OPENING;
- filePtr.p->m_flags |= BackupFile::BF_OPEN;
- /**
- * Check if all files have recived open_reply
- */
- for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr))
- {
- jam();
- if(filePtr.p->m_flags & BackupFile::BF_OPENING) {
- jam();
- return;
- }//if
- }//for
-
- /**
- * Did open succeed for all files
- */
- if(ptr.p->checkError()) {
- jam();
- defineBackupRef(signal, ptr);
- return;
- }//if
-
- if(!ptr.p->is_lcp())
- {
- /**
- * Insert file headers
- */
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
- if(!insertFileHeader(BackupFormat::CTL_FILE, ptr.p, filePtr.p)) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
- return;
- }//if
-
- ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
- if(!insertFileHeader(BackupFormat::LOG_FILE, ptr.p, filePtr.p)) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
- return;
- }//if
-
- ptr.p->files.getPtr(filePtr, ptr.p->dataFilePtr);
- if(!insertFileHeader(BackupFormat::DATA_FILE, ptr.p, filePtr.p)) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
- return;
- }//if
- }
- else
- {
- ptr.p->files.getPtr(filePtr, ptr.p->dataFilePtr);
- if(!insertFileHeader(BackupFormat::LCP_FILE, ptr.p, filePtr.p)) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
- return;
- }//if
-
- ptr.p->ctlFilePtr = ptr.p->dataFilePtr;
- }
-
- /**
- * Start CTL file thread
- */
- if (!ptr.p->is_lcp())
- {
- jam();
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
- filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
-
- signal->theData[0] = BackupContinueB::START_FILE_THREAD;
- signal->theData[1] = filePtr.i;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
- }
- else
- {
- jam();
- filePtr.p->m_flags |= BackupFile::BF_LCP_META;
- }
-
- /**
- * Insert table list in ctl file
- */
- FsBuffer & buf = filePtr.p->operation.dataBuffer;
-
- const Uint32 sz =
- (sizeof(BackupFormat::CtlFile::TableList) >> 2) +
- ptr.p->tables.count() - 1;
-
- Uint32 * dst;
- ndbrequire(sz < buf.getMaxWrite());
- if(!buf.getWritePtr(&dst, sz)) {
- jam();
- defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertTableList);
- return;
- }//if
-
- BackupFormat::CtlFile::TableList* tl =
- (BackupFormat::CtlFile::TableList*)dst;
- tl->SectionType = htonl(BackupFormat::TABLE_LIST);
- tl->SectionLength = htonl(sz);
-
- TablePtr tabPtr;
- Uint32 count = 0;
- for(ptr.p->tables.first(tabPtr);
- tabPtr.i != RNIL;
- ptr.p->tables.next(tabPtr)){
- jam();
- tl->TableIds[count] = htonl(tabPtr.p->tableId);
- count++;
- }//for
-
- buf.updateWritePtr(sz);
-
- /**
- * Start getting table definition data
- */
- ndbrequire(ptr.p->tables.first(tabPtr));
-
- signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
- signal->theData[1] = ptr.i;
- signal->theData[2] = tabPtr.i;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
- return;
-}
-
-bool
-Backup::insertFileHeader(BackupFormat::FileType ft,
- BackupRecord * ptrP,
- BackupFile * filePtrP){
- FsBuffer & buf = filePtrP->operation.dataBuffer;
-
- const Uint32 sz = sizeof(BackupFormat::FileHeader) >> 2;
-
- Uint32 * dst;
- ndbrequire(sz < buf.getMaxWrite());
- if(!buf.getWritePtr(&dst, sz)) {
- jam();
- return false;
- }//if
-
- BackupFormat::FileHeader* header = (BackupFormat::FileHeader*)dst;
- ndbrequire(sizeof(header->Magic) == sizeof(BACKUP_MAGIC));
- memcpy(header->Magic, BACKUP_MAGIC, sizeof(BACKUP_MAGIC));
- header->NdbVersion = htonl(NDB_VERSION);
- header->SectionType = htonl(BackupFormat::FILE_HEADER);
- header->SectionLength = htonl(sz - 3);
- header->FileType = htonl(ft);
- header->BackupId = htonl(ptrP->backupId);
- header->BackupKey_0 = htonl(ptrP->backupKey[0]);
- header->BackupKey_1 = htonl(ptrP->backupKey[1]);
- header->ByteOrder = 0x12345678;
-
- buf.updateWritePtr(sz);
- return true;
-}
-
-void
-Backup::execGET_TABINFOREF(Signal* signal)
-{
- GetTabInfoRef * ref = (GetTabInfoRef*)signal->getDataPtr();
-
- const Uint32 senderData = ref->senderData;
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, senderData);
-
- BackupFilePtr filePtr LINT_SET_PTR;
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
-
- defineBackupRef(signal, ptr, ref->errorCode);
-}
-
-void
-Backup::execGET_TABINFO_CONF(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal)) {
- jam();
- return;
- }//if
-
- GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
- //const Uint32 senderRef = info->senderRef;
- const Uint32 len = conf->totalLen;
- const Uint32 senderData = conf->senderData;
- const Uint32 tableType = conf->tableType;
- const Uint32 tableId = conf->tableId;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, senderData);
-
- SegmentedSectionPtr dictTabInfoPtr;
- signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
- ndbrequire(dictTabInfoPtr.sz == len);
-
- TablePtr tabPtr ;
- ndbrequire(findTable(ptr, tabPtr, tableId));
-
- BackupFilePtr filePtr LINT_SET_PTR;
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
- FsBuffer & buf = filePtr.p->operation.dataBuffer;
- Uint32* dst = 0;
- { // Write into ctl file
- Uint32 dstLen = len + 3;
- if(!buf.getWritePtr(&dst, dstLen)) {
- jam();
- ndbrequire(false);
- ptr.p->setErrorCode(DefineBackupRef::FailedAllocateTableMem);
- releaseSections(signal);
- defineBackupRef(signal, ptr);
- return;
- }//if
- if(dst != 0) {
- jam();
-
- BackupFormat::CtlFile::TableDescription * desc =
- (BackupFormat::CtlFile::TableDescription*)dst;
- desc->SectionType = htonl(BackupFormat::TABLE_DESCRIPTION);
- desc->SectionLength = htonl(len + 3);
- desc->TableType = htonl(tableType);
- dst += 3;
-
- copy(dst, dictTabInfoPtr);
- buf.updateWritePtr(dstLen);
- }//if
- }
-
- releaseSections(signal);
-
- if(ptr.p->checkError()) {
- jam();
- defineBackupRef(signal, ptr);
- return;
- }//if
-
- if (!DictTabInfo::isTable(tabPtr.p->tableType))
- {
- jam();
-
- TablePtr tmp = tabPtr;
- ptr.p->tables.next(tabPtr);
- ptr.p->tables.release(tmp);
- goto next;
- }
-
- if (!parseTableDescription(signal, ptr, tabPtr, dst, len))
- {
- jam();
- defineBackupRef(signal, ptr);
- return;
- }
-
- if(!ptr.p->is_lcp())
- {
- jam();
- signal->theData[0] = tabPtr.p->tableId;
- signal->theData[1] = 1; // lock
- EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
- }
-
- ptr.p->tables.next(tabPtr);
-
-next:
- if(tabPtr.i == RNIL)
- {
- /**
- * Done with all tables...
- */
- jam();
-
- if(ptr.p->is_lcp())
- {
- lcp_open_file_done(signal, ptr);
- return;
- }
-
- ndbrequire(ptr.p->tables.first(tabPtr));
- DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
- req->m_connectionData = RNIL;
- req->m_tableRef = tabPtr.p->tableId;
- req->m_senderData = ptr.i;
- sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
- DihFragCountReq::SignalLength, JBB);
- return;
- }//if
-
- /**
- * Fetch next table...
- */
- signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
- signal->theData[1] = ptr.i;
- signal->theData[2] = tabPtr.i;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
- return;
-}
-
-bool
-Backup::parseTableDescription(Signal* signal,
- BackupRecordPtr ptr,
- TablePtr tabPtr,
- const Uint32 * tabdescptr,
- Uint32 len)
-{
- SimplePropertiesLinearReader it(tabdescptr, len);
-
- it.first();
-
- DictTabInfo::Table tmpTab; tmpTab.init();
- SimpleProperties::UnpackStatus stat;
- stat = SimpleProperties::unpack(it, &tmpTab,
- DictTabInfo::TableMapping,
- DictTabInfo::TableMappingSize,
- true, true);
- ndbrequire(stat == SimpleProperties::Break);
-
- bool lcp = ptr.p->is_lcp();
-
- ndbrequire(tabPtr.p->tableId == tmpTab.TableId);
- ndbrequire(lcp || (tabPtr.p->tableType == tmpTab.TableType));
-
- /**
- * LCP should not save disk attributes but only mem attributes
- */
-
- /**
- * Initialize table object
- */
- tabPtr.p->noOfRecords = 0;
- tabPtr.p->schemaVersion = tmpTab.TableVersion;
- tabPtr.p->noOfAttributes = tmpTab.NoOfAttributes;
- tabPtr.p->noOfNull = 0;
- tabPtr.p->noOfVariable = 0; // Computed while iterating over attribs
- tabPtr.p->sz_FixedAttributes = 0; // Computed while iterating over attribs
- tabPtr.p->triggerIds[0] = ILLEGAL_TRIGGER_ID;
- tabPtr.p->triggerIds[1] = ILLEGAL_TRIGGER_ID;
- tabPtr.p->triggerIds[2] = ILLEGAL_TRIGGER_ID;
- tabPtr.p->triggerAllocated[0] = false;
- tabPtr.p->triggerAllocated[1] = false;
- tabPtr.p->triggerAllocated[2] = false;
-
- Uint32 disk = 0;
- const Uint32 count = tabPtr.p->noOfAttributes;
- for(Uint32 i = 0; i<count; i++) {
- jam();
- DictTabInfo::Attribute tmp; tmp.init();
- stat = SimpleProperties::unpack(it, &tmp,
- DictTabInfo::AttributeMapping,
- DictTabInfo::AttributeMappingSize,
- true, true);
-
- ndbrequire(stat == SimpleProperties::Break);
- it.next(); // Move Past EndOfAttribute
-
- const Uint32 arr = tmp.AttributeArraySize;
- const Uint32 sz = 1 << tmp.AttributeSize;
- const Uint32 sz32 = (sz * arr + 31) >> 5;
-
- if(lcp && tmp.AttributeStorageType == NDB_STORAGETYPE_DISK)
- {
- disk++;
- continue;
- }
-
- AttributePtr attrPtr;
- if(!tabPtr.p->attributes.seize(attrPtr))
- {
- jam();
- ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord);
- return false;
- }
-
- attrPtr.p->data.m_flags = 0;
- attrPtr.p->data.attrId = tmp.AttributeId;
-
- attrPtr.p->data.m_flags |=
- (tmp.AttributeNullableFlag ? Attribute::COL_NULLABLE : 0);
- attrPtr.p->data.m_flags |= (tmp.AttributeArrayType == NDB_ARRAYTYPE_FIXED)?
- Attribute::COL_FIXED : 0;
- attrPtr.p->data.sz32 = sz32;
-
- /**
- * 1) Fixed non-nullable
- * 2) Other
- */
- if(attrPtr.p->data.m_flags & Attribute::COL_FIXED &&
- !(attrPtr.p->data.m_flags & Attribute::COL_NULLABLE)) {
- jam();
- attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
- tabPtr.p->sz_FixedAttributes += sz32;
- } else {
- attrPtr.p->data.offset = ~0;
- tabPtr.p->noOfVariable++;
- }
- }//for
-
-
- if(lcp)
- {
- if (disk)
- {
- /**
- * Remove all disk attributes
- */
- tabPtr.p->noOfAttributes -= disk;
-
- {
- AttributePtr attrPtr;
- ndbrequire(tabPtr.p->attributes.seize(attrPtr));
-
- Uint32 sz32 = 2;
- attrPtr.p->data.attrId = AttributeHeader::DISK_REF;
- attrPtr.p->data.m_flags = Attribute::COL_FIXED;
- attrPtr.p->data.sz32 = 2;
-
- attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
- tabPtr.p->sz_FixedAttributes += sz32;
- tabPtr.p->noOfAttributes ++;
- }
- }
-
- {
- AttributePtr attrPtr;
- ndbrequire(tabPtr.p->attributes.seize(attrPtr));
-
- Uint32 sz32 = 2;
- attrPtr.p->data.attrId = AttributeHeader::ROWID;
- attrPtr.p->data.m_flags = Attribute::COL_FIXED;
- attrPtr.p->data.sz32 = 2;
-
- attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
- tabPtr.p->sz_FixedAttributes += sz32;
- tabPtr.p->noOfAttributes ++;
- }
-
- if (tmpTab.RowGCIFlag)
- {
- AttributePtr attrPtr;
- ndbrequire(tabPtr.p->attributes.seize(attrPtr));
-
- Uint32 sz32 = 2;
- attrPtr.p->data.attrId = AttributeHeader::ROW_GCI;
- attrPtr.p->data.m_flags = Attribute::COL_FIXED;
- attrPtr.p->data.sz32 = 2;
-
- attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
- tabPtr.p->sz_FixedAttributes += sz32;
- tabPtr.p->noOfAttributes ++;
- }
- }
- return true;
-}
-
-void
-Backup::execDI_FCOUNTCONF(Signal* signal)
-{
- jamEntry();
- DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
- const Uint32 userPtr = conf->m_connectionData;
- const Uint32 fragCount = conf->m_fragmentCount;
- const Uint32 tableId = conf->m_tableRef;
- const Uint32 senderData = conf->m_senderData;
-
- ndbrequire(userPtr == RNIL && signal->length() == 5);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, senderData);
-
- TablePtr tabPtr;
- ndbrequire(findTable(ptr, tabPtr, tableId));
-
- ndbrequire(tabPtr.p->fragments.seize(fragCount) != false);
- for(Uint32 i = 0; i<fragCount; i++) {
- jam();
- FragmentPtr fragPtr;
- tabPtr.p->fragments.getPtr(fragPtr, i);
- fragPtr.p->scanned = 0;
- fragPtr.p->scanning = 0;
- fragPtr.p->tableId = tableId;
- fragPtr.p->fragmentId = i;
- fragPtr.p->node = 0;
- }//for
-
- /**
- * Next table
- */
- if(ptr.p->tables.next(tabPtr)) {
- jam();
- DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
- req->m_connectionData = RNIL;
- req->m_tableRef = tabPtr.p->tableId;
- req->m_senderData = ptr.i;
- sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
- DihFragCountReq::SignalLength, JBB);
- return;
- }//if
-
- ptr.p->tables.first(tabPtr);
- getFragmentInfo(signal, ptr, tabPtr, 0);
-}
-
-void
-Backup::getFragmentInfo(Signal* signal,
- BackupRecordPtr ptr, TablePtr tabPtr, Uint32 fragNo)
-{
- jam();
-
- for(; tabPtr.i != RNIL; ptr.p->tables.next(tabPtr)) {
- jam();
- const Uint32 fragCount = tabPtr.p->fragments.getSize();
- for(; fragNo < fragCount; fragNo ++) {
- jam();
- FragmentPtr fragPtr;
- tabPtr.p->fragments.getPtr(fragPtr, fragNo);
-
- if(fragPtr.p->scanned == 0 && fragPtr.p->scanning == 0) {
- jam();
- signal->theData[0] = RNIL;
- signal->theData[1] = ptr.i;
- signal->theData[2] = tabPtr.p->tableId;
- signal->theData[3] = fragNo;
- sendSignal(DBDIH_REF, GSN_DIGETPRIMREQ, signal, 4, JBB);
- return;
- }//if
- }//for
- fragNo = 0;
- }//for
-
- getFragmentInfoDone(signal, ptr);
-}
-
-void
-Backup::execDIGETPRIMCONF(Signal* signal)
-{
- jamEntry();
-
- const Uint32 userPtr = signal->theData[0];
- const Uint32 senderData = signal->theData[1];
- const Uint32 nodeCount = signal->theData[6];
- const Uint32 tableId = signal->theData[7];
- const Uint32 fragNo = signal->theData[8];
-
- ndbrequire(userPtr == RNIL && signal->length() == 9);
- ndbrequire(nodeCount > 0 && nodeCount <= MAX_REPLICAS);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, senderData);
-
- TablePtr tabPtr;
- ndbrequire(findTable(ptr, tabPtr, tableId));
-
- FragmentPtr fragPtr;
- tabPtr.p->fragments.getPtr(fragPtr, fragNo);
-
- fragPtr.p->node = signal->theData[2];
-
- getFragmentInfo(signal, ptr, tabPtr, fragNo + 1);
-}
-
-void
-Backup::getFragmentInfoDone(Signal* signal, BackupRecordPtr ptr)
-{
- ptr.p->m_gsn = GSN_DEFINE_BACKUP_CONF;
- ptr.p->slaveState.setState(DEFINED);
- DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtr();
- conf->backupPtr = ptr.i;
- conf->backupId = ptr.p->backupId;
- sendSignal(ptr.p->masterRef, GSN_DEFINE_BACKUP_CONF, signal,
- DefineBackupConf::SignalLength, JBB);
-}
-
-
-/*****************************************************************************
- *
- * Slave functionallity: Start backup
- *
- *****************************************************************************/
-void
-Backup::execSTART_BACKUP_REQ(Signal* signal)
-{
- jamEntry();
-
- CRASH_INSERTION((10015));
-
- StartBackupReq* req = (StartBackupReq*)signal->getDataPtr();
- const Uint32 ptrI = req->backupPtr;
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->slaveState.setState(STARTED);
- ptr.p->m_gsn = GSN_START_BACKUP_REQ;
-
- /**
- * Start file threads...
- */
- BackupFilePtr filePtr;
- for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr))
- {
- jam();
- if(! (filePtr.p->m_flags & BackupFile::BF_FILE_THREAD))
- {
- jam();
- filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
- signal->theData[0] = BackupContinueB::START_FILE_THREAD;
- signal->theData[1] = filePtr.i;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
- }//if
- }//for
-
- /**
- * Tell DBTUP to create triggers
- */
- TablePtr tabPtr;
- ndbrequire(ptr.p->tables.first(tabPtr));
- sendCreateTrig(signal, ptr, tabPtr);
-}
-
-/*****************************************************************************
- *
- * Slave functionallity: Backup fragment
- *
- *****************************************************************************/
-void
-Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
-{
- jamEntry();
- BackupFragmentReq* req = (BackupFragmentReq*)signal->getDataPtr();
-
- CRASH_INSERTION((10016));
-
- const Uint32 ptrI = req->backupPtr;
- //const Uint32 backupId = req->backupId;
- const Uint32 tableId = req->tableId;
- const Uint32 fragNo = req->fragmentNo;
- const Uint32 count = req->count;
-
- /**
- * Get backup record
- */
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->slaveState.setState(SCANNING);
- ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REQ;
-
- /**
- * Get file
- */
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
-
- ndbrequire(filePtr.p->backupPtr == ptrI);
- ndbrequire(filePtr.p->m_flags ==
- (BackupFile::BF_OPEN | BackupFile::BF_FILE_THREAD));
-
- /**
- * Get table
- */
- TablePtr tabPtr;
- ndbrequire(findTable(ptr, tabPtr, tableId));
-
- /**
- * Get fragment
- */
- FragmentPtr fragPtr;
- tabPtr.p->fragments.getPtr(fragPtr, fragNo);
-
- ndbrequire(fragPtr.p->scanned == 0);
- ndbrequire(fragPtr.p->scanning == 0 ||
- refToNode(ptr.p->masterRef) == getOwnNodeId());
-
- /**
- * Init operation
- */
- if(filePtr.p->tableId != tableId) {
- jam();
- filePtr.p->operation.init(tabPtr);
- filePtr.p->tableId = tableId;
- }//if
-
- /**
- * Check for space in buffer
- */
- if(!filePtr.p->operation.newFragment(tableId, fragPtr.p->fragmentId)) {
- jam();
- req->count = count + 1;
- sendSignalWithDelay(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal, 50,
- signal->length());
- ptr.p->slaveState.setState(STARTED);
- return;
- }//if
-
- /**
- * Mark things as "in use"
- */
- fragPtr.p->scanning = 1;
- filePtr.p->fragmentNo = fragPtr.p->fragmentId;
-
- /**
- * Start scan
- */
- {
- filePtr.p->m_flags |= BackupFile::BF_SCAN_THREAD;
-
- Table & table = * tabPtr.p;
- ScanFragReq * req = (ScanFragReq *)signal->getDataPtrSend();
- const Uint32 parallelism = 16;
- const Uint32 attrLen = 5 + table.noOfAttributes;
-
- req->senderData = filePtr.i;
- req->resultRef = reference();
- req->schemaVersion = table.schemaVersion;
- req->fragmentNoKeyLen = fragPtr.p->fragmentId;
- req->requestInfo = 0;
- req->savePointId = 0;
- req->tableId = table.tableId;
- ScanFragReq::setReadCommittedFlag(req->requestInfo, 1);
- ScanFragReq::setLockMode(req->requestInfo, 0);
- ScanFragReq::setHoldLockFlag(req->requestInfo, 0);
- ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
- ScanFragReq::setAttrLen(req->requestInfo,attrLen);
- ScanFragReq::setTupScanFlag(req->requestInfo, 1);
- if (ptr.p->is_lcp())
- {
- ScanFragReq::setScanPrio(req->requestInfo, 1);
- ScanFragReq::setNoDiskFlag(req->requestInfo, 1);
- ScanFragReq::setLcpScanFlag(req->requestInfo, 1);
- }
- req->transId1 = 0;
- req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
- req->clientOpPtr= filePtr.i;
- req->batch_size_rows= parallelism;
- req->batch_size_bytes= 0;
- sendSignal(DBLQH_REF, GSN_SCAN_FRAGREQ, signal,
- ScanFragReq::SignalLength, JBB);
-
- signal->theData[0] = filePtr.i;
- signal->theData[1] = 0;
- signal->theData[2] = (BACKUP << 20) + (getOwnNodeId() << 8);
-
- // Return all
- signal->theData[3] = table.noOfAttributes;
- signal->theData[4] = 0;
- signal->theData[5] = 0;
- signal->theData[6] = 0;
- signal->theData[7] = 0;
-
- Uint32 dataPos = 8;
- Ptr<Attribute> attrPtr;
- table.attributes.first(attrPtr);
- for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
- {
- jam();
-
- /**
- * LCP should not save disk attributes
- */
- ndbrequire(! (ptr.p->is_lcp() &&
- attrPtr.p->data.m_flags & Attribute::COL_DISK));
-
- AttributeHeader::init(&signal->theData[dataPos],
- attrPtr.p->data.attrId, 0);
- dataPos++;
- if(dataPos == 25) {
- jam();
- sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, 25, JBB);
- dataPos = 3;
- }//if
- }//for
- if(dataPos != 3) {
- jam();
- sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, dataPos, JBB);
- }//if
- }
-}
-
-void
-Backup::execSCAN_HBREP(Signal* signal)
-{
- jamEntry();
-}
-
-void
-Backup::execTRANSID_AI(Signal* signal)
-{
- jamEntry();
-
- const Uint32 filePtrI = signal->theData[0];
- //const Uint32 transId1 = signal->theData[1];
- //const Uint32 transId2 = signal->theData[2];
- const Uint32 dataLen = signal->length() - 3;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, filePtrI);
-
- OperationRecord & op = filePtr.p->operation;
-
- TablePtr tabPtr LINT_SET_PTR;
- c_tablePool.getPtr(tabPtr, op.tablePtr);
-
- Table & table = * tabPtr.p;
-
- /**
- * Unpack data
- */
- op.attrSzTotal += dataLen;
-
- Uint32 srcSz = dataLen;
- Uint32 usedSz = 0;
- const Uint32 * src = &signal->theData[3];
-
- Ptr<Attribute> attrPtr;
- table.attributes.first(attrPtr);
- Uint32 columnNo = 0;
-
- while (usedSz < srcSz)
- {
- jam();
-
- /**
- * Finished with one attribute now find next
- */
- const AttributeHeader attrHead(* src);
- const Uint32 attrId = attrHead.getAttributeId();
- const bool null = attrHead.isNULL();
- const Attribute::Data attr = attrPtr.p->data;
- ndbrequire(attrId == attr.attrId);
-
- usedSz += attrHead.getHeaderSize();
- src += attrHead.getHeaderSize();
-
- if (null) {
- jam();
- ndbrequire(attr.m_flags & Attribute::COL_NULLABLE);
- op.nullVariable();
- } else {
- Uint32* dst;
- Uint32 dstSz = attrHead.getDataSize();
- if (attr.m_flags & Attribute::COL_FIXED &&
- ! (attr.m_flags & Attribute::COL_NULLABLE)) {
- jam();
- dst = op.newAttrib(attr.offset, dstSz);
- ndbrequire(dstSz == attr.sz32);
- } else {
- dst = op.newVariable(columnNo, attrHead.getByteSize());
- ndbrequire(dstSz <= attr.sz32);
- }
-
- memcpy(dst, src, (dstSz << 2));
- src += dstSz;
- usedSz += dstSz;
- }
- table.attributes.next(attrPtr);
- columnNo++;
- }
-
- ndbrequire(usedSz == srcSz);
- ndbrequire(op.finished());
- op.newRecord(op.dst);
-}
-
-void
-Backup::OperationRecord::init(const TablePtr & ptr)
-{
-
- tablePtr = ptr.i;
- noOfAttributes = ptr.p->noOfAttributes;
-
- sz_Bitmask = (ptr.p->noOfNull + 31) >> 5;
- sz_FixedAttribs = ptr.p->sz_FixedAttributes;
-
- if(ptr.p->noOfVariable == 0) {
- jam();
- maxRecordSize = 1 + sz_Bitmask + sz_FixedAttribs;
- } else {
- jam();
- maxRecordSize =
- 1 + sz_Bitmask + 2048 /* Max tuple size */ + 2 * ptr.p->noOfVariable;
- }//if
-}
-
-bool
-Backup::OperationRecord::newFragment(Uint32 tableId, Uint32 fragNo)
-{
- Uint32 * tmp;
- const Uint32 headSz = (sizeof(BackupFormat::DataFile::FragmentHeader) >> 2);
- const Uint32 sz = headSz + 16 * maxRecordSize;
-
- ndbrequire(sz < dataBuffer.getMaxWrite());
- if(dataBuffer.getWritePtr(&tmp, sz)) {
- jam();
- BackupFormat::DataFile::FragmentHeader * head =
- (BackupFormat::DataFile::FragmentHeader*)tmp;
-
- head->SectionType = htonl(BackupFormat::FRAGMENT_HEADER);
- head->SectionLength = htonl(headSz);
- head->TableId = htonl(tableId);
- head->FragmentNo = htonl(fragNo);
- head->ChecksumType = htonl(0);
-
- opNoDone = opNoConf = opLen = 0;
- newRecord(tmp + headSz);
- scanStart = tmp;
- scanStop = (tmp + headSz);
-
- noOfRecords = 0;
- noOfBytes = 0;
- return true;
- }//if
- return false;
-}
-
-bool
-Backup::OperationRecord::fragComplete(Uint32 tableId, Uint32 fragNo, bool fill_record)
-{
- Uint32 * tmp;
- const Uint32 footSz = sizeof(BackupFormat::DataFile::FragmentFooter) >> 2;
- Uint32 sz = footSz + 1;
-
- if (fill_record)
- {
- Uint32 * new_tmp;
- if (!dataBuffer.getWritePtr(&tmp, sz))
- return false;
- new_tmp = tmp + sz;
-
- if ((UintPtr)new_tmp & (sizeof(Page32)-1))
- {
- /* padding is needed to get full write */
- new_tmp += 2 /* to fit empty header minimum 2 words*/;
- new_tmp = (Uint32 *)(((UintPtr)new_tmp + sizeof(Page32)-1) &
- ~(UintPtr)(sizeof(Page32)-1));
- /* new write sz */
- sz = new_tmp - tmp;
- }
- }
-
- if(dataBuffer.getWritePtr(&tmp, sz)) {
- jam();
- * tmp = 0; // Finish record stream
- tmp++;
- BackupFormat::DataFile::FragmentFooter * foot =
- (BackupFormat::DataFile::FragmentFooter*)tmp;
- foot->SectionType = htonl(BackupFormat::FRAGMENT_FOOTER);
- foot->SectionLength = htonl(footSz);
- foot->TableId = htonl(tableId);
- foot->FragmentNo = htonl(fragNo);
- foot->NoOfRecords = htonl(noOfRecords);
- foot->Checksum = htonl(0);
-
- if (sz != footSz + 1)
- {
- tmp += footSz;
- memset(tmp, 0, (sz - footSz - 1) * 4);
- *tmp = htonl(BackupFormat::EMPTY_ENTRY);
- tmp++;
- *tmp = htonl(sz - footSz - 1);
- }
-
- dataBuffer.updateWritePtr(sz);
- return true;
- }//if
- return false;
-}
-
-bool
-Backup::OperationRecord::newScan()
-{
- Uint32 * tmp;
- ndbrequire(16 * maxRecordSize < dataBuffer.getMaxWrite());
- if(dataBuffer.getWritePtr(&tmp, 16 * maxRecordSize)) {
- jam();
- opNoDone = opNoConf = opLen = 0;
- newRecord(tmp);
- scanStart = tmp;
- scanStop = tmp;
- return true;
- }//if
- return false;
-}
-
-bool
-Backup::OperationRecord::closeScan()
-{
- opNoDone = opNoConf = opLen = 0;
- return true;
-}
-
-bool
-Backup::OperationRecord::scanConf(Uint32 noOfOps, Uint32 total_len)
-{
- const Uint32 done = opNoDone-opNoConf;
-
- ndbrequire(noOfOps == done);
- ndbrequire(opLen == total_len);
- opNoConf = opNoDone;
-
- const Uint32 len = (scanStop - scanStart);
- ndbrequire(len < dataBuffer.getMaxWrite());
- dataBuffer.updateWritePtr(len);
- noOfBytes += (len << 2);
- return true;
-}
-
-void
-Backup::execSCAN_FRAGREF(Signal* signal)
-{
- jamEntry();
-
- ScanFragRef * ref = (ScanFragRef*)signal->getDataPtr();
-
- const Uint32 filePtrI = ref->senderData;
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, filePtrI);
-
- filePtr.p->errorCode = ref->errorCode;
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
-
- backupFragmentRef(signal, filePtr);
-}
-
-void
-Backup::execSCAN_FRAGCONF(Signal* signal)
-{
- jamEntry();
-
- CRASH_INSERTION((10017));
-
- ScanFragConf * conf = (ScanFragConf*)signal->getDataPtr();
-
- const Uint32 filePtrI = conf->senderData;
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, filePtrI);
-
- OperationRecord & op = filePtr.p->operation;
-
- op.scanConf(conf->completedOps, conf->total_len);
- const Uint32 completed = conf->fragmentCompleted;
- if(completed != 2) {
- jam();
-
- checkScan(signal, filePtr);
- return;
- }//if
-
- fragmentCompleted(signal, filePtr);
-}
-
-void
-Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
-{
- jam();
-
- if(filePtr.p->errorCode != 0)
- {
- jam();
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
- backupFragmentRef(signal, filePtr); // Scan completed
- return;
- }//if
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
-
- OperationRecord & op = filePtr.p->operation;
- if(!op.fragComplete(filePtr.p->tableId, filePtr.p->fragmentNo,
- c_defaults.m_o_direct))
- {
- jam();
- signal->theData[0] = BackupContinueB::BUFFER_FULL_FRAG_COMPLETE;
- signal->theData[1] = filePtr.i;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
- return;
- }//if
-
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD;
-
- if (ptr.p->is_lcp())
- {
- ptr.p->slaveState.setState(STOPPING);
- filePtr.p->operation.dataBuffer.eof();
- }
- else
- {
- BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
- conf->backupId = ptr.p->backupId;
- conf->backupPtr = ptr.i;
- conf->tableId = filePtr.p->tableId;
- conf->fragmentNo = filePtr.p->fragmentNo;
- 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);
-
- ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_CONF;
- ptr.p->slaveState.setState(STARTED);
- }
- return;
-}
-
-void
-Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr)
-{
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
-
- ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REF;
-
- BackupFragmentRef * ref = (BackupFragmentRef*)signal->getDataPtrSend();
- ref->backupId = ptr.p->backupId;
- ref->backupPtr = ptr.i;
- ref->nodeId = getOwnNodeId();
- ref->errorCode = filePtr.p->errorCode;
- sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_REF, signal,
- BackupFragmentRef::SignalLength, JBB);
-}
-
-void
-Backup::checkScan(Signal* signal, BackupFilePtr filePtr)
-{
- OperationRecord & op = filePtr.p->operation;
-
- if(filePtr.p->errorCode != 0)
- {
- jam();
-
- /**
- * Close scan
- */
- op.closeScan();
- ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
- req->senderData = filePtr.i;
- req->closeFlag = 1;
- req->transId1 = 0;
- req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
- sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- return;
- }//if
-
- if(op.newScan()) {
- jam();
-
- ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
- req->senderData = filePtr.i;
- req->closeFlag = 0;
- req->transId1 = 0;
- req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
- req->batch_size_rows= 16;
- req->batch_size_bytes= 0;
-
- if (ERROR_INSERTED(10036) &&
- filePtr.p->tableId >= 2 &&
- filePtr.p->operation.noOfRecords > 0)
- {
- ndbout_c("halting backup for table %d fragment: %d after %llu records",
- filePtr.p->tableId,
- filePtr.p->fragmentNo,
- filePtr.p->operation.noOfRecords);
- memmove(signal->theData+1, signal->theData,
- 4*ScanFragNextReq::SignalLength);
- signal->theData[0] = BackupContinueB::ZDELAY_SCAN_NEXT;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal,
- 300, 1+ScanFragNextReq::SignalLength);
- return;
- }
- if(ERROR_INSERTED(10032))
- sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
- 100, ScanFragNextReq::SignalLength);
- else if(ERROR_INSERTED(10033))
- {
- SET_ERROR_INSERT_VALUE(10032);
- sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
- 10000, ScanFragNextReq::SignalLength);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
- AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
- ord->backupId = ptr.p->backupId;
- ord->backupPtr = ptr.i;
- ord->requestType = AbortBackupOrd::FileOrScanError;
- ord->senderData= ptr.i;
- sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal,
- AbortBackupOrd::SignalLength, JBB);
- }
- else
- sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- return;
- }//if
-
- signal->theData[0] = BackupContinueB::BUFFER_FULL_SCAN;
- signal->theData[1] = filePtr.i;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 50, 2);
-}
-
-void
-Backup::execFSAPPENDREF(Signal* signal)
-{
- jamEntry();
-
- FsRef * ref = (FsRef *)signal->getDataPtr();
-
- const Uint32 filePtrI = ref->userPointer;
- const Uint32 errCode = ref->errorCode;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, filePtrI);
-
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
- filePtr.p->errorCode = errCode;
-
- checkFile(signal, filePtr);
-}
-
-void
-Backup::execFSAPPENDCONF(Signal* signal)
-{
- jamEntry();
-
- CRASH_INSERTION((10018));
-
- //FsConf * conf = (FsConf*)signal->getDataPtr();
- const Uint32 filePtrI = signal->theData[0]; //conf->userPointer;
- const Uint32 bytes = signal->theData[1]; //conf->bytes;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, filePtrI);
-
- OperationRecord & op = filePtr.p->operation;
-
- op.dataBuffer.updateReadPtr(bytes >> 2);
-
- checkFile(signal, filePtr);
-}
-
-/*
- This routine handles two problems with writing to disk during local
- checkpoints and backups. The first problem is that we need to limit
- the writing to ensure that we don't use too much CPU and disk resources
- for backups and checkpoints. The perfect solution to this is to use
- a dynamic algorithm that adapts to the environment. Until we have
- implemented this we can satisfy ourselves with an algorithm that
- uses a configurable limit.
-
- The second problem is that in Linux we can get severe problems if we
- write very much to the disk without synching. In the worst case we
- can have Gigabytes of data in the Linux page cache before we reach
- the limit of how much we can write. If this happens the performance
- will drop significantly when we reach this limit since the Linux flush
- daemon will spend a few minutes on writing out the page cache to disk.
- To avoid this we ensure that a file never have more than a certain
- amount of data outstanding before synch. This variable is also
- configurable.
-*/
-bool
-Backup::ready_to_write(bool ready, Uint32 sz, bool eof, BackupFile *fileP)
-{
-#if 0
- ndbout << "ready_to_write: ready = " << ready << " eof = " << eof;
- ndbout << " sz = " << sz << endl;
- ndbout << "words this period = " << m_words_written_this_period;
- ndbout << endl << "overflow disk write = " << m_overflow_disk_write;
- ndbout << endl << "Current Millisecond is = ";
- ndbout << NdbTick_CurrentMillisecond() << endl;
-#endif
- if ((ready || eof) &&
- m_words_written_this_period <= m_curr_disk_write_speed)
- {
- /*
- We have a buffer ready to write or we have reached end of
- file and thus we must write the last before closing the
- file.
- We have already check that we are allowed to write at this
- moment. We only worry about history of last 100 milliseconds.
- What happened before that is of no interest since a disk
- write that was issued more than 100 milliseconds should be
- completed by now.
- */
- int overflow;
- m_words_written_this_period += sz;
- overflow = m_words_written_this_period - m_curr_disk_write_speed;
- if (overflow > 0)
- m_overflow_disk_write = overflow;
-#if 0
- ndbout << "Will write with " << endl;
- ndbout << endl;
-#endif
- return true;
- }
- else
- {
-#if 0
- ndbout << "Will not write now" << endl << endl;
-#endif
- return false;
- }
-}
-
-void
-Backup::checkFile(Signal* signal, BackupFilePtr filePtr)
-{
-
-#ifdef DEBUG_ABORT
- // ndbout_c("---- check file filePtr.i = %u", filePtr.i);
-#endif
-
- OperationRecord & op = filePtr.p->operation;
- Uint32 *tmp = NULL;
- Uint32 sz = 0;
- bool eof = FALSE;
- bool ready = op.dataBuffer.getReadPtr(&tmp, &sz, &eof);
-#if 0
- ndbout << "Ptr to data = " << hex << tmp << endl;
-#endif
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
-
- if (ERROR_INSERTED(10036))
- {
- jam();
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
- filePtr.p->errorCode = 2810;
- ptr.p->setErrorCode(2810);
-
- if(ptr.p->m_gsn == GSN_STOP_BACKUP_REQ)
- {
- jam();
- closeFile(signal, ptr, filePtr);
- }
- return;
- }
-
- if(filePtr.p->errorCode != 0)
- {
- jam();
- ptr.p->setErrorCode(filePtr.p->errorCode);
-
- if(ptr.p->m_gsn == GSN_STOP_BACKUP_REQ)
- {
- jam();
- closeFile(signal, ptr, filePtr);
- }
- return;
- }
-
- if (!ready_to_write(ready, sz, eof, filePtr.p))
- {
- jam();
- signal->theData[0] = BackupContinueB::BUFFER_UNDERFLOW;
- signal->theData[1] = filePtr.i;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 20, 2);
- return;
- }
- else if (sz > 0)
- {
- jam();
- FsAppendReq * req = (FsAppendReq *)signal->getDataPtrSend();
- req->filePointer = filePtr.p->filePointer;
- req->userPointer = filePtr.i;
- req->userReference = reference();
- req->varIndex = 0;
- req->offset = tmp - c_startOfPages;
- req->size = sz;
- req->synch_flag = 0;
-
- sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal,
- FsAppendReq::SignalLength, JBA);
- return;
- }
-
- Uint32 flags = filePtr.p->m_flags;
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD;
-
- ndbrequire(flags & BackupFile::BF_OPEN);
- ndbrequire(flags & BackupFile::BF_FILE_THREAD);
-
- closeFile(signal, ptr, filePtr);
-}
-
-
-/****************************************************************************
- *
- * Slave functionallity: Perform logging
- *
- ****************************************************************************/
-void
-Backup::execBACKUP_TRIG_REQ(Signal* signal)
-{
- /*
- TUP asks if this trigger is to be fired on this node.
- */
- TriggerPtr trigPtr LINT_SET_PTR;
- TablePtr tabPtr LINT_SET_PTR;
- FragmentPtr fragPtr;
- Uint32 trigger_id = signal->theData[0];
- Uint32 frag_id = signal->theData[1];
- Uint32 result;
-
- jamEntry();
-
- c_triggerPool.getPtr(trigPtr, trigger_id);
-
- c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i);
- tabPtr.p->fragments.getPtr(fragPtr, frag_id);
- if (fragPtr.p->node != getOwnNodeId()) {
-
- jam();
- result = ZFALSE;
- } else {
- jam();
- result = ZTRUE;
- }//if
- signal->theData[0] = result;
-}
-
-void
-Backup::execTRIG_ATTRINFO(Signal* signal) {
- jamEntry();
-
- CRASH_INSERTION((10019));
-
- TrigAttrInfo * trg = (TrigAttrInfo*)signal->getDataPtr();
-
- TriggerPtr trigPtr LINT_SET_PTR;
- c_triggerPool.getPtr(trigPtr, trg->getTriggerId());
- ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online...
-
- if(trigPtr.p->errorCode != 0) {
- jam();
- return;
- }//if
-
- if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
- jam();
- /**
- * Backup is doing REDO logging and don't need before values
- */
- return;
- }//if
-
- BackupFormat::LogFile::LogEntry * logEntry = trigPtr.p->logEntry;
- if(logEntry == 0)
- {
- jam();
- Uint32 * dst;
- FsBuffer & buf = trigPtr.p->operation->dataBuffer;
- ndbrequire(trigPtr.p->maxRecordSize <= buf.getMaxWrite());
-
- if(ERROR_INSERTED(10030) ||
- !buf.getWritePtr(&dst, trigPtr.p->maxRecordSize))
- {
- jam();
- Uint32 save[TrigAttrInfo::StaticLength];
- memcpy(save, signal->getDataPtr(), 4*TrigAttrInfo::StaticLength);
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
- trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull;
- AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
- ord->backupId = ptr.p->backupId;
- ord->backupPtr = ptr.i;
- ord->requestType = AbortBackupOrd::LogBufferFull;
- ord->senderData= ptr.i;
- sendSignal(ptr.p->masterRef, GSN_ABORT_BACKUP_ORD, signal,
- AbortBackupOrd::SignalLength, JBB);
-
- memcpy(signal->getDataPtrSend(), save, 4*TrigAttrInfo::StaticLength);
- return;
- }//if
-
- logEntry = (BackupFormat::LogFile::LogEntry *)dst;
- trigPtr.p->logEntry = logEntry;
- logEntry->Length = 0;
- logEntry->TableId = htonl(trigPtr.p->tableId);
-
-
- if(trigPtr.p->event==0)
- logEntry->TriggerEvent= htonl(TriggerEvent::TE_INSERT);
- else if(trigPtr.p->event==1)
- logEntry->TriggerEvent= htonl(TriggerEvent::TE_UPDATE);
- else if(trigPtr.p->event==2)
- logEntry->TriggerEvent= htonl(TriggerEvent::TE_DELETE);
- else {
- ndbout << "Bad Event: " << trigPtr.p->event << endl;
- ndbrequire(false);
- }
- } else {
- ndbrequire(logEntry->TableId == htonl(trigPtr.p->tableId));
-// ndbrequire(logEntry->TriggerEvent == htonl(trigPtr.p->event));
- }//if
-
- const Uint32 pos = logEntry->Length;
- const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength;
- memcpy(&logEntry->Data[pos], trg->getData(), dataLen << 2);
-
- logEntry->Length = pos + dataLen;
-}
-
-void
-Backup::execFIRE_TRIG_ORD(Signal* signal)
-{
- jamEntry();
- FireTrigOrd* trg = (FireTrigOrd*)signal->getDataPtr();
-
- const Uint32 gci = trg->getGCI();
- const Uint32 trI = trg->getTriggerId();
- const Uint32 fragId = trg->fragId;
-
- TriggerPtr trigPtr LINT_SET_PTR;
- c_triggerPool.getPtr(trigPtr, trI);
-
- ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID);
-
- if(trigPtr.p->errorCode != 0) {
- jam();
- return;
- }//if
-
- ndbrequire(trigPtr.p->logEntry != 0);
- Uint32 len = trigPtr.p->logEntry->Length;
- trigPtr.p->logEntry->FragId = htonl(fragId);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
- if(gci != ptr.p->currGCP)
- {
- jam();
- trigPtr.p->logEntry->TriggerEvent|= htonl(0x10000);
- trigPtr.p->logEntry->Data[len] = htonl(gci);
- len++;
- ptr.p->currGCP = gci;
- }
-
- len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2;
- trigPtr.p->logEntry->Length = htonl(len);
-
- ndbrequire(len + 1 <= trigPtr.p->operation->dataBuffer.getMaxWrite());
- trigPtr.p->operation->dataBuffer.updateWritePtr(len + 1);
- trigPtr.p->logEntry = 0;
-
- trigPtr.p->operation->noOfBytes += (len + 1) << 2;
- trigPtr.p->operation->noOfRecords += 1;
-}
-
-void
-Backup::sendAbortBackupOrd(Signal* signal, BackupRecordPtr ptr,
- Uint32 requestType)
-{
- jam();
- AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
- ord->backupId = ptr.p->backupId;
- ord->backupPtr = ptr.i;
- ord->requestType = requestType;
- ord->senderData= ptr.i;
- NodePtr node;
- for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)) {
- jam();
- const Uint32 nodeId = node.p->nodeId;
- if(node.p->alive && ptr.p->nodes.get(nodeId)) {
- jam();
- sendSignal(numberToRef(BACKUP, nodeId), GSN_ABORT_BACKUP_ORD, signal,
- AbortBackupOrd::SignalLength, JBB);
- }//if
- }//for
-}
-
-/*****************************************************************************
- *
- * Slave functionallity: Stop backup
- *
- *****************************************************************************/
-void
-Backup::execSTOP_BACKUP_REQ(Signal* signal)
-{
- jamEntry();
- StopBackupReq * req = (StopBackupReq*)signal->getDataPtr();
-
- CRASH_INSERTION((10020));
-
- const Uint32 ptrI = req->backupPtr;
- //const Uint32 backupId = req->backupId;
- const Uint32 startGCP = req->startGCP;
- const Uint32 stopGCP = req->stopGCP;
-
- /**
- * At least one GCP must have passed
- */
- ndbrequire(stopGCP > startGCP);
-
- /**
- * Get backup record
- */
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
-
- ptr.p->slaveState.setState(STOPPING);
- ptr.p->m_gsn = GSN_STOP_BACKUP_REQ;
- ptr.p->startGCP= startGCP;
- ptr.p->stopGCP= stopGCP;
-
- /**
- * Destroy the triggers in local DBTUP we created
- */
- sendDropTrig(signal, ptr);
-}
-
-void
-Backup::closeFiles(Signal* sig, BackupRecordPtr ptr)
-{
- /**
- * Close all files
- */
- BackupFilePtr filePtr;
- int openCount = 0;
- for(ptr.p->files.first(filePtr); filePtr.i!=RNIL; ptr.p->files.next(filePtr))
- {
- if(! (filePtr.p->m_flags & BackupFile::BF_OPEN))
- {
- jam();
- continue;
- }
-
- jam();
- openCount++;
-
- if(filePtr.p->m_flags & BackupFile::BF_CLOSING)
- {
- jam();
- continue;
- }//if
-
- filePtr.p->operation.dataBuffer.eof();
- if(filePtr.p->m_flags & BackupFile::BF_FILE_THREAD)
- {
- jam();
-#ifdef DEBUG_ABORT
- ndbout_c("Close files fileRunning == 1, filePtr.i=%u", filePtr.i);
-#endif
- }
- else
- {
- jam();
- closeFile(sig, ptr, filePtr);
- }
- }
-
- if(openCount == 0){
- jam();
- closeFilesDone(sig, ptr);
- }//if
-}
-
-void
-Backup::closeFile(Signal* signal, BackupRecordPtr ptr, BackupFilePtr filePtr)
-{
- ndbrequire(filePtr.p->m_flags & BackupFile::BF_OPEN);
- ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_OPENING));
- ndbrequire(! (filePtr.p->m_flags & BackupFile::BF_CLOSING));
- filePtr.p->m_flags |= BackupFile::BF_CLOSING;
-
- FsCloseReq * req = (FsCloseReq *)signal->getDataPtrSend();
- req->filePointer = filePtr.p->filePointer;
- req->userPointer = filePtr.i;
- req->userReference = reference();
- req->fileFlag = 0;
-
- if (ptr.p->errorCode)
- {
- FsCloseReq::setRemoveFileFlag(req->fileFlag, 1);
- }
-
-#ifdef DEBUG_ABORT
- ndbout_c("***** a FSCLOSEREQ filePtr.i = %u flags: %x",
- filePtr.i, filePtr.p->m_flags);
-#endif
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
-
-}
-
-void
-Backup::execFSCLOSEREF(Signal* signal)
-{
- jamEntry();
-
- FsRef * ref = (FsRef*)signal->getDataPtr();
- const Uint32 filePtrI = ref->userPointer;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, filePtrI);
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
-
- FsConf * conf = (FsConf*)signal->getDataPtr();
- conf->userPointer = filePtrI;
-
- execFSCLOSECONF(signal);
-}
-
-void
-Backup::execFSCLOSECONF(Signal* signal)
-{
- jamEntry();
-
- FsConf * conf = (FsConf*)signal->getDataPtr();
- const Uint32 filePtrI = conf->userPointer;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, filePtrI);
-
-#ifdef DEBUG_ABORT
- ndbout_c("***** FSCLOSECONF filePtrI = %u", filePtrI);
-#endif
-
- ndbrequire(filePtr.p->m_flags == (BackupFile::BF_OPEN |
- BackupFile::BF_CLOSING));
-
-
- filePtr.p->m_flags &= ~(Uint32)(BackupFile::BF_OPEN |BackupFile::BF_CLOSING);
- filePtr.p->operation.dataBuffer.reset();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
- closeFiles(signal, ptr);
-}
-
-void
-Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr)
-{
- jam();
-
- if(ptr.p->is_lcp())
- {
- lcp_close_file_conf(signal, ptr);
- return;
- }
-
- jam();
-
- //error when do insert footer or close file
- if(ptr.p->checkError())
- {
- StopBackupRef * ref = (StopBackupRef*)signal->getDataPtr();
- ref->backupPtr = ptr.i;
- ref->backupId = ptr.p->backupId;
- ref->errorCode = ptr.p->errorCode;
- ref->nodeId = getOwnNodeId();
- sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_REF, signal,
- StopBackupConf::SignalLength, JBB);
-
- ptr.p->m_gsn = GSN_STOP_BACKUP_REF;
- ptr.p->slaveState.setState(CLEANING);
- return;
- }
-
- StopBackupConf* conf = (StopBackupConf*)signal->getDataPtrSend();
- conf->backupId = ptr.p->backupId;
- conf->backupPtr = ptr.i;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- if(ptr.p->logFilePtr != RNIL)
- {
- ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
- conf->noOfLogBytes= filePtr.p->operation.noOfBytes;
- conf->noOfLogRecords= filePtr.p->operation.noOfRecords;
- }
- else
- {
- conf->noOfLogBytes= 0;
- conf->noOfLogRecords= 0;
- }
-
- sendSignal(ptr.p->masterRef, GSN_STOP_BACKUP_CONF, signal,
- StopBackupConf::SignalLength, JBB);
-
- ptr.p->m_gsn = GSN_STOP_BACKUP_CONF;
- ptr.p->slaveState.setState(CLEANING);
-}
-
-/*****************************************************************************
- *
- * Slave functionallity: Abort backup
- *
- *****************************************************************************/
-/*****************************************************************************
- *
- * Slave functionallity: Abort backup
- *
- *****************************************************************************/
-void
-Backup::execABORT_BACKUP_ORD(Signal* signal)
-{
- jamEntry();
- AbortBackupOrd* ord = (AbortBackupOrd*)signal->getDataPtr();
-
- const Uint32 backupId = ord->backupId;
- const AbortBackupOrd::RequestType requestType =
- (AbortBackupOrd::RequestType)ord->requestType;
- const Uint32 senderData = ord->senderData;
-
-#ifdef DEBUG_ABORT
- ndbout_c("******** ABORT_BACKUP_ORD ********* nodeId = %u",
- refToNode(signal->getSendersBlockRef()));
- ndbout_c("backupId = %u, requestType = %u, senderData = %u, ",
- backupId, requestType, senderData);
- dumpUsedResources();
-#endif
-
- BackupRecordPtr ptr LINT_SET_PTR;
- if(requestType == AbortBackupOrd::ClientAbort) {
- if (getOwnNodeId() != getMasterNodeId()) {
- jam();
- // forward to master
-#ifdef DEBUG_ABORT
- ndbout_c("---- Forward to master nodeId = %u", getMasterNodeId());
-#endif
- sendSignal(calcBackupBlockRef(getMasterNodeId()), GSN_ABORT_BACKUP_ORD,
- signal, AbortBackupOrd::SignalLength, JBB);
- return;
- }
- jam();
- for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
- jam();
- if(ptr.p->backupId == backupId && ptr.p->clientData == senderData) {
- jam();
- break;
- }//if
- }//for
- if(ptr.i == RNIL) {
- jam();
- return;
- }//if
- } else {
- if (c_backupPool.findId(senderData)) {
- jam();
- c_backupPool.getPtr(ptr, senderData);
- } else {
- jam();
-#ifdef DEBUG_ABORT
- ndbout_c("Backup: abort request type=%u on id=%u,%u not found",
- requestType, backupId, senderData);
-#endif
- return;
- }
- }//if
-
- ptr.p->m_gsn = GSN_ABORT_BACKUP_ORD;
- const bool isCoordinator = (ptr.p->masterRef == reference());
-
- bool ok = false;
- switch(requestType){
-
- /**
- * Requests sent to master
- */
- case AbortBackupOrd::ClientAbort:
- jam();
- // fall through
- case AbortBackupOrd::LogBufferFull:
- jam();
- // fall through
- case AbortBackupOrd::FileOrScanError:
- jam();
- ndbrequire(isCoordinator);
- ptr.p->setErrorCode(requestType);
- if(ptr.p->masterData.gsn == GSN_BACKUP_FRAGMENT_REQ)
- {
- /**
- * Only scans are actively aborted
- */
- abort_scan(signal, ptr);
- }
- return;
-
- /**
- * Requests sent to slave
- */
- case AbortBackupOrd::AbortScan:
- jam();
- ptr.p->setErrorCode(requestType);
- return;
-
- case AbortBackupOrd::BackupComplete:
- jam();
- cleanup(signal, ptr);
- return;
- case AbortBackupOrd::BackupFailure:
- case AbortBackupOrd::BackupFailureDueToNodeFail:
- case AbortBackupOrd::OkToClean:
- case AbortBackupOrd::IncompatibleVersions:
-#ifndef VM_TRACE
- default:
-#endif
- ptr.p->setErrorCode(requestType);
- ok= true;
- }
- ndbrequire(ok);
-
- ptr.p->masterRef = reference();
- ptr.p->nodes.clear();
- ptr.p->nodes.set(getOwnNodeId());
-
-
- ptr.p->stopGCP= ptr.p->startGCP + 1;
- sendStopBackup(signal, ptr);
-}
-
-
-void
-Backup::dumpUsedResources()
-{
- jam();
- BackupRecordPtr ptr;
-
- for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)) {
- ndbout_c("Backup id=%u, slaveState.getState = %u, errorCode=%u",
- ptr.p->backupId,
- ptr.p->slaveState.getState(),
- ptr.p->errorCode);
-
- TablePtr tabPtr;
- for(ptr.p->tables.first(tabPtr);
- tabPtr.i != RNIL;
- ptr.p->tables.next(tabPtr)) {
- jam();
- for(Uint32 j = 0; j<3; j++) {
- jam();
- TriggerPtr trigPtr LINT_SET_PTR;
- if(tabPtr.p->triggerAllocated[j]) {
- jam();
- c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
- ndbout_c("Allocated[%u] Triggerid = %u, event = %u",
- j,
- tabPtr.p->triggerIds[j],
- trigPtr.p->event);
- }//if
- }//for
- }//for
-
- BackupFilePtr filePtr;
- for(ptr.p->files.first(filePtr);
- filePtr.i != RNIL;
- ptr.p->files.next(filePtr)) {
- jam();
- ndbout_c("filePtr.i = %u, flags: H'%x ",
- filePtr.i, filePtr.p->m_flags);
- }//for
- }
-}
-
-void
-Backup::cleanup(Signal* signal, BackupRecordPtr ptr)
-{
-
- TablePtr tabPtr;
- for(ptr.p->tables.first(tabPtr); tabPtr.i != RNIL;ptr.p->tables.next(tabPtr))
- {
- jam();
- tabPtr.p->attributes.release();
- tabPtr.p->fragments.release();
- for(Uint32 j = 0; j<3; j++) {
- jam();
- TriggerPtr trigPtr LINT_SET_PTR;
- if(tabPtr.p->triggerAllocated[j]) {
- jam();
- c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
- trigPtr.p->event = ILLEGAL_TRIGGER_ID;
- tabPtr.p->triggerAllocated[j] = false;
- }//if
- tabPtr.p->triggerIds[j] = ILLEGAL_TRIGGER_ID;
- }//for
- {
- signal->theData[0] = tabPtr.p->tableId;
- signal->theData[1] = 0; // unlock
- EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
- }
- }//for
-
- BackupFilePtr filePtr;
- for(ptr.p->files.first(filePtr);filePtr.i != RNIL;ptr.p->files.next(filePtr))
- {
- jam();
- ndbrequire(filePtr.p->m_flags == 0);
- filePtr.p->pages.release();
- }//for
-
- ptr.p->files.release();
- ptr.p->tables.release();
- ptr.p->triggers.release();
- ptr.p->backupId = ~0;
-
- if(ptr.p->checkError())
- removeBackup(signal, ptr);
- else
- c_backups.release(ptr);
-}
-
-
-void
-Backup::removeBackup(Signal* signal, BackupRecordPtr ptr)
-{
- jam();
-
- FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
- req->userReference = reference();
- req->userPointer = ptr.i;
- req->directory = 1;
- req->ownDirectory = 1;
- FsOpenReq::setVersion(req->fileNumber, 2);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL);
- FsOpenReq::v2_setSequence(req->fileNumber, ptr.p->backupId);
- FsOpenReq::v2_setNodeId(req->fileNumber, getOwnNodeId());
- sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
- FsRemoveReq::SignalLength, JBA);
-}
-
-void
-Backup::execFSREMOVEREF(Signal* signal)
-{
- jamEntry();
- FsRef * ref = (FsRef*)signal->getDataPtr();
- const Uint32 ptrI = ref->userPointer;
-
- FsConf * conf = (FsConf*)signal->getDataPtr();
- conf->userPointer = ptrI;
- execFSREMOVECONF(signal);
-}
-
-void
-Backup::execFSREMOVECONF(Signal* signal){
- jamEntry();
-
- FsConf * conf = (FsConf*)signal->getDataPtr();
- const Uint32 ptrI = conf->userPointer;
-
- /**
- * Get backup record
- */
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, ptrI);
- c_backups.release(ptr);
-}
-
-/**
- * LCP
- */
-void
-Backup::execLCP_PREPARE_REQ(Signal* signal)
-{
- jamEntry();
- LcpPrepareReq req = *(LcpPrepareReq*)signal->getDataPtr();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, req.backupPtr);
-
- ptr.p->m_gsn = GSN_LCP_PREPARE_REQ;
-
- TablePtr tabPtr;
- FragmentPtr fragPtr;
- if (!ptr.p->tables.isEmpty())
- {
- jam();
- ndbrequire(ptr.p->errorCode);
- ptr.p->tables.first(tabPtr);
- if (tabPtr.p->tableId == req.tableId)
- {
- jam();
- ndbrequire(!tabPtr.p->fragments.empty());
- tabPtr.p->fragments.getPtr(fragPtr, 0);
- fragPtr.p->fragmentId = req.fragmentId;
- defineBackupRef(signal, ptr, ptr.p->errorCode);
- return;
- }
- else
- {
- jam();
- tabPtr.p->attributes.release();
- tabPtr.p->fragments.release();
- ptr.p->tables.release();
- ptr.p->errorCode = 0;
- // fall-through
- }
- }
-
- if(!ptr.p->tables.seize(tabPtr) || !tabPtr.p->fragments.seize(1))
- {
- if(!tabPtr.isNull())
- ptr.p->tables.release();
- ndbrequire(false); // TODO
- }
- tabPtr.p->tableId = req.tableId;
- tabPtr.p->fragments.getPtr(fragPtr, 0);
- tabPtr.p->tableType = DictTabInfo::UserTable;
- fragPtr.p->fragmentId = req.fragmentId;
- fragPtr.p->lcp_no = req.lcpNo;
- fragPtr.p->scanned = 0;
- fragPtr.p->scanning = 0;
- fragPtr.p->tableId = req.tableId;
-
- ptr.p->backupId= req.backupId;
- lcp_open_file(signal, ptr);
-}
-
-void
-Backup::lcp_close_file_conf(Signal* signal, BackupRecordPtr ptr)
-{
- jam();
-
- TablePtr tabPtr;
- ndbrequire(ptr.p->tables.first(tabPtr));
- Uint32 tableId = tabPtr.p->tableId;
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
- ndbrequire(filePtr.p->m_flags == 0);
-
- if (ptr.p->m_gsn == GSN_LCP_PREPARE_REQ)
- {
- jam();
- defineBackupRef(signal, ptr, ptr.p->errorCode);
- return;
- }
-
- FragmentPtr fragPtr;
- tabPtr.p->fragments.getPtr(fragPtr, 0);
- Uint32 fragmentId = fragPtr.p->fragmentId;
-
- tabPtr.p->attributes.release();
- tabPtr.p->fragments.release();
- ptr.p->tables.release();
- ptr.p->errorCode = 0;
-
- BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
- conf->backupId = ptr.p->backupId;
- conf->backupPtr = ptr.i;
- conf->tableId = tableId;
- conf->fragmentNo = fragmentId;
- conf->noOfRecordsLow = 0;
- conf->noOfRecordsHigh = 0;
- conf->noOfBytesLow = 0;
- conf->noOfBytesHigh = 0;
- sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
- BackupFragmentConf::SignalLength, JBB);
-}
-
-void
-Backup::lcp_open_file(Signal* signal, BackupRecordPtr ptr)
-{
- FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
- req->userReference = reference();
- req->fileFlags =
- FsOpenReq::OM_WRITEONLY |
- FsOpenReq::OM_TRUNCATE |
- FsOpenReq::OM_CREATE |
- FsOpenReq::OM_APPEND |
- FsOpenReq::OM_AUTOSYNC;
- if (c_defaults.m_o_direct)
- req->fileFlags |= FsOpenReq::OM_DIRECT;
- FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
- req->auto_sync_size = c_defaults.m_disk_synch_size;
-
- TablePtr tabPtr;
- FragmentPtr fragPtr;
-
- ndbrequire(ptr.p->tables.first(tabPtr));
- tabPtr.p->fragments.getPtr(fragPtr, 0);
-
- /**
- * Lcp file
- */
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
- ndbrequire(filePtr.p->m_flags == 0);
- filePtr.p->m_flags |= BackupFile::BF_OPENING;
- filePtr.p->tableId = RNIL; // Will force init
- req->userPointer = filePtr.i;
- FsOpenReq::setVersion(req->fileNumber, 5);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
- FsOpenReq::v5_setLcpNo(req->fileNumber, fragPtr.p->lcp_no);
- FsOpenReq::v5_setTableId(req->fileNumber, tabPtr.p->tableId);
- FsOpenReq::v5_setFragmentId(req->fileNumber, fragPtr.p->fragmentId);
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-}
-
-void
-Backup::lcp_open_file_done(Signal* signal, BackupRecordPtr ptr)
-{
- TablePtr tabPtr;
- FragmentPtr fragPtr;
-
- ndbrequire(ptr.p->tables.first(tabPtr));
- tabPtr.p->fragments.getPtr(fragPtr, 0);
-
- BackupFilePtr filePtr LINT_SET_PTR;
- c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
- ndbrequire(filePtr.p->m_flags ==
- (BackupFile::BF_OPEN | BackupFile::BF_LCP_META));
- filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_LCP_META;
-
- ptr.p->slaveState.setState(STARTED);
-
- LcpPrepareConf* conf= (LcpPrepareConf*)signal->getDataPtrSend();
- conf->senderData = ptr.p->clientData;
- conf->senderRef = reference();
- conf->tableId = tabPtr.p->tableId;
- conf->fragmentId = fragPtr.p->fragmentId;
- sendSignal(ptr.p->masterRef, GSN_LCP_PREPARE_CONF,
- signal, LcpPrepareConf::SignalLength, JBB);
-
- /**
- * Start file thread
- */
- filePtr.p->m_flags |= BackupFile::BF_FILE_THREAD;
-
- signal->theData[0] = BackupContinueB::START_FILE_THREAD;
- signal->theData[1] = filePtr.i;
- signal->theData[2] = __LINE__;
- sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 3);
-}
-
-void
-Backup::execEND_LCPREQ(Signal* signal)
-{
- EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
-
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, req->backupPtr);
- ndbrequire(ptr.p->backupId == req->backupId);
-
- BackupFilePtr filePtr LINT_SET_PTR;
- ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
- ndbrequire(filePtr.p->m_flags == 0);
-
- if (!ptr.p->tables.isEmpty())
- {
- jam();
- ndbrequire(ptr.p->errorCode);
- TablePtr tabPtr;
- ptr.p->tables.first(tabPtr);
- tabPtr.p->attributes.release();
- tabPtr.p->fragments.release();
- ptr.p->tables.release();
- ptr.p->errorCode = 0;
- }
-
- ptr.p->errorCode = 0;
- ptr.p->slaveState.setState(CLEANING);
- ptr.p->slaveState.setState(INITIAL);
- ptr.p->slaveState.setState(DEFINING);
- ptr.p->slaveState.setState(DEFINED);
-
- EndLcpConf* conf= (EndLcpConf*)signal->getDataPtr();
- conf->senderData = ptr.p->clientData;
- conf->senderRef = reference();
- sendSignal(ptr.p->masterRef, GSN_END_LCPCONF,
- signal, EndLcpConf::SignalLength, JBB);
-}
diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.hpp b/storage/ndb/src/kernel/blocks/backup/Backup.hpp
deleted file mode 100644
index 7a3280f2ba6..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/Backup.hpp
+++ /dev/null
@@ -1,752 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef BACKUP_H
-#define BACKUP_H
-
-#include <ndb_limits.h>
-#include <SimulatedBlock.hpp>
-
-#include "FsBuffer.hpp"
-#include "BackupFormat.hpp"
-
-#include <NodeBitmask.hpp>
-#include <SimpleProperties.hpp>
-
-#include <SLList.hpp>
-#include <DLFifoList.hpp>
-#include <DLCFifoList.hpp>
-#include <SignalCounter.hpp>
-#include <blocks/mutexes.hpp>
-
-#include <NdbTCP.h>
-#include <NdbTick.h>
-#include <Array.hpp>
-
-/**
- * Backup - This block manages database backup and restore
- */
-class Backup : public SimulatedBlock
-{
-public:
- Backup(Block_context& ctx);
- virtual ~Backup();
- BLOCK_DEFINES(Backup);
-
-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);
- void execINCL_NODEREQ(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- /**
- * Testing
- */
- void execBACKUP_REF(Signal* signal);
- void execBACKUP_CONF(Signal* signal);
- void execBACKUP_ABORT_REP(Signal* signal);
- void execBACKUP_COMPLETE_REP(Signal* signal);
-
- /**
- * Signals sent from master
- */
- void execDEFINE_BACKUP_REQ(Signal* signal);
- 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);
-
- /**
- * The actual scan
- */
- void execSCAN_HBREP(Signal* signal);
- void execTRANSID_AI(Signal* signal);
- void execSCAN_FRAGREF(Signal* signal);
- void execSCAN_FRAGCONF(Signal* signal);
-
- /**
- * Trigger logging
- */
- void execBACKUP_TRIG_REQ(Signal* signal);
- void execTRIG_ATTRINFO(Signal* signal);
- void execFIRE_TRIG_ORD(Signal* signal);
-
- /**
- * DICT signals
- */
- void execLIST_TABLES_CONF(Signal* signal);
- void execGET_TABINFOREF(Signal* signal);
- void execGET_TABINFO_CONF(Signal* signal);
- void execCREATE_TRIG_REF(Signal* signal);
- void execCREATE_TRIG_CONF(Signal* signal);
- void execDROP_TRIG_REF(Signal* signal);
- void execDROP_TRIG_CONF(Signal* signal);
-
- /**
- * DIH signals
- */
- void execDI_FCOUNTCONF(Signal* signal);
- void execDIGETPRIMCONF(Signal* signal);
-
- /**
- * FS signals
- */
- void execFSOPENREF(Signal* signal);
- void execFSOPENCONF(Signal* signal);
-
- void execFSCLOSEREF(Signal* signal);
- void execFSCLOSECONF(Signal* signal);
-
- void execFSAPPENDREF(Signal* signal);
- void execFSAPPENDCONF(Signal* signal);
-
- void execFSREMOVEREF(Signal* signal);
- void execFSREMOVECONF(Signal* signal);
-
- /**
- * Master functinallity
- */
- void execBACKUP_REQ(Signal* signal);
- void execABORT_BACKUP_REQ(Signal* signal);
-
- void execDEFINE_BACKUP_REF(Signal* signal);
- void execDEFINE_BACKUP_CONF(Signal* signal);
-
- void execSTART_BACKUP_REF(Signal* signal);
- void execSTART_BACKUP_CONF(Signal* signal);
-
- void execBACKUP_FRAGMENT_REF(Signal* signal);
- void execBACKUP_FRAGMENT_CONF(Signal* signal);
-
- void execSTOP_BACKUP_REF(Signal* signal);
- void execSTOP_BACKUP_CONF(Signal* signal);
-
- void execBACKUP_STATUS_CONF(Signal* signal);
-
- void execUTIL_SEQUENCE_REF(Signal* signal);
- void execUTIL_SEQUENCE_CONF(Signal* signal);
-
- void execWAIT_GCP_REF(Signal* signal);
- void execWAIT_GCP_CONF(Signal* signal);
-
- void execLCP_PREPARE_REQ(Signal* signal);
- void execLCP_FRAGMENT_REQ(Signal*);
- void execEND_LCPREQ(Signal* signal);
-private:
- void defineBackupMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal);
- void dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal);
-
-public:
- struct Node {
- Uint32 nodeId;
- Uint32 alive;
- Uint32 nextList;
- union { Uint32 prevList; Uint32 nextPool; };
- };
- typedef Ptr<Node> NodePtr;
-
-#define BACKUP_WORDS_PER_PAGE 8191
- struct Page32 {
- Uint32 data[BACKUP_WORDS_PER_PAGE];
- Uint32 nextPool;
- };
- typedef Ptr<Page32> Page32Ptr;
-
- struct Attribute {
- enum Flags {
- COL_NULLABLE = 0x1,
- COL_FIXED = 0x2,
- COL_DISK = 0x4
- };
- struct Data {
- Uint16 m_flags;
- Uint16 attrId;
- Uint32 sz32; // No of 32 bit words
- Uint32 offset; // Relative DataFixedAttributes/DataFixedKeys
- Uint32 offsetNull; // In NullBitmask
- } data;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- typedef Ptr<Attribute> AttributePtr;
-
- struct Fragment {
- Uint64 noOfRecords;
- Uint32 tableId;
- Uint16 node;
- Uint16 fragmentId;
- Uint8 scanned; // 0 = not scanned x = scanned by node x
- Uint8 scanning; // 0 = not scanning x = scanning on node x
- Uint8 lcp_no;
- Uint32 nextPool;
- };
- typedef Ptr<Fragment> FragmentPtr;
-
- struct Table {
- Table(ArrayPool<Attribute> &, ArrayPool<Fragment> &);
-
- Uint64 noOfRecords;
-
- Uint32 tableId;
- Uint32 schemaVersion;
- Uint32 tableType;
- Uint32 noOfNull;
- Uint32 noOfAttributes;
- Uint32 noOfVariable;
- Uint32 sz_FixedAttributes;
- Uint32 triggerIds[3];
- bool triggerAllocated[3];
-
- DLFifoList<Attribute> attributes;
- Array<Fragment> fragments;
-
- Uint32 nextList;
- union { Uint32 nextPool; Uint32 prevList; };
- };
- typedef Ptr<Table> TablePtr;
-
- struct OperationRecord {
- public:
- OperationRecord(Backup & b) : backup(b) {}
-
- /**
- * Once per table
- */
- void init(const TablePtr & ptr);
-
- /**
- * Once per fragment
- */
- bool newFragment(Uint32 tableId, Uint32 fragNo);
- bool fragComplete(Uint32 tableId, Uint32 fragNo, bool fill_record);
-
- /**
- * Once per scan frag (next) req/conf
- */
- bool newScan();
- bool scanConf(Uint32 noOfOps, Uint32 opLen);
- bool closeScan();
-
- /**
- * Per record
- */
- void newRecord(Uint32 * base);
- bool finished();
-
- /**
- * Per attribute
- */
- void nullVariable();
- void nullAttribute(Uint32 nullOffset);
- Uint32 * newNullable(Uint32 attrId, Uint32 sz);
- Uint32 * newAttrib(Uint32 offset, Uint32 sz);
- Uint32 * newVariable(Uint32 id, Uint32 sz);
-
- private:
- Uint32* base;
- Uint32* dst_Length;
- Uint32* dst_Bitmask;
- Uint32* dst_FixedAttribs;
- BackupFormat::DataFile::VariableData* dst_VariableData;
-
- Uint32 noOfAttributes; // No of Attributes
- Uint32 attrLeft; // No of attributes left
-
- Uint32 opNoDone;
- Uint32 opNoConf;
- Uint32 opLen;
-
- public:
- Uint32* dst;
- Uint32 attrSzTotal; // No of AI words received
- Uint32 tablePtr; // Ptr.i to current table
-
- FsBuffer dataBuffer;
- Uint64 noOfRecords;
- Uint64 noOfBytes;
- Uint32 maxRecordSize;
-
- private:
- Uint32* scanStart;
- Uint32* scanStop;
-
- /**
- * sizes of part
- */
- Uint32 sz_Bitmask;
- Uint32 sz_FixedAttribs;
-
- public:
- union { Uint32 nextPool; Uint32 nextList; };
- Uint32 prevList;
- private:
-
- Backup & backup;
- BlockNumber number() const { return backup.number(); }
- void progError(int line, int cause, const char * extra) {
- backup.progError(line, cause, extra);
- }
- };
- friend struct OperationRecord;
-
- struct TriggerRecord {
- TriggerRecord() { event = ~0;}
- OperationRecord * operation;
- BackupFormat::LogFile::LogEntry * logEntry;
- Uint32 maxRecordSize;
- Uint32 tableId;
- Uint32 tab_ptr_i;
- Uint32 event;
- Uint32 backupPtr;
- Uint32 errorCode;
- union { Uint32 nextPool; Uint32 nextList; };
- };
- typedef Ptr<TriggerRecord> TriggerPtr;
-
- /**
- * BackupFile - At least 3 per backup
- */
- struct BackupFile {
- BackupFile(Backup & backup, ArrayPool<Page32> & pp)
- : operation(backup), pages(pp) {}
-
- Uint32 backupPtr; // Pointer to backup record
- Uint32 tableId;
- Uint32 fragmentNo;
- Uint32 filePointer;
- Uint32 errorCode;
- BackupFormat::FileType fileType;
- OperationRecord operation;
-
- Array<Page32> pages;
- Uint32 nextList;
- union { Uint32 prevList; Uint32 nextPool; };
-
- enum {
- BF_OPEN = 0x1
- ,BF_OPENING = 0x2
- ,BF_CLOSING = 0x4
- ,BF_FILE_THREAD = 0x8
- ,BF_SCAN_THREAD = 0x10
- ,BF_LCP_META = 0x20
- };
- Uint32 m_flags;
- Uint32 m_pos;
- };
- typedef Ptr<BackupFile> BackupFilePtr;
-
-
- /**
- * State for BackupRecord
- */
- enum State {
- INITIAL = 0,
- DEFINING = 1, // Defining backup content and parameters
- DEFINED = 2, // DEFINE_BACKUP_CONF sent in slave, received all in master
- STARTED = 3, // Creating triggers
- SCANNING = 4, // Scanning fragments
- STOPPING = 5, // Closing files
- CLEANING = 6, // Cleaning resources
- ABORTING = 7 // Aborting backup
- };
-
- static const Uint32 validSlaveTransitionsCount;
- static const Uint32 validMasterTransitionsCount;
- static const State validSlaveTransitions[];
- static const State validMasterTransitions[];
-
- class CompoundState {
- public:
- CompoundState(Backup & b,
- const State valid[],
- Uint32 count, Uint32 _id)
- : backup(b)
- , validTransitions(valid),
- noOfValidTransitions(count), id(_id)
- {
- state = INITIAL;
- abortState = state;
- }
-
- void setState(State s);
- State getState() const { return state;}
- State getAbortState() const { return abortState;}
-
- void forceState(State s);
-
- BlockNumber number() const { return backup.number(); }
- void progError(int line, int cause, const char * extra) {
- backup.progError(line, cause, extra);
- }
- private:
- Backup & backup;
- State state;
- State abortState; /**
- When state == ABORTING, this contains the state
- when the abort started
- */
- const State * validTransitions;
- const Uint32 noOfValidTransitions;
- const Uint32 id;
- };
- friend class CompoundState;
-
- /**
- * Backup record
- *
- * One record per backup
- */
- struct BackupRecord {
- BackupRecord(Backup& b,
- ArrayPool<Table> & tp,
- ArrayPool<BackupFile> & bp,
- ArrayPool<TriggerRecord> & trp)
- : slaveState(b, validSlaveTransitions, validSlaveTransitionsCount,1)
- , tables(tp), triggers(trp), files(bp)
- , ctlFilePtr(RNIL), logFilePtr(RNIL), dataFilePtr(RNIL)
- , masterData(b), backup(b)
-
- {
- }
-
- Uint32 m_gsn;
- CompoundState slaveState;
-
- Uint32 clientRef;
- Uint32 clientData;
- Uint32 flags;
- Uint32 signalNo;
- Uint32 backupId;
- Uint32 backupKey[2];
- Uint32 masterRef;
- Uint32 errorCode;
- NdbNodeBitmask nodes;
-
- Uint64 noOfBytes;
- Uint64 noOfRecords;
- Uint64 noOfLogBytes;
- Uint64 noOfLogRecords;
-
- Uint32 startGCP;
- Uint32 currGCP;
- Uint32 stopGCP;
- DLCFifoList<Table> tables;
- SLList<TriggerRecord> triggers;
-
- SLList<BackupFile> files;
- Uint32 ctlFilePtr; // Ptr.i to ctl-file
- Uint32 logFilePtr; // Ptr.i to log-file
- Uint32 dataFilePtr; // Ptr.i to first data-file
-
- Uint32 backupDataLen; // Used for (un)packing backup request
- SimpleProperties props;// Used for (un)packing backup request
-
- struct SlaveData {
- SignalCounter trigSendCounter;
- Uint32 gsn;
- struct {
- Uint32 tableId;
- } createTrig;
- struct {
- Uint32 tableId;
- } dropTrig;
- } slaveData;
-
- struct MasterData {
- MasterData(Backup & b)
- {
- }
- MutexHandle2<BACKUP_DEFINE_MUTEX> m_defineBackupMutex;
- MutexHandle2<DICT_COMMIT_TABLE_MUTEX> m_dictCommitTableMutex;
-
- Uint32 gsn;
- SignalCounter sendCounter;
- Uint32 errorCode;
- union {
- struct {
- Uint32 startBackup;
- } waitGCP;
- struct {
- Uint32 signalNo;
- Uint32 noOfSignals;
- Uint32 tablePtr;
- } startBackup;
- struct {
- Uint32 dummy;
- } stopBackup;
- };
- } masterData;
-
- Uint32 nextList;
- union { Uint32 prevList; Uint32 nextPool; };
-
- void setErrorCode(Uint32 errCode){
- if(errorCode == 0)
- errorCode = errCode;
- }
-
- bool checkError() const {
- return errorCode != 0;
- }
-
- bool is_lcp() const {
- return backupDataLen == ~(Uint32)0;
- }
-
- Backup & backup;
- BlockNumber number() const { return backup.number(); }
- void progError(int line, int cause, const char * extra) {
- backup.progError(line, cause, extra);
- }
- };
- friend struct BackupRecord;
- typedef Ptr<BackupRecord> BackupRecordPtr;
-
- struct Config {
- Uint32 m_dataBufferSize;
- Uint32 m_logBufferSize;
- Uint32 m_minWriteSize;
- Uint32 m_maxWriteSize;
- Uint32 m_lcp_buffer_size;
-
- Uint32 m_disk_write_speed_sr;
- Uint32 m_disk_write_speed;
- Uint32 m_disk_synch_size;
- Uint32 m_diskless;
- Uint32 m_o_direct;
- };
-
- /**
- * Variables
- */
- Uint32 * c_startOfPages;
- NodeId c_masterNodeId;
- SLList<Node> c_nodes;
- NdbNodeBitmask c_aliveNodes;
- DLList<BackupRecord> c_backups;
- Config c_defaults;
-
- /*
- Variables that control checkpoint to disk speed
- */
- Uint32 m_curr_disk_write_speed;
- Uint32 m_words_written_this_period;
- Uint32 m_overflow_disk_write;
- Uint32 m_reset_delay_used;
- NDB_TICKS m_reset_disk_speed_time;
- static const int DISK_SPEED_CHECK_DELAY = 100;
-
- STATIC_CONST(NO_OF_PAGES_META_FILE =
- (2*MAX_WORDS_META_FILE + BACKUP_WORDS_PER_PAGE - 1) /
- BACKUP_WORDS_PER_PAGE);
-
- /**
- * Pools
- */
- ArrayPool<Table> c_tablePool;
- ArrayPool<Attribute> c_attributePool;
- ArrayPool<BackupRecord> c_backupPool;
- ArrayPool<BackupFile> c_backupFilePool;
- ArrayPool<Page32> c_pagePool;
- ArrayPool<Fragment> c_fragmentPool;
- ArrayPool<Node> c_nodePool;
- ArrayPool<TriggerRecord> c_triggerPool;
-
- void checkFile(Signal*, BackupFilePtr);
- void checkScan(Signal*, BackupFilePtr);
- void fragmentCompleted(Signal*, BackupFilePtr);
-
- void backupAllData(Signal* signal, BackupRecordPtr);
-
- void getFragmentInfo(Signal*, BackupRecordPtr, TablePtr, Uint32 fragNo);
- void getFragmentInfoDone(Signal*, BackupRecordPtr);
-
- void openFiles(Signal* signal, BackupRecordPtr ptr);
- void openFilesReply(Signal*, BackupRecordPtr ptr, BackupFilePtr);
- void closeFiles(Signal*, BackupRecordPtr ptr);
- void closeFile(Signal*, BackupRecordPtr, BackupFilePtr);
- void closeFilesDone(Signal*, BackupRecordPtr ptr);
-
- void sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr);
-
- void defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId);
- void createTrigReply(Signal* signal, BackupRecordPtr ptr);
- void alterTrigReply(Signal* signal, BackupRecordPtr ptr);
- void startBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32);
- void stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId);
-
- void defineBackupRef(Signal*, BackupRecordPtr, Uint32 errCode = 0);
- void backupFragmentRef(Signal * signal, BackupFilePtr filePtr);
-
- void nextFragment(Signal*, BackupRecordPtr);
-
- void sendCreateTrig(Signal*, BackupRecordPtr ptr, TablePtr tabPtr);
- void createAttributeMask(TablePtr tab, Bitmask<MAXNROFATTRIBUTESINWORDS>&);
- void sendStartBackup(Signal*, BackupRecordPtr, TablePtr);
- void sendAlterTrig(Signal*, BackupRecordPtr ptr);
-
- void sendDropTrig(Signal*, BackupRecordPtr ptr);
- void sendDropTrig(Signal* signal, BackupRecordPtr ptr, TablePtr tabPtr);
- void dropTrigReply(Signal*, BackupRecordPtr ptr);
-
- void sendSignalAllWait(BackupRecordPtr ptr, Uint32 gsn, Signal *signal,
- Uint32 signalLength,
- bool executeDirect = false);
- bool haveAllSignals(BackupRecordPtr ptr, Uint32 gsn, Uint32 nodeId);
-
- void sendStopBackup(Signal*, BackupRecordPtr ptr);
- void sendAbortBackupOrd(Signal* signal, BackupRecordPtr ptr, Uint32 errCode);
- void sendAbortBackupOrdSlave(Signal* signal, BackupRecordPtr ptr,
- Uint32 errCode);
- void masterAbort(Signal*, BackupRecordPtr ptr);
- void masterSendAbortBackup(Signal*, BackupRecordPtr ptr);
- void slaveAbort(Signal*, BackupRecordPtr ptr);
-
- void abortFile(Signal* signal, BackupRecordPtr ptr, BackupFilePtr filePtr);
- void abortFileHook(Signal* signal, BackupFilePtr filePtr, bool scanDone);
-
- bool verifyNodesAlive(BackupRecordPtr, const NdbNodeBitmask& aNodeBitMask);
- bool checkAbort(BackupRecordPtr ptr);
- void checkNodeFail(Signal* signal,
- BackupRecordPtr ptr,
- NodeId newCoord,
- Uint32 theFailedNodes[NodeBitmask::Size]);
- void masterTakeOver(Signal* signal, BackupRecordPtr ptr);
-
-
- NodeId getMasterNodeId() const { return c_masterNodeId; }
- bool findTable(const BackupRecordPtr &, TablePtr &, Uint32 tableId) const;
- bool parseTableDescription(Signal*, BackupRecordPtr ptr, TablePtr, const Uint32*, Uint32);
-
- bool insertFileHeader(BackupFormat::FileType, BackupRecord*, BackupFile*);
- void sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode);
- void sendBackupRef(BlockReference ref, Uint32 flags, Signal *signal,
- Uint32 senderData, Uint32 errorCode);
- void dumpUsedResources();
- void cleanup(Signal*, BackupRecordPtr ptr);
- void abort_scan(Signal*, BackupRecordPtr ptr);
- void removeBackup(Signal*, BackupRecordPtr ptr);
-
- void sendSTTORRY(Signal*);
- void createSequence(Signal* signal);
- void createSequenceReply(Signal*, class UtilSequenceConf *);
-
- void lcp_open_file(Signal* signal, BackupRecordPtr ptr);
- void lcp_open_file_done(Signal*, BackupRecordPtr);
- void lcp_close_file_conf(Signal* signal, BackupRecordPtr);
-
- bool ready_to_write(bool ready, Uint32 sz, bool eof, BackupFile *fileP);
-};
-
-inline
-void
-Backup::OperationRecord::newRecord(Uint32 * p){
- base = p;
- dst_Length = p; p += 1;
- dst_Bitmask = p; p += sz_Bitmask;
- dst_FixedAttribs = p; p += sz_FixedAttribs;
- dst_VariableData = (BackupFormat::DataFile::VariableData*)p;
- BitmaskImpl::clear(sz_Bitmask, dst_Bitmask);
- attrLeft = noOfAttributes;
- attrSzTotal = 0;
-}
-
-inline
-Uint32 *
-Backup::OperationRecord::newAttrib(Uint32 offset, Uint32 sz){
- attrLeft--;
- dst = dst_FixedAttribs + offset;
- return dst;
-}
-
-inline
-void
-Backup::OperationRecord::nullAttribute(Uint32 offsetNull){
- attrLeft --;
- BitmaskImpl::set(sz_Bitmask, dst_Bitmask, offsetNull);
-}
-
-inline
-void
-Backup::OperationRecord::nullVariable()
-{
- attrLeft --;
-}
-
-inline
-Uint32 *
-Backup::OperationRecord::newNullable(Uint32 id, Uint32 sz){
- Uint32 sz32 = (sz + 3) >> 2;
-
- attrLeft--;
-
- dst = &dst_VariableData->Data[0];
- dst_VariableData->Sz = htonl(sz);
- dst_VariableData->Id = htonl(id);
-
- dst_VariableData = (BackupFormat::DataFile::VariableData *)(dst + sz32);
-
- // Clear all bits on newRecord -> dont need to clear this
- // BitmaskImpl::clear(sz_Bitmask, dst_Bitmask, offsetNull);
- return dst;
-}
-
-inline
-Uint32 *
-Backup::OperationRecord::newVariable(Uint32 id, Uint32 sz){
- Uint32 sz32 = (sz + 3) >> 2;
-
- attrLeft--;
-
- dst = &dst_VariableData->Data[0];
- dst_VariableData->Sz = htonl(sz);
- dst_VariableData->Id = htonl(id);
-
- dst_VariableData = (BackupFormat::DataFile::VariableData *)(dst + sz32);
- return dst;
-}
-
-inline
-bool
-Backup::OperationRecord::finished(){
- if(attrLeft != 0){
- return false;
- }
-
- opLen += attrSzTotal;
- opNoDone++;
-
- scanStop = dst = (Uint32 *)dst_VariableData;
-
- const Uint32 len = (dst - base - 1);
- * dst_Length = htonl(len);
-
- noOfRecords++;
-
- return true;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.txt b/storage/ndb/src/kernel/blocks/backup/Backup.txt
deleted file mode 100644
index 38b93f2d3c4..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/Backup.txt
+++ /dev/null
@@ -1,427 +0,0 @@
--- BACKUP SIGNAL DIAGRAM COMPLEMENT TO BACKUP AMENDMENTS 2003-07-11 --
-
-USER MASTER MASTER SLAVE SLAVE
----------------------------------------------------------------------
-BACKUP_REQ
----------------->
- UTIL_SEQUENCE
- --------------->
- <---------------
- DEFINE_BACKUP
- ------------------------------> (Local signals)
- LIST_TABLES
- --------------->
- <---------------
- FSOPEN
- --------------->
- GET_TABINFO
- <---------------
- DI_FCOUNT
- --------------->
- <---------------
- DI_GETPRIM
- --------------->
- <---------------
- <-------------------------------
-BACKUP_CONF
-<----------------
- START_BACKUP
- ------------------------------>
- CREATE_TRIG
- -------------->
- <--------------
- <------------------------------
- WAIT_GCP
- -------------->
- <--------------
- BACKUP_FRAGMENT
- ------------------------------>
- SCAN_FRAG
- --------------->
- <---------------
- <------------------------------
- WAIT_GCP
- -------------->
- <--------------
- STOP_BACKUP
- ------------------------------>
- DROP_TRIG
- -------------->
- <--------------
- <------------------------------
-BACKUP_COMPLETE_REP
-<----------------
- ABORT_BACKUP
- ------------------------------>
-
-----------------------------------------------------------------------------
-
-USER BACKUP-MASTER
-
-1) BACKUP_REQ -->
-
-2) To all slaves DEFINE_BACKUP_REQ
- This signals contains info so that all
- slaves can take over as master
- Tomas: Except triggerId info...
-
-3) Wait for conf
-
-4) <-- BACKUP_CONF
-
-5) For Each Table
- PREP_CREATE_TRIG_REQ
- Wait for Conf
-
-6) To all slaves START_BACKUP_REQ
- Include trigger ids
- Wait for conf
-
-7) For Each Table
- CREATE_TRIG_REQ
- Wait for conf
-
-8) Wait for GCP
-
-9) For each table
- For each fragment
- BACKUP_FRAGMENT_REQ -->
- <-- BACKUP_FRAGMENT_CONF
-
-10) Wait for GCP
-
-11) To all slaves STOP_BACKUP_REQ
- This signal turns off logging
-
-12) Wait for conf
-
-13) <-- BACKUP_COMPLETE_REP
-
-----
-
-Slave: Master Died
-Wait for master take-over, max 30 sec then abort everything
-
-Slave: Master TakeOver
-
-BACKUP_STATUS_REQ --> To all nodes
-<-- BACKUP_STATUS_CONF
-
-BACKUP_STATUS_CONF
- BACKUP_DEFINED
- BACKUP_STARTED
- BACKUP_FRAGMENT
-
-Master: Slave died
-
--- Define Backup Req --
-
-1) Get backup definition
- Which tables (all)
-
-2) Open files
- Write table list to CTL - file
-
-3) Get definitions for all tables in backup
-
-4) Get Fragment info
-
-5) Define Backup Conf
-
--- Define Backup Req --
-
--- Abort Backup Req --
-
-1) Report to others
-
-2) Stop logging
-3) Stop file(s)
-4) Stop scan
-
-5) If failure/abort
- Remove files
-
-6) If XXX
- Report to user
-7) Clean up records/stuff
-
--- Abort Backup --
-
-Reasons for aborting:
-
-1a) client abort
-
-1b) slave failure
-
-1c) node failure
-
-Resources to be cleaned up:
-
-Slave responsability:
-
-2a) Close and remove files
-
-2b) Free allocated resources
-
-Master responsability:
-
-2c) Drop triggers
-
-USER MASTER MASTER SLAVE SLAVE
----------------------------------------------------------------------
- BACKUP_ABORT_ORD:
- -------------------------(ALL)-->
- Set Master State ABORTING Set Slave State ABORTING
- Drop Triggers Close and Remove files
- CleanupSlaveResources()
-
- BACKUP_ABORT_ORD:OkToClean
- -------------------------(ALL)-->
-
-
- CleanupMasterResources()
-
-BACKUP_ABORT_REP
-<---------------
-
-
-
-State descriptions:
-
-Master - INITIAL
-BACKUP_REQ ->
-Master - DEFINING
-DEFINE_BACKUP_CONF ->
-Master - DEFINED
-CREATE_TRIG_CONF ->
-Master - STARTED
-<--->
-Master - SCANNING
-WAIT_GCP_CONF ->
-Master - STOPPING
-(Master - CLEANING)
---------
-Master - ABORTING
-
-
-Slave - INITIAL
-DEFINE_BACKUP_REQ ->
-Slave - DEFINING
- - backupId
- - tables
-DIGETPRIMCONF ->
-Slave - DEFINED
-START_BACKUP_REQ ->
-Slave - STARTED
-Slave - SCANNING
-STOP_BACKUP_REQ ->
-Slave - STOPPING
-FSCLOSECONF ->
-Slave - CLEANING
------
-Slave - ABORTING
-
-
-
-Testcases:
-
-2. Master failure at first START_BACKUP_CONF
-
-<masterId> error 10004
-start backup
-
-- Ok
-
-2. Master failure at first CREATE_TRIG_CONF
-
-<masterId> error 10003
-start backup
-
-- Ok
-
-2. Master failure at first ALTER_TRIG_CONF
-
-<masterId> error 10005
-start backup
-
-- Ok
-
-2. Master failure at WAIT_GCP_CONF
-
-<masterId> error 10007
-start backup
-
-- Ok
-
-2. Master failure at WAIT_GCP_CONF, nextFragment
-
-<masterId> error 10008
-start backup
-
-- Ok
-
-2. Master failure at WAIT_GCP_CONF, stopping
-
-<masterId> error 10009
-start backup
-
-- Ok
-
-2. Master failure at BACKUP_FRAGMENT_CONF
-
-<masterId> error 10010
-start backup
-
-- Ok
-
-2. Master failure at first DROP_TRIG_CONF
-
-<masterId> error 10012
-start backup
-
-- Ok
-
-1. Master failure at first STOP_BACKUP_CONF
-
-<masterId> error 10013
-start backup
-
-- Ok
-
-3. Multiple node failiure:
-
-<masterId> error 10001
-<otheId> error 10014
-start backup
-
-- Ok (note, mgmtsrvr does gets BACKUP_ABORT_REP but expects BACKUP_REF, hangs...)
-
-4. Multiple node failiure:
-
-<masterId> error 10007
-<takeover id> error 10002
-start backup
-
-- Ok
-
-
-
- ndbrequire(!ERROR_INSERTED(10001));
- ndbrequire(!ERROR_INSERTED(10002));
- ndbrequire(!ERROR_INSERTED(10021));
- ndbrequire(!ERROR_INSERTED(10003));
- ndbrequire(!ERROR_INSERTED(10004));
- ndbrequire(!ERROR_INSERTED(10005));
- ndbrequire(!ERROR_INSERTED(10006));
- ndbrequire(!ERROR_INSERTED(10007));
- ndbrequire(!ERROR_INSERTED(10008));
- ndbrequire(!ERROR_INSERTED(10009));
- ndbrequire(!ERROR_INSERTED(10010));
- ndbrequire(!ERROR_INSERTED(10011));
- ndbrequire(!ERROR_INSERTED(10012));
- ndbrequire(!ERROR_INSERTED(10013));
- ndbrequire(!ERROR_INSERTED(10014));
- ndbrequire(!ERROR_INSERTED(10015));
- ndbrequire(!ERROR_INSERTED(10016));
- ndbrequire(!ERROR_INSERTED(10017));
- ndbrequire(!ERROR_INSERTED(10018));
- ndbrequire(!ERROR_INSERTED(10019));
- ndbrequire(!ERROR_INSERTED(10020));
-
- if (ERROR_INSERTED(10023)) {
- if (ERROR_INSERTED(10023)) {
- if (ERROR_INSERTED(10024)) {
- if (ERROR_INSERTED(10025)) {
- if (ERROR_INSERTED(10026)) {
- if (ERROR_INSERTED(10028)) {
- if (ERROR_INSERTED(10027)) {
- (ERROR_INSERTED(10022))) {
- if (ERROR_INSERTED(10029)) {
- if(trigPtr.p->operation->noOfBytes > 123 && ERROR_INSERTED(10030)) {
-
------ XXX ---
-
-DEFINE_BACKUP_REF ->
- ABORT_BACKUP_ORD(no reply) when all DEFINE_BACKUP replies has arrived
-
-START_BACKUP_REF
- ABORT_BACKUP_ORD(no reply) when all START_BACKUP_ replies has arrived
-
-BACKUP_FRAGMENT_REF
- ABORT_BACKUP_ORD(reply) directly to all nodes running BACKUP_FRAGMENT
-
- When all nodes has replied BACKUP_FRAGMENT
- ABORT_BACKUP_ORD(no reply)
-
-STOP_BACKUP_REF
- ABORT_BACKUP_ORD(no reply) when all STOP_BACKUP_ replies has arrived
-
-NF_COMPLETE_REP
- slave dies
- master sends OUTSTANDING_REF to self
- slave does nothing
-
- master dies
- slave elects self as master and sets only itself as participant
-
-
-DATA FORMATS
-------------
-
-Note: api-restore must be able to read all old formats.
-
-Todo: header formats
-
-4.1.x
------
-
-Todo
-
-5.0.x
------
-
-Producers: backup, Consumers: api-restore
-
-In 5.0
- 1) attrs have fixed size
- 2) external attr id (column_no) is same as internal attr id (attr_id).
- 3) no disk attributes
-
-Format:
- Part 0: null-bit mask for all nullable rounded to word
- Part 1: fixed + non-nullable in column_no order
- Part 2: fixed + nullable in column_no order
-
-Part 1:
- plain value rounded to words [value]
-
-Part 2:
- not-null => clear null bit, data words [len_in_words attr_id value]
- null => set only null bit in null-bit mask
-
-Note: redundancy in null-bit mask vs 2 word header
-
-5.1.x
------
-
-Producers: backup, Consumers: api-restore lcp-restore
-
-In 5.1
- 1) attrs can have var size, length encoded in value
- 2) column_no need not equal attr_id
- 3) disk attributes
-
-Null-bit mask (5.0) is dropped.
-Length encoded in value is not used.
-In "lcp backup" disk attributes are replaced by 64-bit DISK_REF.
-
-Format:
- Part 1: fixed + non-nullable in column_no order
- Part 2: other attributes
-
-Part 1:
- plain value rounded to words [value]
-
-Part 2:
- not-null => data words [len_in_bytes attr_id value]
- null => not present
diff --git a/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp b/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
deleted file mode 100644
index f48d0ed09d3..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef BACKUP_FORMAT_HPP
-#define BACKUP_FORMAT_HPP
-
-#include <ndb_types.h>
-
-static const char BACKUP_MAGIC[] = { 'N', 'D', 'B', 'B', 'C', 'K', 'U', 'P' };
-
-struct BackupFormat {
-
- /**
- * Section types in file
- */
- enum SectionType {
- FILE_HEADER = 1,
- FRAGMENT_HEADER = 2,
- FRAGMENT_FOOTER = 3,
- TABLE_LIST = 4,
- TABLE_DESCRIPTION = 5,
- GCP_ENTRY = 6,
- FRAGMENT_INFO = 7,
- EMPTY_ENTRY = 8
- };
-
- struct FileHeader {
- char Magic[8];
- Uint32 NdbVersion;
-
- Uint32 SectionType;
- Uint32 SectionLength;
- Uint32 FileType;
- Uint32 BackupId;
- Uint32 BackupKey_0;
- Uint32 BackupKey_1;
- Uint32 ByteOrder;
- };
-
- /**
- * File types
- */
- enum FileType {
- CTL_FILE = 1,
- LOG_FILE = 2,
- DATA_FILE = 3,
- LCP_FILE = 4
- };
-
- /**
- * Data file formats
- */
- struct DataFile {
-
- struct FragmentHeader {
- Uint32 SectionType;
- Uint32 SectionLength;
- Uint32 TableId;
- Uint32 FragmentNo;
- Uint32 ChecksumType;
- };
-
- struct VariableData {
- Uint32 Sz;
- Uint32 Id;
- Uint32 Data[1];
- };
-
- struct Record {
- Uint32 Length;
- Uint32 NullBitmask[1];
- Uint32 DataFixedKeys[1];
- Uint32 DataFixedAttributes[1];
- VariableData DataVariableAttributes[1];
- };
-
- struct FragmentFooter {
- Uint32 SectionType;
- Uint32 SectionLength;
- Uint32 TableId;
- Uint32 FragmentNo;
- Uint32 NoOfRecords;
- Uint32 Checksum;
- };
-
- /* optional padding for O_DIRECT */
- struct EmptyEntry {
- Uint32 SectionType;
- Uint32 SectionLength;
- /* not used data */
- };
- };
-
- /**
- * CTL file formats
- */
- struct CtlFile {
-
- /**
- * Table list
- */
- struct TableList {
- Uint32 SectionType;
- Uint32 SectionLength;
- Uint32 TableIds[1]; // Length = SectionLength - 2
- };
-
- /**
- * Table description(s)
- */
- struct TableDescription {
- Uint32 SectionType;
- Uint32 SectionLength;
- Uint32 TableType;
- Uint32 DictTabInfo[1]; // Length = SectionLength - 3
- };
-
- /**
- * GCP Entry
- */
- struct GCPEntry {
- Uint32 SectionType;
- Uint32 SectionLength;
- Uint32 StartGCP;
- Uint32 StopGCP;
- };
-
- /**
- * Fragment Info
- */
- struct FragmentInfo {
- Uint32 SectionType;
- Uint32 SectionLength;
- Uint32 TableId;
- Uint32 FragmentNo;
- Uint32 NoOfRecordsLow;
- Uint32 NoOfRecordsHigh;
- Uint32 FilePosLow;
- Uint32 FilePosHigh;
- };
- };
-
- /**
- * LOG file format
- */
- struct LogFile {
-
- /**
- * Log Entry
- */
- struct LogEntry {
- Uint32 Length;
- Uint32 TableId;
- // If TriggerEvent & 0x10000 == true then GCI is right after data
- Uint32 TriggerEvent;
- Uint32 FragId;
- Uint32 Data[1]; // Len = Length - 3
- };
-
- /**
- * Log Entry pre NDBD_FRAGID_VERSION
- */
- struct LogEntry_no_fragid {
- Uint32 Length;
- Uint32 TableId;
- // If TriggerEvent & 0x10000 == true then GCI is right after data
- Uint32 TriggerEvent;
- Uint32 Data[1]; // Len = Length - 2
- };
- };
-
- /**
- * LCP file format
- */
- struct LcpFile {
- CtlFile::TableList TableList;
- CtlFile::TableDescription TableDescription;
- DataFile::FragmentHeader FragmentHeader;
- DataFile::Record Record;
- DataFile::FragmentFooter FragmentFooter;
- };
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp b/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
deleted file mode 100644
index 00a2a258085..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-//****************************************************************************
-//
-// NAME
-// Backup - Database backup / restore
-//
-//===========================================================================
-#include "Backup.hpp"
-
-#include <Properties.hpp>
-#include <Configuration.hpp>
-
-//extern const unsigned Ndbcntr::g_sysTableCount;
-
-Backup::Backup(Block_context& ctx) :
- SimulatedBlock(BACKUP, ctx),
- c_nodes(c_nodePool),
- c_backups(c_backupPool)
-{
- BLOCK_CONSTRUCTOR(Backup);
-
- c_masterNodeId = getOwnNodeId();
-
- // 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);
- addRecSignal(GSN_NODE_FAILREP, &Backup::execNODE_FAILREP);
- addRecSignal(GSN_INCL_NODEREQ, &Backup::execINCL_NODEREQ);
- addRecSignal(GSN_CONTINUEB, &Backup::execCONTINUEB);
- addRecSignal(GSN_READ_CONFIG_REQ, &Backup::execREAD_CONFIG_REQ, true);
-
- addRecSignal(GSN_SCAN_HBREP, &Backup::execSCAN_HBREP);
- addRecSignal(GSN_TRANSID_AI, &Backup::execTRANSID_AI);
- addRecSignal(GSN_SCAN_FRAGREF, &Backup::execSCAN_FRAGREF);
- addRecSignal(GSN_SCAN_FRAGCONF, &Backup::execSCAN_FRAGCONF);
-
- addRecSignal(GSN_BACKUP_TRIG_REQ, &Backup::execBACKUP_TRIG_REQ);
- addRecSignal(GSN_TRIG_ATTRINFO, &Backup::execTRIG_ATTRINFO);
- addRecSignal(GSN_FIRE_TRIG_ORD, &Backup::execFIRE_TRIG_ORD);
-
- addRecSignal(GSN_LIST_TABLES_CONF, &Backup::execLIST_TABLES_CONF);
- addRecSignal(GSN_GET_TABINFOREF, &Backup::execGET_TABINFOREF);
- addRecSignal(GSN_GET_TABINFO_CONF, &Backup::execGET_TABINFO_CONF);
-
- addRecSignal(GSN_CREATE_TRIG_REF, &Backup::execCREATE_TRIG_REF);
- addRecSignal(GSN_CREATE_TRIG_CONF, &Backup::execCREATE_TRIG_CONF);
-
- addRecSignal(GSN_DROP_TRIG_REF, &Backup::execDROP_TRIG_REF);
- addRecSignal(GSN_DROP_TRIG_CONF, &Backup::execDROP_TRIG_CONF);
-
- addRecSignal(GSN_DI_FCOUNTCONF, &Backup::execDI_FCOUNTCONF);
- addRecSignal(GSN_DIGETPRIMCONF, &Backup::execDIGETPRIMCONF);
-
- addRecSignal(GSN_FSOPENREF, &Backup::execFSOPENREF, true);
- addRecSignal(GSN_FSOPENCONF, &Backup::execFSOPENCONF);
-
- addRecSignal(GSN_FSCLOSEREF, &Backup::execFSCLOSEREF, true);
- addRecSignal(GSN_FSCLOSECONF, &Backup::execFSCLOSECONF);
-
- addRecSignal(GSN_FSAPPENDREF, &Backup::execFSAPPENDREF, true);
- addRecSignal(GSN_FSAPPENDCONF, &Backup::execFSAPPENDCONF);
-
- addRecSignal(GSN_FSREMOVEREF, &Backup::execFSREMOVEREF, true);
- addRecSignal(GSN_FSREMOVECONF, &Backup::execFSREMOVECONF);
-
- /*****/
- addRecSignal(GSN_BACKUP_REQ, &Backup::execBACKUP_REQ);
- addRecSignal(GSN_ABORT_BACKUP_ORD, &Backup::execABORT_BACKUP_ORD);
-
- addRecSignal(GSN_DEFINE_BACKUP_REQ, &Backup::execDEFINE_BACKUP_REQ);
- addRecSignal(GSN_DEFINE_BACKUP_REF, &Backup::execDEFINE_BACKUP_REF);
- addRecSignal(GSN_DEFINE_BACKUP_CONF, &Backup::execDEFINE_BACKUP_CONF);
-
- addRecSignal(GSN_START_BACKUP_REQ, &Backup::execSTART_BACKUP_REQ);
- addRecSignal(GSN_START_BACKUP_REF, &Backup::execSTART_BACKUP_REF);
- addRecSignal(GSN_START_BACKUP_CONF, &Backup::execSTART_BACKUP_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);
- addRecSignal(GSN_STOP_BACKUP_CONF, &Backup::execSTOP_BACKUP_CONF);
-
- //addRecSignal(GSN_BACKUP_STATUS_REQ, &Backup::execBACKUP_STATUS_REQ);
- //addRecSignal(GSN_BACKUP_STATUS_CONF, &Backup::execBACKUP_STATUS_CONF);
-
- addRecSignal(GSN_UTIL_SEQUENCE_REF, &Backup::execUTIL_SEQUENCE_REF);
- addRecSignal(GSN_UTIL_SEQUENCE_CONF, &Backup::execUTIL_SEQUENCE_CONF);
-
- addRecSignal(GSN_WAIT_GCP_REF, &Backup::execWAIT_GCP_REF);
- addRecSignal(GSN_WAIT_GCP_CONF, &Backup::execWAIT_GCP_CONF);
-
- /**
- * Testing
- */
- addRecSignal(GSN_BACKUP_REF, &Backup::execBACKUP_REF);
- addRecSignal(GSN_BACKUP_CONF, &Backup::execBACKUP_CONF);
- addRecSignal(GSN_BACKUP_ABORT_REP, &Backup::execBACKUP_ABORT_REP);
- addRecSignal(GSN_BACKUP_COMPLETE_REP, &Backup::execBACKUP_COMPLETE_REP);
-
- addRecSignal(GSN_LCP_PREPARE_REQ, &Backup::execLCP_PREPARE_REQ);
- addRecSignal(GSN_END_LCPREQ, &Backup::execEND_LCPREQ);
-}
-
-Backup::~Backup()
-{
-}
-
-BLOCK_FUNCTIONS(Backup)
-
-template class ArrayPool<Backup::Page32>;
-template class ArrayPool<Backup::Attribute>;
-template class ArrayPool<Backup::Fragment>;
-
-void
-Backup::execREAD_CONFIG_REQ(Signal* signal)
-{
- const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
- Uint32 ref = req->senderRef;
- Uint32 senderData = req->senderData;
- ndbrequire(req->noOfParameters == 0);
-
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- c_defaults.m_disk_write_speed = 10 * (1024 * 1024);
- c_defaults.m_disk_write_speed_sr = 100 * (1024 * 1024);
- c_defaults.m_disk_synch_size = 4 * (1024 * 1024);
- c_defaults.m_o_direct = true;
-
- Uint32 noBackups = 0, noTables = 0, noAttribs = 0, noFrags = 0;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS,
- &c_defaults.m_diskless));
- ndb_mgm_get_int_parameter(p, CFG_DB_O_DIRECT,
- &c_defaults.m_o_direct);
- ndb_mgm_get_int_parameter(p, CFG_DB_CHECKPOINT_SPEED_SR,
- &c_defaults.m_disk_write_speed_sr);
- ndb_mgm_get_int_parameter(p, CFG_DB_CHECKPOINT_SPEED,
- &c_defaults.m_disk_write_speed);
- ndb_mgm_get_int_parameter(p, CFG_DB_DISK_SYNCH_SIZE,
- &c_defaults.m_disk_synch_size);
-
- /*
- We adjust the disk speed parameters from bytes per second to rather be
- words per 100 milliseconds. We convert disk synch size from bytes per
- second to words per second.
- */
- c_defaults.m_disk_write_speed /= (4 * 10);
- c_defaults.m_disk_write_speed_sr /= (4 * 10);
-
- 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_nodePool.setSize(MAX_NDB_NODES);
- c_backupPool.setSize(noBackups + 1);
- c_backupFilePool.setSize(3 * noBackups + 1);
- c_tablePool.setSize(noBackups * noTables + 1);
- c_attributePool.setSize(noBackups * noAttribs + MAX_ATTRIBUTES_IN_TABLE);
- c_triggerPool.setSize(noBackups * 3 * noTables);
- c_fragmentPool.setSize(noBackups * noFrags + 1);
-
- 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;
- c_defaults.m_lcp_buffer_size = szDataBuf;
-
-
- Uint32 szMem = 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MEM, &szMem);
- Uint32 noPages = (szMem + c_defaults.m_lcp_buffer_size + 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, true);
-
- { // Init all tables
- SLList<Table> tables(c_tablePool);
- TablePtr ptr;
- while(tables.seize(ptr)){
- new (ptr.p) Table(c_attributePool, c_fragmentPool);
- }
- tables.release();
- }
-
- {
- SLList<BackupFile> ops(c_backupFilePool);
- BackupFilePtr ptr;
- while(ops.seize(ptr)){
- new (ptr.p) BackupFile(* this, c_pagePool);
- }
- ops.release();
- }
-
- {
- SLList<BackupRecord> recs(c_backupPool);
- BackupRecordPtr ptr;
- while(recs.seize(ptr)){
- new (ptr.p) BackupRecord(* this, 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);
-}
-
diff --git a/storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp b/storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp
deleted file mode 100644
index 1349ddf6282..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef FS_BUFFER_HPP
-#define FS_BUFFER_HPP
-
-#include <ndb_global.h>
-
-#define DEBUG(x)
-
-/**
- * A circular data buffer to be used together with the FS
- *
- * One writer - Typically your block
- * getWritePtr()
- * updateWritePtr()
- *
- * One reader - Typically "thread" in your block sending stuff to NDBFS
- * getReadPtr()
- * updateReadPtr()
- */
-class FsBuffer {
-public:
- /**
- * Default constructor
- */
- FsBuffer();
-
- /**
- * setup FsBuffer
- *
- * @param Buffer - Ptr to continuous memory
- * @param Size - Buffer size in 32-bit words
- * @param BlockSize - Size of block in 32-bit words
- * @param MinRead - Min read size in 32-bit words
- * Get rounded(down) to nearest multiple of block size.
- * @param MaxRead - Max read size in 32-bit words
- * Get rounded(down) to nearest multiple of block size.
- * @param MaxWrite - Maximum write (into buffer) in 32-bit words
- *
- * @return NULL if everything is OK
- * else A string describing problem
- */
- const char * setup(Uint32 * Buffer,
- Uint32 Size,
- Uint32 BlockSize = 128, // 512 bytes
- Uint32 MinRead = 1024, // 4k
- Uint32 MaxRead = 1024, // 4k
- Uint32 MaxWrite = 1024); // 4k
- /*
- * @return NULL if everything is OK
- * else A string describing problem
- */
- const char * valid() const;
-
- Uint32 getBufferSize() const;
- Uint32 getUsableSize() const;
- Uint32 * getStart() const;
-
- /**
- * getReadPtr - Get pointer and size of data to send to FS
- *
- * @param ptr - Where to fetch data
- * @param sz - How much data in 32-bit words
- * @param eof - Is this the last fetch (only if return false)
- *
- * @return true - If there is data of size >= minread
- * false - If there is can be data be if it is is < minread
- * - else eof = true
- */
- bool getReadPtr(Uint32 ** ptr, Uint32 * sz, bool * eof);
-
- /**
- * @note: sz must be equal to sz returned by getReadPtr
- */
- void updateReadPtr(Uint32 sz);
-
- /**
- *
- * @note Must be followed by a updateWritePtr(no of words used)
- */
- bool getWritePtr(Uint32 ** ptr, Uint32 sz);
-
- void updateWritePtr(Uint32 sz);
-
- /**
- * There will be no more writing to this buffer
- */
- void eof();
-
- /**
- * Getters for varibles
- */
- Uint32 getMaxWrite() const { return m_maxWrite;}
- Uint32 getMinRead() const { return m_minRead;}
-
- Uint32 getFreeSize() const { return m_free; }
-
- /**
- * reset
- */
- void reset();
-
-private:
-
- Uint32 m_free;
- Uint32 m_readIndex;
- Uint32 m_writeIndex;
- Uint32 m_eof;
- Uint32 * m_start;
- Uint32 m_minRead;
- Uint32 m_maxRead;
- Uint32 m_maxWrite;
- Uint32 m_size;
-
- Uint32 * m_buffer;
- Uint32 m_bufSize;
- Uint32 m_blockSize;
-
- void clear();
-};
-
-inline
-FsBuffer::FsBuffer()
-{
- clear();
-}
-
-inline
-void
-FsBuffer::clear(){
- m_minRead = m_maxRead = m_maxWrite = m_size = m_bufSize = m_free = 0;
- m_buffer = m_start = 0;
-}
-
-static
-Uint32 *
-align(Uint32 * ptr, Uint32 alignment, bool downwards){
-
- const UintPtr a = (UintPtr)ptr;
- const UintPtr b = a % alignment;
-
- if(downwards){
- return (Uint32 *)(a - b);
- } else {
- return (Uint32 *)(a + (b == 0 ? 0 : (alignment - b)));
- }
-}
-
-inline
-const char *
-FsBuffer::setup(Uint32 * Buffer,
- Uint32 Size,
- Uint32 Block,
- Uint32 MinRead,
- Uint32 MaxRead,
- Uint32 MaxWrite)
-{
- clear();
- m_buffer = Buffer;
- m_bufSize = Size;
- m_blockSize = Block;
- if(Block == 0){
- return valid();
- }
-
- m_minRead = (MinRead / Block) * Block;
- m_maxRead = (MaxRead / Block) * Block;
- m_maxWrite = MaxWrite;
-
- m_start = align(Buffer, Block*4, false);
- Uint32 * stop = align(Buffer + Size - MaxWrite, Block*4, true);
- if(stop > m_start){
- m_size = stop - m_start;
- } else {
- m_size = 0;
- }
-
- if(m_minRead == 0)
- m_size = 0;
- else
- m_size = (m_size / m_minRead) * m_minRead;
-
-#if 0
- ndbout_c("Block = %d MinRead = %d -> %d", Block*4, MinRead*4, m_minRead*4);
- ndbout_c("Block = %d MaxRead = %d -> %d", Block*4, MaxRead*4, m_maxRead*4);
-
- ndbout_c("Buffer = %d -> %d", Buffer, m_start);
- ndbout_c("Buffer = %d Size = %d MaxWrite = %d -> %d",
- Buffer, Size*4, MaxWrite*4, m_size*4);
-#endif
-
- m_readIndex = m_writeIndex = m_eof = 0;
- m_free = m_size;
- return valid();
-}
-
-inline
-void
-FsBuffer::reset()
-{
- m_readIndex = m_writeIndex = 0;
- m_free = m_size;
- m_eof = 0;
-}
-
-inline
-const char *
-FsBuffer::valid() const {
- if(m_buffer == 0) return "Null pointer buffer";
- if(m_bufSize == 0) return "Zero size buffer";
- if(m_blockSize == 0) return "Zero block size";
- if(m_minRead < m_blockSize) return "Min read less than block size";
- if(m_maxRead < m_blockSize) return "Max read less than block size";
- if(m_maxRead < m_minRead) return "Max read less than min read";
- if(m_size == 0) return "Zero usable space";
- return 0;
-}
-
-inline
-Uint32
-FsBuffer::getBufferSize() const {
- return m_bufSize;
-}
-
-inline
-Uint32
-FsBuffer::getUsableSize() const {
- return m_size;
-}
-
-inline
-Uint32 *
-FsBuffer::getStart() const {
- return m_start;
-}
-
-inline
-bool
-FsBuffer::getReadPtr(Uint32 ** ptr, Uint32 * sz, bool * _eof){
-
- Uint32 * Tp = m_start;
- const Uint32 Tr = m_readIndex;
- const Uint32 Tm = m_minRead;
- const Uint32 Ts = m_size;
- const Uint32 Tmw = m_maxRead;
-
- Uint32 sz1 = m_size - m_free; // Used
-
- if(sz1 >= Tm){
- if(Tr + sz1 > Ts)
- sz1 = (Ts - Tr);
-
- if(sz1 > Tmw)
- * sz = Tmw;
- else
- * sz = sz1 - (sz1 % Tm);
-
- * ptr = &Tp[Tr];
-
- DEBUG(ndbout_c("getReadPtr() Tr: %d Tmw: %d Ts: %d Tm: %d sz1: %d -> %d",
- Tr, Tmw, Ts, Tm, sz1, * sz));
-
- return true;
- }
-
- if(!m_eof){
- * _eof = false;
-
- DEBUG(ndbout_c("getReadPtr() Tr: %d Tmw: %d Ts: %d Tm: %d sz1: %d -> false",
- Tr, Tmw, Ts, Tm, sz1));
-
- return false;
- }
-
- * sz = sz1;
- * _eof = true;
- * ptr = &Tp[Tr];
-
- DEBUG(ndbout_c("getReadPtr() Tr: %d Tmw: %d Ts: %d Tm: %d sz1: %d -> %d eof",
- Tr, Tmw, Ts, Tm, sz1, * sz));
-
- return false;
-}
-
-inline
-void
-FsBuffer::updateReadPtr(Uint32 sz){
- const Uint32 Tr = m_readIndex;
- const Uint32 Ts = m_size;
-
- m_free += sz;
- m_readIndex = (Tr + sz) % Ts;
-}
-
-inline
-bool
-FsBuffer::getWritePtr(Uint32 ** ptr, Uint32 sz){
- assert(sz <= m_maxWrite);
- Uint32 * Tp = m_start;
- const Uint32 Tw = m_writeIndex;
- const Uint32 sz1 = m_free;
-
- if(sz1 > sz){ // Note at least 1 word of slack
- * ptr = &Tp[Tw];
-
- DEBUG(ndbout_c("getWritePtr(%d) Tw: %d sz1: %d -> true",
- sz, Tw, sz1));
- return true;
- }
-
- DEBUG(ndbout_c("getWritePtr(%d) Tw: %d sz1: %d -> false",
- sz, Tw, sz1));
-
- return false;
-}
-
-inline
-void
-FsBuffer::updateWritePtr(Uint32 sz){
- assert(sz <= m_maxWrite);
- Uint32 * Tp = m_start;
- const Uint32 Tw = m_writeIndex;
- const Uint32 Ts = m_size;
-
- const Uint32 Tnew = (Tw + sz);
- m_free -= sz;
- if(Tnew < Ts){
- m_writeIndex = Tnew;
- DEBUG(ndbout_c("updateWritePtr(%d) m_writeIndex: %d",
- sz, m_writeIndex));
- return;
- }
-
- memcpy(Tp, &Tp[Ts], (Tnew - Ts) << 2);
- m_writeIndex = Tnew - Ts;
- DEBUG(ndbout_c("updateWritePtr(%d) m_writeIndex: %d",
- sz, m_writeIndex));
-}
-
-inline
-void
-FsBuffer::eof(){
- m_eof = 1;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/backup/Makefile.am b/storage/ndb/src/kernel/blocks/backup/Makefile.am
deleted file mode 100644
index d8a82014445..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2004 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-ndbtools_PROGRAMS = ndb_print_backup_file
-ndb_print_backup_file_SOURCES = read.cpp
-ndb_print_backup_file_LDFLAGS = @ndb_bin_am_ldflags@ \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
diff --git a/storage/ndb/src/kernel/blocks/backup/read.cpp b/storage/ndb/src/kernel/blocks/backup/read.cpp
deleted file mode 100644
index 3d4780f5eb4..00000000000
--- a/storage/ndb/src/kernel/blocks/backup/read.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbTCP.h>
-#include <NdbOut.hpp>
-#include "BackupFormat.hpp"
-#include <AttributeHeader.hpp>
-#include <SimpleProperties.hpp>
-#include <ndb_version.h>
-
-bool readHeader(FILE*, BackupFormat::FileHeader *);
-bool readFragHeader(FILE*, BackupFormat::DataFile::FragmentHeader *);
-bool readFragFooter(FILE*, BackupFormat::DataFile::FragmentFooter *);
-Int32 readRecord(FILE*, Uint32 **);
-
-NdbOut & operator<<(NdbOut&, const BackupFormat::FileHeader &);
-NdbOut & operator<<(NdbOut&, const BackupFormat::DataFile::FragmentHeader &);
-NdbOut & operator<<(NdbOut&, const BackupFormat::DataFile::FragmentFooter &);
-
-bool readTableList(FILE*, BackupFormat::CtlFile::TableList **);
-bool readTableDesc(FILE*, BackupFormat::CtlFile::TableDescription **);
-bool readGCPEntry(FILE*, BackupFormat::CtlFile::GCPEntry **);
-
-NdbOut & operator<<(NdbOut&, const BackupFormat::CtlFile::TableList &);
-NdbOut & operator<<(NdbOut&, const BackupFormat::CtlFile::TableDescription &);
-NdbOut & operator<<(NdbOut&, const BackupFormat::CtlFile::GCPEntry &);
-
-Int32 readLogEntry(FILE*, Uint32**);
-
-static Uint32 recNo;
-static Uint32 logEntryNo;
-
-int
-main(int argc, const char * argv[]){
-
- ndb_init();
- if(argc <= 1){
- printf("Usage: %s <filename>\n", argv[0]);
- exit(1);
- }
- FILE * f = fopen(argv[1], "rb");
- if(!f){
- ndbout << "No such file!" << endl;
- exit(1);
- }
-
- BackupFormat::FileHeader fileHeader;
- if(!readHeader(f, &fileHeader)){
- ndbout << "Invalid file!" << endl;
- exit(1);
- }
- ndbout << fileHeader << endl;
-
- switch(fileHeader.FileType){
- case BackupFormat::DATA_FILE:
- while(!feof(f)){
- BackupFormat::DataFile::FragmentHeader fragHeader;
- if(!readFragHeader(f, &fragHeader))
- break;
- ndbout << fragHeader << endl;
-
- Uint32 len, * data;
- while((len = readRecord(f, &data)) > 0){
-#if 0
- ndbout << "-> " << hex;
- for(Uint32 i = 0; i<len; i++){
- ndbout << data[i] << " ";
- }
- ndbout << endl;
-#endif
- }
-
- BackupFormat::DataFile::FragmentFooter fragFooter;
- if(!readFragFooter(f, &fragFooter))
- break;
- ndbout << fragFooter << endl;
- }
- break;
- case BackupFormat::CTL_FILE:{
- BackupFormat::CtlFile::TableList * tabList;
- if(!readTableList(f, &tabList)){
- ndbout << "Invalid file! No table list" << endl;
- break;
- }
- ndbout << (* tabList) << endl;
-
- const Uint32 noOfTables = tabList->SectionLength - 2;
- for(Uint32 i = 0; i<noOfTables; i++){
- BackupFormat::CtlFile::TableDescription * tabDesc;
- if(!readTableDesc(f, &tabDesc)){
- ndbout << "Invalid file missing table description" << endl;
- break;
- }
- ndbout << (* tabDesc) << endl;
- }
-
- BackupFormat::CtlFile::GCPEntry * gcpE;
- if(!readGCPEntry(f, &gcpE)){
- ndbout << "Invalid file! GCP ENtry" << endl;
- break;
- }
- ndbout << (* gcpE) << endl;
-
- break;
- }
- case BackupFormat::LOG_FILE:{
- logEntryNo = 0;
-
- typedef BackupFormat::LogFile::LogEntry LogEntry;
-
- Uint32 len, * data;
- while((len = readLogEntry(f, &data)) > 0){
- LogEntry * logEntry = (LogEntry *) data;
- /**
- * Log Entry
- */
- Uint32 event = ntohl(logEntry->TriggerEvent);
- bool gcp = (event & 0x10000) != 0;
- event &= 0xFFFF;
- if(gcp)
- len --;
-
- ndbout << "LogEntry Table: " << (Uint32)ntohl(logEntry->TableId)
- << " Event: " << event
- << " Length: " << (len - 2);
-
- const Uint32 dataLen = len - 2;
-#if 0
- Uint32 pos = 0;
- while(pos < dataLen){
- AttributeHeader * ah = (AttributeHeader*)&logEntry->Data[pos];
- ndbout_c(" Attribut: %d Size: %d",
- ah->getAttributeId(),
- ah->getDataSize());
- pos += ah->getDataSize() + 1;
- }
-#endif
- if(gcp)
- ndbout << " GCP: " << (Uint32)ntohl(logEntry->Data[dataLen]);
- ndbout << endl;
- }
- break;
- }
- case BackupFormat::LCP_FILE:
- {
- BackupFormat::CtlFile::TableList * tabList;
- if(!readTableList(f, &tabList)){
- ndbout << "Invalid file! No table list" << endl;
- break;
- }
- ndbout << (* tabList) << endl;
-
- const Uint32 noOfTables = tabList->SectionLength - 2;
- for(Uint32 i = 0; i<noOfTables; i++){
- BackupFormat::CtlFile::TableDescription * tabDesc;
- if(!readTableDesc(f, &tabDesc)){
- ndbout << "Invalid file missing table description" << endl;
- break;
- }
- ndbout << (* tabDesc) << endl;
- }
-
- while(!feof(f)){
- BackupFormat::DataFile::FragmentHeader fragHeader;
- if(!readFragHeader(f, &fragHeader))
- break;
- ndbout << fragHeader << endl;
-
- Uint32 len, * data;
- while((len = readRecord(f, &data)) > 0){
-#if 0
- ndbout << "-> " << hex;
- for(Uint32 i = 0; i<len; i++){
- ndbout << data[i] << " ";
- }
- ndbout << endl;
-#endif
- }
-
- BackupFormat::DataFile::FragmentFooter fragFooter;
- if(!readFragFooter(f, &fragFooter))
- break;
- ndbout << fragFooter << endl;
- }
- break;
- }
- default:
- ndbout << "Unsupported file type for printer: "
- << fileHeader.FileType << endl;
- break;
- }
- fclose(f);
- return 0;
-}
-
-#define RETURN_FALSE() { ndbout_c("false: %d", __LINE__); abort(); return false; }
-
-static bool endian = false;
-
-bool
-readHeader(FILE* f, BackupFormat::FileHeader * dst){
- if(fread(dst, 4, 3, f) != 3)
- RETURN_FALSE();
-
- if(memcmp(dst->Magic, BACKUP_MAGIC, sizeof(BACKUP_MAGIC)) != 0)
- RETURN_FALSE();
-
- dst->NdbVersion = ntohl(dst->NdbVersion);
- if(dst->NdbVersion != NDB_VERSION)
- RETURN_FALSE();
-
- if(fread(&dst->SectionType, 4, 2, f) != 2)
- RETURN_FALSE();
- dst->SectionType = ntohl(dst->SectionType);
- dst->SectionLength = ntohl(dst->SectionLength);
-
- if(dst->SectionType != BackupFormat::FILE_HEADER)
- RETURN_FALSE();
-
- if(dst->SectionLength != ((sizeof(BackupFormat::FileHeader) - 12) >> 2))
- RETURN_FALSE();
-
- if(fread(&dst->FileType, 4, dst->SectionLength - 2, f) !=
- (dst->SectionLength - 2))
- RETURN_FALSE();
-
- dst->FileType = ntohl(dst->FileType);
- dst->BackupId = ntohl(dst->BackupId);
- dst->BackupKey_0 = ntohl(dst->BackupKey_0);
- dst->BackupKey_1 = ntohl(dst->BackupKey_1);
-
- if(dst->ByteOrder != 0x12345678)
- endian = true;
-
- return true;
-}
-
-bool
-readFragHeader(FILE* f, BackupFormat::DataFile::FragmentHeader * dst){
- if(fread(dst, 1, sizeof(* dst), f) != sizeof(* dst))
- return false;
-
- dst->SectionType = ntohl(dst->SectionType);
- dst->SectionLength = ntohl(dst->SectionLength);
- dst->TableId = ntohl(dst->TableId);
- dst->FragmentNo = ntohl(dst->FragmentNo);
- dst->ChecksumType = ntohl(dst->ChecksumType);
-
- if(dst->SectionLength != (sizeof(* dst) >> 2))
- RETURN_FALSE();
-
- if(dst->SectionType != BackupFormat::FRAGMENT_HEADER)
- RETURN_FALSE();
-
- recNo = 0;
-
- return true;
-}
-
-bool
-readFragFooter(FILE* f, BackupFormat::DataFile::FragmentFooter * dst){
- if(fread(dst, 1, sizeof(* dst), f) != sizeof(* dst))
- RETURN_FALSE();
-
- dst->SectionType = ntohl(dst->SectionType);
- dst->SectionLength = ntohl(dst->SectionLength);
- dst->TableId = ntohl(dst->TableId);
- dst->FragmentNo = ntohl(dst->FragmentNo);
- dst->NoOfRecords = ntohl(dst->NoOfRecords);
- dst->Checksum = ntohl(dst->Checksum);
-
- if(dst->SectionLength != (sizeof(* dst) >> 2))
- RETURN_FALSE();
-
- if(dst->SectionType != BackupFormat::FRAGMENT_FOOTER)
- RETURN_FALSE();
- return true;
-}
-
-static Uint32 buf[8192];
-
-Int32
-readRecord(FILE* f, Uint32 **dst){
- Uint32 len;
- if(fread(&len, 1, 4, f) != 4)
- RETURN_FALSE();
-
- len = ntohl(len);
-
- if(fread(buf, 4, len, f) != len)
- {
- return -1;
- }
-
- if(len > 0)
- recNo++;
- else
- ndbout_c("Found %d records", recNo);
-
- * dst = &buf[0];
-
-
- return len;
-}
-
-Int32
-readLogEntry(FILE* f, Uint32 **dst){
- Uint32 len;
- if(fread(&len, 1, 4, f) != 4)
- RETURN_FALSE();
-
- len = ntohl(len);
-
- if(fread(&buf[1], 4, len, f) != len)
- return -1;
-
- buf[0] = len;
-
- if(len > 0)
- logEntryNo++;
-
- * dst = &buf[0];
-
- return len;
-}
-
-
-NdbOut &
-operator<<(NdbOut& ndbout, const BackupFormat::FileHeader & hf){
-
- char buf[9];
- memcpy(buf, hf.Magic, sizeof(hf.Magic));
- buf[8] = 0;
-
- ndbout << "-- FileHeader:" << endl;
- ndbout << "Magic: " << buf << endl;
- ndbout << "NdbVersion: " << hf.NdbVersion << endl;
- ndbout << "SectionType: " << hf.SectionType << endl;
- ndbout << "SectionLength: " << hf.SectionLength << endl;
- ndbout << "FileType: " << hf.FileType << endl;
- ndbout << "BackupId: " << hf.BackupId << endl;
- ndbout << "BackupKey: [ " << hex << hf.BackupKey_0
- << " "<< hf.BackupKey_1 << " ]" << endl;
- ndbout << "ByteOrder: " << hex << hf.ByteOrder << endl;
- return ndbout;
-}
-
-NdbOut & operator<<(NdbOut& ndbout,
- const BackupFormat::DataFile::FragmentHeader & hf){
-
- ndbout << "-- Fragment header:" << endl;
- ndbout << "SectionType: " << hf.SectionType << endl;
- ndbout << "SectionLength: " << hf.SectionLength << endl;
- ndbout << "TableId: " << hf.TableId << endl;
- ndbout << "FragmentNo: " << hf.FragmentNo << endl;
- ndbout << "ChecksumType: " << hf.ChecksumType << endl;
-
- return ndbout;
-}
-NdbOut & operator<<(NdbOut& ndbout,
- const BackupFormat::DataFile::FragmentFooter & hf){
-
- ndbout << "-- Fragment footer:" << endl;
- ndbout << "SectionType: " << hf.SectionType << endl;
- ndbout << "SectionLength: " << hf.SectionLength << endl;
- ndbout << "TableId: " << hf.TableId << endl;
- ndbout << "FragmentNo: " << hf.FragmentNo << endl;
- ndbout << "NoOfRecords: " << hf.NoOfRecords << endl;
- ndbout << "Checksum: " << hf.Checksum << endl;
-
- return ndbout;
-}
-
-bool
-readTableList(FILE* f, BackupFormat::CtlFile::TableList **ret){
- BackupFormat::CtlFile::TableList * dst =
- (BackupFormat::CtlFile::TableList *)&buf[0];
-
- if(fread(dst, 4, 2, f) != 2)
- RETURN_FALSE();
-
- dst->SectionType = ntohl(dst->SectionType);
- dst->SectionLength = ntohl(dst->SectionLength);
-
- if(dst->SectionType != BackupFormat::TABLE_LIST)
- RETURN_FALSE();
-
- const Uint32 len = dst->SectionLength - 2;
- if(fread(&dst->TableIds[0], 4, len, f) != len)
- RETURN_FALSE();
-
- for(Uint32 i = 0; i<len; i++){
- dst->TableIds[i] = ntohl(dst->TableIds[i]);
- }
-
- * ret = dst;
-
- return true;
-}
-
-bool
-readTableDesc(FILE* f, BackupFormat::CtlFile::TableDescription **ret){
- BackupFormat::CtlFile::TableDescription * dst =
- (BackupFormat::CtlFile::TableDescription *)&buf[0];
-
- if(fread(dst, 4, 2, f) != 2)
- RETURN_FALSE();
-
- dst->SectionType = ntohl(dst->SectionType);
- dst->SectionLength = ntohl(dst->SectionLength);
-
- if(dst->SectionType != BackupFormat::TABLE_DESCRIPTION)
- RETURN_FALSE();
-
- const Uint32 len = dst->SectionLength - 2;
- if(fread(&dst->DictTabInfo[0], 4, len, f) != len)
- RETURN_FALSE();
-
- * ret = dst;
-
- return true;
-}
-
-bool
-readGCPEntry(FILE* f, BackupFormat::CtlFile::GCPEntry **ret){
- BackupFormat::CtlFile::GCPEntry * dst =
- (BackupFormat::CtlFile::GCPEntry *)&buf[0];
-
- if(fread(dst, 4, 4, f) != 4)
- RETURN_FALSE();
-
- dst->SectionType = ntohl(dst->SectionType);
- dst->SectionLength = ntohl(dst->SectionLength);
-
- if(dst->SectionType != BackupFormat::GCP_ENTRY)
- RETURN_FALSE();
-
- dst->StartGCP = ntohl(dst->StartGCP);
- dst->StopGCP = ntohl(dst->StopGCP);
-
- * ret = dst;
-
- return true;
-}
-
-
-NdbOut &
-operator<<(NdbOut& ndbout, const BackupFormat::CtlFile::TableList & hf) {
- ndbout << "-- Table List:" << endl;
- ndbout << "SectionType: " << hf.SectionType << endl;
- ndbout << "SectionLength: " << hf.SectionLength << endl;
- for(Uint32 i = 0; i < hf.SectionLength - 2; i++){
- ndbout << hf.TableIds[i] << " ";
- if((i + 1) % 16 == 0)
- ndbout << endl;
- }
- return ndbout;
-}
-
-NdbOut &
-operator<<(NdbOut& ndbout, const BackupFormat::CtlFile::TableDescription & hf){
- ndbout << "-- Table Description:" << endl;
- ndbout << "SectionType: " << hf.SectionType << endl;
- ndbout << "SectionLength: " << hf.SectionLength << endl;
-
- SimplePropertiesLinearReader it(&hf.DictTabInfo[0], hf.SectionLength - 2);
- char buf[1024];
- for(it.first(); it.valid(); it.next()){
- switch(it.getValueType()){
- case SimpleProperties::Uint32Value:
- ndbout << "Key: " << it.getKey()
- << " value(" << it.getValueLen() << ") : "
- << it.getUint32() << endl;
- break;
- case SimpleProperties::StringValue:
- if(it.getValueLen() < sizeof(buf)){
- it.getString(buf);
- ndbout << "Key: " << it.getKey()
- << " value(" << it.getValueLen() << ") : "
- << "\"" << buf << "\"" << endl;
- } else {
- ndbout << "Key: " << it.getKey()
- << " value(" << it.getValueLen() << ") : "
- << "\"" << "<TOO LONG>" << "\"" << endl;
-
- }
- break;
- default:
- ndbout << "Unknown type for key: " << it.getKey()
- << " type: " << it.getValueType() << endl;
- }
- }
-
- return ndbout;
-}
-
-NdbOut &
-operator<<(NdbOut& ndbout, const BackupFormat::CtlFile::GCPEntry & hf) {
- ndbout << "-- GCP Entry:" << endl;
- ndbout << "SectionType: " << hf.SectionType << endl;
- ndbout << "SectionLength: " << hf.SectionLength << endl;
- ndbout << "Start GCP: " << hf.StartGCP << endl;
- ndbout << "Stop GCP: " << hf.StopGCP << endl;
-
- return ndbout;
-}
-
diff --git a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
deleted file mode 100644
index a99ae597f00..00000000000
--- a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ /dev/null
@@ -1,1453 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "Cmvmi.hpp"
-
-#include <Configuration.hpp>
-#include <kernel_types.h>
-#include <TransporterRegistry.hpp>
-#include <NdbOut.hpp>
-#include <NdbMem.h>
-
-#include <SignalLoggerManager.hpp>
-#include <FastScheduler.hpp>
-
-#define DEBUG(x) { ndbout << "CMVMI::" << x << endl; }
-
-#include <signaldata/TestOrd.hpp>
-#include <signaldata/EventReport.hpp>
-#include <signaldata/TamperOrd.hpp>
-#include <signaldata/StartOrd.hpp>
-#include <signaldata/CloseComReqConf.hpp>
-#include <signaldata/SetLogLevelOrd.hpp>
-#include <signaldata/EventSubscribeReq.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/DisconnectRep.hpp>
-
-#include <EventLogger.hpp>
-#include <TimeQueue.hpp>
-
-#include <NdbSleep.h>
-#include <SafeCounter.hpp>
-
-// Used here only to print event reports on stdout/console.
-EventLogger g_eventLogger;
-extern int simulate_error_during_shutdown;
-
-Cmvmi::Cmvmi(Block_context& ctx) :
- SimulatedBlock(CMVMI, ctx)
- ,subscribers(subscriberPool)
-{
- BLOCK_CONSTRUCTOR(Cmvmi);
-
- Uint32 long_sig_buffer_size;
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndb_mgm_get_int_parameter(p, CFG_DB_LONG_SIGNAL_BUFFER,
- &long_sig_buffer_size);
-
- long_sig_buffer_size= long_sig_buffer_size / 256;
- g_sectionSegmentPool.setSize(long_sig_buffer_size,
- false,true,true,CFG_DB_LONG_SIGNAL_BUFFER);
-
- // Add received signals
- addRecSignal(GSN_CONNECT_REP, &Cmvmi::execCONNECT_REP);
- addRecSignal(GSN_DISCONNECT_REP, &Cmvmi::execDISCONNECT_REP);
-
- addRecSignal(GSN_NDB_TAMPER, &Cmvmi::execNDB_TAMPER, true);
- 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);
- addRecSignal(GSN_TEST_ORD, &Cmvmi::execTEST_ORD);
-
- addRecSignal(GSN_TAMPER_ORD, &Cmvmi::execTAMPER_ORD);
- addRecSignal(GSN_STOP_ORD, &Cmvmi::execSTOP_ORD);
- addRecSignal(GSN_START_ORD, &Cmvmi::execSTART_ORD);
- addRecSignal(GSN_EVENT_SUBSCRIBE_REQ,
- &Cmvmi::execEVENT_SUBSCRIBE_REQ);
-
- addRecSignal(GSN_DUMP_STATE_ORD, &Cmvmi::execDUMP_STATE_ORD);
-
- addRecSignal(GSN_TESTSIG, &Cmvmi::execTESTSIG);
- addRecSignal(GSN_NODE_START_REP, &Cmvmi::execNODE_START_REP, true);
-
- subscriberPool.setSize(5);
-
- const ndb_mgm_configuration_iterator * db = m_ctx.m_config.getOwnConfigIterator();
- for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
- Uint32 logLevel;
- if(!ndb_mgm_get_int_parameter(db, CFG_MIN_LOGLEVEL+j, &logLevel)){
- clogLevel.setLogLevel((LogLevel::EventCategory)j,
- logLevel);
- }
- }
-
- ndb_mgm_configuration_iterator * iter = m_ctx.m_config.getClusterConfigIterator();
- for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
- jam();
- Uint32 nodeId;
- Uint32 nodeType;
-
- ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_NODE_ID, &nodeId));
- ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_TYPE_OF_SECTION,&nodeType));
-
- switch(nodeType){
- case NodeInfo::DB:
- c_dbNodes.set(nodeId);
- break;
- case NodeInfo::API:
- case NodeInfo::MGM:
- break;
- default:
- ndbrequire(false);
- }
- setNodeInfo(nodeId).m_type = nodeType;
- }
-
- setNodeInfo(getOwnNodeId()).m_connected = true;
- setNodeInfo(getOwnNodeId()).m_version = ndbGetOwnVersion();
-}
-
-Cmvmi::~Cmvmi()
-{
- m_shared_page_pool.clear();
-}
-
-#ifdef ERROR_INSERT
-NodeBitmask c_error_9000_nodes_mask;
-extern Uint32 MAX_RECEIVED_SIGNALS;
-#endif
-
-void Cmvmi::execNDB_TAMPER(Signal* signal)
-{
- jamEntry();
- SET_ERROR_INSERT_VALUE(signal->theData[0]);
- if(ERROR_INSERTED(9999)){
- CRASH_INSERTION(9999);
- }
-
- if(ERROR_INSERTED(9998)){
- while(true) NdbSleep_SecSleep(1);
- }
-
- if(ERROR_INSERTED(9997)){
- ndbrequire(false);
- }
-
-#ifndef NDB_WIN32
- if(ERROR_INSERTED(9996)){
- simulate_error_during_shutdown= SIGSEGV;
- ndbrequire(false);
- }
-
- if(ERROR_INSERTED(9995)){
- simulate_error_during_shutdown= SIGSEGV;
- kill(getpid(), SIGABRT);
- }
-#endif
-
-#ifdef ERROR_INSERT
- if (signal->theData[0] == 9003)
- {
- if (MAX_RECEIVED_SIGNALS < 1024)
- {
- MAX_RECEIVED_SIGNALS = 1024;
- }
- else
- {
- MAX_RECEIVED_SIGNALS = 1 + (rand() % 128);
- }
- ndbout_c("MAX_RECEIVED_SIGNALS: %d", MAX_RECEIVED_SIGNALS);
- CLEAR_ERROR_INSERT_VALUE;
- }
-#endif
-}//execNDB_TAMPER()
-
-void Cmvmi::execSET_LOGLEVELORD(Signal* signal)
-{
- SetLogLevelOrd * const llOrd = (SetLogLevelOrd *)&signal->theData[0];
- LogLevel::EventCategory category;
- Uint32 level;
- jamEntry();
-
- for(unsigned int i = 0; i<llOrd->noOfEntries; i++){
- category = (LogLevel::EventCategory)(llOrd->theData[i] >> 16);
- level = llOrd->theData[i] & 0xFFFF;
-
- clogLevel.setLogLevel(category, level);
- }
-}//execSET_LOGLEVELORD()
-
-void Cmvmi::execEVENT_REP(Signal* signal)
-{
- //-----------------------------------------------------------------------
- // This message is sent to report any types of events in NDB.
- // Based on the log level they will be either ignored or
- // reported. Currently they are printed, but they will be
- // transferred to the management server for further distribution
- // to the graphical management interface.
- //-----------------------------------------------------------------------
- EventReport * const eventReport = (EventReport *)&signal->theData[0];
- Ndb_logevent_type eventType = eventReport->getEventType();
- Uint32 nodeId= eventReport->getNodeId();
- if (nodeId == 0)
- {
- nodeId= refToNode(signal->getSendersBlockRef());
- eventReport->setNodeId(nodeId);
- }
-
- jamEntry();
-
- /**
- * If entry is not found
- */
- Uint32 threshold;
- LogLevel::EventCategory eventCategory;
- Logger::LoggerLevel severity;
- EventLoggerBase::EventTextFunction textF;
- if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity,textF))
- return;
-
- SubscriberPtr ptr;
- for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
- if(ptr.p->logLevel.getLogLevel(eventCategory) < threshold){
- continue;
- }
-
- sendSignal(ptr.p->blockRef, GSN_EVENT_REP, signal, signal->length(), JBB);
- }
-
- if(clogLevel.getLogLevel(eventCategory) < threshold){
- return;
- }
-
- // Print the event info
- g_eventLogger.log(eventReport->getEventType(), signal->theData);
-
- return;
-}//execEVENT_REP()
-
-void
-Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
- EventSubscribeReq * subReq = (EventSubscribeReq *)&signal->theData[0];
- Uint32 senderRef = signal->getSendersBlockRef();
- SubscriberPtr ptr;
- jamEntry();
- DBUG_ENTER("Cmvmi::execEVENT_SUBSCRIBE_REQ");
-
- /**
- * Search for subcription
- */
- for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
- if(ptr.p->blockRef == subReq->blockRef)
- break;
- }
-
- if(ptr.i == RNIL){
- /**
- * Create a new one
- */
- if(subscribers.seize(ptr) == false){
- sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
- return;
- }
- ptr.p->logLevel.clear();
- ptr.p->blockRef = subReq->blockRef;
- }
-
- if(subReq->noOfEntries == 0){
- /**
- * Cancel subscription
- */
- subscribers.release(ptr.i);
- } else {
- /**
- * Update subscription
- */
- LogLevel::EventCategory category;
- Uint32 level = 0;
- for(Uint32 i = 0; i<subReq->noOfEntries; i++){
- category = (LogLevel::EventCategory)(subReq->theData[i] >> 16);
- level = subReq->theData[i] & 0xFFFF;
- ptr.p->logLevel.setLogLevel(category, level);
- DBUG_PRINT("info",("entry %d: level=%d, category= %d", i, level, category));
- }
- }
-
- signal->theData[0] = ptr.i;
- sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB);
- DBUG_VOID_RETURN;
-}
-
-void
-Cmvmi::cancelSubscription(NodeId nodeId){
-
- SubscriberPtr ptr;
- subscribers.first(ptr);
-
- while(ptr.i != RNIL){
- Uint32 i = ptr.i;
- BlockReference blockRef = ptr.p->blockRef;
-
- subscribers.next(ptr);
-
- if(refToNode(blockRef) == nodeId){
- subscribers.release(i);
- }
- }
-}
-
-void Cmvmi::sendSTTORRY(Signal* signal)
-{
- jam();
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 8;
- signal->theData[6] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
-}//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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Uint64 page_buffer = 64*1024*1024;
- ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY, &page_buffer);
-
- Uint32 pages = 0;
- pages += page_buffer / GLOBAL_PAGE_SIZE; // in pages
- pages += LCP_RESTORE_BUFFER;
- m_global_page_pool.setSize(pages + 64, true);
-
- Uint64 shared_mem = 8*1024*1024;
- ndb_mgm_get_int64_parameter(p, CFG_DB_SGA, &shared_mem);
- shared_mem /= GLOBAL_PAGE_SIZE;
- if (shared_mem)
- {
- Resource_limit rl;
- rl.m_min = 0;
- rl.m_max = shared_mem;
- rl.m_resource_id = 0;
- m_ctx.m_mm.set_resource_limit(rl);
- }
-
- ndbrequire(m_ctx.m_mm.init());
- {
- void* ptr = m_ctx.m_mm.get_memroot();
- m_shared_page_pool.set((GlobalPage*)ptr, ~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];
-
- jamEntry();
- if (theStartPhase == 1){
- jam();
-
- if(m_ctx.m_config.lockPagesInMainMemory() == 1)
- {
- int res = NdbMem_MemLockAll(0);
- if(res != 0){
- g_eventLogger.warning("Failed to memlock pages");
- warningEvent("Failed to memlock pages");
- }
- }
-
- sendSTTORRY(signal);
- return;
- } else if (theStartPhase == 3) {
- jam();
- globalData.activateSendPacked = 1;
- sendSTTORRY(signal);
- } else if (theStartPhase == 8){
- /*---------------------------------------------------*/
- /* Open com to API + REP nodes */
- /*---------------------------------------------------*/
- signal->theData[0] = 0; // no answer
- signal->theData[1] = 0; // no id
- signal->theData[2] = NodeInfo::API;
- execOPEN_COMREQ(signal);
- globalData.theStartLevel = NodeState::SL_STARTED;
- sendSTTORRY(signal);
- }
-}
-
-void Cmvmi::execCLOSE_COMREQ(Signal* signal)
-{
- // Close communication with the node and halt input/output from
- // other blocks than QMGR
-
- CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
-
- const BlockReference userRef = closeCom->xxxBlockRef;
- Uint32 failNo = closeCom->failNo;
-// Uint32 noOfNodes = closeCom->noOfNodes;
-
- jamEntry();
- for (unsigned i = 0; i < MAX_NODES; i++)
- {
- if(NodeBitmask::get(closeCom->theNodes, i))
- {
- jam();
-
- //-----------------------------------------------------
- // Report that the connection to the node is closed
- //-----------------------------------------------------
- signal->theData[0] = NDB_LE_CommunicationClosed;
- signal->theData[1] = i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- globalTransporterRegistry.setIOState(i, HaltIO);
- globalTransporterRegistry.do_disconnect(i);
- }
- }
-
- if (failNo != 0)
- {
- jam();
- signal->theData[0] = userRef;
- signal->theData[1] = failNo;
- sendSignal(QMGR_REF, GSN_CLOSE_COMCONF, signal, 19, JBA);
- }
-}
-
-void Cmvmi::execOPEN_COMREQ(Signal* signal)
-{
- // Connect to the specifed NDB node, only QMGR allowed communication
- // so far with the node
-
- const BlockReference userRef = signal->theData[0];
- Uint32 tStartingNode = signal->theData[1];
- Uint32 tData2 = signal->theData[2];
- jamEntry();
-
- const Uint32 len = signal->getLength();
- if(len == 2)
- {
-#ifdef ERROR_INSERT
- if (! ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002))
- && c_error_9000_nodes_mask.get(tStartingNode)))
-#endif
- {
- if (globalData.theStartLevel != NodeState::SL_STARTED &&
- (getNodeInfo(tStartingNode).m_type != NodeInfo::DB &&
- getNodeInfo(tStartingNode).m_type != NodeInfo::MGM))
- {
- jam();
- goto done;
- }
-
- globalTransporterRegistry.do_connect(tStartingNode);
- globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
-
- //-----------------------------------------------------
- // Report that the connection to the node is opened
- //-----------------------------------------------------
- signal->theData[0] = NDB_LE_CommunicationOpened;
- signal->theData[1] = tStartingNode;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- //-----------------------------------------------------
- }
- } else {
- for(unsigned int i = 1; i < MAX_NODES; i++ )
- {
- jam();
- if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2)
- {
- jam();
-
-#ifdef ERROR_INSERT
- if ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002))
- && c_error_9000_nodes_mask.get(i))
- continue;
-#endif
-
- globalTransporterRegistry.do_connect(i);
- globalTransporterRegistry.setIOState(i, HaltIO);
-
- signal->theData[0] = NDB_LE_CommunicationOpened;
- signal->theData[1] = i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- }
- }
- }
-
-done:
- if (userRef != 0) {
- jam();
- signal->theData[0] = tStartingNode;
- signal->theData[1] = tData2;
- sendSignal(userRef, GSN_OPEN_COMCONF, signal, len - 1,JBA);
- }
-}
-
-void Cmvmi::execENABLE_COMORD(Signal* signal)
-{
- // Enable communication with all our NDB blocks to this node
-
- Uint32 tStartingNode = signal->theData[0];
- globalTransporterRegistry.setIOState(tStartingNode, NoHalt);
- setNodeInfo(tStartingNode).m_connected = true;
- //-----------------------------------------------------
- // Report that the version of the node
- //-----------------------------------------------------
- signal->theData[0] = NDB_LE_ConnectedApiVersion;
- signal->theData[1] = tStartingNode;
- signal->theData[2] = getNodeInfo(tStartingNode).m_version;
-
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
- //-----------------------------------------------------
-
- jamEntry();
-}
-
-void Cmvmi::execDISCONNECT_REP(Signal *signal)
-{
- const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
- const Uint32 hostId = rep->nodeId;
- const Uint32 errNo = rep->err;
-
- jamEntry();
-
- setNodeInfo(hostId).m_connected = false;
- setNodeInfo(hostId).m_connectCount++;
- const NodeInfo::NodeType type = getNodeInfo(hostId).getType();
- ndbrequire(type != NodeInfo::INVALID);
-
- sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
- DisconnectRep::SignalLength, JBA);
-
- cancelSubscription(hostId);
-
- signal->theData[0] = NDB_LE_Disconnected;
- signal->theData[1] = hostId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-}
-
-void Cmvmi::execCONNECT_REP(Signal *signal){
- const Uint32 hostId = signal->theData[0];
- jamEntry();
-
- const NodeInfo::NodeType type = (NodeInfo::NodeType)getNodeInfo(hostId).m_type;
- ndbrequire(type != NodeInfo::INVALID);
- globalData.m_nodeInfo[hostId].m_version = 0;
- globalData.m_nodeInfo[hostId].m_signalVersion = 0;
-
- if(type == NodeInfo::DB || globalData.theStartLevel >= NodeState::SL_STARTED){
- jam();
-
- /**
- * Inform QMGR that client has connected
- */
-
- signal->theData[0] = hostId;
- sendSignal(QMGR_REF, GSN_CONNECT_REP, signal, 1, JBA);
- } else if(globalData.theStartLevel == NodeState::SL_CMVMI ||
- globalData.theStartLevel == NodeState::SL_STARTING) {
- jam();
- /**
- * Someone connected before start was finished
- */
- if(type == NodeInfo::MGM){
- jam();
- signal->theData[0] = hostId;
- sendSignal(QMGR_REF, GSN_CONNECT_REP, signal, 1, JBA);
- } else {
- /**
- * Dont allow api nodes to connect
- */
- ndbout_c("%d %d %d", hostId, type, globalData.theStartLevel);
- abort();
- globalTransporterRegistry.do_disconnect(hostId);
- }
- }
-
- /* Automatically subscribe events for MGM nodes.
- */
- if(type == NodeInfo::MGM){
- jam();
- globalTransporterRegistry.setIOState(hostId, NoHalt);
- }
-
- //------------------------------------------
- // Also report this event to the Event handler
- //------------------------------------------
- signal->theData[0] = NDB_LE_Connected;
- signal->theData[1] = hostId;
- signal->header.theLength = 2;
-
- execEVENT_REP(signal);
-}
-
-#ifdef VM_TRACE
-void
-modifySignalLogger(bool allBlocks, BlockNumber bno,
- TestOrd::Command cmd,
- TestOrd::SignalLoggerSpecification spec){
- SignalLoggerManager::LogMode logMode;
-
- /**
- * Mapping between SignalLoggerManager::LogMode and
- * TestOrd::SignalLoggerSpecification
- */
- switch(spec){
- case TestOrd::InputSignals:
- logMode = SignalLoggerManager::LogIn;
- break;
- case TestOrd::OutputSignals:
- logMode = SignalLoggerManager::LogOut;
- break;
- case TestOrd::InputOutputSignals:
- logMode = SignalLoggerManager::LogInOut;
- break;
- default:
- return;
- break;
- }
-
- switch(cmd){
- case TestOrd::On:
- globalSignalLoggers.logOn(allBlocks, bno, logMode);
- break;
- case TestOrd::Off:
- globalSignalLoggers.logOff(allBlocks, bno, logMode);
- break;
- case TestOrd::Toggle:
- globalSignalLoggers.logToggle(allBlocks, bno, logMode);
- break;
- case TestOrd::KeepUnchanged:
- // Do nothing
- break;
- }
- globalSignalLoggers.flushSignalLog();
-}
-#endif
-
-void
-Cmvmi::execTEST_ORD(Signal * signal){
- jamEntry();
-
-#ifdef VM_TRACE
- TestOrd * const testOrd = (TestOrd *)&signal->theData[0];
-
- TestOrd::Command cmd;
-
- {
- /**
- * Process Trace command
- */
- TestOrd::TraceSpecification traceSpec;
-
- testOrd->getTraceCommand(cmd, traceSpec);
- unsigned long traceVal = traceSpec;
- unsigned long currentTraceVal = globalSignalLoggers.getTrace();
- switch(cmd){
- case TestOrd::On:
- currentTraceVal |= traceVal;
- break;
- case TestOrd::Off:
- currentTraceVal &= (~traceVal);
- break;
- case TestOrd::Toggle:
- currentTraceVal ^= traceVal;
- break;
- case TestOrd::KeepUnchanged:
- // Do nothing
- break;
- }
- globalSignalLoggers.setTrace(currentTraceVal);
- }
-
- {
- /**
- * Process Log command
- */
- TestOrd::SignalLoggerSpecification logSpec;
- BlockNumber bno;
- unsigned int loggers = testOrd->getNoOfSignalLoggerCommands();
-
- if(loggers == (unsigned)~0){ // Apply command to all blocks
- testOrd->getSignalLoggerCommand(0, bno, cmd, logSpec);
- modifySignalLogger(true, bno, cmd, logSpec);
- } else {
- for(unsigned int i = 0; i<loggers; i++){
- testOrd->getSignalLoggerCommand(i, bno, cmd, logSpec);
- modifySignalLogger(false, bno, cmd, logSpec);
- }
- }
- }
-
- {
- /**
- * Process test command
- */
- testOrd->getTestCommand(cmd);
- switch(cmd){
- case TestOrd::On:{
- SET_GLOBAL_TEST_ON;
- }
- break;
- case TestOrd::Off:{
- SET_GLOBAL_TEST_OFF;
- }
- break;
- case TestOrd::Toggle:{
- TOGGLE_GLOBAL_TEST_FLAG;
- }
- break;
- case TestOrd::KeepUnchanged:
- // Do nothing
- break;
- }
- globalSignalLoggers.flushSignalLog();
- }
-
-#endif
-}
-
-void Cmvmi::execSTOP_ORD(Signal* signal)
-{
- jamEntry();
- globalData.theRestartFlag = perform_stop;
-}//execSTOP_ORD()
-
-void
-Cmvmi::execSTART_ORD(Signal* signal) {
-
- StartOrd * const startOrd = (StartOrd *)&signal->theData[0];
- jamEntry();
-
- Uint32 tmp = startOrd->restartInfo;
- if(StopReq::getPerformRestart(tmp)){
- jam();
- /**
- *
- */
- NdbRestartType type = NRT_Default;
- if(StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
- type = NRT_NoStart_InitialStart;
- if(StopReq::getNoStart(tmp) && !StopReq::getInitialStart(tmp))
- type = NRT_NoStart_Restart;
- if(!StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
- type = NRT_DoStart_InitialStart;
- if(!StopReq::getNoStart(tmp)&&!StopReq::getInitialStart(tmp))
- type = NRT_DoStart_Restart;
- NdbShutdown(NST_Restart, type);
- }
-
- if(globalData.theRestartFlag == system_started){
- jam()
- /**
- * START_ORD received when already started(ignored)
- */
- //ndbout << "START_ORD received when already started(ignored)" << endl;
- return;
- }
-
- if(globalData.theRestartFlag == perform_stop){
- jam()
- /**
- * START_ORD received when stopping(ignored)
- */
- //ndbout << "START_ORD received when stopping(ignored)" << endl;
- return;
- }
-
- if(globalData.theStartLevel == NodeState::SL_NOTHING){
- jam();
- globalData.theStartLevel = NodeState::SL_CMVMI;
- /**
- * Open connections to management servers
- */
- for(unsigned int i = 1; i < MAX_NODES; i++ ){
- if (getNodeInfo(i).m_type == NodeInfo::MGM){
- if(!globalTransporterRegistry.is_connected(i)){
- globalTransporterRegistry.do_connect(i);
- globalTransporterRegistry.setIOState(i, NoHalt);
- }
- }
- }
-
- EXECUTE_DIRECT(QMGR, GSN_START_ORD, signal, 1);
- return ;
- }
-
- if(globalData.theStartLevel == NodeState::SL_CMVMI){
- jam();
-
- if(m_ctx.m_config.lockPagesInMainMemory() == 2)
- {
- int res = NdbMem_MemLockAll(1);
- if(res != 0)
- {
- g_eventLogger.warning("Failed to memlock pages");
- warningEvent("Failed to memlock pages");
- }
- else
- {
- g_eventLogger.info("Locked future allocations");
- }
- }
-
- globalData.theStartLevel = NodeState::SL_STARTING;
- globalData.theRestartFlag = system_started;
- /**
- * StartLevel 1
- *
- * Do Restart
- */
-
- // Disconnect all nodes as part of the system restart.
- // We need to ensure that we are starting up
- // without any connected nodes.
- for(unsigned int i = 1; i < MAX_NODES; i++ ){
- if (i != getOwnNodeId() && getNodeInfo(i).m_type != NodeInfo::MGM){
- globalTransporterRegistry.do_disconnect(i);
- globalTransporterRegistry.setIOState(i, HaltIO);
- }
- }
-
- /**
- * Start running startphases
- */
- sendSignal(NDBCNTR_REF, GSN_START_ORD, signal, 1, JBA);
- return;
- }
-}//execSTART_ORD()
-
-void Cmvmi::execTAMPER_ORD(Signal* signal)
-{
- jamEntry();
- // TODO We should maybe introduce a CONF and REF signal
- // to be able to indicate if we really introduced an error.
-#ifdef ERROR_INSERT
- TamperOrd* const tamperOrd = (TamperOrd*)&signal->theData[0];
- signal->theData[2] = 0;
- signal->theData[1] = tamperOrd->errorNo;
- signal->theData[0] = 5;
- sendSignal(DBDIH_REF, GSN_DIHNDBTAMPER, signal, 3,JBB);
-#endif
-
-}//execTAMPER_ORD()
-
-#ifdef VM_TRACE
-class RefSignalTest {
-public:
- enum ErrorCode {
- OK = 0,
- NF_FakeErrorREF = 7
- };
- Uint32 senderRef;
- Uint32 senderData;
- Uint32 errorCode;
-};
-#endif
-
-
-static int iii;
-
-static
-int
-recurse(char * buf, int loops, int arg){
- char * tmp = (char*)alloca(arg);
- printf("tmp = %p\n", tmp);
- for(iii = 0; iii<arg; iii += 1024){
- tmp[iii] = (iii % 23 + (arg & iii));
- }
-
- if(loops == 0)
- return tmp[345];
- else
- return tmp[arg/loops] + recurse(tmp, loops - 1, arg);
-}
-
-void
-Cmvmi::execDUMP_STATE_ORD(Signal* signal)
-{
-
- sendSignal(QMGR_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(NDBCNTR_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBTC_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBDICT_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBLQH_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBTUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBACC_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(NDBFS_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(BACKUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBUTIL_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(SUMA_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(TRIX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(DBTUX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(LGMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(TSMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(PGMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
-
- /**
- *
- * Here I can dump CMVMI state if needed
- */
- if(signal->theData[0] == 13){
-#if 0
- int loop = 100;
- int len = (10*1024*1024);
- if(signal->getLength() > 1)
- loop = signal->theData[1];
- if(signal->getLength() > 2)
- len = signal->theData[2];
-
- ndbout_c("recurse(%d loop, %dkb per recurse)", loop, len/1024);
- int a = recurse(0, loop, len);
- ndbout_c("after...%d", a);
-#endif
- }
-
- DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
- Uint32 arg = dumpState->args[0];
- if (arg == DumpStateOrd::CmvmiDumpConnections){
- for(unsigned int i = 1; i < MAX_NODES; i++ ){
- const char* nodeTypeStr = "";
- switch(getNodeInfo(i).m_type){
- case NodeInfo::DB:
- nodeTypeStr = "DB";
- break;
- case NodeInfo::API:
- nodeTypeStr = "API";
- break;
- case NodeInfo::MGM:
- nodeTypeStr = "MGM";
- break;
- case NodeInfo::INVALID:
- nodeTypeStr = 0;
- break;
- default:
- nodeTypeStr = "<UNKNOWN>";
- }
-
- if(nodeTypeStr == 0)
- continue;
-
- infoEvent("Connection to %d (%s) %s",
- i,
- nodeTypeStr,
- globalTransporterRegistry.getPerformStateString(i));
- }
- }
-
- if (arg == DumpStateOrd::CmvmiDumpSubscriptions)
- {
- SubscriberPtr ptr;
- subscribers.first(ptr);
- g_eventLogger.info("List subscriptions:");
- while(ptr.i != RNIL)
- {
- g_eventLogger.info("Subscription: %u, nodeId: %u, ref: 0x%x",
- ptr.i, refToNode(ptr.p->blockRef), ptr.p->blockRef);
- for(Uint32 i = 0; i < LogLevel::LOGLEVEL_CATEGORIES; i++)
- {
- Uint32 level = ptr.p->logLevel.getLogLevel((LogLevel::EventCategory)i);
- g_eventLogger.info("Category %u Level %u", i, level);
- }
- subscribers.next(ptr);
- }
- }
-
- if (arg == DumpStateOrd::CmvmiDumpLongSignalMemory){
- infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d",
- g_sectionSegmentPool.getSize(),
- g_sectionSegmentPool.getNoOfFree());
- }
-
- if (dumpState->args[0] == 1000)
- {
- Uint32 len = signal->getLength();
- if (signal->getLength() == 1)
- {
- signal->theData[1] = 0;
- signal->theData[2] = ~0;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
- return;
- }
- Uint32 id = signal->theData[1];
- Resource_limit rl;
- if (!m_ctx.m_mm.get_resource_limit(id, rl))
- len = 2;
- else
- {
- if (rl.m_min || rl.m_curr || rl.m_max)
- infoEvent("Resource %d min: %d max: %d curr: %d",
- id, rl.m_min, rl.m_max, rl.m_curr);
- }
-
- if (len == 3)
- {
- signal->theData[0] = 1000;
- signal->theData[1] = id+1;
- signal->theData[2] = ~0;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
- }
- return;
- }
-
- if (arg == DumpStateOrd::CmvmiSetRestartOnErrorInsert)
- {
- if(signal->getLength() == 1)
- {
- Uint32 val = (Uint32)NRT_NoStart_Restart;
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- if(!ndb_mgm_get_int_parameter(p, CFG_DB_STOP_ON_ERROR_INSERT, &val))
- {
- m_ctx.m_config.setRestartOnErrorInsert(val);
- }
- }
- else
- {
- m_ctx.m_config.setRestartOnErrorInsert(signal->theData[1]);
- }
- }
-
- if (arg == DumpStateOrd::CmvmiTestLongSigWithDelay) {
- unsigned i;
- Uint32 loopCount = dumpState->args[1];
- const unsigned len0 = 11;
- const unsigned len1 = 123;
- Uint32 sec0[len0];
- Uint32 sec1[len1];
- for (i = 0; i < len0; i++)
- sec0[i] = i;
- for (i = 0; i < len1; i++)
- sec1[i] = 16 * i;
- Uint32* sig = signal->getDataPtrSend();
- sig[0] = reference();
- sig[1] = 20; // test type
- sig[2] = 0;
- sig[3] = 0;
- sig[4] = loopCount;
- sig[5] = len0;
- sig[6] = len1;
- sig[7] = 0;
- LinearSectionPtr ptr[3];
- ptr[0].p = sec0;
- ptr[0].sz = len0;
- ptr[1].p = sec1;
- ptr[1].sz = len1;
- sendSignal(reference(), GSN_TESTSIG, signal, 8, JBB, ptr, 2);
- }
-
-#ifdef ERROR_INSERT
- if (arg == 9000 || arg == 9002)
- {
- SET_ERROR_INSERT_VALUE(arg);
- for (Uint32 i = 1; i<signal->getLength(); i++)
- c_error_9000_nodes_mask.set(signal->theData[i]);
- }
-
- if (arg == 9001)
- {
- CLEAR_ERROR_INSERT_VALUE;
- if (signal->getLength() == 1 || signal->theData[1])
- {
- for (Uint32 i = 0; i<MAX_NODES; i++)
- {
- if (c_error_9000_nodes_mask.get(i))
- {
- signal->theData[0] = 0;
- signal->theData[1] = i;
- EXECUTE_DIRECT(CMVMI, GSN_OPEN_COMREQ, signal, 2);
- }
- }
- }
- c_error_9000_nodes_mask.clear();
- }
-#endif
-
-#ifdef VM_TRACE
-#if 0
- {
- SafeCounterManager mgr(* this); mgr.setSize(1);
- SafeCounterHandle handle;
-
- {
- SafeCounter tmp(mgr, handle);
- tmp.init<RefSignalTest>(CMVMI, GSN_TESTSIG, /* senderData */ 13);
- tmp.setWaitingFor(3);
- ndbrequire(!tmp.done());
- ndbout_c("Allocted");
- }
- ndbrequire(!handle.done());
- {
- SafeCounter tmp(mgr, handle);
- tmp.clearWaitingFor(3);
- ndbrequire(tmp.done());
- ndbout_c("Deallocted");
- }
- ndbrequire(handle.done());
- }
-#endif
-#endif
-
- if (arg == 9999)
- {
- Uint32 delay = 1000;
- switch(signal->getLength()){
- case 1:
- break;
- case 2:
- delay = signal->theData[1];
- break;
- default:{
- Uint32 dmin = signal->theData[1];
- Uint32 dmax = signal->theData[2];
- delay = dmin + (rand() % (dmax - dmin));
- break;
- }
- }
-
- signal->theData[0] = 9999;
- if (delay == 0)
- {
- execNDB_TAMPER(signal);
- }
- else if (delay < 10)
- {
- sendSignal(reference(), GSN_NDB_TAMPER, signal, 1, JBB);
- }
- else
- {
- sendSignalWithDelay(reference(), GSN_NDB_TAMPER, signal, delay, 1);
- }
- }
-}//Cmvmi::execDUMP_STATE_ORD()
-
-void
-Cmvmi::execNODE_START_REP(Signal* signal)
-{
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(9002) && signal->theData[0] == getOwnNodeId())
- {
- signal->theData[0] = 9001;
- execDUMP_STATE_ORD(signal);
- }
-#endif
-}
-
-BLOCK_FUNCTIONS(Cmvmi)
-
-static Uint32 g_print;
-static LinearSectionPtr g_test[3];
-
-void
-Cmvmi::execTESTSIG(Signal* signal){
- Uint32 i;
- /**
- * Test of SafeCounter
- */
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- Uint32 ref = signal->theData[0];
- Uint32 testType = signal->theData[1];
- Uint32 fragmentLength = signal->theData[2];
- g_print = signal->theData[3];
-// Uint32 returnCount = signal->theData[4];
- Uint32 * secSizes = &signal->theData[5];
-
- if(g_print){
- SignalLoggerManager::printSignalHeader(stdout,
- signal->header,
- 0,
- getOwnNodeId(),
- true);
- ndbout_c("-- Fixed section --");
- for(i = 0; i<signal->length(); i++){
- fprintf(stdout, "H'0x%.8x ", signal->theData[i]);
- if(((i + 1) % 6) == 0)
- fprintf(stdout, "\n");
- }
- fprintf(stdout, "\n");
-
- for(i = 0; i<signal->header.m_noOfSections; i++){
- SegmentedSectionPtr ptr(0,0,0);
- ndbout_c("-- Section %d --", i);
- signal->getSection(ptr, i);
- ndbrequire(ptr.p != 0);
- print(ptr, stdout);
- ndbrequire(ptr.sz == secSizes[i]);
- }
- }
-
- /**
- * Validate length:s
- */
- for(i = 0; i<signal->header.m_noOfSections; i++){
- SegmentedSectionPtr ptr;
- signal->getSection(ptr, i);
- ndbrequire(ptr.p != 0);
- ndbrequire(ptr.sz == secSizes[i]);
- }
-
- /**
- * Testing send with delay.
- */
- if (testType == 20) {
- if (signal->theData[4] == 0) {
- releaseSections(signal);
- return;
- }
- signal->theData[4]--;
- sendSignalWithDelay(reference(), GSN_TESTSIG, signal, 100, 8);
- return;
- }
-
- NodeReceiverGroup rg(CMVMI, c_dbNodes);
-
- if(signal->getSendersBlockRef() == ref){
- /**
- * Signal from API (not via NodeReceiverGroup)
- */
- if((testType % 2) == 1){
- signal->theData[4] = 1;
- } else {
- signal->theData[1] --;
- signal->theData[4] = rg.m_nodes.count();
- }
- }
-
- switch(testType){
- case 1:
- sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB);
- break;
- case 2:
- sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB);
- break;
- case 3:
- case 4:{
- LinearSectionPtr ptr[3];
- const Uint32 secs = signal->getNoOfSections();
- for(i = 0; i<secs; i++){
- SegmentedSectionPtr sptr(0,0,0);
- signal->getSection(sptr, i);
- ptr[i].sz = sptr.sz;
- ptr[i].p = new Uint32[sptr.sz];
- copy(ptr[i].p, sptr);
- }
-
- if(testType == 3){
- sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB, ptr, secs);
- } else {
- sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB, ptr, secs);
- }
- for(Uint32 i = 0; i<secs; i++){
- delete[] ptr[i].p;
- }
- break;
- }
- case 5:
- case 6:{
-
- NodeReceiverGroup tmp;
- if(testType == 5){
- tmp = ref;
- } else {
- tmp = rg;
- }
-
- FragmentSendInfo fragSend;
- sendFirstFragment(fragSend,
- tmp,
- GSN_TESTSIG,
- signal,
- signal->length(),
- JBB,
- fragmentLength);
- int count = 1;
- while(fragSend.m_status != FragmentSendInfo::SendComplete){
- count++;
- if(g_print)
- ndbout_c("Sending fragment %d", count);
- sendNextSegmentedFragment(signal, fragSend);
- }
- break;
- }
- case 7:
- case 8:{
- LinearSectionPtr ptr[3];
- const Uint32 secs = signal->getNoOfSections();
- for(i = 0; i<secs; i++){
- SegmentedSectionPtr sptr(0,0,0);
- signal->getSection(sptr, i);
- ptr[i].sz = sptr.sz;
- ptr[i].p = new Uint32[sptr.sz];
- copy(ptr[i].p, sptr);
- }
-
- NodeReceiverGroup tmp;
- if(testType == 7){
- tmp = ref;
- } else {
- tmp = rg;
- }
-
- FragmentSendInfo fragSend;
- sendFirstFragment(fragSend,
- tmp,
- GSN_TESTSIG,
- signal,
- signal->length(),
- JBB,
- ptr,
- secs,
- fragmentLength);
-
- int count = 1;
- while(fragSend.m_status != FragmentSendInfo::SendComplete){
- count++;
- if(g_print)
- ndbout_c("Sending fragment %d", count);
- sendNextLinearFragment(signal, fragSend);
- }
-
- for(i = 0; i<secs; i++){
- delete[] ptr[i].p;
- }
- break;
- }
- case 9:
- case 10:{
-
- Callback m_callBack;
- m_callBack.m_callbackFunction =
- safe_cast(&Cmvmi::sendFragmentedComplete);
-
- if(testType == 9){
- m_callBack.m_callbackData = 9;
- sendFragmentedSignal(ref,
- GSN_TESTSIG, signal, signal->length(), JBB,
- m_callBack,
- fragmentLength);
- } else {
- m_callBack.m_callbackData = 10;
- sendFragmentedSignal(rg,
- GSN_TESTSIG, signal, signal->length(), JBB,
- m_callBack,
- fragmentLength);
- }
- break;
- }
- case 11:
- case 12:{
-
- const Uint32 secs = signal->getNoOfSections();
- memset(g_test, 0, sizeof(g_test));
- for(i = 0; i<secs; i++){
- SegmentedSectionPtr sptr(0,0,0);
- signal->getSection(sptr, i);
- g_test[i].sz = sptr.sz;
- g_test[i].p = new Uint32[sptr.sz];
- copy(g_test[i].p, sptr);
- }
-
-
- Callback m_callBack;
- m_callBack.m_callbackFunction =
- safe_cast(&Cmvmi::sendFragmentedComplete);
-
- if(testType == 11){
- m_callBack.m_callbackData = 11;
- sendFragmentedSignal(ref,
- GSN_TESTSIG, signal, signal->length(), JBB,
- g_test, secs,
- m_callBack,
- fragmentLength);
- } else {
- m_callBack.m_callbackData = 12;
- sendFragmentedSignal(rg,
- GSN_TESTSIG, signal, signal->length(), JBB,
- g_test, secs,
- m_callBack,
- fragmentLength);
- }
- break;
- }
- case 13:{
- ndbrequire(signal->getNoOfSections() == 0);
- Uint32 loop = signal->theData[9];
- if(loop > 0){
- signal->theData[9] --;
- sendSignal(CMVMI_REF, GSN_TESTSIG, signal, signal->length(), JBB);
- return;
- }
- sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB);
- return;
- }
- case 14:{
- Uint32 count = signal->theData[8];
- signal->theData[10] = count * rg.m_nodes.count();
- for(i = 0; i<count; i++){
- sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB);
- }
- return;
- }
-
- default:
- ndbrequire(false);
- }
- return;
-}
-
-void
-Cmvmi::sendFragmentedComplete(Signal* signal, Uint32 data, Uint32 returnCode){
- if(g_print)
- ndbout_c("sendFragmentedComplete: %d", data);
- if(data == 11 || data == 12){
- for(Uint32 i = 0; i<3; i++){
- if(g_test[i].p != 0)
- delete[] g_test[i].p;
- }
- }
-}
diff --git a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
deleted file mode 100644
index 8e4f140ea4d..00000000000
--- a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef Cmvmi_H_
-#define Cmvmi_H_
-
-#include <pc.hpp>
-#include <SimulatedBlock.hpp>
-#include <LogLevel.hpp>
-
-#include <DLList.hpp>
-
-/**
- * Cmvmi class
- */
-class Cmvmi : public SimulatedBlock {
-public:
- Cmvmi(Block_context&);
- virtual ~Cmvmi();
-
-private:
- /**
- * These methods used to be reportXXX
- *
- * But they in a nasty way intefere with the execution model
- * they been turned in to exec-Method used via prio A signals
- */
- void execDISCONNECT_REP(Signal*);
- void execCONNECT_REP(Signal*);
-
-private:
- BLOCK_DEFINES(Cmvmi);
-
- // The signal processing functions
- 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);
- void execOPEN_COMREQ(Signal* signal);
- void execSIZEALT_ACK(Signal* signal);
- void execTEST_ORD(Signal* signal);
-
- void execSTOP_ORD(Signal* signal);
- void execSTART_ORD(Signal* signal);
- void execTAMPER_ORD(Signal* signal);
-
- void execDUMP_STATE_ORD(Signal* signal);
-
- void execEVENT_SUBSCRIBE_REQ(Signal *);
- void cancelSubscription(NodeId nodeId);
-
- void execTESTSIG(Signal* signal);
- void execNODE_START_REP(Signal* signal);
-
- char theErrorMessage[256];
- void sendSTTORRY(Signal* signal);
-
- LogLevel clogLevel;
- NdbNodeBitmask c_dbNodes;
-
- /**
- * This struct defines the data needed for a EVENT_REP subscriber
- */
- struct EventRepSubscriber {
- /**
- * What log level is the subscriber using
- */
- LogLevel logLevel;
-
- /**
- * What block reference does he use
- * (Where should the EVENT_REP's be forwarded)
- */
- BlockReference blockRef;
-
- /**
- * Next ptr (used in pool/list)
- */
- union { Uint32 nextPool; Uint32 nextList; };
- Uint32 prevList;
- };
- typedef Ptr<EventRepSubscriber> SubscriberPtr;
-
- /**
- * Pool of EventRepSubscriber record
- */
- ArrayPool<EventRepSubscriber> subscriberPool;
-
- /**
- * List of current subscribers
- */
- DLList<EventRepSubscriber> subscribers;
-
-private:
- // Declared but not defined
- Cmvmi(const Cmvmi &obj);
- void operator = (const Cmvmi &);
-
- void sendFragmentedComplete(Signal* signal, Uint32 data, Uint32 returnCode);
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
deleted file mode 100644
index 267fc2ec8ef..00000000000
--- a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ /dev/null
@@ -1,1106 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBACC_H
-#define DBACC_H
-
-#ifdef VM_TRACE
-#define ACC_SAFE_QUEUE
-#endif
-
-#include <pc.hpp>
-#include <SimulatedBlock.hpp>
-
-#ifdef DBACC_C
-// Debug Macros
-#define dbgWord32(ptr, ind, val)
-
-/*
-#define dbgWord32(ptr, ind, val) \
-if(debug_jan){ \
-tmp_val = val; \
-switch(ind){ \
-case 1: strcpy(tmp_string, "ZPOS_PAGE_TYPE "); \
-break; \
-case 2: strcpy(tmp_string, "ZPOS_NO_ELEM_IN_PAGE"); \
-break; \
-case 3: strcpy(tmp_string, "ZPOS_CHECKSUM "); \
-break; \
-case 4: strcpy(tmp_string, "ZPOS_OVERFLOWREC "); \
-break; \
-case 5: strcpy(tmp_string, "ZPOS_FREE_AREA_IN_PAGE"); \
-break; \
-case 6: strcpy(tmp_string, "ZPOS_LAST_INDEX "); \
-break; \
-case 7: strcpy(tmp_string, "ZPOS_INSERT_INDEX "); \
-break; \
-case 8: strcpy(tmp_string, "ZPOS_ARRAY_POS "); \
-break; \
-case 9: strcpy(tmp_string, "ZPOS_NEXT_FREE_INDEX"); \
-break; \
-case 10: strcpy(tmp_string, "ZPOS_NEXT_PAGE "); \
-break; \
-case 11: strcpy(tmp_string, "ZPOS_PREV_PAGE "); \
-break; \
-default: sprintf(tmp_string, "%-20d", ind);\
-} \
-ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: " << tmp_val << " \tLINE: " << __LINE__ << endl; \
-}\
-*/
-
-// Constants
-/** ------------------------------------------------------------------------
- * THESE ARE CONSTANTS THAT ARE USED FOR DEFINING THE SIZE OF BUFFERS, THE
- * SIZE OF PAGE HEADERS, THE NUMBER OF BUFFERS IN A PAGE AND A NUMBER OF
- * OTHER CONSTANTS WHICH ARE CHANGED WHEN THE BUFFER SIZE IS CHANGED.
- * ----------------------------------------------------------------------- */
-#define ZHEAD_SIZE 32
-#define ZCON_HEAD_SIZE 2
-#define ZBUF_SIZE 28
-#define ZEMPTYLIST 72
-#define ZUP_LIMIT 14
-#define ZDOWN_LIMIT 12
-#define ZSHIFT_PLUS 5
-#define ZSHIFT_MINUS 2
-#define ZFREE_LIMIT 65
-#define ZNO_CONTAINERS 64
-#define ZELEM_HEAD_SIZE 1
-/* ------------------------------------------------------------------------- */
-/* THESE CONSTANTS DEFINE THE USE OF THE PAGE HEADER IN THE INDEX PAGES. */
-/* ------------------------------------------------------------------------- */
-#define ZPOS_PAGE_ID 0
-#define ZPOS_PAGE_TYPE 1
-#define ZPOS_PAGE_TYPE_BIT 14
-#define ZPOS_EMPTY_LIST 1
-#define ZPOS_ALLOC_CONTAINERS 2
-#define ZPOS_CHECKSUM 3
-#define ZPOS_OVERFLOWREC 4
-#define ZPOS_NO_ELEM_IN_PAGE 2
-#define ZPOS_FREE_AREA_IN_PAGE 5
-#define ZPOS_LAST_INDEX 6
-#define ZPOS_INSERT_INDEX 7
-#define ZPOS_ARRAY_POS 8
-#define ZPOS_NEXT_FREE_INDEX 9
-#define ZPOS_NEXT_PAGE 10
-#define ZPOS_PREV_PAGE 11
-#define ZNORMAL_PAGE_TYPE 0
-#define ZOVERFLOW_PAGE_TYPE 1
-#define ZDEFAULT_LIST 3
-#define ZWORDS_IN_PAGE 2048
-#define ZADDFRAG 0
-#define ZDIRARRAY 68
-#define ZDIRRANGESIZE 65
-//#define ZEMPTY_FRAGMENT 0
-#define ZFRAGMENTSIZE 64
-#define ZFIRSTTIME 1
-#define ZFS_CONNECTSIZE 300
-#define ZFS_OPSIZE 100
-#define ZKEYINKEYREQ 4
-#define ZLEFT 1
-#define ZLOCALLOGFILE 2
-#define ZLOCKED 0
-#define ZMAXSCANSIGNALLEN 20
-#define ZMAINKEYLEN 8
-#define ZNO_OF_DISK_VERSION 3
-#define ZNO_OF_OP_PER_SIGNAL 20
-//#define ZNOT_EMPTY_FRAGMENT 1
-#define ZOP_HEAD_INFO_LN 3
-#define ZOPRECSIZE 740
-#define ZOVERFLOWRECSIZE 5
-#define ZPAGE8_BASE_ADD 1
-#define ZPAGESIZE 128
-#define ZPARALLEL_QUEUE 1
-#define ZPDIRECTORY 1
-#define ZSCAN_MAX_LOCK 4
-#define ZSERIAL_QUEUE 2
-#define ZSPH1 1
-#define ZSPH2 2
-#define ZSPH3 3
-#define ZSPH6 6
-#define ZREADLOCK 0
-#define ZRIGHT 2
-#define ZROOTFRAGMENTSIZE 32
-#define ZSCAN_LOCK_ALL 3
-/**
- * Check kernel_types for other operation types
- */
-#define ZSCAN_OP 6
-#define ZSCAN_REC_SIZE 256
-#define ZSTAND_BY 2
-#define ZTABLESIZE 16
-#define ZTABMAXINDEX 3
-#define ZUNDEFINED_OP 6
-#define ZUNLOCKED 1
-
-/* --------------------------------------------------------------------------------- */
-/* CONTINUEB CODES */
-/* --------------------------------------------------------------------------------- */
-#define ZINITIALISE_RECORDS 1
-#define ZSEND_SCAN_HBREP 4
-#define ZREL_ROOT_FRAG 5
-#define ZREL_FRAG 6
-#define ZREL_DIR 7
-#define ZREPORT_MEMORY_USAGE 8
-
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES */
-/* ------------------------------------------------------------------------- */
-#define ZLIMIT_OF_ERROR 600 // Limit check for error codes
-#define ZCHECKROOT_ERROR 601 // Delete fragment error code
-#define ZCONNECT_SIZE_ERROR 602 // ACC_SEIZEREF
-#define ZDIR_RANGE_ERROR 603 // Add fragment error code
-#define ZFULL_FRAGRECORD_ERROR 604 // Add fragment error code
-#define ZFULL_ROOTFRAGRECORD_ERROR 605 // Add fragment error code
-#define ZROOTFRAG_STATE_ERROR 606 // Add fragment
-#define ZOVERTAB_REC_ERROR 607 // Add fragment
-
-#define ZSCAN_REFACC_CONNECT_ERROR 608 // ACC_SCANREF
-#define ZFOUR_ACTIVE_SCAN_ERROR 609 // ACC_SCANREF
-#define ZNULL_SCAN_REC_ERROR 610 // ACC_SCANREF
-
-#define ZDIRSIZE_ERROR 623
-#define ZOVER_REC_ERROR 624 // Insufficient Space
-#define ZPAGESIZE_ERROR 625
-#define ZTUPLE_DELETED_ERROR 626
-#define ZREAD_ERROR 626
-#define ZWRITE_ERROR 630
-#define ZTO_OP_STATE_ERROR 631
-#define ZTOO_EARLY_ACCESS_ERROR 632
-#endif
-
-class ElementHeader {
- /**
- *
- * l = Locked -- If true contains operation else scan bits + hash value
- * s = Scan bits
- * h = Hash value
- * o = Operation ptr I
- *
- * 1111111111222222222233
- * 01234567890123456789012345678901
- * lssssssssssss hhhhhhhhhhhhhhhh
- * ooooooooooooooooooooooooooooooo
- */
-public:
- STATIC_CONST( HASH_VALUE_PART_MASK = 0xFFFF );
-
- static bool getLocked(Uint32 data);
- static bool getUnlocked(Uint32 data);
- static Uint32 getScanBits(Uint32 data);
- static Uint32 getHashValuePart(Uint32 data);
- static Uint32 getOpPtrI(Uint32 data);
-
- static Uint32 setLocked(Uint32 opPtrI);
- static Uint32 setUnlocked(Uint32 hashValuePart, Uint32 scanBits);
- static Uint32 setScanBit(Uint32 header, Uint32 scanBit);
- static Uint32 clearScanBit(Uint32 header, Uint32 scanBit);
-};
-
-inline
-bool
-ElementHeader::getLocked(Uint32 data){
- return (data & 1) == 0;
-}
-
-inline
-bool
-ElementHeader::getUnlocked(Uint32 data){
- return (data & 1) == 1;
-}
-
-inline
-Uint32
-ElementHeader::getScanBits(Uint32 data){
- assert(getUnlocked(data));
- return (data >> 1) & ((1 << MAX_PARALLEL_SCANS_PER_FRAG) - 1);
-}
-
-inline
-Uint32
-ElementHeader::getHashValuePart(Uint32 data){
- assert(getUnlocked(data));
- return data >> 16;
-}
-
-inline
-Uint32
-ElementHeader::getOpPtrI(Uint32 data){
- assert(getLocked(data));
- return data >> 1;
-}
-
-inline
-Uint32
-ElementHeader::setLocked(Uint32 opPtrI){
- return (opPtrI << 1) + 0;
-}
-inline
-Uint32
-ElementHeader::setUnlocked(Uint32 hashValue, Uint32 scanBits){
- return (hashValue << 16) + (scanBits << 1) + 1;
-}
-
-inline
-Uint32
-ElementHeader::setScanBit(Uint32 header, Uint32 scanBit){
- assert(getUnlocked(header));
- return header | (scanBit << 1);
-}
-
-inline
-Uint32
-ElementHeader::clearScanBit(Uint32 header, Uint32 scanBit){
- assert(getUnlocked(header));
- return header & (~(scanBit << 1));
-}
-
-
-class Dbacc: public SimulatedBlock {
-public:
-// State values
-enum State {
- FREEFRAG = 0,
- ACTIVEFRAG = 1,
- //SEND_QUE_OP = 2,
- WAIT_NOTHING = 10,
- WAIT_ONE_CONF = 26,
- FREE_OP = 30,
- WAIT_EXE_OP = 32,
- WAIT_IN_QUEUE = 34,
- EXE_OP = 35,
- SCAN_ACTIVE = 36,
- SCAN_WAIT_IN_QUEUE = 37,
- IDLE = 39,
- ACTIVE = 40,
- WAIT_COMMIT_ABORT = 41,
- ABORT = 42,
- ABORTADDFRAG = 43,
- REFUSEADDFRAG = 44,
- DELETEFRAG = 45,
- DELETETABLE = 46,
- UNDEFINEDROOT = 47,
- ADDFIRSTFRAG = 48,
- ADDSECONDFRAG = 49,
- DELETEFIRSTFRAG = 50,
- DELETESECONDFRAG = 51,
- ACTIVEROOT = 52
-};
-
-// Records
-
-/* --------------------------------------------------------------------------------- */
-/* DIRECTORY RANGE */
-/* --------------------------------------------------------------------------------- */
- struct DirRange {
- Uint32 dirArray[256];
- }; /* p2c: size = 1024 bytes */
-
- typedef Ptr<DirRange> DirRangePtr;
-
-/* --------------------------------------------------------------------------------- */
-/* DIRECTORYARRAY */
-/* --------------------------------------------------------------------------------- */
-struct Directoryarray {
- Uint32 pagep[256];
-}; /* p2c: size = 1024 bytes */
-
- typedef Ptr<Directoryarray> DirectoryarrayPtr;
-
-/* --------------------------------------------------------------------------------- */
-/* FRAGMENTREC. ALL INFORMATION ABOUT FRAMENT AND HASH TABLE IS SAVED IN FRAGMENT */
-/* REC A POINTER TO FRAGMENT RECORD IS SAVED IN ROOTFRAGMENTREC FRAGMENT */
-/* --------------------------------------------------------------------------------- */
-struct Fragmentrec {
- Uint32 scan[MAX_PARALLEL_SCANS_PER_FRAG];
- union {
- Uint32 mytabptr;
- Uint32 myTableId;
- };
- union {
- Uint32 fragmentid;
- Uint32 myfid;
- };
- Uint32 roothashcheck;
- Uint32 noOfElements;
- Uint32 m_commit_count;
- State rootState;
-
-//-----------------------------------------------------------------------------
-// These variables keep track of allocated pages, the number of them and the
-// start file page of them. Used during local checkpoints.
-//-----------------------------------------------------------------------------
- Uint32 datapages[8];
- Uint32 activeDataPage;
-
-//-----------------------------------------------------------------------------
-// Temporary variables used during shrink and expand process.
-//-----------------------------------------------------------------------------
- Uint32 expReceivePageptr;
- Uint32 expReceiveIndex;
- Uint32 expReceiveForward;
- Uint32 expSenderDirIndex;
- Uint32 expSenderDirptr;
- Uint32 expSenderIndex;
- Uint32 expSenderPageptr;
-
-//-----------------------------------------------------------------------------
-// List of lock owners and list of lock waiters to support LCP handling
-//-----------------------------------------------------------------------------
- Uint32 lockOwnersList;
-
-//-----------------------------------------------------------------------------
-// References to Directory Ranges (which in turn references directories, which
-// in its turn references the pages) for the bucket pages and the overflow
-// bucket pages.
-//-----------------------------------------------------------------------------
- Uint32 directory;
- Uint32 dirsize;
- Uint32 overflowdir;
- Uint32 lastOverIndex;
-
-//-----------------------------------------------------------------------------
-// We have a list of overflow pages with free areas. We have a special record,
-// the overflow record representing these pages. The reason is that the
-// same record is also used to represent pages in the directory array that have
-// been released since they were empty (there were however higher indexes with
-// data in them). These are put in the firstFreeDirIndexRec-list.
-// An overflow record representing a page can only be in one of these lists.
-//-----------------------------------------------------------------------------
- Uint32 firstOverflowRec;
- Uint32 lastOverflowRec;
- Uint32 firstFreeDirindexRec;
-
-//-----------------------------------------------------------------------------
-// Counter keeping track of how many times we have expanded. We need to ensure
-// that we do not shrink so many times that this variable becomes negative.
-//-----------------------------------------------------------------------------
- Uint32 expandCounter;
-
-//-----------------------------------------------------------------------------
-// These variables are important for the linear hashing algorithm.
-// localkeylen is the size of the local key (1 and 2 is currently supported)
-// maxloadfactor is the factor specifying when to expand
-// minloadfactor is the factor specifying when to shrink (hysteresis model)
-// maxp and p
-// maxp and p is the variables most central to linear hashing. p + maxp + 1 is the
-// current number of buckets. maxp is the largest value of the type 2**n - 1
-// which is smaller than the number of buckets. These values are used to find
-// correct bucket with the aid of the hash value.
-//
-// slack is the variable keeping track of whether we have inserted more than
-// the current size is suitable for or less. Slack together with the boundaries
-// set by maxloadfactor and minloadfactor decides when to expand/shrink
-// slackCheck When slack goes over this value it is time to expand.
-// slackCheck = (maxp + p + 1)*(maxloadfactor - minloadfactor) or
-// bucketSize * hysteresis
-//-----------------------------------------------------------------------------
- Uint32 localkeylen;
- Uint32 maxp;
- Uint32 maxloadfactor;
- Uint32 minloadfactor;
- Uint32 p;
- Uint32 slack;
- Uint32 slackCheck;
-
-//-----------------------------------------------------------------------------
-// nextfreefrag is the next free fragment if linked into a free list
-//-----------------------------------------------------------------------------
- Uint32 nextfreefrag;
-
-//-----------------------------------------------------------------------------
-// This variable is used during restore to keep track of page id of read pages.
-// During read of bucket pages this is used to calculate the page id and also
-// to verify that the page id of the read page is correct. During read of over-
-// flow pages it is only used to keep track of the number of pages read.
-//-----------------------------------------------------------------------------
- Uint32 nextAllocPage;
-
-//-----------------------------------------------------------------------------
-// Number of pages read from file during restore
-//-----------------------------------------------------------------------------
- Uint32 noOfExpectedPages;
-
-//-----------------------------------------------------------------------------
-// Fragment State, mostly applicable during LCP and restore
-//-----------------------------------------------------------------------------
- State fragState;
-
-//-----------------------------------------------------------------------------
-// elementLength: Length of element in bucket and overflow pages
-// keyLength: Length of key
-//-----------------------------------------------------------------------------
- Uint8 elementLength;
- Uint16 keyLength;
-
-//-----------------------------------------------------------------------------
-// This flag is used to avoid sending a big number of expand or shrink signals
-// when simultaneously committing many inserts or deletes.
-//-----------------------------------------------------------------------------
- Uint8 expandFlag;
-
-//-----------------------------------------------------------------------------
-// hashcheckbit is the bit to check whether to send element to split bucket or not
-// k (== 6) is the number of buckets per page
-// lhfragbits is the number of bits used to calculate the fragment id
-// lhdirbits is the number of bits used to calculate the page id
-//-----------------------------------------------------------------------------
- Uint8 hashcheckbit;
- Uint8 k;
- Uint8 lhfragbits;
- Uint8 lhdirbits;
-
-//-----------------------------------------------------------------------------
-// nodetype can only be STORED in this release. Is currently only set, never read
-//-----------------------------------------------------------------------------
- Uint8 nodetype;
-
-//-----------------------------------------------------------------------------
-// flag to avoid accessing table record if no char attributes
-//-----------------------------------------------------------------------------
- Uint8 hasCharAttr;
-};
-
- typedef Ptr<Fragmentrec> FragmentrecPtr;
-
-/* --------------------------------------------------------------------------------- */
-/* OPERATIONREC */
-/* --------------------------------------------------------------------------------- */
-struct Operationrec {
- Uint32 m_op_bits;
- Uint32 localdata[2];
- Uint32 elementIsforward;
- Uint32 elementPage;
- Uint32 elementPointer;
- Uint32 fid;
- Uint32 fragptr;
- Uint32 hashvaluePart;
- Uint32 hashValue;
- Uint32 nextLockOwnerOp;
- Uint32 nextOp;
- Uint32 nextParallelQue;
- union {
- Uint32 nextSerialQue;
- Uint32 m_lock_owner_ptr_i; // if nextParallelQue = RNIL, else undefined
- };
- Uint32 prevOp;
- Uint32 prevLockOwnerOp;
- union {
- Uint32 prevParallelQue;
- Uint32 m_lo_last_parallel_op_ptr_i;
- };
- union {
- Uint32 prevSerialQue;
- Uint32 m_lo_last_serial_op_ptr_i;
- };
- Uint32 scanRecPtr;
- Uint32 transId1;
- Uint32 transId2;
- Uint32 userptr;
- Uint16 elementContainer;
- Uint16 tupkeylen;
- Uint32 xfrmtupkeylen;
- Uint32 userblockref;
- Uint32 scanBits;
-
- enum OpBits {
- OP_MASK = 0x0000F // 4 bits for operation type
- ,OP_LOCK_MODE = 0x00010 // 0 - shared lock, 1 = exclusive lock
- ,OP_ACC_LOCK_MODE = 0x00020 // Or:de lock mode of all operation
- // before me
- ,OP_LOCK_OWNER = 0x00040
- ,OP_RUN_QUEUE = 0x00080 // In parallell queue of lock owner
- ,OP_DIRTY_READ = 0x00100
- ,OP_LOCK_REQ = 0x00200 // isAccLockReq
- ,OP_COMMIT_DELETE_CHECK = 0x00400
- ,OP_INSERT_IS_DONE = 0x00800
- ,OP_ELEMENT_DISAPPEARED = 0x01000
-
- ,OP_STATE_MASK = 0xF0000
- ,OP_STATE_IDLE = 0xF0000
- ,OP_STATE_WAITING = 0x00000
- ,OP_STATE_RUNNING = 0x10000
- ,OP_STATE_EXECUTED = 0x30000
-
- ,OP_EXECUTED_DIRTY_READ = 0x3050F
- ,OP_INITIAL = ~(Uint32)0
- };
-
- Operationrec() {}
- bool is_same_trans(const Operationrec* op) const {
- return
- transId1 == op->transId1 && transId2 == op->transId2;
- }
-
-}; /* p2c: size = 168 bytes */
-
- typedef Ptr<Operationrec> OperationrecPtr;
-
-/* --------------------------------------------------------------------------------- */
-/* OVERFLOW_RECORD */
-/* --------------------------------------------------------------------------------- */
-struct OverflowRecord {
- Uint32 dirindex;
- Uint32 nextOverRec;
- Uint32 nextOverList;
- Uint32 prevOverRec;
- Uint32 prevOverList;
- Uint32 overpage;
- Uint32 nextfreeoverrec;
-};
-
- typedef Ptr<OverflowRecord> OverflowRecordPtr;
-
-/* --------------------------------------------------------------------------------- */
-/* PAGE8 */
-/* --------------------------------------------------------------------------------- */
-struct Page8 {
- Uint32 word32[2048];
-}; /* p2c: size = 8192 bytes */
-
- typedef Ptr<Page8> Page8Ptr;
-
-/* --------------------------------------------------------------------------------- */
-/* SCAN_REC */
-/* --------------------------------------------------------------------------------- */
-struct ScanRec {
- enum ScanState {
- WAIT_NEXT,
- SCAN_DISCONNECT
- };
- enum ScanBucketState {
- FIRST_LAP,
- SECOND_LAP,
- SCAN_COMPLETED
- };
- Uint32 activeLocalFrag;
- Uint32 nextBucketIndex;
- Uint32 scanNextfreerec;
- Uint32 scanFirstActiveOp;
- Uint32 scanFirstLockedOp;
- Uint32 scanLastLockedOp;
- Uint32 scanFirstQueuedOp;
- Uint32 scanLastQueuedOp;
- Uint32 scanUserptr;
- Uint32 scanTrid1;
- Uint32 scanTrid2;
- Uint32 startNoOfBuckets;
- Uint32 minBucketIndexToRescan;
- Uint32 maxBucketIndexToRescan;
- Uint32 scanOpsAllocated;
- ScanBucketState scanBucketState;
- ScanState scanState;
- Uint16 scanLockHeld;
- Uint32 scanUserblockref;
- Uint32 scanMask;
- Uint8 scanLockMode;
- Uint8 scanTimer;
- Uint8 scanContinuebCounter;
- Uint8 scanReadCommittedFlag;
-};
-
- typedef Ptr<ScanRec> ScanRecPtr;
-
-
-/* --------------------------------------------------------------------------------- */
-/* TABREC */
-/* --------------------------------------------------------------------------------- */
-struct Tabrec {
- Uint32 fragholder[MAX_FRAG_PER_NODE];
- Uint32 fragptrholder[MAX_FRAG_PER_NODE];
- Uint32 tabUserPtr;
- BlockReference tabUserRef;
-};
- typedef Ptr<Tabrec> TabrecPtr;
-
-public:
- Dbacc(Block_context&);
- virtual ~Dbacc();
-
- // pointer to TUP instance in this thread
- class Dbtup* c_tup;
- class Dblqh* c_lqh;
-
- void execACCMINUPDATE(Signal* signal);
-
-private:
- BLOCK_DEFINES(Dbacc);
-
- // Transit signals
- void execDEBUG_SIG(Signal* signal);
- void execCONTINUEB(Signal* signal);
- void execACC_CHECK_SCAN(Signal* signal);
- void execEXPANDCHECK2(Signal* signal);
- void execSHRINKCHECK2(Signal* signal);
- void execACC_OVER_REC(Signal* signal);
- void execNEXTOPERATION(Signal* signal);
- void execREAD_PSEUDO_REQ(Signal* signal);
-
- // Received signals
- void execSTTOR(Signal* signal);
- void execACCKEYREQ(Signal* signal);
- void execACCSEIZEREQ(Signal* signal);
- void execACCFRAGREQ(Signal* signal);
- void execNEXT_SCANREQ(Signal* signal);
- void execACC_ABORTREQ(Signal* signal);
- void execACC_SCANREQ(Signal* signal);
- void execACC_COMMITREQ(Signal* signal);
- void execACC_TO_REQ(Signal* signal);
- void execACC_LOCKREQ(Signal* signal);
- void execNDB_STTOR(Signal* signal);
- void execDROP_TAB_REQ(Signal* signal);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execDUMP_STATE_ORD(Signal* signal);
-
- // Statement blocks
- void ACCKEY_error(Uint32 fromWhere);
-
- void commitDeleteCheck();
- void report_dealloc(Signal* signal, const Operationrec* opPtrP);
-
- typedef void * RootfragmentrecPtr;
- void initRootFragPageZero(FragmentrecPtr, Page8Ptr);
- void initFragAdd(Signal*, FragmentrecPtr);
- void initFragPageZero(FragmentrecPtr, Page8Ptr);
- void initFragGeneral(FragmentrecPtr);
- void verifyFragCorrect(FragmentrecPtr regFragPtr);
- void releaseFragResources(Signal* signal, Uint32 fragIndex);
- void releaseRootFragRecord(Signal* signal, RootfragmentrecPtr rootPtr);
- void releaseRootFragResources(Signal* signal, Uint32 tableId);
- void releaseDirResources(Signal* signal,
- Uint32 fragIndex,
- Uint32 dirIndex,
- Uint32 startIndex);
- void releaseDirectoryResources(Signal* signal,
- Uint32 fragIndex,
- Uint32 dirIndex,
- Uint32 startIndex,
- Uint32 directoryIndex);
- void releaseOverflowResources(Signal* signal, FragmentrecPtr regFragPtr);
- void releaseDirIndexResources(Signal* signal, FragmentrecPtr regFragPtr);
- void releaseFragRecord(Signal* signal, FragmentrecPtr regFragPtr);
- void initScanFragmentPart(Signal* signal);
- Uint32 checkScanExpand(Signal* signal);
- Uint32 checkScanShrink(Signal* signal);
- void initialiseDirRec(Signal* signal);
- void initialiseDirRangeRec(Signal* signal);
- void initialiseFragRec(Signal* signal);
- void initialiseFsConnectionRec(Signal* signal);
- void initialiseFsOpRec(Signal* signal);
- void initialiseOperationRec(Signal* signal);
- void initialiseOverflowRec(Signal* signal);
- void initialisePageRec(Signal* signal);
- void initialiseRootfragRec(Signal* signal);
- void initialiseScanRec(Signal* signal);
- void initialiseTableRec(Signal* signal);
- bool addfragtotab(Signal* signal, Uint32 rootIndex, Uint32 fragId);
- void initOpRec(Signal* signal);
- void sendAcckeyconf(Signal* signal);
- Uint32 getNoParallelTransaction(const Operationrec*);
-
-#ifdef VM_TRACE
- Uint32 getNoParallelTransactionFull(const Operationrec*);
-#endif
-#ifdef ACC_SAFE_QUEUE
- bool validate_lock_queue(OperationrecPtr opPtr);
- Uint32 get_parallel_head(OperationrecPtr opPtr);
- void dump_lock_queue(OperationrecPtr loPtr);
-#else
- bool validate_lock_queue(OperationrecPtr) { return true;}
-#endif
-
-public:
- void execACCKEY_ORD(Signal* signal, Uint32 opPtrI);
- void startNext(Signal* signal, OperationrecPtr lastOp);
-
-private:
- Uint32 placeReadInLockQueue(OperationrecPtr lockOwnerPtr);
- Uint32 placeWriteInLockQueue(OperationrecPtr lockOwnerPtr);
- void placeSerialQueue(OperationrecPtr lockOwner, OperationrecPtr op);
- void abortSerieQueueOperation(Signal* signal, OperationrecPtr op);
- void abortParallelQueueOperation(Signal* signal, OperationrecPtr op);
-
- void expandcontainer(Signal* signal);
- void shrinkcontainer(Signal* signal);
- void nextcontainerinfoExp(Signal* signal);
- void releaseAndCommitActiveOps(Signal* signal);
- void releaseAndCommitQueuedOps(Signal* signal);
- void releaseAndAbortLockedOps(Signal* signal);
- void containerinfo(Signal* signal);
- bool getScanElement(Signal* signal);
- void initScanOpRec(Signal* signal);
- void nextcontainerinfo(Signal* signal);
- void putActiveScanOp(Signal* signal);
- void putOpScanLockQue();
- void putReadyScanQueue(Signal* signal, Uint32 scanRecIndex);
- void releaseScanBucket(Signal* signal);
- void releaseScanContainer(Signal* signal);
- void releaseScanRec(Signal* signal);
- bool searchScanContainer(Signal* signal);
- void sendNextScanConf(Signal* signal);
- void setlock(Signal* signal);
- void takeOutActiveScanOp(Signal* signal);
- void takeOutScanLockQueue(Uint32 scanRecIndex);
- void takeOutReadyScanQueue(Signal* signal);
- void insertElement(Signal* signal);
- void insertContainer(Signal* signal);
- void addnewcontainer(Signal* signal);
- void getfreelist(Signal* signal);
- void increaselistcont(Signal* signal);
- void seizeLeftlist(Signal* signal);
- void seizeRightlist(Signal* signal);
- Uint32 readTablePk(Uint32 localkey1, Uint32 eh, OperationrecPtr);
- Uint32 getElement(Signal* signal, OperationrecPtr& lockOwner);
- void getdirindex(Signal* signal);
- void commitdelete(Signal* signal);
- void deleteElement(Signal* signal);
- void getLastAndRemove(Signal* signal);
- void releaseLeftlist(Signal* signal);
- void releaseRightlist(Signal* signal);
- void checkoverfreelist(Signal* signal);
- void abortOperation(Signal* signal);
- void commitOperation(Signal* signal);
- void copyOpInfo(OperationrecPtr dst, OperationrecPtr src);
- Uint32 executeNextOperation(Signal* signal);
- void releaselock(Signal* signal);
- void release_lockowner(Signal* signal, OperationrecPtr, bool commit);
- void startNew(Signal* signal, OperationrecPtr newOwner);
- void abortWaitingOperation(Signal*, OperationrecPtr);
- void abortExecutedOperation(Signal*, OperationrecPtr);
-
- void takeOutFragWaitQue(Signal* signal);
- void check_lock_upgrade(Signal* signal, OperationrecPtr release_op, bool lo);
- void check_lock_upgrade(Signal* signal, OperationrecPtr lock_owner,
- OperationrecPtr release_op);
- void allocOverflowPage(Signal* signal);
- bool getfragmentrec(Signal* signal, FragmentrecPtr&, Uint32 fragId);
- void insertLockOwnersList(Signal* signal, const OperationrecPtr&);
- void takeOutLockOwnersList(Signal* signal, const OperationrecPtr&);
-
- void initFsOpRec(Signal* signal);
- void initOverpage(Signal* signal);
- void initPage(Signal* signal);
- void initRootfragrec(Signal* signal);
- void putOpInFragWaitQue(Signal* signal);
- void putOverflowRecInFrag(Signal* signal);
- void putRecInFreeOverdir(Signal* signal);
- void releaseDirectory(Signal* signal);
- void releaseDirrange(Signal* signal);
- void releaseFsConnRec(Signal* signal);
- void releaseFsOpRec(Signal* signal);
- void releaseOpRec(Signal* signal);
- void releaseOverflowRec(Signal* signal);
- void releaseOverpage(Signal* signal);
- void releasePage(Signal* signal);
- void releaseLogicalPage(Fragmentrec * fragP, Uint32 logicalPageId);
- void seizeDirectory(Signal* signal);
- void seizeDirrange(Signal* signal);
- void seizeFragrec(Signal* signal);
- void seizeFsConnectRec(Signal* signal);
- void seizeFsOpRec(Signal* signal);
- void seizeOpRec(Signal* signal);
- void seizeOverRec(Signal* signal);
- void seizePage(Signal* signal);
- void seizeRootfragrec(Signal* signal);
- void seizeScanRec(Signal* signal);
- void sendSystemerror(Signal* signal, int line);
- void takeRecOutOfFreeOverdir(Signal* signal);
- void takeRecOutOfFreeOverpage(Signal* signal);
- void sendScanHbRep(Signal* signal, Uint32);
-
- void addFragRefuse(Signal* signal, Uint32 errorCode);
- void ndbsttorryLab(Signal* signal);
- void acckeyref1Lab(Signal* signal, Uint32 result_code);
- void insertelementLab(Signal* signal);
- void checkNextFragmentLab(Signal* signal);
- void endofexpLab(Signal* signal);
- void endofshrinkbucketLab(Signal* signal);
- void senddatapagesLab(Signal* signal);
- void sttorrysignalLab(Signal* signal);
- void sendholdconfsignalLab(Signal* signal);
- void accIsLockedLab(Signal* signal, OperationrecPtr lockOwnerPtr);
- void insertExistElemLab(Signal* signal, OperationrecPtr lockOwnerPtr);
- void refaccConnectLab(Signal* signal);
- void releaseScanLab(Signal* signal);
- void ndbrestart1Lab(Signal* signal);
- void initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data);
- void checkNextBucketLab(Signal* signal);
- void storeDataPageInDirectoryLab(Signal* signal);
-
- void zpagesize_error(const char* where);
-
- void reportMemoryUsage(Signal* signal, int gth);
- void reenable_expand_after_redo_log_exection_complete(Signal*);
-
- // charsets
- void xfrmKeyData(Signal* signal);
-
- // Initialisation
- void initData();
- void initRecords();
-
- // Variables
-/* --------------------------------------------------------------------------------- */
-/* DIRECTORY RANGE */
-/* --------------------------------------------------------------------------------- */
- DirRange *dirRange;
- DirRangePtr expDirRangePtr;
- DirRangePtr gnsDirRangePtr;
- DirRangePtr newDirRangePtr;
- DirRangePtr rdDirRangePtr;
- DirRangePtr nciOverflowrangeptr;
- Uint32 cdirrangesize;
- Uint32 cfirstfreeDirrange;
-/* --------------------------------------------------------------------------------- */
-/* DIRECTORYARRAY */
-/* --------------------------------------------------------------------------------- */
- Directoryarray *directoryarray;
- DirectoryarrayPtr expDirptr;
- DirectoryarrayPtr rdDirptr;
- DirectoryarrayPtr sdDirptr;
- DirectoryarrayPtr nciOverflowDirptr;
- Uint32 cdirarraysize;
- Uint32 cdirmemory;
- Uint32 cfirstfreedir;
-/* --------------------------------------------------------------------------------- */
-/* FRAGMENTREC. ALL INFORMATION ABOUT FRAMENT AND HASH TABLE IS SAVED IN FRAGMENT */
-/* REC A POINTER TO FRAGMENT RECORD IS SAVED IN ROOTFRAGMENTREC FRAGMENT */
-/* --------------------------------------------------------------------------------- */
- Fragmentrec *fragmentrec;
- FragmentrecPtr fragrecptr;
- Uint32 cfirstfreefrag;
- Uint32 cfragmentsize;
-/* --------------------------------------------------------------------------------- */
-/* FS_CONNECTREC */
-/* --------------------------------------------------------------------------------- */
-/* OPERATIONREC */
-/* --------------------------------------------------------------------------------- */
- Operationrec *operationrec;
- OperationrecPtr operationRecPtr;
- OperationrecPtr idrOperationRecPtr;
- OperationrecPtr mlpqOperPtr;
- OperationrecPtr queOperPtr;
- OperationrecPtr readWriteOpPtr;
- Uint32 cfreeopRec;
- Uint32 coprecsize;
-/* --------------------------------------------------------------------------------- */
-/* OVERFLOW_RECORD */
-/* --------------------------------------------------------------------------------- */
- OverflowRecord *overflowRecord;
- OverflowRecordPtr iopOverflowRecPtr;
- OverflowRecordPtr tfoOverflowRecPtr;
- OverflowRecordPtr porOverflowRecPtr;
- OverflowRecordPtr priOverflowRecPtr;
- OverflowRecordPtr rorOverflowRecPtr;
- OverflowRecordPtr sorOverflowRecPtr;
- OverflowRecordPtr troOverflowRecPtr;
- Uint32 cfirstfreeoverrec;
- Uint32 coverflowrecsize;
-
-/* --------------------------------------------------------------------------------- */
-/* PAGE8 */
-/* --------------------------------------------------------------------------------- */
- Page8 *page8;
- /* 8 KB PAGE */
- Page8Ptr ancPageptr;
- Page8Ptr colPageptr;
- Page8Ptr ccoPageptr;
- Page8Ptr datapageptr;
- Page8Ptr delPageptr;
- Page8Ptr excPageptr;
- Page8Ptr expPageptr;
- Page8Ptr gdiPageptr;
- Page8Ptr gePageptr;
- Page8Ptr gflPageptr;
- Page8Ptr idrPageptr;
- Page8Ptr ilcPageptr;
- Page8Ptr inpPageptr;
- Page8Ptr iopPageptr;
- Page8Ptr lastPageptr;
- Page8Ptr lastPrevpageptr;
- Page8Ptr lcnPageptr;
- Page8Ptr lcnCopyPageptr;
- Page8Ptr lupPageptr;
- Page8Ptr ciPageidptr;
- Page8Ptr gsePageidptr;
- Page8Ptr isoPageptr;
- Page8Ptr nciPageidptr;
- Page8Ptr rsbPageidptr;
- Page8Ptr rscPageidptr;
- Page8Ptr slPageidptr;
- Page8Ptr sscPageidptr;
- Page8Ptr rlPageptr;
- Page8Ptr rlpPageptr;
- Page8Ptr ropPageptr;
- Page8Ptr rpPageptr;
- Page8Ptr slPageptr;
- Page8Ptr spPageptr;
- Uint32 cfirstfreepage;
- Uint32 cfreepage;
- Uint32 cpagesize;
- Uint32 cnoOfAllocatedPages;
-/* --------------------------------------------------------------------------------- */
-/* ROOTFRAGMENTREC */
-/* DURING EXPAND FRAGMENT PROCESS, EACH FRAGMEND WILL BE EXPAND INTO TWO */
-/* NEW FRAGMENTS.TO MAKE THIS PROCESS EASIER, DURING ADD FRAGMENT PROCESS */
-/* NEXT FRAGMENT IDENTIIES WILL BE CALCULATED, AND TWO FRAGMENTS WILL BE */
-/* ADDED IN (NDBACC). THEREBY EXPAND OF FRAGMENT CAN BE PERFORMED QUICK AND */
-/* EASY.THE NEW FRAGMENT ID SENDS TO TUP MANAGER FOR ALL OPERATION PROCESS. */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* SCAN_REC */
-/* --------------------------------------------------------------------------------- */
- ScanRec *scanRec;
- ScanRecPtr scanPtr;
- Uint32 cscanRecSize;
- Uint32 cfirstFreeScanRec;
-/* --------------------------------------------------------------------------------- */
-/* TABREC */
-/* --------------------------------------------------------------------------------- */
- Tabrec *tabrec;
- TabrecPtr tabptr;
- Uint32 ctablesize;
- Uint32 tgseElementptr;
- Uint32 tgseContainerptr;
- Uint32 trlHead;
- Uint32 trlRelCon;
- Uint32 trlNextused;
- Uint32 trlPrevused;
- Uint32 tlcnChecksum;
- Uint32 tlupElemIndex;
- Uint32 tlupIndex;
- Uint32 tlupForward;
- Uint32 tancNext;
- Uint32 tancBufType;
- Uint32 tancContainerptr;
- Uint32 tancPageindex;
- Uint32 tancPageid;
- Uint32 tidrResult;
- Uint32 tidrElemhead;
- Uint32 tidrForward;
- Uint32 tidrPageindex;
- Uint32 tidrContainerptr;
- Uint32 tidrContainerhead;
- Uint32 tlastForward;
- Uint32 tlastPageindex;
- Uint32 tlastContainerlen;
- Uint32 tlastElementptr;
- Uint32 tlastContainerptr;
- Uint32 tlastContainerhead;
- Uint32 trlPageindex;
- Uint32 tdelContainerptr;
- Uint32 tdelElementptr;
- Uint32 tdelForward;
- Uint32 tiopPageId;
- Uint32 tipPageId;
- Uint32 tgeContainerptr;
- Uint32 tgeElementptr;
- Uint32 tgeForward;
- Uint32 texpReceivedBucket;
- Uint32 texpDirInd;
- Uint32 texpDirRangeIndex;
- Uint32 texpDirPageIndex;
- Uint32 tdata0;
- Uint32 tcheckpointid;
- Uint32 tciContainerptr;
- Uint32 tnciContainerptr;
- Uint32 tisoContainerptr;
- Uint32 trscContainerptr;
- Uint32 tsscContainerptr;
- Uint32 tciContainerlen;
- Uint32 trscContainerlen;
- Uint32 tsscContainerlen;
- Uint32 tciContainerhead;
- Uint32 tnciContainerhead;
- Uint32 tslElementptr;
- Uint32 tisoElementptr;
- Uint32 tsscElementptr;
- Uint32 tfid;
- Uint32 tscanFlag;
- Uint32 tgflBufType;
- Uint32 tgseIsforward;
- Uint32 tsscIsforward;
- Uint32 trscIsforward;
- Uint32 tciIsforward;
- Uint32 tnciIsforward;
- Uint32 tisoIsforward;
- Uint32 tgseIsLocked;
- Uint32 tsscIsLocked;
- Uint32 tkeylen;
- Uint32 tmp;
- Uint32 tmpP;
- Uint32 tmpP2;
- Uint32 tmp1;
- Uint32 tmp2;
- Uint32 tgflPageindex;
- Uint32 tmpindex;
- Uint32 tslNextfree;
- Uint32 tslPageindex;
- Uint32 tgsePageindex;
- Uint32 tnciNextSamePage;
- Uint32 tslPrevfree;
- Uint32 tciPageindex;
- Uint32 trsbPageindex;
- Uint32 tnciPageindex;
- Uint32 tlastPrevconptr;
- Uint32 tresult;
- Uint32 tslUpdateHeader;
- Uint32 tuserptr;
- BlockReference tuserblockref;
- Uint32 tlqhPointer;
- Uint32 tholdSentOp;
- Uint32 tholdMore;
- Uint32 tgdiPageindex;
- Uint32 tiopIndex;
- Uint32 tnciTmp;
- Uint32 tullIndex;
- Uint32 turlIndex;
- Uint32 tlfrTmp1;
- Uint32 tlfrTmp2;
- Uint32 tscanTrid1;
- Uint32 tscanTrid2;
-
- Uint32 ctest;
- Uint32 clqhPtr;
- BlockReference clqhBlockRef;
- Uint32 cminusOne;
- NodeId cmynodeid;
- BlockReference cownBlockref;
- BlockReference cndbcntrRef;
- Uint16 csignalkey;
- Uint32 czero;
- Uint32 csystemRestart;
- Uint32 cexcForward;
- Uint32 cexcPageindex;
- Uint32 cexcContainerptr;
- Uint32 cexcContainerhead;
- Uint32 cexcContainerlen;
- Uint32 cexcElementptr;
- Uint32 cexcPrevconptr;
- Uint32 cexcMovedLen;
- Uint32 cexcPrevpageptr;
- Uint32 cexcPrevpageindex;
- Uint32 cexcPrevforward;
- Uint32 clocalkey[32];
- union {
- Uint32 ckeys[2048 * MAX_XFRM_MULTIPLY];
- Uint64 ckeys_align;
- };
-
- Uint32 c_errorInsert3000_TableId;
- Uint32 c_memusage_report_frequency;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
deleted file mode 100644
index 29ea4801b7b..00000000000
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-
-#define DBACC_C
-#include "Dbacc.hpp"
-
-#define DEBUG(x) { ndbout << "ACC::" << x << endl; }
-
-void Dbacc::initData()
-{
- cdirarraysize = ZDIRARRAY;
- coprecsize = ZOPRECSIZE;
- cpagesize = ZPAGESIZE;
- ctablesize = ZTABLESIZE;
- cfragmentsize = ZFRAGMENTSIZE;
- cdirrangesize = ZDIRRANGESIZE;
- coverflowrecsize = ZOVERFLOWRECSIZE;
- cscanRecSize = ZSCAN_REC_SIZE;
-
-
- dirRange = 0;
- directoryarray = 0;
- fragmentrec = 0;
- operationrec = 0;
- overflowRecord = 0;
- page8 = 0;
- scanRec = 0;
- tabrec = 0;
-
- cnoOfAllocatedPages = cpagesize = 0;
- // Records with constant sizes
-}//Dbacc::initData()
-
-void Dbacc::initRecords()
-{
- // Records with dynamic sizes
- page8 = (Page8*)allocRecord("Page8",
- sizeof(Page8),
- cpagesize,
- false,
- CFG_DB_INDEX_MEM);
-
- operationrec = (Operationrec*)allocRecord("Operationrec",
- sizeof(Operationrec),
- coprecsize);
-
- dirRange = (DirRange*)allocRecord("DirRange",
- sizeof(DirRange),
- cdirrangesize);
-
- directoryarray = (Directoryarray*)allocRecord("Directoryarray",
- sizeof(Directoryarray),
- cdirarraysize);
-
- fragmentrec = (Fragmentrec*)allocRecord("Fragmentrec",
- sizeof(Fragmentrec),
- cfragmentsize);
-
- overflowRecord = (OverflowRecord*)allocRecord("OverflowRecord",
- sizeof(OverflowRecord),
- coverflowrecsize);
-
- scanRec = (ScanRec*)allocRecord("ScanRec",
- sizeof(ScanRec),
- cscanRecSize);
-
- tabrec = (Tabrec*)allocRecord("Tabrec",
- sizeof(Tabrec),
- ctablesize);
-}//Dbacc::initRecords()
-
-Dbacc::Dbacc(Block_context& ctx):
- SimulatedBlock(DBACC, ctx),
- c_tup(0)
-{
- BLOCK_CONSTRUCTOR(Dbacc);
-
- // Transit signals
- addRecSignal(GSN_DUMP_STATE_ORD, &Dbacc::execDUMP_STATE_ORD);
- addRecSignal(GSN_DEBUG_SIG, &Dbacc::execDEBUG_SIG);
- addRecSignal(GSN_CONTINUEB, &Dbacc::execCONTINUEB);
- addRecSignal(GSN_ACC_CHECK_SCAN, &Dbacc::execACC_CHECK_SCAN);
- addRecSignal(GSN_EXPANDCHECK2, &Dbacc::execEXPANDCHECK2);
- addRecSignal(GSN_SHRINKCHECK2, &Dbacc::execSHRINKCHECK2);
- addRecSignal(GSN_READ_PSEUDO_REQ, &Dbacc::execREAD_PSEUDO_REQ);
-
- // Received signals
- addRecSignal(GSN_STTOR, &Dbacc::execSTTOR);
- addRecSignal(GSN_ACCKEYREQ, &Dbacc::execACCKEYREQ);
- addRecSignal(GSN_ACCSEIZEREQ, &Dbacc::execACCSEIZEREQ);
- addRecSignal(GSN_ACCFRAGREQ, &Dbacc::execACCFRAGREQ);
- addRecSignal(GSN_NEXT_SCANREQ, &Dbacc::execNEXT_SCANREQ);
- addRecSignal(GSN_ACC_ABORTREQ, &Dbacc::execACC_ABORTREQ);
- addRecSignal(GSN_ACC_SCANREQ, &Dbacc::execACC_SCANREQ);
- addRecSignal(GSN_ACCMINUPDATE, &Dbacc::execACCMINUPDATE);
- addRecSignal(GSN_ACC_COMMITREQ, &Dbacc::execACC_COMMITREQ);
- addRecSignal(GSN_ACC_TO_REQ, &Dbacc::execACC_TO_REQ);
- addRecSignal(GSN_ACC_LOCKREQ, &Dbacc::execACC_LOCKREQ);
- addRecSignal(GSN_NDB_STTOR, &Dbacc::execNDB_STTOR);
- addRecSignal(GSN_DROP_TAB_REQ, &Dbacc::execDROP_TAB_REQ);
- addRecSignal(GSN_READ_CONFIG_REQ, &Dbacc::execREAD_CONFIG_REQ, true);
-
- initData();
-
-#ifdef VM_TRACE
- {
- void* tmp[] = { &expDirRangePtr,
- &gnsDirRangePtr,
- &newDirRangePtr,
- &rdDirRangePtr,
- &nciOverflowrangeptr,
- &expDirptr,
- &rdDirptr,
- &sdDirptr,
- &nciOverflowDirptr,
- &fragrecptr,
- &operationRecPtr,
- &idrOperationRecPtr,
- &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,
- &ciPageidptr,
- &gsePageidptr,
- &isoPageptr,
- &nciPageidptr,
- &rsbPageidptr,
- &rscPageidptr,
- &slPageidptr,
- &sscPageidptr,
- &rlPageptr,
- &rlpPageptr,
- &ropPageptr,
- &rpPageptr,
- &slPageptr,
- &spPageptr,
- &scanPtr,
- &tabptr
- };
- init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
- }
-#endif
-}//Dbacc::Dbacc()
-
-Dbacc::~Dbacc()
-{
- deallocRecord((void **)&dirRange, "DirRange",
- sizeof(DirRange),
- cdirrangesize);
-
- deallocRecord((void **)&directoryarray, "Directoryarray",
- sizeof(Directoryarray),
- cdirarraysize);
-
- deallocRecord((void **)&fragmentrec, "Fragmentrec",
- sizeof(Fragmentrec),
- cfragmentsize);
-
- deallocRecord((void **)&operationrec, "Operationrec",
- sizeof(Operationrec),
- coprecsize);
-
- deallocRecord((void **)&overflowRecord, "OverflowRecord",
- sizeof(OverflowRecord),
- coverflowrecsize);
-
- deallocRecord((void **)&page8, "Page8",
- sizeof(Page8),
- cpagesize);
-
- deallocRecord((void **)&scanRec, "ScanRec",
- sizeof(ScanRec),
- cscanRecSize);
-
- deallocRecord((void **)&tabrec, "Tabrec",
- sizeof(Tabrec),
- ctablesize);
- }//Dbacc::~Dbacc()
-
-BLOCK_FUNCTIONS(Dbacc)
diff --git a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
deleted file mode 100644
index da614b0276c..00000000000
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ /dev/null
@@ -1,8549 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBACC_C
-#include "Dbacc.hpp"
-#include <my_sys.h>
-
-#include <AttributeHeader.hpp>
-#include <signaldata/AccFrag.hpp>
-#include <signaldata/AccScan.hpp>
-#include <signaldata/NextScan.hpp>
-#include <signaldata/AccLock.hpp>
-#include <signaldata/EventReport.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsRemoveReq.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/TuxMaint.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.
-
-#ifdef VM_TRACE
-#define DEBUG(x) ndbout << "DBACC: "<< x << endl;
-#else
-#define DEBUG(x)
-#endif
-
-#ifdef ACC_SAFE_QUEUE
-#define vlqrequire(x) do { if (unlikely(!(x))) {\
- dump_lock_queue(loPtr); \
- ndbrequire(false); } } while(0)
-#else
-#define vlqrequire(x) ndbrequire(x)
-#define dump_lock_queue(x)
-#endif
-
-
-// primary key is stored in TUP
-#include "../dbtup/Dbtup.hpp"
-#include "../dblqh/Dblqh.hpp"
-
-
-// Signal entries and statement blocks
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* COMMON SIGNAL RECEPTION MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-
-/* --------------------------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* CONTINUEB CONTINUE SIGNAL */
-/* ******************------------------------------+ */
-/* SENDER: ACC, LEVEL B */
-void Dbacc::execCONTINUEB(Signal* signal)
-{
- Uint32 tcase;
-
- jamEntry();
- tcase = signal->theData[0];
- tdata0 = signal->theData[1];
- tresult = 0;
- switch (tcase) {
- case ZINITIALISE_RECORDS:
- jam();
- initialiseRecordsLab(signal, signal->theData[3], signal->theData[4]);
- return;
- break;
- case ZSEND_SCAN_HBREP:
- jam();
- sendScanHbRep(signal, tdata0);
- break;
- case ZREL_ROOT_FRAG:
- {
- jam();
- Uint32 tableId = signal->theData[1];
- releaseRootFragResources(signal, tableId);
- break;
- }
- case ZREL_FRAG:
- {
- jam();
- Uint32 fragIndex = signal->theData[1];
- releaseFragResources(signal, fragIndex);
- break;
- }
- case ZREL_DIR:
- {
- jam();
- Uint32 fragIndex = signal->theData[1];
- Uint32 dirIndex = signal->theData[2];
- Uint32 startIndex = signal->theData[3];
- releaseDirResources(signal, fragIndex, dirIndex, startIndex);
- break;
- }
- case ZREPORT_MEMORY_USAGE:{
- jam();
- Uint32 cnt = signal->theData[1];
- static int c_currentMemUsed = 0;
- int now = cpagesize ? (cnoOfAllocatedPages * 100)/cpagesize : 0;
- const int thresholds[] = { 99, 90, 80, 0};
-
- Uint32 i = 0;
- const Uint32 sz = sizeof(thresholds)/sizeof(thresholds[0]);
- for(i = 0; i<sz; i++){
- if(now >= thresholds[i]){
- now = thresholds[i];
- break;
- }
- }
-
- if(now != c_currentMemUsed ||
- (c_memusage_report_frequency && cnt + 1 == c_memusage_report_frequency))
- {
- reportMemoryUsage(signal,
- now > c_currentMemUsed ? 1 :
- now < c_currentMemUsed ? -1 : 0);
- cnt = 0;
- c_currentMemUsed = now;
- }
- else
- {
- cnt ++;
- }
- signal->theData[0] = ZREPORT_MEMORY_USAGE;
- signal->theData[1] = cnt;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 2);
- return;
- }
-
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbacc::execCONTINUEB()
-
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* */
-/* END OF COMMON SIGNAL RECEPTION MODULE */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* */
-/* SYSTEM RESTART MODULE */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-void Dbacc::execNDB_STTOR(Signal* signal)
-{
- Uint32 tstartphase;
- Uint32 tStartType;
-
- jamEntry();
- cndbcntrRef = signal->theData[0];
- cmynodeid = signal->theData[1];
- tstartphase = signal->theData[2];
- tStartType = signal->theData[3];
- switch (tstartphase) {
- case ZSPH1:
- jam();
- ndbsttorryLab(signal);
- return;
- break;
- case ZSPH2:
- ndbsttorryLab(signal);
- return;
- break;
- case ZSPH3:
- if ((tStartType == NodeState::ST_NODE_RESTART) ||
- (tStartType == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- //---------------------------------------------
- // csystemRestart is used to check what is needed
- // during log execution. When starting a node it
- // is not a log execution and rather a normal
- // execution. Thus we reset the variable here to
- // avoid unnecessary system crashes.
- //---------------------------------------------
- csystemRestart = ZFALSE;
- }//if
- break;
- case ZSPH6:
- jam();
- csystemRestart = ZFALSE;
-
- signal->theData[0] = ZREPORT_MEMORY_USAGE;
- signal->theData[1] = 0;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 2);
- break;
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- ndbsttorryLab(signal);
- return;
-}//Dbacc::execNDB_STTOR()
-
-/* ******************--------------------------------------------------------------- */
-/* STTOR START / RESTART */
-/* ******************------------------------------+ */
-/* SENDER: ANY, LEVEL B */
-void Dbacc::execSTTOR(Signal* signal)
-{
- jamEntry();
- Uint32 tstartphase = signal->theData[1];
- switch (tstartphase) {
- case 1:
- jam();
- ndbrequire((c_tup = (Dbtup*)globalData.getBlock(DBTUP)) != 0);
- ndbrequire((c_lqh = (Dblqh*)globalData.getBlock(DBLQH)) != 0);
- break;
- }
- tuserblockref = signal->theData[3];
- csignalkey = signal->theData[6];
- sttorrysignalLab(signal);
- return;
-}//Dbacc::execSTTOR()
-
-/* --------------------------------------------------------------------------------- */
-/* ZSPH1 */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::ndbrestart1Lab(Signal* signal)
-{
- cmynodeid = globalData.ownId;
- cownBlockref = numberToRef(DBACC, cmynodeid);
- czero = 0;
- cminusOne = czero - 1;
- ctest = 0;
- csystemRestart = ZTRUE;
- return;
-}//Dbacc::ndbrestart1Lab()
-
-void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data)
-{
- switch (tdata0) {
- case 0:
- jam();
- initialiseTableRec(signal);
- break;
- case 1:
- case 2:
- break;
- case 3:
- jam();
- break;
- case 4:
- jam();
- initialiseDirRec(signal);
- break;
- case 5:
- jam();
- initialiseDirRangeRec(signal);
- break;
- case 6:
- jam();
- initialiseFragRec(signal);
- break;
- case 7:
- jam();
- initialiseOverflowRec(signal);
- break;
- case 8:
- jam();
- initialiseOperationRec(signal);
- break;
- case 9:
- jam();
- initialisePageRec(signal);
- break;
- case 10:
- jam();
- break;
- case 11:
- jam();
- initialiseScanRec(signal);
- break;
- case 12:
- jam();
-
- {
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = data;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
- }
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
-
- signal->theData[0] = ZINITIALISE_RECORDS;
- signal->theData[1] = tdata0 + 1;
- signal->theData[2] = 0;
- signal->theData[3] = ref;
- signal->theData[4] = data;
- sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
- return;
-}//Dbacc::initialiseRecordsLab()
-
-/* *********************************<< */
-/* NDB_STTORRY */
-/* *********************************<< */
-void Dbacc::ndbsttorryLab(Signal* signal)
-{
- signal->theData[0] = cownBlockref;
- sendSignal(cndbcntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
- return;
-}//Dbacc::ndbsttorryLab()
-
-/* *********************************<< */
-/* SIZEALT_REP SIZE ALTERATION */
-/* *********************************<< */
-void Dbacc::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- 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));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OP_RECS, &coprecsize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OVERFLOW_RECS,
- &coverflowrecsize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_PAGE8, &cpagesize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_TABLE, &ctablesize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_SCAN, &cscanRecSize));
- initRecords();
- ndbrestart1Lab(signal);
-
- c_memusage_report_frequency = 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_MEMREPORT_FREQUENCY,
- &c_memusage_report_frequency);
-
- tdata0 = 0;
- initialiseRecordsLab(signal, ref, senderData);
- return;
-}//Dbacc::execSIZEALT_REP()
-
-/* *********************************<< */
-/* STTORRY */
-/* *********************************<< */
-void Dbacc::sttorrysignalLab(Signal* signal)
-{
- signal->theData[0] = csignalkey;
- signal->theData[1] = 3;
- /* BLOCK CATEGORY */
- signal->theData[2] = 2;
- /* SIGNAL VERSION NUMBER */
- signal->theData[3] = ZSPH1;
- signal->theData[4] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
- /* END OF START PHASES */
- return;
-}//Dbacc::sttorrysignalLab()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_DIR_REC */
-/* INITIALATES THE DIRECTORY RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseDirRec(Signal* signal)
-{
- DirectoryarrayPtr idrDirptr;
- ndbrequire(cdirarraysize > 0);
- for (idrDirptr.i = 0; idrDirptr.i < cdirarraysize; idrDirptr.i++) {
- refresh_watch_dog();
- ptrAss(idrDirptr, directoryarray);
- for (Uint32 i = 0; i <= 255; i++) {
- idrDirptr.p->pagep[i] = RNIL;
- }//for
- }//for
- cdirmemory = 0;
- cfirstfreedir = RNIL;
-}//Dbacc::initialiseDirRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_DIR_RANGE_REC */
-/* INITIALATES THE DIR_RANGE RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseDirRangeRec(Signal* signal)
-{
- DirRangePtr idrDirRangePtr;
-
- ndbrequire(cdirrangesize > 0);
- for (idrDirRangePtr.i = 0; idrDirRangePtr.i < cdirrangesize; idrDirRangePtr.i++) {
- refresh_watch_dog();
- ptrAss(idrDirRangePtr, dirRange);
- idrDirRangePtr.p->dirArray[0] = idrDirRangePtr.i + 1;
- for (Uint32 i = 1; i < 256; i++) {
- idrDirRangePtr.p->dirArray[i] = RNIL;
- }//for
- }//for
- idrDirRangePtr.i = cdirrangesize - 1;
- ptrAss(idrDirRangePtr, dirRange);
- idrDirRangePtr.p->dirArray[0] = RNIL;
- cfirstfreeDirrange = 0;
-}//Dbacc::initialiseDirRangeRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_FRAG_REC */
-/* INITIALATES THE FRAGMENT RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseFragRec(Signal* signal)
-{
- FragmentrecPtr regFragPtr;
- ndbrequire(cfragmentsize > 0);
- for (regFragPtr.i = 0; regFragPtr.i < cfragmentsize; regFragPtr.i++) {
- jam();
- refresh_watch_dog();
- ptrAss(regFragPtr, fragmentrec);
- initFragGeneral(regFragPtr);
- regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
- }//for
- regFragPtr.i = cfragmentsize - 1;
- ptrAss(regFragPtr, fragmentrec);
- regFragPtr.p->nextfreefrag = RNIL;
- cfirstfreefrag = 0;
-}//Dbacc::initialiseFragRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_OPERATION_REC */
-/* INITIALATES THE OPERATION RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseOperationRec(Signal* signal)
-{
- ndbrequire(coprecsize > 0);
- for (operationRecPtr.i = 0; operationRecPtr.i < coprecsize; operationRecPtr.i++) {
- refresh_watch_dog();
- ptrAss(operationRecPtr, operationrec);
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- operationRecPtr.p->nextOp = operationRecPtr.i + 1;
- }//for
- operationRecPtr.i = coprecsize - 1;
- ptrAss(operationRecPtr, operationrec);
- operationRecPtr.p->nextOp = RNIL;
- cfreeopRec = 0;
-}//Dbacc::initialiseOperationRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_OVERFLOW_REC */
-/* INITIALATES THE OVERFLOW RECORDS */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseOverflowRec(Signal* signal)
-{
- OverflowRecordPtr iorOverflowRecPtr;
-
- ndbrequire(coverflowrecsize > 0);
- for (iorOverflowRecPtr.i = 0; iorOverflowRecPtr.i < coverflowrecsize; iorOverflowRecPtr.i++) {
- refresh_watch_dog();
- ptrAss(iorOverflowRecPtr, overflowRecord);
- iorOverflowRecPtr.p->nextfreeoverrec = iorOverflowRecPtr.i + 1;
- }//for
- iorOverflowRecPtr.i = coverflowrecsize - 1;
- ptrAss(iorOverflowRecPtr, overflowRecord);
- iorOverflowRecPtr.p->nextfreeoverrec = RNIL;
- cfirstfreeoverrec = 0;
-}//Dbacc::initialiseOverflowRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_PAGE_REC */
-/* INITIALATES THE PAGE RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialisePageRec(Signal* signal)
-{
- ndbrequire(cpagesize > 0);
- cfreepage = 0;
- cfirstfreepage = RNIL;
- cnoOfAllocatedPages = 0;
-}//Dbacc::initialisePageRec()
-
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_ROOTFRAG_REC */
-/* INITIALATES THE ROOTFRAG RECORDS. */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_SCAN_REC */
-/* INITIALATES THE QUE_SCAN RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseScanRec(Signal* signal)
-{
- ndbrequire(cscanRecSize > 0);
- for (scanPtr.i = 0; scanPtr.i < cscanRecSize; scanPtr.i++) {
- ptrAss(scanPtr, scanRec);
- scanPtr.p->scanNextfreerec = scanPtr.i + 1;
- scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT;
- scanPtr.p->scanTimer = 0;
- scanPtr.p->scanContinuebCounter = 0;
- }//for
- scanPtr.i = cscanRecSize - 1;
- ptrAss(scanPtr, scanRec);
- scanPtr.p->scanNextfreerec = RNIL;
- cfirstFreeScanRec = 0;
-}//Dbacc::initialiseScanRec()
-
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_TABLE_REC */
-/* INITIALATES THE TABLE RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseTableRec(Signal* signal)
-{
- ndbrequire(ctablesize > 0);
- for (tabptr.i = 0; tabptr.i < ctablesize; tabptr.i++) {
- refresh_watch_dog();
- ptrAss(tabptr, tabrec);
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- tabptr.p->fragholder[i] = RNIL;
- tabptr.p->fragptrholder[i] = RNIL;
- }//for
- }//for
-}//Dbacc::initialiseTableRec()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF SYSTEM RESTART MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* ADD/DELETE FRAGMENT MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-
-// JONAS This methods "aer ett saall"
-void Dbacc::execACCFRAGREQ(Signal* signal)
-{
- const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
- jamEntry();
- if (ERROR_INSERTED(3001)) {
- jam();
- addFragRefuse(signal, 1);
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }
- tabptr.i = req->tableId;
-#ifndef VM_TRACE
- // config mismatch - do not crash if release compiled
- if (tabptr.i >= ctablesize) {
- jam();
- addFragRefuse(signal, 640);
- return;
- }
-#endif
- ptrCheckGuard(tabptr, ctablesize, tabrec);
- ndbrequire((req->reqInfo & 0xF) == ZADDFRAG);
- ndbrequire(!getfragmentrec(signal, fragrecptr, req->fragId));
- if (cfirstfreefrag == RNIL) {
- jam();
- addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
- return;
- }//if
-
- seizeFragrec(signal);
- initFragGeneral(fragrecptr);
- initFragAdd(signal, fragrecptr);
-
- if (!addfragtotab(signal, fragrecptr.i, req->fragId)) {
- jam();
- releaseFragRecord(signal, fragrecptr);
- addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
- return;
- }//if
- if (cfirstfreeDirrange == RNIL) {
- jam();
- releaseFragRecord(signal, fragrecptr);
- addFragRefuse(signal, ZDIR_RANGE_ERROR);
- return;
- } else {
- jam();
- seizeDirrange(signal);
- }//if
-
- fragrecptr.p->directory = newDirRangePtr.i;
- seizeDirectory(signal);
- if (tresult < ZLIMIT_OF_ERROR) {
- jam();
- newDirRangePtr.p->dirArray[0] = sdDirptr.i;
- } else {
- jam();
- addFragRefuse(signal, tresult);
- return;
- }//if
-
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- addFragRefuse(signal, tresult);
- return;
- }//if
- sdDirptr.p->pagep[0] = spPageptr.i;
- tipPageId = 0;
- inpPageptr = spPageptr;
- initPage(signal);
- if (cfirstfreeDirrange == RNIL) {
- jam();
- addFragRefuse(signal, ZDIR_RANGE_ERROR);
- return;
- } else {
- jam();
- seizeDirrange(signal);
- }//if
- fragrecptr.p->overflowdir = newDirRangePtr.i;
- seizeDirectory(signal);
- if (tresult < ZLIMIT_OF_ERROR) {
- jam();
- newDirRangePtr.p->dirArray[0] = sdDirptr.i;
- } else {
- jam();
- addFragRefuse(signal, tresult);
- return;
- }//if
-
- Uint32 userPtr = req->userPtr;
- BlockReference retRef = req->userRef;
- fragrecptr.p->rootState = ACTIVEROOT;
-
- AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
- conf->userPtr = userPtr;
- conf->rootFragPtr = RNIL;
- conf->fragId[0] = fragrecptr.p->fragmentid;
- conf->fragId[1] = RNIL;
- conf->fragPtr[0] = fragrecptr.i;
- conf->fragPtr[1] = RNIL;
- conf->rootHashCheck = fragrecptr.p->roothashcheck;
- sendSignal(retRef, GSN_ACCFRAGCONF, signal, AccFragConf::SignalLength, JBB);
-}//Dbacc::execACCFRAGREQ()
-
-void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode)
-{
- const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
- AccFragRef * const ref = (AccFragRef*)&signal->theData[0];
- Uint32 userPtr = req->userPtr;
- BlockReference retRef = req->userRef;
-
- ref->userPtr = userPtr;
- ref->errorCode = errorCode;
- sendSignal(retRef, GSN_ACCFRAGREF, signal, AccFragRef::SignalLength, JBB);
- return;
-}//Dbacc::addFragRefuseEarly()
-
-void
-Dbacc::execDROP_TAB_REQ(Signal* signal){
- jamEntry();
- DropTabReq* req = (DropTabReq*)signal->getDataPtr();
-
- TabrecPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctablesize, tabrec);
-
- tabPtr.p->tabUserRef = req->senderRef;
- tabPtr.p->tabUserPtr = req->senderData;
-
- signal->theData[0] = ZREL_ROOT_FRAG;
- signal->theData[1] = tabPtr.i;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void Dbacc::releaseRootFragResources(Signal* signal, Uint32 tableId)
-{
- TabrecPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctablesize, tabrec);
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabPtr.p->fragholder[i] != RNIL) {
- jam();
- tabPtr.p->fragholder[i] = RNIL;
- releaseFragResources(signal, tabPtr.p->fragptrholder[i]);
- return;
- }//if
- }//for
-
- /**
- * Finished...
- */
-
- DropTabConf * const dropConf = (DropTabConf *)signal->getDataPtrSend();
- dropConf->senderRef = reference();
- dropConf->senderData = tabPtr.p->tabUserPtr;
- dropConf->tableId = tabPtr.i;
- sendSignal(tabPtr.p->tabUserRef, GSN_DROP_TAB_CONF,
- signal, DropTabConf::SignalLength, JBB);
-
- tabPtr.p->tabUserPtr = RNIL;
- tabPtr.p->tabUserRef = 0;
-}//Dbacc::releaseRootFragResources()
-
-void Dbacc::releaseFragResources(Signal* signal, Uint32 fragIndex)
-{
- FragmentrecPtr regFragPtr;
- regFragPtr.i = fragIndex;
- ptrCheckGuard(regFragPtr, cfragmentsize, fragmentrec);
- verifyFragCorrect(regFragPtr);
- if (regFragPtr.p->directory != RNIL) {
- jam();
- releaseDirResources(signal, regFragPtr.i, regFragPtr.p->directory, 0);
- regFragPtr.p->directory = RNIL;
- } else if (regFragPtr.p->overflowdir != RNIL) {
- jam();
- releaseDirResources(signal, regFragPtr.i, regFragPtr.p->overflowdir, 0);
- regFragPtr.p->overflowdir = RNIL;
- } else if (regFragPtr.p->firstOverflowRec != RNIL) {
- jam();
- releaseOverflowResources(signal, regFragPtr);
- } else if (regFragPtr.p->firstFreeDirindexRec != RNIL) {
- jam();
- releaseDirIndexResources(signal, regFragPtr);
- } else {
- jam();
- Uint32 tab = regFragPtr.p->mytabptr;
- releaseFragRecord(signal, regFragPtr);
- signal->theData[0] = ZREL_ROOT_FRAG;
- signal->theData[1] = tab;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
-}//Dbacc::releaseFragResources()
-
-void Dbacc::verifyFragCorrect(FragmentrecPtr regFragPtr)
-{
- ndbrequire(regFragPtr.p->lockOwnersList == RNIL);
-}//Dbacc::verifyFragCorrect()
-
-void Dbacc::releaseDirResources(Signal* signal,
- Uint32 fragIndex,
- Uint32 dirIndex,
- Uint32 startIndex)
-{
- DirRangePtr regDirRangePtr;
- regDirRangePtr.i = dirIndex;
- ptrCheckGuard(regDirRangePtr, cdirrangesize, dirRange);
- for (Uint32 i = startIndex; i < 256; i++) {
- jam();
- if (regDirRangePtr.p->dirArray[i] != RNIL) {
- jam();
- Uint32 directoryIndex = regDirRangePtr.p->dirArray[i];
- regDirRangePtr.p->dirArray[i] = RNIL;
- releaseDirectoryResources(signal, fragIndex, dirIndex, (i + 1), directoryIndex);
- return;
- }//if
- }//for
- rdDirRangePtr = regDirRangePtr;
- releaseDirrange(signal);
- signal->theData[0] = ZREL_FRAG;
- signal->theData[1] = fragIndex;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
-}//Dbacc::releaseDirResources()
-
-void Dbacc::releaseDirectoryResources(Signal* signal,
- Uint32 fragIndex,
- Uint32 dirIndex,
- Uint32 startIndex,
- Uint32 directoryIndex)
-{
- DirectoryarrayPtr regDirPtr;
- regDirPtr.i = directoryIndex;
- ptrCheckGuard(regDirPtr, cdirarraysize, directoryarray);
- for (Uint32 i = 0; i < 256; i++) {
- jam();
- if (regDirPtr.p->pagep[i] != RNIL) {
- jam();
- rpPageptr.i = regDirPtr.p->pagep[i];
- ptrCheckGuard(rpPageptr, cpagesize, page8);
- releasePage(signal);
- regDirPtr.p->pagep[i] = RNIL;
- }//if
- }//for
- rdDirptr = regDirPtr;
- releaseDirectory(signal);
- signal->theData[0] = ZREL_DIR;
- signal->theData[1] = fragIndex;
- signal->theData[2] = dirIndex;
- signal->theData[3] = startIndex;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB);
-}//Dbacc::releaseDirectoryResources()
-
-void Dbacc::releaseOverflowResources(Signal* signal, FragmentrecPtr regFragPtr)
-{
- Uint32 loopCount = 0;
- OverflowRecordPtr regOverflowRecPtr;
- while ((regFragPtr.p->firstOverflowRec != RNIL) &&
- (loopCount < 1)) {
- jam();
- regOverflowRecPtr.i = regFragPtr.p->firstOverflowRec;
- ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord);
- regFragPtr.p->firstOverflowRec = regOverflowRecPtr.p->nextOverRec;
- rorOverflowRecPtr = regOverflowRecPtr;
- releaseOverflowRec(signal);
- loopCount++;
- }//while
- signal->theData[0] = ZREL_FRAG;
- signal->theData[1] = regFragPtr.i;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
-}//Dbacc::releaseOverflowResources()
-
-void Dbacc::releaseDirIndexResources(Signal* signal, FragmentrecPtr regFragPtr)
-{
- Uint32 loopCount = 0;
- OverflowRecordPtr regOverflowRecPtr;
- while ((regFragPtr.p->firstFreeDirindexRec != RNIL) &&
- (loopCount < 1)) {
- jam();
- regOverflowRecPtr.i = regFragPtr.p->firstFreeDirindexRec;
- ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord);
- regFragPtr.p->firstFreeDirindexRec = regOverflowRecPtr.p->nextOverList;
- rorOverflowRecPtr = regOverflowRecPtr;
- releaseOverflowRec(signal);
- loopCount++;
- }//while
- signal->theData[0] = ZREL_FRAG;
- signal->theData[1] = regFragPtr.i;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
-}//Dbacc::releaseDirIndexResources()
-
-void Dbacc::releaseFragRecord(Signal* signal, FragmentrecPtr regFragPtr)
-{
- regFragPtr.p->nextfreefrag = cfirstfreefrag;
- cfirstfreefrag = regFragPtr.i;
- initFragGeneral(regFragPtr);
-}//Dbacc::releaseFragRecord()
-
-/* -------------------------------------------------------------------------- */
-/* ADDFRAGTOTAB */
-/* DESCRIPTION: PUTS A FRAGMENT ID AND A POINTER TO ITS RECORD INTO */
-/* TABLE ARRRAY OF THE TABLE RECORD. */
-/* -------------------------------------------------------------------------- */
-bool Dbacc::addfragtotab(Signal* signal, Uint32 rootIndex, Uint32 fid)
-{
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabptr.p->fragholder[i] == RNIL) {
- jam();
- tabptr.p->fragholder[i] = fid;
- tabptr.p->fragptrholder[i] = rootIndex;
- return true;
- }//if
- }//for
- return false;
-}//Dbacc::addfragtotab()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF ADD/DELETE FRAGMENT MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* CONNECTION MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACCSEIZEREQ SEIZE REQ */
-/* SENDER: LQH, LEVEL B */
-/* ENTER ACCSEIZEREQ WITH */
-/* TUSERPTR , CONECTION PTR OF LQH */
-/* TUSERBLOCKREF BLOCK REFERENCE OF LQH */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACCSEIZEREQ SEIZE REQ */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execACCSEIZEREQ(Signal* signal)
-{
- jamEntry();
- tuserptr = signal->theData[0];
- /* CONECTION PTR OF LQH */
- tuserblockref = signal->theData[1];
- /* BLOCK REFERENCE OF LQH */
- tresult = 0;
- if (cfreeopRec == RNIL) {
- jam();
- refaccConnectLab(signal);
- return;
- }//if
- seizeOpRec(signal);
- ptrGuard(operationRecPtr);
- operationRecPtr.p->userptr = tuserptr;
- operationRecPtr.p->userblockref = tuserblockref;
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- /* ******************************< */
- /* ACCSEIZECONF */
- /* ******************************< */
- signal->theData[0] = tuserptr;
- signal->theData[1] = operationRecPtr.i;
- sendSignal(tuserblockref, GSN_ACCSEIZECONF, signal, 2, JBB);
- return;
-}//Dbacc::execACCSEIZEREQ()
-
-void Dbacc::refaccConnectLab(Signal* signal)
-{
- tresult = ZCONNECT_SIZE_ERROR;
- /* ******************************< */
- /* ACCSEIZEREF */
- /* ******************************< */
- signal->theData[0] = tuserptr;
- signal->theData[1] = tresult;
- sendSignal(tuserblockref, GSN_ACCSEIZEREF, signal, 2, JBB);
- return;
-}//Dbacc::refaccConnectLab()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF CONNECTION MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* EXECUTE OPERATION MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* INIT_OP_REC */
-/* INFORMATION WHICH IS RECIEVED BY ACCKEYREQ WILL BE SAVED */
-/* IN THE OPERATION RECORD. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initOpRec(Signal* signal)
-{
- register Uint32 Treqinfo;
-
- Treqinfo = signal->theData[2];
-
- 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];
-
- Uint32 readFlag = (((Treqinfo >> 4) & 0x3) == 0); // Only 1 if Read
- Uint32 dirtyFlag = (((Treqinfo >> 6) & 0x1) == 1); // Only 1 if Dirty
- Uint32 dirtyReadFlag = readFlag & dirtyFlag;
-
- Uint32 opbits = 0;
- opbits |= Treqinfo & 0x7;
- opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_LOCK_MODE : 0;
- opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0;
- opbits |= (dirtyReadFlag) ? (Uint32) Operationrec::OP_DIRTY_READ : 0;
- opbits |= ((Treqinfo >> 31) & 0x1) ? (Uint32) Operationrec::OP_LOCK_REQ : 0;
-
- //operationRecPtr.p->nodeType = (Treqinfo >> 7) & 0x3;
- operationRecPtr.p->fid = fragrecptr.p->myfid;
- operationRecPtr.p->fragptr = fragrecptr.i;
- operationRecPtr.p->nextParallelQue = RNIL;
- operationRecPtr.p->prevParallelQue = RNIL;
- operationRecPtr.p->nextSerialQue = RNIL;
- operationRecPtr.p->prevSerialQue = RNIL;
- operationRecPtr.p->elementPage = RNIL;
- operationRecPtr.p->scanRecPtr = RNIL;
- operationRecPtr.p->m_op_bits = opbits;
-
- // bit to mark lock operation
- // undo log is not run via ACCKEYREQ
-
-}//Dbacc::initOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* SEND_ACCKEYCONF */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::sendAcckeyconf(Signal* signal)
-{
- signal->theData[0] = operationRecPtr.p->userptr;
- signal->theData[1] = operationRecPtr.p->m_op_bits & Operationrec::OP_MASK;
- 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;
-}//Dbacc::sendAcckeyconf()
-
-
-void
-Dbacc::ACCKEY_error(Uint32 fromWhere)
-{
- switch(fromWhere) {
- case 0:
- ndbrequire(false);
- case 1:
- ndbrequire(false);
- case 2:
- ndbrequire(false);
- case 3:
- ndbrequire(false);
- case 4:
- ndbrequire(false);
- case 5:
- ndbrequire(false);
- case 6:
- ndbrequire(false);
- case 7:
- ndbrequire(false);
- case 8:
- ndbrequire(false);
- case 9:
- ndbrequire(false);
- default:
- ndbrequire(false);
- }//switch
-}//Dbacc::ACCKEY_error()
-
-/* ******************--------------------------------------------------------------- */
-/* ACCKEYREQ REQUEST FOR INSERT, DELETE, */
-/* RERAD AND UPDATE, A TUPLE. */
-/* SENDER: LQH, LEVEL B */
-/* SIGNAL DATA: OPERATION_REC_PTR, CONNECTION PTR */
-/* TABPTR, TABLE ID = TABLE RECORD POINTER */
-/* TREQINFO, */
-/* THASHVALUE, HASH VALUE OF THE TUP */
-/* TKEYLEN, LENGTH OF THE PRIMARY KEYS */
-/* TKEY1, PRIMARY KEY 1 */
-/* TKEY2, PRIMARY KEY 2 */
-/* TKEY3, PRIMARY KEY 3 */
-/* TKEY4, PRIMARY KEY 4 */
-/* ******************--------------------------------------------------------------- */
-void Dbacc::execACCKEYREQ(Signal* signal)
-{
- jamEntry();
- operationRecPtr.i = signal->theData[0]; /* CONNECTION PTR */
- fragrecptr.i = signal->theData[1]; /* FRAGMENT RECORD POINTER */
- if (!((operationRecPtr.i < coprecsize) ||
- (fragrecptr.i < cfragmentsize))) {
- ACCKEY_error(0);
- return;
- }//if
- ptrAss(operationRecPtr, operationrec);
- ptrAss(fragrecptr, fragmentrec);
-
- ndbrequire(operationRecPtr.p->m_op_bits == Operationrec::OP_INITIAL);
-
- initOpRec(signal);
- // normalize key if any char attr
- if (operationRecPtr.p->tupkeylen && fragrecptr.p->hasCharAttr)
- xfrmKeyData(signal);
-
- /*---------------------------------------------------------------*/
- /* */
- /* WE WILL USE THE HASH VALUE TO LOOK UP THE PROPER MEMORY */
- /* PAGE AND MEMORY PAGE INDEX TO START THE SEARCH WITHIN. */
- /* WE REMEMBER THESE ADDRESS IF WE LATER NEED TO INSERT */
- /* THE ITEM AFTER NOT FINDING THE ITEM. */
- /*---------------------------------------------------------------*/
- OperationrecPtr lockOwnerPtr;
- const Uint32 found = getElement(signal, lockOwnerPtr);
-
- Uint32 opbits = operationRecPtr.p->m_op_bits;
- Uint32 op = opbits & Operationrec::OP_MASK;
- if (found == ZTRUE)
- {
- switch (op) {
- case ZREAD:
- case ZUPDATE:
- case ZDELETE:
- case ZWRITE:
- case ZSCAN_OP:
- if (!lockOwnerPtr.p)
- {
- if(op == ZWRITE)
- {
- jam();
- opbits &= ~(Uint32)Operationrec::OP_MASK;
- opbits |= (op = ZUPDATE);
- operationRecPtr.p->m_op_bits = opbits; // store to get correct ACCKEYCONF
- }
- opbits |= Operationrec::OP_STATE_RUNNING;
- opbits |= Operationrec::OP_RUN_QUEUE;
- sendAcckeyconf(signal);
- if (! (opbits & Operationrec::OP_DIRTY_READ)) {
- /*---------------------------------------------------------------*/
- // It is not a dirty read. We proceed by locking and continue with
- // the operation.
- /*---------------------------------------------------------------*/
- Uint32 eh = gePageptr.p->word32[tgeElementptr];
- operationRecPtr.p->scanBits = ElementHeader::getScanBits(eh);
- operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(eh);
- operationRecPtr.p->elementPage = gePageptr.i;
- operationRecPtr.p->elementContainer = tgeContainerptr;
- operationRecPtr.p->elementPointer = tgeElementptr;
- operationRecPtr.p->elementIsforward = tgeForward;
-
- eh = ElementHeader::setLocked(operationRecPtr.i);
- dbgWord32(gePageptr, tgeElementptr, eh);
- gePageptr.p->word32[tgeElementptr] = eh;
-
- opbits |= Operationrec::OP_LOCK_OWNER;
- insertLockOwnersList(signal, operationRecPtr);
- } else {
- jam();
- /*---------------------------------------------------------------*/
- // It is a dirty read. We do not lock anything. Set state to
- // IDLE since no COMMIT call will come.
- /*---------------------------------------------------------------*/
- opbits = Operationrec::OP_EXECUTED_DIRTY_READ;
- }//if
- operationRecPtr.p->m_op_bits = opbits;
- return;
- } else {
- jam();
- accIsLockedLab(signal, lockOwnerPtr);
- return;
- }//if
- break;
- case ZINSERT:
- jam();
- insertExistElemLab(signal, lockOwnerPtr);
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- } else if (found == ZFALSE) {
- switch (op){
- case ZWRITE:
- opbits &= ~(Uint32)Operationrec::OP_MASK;
- opbits |= (op = ZINSERT);
- case ZINSERT:
- jam();
- opbits |= Operationrec::OP_INSERT_IS_DONE;
- opbits |= Operationrec::OP_STATE_RUNNING;
- opbits |= Operationrec::OP_RUN_QUEUE;
- operationRecPtr.p->m_op_bits = opbits;
- insertelementLab(signal);
- return;
- break;
- case ZREAD:
- case ZUPDATE:
- case ZDELETE:
- case ZSCAN_OP:
- jam();
- acckeyref1Lab(signal, ZREAD_ERROR);
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- } else {
- jam();
- acckeyref1Lab(signal, found);
- return;
- }//if
- return;
-}//Dbacc::execACCKEYREQ()
-
-void
-Dbacc::execACCKEY_ORD(Signal* signal, Uint32 opPtrI)
-{
- jamEntry();
- OperationrecPtr lastOp;
- lastOp.i = opPtrI;
- ptrCheckGuard(lastOp, coprecsize, operationrec);
- Uint32 opbits = lastOp.p->m_op_bits;
- Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
-
- if (likely(opbits == Operationrec::OP_EXECUTED_DIRTY_READ))
- {
- jam();
- lastOp.p->m_op_bits = Operationrec::OP_INITIAL;
- return;
- }
- else if (likely(opstate == Operationrec::OP_STATE_RUNNING))
- {
- opbits |= Operationrec::OP_STATE_EXECUTED;
- lastOp.p->m_op_bits = opbits;
- startNext(signal, lastOp);
- return;
- }
- else
- {
- }
-
- ndbout_c("bits: %.8x state: %.8x", opbits, opstate);
- ndbrequire(false);
-}
-
-void
-Dbacc::startNext(Signal* signal, OperationrecPtr lastOp)
-{
- jam();
- OperationrecPtr nextOp;
- OperationrecPtr loPtr;
- nextOp.i = lastOp.p->nextParallelQue;
- loPtr.i = lastOp.p->m_lock_owner_ptr_i;
- Uint32 opbits = lastOp.p->m_op_bits;
-
- if ((opbits & Operationrec::OP_STATE_MASK)!= Operationrec::OP_STATE_EXECUTED)
- {
- jam();
- return;
- }
-
- Uint32 nextbits;
- if (nextOp.i != RNIL)
- {
- jam();
- ptrCheckGuard(nextOp, coprecsize, operationrec);
- nextbits = nextOp.p->m_op_bits;
- goto checkop;
- }
-
- if ((opbits & Operationrec::OP_LOCK_OWNER) == 0)
- {
- jam();
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- }
- else
- {
- jam();
- loPtr = lastOp;
- }
-
- nextOp.i = loPtr.p->nextSerialQue;
- ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
-
- if (nextOp.i == RNIL)
- {
- jam();
- return;
- }
-
- /**
- * There is an op in serie queue...
- * Check if it can run
- */
- ptrCheckGuard(nextOp, coprecsize, operationrec);
- nextbits = nextOp.p->m_op_bits;
-
- {
- const bool same = nextOp.p->is_same_trans(lastOp.p);
-
- if (!same && ((opbits & Operationrec::OP_ACC_LOCK_MODE) ||
- (nextbits & Operationrec::OP_LOCK_MODE)))
- {
- jam();
- /**
- * Not same transaction
- * and either last had exclusive lock
- * or next had exclusive lock
- */
- return;
- }
-
- /**
- * same trans and X-lock
- */
- if (same && (opbits & Operationrec::OP_ACC_LOCK_MODE))
- {
- jam();
- goto upgrade;
- }
- }
-
- /**
- * all shared lock...
- */
- if ((opbits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
- (nextbits & Operationrec::OP_LOCK_MODE) == 0)
- {
- jam();
- goto upgrade;
- }
-
- /**
- * There is a shared parallell queue & and exclusive op is first in queue
- */
- ndbassert((opbits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
- (nextbits & Operationrec::OP_LOCK_MODE));
-
- /**
- * We must check if there are many transactions in parallel queue...
- */
- OperationrecPtr tmp;
- tmp= loPtr;
- while (tmp.i != RNIL)
- {
- ptrCheckGuard(tmp, coprecsize, operationrec);
- if (!nextOp.p->is_same_trans(tmp.p))
- {
- jam();
- /**
- * parallel queue contained another transaction, dont let it run
- */
- return;
- }
- tmp.i = tmp.p->nextParallelQue;
- }
-
-upgrade:
- /**
- * Move first op in serie queue to end of parallell queue
- */
-
- tmp.i = loPtr.p->nextSerialQue = nextOp.p->nextSerialQue;
- loPtr.p->m_lo_last_parallel_op_ptr_i = nextOp.i;
- nextOp.p->nextSerialQue = RNIL;
- nextOp.p->prevSerialQue = RNIL;
- nextOp.p->m_lock_owner_ptr_i = loPtr.i;
- nextOp.p->prevParallelQue = lastOp.i;
- lastOp.p->nextParallelQue = nextOp.i;
-
- if (tmp.i != RNIL)
- {
- jam();
- ptrCheckGuard(tmp, coprecsize, operationrec);
- tmp.p->prevSerialQue = loPtr.i;
- }
- else
- {
- jam();
- loPtr.p->m_lo_last_serial_op_ptr_i = RNIL;
- }
-
- nextbits |= Operationrec::OP_RUN_QUEUE;
-
- /**
- * Currently no grouping of ops in serie queue
- */
- ndbrequire(nextOp.p->nextParallelQue == RNIL);
-
-checkop:
- Uint32 errCode = 0;
- OperationrecPtr save = operationRecPtr;
- operationRecPtr = nextOp;
-
- Uint32 lastop = opbits & Operationrec::OP_MASK;
- Uint32 nextop = nextbits & Operationrec::OP_MASK;
-
- nextbits &= nextbits & ~(Uint32)Operationrec::OP_STATE_MASK;
- nextbits |= Operationrec::OP_STATE_RUNNING;
-
- if (lastop == ZDELETE)
- {
- jam();
- if (nextop != ZINSERT && nextop != ZWRITE)
- {
- errCode = ZREAD_ERROR;
- goto ref;
- }
-
- nextbits &= ~(Uint32)Operationrec::OP_MASK;
- nextbits &= ~(Uint32)Operationrec::OP_ELEMENT_DISAPPEARED;
- nextbits |= (nextop = ZINSERT);
- nextbits |= Operationrec::OP_INSERT_IS_DONE;
- goto conf;
- }
- else if (nextop == ZINSERT)
- {
- jam();
- errCode = ZWRITE_ERROR;
- goto ref;
- }
- else if (nextop == ZWRITE)
- {
- jam();
- nextbits &= ~(Uint32)Operationrec::OP_MASK;
- nextbits |= (nextop = ZUPDATE);
- goto conf;
- }
- else
- {
- jam();
- }
-
-conf:
- nextOp.p->m_op_bits = nextbits;
- nextOp.p->localdata[0] = lastOp.p->localdata[0];
- nextOp.p->localdata[1] = lastOp.p->localdata[1];
-
- if (nextop == ZSCAN_OP && (nextbits & Operationrec::OP_LOCK_REQ) == 0)
- {
- jam();
- takeOutScanLockQueue(nextOp.p->scanRecPtr);
- putReadyScanQueue(signal, nextOp.p->scanRecPtr);
- }
- else
- {
- jam();
- fragrecptr.i = nextOp.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
-
- sendAcckeyconf(signal);
- sendSignal(nextOp.p->userblockref, GSN_ACCKEYCONF,
- signal, 6, JBB);
- }
-
- operationRecPtr = save;
- return;
-
-ref:
- nextOp.p->m_op_bits = nextbits;
-
- if (nextop == ZSCAN_OP && (nextbits & Operationrec::OP_LOCK_REQ) == 0)
- {
- jam();
- nextOp.p->m_op_bits |= Operationrec::OP_ELEMENT_DISAPPEARED;
- takeOutScanLockQueue(nextOp.p->scanRecPtr);
- putReadyScanQueue(signal, nextOp.p->scanRecPtr);
- }
- else
- {
- jam();
- signal->theData[0] = nextOp.p->userptr;
- signal->theData[1] = errCode;
- sendSignal(nextOp.p->userblockref, GSN_ACCKEYREF, signal,
- 2, JBB);
- }
-
- operationRecPtr = save;
- return;
-}
-
-
-#if 0
-void
-Dbacc::execACCKEY_REP_REF(Signal* signal, Uint32 opPtrI)
-{
-}
-#endif
-
-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, OperationrecPtr lockOwnerPtr)
-{
- ndbrequire(csystemRestart == ZFALSE);
-
- Uint32 bits = operationRecPtr.p->m_op_bits;
- validate_lock_queue(lockOwnerPtr);
-
- if ((bits & Operationrec::OP_DIRTY_READ) == 0){
- Uint32 return_result;
- if ((bits & Operationrec::OP_LOCK_MODE) == ZREADLOCK) {
- jam();
- return_result = placeReadInLockQueue(lockOwnerPtr);
- } else {
- jam();
- return_result = placeWriteInLockQueue(lockOwnerPtr);
- }//if
- if (return_result == ZPARALLEL_QUEUE) {
- jam();
- sendAcckeyconf(signal);
- return;
- } else if (return_result == ZSERIAL_QUEUE) {
- jam();
- signal->theData[0] = RNIL;
- return;
- } else {
- jam();
- acckeyref1Lab(signal, return_result);
- return;
- }//if
- ndbrequire(false);
- }
- else
- {
- if (!(lockOwnerPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED) &&
- lockOwnerPtr.p->localdata[0] != ~(Uint32)0)
- {
- jam();
- /* ---------------------------------------------------------------
- * It is a dirty read. We do not lock anything. Set state to
- *IDLE since no COMMIT call will arrive.
- * ---------------------------------------------------------------*/
- sendAcckeyconf(signal);
- operationRecPtr.p->m_op_bits = Operationrec::OP_EXECUTED_DIRTY_READ;
- return;
- }
- else
- {
- jam();
- /*---------------------------------------------------------------*/
- // The tuple does not exist in the committed world currently.
- // Report read error.
- /*---------------------------------------------------------------*/
- acckeyref1Lab(signal, ZREAD_ERROR);
- return;
- }//if
- }//if
-}//Dbacc::accIsLockedLab()
-
-/* ------------------------------------------------------------------------ */
-/* I N S E R T E X I S T E L E M E N T */
-/* ------------------------------------------------------------------------ */
-void Dbacc::insertExistElemLab(Signal* signal, OperationrecPtr lockOwnerPtr)
-{
- if (!lockOwnerPtr.p)
- {
- jam();
- acckeyref1Lab(signal, ZWRITE_ERROR);/* THE ELEMENT ALREADY EXIST */
- return;
- }//if
- accIsLockedLab(signal, lockOwnerPtr);
-}//Dbacc::insertExistElemLab()
-
-/* --------------------------------------------------------------------------------- */
-/* INSERTELEMENT */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::insertelementLab(Signal* signal)
-{
- if (fragrecptr.p->firstOverflowRec == RNIL) {
- jam();
- allocOverflowPage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- acckeyref1Lab(signal, tresult);
- return;
- }//if
- }//if
- ndbrequire(operationRecPtr.p->tupkeylen <= fragrecptr.p->keyLength);
- ndbassert(!(operationRecPtr.p->m_op_bits & Operationrec::OP_LOCK_REQ));
- Uint32 localKey = ~(Uint32)0;
-
- insertLockOwnersList(signal, operationRecPtr);
-
- const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits;
- operationRecPtr.p->hashvaluePart =
- (operationRecPtr.p->hashValue >> tmp) & 0xFFFF;
- operationRecPtr.p->scanBits = 0; /* NOT ANY ACTIVE SCAN */
- tidrElemhead = ElementHeader::setLocked(operationRecPtr.i);
- idrPageptr = gdiPageptr;
- tidrPageindex = tgdiPageindex;
- tidrForward = ZTRUE;
- idrOperationRecPtr = operationRecPtr;
- clocalkey[0] = localKey;
- operationRecPtr.p->localdata[0] = localKey;
- /* ----------------------------------------------------------------------- */
- /* WE SET THE LOCAL KEY TO MINUS ONE TO INDICATE IT IS NOT YET VALID. */
- /* ----------------------------------------------------------------------- */
- insertElement(signal);
- sendAcckeyconf(signal);
- return;
-}//Dbacc::insertelementLab()
-
-
-/* ------------------------------------------------------------------------ */
-/* GET_NO_PARALLEL_TRANSACTION */
-/* ------------------------------------------------------------------------ */
-Uint32
-Dbacc::getNoParallelTransaction(const Operationrec * op)
-{
- OperationrecPtr tmp;
-
- tmp.i= op->nextParallelQue;
- Uint32 transId[2] = { op->transId1, op->transId2 };
- while (tmp.i != RNIL)
- {
- jam();
- ptrCheckGuard(tmp, coprecsize, operationrec);
- if (tmp.p->transId1 == transId[0] && tmp.p->transId2 == transId[1])
- tmp.i = tmp.p->nextParallelQue;
- else
- return 2;
- }
- return 1;
-}//Dbacc::getNoParallelTransaction()
-
-#ifdef VM_TRACE
-Uint32
-Dbacc::getNoParallelTransactionFull(const Operationrec * op)
-{
- ConstPtr<Operationrec> tmp;
-
- tmp.p = op;
- while ((tmp.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
- {
- tmp.i = tmp.p->prevParallelQue;
- if (tmp.i != RNIL)
- {
- ptrCheckGuard(tmp, coprecsize, operationrec);
- }
- else
- {
- break;
- }
- }
-
- return getNoParallelTransaction(tmp.p);
-}
-#endif
-
-#ifdef ACC_SAFE_QUEUE
-
-Uint32
-Dbacc::get_parallel_head(OperationrecPtr opPtr)
-{
- while ((opPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
- opPtr.p->prevParallelQue != RNIL)
- {
- opPtr.i = opPtr.p->prevParallelQue;
- ptrCheckGuard(opPtr, coprecsize, operationrec);
- }
-
- return opPtr.i;
-}
-
-bool
-Dbacc::validate_lock_queue(OperationrecPtr opPtr)
-{
- OperationrecPtr loPtr;
- loPtr.i = get_parallel_head(opPtr);
- ptrCheckGuard(loPtr, coprecsize, operationrec);
-
- while((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
- loPtr.p->prevSerialQue != RNIL)
- {
- loPtr.i = loPtr.p->prevSerialQue;
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- }
-
- // Now we have lock owner...
- vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
- vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_RUN_QUEUE);
-
- // 1 Validate page pointer
- {
- Page8Ptr pagePtr;
- pagePtr.i = loPtr.p->elementPage;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- arrGuard(loPtr.p->elementPointer, 2048);
- Uint32 eh = pagePtr.p->word32[loPtr.p->elementPointer];
- vlqrequire(ElementHeader::getLocked(eh));
- vlqrequire(ElementHeader::getOpPtrI(eh) == loPtr.i);
- }
-
- // 2 Lock owner should always have same LOCK_MODE and ACC_LOCK_MODE
- if (loPtr.p->m_op_bits & Operationrec::OP_LOCK_MODE)
- {
- vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
- }
- else
- {
- vlqrequire((loPtr.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE) == 0);
- }
-
- // 3 Lock owner should never be waiting...
- bool running = false;
- {
- Uint32 opstate = loPtr.p->m_op_bits & Operationrec::OP_STATE_MASK;
- if (opstate == Operationrec::OP_STATE_RUNNING)
- running = true;
- else
- {
- vlqrequire(opstate == Operationrec::OP_STATE_EXECUTED);
- }
- }
-
- // Validate parallel queue
- {
- bool many = false;
- bool orlockmode = loPtr.p->m_op_bits & Operationrec::OP_LOCK_MODE;
- OperationrecPtr lastP = loPtr;
-
- while (lastP.p->nextParallelQue != RNIL)
- {
- Uint32 prev = lastP.i;
- lastP.i = lastP.p->nextParallelQue;
- ptrCheckGuard(lastP, coprecsize, operationrec);
-
- vlqrequire(lastP.p->prevParallelQue == prev);
-
- Uint32 opbits = lastP.p->m_op_bits;
- many |= loPtr.p->is_same_trans(lastP.p) ? 0 : 1;
- orlockmode |= !!(opbits & Operationrec::OP_LOCK_MODE);
-
- vlqrequire(opbits & Operationrec::OP_RUN_QUEUE);
- vlqrequire((opbits & Operationrec::OP_LOCK_OWNER) == 0);
-
- Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
- if (running)
- {
- // If I found a running operation,
- // all following should be waiting
- vlqrequire(opstate == Operationrec::OP_STATE_WAITING);
- }
- else
- {
- if (opstate == Operationrec::OP_STATE_RUNNING)
- running = true;
- else
- vlqrequire(opstate == Operationrec::OP_STATE_EXECUTED);
- }
-
- if (lastP.p->m_op_bits & Operationrec::OP_LOCK_MODE)
- {
- vlqrequire(lastP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
- }
- else
- {
- vlqrequire((lastP.p->m_op_bits && orlockmode) == orlockmode);
- vlqrequire((lastP.p->m_op_bits & Operationrec::OP_MASK) == ZREAD ||
- (lastP.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP);
- }
-
- if (many)
- {
- vlqrequire(orlockmode == 0);
- }
- }
-
- if (lastP.i != loPtr.i)
- {
- vlqrequire(loPtr.p->m_lo_last_parallel_op_ptr_i == lastP.i);
- vlqrequire(lastP.p->m_lock_owner_ptr_i == loPtr.i);
- }
- else
- {
- vlqrequire(loPtr.p->m_lo_last_parallel_op_ptr_i == RNIL);
- }
- }
-
- // Validate serie queue
- if (loPtr.p->nextSerialQue != RNIL)
- {
- Uint32 prev = loPtr.i;
- OperationrecPtr lastS;
- lastS.i = loPtr.p->nextSerialQue;
- while (true)
- {
- ptrCheckGuard(lastS, coprecsize, operationrec);
- vlqrequire(lastS.p->prevSerialQue == prev);
- vlqrequire(getNoParallelTransaction(lastS.p) == 1);
- vlqrequire((lastS.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0);
- vlqrequire((lastS.p->m_op_bits & Operationrec::OP_RUN_QUEUE) == 0);
- vlqrequire((lastS.p->m_op_bits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_WAITING);
- if (lastS.p->nextSerialQue == RNIL)
- break;
- prev = lastS.i;
- lastS.i = lastS.p->nextSerialQue;
- }
-
- vlqrequire(loPtr.p->m_lo_last_serial_op_ptr_i == lastS.i);
- }
- else
- {
- vlqrequire(loPtr.p->m_lo_last_serial_op_ptr_i == RNIL);
- }
- return true;
-}
-
-NdbOut&
-operator<<(NdbOut & out, Dbacc::OperationrecPtr ptr)
-{
- Uint32 opbits = ptr.p->m_op_bits;
- out << "[ " << dec << ptr.i
- << " [ " << hex << ptr.p->transId1
- << " " << hex << ptr.p->transId2 << "] "
- << " bits: H'" << hex << opbits << " ";
-
- bool read = false;
- switch(opbits & Dbacc::Operationrec::OP_MASK){
- case ZREAD: out << "READ "; read = true; break;
- case ZINSERT: out << "INSERT "; break;
- case ZUPDATE: out << "UPDATE "; break;
- case ZDELETE: out << "DELETE "; break;
- case ZWRITE: out << "WRITE "; break;
- case ZSCAN_OP: out << "SCAN "; read = true; break;
- default:
- out << "<Unknown: H'"
- << hex << (opbits & Dbacc::Operationrec::OP_MASK)
- << "> ";
- }
-
- if (read)
- {
- if (opbits & Dbacc::Operationrec::OP_LOCK_MODE)
- out << "(X)";
- else
- out << "(S)";
- if (opbits & Dbacc::Operationrec::OP_ACC_LOCK_MODE)
- out << "(X)";
- else
- out << "(S)";
- }
-
- if (opbits)
- {
- out << "(RQ)";
- }
-
- switch(opbits & Dbacc::Operationrec::OP_STATE_MASK){
- case Dbacc::Operationrec::OP_STATE_WAITING:
- out << " WAITING "; break;
- case Dbacc::Operationrec::OP_STATE_RUNNING:
- out << " RUNNING "; break;
- case Dbacc::Operationrec::OP_STATE_EXECUTED:
- out << " EXECUTED "; break;
- case Dbacc::Operationrec::OP_STATE_IDLE:
- out << " IDLE "; break;
- default:
- out << " <Unknown: H'"
- << hex << (opbits & Dbacc::Operationrec::OP_STATE_MASK)
- << "> ";
- }
-
-/*
- OP_MASK = 0x000F // 4 bits for operation type
- ,OP_LOCK_MODE = 0x0010 // 0 - shared lock, 1 = exclusive lock
- ,OP_ACC_LOCK_MODE = 0x0020 // Or:de lock mode of all operation
- // before me
- ,OP_LOCK_OWNER = 0x0040
- ,OP_DIRTY_READ = 0x0080
- ,OP_LOCK_REQ = 0x0100 // isAccLockReq
- ,OP_COMMIT_DELETE_CHECK = 0x0200
- ,OP_INSERT_IS_DONE = 0x0400
- ,OP_ELEMENT_DISAPPEARED = 0x0800
-
- ,OP_STATE_MASK = 0xF000
- ,OP_STATE_IDLE = 0xF000
- ,OP_STATE_WAITING = 0x0000
- ,OP_STATE_RUNNING = 0x1000
- ,OP_STATE_EXECUTED = 0x3000
- };
-*/
- if (opbits & Dbacc::Operationrec::OP_LOCK_OWNER)
- out << "LO ";
-
- if (opbits & Dbacc::Operationrec::OP_DIRTY_READ)
- out << "DR ";
-
- if (opbits & Dbacc::Operationrec::OP_LOCK_REQ)
- out << "LOCK_REQ ";
-
- if (opbits & Dbacc::Operationrec::OP_COMMIT_DELETE_CHECK)
- out << "COMMIT_DELETE_CHECK ";
-
- if (opbits & Dbacc::Operationrec::OP_INSERT_IS_DONE)
- out << "INSERT_IS_DONE ";
-
- if (opbits & Dbacc::Operationrec::OP_ELEMENT_DISAPPEARED)
- out << "ELEMENT_DISAPPEARED ";
-
- if (opbits & Dbacc::Operationrec::OP_LOCK_OWNER)
- {
- out << "last_parallel: " << dec << ptr.p->m_lo_last_parallel_op_ptr_i << " ";
- out << "last_serial: " << dec << ptr.p->m_lo_last_serial_op_ptr_i << " ";
- }
-
- out << "]";
- return out;
-}
-
-void
-Dbacc::dump_lock_queue(OperationrecPtr loPtr)
-{
- if ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
- {
- while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
- loPtr.p->prevParallelQue != RNIL)
- {
- loPtr.i = loPtr.p->prevParallelQue;
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- }
-
- while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
- loPtr.p->prevSerialQue != RNIL)
- {
- loPtr.i = loPtr.p->prevSerialQue;
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- }
-
- ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
- }
-
- ndbout << "-- HEAD --" << endl;
- OperationrecPtr tmp = loPtr;
- while (tmp.i != RNIL)
- {
- ptrCheckGuard(tmp, coprecsize, operationrec);
- ndbout << tmp << " ";
- tmp.i = tmp.p->nextParallelQue;
-
- if (tmp.i == loPtr.i)
- {
- ndbout << " <LOOP>";
- break;
- }
- }
- ndbout << endl;
-
- tmp.i = loPtr.p->nextSerialQue;
- while (tmp.i != RNIL)
- {
- ptrCheckGuard(tmp, coprecsize, operationrec);
- OperationrecPtr tmp2 = tmp;
-
- if (tmp.i == loPtr.i)
- {
- ndbout << "<LOOP S>" << endl;
- break;
- }
-
- while (tmp2.i != RNIL)
- {
- ptrCheckGuard(tmp2, coprecsize, operationrec);
- ndbout << tmp2 << " ";
- tmp2.i = tmp2.p->nextParallelQue;
-
- if (tmp2.i == tmp.i)
- {
- ndbout << "<LOOP 3>";
- break;
- }
- }
- ndbout << endl;
- tmp.i = tmp.p->nextSerialQue;
- }
-}
-#endif
-
-/* -------------------------------------------------------------------------
- * PLACE_WRITE_IN_LOCK_QUEUE
- * INPUT: OPERATION_REC_PTR OUR OPERATION POINTER
- * QUE_OPER_PTR LOCK QUEUE OWNER OPERATION POINTER
- * PWI_PAGEPTR PAGE POINTER OF ELEMENT
- * TPWI_ELEMENTPTR ELEMENT POINTER OF ELEMENT
- * OUTPUT TRESULT =
- * ZPARALLEL_QUEUE OPERATION PLACED IN PARALLEL QUEUE
- * OPERATION CAN PROCEED NOW.
- * ZSERIAL_QUEUE OPERATION PLACED IN SERIAL QUEUE
- * ERROR CODE OPERATION NEEDS ABORTING
- * ------------------------------------------------------------------------- */
-Uint32
-Dbacc::placeWriteInLockQueue(OperationrecPtr lockOwnerPtr)
-{
- OperationrecPtr lastOpPtr;
- lastOpPtr.i = lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i;
- Uint32 opbits = operationRecPtr.p->m_op_bits;
-
- if (lastOpPtr.i == RNIL)
- {
- lastOpPtr = lockOwnerPtr;
- }
- else
- {
- ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
- }
-
- ndbassert(get_parallel_head(lastOpPtr) == lockOwnerPtr.i);
-
- Uint32 lastbits = lastOpPtr.p->m_op_bits;
- if (lastbits & Operationrec::OP_ACC_LOCK_MODE)
- {
- if(operationRecPtr.p->is_same_trans(lastOpPtr.p))
- {
- goto checkop;
- }
- }
- else
- {
- /**
- * We dont have an exclusive lock on operation and
- *
- */
- jam();
-
- /**
- * Scan parallell queue to see if we are the only one
- */
- OperationrecPtr loopPtr = lockOwnerPtr;
- do
- {
- ptrCheckGuard(loopPtr, coprecsize, operationrec);
- if (!loopPtr.p->is_same_trans(operationRecPtr.p))
- {
- goto serial;
- }
- loopPtr.i = loopPtr.p->nextParallelQue;
- } while (loopPtr.i != RNIL);
-
- goto checkop;
- }
-
-serial:
- jam();
- placeSerialQueue(lockOwnerPtr, operationRecPtr);
-
- validate_lock_queue(lockOwnerPtr);
-
- return ZSERIAL_QUEUE;
-
-checkop:
- /*
- WE ARE PERFORMING AN READ EXCLUSIVE, INSERT, UPDATE OR DELETE IN THE SAME
- TRANSACTION WHERE WE PREVIOUSLY HAVE EXECUTED AN OPERATION.
- Read-All, Update-All, Insert-All and Delete-Insert are allowed
- combinations.
- Delete-Read, Delete-Update and Delete-Delete are not an allowed
- combination and will result in tuple not found error.
- */
- Uint32 lstate = lastbits & Operationrec::OP_STATE_MASK;
-
- Uint32 retValue = ZSERIAL_QUEUE; // So that it gets blocked...
- if (lstate == Operationrec::OP_STATE_EXECUTED)
- {
- jam();
-
- /**
- * Since last operation has executed...we can now check operation types
- * if not, we have to wait until it has executed
- */
- Uint32 op = opbits & Operationrec::OP_MASK;
- Uint32 lop = lastbits & Operationrec::OP_MASK;
- if (op == ZINSERT && lop != ZDELETE)
- {
- jam();
- return ZWRITE_ERROR;
- }//if
-
- /**
- * NOTE. No checking op operation types, as one can read different save
- * points...
- */
-#if 0
- if (lop == ZDELETE && (op != ZINSERT && op != ZWRITE))
- {
- jam();
- return ZREAD_ERROR;
- }
-#else
- if (lop == ZDELETE && (op == ZUPDATE && op == ZDELETE))
- {
- jam();
- return ZREAD_ERROR;
- }
-#endif
-
- if(op == ZWRITE)
- {
- opbits &= ~(Uint32)Operationrec::OP_MASK;
- opbits |= (lop == ZDELETE) ? ZINSERT : ZUPDATE;
- }
-
- opbits |= Operationrec::OP_STATE_RUNNING;
- operationRecPtr.p->localdata[0] = lastOpPtr.p->localdata[0];
- operationRecPtr.p->localdata[1] = lastOpPtr.p->localdata[1];
- retValue = ZPARALLEL_QUEUE;
- }
-
- opbits |= Operationrec::OP_RUN_QUEUE;
- operationRecPtr.p->m_op_bits = opbits;
- operationRecPtr.p->prevParallelQue = lastOpPtr.i;
- operationRecPtr.p->m_lock_owner_ptr_i = lockOwnerPtr.i;
- lastOpPtr.p->nextParallelQue = operationRecPtr.i;
- lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i = operationRecPtr.i;
-
- validate_lock_queue(lockOwnerPtr);
-
- return retValue;
-}//Dbacc::placeWriteInLockQueue()
-
-Uint32
-Dbacc::placeReadInLockQueue(OperationrecPtr lockOwnerPtr)
-{
- OperationrecPtr lastOpPtr;
- OperationrecPtr loopPtr = lockOwnerPtr;
- lastOpPtr.i = lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i;
- Uint32 opbits = operationRecPtr.p->m_op_bits;
-
- if (lastOpPtr.i == RNIL)
- {
- lastOpPtr = lockOwnerPtr;
- }
- else
- {
- ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
- }
-
- ndbassert(get_parallel_head(lastOpPtr) == lockOwnerPtr.i);
-
- /**
- * Last operation in parallell queue of lock owner is same trans
- * and ACC_LOCK_MODE is exlusive, then we can proceed
- */
- Uint32 lastbits = lastOpPtr.p->m_op_bits;
- bool same = operationRecPtr.p->is_same_trans(lastOpPtr.p);
- if (same && (lastbits & Operationrec::OP_ACC_LOCK_MODE))
- {
- jam();
- opbits |= Operationrec::OP_LOCK_MODE; // Upgrade to X-lock
- goto checkop;
- }
-
- if ((lastbits & Operationrec::OP_ACC_LOCK_MODE) && !same)
- {
- jam();
- /**
- * Last op in serial queue had X-lock and was not our transaction...
- */
- goto serial;
- }
-
- if (lockOwnerPtr.p->nextSerialQue == RNIL)
- {
- jam();
- goto checkop;
- }
-
- /**
- * Scan parallell queue to see if we are already there...
- */
- do
- {
- ptrCheckGuard(loopPtr, coprecsize, operationrec);
- if (loopPtr.p->is_same_trans(operationRecPtr.p))
- goto checkop;
- loopPtr.i = loopPtr.p->nextParallelQue;
- } while (loopPtr.i != RNIL);
-
-serial:
- placeSerialQueue(lockOwnerPtr, operationRecPtr);
-
- validate_lock_queue(lockOwnerPtr);
-
- return ZSERIAL_QUEUE;
-
-checkop:
- Uint32 lstate = lastbits & Operationrec::OP_STATE_MASK;
-
- Uint32 retValue = ZSERIAL_QUEUE; // So that it gets blocked...
- if (lstate == Operationrec::OP_STATE_EXECUTED)
- {
- jam();
-
- /**
- * NOTE. No checking op operation types, as one can read different save
- * points...
- */
-
-#if 0
- /**
- * Since last operation has executed...we can now check operation types
- * if not, we have to wait until it has executed
- */
- if (lop == ZDELETE)
- {
- jam();
- return ZREAD_ERROR;
- }
-#endif
-
- opbits |= Operationrec::OP_STATE_RUNNING;
- operationRecPtr.p->localdata[0] = lastOpPtr.p->localdata[0];
- operationRecPtr.p->localdata[1] = lastOpPtr.p->localdata[1];
- retValue = ZPARALLEL_QUEUE;
- }
- opbits |= (lastbits & Operationrec::OP_ACC_LOCK_MODE);
- opbits |= Operationrec::OP_RUN_QUEUE;
- operationRecPtr.p->m_op_bits = opbits;
-
- operationRecPtr.p->prevParallelQue = lastOpPtr.i;
- operationRecPtr.p->m_lock_owner_ptr_i = lockOwnerPtr.i;
- lastOpPtr.p->nextParallelQue = operationRecPtr.i;
- lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i = operationRecPtr.i;
-
- validate_lock_queue(lockOwnerPtr);
-
- return retValue;
-}//Dbacc::placeReadInLockQueue
-
-void Dbacc::placeSerialQueue(OperationrecPtr lockOwnerPtr,
- OperationrecPtr opPtr)
-{
- OperationrecPtr lastOpPtr;
- lastOpPtr.i = lockOwnerPtr.p->m_lo_last_serial_op_ptr_i;
-
- if (lastOpPtr.i == RNIL)
- {
- // Lock owner is last...
- ndbrequire(lockOwnerPtr.p->nextSerialQue == RNIL);
- lastOpPtr = lockOwnerPtr;
- }
- else
- {
- ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
- }
-
- operationRecPtr.p->prevSerialQue = lastOpPtr.i;
- lastOpPtr.p->nextSerialQue = opPtr.i;
- lockOwnerPtr.p->m_lo_last_serial_op_ptr_i = opPtr.i;
-}
-
-/* ------------------------------------------------------------------------- */
-/* ACC KEYREQ END */
-/* ------------------------------------------------------------------------- */
-void Dbacc::acckeyref1Lab(Signal* signal, Uint32 result_code)
-{
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- /* ************************<< */
- /* ACCKEYREF */
- /* ************************<< */
- signal->theData[0] = cminusOne;
- signal->theData[1] = result_code;
- return;
-}//Dbacc::acckeyref1Lab()
-
-/* ******************----------------------------------------------------- */
-/* ACCMINUPDATE UPDATE LOCAL KEY REQ */
-/* DESCRIPTION: UPDATES LOCAL KEY OF AN ELEMENTS IN THE HASH TABLE */
-/* THIS SIGNAL IS WAITED AFTER ANY INSERT REQ */
-/* ENTER ACCMINUPDATE WITH SENDER: LQH, LEVEL B */
-/* OPERATION_REC_PTR, OPERATION RECORD PTR */
-/* CLOCALKEY(0), LOCAL KEY 1 */
-/* CLOCALKEY(1) LOCAL KEY 2 */
-/* ******************----------------------------------------------------- */
-void Dbacc::execACCMINUPDATE(Signal* signal)
-{
- Page8Ptr ulkPageidptr;
- Uint32 tulkLocalPtr;
- Uint32 tlocalkey1, tlocalkey2;
-
- jamEntry();
- operationRecPtr.i = signal->theData[0];
- tlocalkey1 = signal->theData[1];
- tlocalkey2 = signal->theData[2];
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- Uint32 opbits = operationRecPtr.p->m_op_bits;
- fragrecptr.i = operationRecPtr.p->fragptr;
- ulkPageidptr.i = operationRecPtr.p->elementPage;
- tulkLocalPtr = operationRecPtr.p->elementPointer +
- operationRecPtr.p->elementIsforward;
-
- if ((opbits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_RUNNING)
- {
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- ptrCheckGuard(ulkPageidptr, cpagesize, page8);
- dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey1);
- arrGuard(tulkLocalPtr, 2048);
- ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey1;
- operationRecPtr.p->localdata[0] = tlocalkey1;
- if (likely(fragrecptr.p->localkeylen == 1))
- {
- return;
- }
- else if (fragrecptr.p->localkeylen == 2)
- {
- jam();
- tulkLocalPtr = tulkLocalPtr + operationRecPtr.p->elementIsforward;
- operationRecPtr.p->localdata[1] = tlocalkey2;
- dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey2);
- arrGuard(tulkLocalPtr, 2048);
- ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey2;
- return;
- } else {
- jam();
- }//if
- }//if
- ndbrequire(false);
-}//Dbacc::execACCMINUPDATE()
-
-/* ******************--------------------------------------------------------------- */
-/* ACC_COMMITREQ COMMIT TRANSACTION */
-/* SENDER: LQH, LEVEL B */
-/* INPUT: OPERATION_REC_PTR , */
-/* ******************--------------------------------------------------------------- */
-void Dbacc::execACC_COMMITREQ(Signal* signal)
-{
- Uint8 Toperation;
- jamEntry();
- Uint32 tmp = operationRecPtr.i = signal->theData[0];
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- void* ptr = operationRecPtr.p;
- Uint32 opbits = operationRecPtr.p->m_op_bits;
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- Toperation = opbits & Operationrec::OP_MASK;
- commitOperation(signal);
- ndbassert(operationRecPtr.i == tmp);
- ndbassert(operationRecPtr.p == ptr);
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- if(Toperation != ZREAD){
- fragrecptr.p->m_commit_count++;
- if (Toperation != ZINSERT) {
- if (Toperation != ZDELETE) {
- return;
- } else {
- jam();
- fragrecptr.p->noOfElements--;
- fragrecptr.p->slack += fragrecptr.p->elementLength;
- if (fragrecptr.p->slack > fragrecptr.p->slackCheck) {
- /* TIME FOR JOIN BUCKETS PROCESS */
- if (fragrecptr.p->expandCounter > 0) {
- if (fragrecptr.p->expandFlag < 2) {
- jam();
- signal->theData[0] = fragrecptr.i;
- signal->theData[1] = fragrecptr.p->p;
- signal->theData[2] = fragrecptr.p->maxp;
- signal->theData[3] = fragrecptr.p->expandFlag;
- fragrecptr.p->expandFlag = 2;
- sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
- }//if
- }//if
- }//if
- }//if
- } else {
- jam(); /* EXPAND PROCESS HANDLING */
- fragrecptr.p->noOfElements++;
- fragrecptr.p->slack -= fragrecptr.p->elementLength;
- if (fragrecptr.p->slack >= (1u << 31)) {
- /* IT MEANS THAT IF SLACK < ZERO */
- if (fragrecptr.p->expandFlag == 0) {
- jam();
- fragrecptr.p->expandFlag = 2;
- signal->theData[0] = fragrecptr.i;
- signal->theData[1] = fragrecptr.p->p;
- signal->theData[2] = fragrecptr.p->maxp;
- sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
- }//if
- }//if
- }
- }
- return;
-}//Dbacc::execACC_COMMITREQ()
-
-/* ******************------------------------------------------------------- */
-/* ACC ABORT REQ ABORT ALL OPERATION OF THE TRANSACTION */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-/* ******************------------------------------------------------------- */
-/* ACC ABORT REQ ABORT TRANSACTION */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execACC_ABORTREQ(Signal* signal)
-{
- jamEntry();
- operationRecPtr.i = signal->theData[0];
- Uint32 sendConf = signal->theData[1];
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- fragrecptr.i = operationRecPtr.p->fragptr;
- Uint32 opbits = operationRecPtr.p->m_op_bits;
- Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
- tresult = 0; /* ZFALSE */
-
- if (opbits == Operationrec::OP_EXECUTED_DIRTY_READ)
- {
- jam();
- }
- else if (opstate == Operationrec::OP_STATE_EXECUTED ||
- opstate == Operationrec::OP_STATE_WAITING ||
- opstate == Operationrec::OP_STATE_RUNNING)
- {
- jam();
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- abortOperation(signal);
- }
-
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
-
- signal->theData[0] = operationRecPtr.p->userptr;
- signal->theData[1] = 0;
- switch(sendConf){
- case 0:
- return;
- case 2:
- if (opstate != Operationrec::OP_STATE_RUNNING)
- {
- return;
- }
- case 1:
- sendSignal(operationRecPtr.p->userblockref, GSN_ACC_ABORTCONF,
- signal, 1, JBB);
- }
-
- signal->theData[1] = RNIL;
-}
-
-/*
- * Lock or unlock tuple.
- */
-void Dbacc::execACC_LOCKREQ(Signal* signal)
-{
- jamEntry();
- AccLockReq* sig = (AccLockReq*)signal->getDataPtrSend();
- AccLockReq reqCopy = *sig;
- AccLockReq* const req = &reqCopy;
- Uint32 lockOp = (req->requestInfo & 0xFF);
- if (lockOp == AccLockReq::LockShared ||
- lockOp == AccLockReq::LockExclusive) {
- jam();
- // find table
- tabptr.i = req->tableId;
- ptrCheckGuard(tabptr, ctablesize, tabrec);
- // find fragment (TUX will know it)
- if (req->fragPtrI == RNIL) {
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabptr.p->fragholder[i] == req->fragId){
- jam();
- req->fragPtrI = tabptr.p->fragptrholder[i];
- break;
- }
- }
- }
- fragrecptr.i = req->fragPtrI;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- ndbrequire(req->fragId == fragrecptr.p->myfid);
- // caller must be explicit here
- ndbrequire(req->accOpPtr == RNIL);
- // seize operation to hold the lock
- if (cfreeopRec != RNIL) {
- jam();
- seizeOpRec(signal);
- // init as in ACCSEIZEREQ
- operationRecPtr.p->userptr = req->userPtr;
- operationRecPtr.p->userblockref = req->userRef;
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- operationRecPtr.p->scanRecPtr = RNIL;
- // do read with lock via ACCKEYREQ
- Uint32 lockMode = (lockOp == AccLockReq::LockShared) ? 0 : 1;
- Uint32 opCode = ZSCAN_OP;
- signal->theData[0] = operationRecPtr.i;
- signal->theData[1] = fragrecptr.i;
- signal->theData[2] = opCode | (lockMode << 4) | (1u << 31);
- signal->theData[3] = req->hashValue;
- signal->theData[4] = 0; // search local key
- 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
- if (signal->theData[0] < RNIL) {
- jam();
- req->returnCode = AccLockReq::Success;
- req->accOpPtr = operationRecPtr.i;
- } else if (signal->theData[0] == RNIL) {
- jam();
- req->returnCode = AccLockReq::IsBlocked;
- req->accOpPtr = operationRecPtr.i;
- } else {
- ndbrequire(signal->theData[0] == (UintR)-1);
- releaseOpRec(signal);
- req->returnCode = AccLockReq::Refused;
- req->accOpPtr = RNIL;
- }
- } else {
- jam();
- req->returnCode = AccLockReq::NoFreeOp;
- }
- *sig = *req;
- return;
- }
- if (lockOp == AccLockReq::Unlock) {
- jam();
- // do unlock via ACC_COMMITREQ (immediate)
- signal->theData[0] = req->accOpPtr;
- EXECUTE_DIRECT(DBACC, GSN_ACC_COMMITREQ, signal, 1);
- releaseOpRec(signal);
- req->returnCode = AccLockReq::Success;
- *sig = *req;
- return;
- }
- if (lockOp == AccLockReq::Abort) {
- jam();
- // do abort via ACC_ABORTREQ (immediate)
- signal->theData[0] = req->accOpPtr;
- signal->theData[1] = 0; // Dont send abort
- execACC_ABORTREQ(signal);
- releaseOpRec(signal);
- req->returnCode = AccLockReq::Success;
- *sig = *req;
- return;
- }
- if (lockOp == AccLockReq::AbortWithConf) {
- jam();
- // do abort via ACC_ABORTREQ (with conf signal)
- signal->theData[0] = req->accOpPtr;
- signal->theData[1] = 1; // send abort
- execACC_ABORTREQ(signal);
- releaseOpRec(signal);
- req->returnCode = AccLockReq::Success;
- *sig = *req;
- return;
- }
- ndbrequire(false);
-}
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF EXECUTE OPERATION MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* MODULE: INSERT */
-/* THE FOLLOWING SUBROUTINES ARE ONLY USED BY INSERT_ELEMENT. THIS */
-/* ROUTINE IS THE SOLE INTERFACE TO INSERT ELEMENTS INTO THE INDEX. */
-/* CURRENT USERS ARE INSERT REQUESTS, EXPAND CONTAINER AND SHRINK */
-/* CONTAINER. */
-/* */
-/* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */
-/* INSERT_ELEMENT */
-/* INSERT_CONTAINER */
-/* ADDNEWCONTAINER */
-/* GETFREELIST */
-/* INCREASELISTCONT */
-/* SEIZE_LEFTLIST */
-/* SEIZE_RIGHTLIST */
-/* */
-/* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */
-/* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */
-/* TAKE_REC_OUT_OF_FREE_OVERPAGE AND RELEASE_OVERFLOW_REC ARE */
-/* EXCEPTIONS TO THIS RULE. */
-/* */
-/* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */
-/* THOSE DEFINED AS INPUT AND OUTPUT IN INSERT_ELEMENT */
-/* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */
-/* AND POINTER VARIABLES. */
-/* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */
-/* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */
-/* EXECUTION. */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* INSERT_ELEMENT */
-/* INPUT: */
-/* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */
-/* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */
-/* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */
-/* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */
-/* CIDR_KEYS(ARRAY OF TUPLE KEYS) */
-/* CLOCALKEY(ARRAY OF LOCAL KEYS). */
-/* FRAGRECPTR */
-/* IDR_OPERATION_REC_PTR */
-/* TIDR_KEY_LEN */
-/* */
-/* OUTPUT: */
-/* TIDR_PAGEINDEX (PAGE INDEX OF INSERTED ELEMENT) */
-/* IDR_PAGEPTR (PAGE POINTER OF INSERTED ELEMENT) */
-/* TIDR_FORWARD (CONTAINER DIRECTION OF INSERTED ELEMENT) */
-/* NONE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::insertElement(Signal* signal)
-{
- DirRangePtr inrOverflowrangeptr;
- DirectoryarrayPtr inrOverflowDirptr;
- OverflowRecordPtr inrOverflowRecPtr;
- Page8Ptr inrNewPageptr;
- Uint32 tinrNextSamePage;
- Uint32 tinrTmp;
-
- do {
- insertContainer(signal);
- if (tidrResult != ZFALSE) {
- jam();
- return;
- /* INSERTION IS DONE, OR */
- /* AN ERROR IS DETECTED */
- }//if
- if (((tidrContainerhead >> 7) & 0x3) != 0) {
- tinrNextSamePage = (tidrContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
- /* THE NEXT CONTAINER IS IN THE SAME PAGE */
- tidrPageindex = tidrContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
- if (((tidrContainerhead >> 7) & 3) == ZLEFT) {
- jam();
- tidrForward = ZTRUE;
- } else if (((tidrContainerhead >> 7) & 3) == ZRIGHT) {
- jam();
- tidrForward = cminusOne;
- } else {
- ndbrequire(false);
- return;
- }//if
- if (tinrNextSamePage == ZFALSE) {
- jam(); /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
- tinrTmp = idrPageptr.p->word32[tidrContainerptr + 1];
- inrOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(inrOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tinrTmp >> 8), 256);
- inrOverflowDirptr.i = inrOverflowrangeptr.p->dirArray[tinrTmp >> 8];
- ptrCheckGuard(inrOverflowDirptr, cdirarraysize, directoryarray);
- idrPageptr.i = inrOverflowDirptr.p->pagep[tinrTmp & 0xff];
- ptrCheckGuard(idrPageptr, cpagesize, page8);
- }//if
- ndbrequire(tidrPageindex < ZEMPTYLIST);
- } else {
- break;
- }//if
- } while (1);
- gflPageptr.p = idrPageptr.p;
- getfreelist(signal);
- if (tgflPageindex == ZEMPTYLIST) {
- jam();
- /* NO FREE BUFFER IS FOUND */
- if (fragrecptr.p->firstOverflowRec == RNIL) {
- jam();
- allocOverflowPage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- }//if
- inrOverflowRecPtr.i = fragrecptr.p->firstOverflowRec;
- ptrCheckGuard(inrOverflowRecPtr, coverflowrecsize, overflowRecord);
- inrNewPageptr.i = inrOverflowRecPtr.p->overpage;
- ptrCheckGuard(inrNewPageptr, cpagesize, page8);
- gflPageptr.p = inrNewPageptr.p;
- getfreelist(signal);
- ndbrequire(tgflPageindex != ZEMPTYLIST);
- tancNext = 0;
- } else {
- jam();
- inrNewPageptr = idrPageptr;
- tancNext = 1;
- }//if
- tslUpdateHeader = ZTRUE;
- tslPageindex = tgflPageindex;
- slPageptr.p = inrNewPageptr.p;
- if (tgflBufType == ZLEFT) {
- seizeLeftlist(signal);
- tidrForward = ZTRUE;
- } else {
- seizeRightlist(signal);
- tidrForward = cminusOne;
- }//if
- tancPageindex = tgflPageindex;
- tancPageid = inrNewPageptr.p->word32[ZPOS_PAGE_ID];
- tancBufType = tgflBufType;
- tancContainerptr = tidrContainerptr;
- ancPageptr.p = idrPageptr.p;
- addnewcontainer(signal);
-
- idrPageptr = inrNewPageptr;
- tidrPageindex = tgflPageindex;
- insertContainer(signal);
- ndbrequire(tidrResult == ZTRUE);
-}//Dbacc::insertElement()
-
-/* --------------------------------------------------------------------------------- */
-/* INSERT_CONTAINER */
-/* INPUT: */
-/* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */
-/* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */
-/* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */
-/* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */
-/* CKEYS(ARRAY OF TUPLE KEYS) */
-/* CLOCALKEY(ARRAY 0F LOCAL KEYS). */
-/* TIDR_KEY_LEN */
-/* FRAGRECPTR */
-/* IDR_OPERATION_REC_PTR */
-/* OUTPUT: */
-/* TIDR_RESULT (ZTRUE FOR SUCCESS AND ZFALSE OTHERWISE) */
-/* TIDR_CONTAINERHEAD (HEADER OF CONTAINER) */
-/* TIDR_CONTAINERPTR (POINTER TO CONTAINER HEADER) */
-/* */
-/* DESCRIPTION: */
-/* THE FREE AREA OF THE CONTAINER WILL BE CALCULATED. IF IT IS */
-/* LARGER THAN OR EQUAL THE ELEMENT LENGTH. THE ELEMENT WILL BE */
-/* INSERT IN THE CONTAINER AND CONTAINER HEAD WILL BE UPDATED. */
-/* THIS ROUTINE ALWAYS DEALS WITH ONLY ONE CONTAINER AND DO NEVER */
-/* START ANYTHING OUTSIDE OF THIS CONTAINER. */
-/* */
-/* SHORT FORM: IDR */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::insertContainer(Signal* signal)
-{
- Uint32 tidrContainerlen;
- Uint32 tidrConfreelen;
- Uint32 tidrNextSide;
- Uint32 tidrNextConLen;
- Uint32 tidrIndex;
- Uint32 tidrInputIndex;
- Uint32 tidrContLen;
- Uint32 guard26;
-
- tidrResult = ZFALSE;
- tidrContainerptr = (tidrPageindex << ZSHIFT_PLUS) - (tidrPageindex << ZSHIFT_MINUS);
- tidrContainerptr = tidrContainerptr + ZHEAD_SIZE;
- /* --------------------------------------------------------------------------------- */
- /* CALCULATE THE POINTER TO THE ELEMENT TO BE INSERTED AND THE POINTER TO THE */
- /* CONTAINER HEADER OF THE OTHER SIDE OF THE BUFFER. */
- /* --------------------------------------------------------------------------------- */
- if (tidrForward == ZTRUE) {
- jam();
- tidrNextSide = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
- arrGuard(tidrNextSide + 1, 2048);
- tidrContainerhead = idrPageptr.p->word32[tidrContainerptr];
- tidrContainerlen = tidrContainerhead >> 26;
- tidrIndex = tidrContainerptr + tidrContainerlen;
- } else {
- jam();
- tidrNextSide = tidrContainerptr;
- tidrContainerptr = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
- arrGuard(tidrContainerptr + 1, 2048);
- tidrContainerhead = idrPageptr.p->word32[tidrContainerptr];
- tidrContainerlen = tidrContainerhead >> 26;
- tidrIndex = (tidrContainerptr - tidrContainerlen) + (ZCON_HEAD_SIZE - 1);
- }//if
- if (tidrContainerlen > (ZBUF_SIZE - 3)) {
- return;
- }//if
- tidrConfreelen = ZBUF_SIZE - tidrContainerlen;
- /* --------------------------------------------------------------------------------- */
- /* WE CALCULATE THE TOTAL LENGTH THE CONTAINER CAN EXPAND TO */
- /* THIS INCLUDES THE OTHER SIDE OF THE BUFFER IF POSSIBLE TO EXPAND THERE. */
- /* --------------------------------------------------------------------------------- */
- if (((tidrContainerhead >> 10) & 1) == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE NOT EXPANDED TO THE ENTIRE BUFFER YET. WE CAN THUS READ THE OTHER */
- /* SIDE'S CONTAINER HEADER TO READ HIS LENGTH. */
- /* --------------------------------------------------------------------------------- */
- tidrNextConLen = idrPageptr.p->word32[tidrNextSide] >> 26;
- tidrConfreelen = tidrConfreelen - tidrNextConLen;
- if (tidrConfreelen > ZBUF_SIZE) {
- ndbrequire(false);
- /* --------------------------------------------------------------------------------- */
- /* THE BUFFERS ARE PLACED ON TOP OF EACH OTHER. THIS SHOULD NEVER OCCUR. */
- /* --------------------------------------------------------------------------------- */
- return;
- }//if
- } else {
- jam();
- tidrNextConLen = 1; /* INDICATE OTHER SIDE IS NOT PART OF FREE LIST */
- }//if
- if (tidrConfreelen < fragrecptr.p->elementLength) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE CONTAINER COULD NOT BE EXPANDED TO FIT THE NEW ELEMENT. WE HAVE TO */
- /* RETURN AND FIND A NEW CONTAINER TO INSERT IT INTO. */
- /* --------------------------------------------------------------------------------- */
- return;
- }//if
- tidrContainerlen = tidrContainerlen + fragrecptr.p->elementLength;
- if (tidrNextConLen == 0) {
- /* EACH SIDE OF THE BUFFER WHICH BELONG TO A FREE */
- /* LIST, HAS ZERO AS LENGTH. */
- if (tidrContainerlen > ZUP_LIMIT) {
- dbgWord32(idrPageptr, tidrContainerptr, idrPageptr.p->word32[tidrContainerptr] | (1 << 10));
- idrPageptr.p->word32[tidrContainerptr] = idrPageptr.p->word32[tidrContainerptr] | (1 << 10);
- tslUpdateHeader = ZFALSE;
- tslPageindex = tidrPageindex;
- slPageptr.p = idrPageptr.p;
- if (tidrForward == ZTRUE) {
- jam();
- seizeRightlist(signal); /* REMOVE THE RIGHT SIDE OF THE BUFFER FROM THE LIST */
- } else {
- jam();
- /* OF THE FREE CONTAINERS */
- seizeLeftlist(signal); /* REMOVE THE LEFT SIDE OF THE BUFFER FROM THE LIST */
- }//if
- }//if
- }//if
- /* OF THE FREE CONTAINERS */
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE NOW FOUND A FREE SPOT IN THE CURRENT CONTAINER. WE INSERT THE */
- /* ELEMENT HERE. THE ELEMENT CONTAINS A HEADER, A LOCAL KEY AND A TUPLE KEY. */
- /* BEFORE INSERTING THE ELEMENT WE WILL UPDATE THE OPERATION RECORD WITH THE */
- /* DATA CONCERNING WHERE WE INSERTED THE ELEMENT. THIS MAKES IT EASY TO FIND */
- /* THIS INFORMATION WHEN WE RETURN TO UPDATE THE LOCAL KEY OR RETURN TO COMMIT */
- /* OR ABORT THE INSERT. IF NO OPERATION RECORD EXIST IT MEANS THAT WE ARE */
- /* PERFORMING THIS AS A PART OF THE EXPAND OR SHRINK PROCESS. */
- /* --------------------------------------------------------------------------------- */
- if (idrOperationRecPtr.i != RNIL) {
- jam();
- idrOperationRecPtr.p->elementIsforward = tidrForward;
- idrOperationRecPtr.p->elementPage = idrPageptr.i;
- idrOperationRecPtr.p->elementContainer = tidrContainerptr;
- idrOperationRecPtr.p->elementPointer = tidrIndex;
- }//if
- /* --------------------------------------------------------------------------------- */
- /* WE CHOOSE TO UNDO LOG INSERTS BY WRITING THE BEFORE VALUE TO THE UNDO LOG. */
- /* WE COULD ALSO HAVE DONE THIS BY WRITING THIS BEFORE VALUE WHEN DELETING */
- /* ELEMENTS. WE CHOOSE TO PUT IT HERE SINCE WE THEREBY ENSURE THAT WE ALWAYS */
- /* UNDO LOG ALL WRITES TO PAGE MEMORY. IT SHOULD BE EASIER TO MAINTAIN SUCH A */
- /* STRUCTURE. IT IS RATHER DIFFICULT TO MAINTAIN A LOGICAL STRUCTURE WHERE */
- /* DELETES ARE INSERTS AND INSERTS ARE PURELY DELETES. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(idrPageptr, tidrIndex, tidrElemhead);
- idrPageptr.p->word32[tidrIndex] = tidrElemhead; /* INSERTS THE HEAD OF THE ELEMENT */
- tidrIndex += tidrForward;
- guard26 = fragrecptr.p->localkeylen - 1;
- arrGuard(guard26, 2);
- for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) {
- dbgWord32(idrPageptr, tidrIndex, clocalkey[tidrInputIndex]);
- arrGuard(tidrIndex, 2048);
- idrPageptr.p->word32[tidrIndex] = clocalkey[tidrInputIndex]; /* INSERTS LOCALKEY */
- tidrIndex += tidrForward;
- }//for
- tidrContLen = idrPageptr.p->word32[tidrContainerptr] << 6;
- tidrContLen = tidrContLen >> 6;
- dbgWord32(idrPageptr, tidrContainerptr, (tidrContainerlen << 26) | tidrContLen);
- idrPageptr.p->word32[tidrContainerptr] = (tidrContainerlen << 26) | tidrContLen;
- tidrResult = ZTRUE;
-}//Dbacc::insertContainer()
-
-/* --------------------------------------------------------------------------------- */
-/* ADDNEWCONTAINER */
-/* INPUT: */
-/* TANC_CONTAINERPTR */
-/* ANC_PAGEPTR */
-/* TANC_NEXT */
-/* TANC_PAGEINDEX */
-/* TANC_BUF_TYPE */
-/* TANC_PAGEID */
-/* OUTPUT: */
-/* NONE */
-/* */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::addnewcontainer(Signal* signal)
-{
- Uint32 tancTmp1;
-
- /* THE OLD DATA IS STORED ON AN UNDO PAGE */
- /* --------------------------------------------------------------------------------- */
- /* KEEP LENGTH INFORMATION IN BIT 26-31. */
- /* SET BIT 9 INDICATING IF NEXT BUFFER IN THE SAME PAGE USING TANC_NEXT. */
- /* SET TYPE OF NEXT CONTAINER IN BIT 7-8. */
- /* SET PAGE INDEX OF NEXT CONTAINER IN BIT 0-6. */
- /* KEEP INDICATOR OF OWNING OTHER SIDE OF BUFFER IN BIT 10. */
- /* --------------------------------------------------------------------------------- */
- tancTmp1 = ancPageptr.p->word32[tancContainerptr] >> 10;
- tancTmp1 = tancTmp1 << 1;
- tancTmp1 = tancTmp1 | tancNext;
- tancTmp1 = tancTmp1 << 2;
- tancTmp1 = tancTmp1 | tancBufType; /* TYPE OF THE NEXT CONTAINER */
- tancTmp1 = tancTmp1 << 7;
- tancTmp1 = tancTmp1 | tancPageindex;
- dbgWord32(ancPageptr, tancContainerptr, tancTmp1);
- ancPageptr.p->word32[tancContainerptr] = tancTmp1; /* HEAD OF THE CONTAINER IS UPDATED */
- dbgWord32(ancPageptr, tancContainerptr + 1, tancPageid);
- ancPageptr.p->word32[tancContainerptr + 1] = tancPageid;
-}//Dbacc::addnewcontainer()
-
-/* --------------------------------------------------------------------------------- */
-/* GETFREELIST */
-/* INPUT: */
-/* GFL_PAGEPTR (POINTER TO A PAGE RECORD). */
-/* OUTPUT: */
-/* TGFL_PAGEINDEX(POINTER TO A FREE BUFFER IN THE FREEPAGE), AND */
-/* TGFL_BUF_TYPE( TYPE OF THE FREE BUFFER). */
-/* DESCRIPTION: SEARCHS IN THE FREE LIST OF THE FREE BUFFER IN THE PAGE HEAD */
-/* (WORD32(1)),AND RETURN ADDRESS OF A FREE BUFFER OR NIL. */
-/* THE FREE BUFFER CAN BE A RIGHT CONTAINER OR A LEFT ONE */
-/* THE KIND OF THE CONTAINER IS NOTED BY TGFL_BUF_TYPE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::getfreelist(Signal* signal)
-{
- Uint32 tgflTmp;
-
- tgflTmp = gflPageptr.p->word32[ZPOS_EMPTY_LIST];
- tgflPageindex = (tgflTmp >> 7) & 0x7f; /* LEFT FREE LIST */
- tgflBufType = ZLEFT;
- if (tgflPageindex == ZEMPTYLIST) {
- jam();
- tgflPageindex = tgflTmp & 0x7f; /* RIGHT FREE LIST */
- tgflBufType = ZRIGHT;
- }//if
- ndbrequire(tgflPageindex <= ZEMPTYLIST);
-}//Dbacc::getfreelist()
-
-/* --------------------------------------------------------------------------------- */
-/* INCREASELISTCONT */
-/* INPUT: */
-/* ILC_PAGEPTR PAGE POINTER TO INCREASE NUMBER OF CONTAINERS IN */
-/* A CONTAINER OF AN OVERFLOW PAGE (FREEPAGEPTR) IS ALLOCATED, NR OF */
-/* ALLOCATED CONTAINER HAVE TO BE INCRESE BY ONE . */
-/* IF THE NUMBER OF ALLOCATED CONTAINERS IS ABOVE THE FREE LIMIT WE WILL */
-/* REMOVE THE PAGE FROM THE FREE LIST. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::increaselistcont(Signal* signal)
-{
- OverflowRecordPtr ilcOverflowRecPtr;
-
- dbgWord32(ilcPageptr, ZPOS_ALLOC_CONTAINERS, ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1);
- ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1;
- if (ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
- if (ilcPageptr.p->word32[ZPOS_OVERFLOWREC] != RNIL) {
- jam();
- ilcOverflowRecPtr.i = ilcPageptr.p->word32[ZPOS_OVERFLOWREC];
- dbgWord32(ilcPageptr, ZPOS_OVERFLOWREC, RNIL);
- ilcPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- ptrCheckGuard(ilcOverflowRecPtr, coverflowrecsize, overflowRecord);
- tfoOverflowRecPtr = ilcOverflowRecPtr;
- takeRecOutOfFreeOverpage(signal);
- rorOverflowRecPtr = ilcOverflowRecPtr;
- releaseOverflowRec(signal);
- }//if
- }//if
-}//Dbacc::increaselistcont()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_LEFTLIST */
-/* INPUT: */
-/* TSL_PAGEINDEX PAGE INDEX OF CONTAINER TO SEIZE */
-/* SL_PAGEPTR PAGE POINTER OF CONTAINER TO SEIZE */
-/* TSL_UPDATE_HEADER SHOULD WE UPDATE THE CONTAINER HEADER */
-/* */
-/* OUTPUT: */
-/* NONE */
-/* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */
-/* LIST OF LEFT FREE CONTAINER, IN THE HEADER OF THE PAGE */
-/* (FREEPAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */
-/* WILL BE UPDATED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeLeftlist(Signal* signal)
-{
- Uint32 tsllTmp1;
- Uint32 tsllNewHead;
- Uint32 tsllHeadIndex;
- Uint32 tsllTmp;
-
- tsllHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ZHEAD_SIZE;
- arrGuard(tsllHeadIndex + 1, 2048);
- tslNextfree = slPageptr.p->word32[tsllHeadIndex];
- tslPrevfree = slPageptr.p->word32[tsllHeadIndex + 1];
- if (tslPrevfree == ZEMPTYLIST) {
- jam();
- /* UPDATE FREE LIST OF LEFT CONTAINER IN PAGE HEAD */
- tsllTmp1 = slPageptr.p->word32[ZPOS_EMPTY_LIST];
- tsllTmp = tsllTmp1 & 0x7f;
- tsllTmp1 = (tsllTmp1 >> 14) << 14;
- tsllTmp1 = (tsllTmp1 | (tslNextfree << 7)) | tsllTmp;
- dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp1);
- slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp1;
- } else {
- ndbrequire(tslPrevfree < ZEMPTYLIST);
- jam();
- tsllTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
- dbgWord32(slPageptr, tsllTmp, tslNextfree);
- slPageptr.p->word32[tsllTmp] = tslNextfree;
- }//if
- if (tslNextfree < ZEMPTYLIST) {
- jam();
- tsllTmp = (((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE) + 1;
- dbgWord32(slPageptr, tsllTmp, tslPrevfree);
- slPageptr.p->word32[tsllTmp] = tslPrevfree;
- } else {
- ndbrequire(tslNextfree == ZEMPTYLIST);
- jam();
- }//if
- /* --------------------------------------------------------------------------------- */
- /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */
- /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */
- /* LISTS IN THE PAGE. */
- /* */
- /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */
- /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */
- /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */
- /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */
- /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */
- /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */
- /* WE ALSO SET BIT 25 TO INDICATE THAT IT IS A CONTAINER HEADER. */
- /* --------------------------------------------------------------------------------- */
- if (tslUpdateHeader == ZTRUE) {
- jam();
- tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- tsllNewHead = ZCON_HEAD_SIZE;
- tsllNewHead = ((tsllNewHead << 8) + ZEMPTYLIST) + (1 << 7);
- tsllNewHead = (tsllNewHead << 7) + tslNextfree;
- tsllNewHead = tsllNewHead << 11;
- dbgWord32(slPageptr, tsllHeadIndex, tsllNewHead);
- slPageptr.p->word32[tsllHeadIndex] = tsllNewHead;
- tsllTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff;
- tsllTmp = tsllTmp | (tslPageindex << 23);
- dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp);
- slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp;
- if (tslNextfree < ZEMPTYLIST) {
- jam();
- tsllTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
- tsllTmp1 = slPageptr.p->word32[tsllTmp] & 0xfe03ffff;
- tsllTmp1 = tsllTmp1 | (tslPageindex << 18);
- dbgWord32(slPageptr, tsllTmp, tsllTmp1);
- slPageptr.p->word32[tsllTmp] = tsllTmp1;
- } else {
- ndbrequire(tslNextfree == ZEMPTYLIST);
- jam();
- }//if
- }//if
- ilcPageptr.p = slPageptr.p;
- increaselistcont(signal);
-}//Dbacc::seizeLeftlist()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_RIGHTLIST */
-/* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */
-/* LIST OF RIGHT FREE CONTAINER, IN THE HEADER OF THE PAGE */
-/* (SL_PAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */
-/* WILL BE UPDATED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeRightlist(Signal* signal)
-{
- Uint32 tsrlTmp1;
- Uint32 tsrlNewHead;
- Uint32 tsrlHeadIndex;
- Uint32 tsrlTmp;
-
- tsrlHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- arrGuard(tsrlHeadIndex + 1, 2048);
- tslNextfree = slPageptr.p->word32[tsrlHeadIndex];
- tslPrevfree = slPageptr.p->word32[tsrlHeadIndex + 1];
- if (tslPrevfree == ZEMPTYLIST) {
- jam();
- tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST];
- dbgWord32(slPageptr, ZPOS_EMPTY_LIST, ((tsrlTmp >> 7) << 7) | tslNextfree);
- slPageptr.p->word32[ZPOS_EMPTY_LIST] = ((tsrlTmp >> 7) << 7) | tslNextfree;
- } else {
- ndbrequire(tslPrevfree < ZEMPTYLIST);
- jam();
- tsrlTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- dbgWord32(slPageptr, tsrlTmp, tslNextfree);
- slPageptr.p->word32[tsrlTmp] = tslNextfree;
- }//if
- if (tslNextfree < ZEMPTYLIST) {
- jam();
- tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1));
- dbgWord32(slPageptr, tsrlTmp, tslPrevfree);
- slPageptr.p->word32[tsrlTmp] = tslPrevfree;
- } else {
- ndbrequire(tslNextfree == ZEMPTYLIST);
- jam();
- }//if
- /* --------------------------------------------------------------------------------- */
- /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */
- /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */
- /* LISTS IN THE PAGE. */
- /* */
- /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */
- /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */
- /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */
- /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */
- /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */
- /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */
- /* --------------------------------------------------------------------------------- */
- if (tslUpdateHeader == ZTRUE) {
- jam();
- tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- tsrlNewHead = ZCON_HEAD_SIZE;
- tsrlNewHead = ((tsrlNewHead << 8) + ZEMPTYLIST) + (1 << 7);
- tsrlNewHead = (tsrlNewHead << 7) + tslNextfree;
- tsrlNewHead = tsrlNewHead << 11;
- dbgWord32(slPageptr, tsrlHeadIndex, tsrlNewHead);
- slPageptr.p->word32[tsrlHeadIndex] = tsrlNewHead;
- tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff;
- dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsrlTmp | (tslPageindex << 16));
- slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsrlTmp | (tslPageindex << 16);
- if (tslNextfree < ZEMPTYLIST) {
- jam();
- tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tsrlTmp1 = slPageptr.p->word32[tsrlTmp] & 0xfe03ffff;
- dbgWord32(slPageptr, tsrlTmp, tsrlTmp1 | (tslPageindex << 18));
- slPageptr.p->word32[tsrlTmp] = tsrlTmp1 | (tslPageindex << 18);
- } else {
- ndbrequire(tslNextfree == ZEMPTYLIST);
- jam();
- }//if
- }//if
- ilcPageptr.p = slPageptr.p;
- increaselistcont(signal);
-}//Dbacc::seizeRightlist()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF INSERT_ELEMENT MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* 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 */
-/* */
-/* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */
-/* GET_ELEMENT */
-/* GET_DIRINDEX */
-/* SEARCH_LONG_KEY */
-/* */
-/* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */
-/* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */
-/* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */
-/* THOSE DEFINED AS INPUT AND OUTPUT IN GET_ELEMENT AND GETDIRINDEX */
-/* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */
-/* AND POINTER VARIABLES. */
-/* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */
-/* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */
-/* EXECUTION. */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* GETDIRINDEX */
-/* SUPPORT ROUTINE FOR INSERT ELEMENT, GET ELEMENT AND COMMITDELETE */
-/* INPUT:FRAGRECPTR ( POINTER TO THE ACTIVE FRAGMENT REC) */
-/* OPERATION_REC_PTR (POINTER TO THE OPERATION REC). */
-/* */
-/* OUTPUT:GDI_PAGEPTR ( POINTER TO THE PAGE OF THE ELEMENT) */
-/* TGDI_PAGEINDEX ( INDEX OF THE ELEMENT IN THE PAGE). */
-/* */
-/* DESCRIPTION: CHECK THE HASH VALUE OF THE OPERATION REC AND CALCULATE THE */
-/* THE ADDRESS OF THE ELEMENT IN THE HASH TABLE,(GDI_PAGEPTR, */
-/* TGDI_PAGEINDEX) ACCORDING TO LH3. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::getdirindex(Signal* signal)
-{
- DirRangePtr gdiDirRangePtr;
- DirectoryarrayPtr gdiDirptr;
- Uint32 tgdiTmp;
- Uint32 tgdiAddress;
-
- tgdiTmp = fragrecptr.p->k + fragrecptr.p->lhfragbits; /* OBS K = 6 */
- tgdiPageindex = operationRecPtr.p->hashValue & ((1 << fragrecptr.p->k) - 1);
- tgdiTmp = operationRecPtr.p->hashValue >> tgdiTmp;
- tgdiTmp = (tgdiTmp << fragrecptr.p->k) | tgdiPageindex;
- tgdiAddress = tgdiTmp & fragrecptr.p->maxp;
- gdiDirRangePtr.i = fragrecptr.p->directory;
- ptrCheckGuard(gdiDirRangePtr, cdirrangesize, dirRange);
- if (tgdiAddress < fragrecptr.p->p) {
- jam();
- tgdiAddress = tgdiTmp & ((fragrecptr.p->maxp << 1) | 1);
- }//if
- tgdiTmp = tgdiAddress >> fragrecptr.p->k;
- arrGuard((tgdiTmp >> 8), 256);
- gdiDirptr.i = gdiDirRangePtr.p->dirArray[tgdiTmp >> 8];
- ptrCheckGuard(gdiDirptr, cdirarraysize, directoryarray);
- gdiPageptr.i = gdiDirptr.p->pagep[tgdiTmp & 0xff]; /* DIRECTORY INDEX OF SEND BUCKET PAGE */
- ptrCheckGuard(gdiPageptr, cpagesize, page8);
-}//Dbacc::getdirindex()
-
-Uint32
-Dbacc::readTablePk(Uint32 localkey1, Uint32 eh, Ptr<Operationrec> opPtr)
-{
- int ret;
- Uint32 tableId = fragrecptr.p->myTableId;
- Uint32 fragId = fragrecptr.p->myfid;
- bool xfrm = fragrecptr.p->hasCharAttr;
-
-#ifdef VM_TRACE
- memset(ckeys, 0x1f, (fragrecptr.p->keyLength * MAX_XFRM_MULTIPLY) << 2);
-#endif
-
- if (likely(localkey1 != ~(Uint32)0))
- {
- Uint32 fragPageId = localkey1 >> MAX_TUPLES_BITS;
- Uint32 pageIndex = localkey1 & ((1 << MAX_TUPLES_BITS ) - 1);
- ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex,
- ckeys, true);
- }
- else
- {
- ndbrequire(ElementHeader::getLocked(eh));
- if (unlikely((opPtr.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP))
- {
- dump_lock_queue(opPtr);
- ndbrequire(opPtr.p->nextParallelQue == RNIL);
- ndbrequire(opPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED);
- ndbrequire(opPtr.p->m_op_bits & Operationrec::OP_COMMIT_DELETE_CHECK);
- ndbrequire((opPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_RUNNING);
- return 0;
- }
- ret = c_lqh->readPrimaryKeys(opPtr.p->userptr, ckeys, xfrm);
- }
- jamEntry();
- ndbrequire(ret >= 0);
- return ret;
-}
-
-/* --------------------------------------------------------------------------------- */
-/* GET_ELEMENT */
-/* INPUT: */
-/* OPERATION_REC_PTR */
-/* FRAGRECPTR */
-/* OUTPUT: */
-/* TGE_RESULT RESULT SUCCESS = ZTRUE OTHERWISE ZFALSE */
-/* TGE_LOCKED LOCK INFORMATION IF SUCCESSFUL RESULT */
-/* GE_PAGEPTR PAGE POINTER OF FOUND ELEMENT */
-/* TGE_CONTAINERPTR CONTAINER INDEX OF FOUND ELEMENT */
-/* TGE_ELEMENTPTR ELEMENT INDEX OF FOUND ELEMENT */
-/* TGE_FORWARD DIRECTION OF CONTAINER WHERE ELEMENT FOUND */
-/* */
-/* DESCRIPTION: THE SUBROUTIN GOES THROUGH ALL CONTAINERS OF THE ACTIVE */
-/* BUCKET, AND SERCH FOR ELEMENT.THE PRIMARY KEYS WHICH IS SAVED */
-/* IN THE OPERATION REC ARE THE CHECK ITEMS IN THE SEARCHING. */
-/* --------------------------------------------------------------------------------- */
-
-#if __ia64 == 1
-#if __INTEL_COMPILER == 810
-int ndb_acc_ia64_icc810_dummy_var = 0;
-void ndb_acc_ia64_icc810_dummy_func()
-{
- ndb_acc_ia64_icc810_dummy_var++;
-}
-#endif
-#endif
-
-Uint32
-Dbacc::getElement(Signal* signal, OperationrecPtr& lockOwnerPtr)
-{
- Uint32 errcode;
- DirRangePtr geOverflowrangeptr;
- DirectoryarrayPtr geOverflowDirptr;
- Uint32 tgeElementHeader;
- Uint32 tgeElemStep;
- Uint32 tgeContainerhead;
- Uint32 tgePageindex;
- Uint32 tgeActivePageDir;
- Uint32 tgeNextptrtype;
- register Uint32 tgeKeyptr;
- register Uint32 tgeRemLen;
- register Uint32 TelemLen = fragrecptr.p->elementLength;
- register Uint32* Tkeydata = (Uint32*)&signal->theData[7];
-
- getdirindex(signal);
- tgePageindex = tgdiPageindex;
- gePageptr = gdiPageptr;
- /*
- * 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->tupkeylen == 0;
-
- ndbrequire(TelemLen == ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
- tgeNextptrtype = ZLEFT;
-
- const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits;
- const Uint32 opHashValuePart = (operationRecPtr.p->hashValue >> tmp) &0xFFFF;
- do {
- tgeContainerptr = (tgePageindex << ZSHIFT_PLUS) - (tgePageindex << ZSHIFT_MINUS);
- if (tgeNextptrtype == ZLEFT) {
- jam();
- tgeContainerptr = tgeContainerptr + ZHEAD_SIZE;
- tgeElementptr = tgeContainerptr + ZCON_HEAD_SIZE;
- tgeKeyptr = (tgeElementptr + ZELEM_HEAD_SIZE) + fragrecptr.p->localkeylen;
- tgeElemStep = TelemLen;
- tgeForward = 1;
- if (unlikely(tgeContainerptr >= 2048))
- {
- errcode = 4;
- goto error;
- }
- tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26;
- if (unlikely(((tgeContainerptr + tgeRemLen - 1) >= 2048)))
- {
- errcode = 5;
- goto error;
- }
- } else if (tgeNextptrtype == ZRIGHT) {
- jam();
- tgeContainerptr = tgeContainerptr + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tgeElementptr = tgeContainerptr - 1;
- tgeKeyptr = (tgeElementptr - ZELEM_HEAD_SIZE) - fragrecptr.p->localkeylen;
- tgeElemStep = 0 - TelemLen;
- tgeForward = (Uint32)-1;
- if (unlikely(tgeContainerptr >= 2048))
- {
- errcode = 4;
- goto error;
- }
- tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26;
- if (unlikely((tgeContainerptr - tgeRemLen) >= 2048))
- {
- errcode = 5;
- goto error;
- }
- } else {
- errcode = 6;
- goto error;
- }//if
- if (tgeRemLen >= ZCON_HEAD_SIZE + TelemLen) {
- if (unlikely(tgeRemLen > ZBUF_SIZE))
- {
- errcode = 7;
- goto error;
- }//if
- /* ------------------------------------------------------------------- */
- // There is at least one element in this container.
- // Check if it is the element searched for.
- /* ------------------------------------------------------------------- */
- do {
- tgeElementHeader = gePageptr.p->word32[tgeElementptr];
- tgeRemLen = tgeRemLen - TelemLen;
- Uint32 hashValuePart;
- Uint32 localkey1, localkey2;
- lockOwnerPtr.i = RNIL;
- lockOwnerPtr.p = NULL;
- if (ElementHeader::getLocked(tgeElementHeader)) {
- jam();
- lockOwnerPtr.i = ElementHeader::getOpPtrI(tgeElementHeader);
- ptrCheckGuard(lockOwnerPtr, coprecsize, operationrec);
- hashValuePart = lockOwnerPtr.p->hashvaluePart;
- localkey1 = lockOwnerPtr.p->localdata[0];
- localkey2 = lockOwnerPtr.p->localdata[1];
- } else {
- jam();
- hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
- localkey1 = gePageptr.p->word32[tgeElementptr + tgeForward];
- localkey2 = 0;
- }
- if (hashValuePart == opHashValuePart) {
- jam();
- bool found;
- if (! searchLocalKey)
- {
- Uint32 len = readTablePk(localkey1, tgeElementHeader,
- lockOwnerPtr);
- found = (len == operationRecPtr.p->xfrmtupkeylen) &&
- (memcmp(Tkeydata, ckeys, len << 2) == 0);
- } else {
- jam();
- found = (localkey1 == Tkeydata[0]);
- }
- if (found)
- {
- jam();
- operationRecPtr.p->localdata[0] = localkey1;
- operationRecPtr.p->localdata[1] = localkey2;
- return ZTRUE;
- }
- }
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (true);
- }//if
- if (unlikely(tgeRemLen != ZCON_HEAD_SIZE))
- {
- errcode = 8;
- goto error;
- }//if
- tgeContainerhead = gePageptr.p->word32[tgeContainerptr];
- tgeNextptrtype = (tgeContainerhead >> 7) & 0x3;
- if (tgeNextptrtype == 0) {
- jam();
- return ZFALSE; /* NO MORE CONTAINER */
- }//if
- tgePageindex = tgeContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
- if (unlikely(tgePageindex > ZEMPTYLIST))
- {
- errcode = 9;
- goto error;
- }//if
- if (((tgeContainerhead >> 9) & 1) == ZFALSE) {
- jam();
- tgeActivePageDir = gePageptr.p->word32[tgeContainerptr + 1]; /* NEXT PAGE ID */
- geOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(geOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tgeActivePageDir >> 8), 256);
- geOverflowDirptr.i = geOverflowrangeptr.p->dirArray[tgeActivePageDir >> 8];
- ptrCheckGuard(geOverflowDirptr, cdirarraysize, directoryarray);
- gePageptr.i = geOverflowDirptr.p->pagep[tgeActivePageDir & 0xff];
- ptrCheckGuard(gePageptr, cpagesize, page8);
- }//if
- } while (1);
-
- return ZFALSE;
-
-error:
- ACCKEY_error(errcode);
- return ~0;
-}//Dbacc::getElement()
-
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* */
-/* END OF GET_ELEMENT MODULE */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* */
-/* MODULE: DELETE */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* COMMITDELETE */
-/* INPUT: OPERATION_REC_PTR, PTR TO AN OPERATION RECORD. */
-/* FRAGRECPTR, PTR TO A FRAGMENT RECORD */
-/* */
-/* OUTPUT: */
-/* NONE */
-/* DESCRIPTION: DELETE OPERATIONS WILL BE COMPLETED AT THE
- * COMMIT OF TRANSACTION. THIS SUBROUTINE SEARCHS FOR ELEMENT AND
- * DELETES IT. IT DOES SO BY REPLACING IT WITH THE LAST
- * ELEMENT IN THE BUCKET. IF THE DELETED ELEMENT IS ALSO THE LAST
- * ELEMENT THEN IT IS ONLY NECESSARY TO REMOVE THE ELEMENT
- * ------------------------------------------------------------------------- */
-void
-Dbacc::report_dealloc(Signal* signal, const Operationrec* opPtrP)
-{
- Uint32 localKey = opPtrP->localdata[0];
- Uint32 opbits = opPtrP->m_op_bits;
- Uint32 userptr= opPtrP->userptr;
- Uint32 scanInd =
- ((opbits & Operationrec::OP_MASK) == ZSCAN_OP) ||
- (opbits & Operationrec::OP_LOCK_REQ);
-
- if (localKey != ~(Uint32)0)
- {
- signal->theData[0] = fragrecptr.p->myfid;
- signal->theData[1] = fragrecptr.p->myTableId;
- Uint32 pageId = localKey >> MAX_TUPLES_BITS;
- Uint32 pageIndex = localKey & ((1 << MAX_TUPLES_BITS) - 1);
- signal->theData[2] = pageId;
- signal->theData[3] = pageIndex;
- signal->theData[4] = userptr;
- signal->theData[5] = scanInd;
- EXECUTE_DIRECT(DBLQH, GSN_TUP_DEALLOCREQ, signal, 6);
- jamEntry();
- }
-}
-
-void Dbacc::commitdelete(Signal* signal)
-{
- jam();
- report_dealloc(signal, operationRecPtr.p);
-
- getdirindex(signal);
- tlastPageindex = tgdiPageindex;
- lastPageptr.i = gdiPageptr.i;
- lastPageptr.p = gdiPageptr.p;
- tlastForward = ZTRUE;
- tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS);
- tlastContainerptr = tlastContainerptr + ZHEAD_SIZE;
- arrGuard(tlastContainerptr, 2048);
- tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
- tlastContainerlen = tlastContainerhead >> 26;
- lastPrevpageptr.i = RNIL;
- ptrNull(lastPrevpageptr);
- tlastPrevconptr = 0;
- getLastAndRemove(signal);
-
- delPageptr.i = operationRecPtr.p->elementPage;
- ptrCheckGuard(delPageptr, cpagesize, page8);
- tdelElementptr = operationRecPtr.p->elementPointer;
- /* --------------------------------------------------------------------------------- */
- // Here we have to take extreme care since we do not want locks to end up after the
- // log execution. Thus it is necessary to put back the element in unlocked shape.
- // We thus update the element header to ensure we log an unlocked element. We do not
- // need to restore it later since it is deleted immediately anyway.
- /* --------------------------------------------------------------------------------- */
- const Uint32 hv = operationRecPtr.p->hashvaluePart;
- const Uint32 eh = ElementHeader::setUnlocked(hv, 0);
- delPageptr.p->word32[tdelElementptr] = eh;
- if (operationRecPtr.p->elementPage == lastPageptr.i) {
- if (operationRecPtr.p->elementPointer == tlastElementptr) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE LAST ELEMENT WAS THE ELEMENT TO BE DELETED. WE NEED NOT COPY IT. */
- /* --------------------------------------------------------------------------------- */
- return;
- }//if
- }//if
- /* --------------------------------------------------------------------------------- */
- /* THE DELETED ELEMENT IS NOT THE LAST. WE READ THE LAST ELEMENT AND OVERWRITE THE */
- /* DELETED ELEMENT. */
- /* --------------------------------------------------------------------------------- */
- tdelContainerptr = operationRecPtr.p->elementContainer;
- tdelForward = operationRecPtr.p->elementIsforward;
- deleteElement(signal);
-}//Dbacc::commitdelete()
-
-/* --------------------------------------------------------------------------------- */
-/* DELETE_ELEMENT */
-/* INPUT: FRAGRECPTR, POINTER TO A FRAGMENT RECORD */
-/* LAST_PAGEPTR, POINTER TO THE PAGE OF THE LAST ELEMENT */
-/* DEL_PAGEPTR, POINTER TO THE PAGE OF THE DELETED ELEMENT */
-/* TLAST_ELEMENTPTR, ELEMENT POINTER OF THE LAST ELEMENT */
-/* TDEL_ELEMENTPTR, ELEMENT POINTER OF THE DELETED ELEMENT */
-/* TLAST_FORWARD, DIRECTION OF LAST ELEMENT */
-/* TDEL_FORWARD, DIRECTION OF DELETED ELEMENT */
-/* TDEL_CONTAINERPTR, CONTAINER POINTER OF DELETED ELEMENT */
-/* DESCRIPTION: COPY LAST ELEMENT TO DELETED ELEMENT AND UPDATE UNDO LOG AND */
-/* UPDATE ANY ACTIVE OPERATION ON THE MOVED ELEMENT. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::deleteElement(Signal* signal)
-{
- OperationrecPtr deOperationRecPtr;
- Uint32 tdeIndex;
- Uint32 tlastMoveElemptr;
- Uint32 tdelMoveElemptr;
- Uint32 guard31;
-
- if (tlastElementptr >= 2048)
- goto deleteElement_index_error1;
- {
- const Uint32 tdeElemhead = lastPageptr.p->word32[tlastElementptr];
- tlastMoveElemptr = tlastElementptr;
- tdelMoveElemptr = tdelElementptr;
- guard31 = fragrecptr.p->elementLength - 1;
- for (tdeIndex = 0; tdeIndex <= guard31; tdeIndex++) {
- dbgWord32(delPageptr, tdelMoveElemptr, lastPageptr.p->word32[tlastMoveElemptr]);
- if ((tlastMoveElemptr >= 2048) ||
- (tdelMoveElemptr >= 2048))
- goto deleteElement_index_error2;
- delPageptr.p->word32[tdelMoveElemptr] = lastPageptr.p->word32[tlastMoveElemptr];
- tdelMoveElemptr = tdelMoveElemptr + tdelForward;
- tlastMoveElemptr = tlastMoveElemptr + tlastForward;
- }//for
- if (ElementHeader::getLocked(tdeElemhead)) {
- /* --------------------------------------------------------------------------------- */
- /* THE LAST ELEMENT IS LOCKED AND IS THUS REFERENCED BY AN OPERATION RECORD. WE NEED */
- /* TO UPDATE THE OPERATION RECORD WITH THE NEW REFERENCE TO THE ELEMENT. */
- /* --------------------------------------------------------------------------------- */
- deOperationRecPtr.i = ElementHeader::getOpPtrI(tdeElemhead);
- ptrCheckGuard(deOperationRecPtr, coprecsize, operationrec);
- deOperationRecPtr.p->elementPage = delPageptr.i;
- deOperationRecPtr.p->elementContainer = tdelContainerptr;
- deOperationRecPtr.p->elementPointer = tdelElementptr;
- deOperationRecPtr.p->elementIsforward = tdelForward;
- /* --------------------------------------------------------------------------------- */
- // We need to take extreme care to not install locked records after system restart.
- // An undo of the delete will reinstall the moved record. We have to ensure that the
- // lock is removed to ensure that no such thing happen.
- /* --------------------------------------------------------------------------------- */
- Uint32 eh = ElementHeader::setUnlocked(deOperationRecPtr.p->hashvaluePart,
- 0);
- lastPageptr.p->word32[tlastElementptr] = eh;
- }//if
- return;
- }
-
- deleteElement_index_error1:
- arrGuard(tlastElementptr, 2048);
- return;
-
- deleteElement_index_error2:
- arrGuard(tdelMoveElemptr + guard31, 2048);
- arrGuard(tlastMoveElemptr, 2048);
- return;
-
-}//Dbacc::deleteElement()
-
-/* --------------------------------------------------------------------------------- */
-/* GET_LAST_AND_REMOVE */
-/* INPUT: */
-/* LAST_PAGEPTR PAGE POINTER OF FIRST CONTAINER IN SEARCH OF LAST*/
-/* TLAST_CONTAINERPTR CONTAINER INDEX OF THE SAME */
-/* TLAST_CONTAINERHEAD CONTAINER HEADER OF THE SAME */
-/* TLAST_PAGEINDEX PAGE INDEX OF THE SAME */
-/* TLAST_FORWARD CONTAINER DIRECTION OF THE SAME */
-/* TLAST_CONTAINERLEN CONTAINER LENGTH OF THE SAME */
-/* LAST_PREVPAGEPTR PAGE POINTER OF PREVIOUS CONTAINER OF THE SAME */
-/* TLAST_PREVCONPTR CONTAINER INDEX OF PREVIOUS CONTAINER OF THE SAME*/
-/* */
-/* OUTPUT: */
-/* ALL VARIABLES FROM INPUT BUT NOW CONTAINING INFO ABOUT LAST */
-/* CONTAINER. */
-/* TLAST_ELEMENTPTR LAST ELEMENT POINTER IN LAST CONTAINER */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::getLastAndRemove(Signal* signal)
-{
- DirRangePtr glrOverflowrangeptr;
- DirectoryarrayPtr glrOverflowDirptr;
- Uint32 tglrHead;
- Uint32 tglrTmp;
-
- GLR_LOOP_10:
- if (((tlastContainerhead >> 7) & 0x3) != 0) {
- jam();
- lastPrevpageptr.i = lastPageptr.i;
- lastPrevpageptr.p = lastPageptr.p;
- tlastPrevconptr = tlastContainerptr;
- tlastPageindex = tlastContainerhead & 0x7f;
- if (((tlastContainerhead >> 9) & 0x1) == ZFALSE) {
- jam();
- arrGuard(tlastContainerptr + 1, 2048);
- tglrTmp = lastPageptr.p->word32[tlastContainerptr + 1];
- glrOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(glrOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tglrTmp >> 8), 256);
- glrOverflowDirptr.i = glrOverflowrangeptr.p->dirArray[tglrTmp >> 8];
- ptrCheckGuard(glrOverflowDirptr, cdirarraysize, directoryarray);
- lastPageptr.i = glrOverflowDirptr.p->pagep[tglrTmp & 0xff];
- ptrCheckGuard(lastPageptr, cpagesize, page8);
- }//if
- tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS);
- if (((tlastContainerhead >> 7) & 3) == ZLEFT) {
- jam();
- tlastForward = ZTRUE;
- tlastContainerptr = tlastContainerptr + ZHEAD_SIZE;
- } else if (((tlastContainerhead >> 7) & 3) == ZRIGHT) {
- jam();
- tlastForward = cminusOne;
- tlastContainerptr = ((tlastContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
- } else {
- ndbrequire(false);
- return;
- }//if
- arrGuard(tlastContainerptr, 2048);
- tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
- tlastContainerlen = tlastContainerhead >> 26;
- ndbrequire(tlastContainerlen >= ((Uint32)ZCON_HEAD_SIZE + fragrecptr.p->elementLength));
- goto GLR_LOOP_10;
- }//if
- tlastContainerlen = tlastContainerlen - fragrecptr.p->elementLength;
- if (tlastForward == ZTRUE) {
- jam();
- tlastElementptr = tlastContainerptr + tlastContainerlen;
- } else {
- jam();
- tlastElementptr = (tlastContainerptr + (ZCON_HEAD_SIZE - 1)) - tlastContainerlen;
- }//if
- rlPageptr.i = lastPageptr.i;
- rlPageptr.p = lastPageptr.p;
- trlPageindex = tlastPageindex;
- if (((tlastContainerhead >> 10) & 1) == 1) {
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE OWNERSHIP OF BOTH PARTS OF THE CONTAINER ENDS. */
- /* --------------------------------------------------------------------------------- */
- if (tlastContainerlen < ZDOWN_LIMIT) {
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE DECREASED THE SIZE BELOW THE DOWN LIMIT, WE MUST GIVE UP THE OTHER */
- /* SIDE OF THE BUFFER. */
- /* --------------------------------------------------------------------------------- */
- tlastContainerhead = tlastContainerhead ^ (1 << 10);
- trlRelCon = ZFALSE;
- if (tlastForward == ZTRUE) {
- jam();
- turlIndex = tlastContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
- releaseRightlist(signal);
- } else {
- jam();
- tullIndex = tlastContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE);
- releaseLeftlist(signal);
- }//if
- }//if
- }//if
- if (tlastContainerlen <= 2) {
- ndbrequire(tlastContainerlen == 2);
- if (lastPrevpageptr.i != RNIL) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE LAST CONTAINER IS EMPTY AND IS NOT THE FIRST CONTAINER WHICH IS NOT REMOVED. */
- /* DELETE THE LAST CONTAINER AND UPDATE THE PREVIOUS CONTAINER. ALSO PUT THIS */
- /* CONTAINER IN FREE CONTAINER LIST OF THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- ndbrequire(tlastPrevconptr < 2048);
- tglrTmp = lastPrevpageptr.p->word32[tlastPrevconptr] >> 9;
- dbgWord32(lastPrevpageptr, tlastPrevconptr, tglrTmp << 9);
- lastPrevpageptr.p->word32[tlastPrevconptr] = tglrTmp << 9;
- trlRelCon = ZTRUE;
- if (tlastForward == ZTRUE) {
- jam();
- tullIndex = tlastContainerptr;
- releaseLeftlist(signal);
- } else {
- jam();
- turlIndex = tlastContainerptr;
- releaseRightlist(signal);
- }//if
- return;
- }//if
- }//if
- tglrHead = tlastContainerhead << 6;
- tglrHead = tglrHead >> 6;
- tglrHead = tglrHead | (tlastContainerlen << 26);
- dbgWord32(lastPageptr, tlastContainerptr, tglrHead);
- arrGuard(tlastContainerptr, 2048);
- lastPageptr.p->word32[tlastContainerptr] = tglrHead;
-}//Dbacc::getLastAndRemove()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_LEFTLIST */
-/* INPUT: */
-/* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */
-/* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */
-/* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */
-/* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */
-/* A PART IS RELEASED. */
-/* */
-/* OUTPUT: */
-/* NONE */
-/* */
-/* THE FREE LIST OF LEFT FREE BUFFER IN THE PAGE WILL BE UPDATE */
-/* TULL_INDEX IS INDEX TO THE FIRST WORD IN THE LEFT SIDE OF THE BUFFER */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseLeftlist(Signal* signal)
-{
- Uint32 tullTmp;
- Uint32 tullTmp1;
-
- /* --------------------------------------------------------------------------------- */
- /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */
- /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */
- /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */
- /* --------------------------------------------------------------------------------- */
- if (trlRelCon == ZTRUE) {
- arrGuard(tullIndex, 2048);
- trlHead = rlPageptr.p->word32[tullIndex];
- trlNextused = (trlHead >> 11) & 0x7f;
- trlPrevused = (trlHead >> 18) & 0x7f;
- if (trlNextused < ZEMPTYLIST) {
- jam();
- tullTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
- tullTmp1 = tullTmp1 + ZHEAD_SIZE;
- tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfe03ffff;
- dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlPrevused << 18));
- rlPageptr.p->word32[tullTmp1] = tullTmp | (trlPrevused << 18);
- } else {
- ndbrequire(trlNextused == ZEMPTYLIST);
- jam();
- }//if
- if (trlPrevused < ZEMPTYLIST) {
- jam();
- tullTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
- tullTmp1 = tullTmp1 + ZHEAD_SIZE;
- tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfffc07ff;
- dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlNextused << 11));
- rlPageptr.p->word32[tullTmp1] = tullTmp | (trlNextused << 11);
- } else {
- ndbrequire(trlPrevused == ZEMPTYLIST);
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER. */
- /* --------------------------------------------------------------------------------- */
- tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff;
- dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp | (trlNextused << 23));
- rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp | (trlNextused << 23);
- }//if
- }//if
- dbgWord32(rlPageptr, tullIndex + 1, ZEMPTYLIST);
- arrGuard(tullIndex + 1, 2048);
- rlPageptr.p->word32[tullIndex + 1] = ZEMPTYLIST;
- tullTmp1 = (rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> 7) & 0x7f;
- dbgWord32(rlPageptr, tullIndex, tullTmp1);
- arrGuard(tullIndex, 2048);
- rlPageptr.p->word32[tullIndex] = tullTmp1;
- if (tullTmp1 < ZEMPTYLIST) {
- jam();
- tullTmp1 = (tullTmp1 << ZSHIFT_PLUS) - (tullTmp1 << ZSHIFT_MINUS);
- tullTmp1 = (tullTmp1 + ZHEAD_SIZE) + 1;
- dbgWord32(rlPageptr, tullTmp1, trlPageindex);
- rlPageptr.p->word32[tullTmp1] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
- } else {
- ndbrequire(tullTmp1 == ZEMPTYLIST);
- }//if
- tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST];
- tullTmp = (((tullTmp >> 14) << 14) | (trlPageindex << 7)) | (tullTmp & 0x7f);
- dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp);
- rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp;
- dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1);
- rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1;
- ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL);
- if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) {
- jam();
- colPageptr.i = rlPageptr.i;
- colPageptr.p = rlPageptr.p;
- ptrCheck(colPageptr, cpagesize, page8);
- checkoverfreelist(signal);
- }//if
-}//Dbacc::releaseLeftlist()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_RIGHTLIST */
-/* INPUT: */
-/* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */
-/* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */
-/* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */
-/* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */
-/* A PART IS RELEASED. */
-/* */
-/* OUTPUT: */
-/* NONE */
-/* */
-/* THE FREE LIST OF RIGHT FREE BUFFER IN THE PAGE WILL BE UPDATE. */
-/* TURL_INDEX IS INDEX TO THE FIRST WORD IN THE RIGHT SIDE OF */
-/* THE BUFFER, WHICH IS THE LAST WORD IN THE BUFFER. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseRightlist(Signal* signal)
-{
- Uint32 turlTmp1;
- Uint32 turlTmp;
-
- /* --------------------------------------------------------------------------------- */
- /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */
- /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */
- /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */
- /* --------------------------------------------------------------------------------- */
- if (trlRelCon == ZTRUE) {
- jam();
- arrGuard(turlIndex, 2048);
- trlHead = rlPageptr.p->word32[turlIndex];
- trlNextused = (trlHead >> 11) & 0x7f;
- trlPrevused = (trlHead >> 18) & 0x7f;
- if (trlNextused < ZEMPTYLIST) {
- jam();
- turlTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
- turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfe03ffff;
- dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlPrevused << 18));
- rlPageptr.p->word32[turlTmp1] = turlTmp | (trlPrevused << 18);
- } else {
- ndbrequire(trlNextused == ZEMPTYLIST);
- jam();
- }//if
- if (trlPrevused < ZEMPTYLIST) {
- jam();
- turlTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
- turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfffc07ff;
- dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlNextused << 11));
- rlPageptr.p->word32[turlTmp1] = turlTmp | (trlNextused << 11);
- } else {
- ndbrequire(trlPrevused == ZEMPTYLIST);
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER */
- /* OF THE RIGHT CONTAINER LIST. */
- /* --------------------------------------------------------------------------------- */
- turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff;
- dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, turlTmp | (trlNextused << 16));
- rlPageptr.p->word32[ZPOS_EMPTY_LIST] = turlTmp | (trlNextused << 16);
- }//if
- }//if
- dbgWord32(rlPageptr, turlIndex + 1, ZEMPTYLIST);
- arrGuard(turlIndex + 1, 2048);
- rlPageptr.p->word32[turlIndex + 1] = ZEMPTYLIST;
- turlTmp1 = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0x7f;
- dbgWord32(rlPageptr, turlIndex, turlTmp1);
- arrGuard(turlIndex, 2048);
- rlPageptr.p->word32[turlIndex] = turlTmp1;
- if (turlTmp1 < ZEMPTYLIST) {
- jam();
- turlTmp = (turlTmp1 << ZSHIFT_PLUS) - (turlTmp1 << ZSHIFT_MINUS);
- turlTmp = turlTmp + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1));
- dbgWord32(rlPageptr, turlTmp, trlPageindex);
- rlPageptr.p->word32[turlTmp] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
- } else {
- ndbrequire(turlTmp1 == ZEMPTYLIST);
- }//if
- turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST];
- dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, ((turlTmp >> 7) << 7) | trlPageindex);
- rlPageptr.p->word32[ZPOS_EMPTY_LIST] = ((turlTmp >> 7) << 7) | trlPageindex;
- dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1);
- rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1;
- ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL);
- if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) {
- jam();
- colPageptr.i = rlPageptr.i;
- colPageptr.p = rlPageptr.p;
- checkoverfreelist(signal);
- }//if
-}//Dbacc::releaseRightlist()
-
-/* --------------------------------------------------------------------------------- */
-/* CHECKOVERFREELIST */
-/* INPUT: COL_PAGEPTR, POINTER OF AN OVERFLOW PAGE RECORD. */
-/* DESCRIPTION: CHECKS IF THE PAGE HAVE TO PUT IN FREE LIST OF OVER FLOW */
-/* PAGES. WHEN IT HAVE TO, AN OVERFLOW REC PTR WILL BE ALLOCATED */
-/* TO KEEP NFORMATION ABOUT THE PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::checkoverfreelist(Signal* signal)
-{
- Uint32 tcolTmp;
-
- tcolTmp = colPageptr.p->word32[ZPOS_ALLOC_CONTAINERS];
- if (tcolTmp <= ZFREE_LIMIT) {
- if (tcolTmp == 0) {
- jam();
- ropPageptr = colPageptr;
- releaseOverpage(signal);
- } else {
- jam();
- if (colPageptr.p->word32[ZPOS_OVERFLOWREC] == RNIL) {
- ndbrequire(cfirstfreeoverrec != RNIL);
- jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = colPageptr.p->word32[ZPOS_PAGE_ID];
- sorOverflowRecPtr.p->overpage = colPageptr.i;
- dbgWord32(colPageptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
- colPageptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
- porOverflowRecPtr = sorOverflowRecPtr;
- putOverflowRecInFrag(signal);
- }//if
- }//if
- }//if
-}//Dbacc::checkoverfreelist()
-
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* */
-/* END OF DELETE MODULE */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* */
-/* COMMIT AND ABORT MODULE */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ABORT_OPERATION */
-/*DESCRIPTION: AN OPERATION RECORD CAN BE IN A LOCK QUEUE OF AN ELEMENT OR */
-/*OWNS THE LOCK. BY THIS SUBROUTINE THE LOCK STATE OF THE OPERATION WILL */
-/*BE CHECKED. THE OPERATION RECORD WILL BE REMOVED FROM THE QUEUE IF IT */
-/*BELONGED TO ANY ONE, OTHERWISE THE ELEMENT HEAD WILL BE UPDATED. */
-/* ------------------------------------------------------------------------- */
-
-/**
- *
- * P0 - P1 - P2 - P3
- * S0
- * S1
- * S2
- */
-void
-Dbacc::abortParallelQueueOperation(Signal* signal, OperationrecPtr opPtr)
-{
- jam();
- OperationrecPtr nextP;
- OperationrecPtr prevP;
- OperationrecPtr loPtr;
-
- Uint32 opbits = opPtr.p->m_op_bits;
- Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
- nextP.i = opPtr.p->nextParallelQue;
- prevP.i = opPtr.p->prevParallelQue;
- loPtr.i = opPtr.p->m_lock_owner_ptr_i;
-
- ndbassert(! (opbits & Operationrec::OP_LOCK_OWNER));
- ndbassert(opbits & Operationrec::OP_RUN_QUEUE);
-
- ptrCheckGuard(prevP, coprecsize, operationrec);
- ndbassert(prevP.p->nextParallelQue == opPtr.i);
- prevP.p->nextParallelQue = nextP.i;
-
- if (nextP.i != RNIL)
- {
- ptrCheckGuard(nextP, coprecsize, operationrec);
- ndbassert(nextP.p->prevParallelQue == opPtr.i);
- nextP.p->prevParallelQue = prevP.i;
- }
- else if (prevP.i != loPtr.i)
- {
- jam();
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
- ndbassert(loPtr.p->m_lo_last_parallel_op_ptr_i == opPtr.i);
- loPtr.p->m_lo_last_parallel_op_ptr_i = prevP.i;
- prevP.p->m_lock_owner_ptr_i = loPtr.i;
-
- /**
- * Abort P3...check start next
- */
- startNext(signal, prevP);
- validate_lock_queue(prevP);
- return;
- }
- else
- {
- jam();
- /**
- * P0 - P1
- *
- * Abort P1, check start next
- */
- ndbassert(prevP.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
- prevP.p->m_lo_last_parallel_op_ptr_i = RNIL;
- startNext(signal, prevP);
- validate_lock_queue(prevP);
- return;
- }
-
- /**
- * Abort P1/P2
- */
- if (opbits & Operationrec::OP_LOCK_MODE)
- {
- Uint32 nextbits = nextP.p->m_op_bits;
- while ((nextbits & Operationrec::OP_LOCK_MODE) == 0)
- {
- ndbassert(nextbits & Operationrec::OP_ACC_LOCK_MODE);
- nextbits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
- nextP.p->m_op_bits = nextbits;
-
- if (nextP.p->nextParallelQue != RNIL)
- {
- nextP.i = nextP.p->nextParallelQue;
- ptrCheckGuard(nextP, coprecsize, operationrec);
- nextbits = nextP.p->m_op_bits;
- }
- else
- {
- break;
- }
- }
- }
-
- /**
- * Abort P1, P2
- */
- if (opstate == Operationrec::OP_STATE_RUNNING)
- {
- jam();
- startNext(signal, prevP);
- validate_lock_queue(prevP);
- return;
- }
-
- ndbassert(opstate == Operationrec::OP_STATE_EXECUTED ||
- opstate == Operationrec::OP_STATE_WAITING);
-
- /**
- * Scan to last of run queue
- */
- while (nextP.p->nextParallelQue != RNIL)
- {
- jam();
- nextP.i = nextP.p->nextParallelQue;
- ptrCheckGuard(nextP, coprecsize, operationrec);
- }
-
-#ifdef VM_TRACE
- loPtr.i = nextP.p->m_lock_owner_ptr_i;
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
- ndbassert(loPtr.p->m_lo_last_parallel_op_ptr_i == nextP.i);
-#endif
- startNext(signal, nextP);
- validate_lock_queue(nextP);
-
- return;
-}
-
-void
-Dbacc::abortSerieQueueOperation(Signal* signal, OperationrecPtr opPtr)
-{
- jam();
- OperationrecPtr prevS, nextS;
- OperationrecPtr prevP, nextP;
- OperationrecPtr loPtr;
-
- Uint32 opbits = opPtr.p->m_op_bits;
-
- prevS.i = opPtr.p->prevSerialQue;
- nextS.i = opPtr.p->nextSerialQue;
-
- prevP.i = opPtr.p->prevParallelQue;
- nextP.i = opPtr.p->nextParallelQue;
-
- ndbassert((opbits & Operationrec::OP_LOCK_OWNER) == 0);
- ndbassert((opbits & Operationrec::OP_RUN_QUEUE) == 0);
-
- if (prevP.i != RNIL)
- {
- /**
- * We're not list head...
- */
- ptrCheckGuard(prevP, coprecsize, operationrec);
- ndbassert(prevP.p->nextParallelQue == opPtr.i);
- prevP.p->nextParallelQue = nextP.i;
-
- if (nextP.i != RNIL)
- {
- ptrCheckGuard(nextP, coprecsize, operationrec);
- ndbassert(nextP.p->prevParallelQue == opPtr.i);
- ndbassert((nextP.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
- Operationrec::OP_STATE_WAITING);
- nextP.p->prevParallelQue = prevP.i;
-
- if ((prevP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
- opbits & Operationrec::OP_LOCK_MODE)
- {
- /**
- * Scan right in parallel queue to fix OP_ACC_LOCK_MODE
- */
- while ((nextP.p->m_op_bits & Operationrec::OP_LOCK_MODE) == 0)
- {
- ndbassert(nextP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
- nextP.p->m_op_bits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
- nextP.i = nextP.p->nextParallelQue;
- if (nextP.i == RNIL)
- break;
- ptrCheckGuard(nextP, coprecsize, operationrec);
- }
- }
- }
- validate_lock_queue(prevP);
- return;
- }
- else
- {
- /**
- * We're a list head
- */
- ptrCheckGuard(prevS, coprecsize, operationrec);
- ndbassert(prevS.p->nextSerialQue == opPtr.i);
-
- if (nextP.i != RNIL)
- {
- /**
- * Promote nextP to list head
- */
- ptrCheckGuard(nextP, coprecsize, operationrec);
- ndbassert(nextP.p->prevParallelQue == opPtr.i);
- prevS.p->nextSerialQue = nextP.i;
- nextP.p->prevParallelQue = RNIL;
- nextP.p->nextSerialQue = nextS.i;
- if (nextS.i != RNIL)
- {
- jam();
- ptrCheckGuard(nextS, coprecsize, operationrec);
- ndbassert(nextS.p->prevSerialQue == opPtr.i);
- nextS.p->prevSerialQue = nextP.i;
- validate_lock_queue(prevS);
- return;
- }
- else
- {
- // nextS is RNIL, i.e we're last in serie queue...
- // we must update lockOwner.m_lo_last_serial_op_ptr_i
- loPtr = prevS;
- while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
- {
- loPtr.i = loPtr.p->prevSerialQue;
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- }
- ndbassert(loPtr.p->m_lo_last_serial_op_ptr_i == opPtr.i);
- loPtr.p->m_lo_last_serial_op_ptr_i = nextP.i;
- validate_lock_queue(loPtr);
- return;
- }
- }
-
- if (nextS.i == RNIL)
- {
- /**
- * Abort S2
- */
-
- // nextS is RNIL, i.e we're last in serie queue...
- // and we have no parallel queue,
- // we must update lockOwner.m_lo_last_serial_op_ptr_i
- prevS.p->nextSerialQue = RNIL;
-
- loPtr = prevS;
- while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
- {
- loPtr.i = loPtr.p->prevSerialQue;
- ptrCheckGuard(loPtr, coprecsize, operationrec);
- }
- ndbassert(loPtr.p->m_lo_last_serial_op_ptr_i == opPtr.i);
- if (prevS.i != loPtr.i)
- {
- jam();
- loPtr.p->m_lo_last_serial_op_ptr_i = prevS.i;
- }
- else
- {
- loPtr.p->m_lo_last_serial_op_ptr_i = RNIL;
- }
- validate_lock_queue(loPtr);
- }
- else if (nextP.i == RNIL)
- {
- ptrCheckGuard(nextS, coprecsize, operationrec);
- ndbassert(nextS.p->prevSerialQue == opPtr.i);
- prevS.p->nextSerialQue = nextS.i;
- nextS.p->prevSerialQue = prevS.i;
-
- if (prevS.p->m_op_bits & Operationrec::OP_LOCK_OWNER)
- {
- /**
- * Abort S0
- */
- OperationrecPtr lastOp;
- lastOp.i = prevS.p->m_lo_last_parallel_op_ptr_i;
- if (lastOp.i != RNIL)
- {
- jam();
- ptrCheckGuard(lastOp, coprecsize, operationrec);
- ndbassert(lastOp.p->m_lock_owner_ptr_i == prevS.i);
- }
- else
- {
- jam();
- lastOp = prevS;
- }
- startNext(signal, lastOp);
- validate_lock_queue(lastOp);
- }
- else
- {
- validate_lock_queue(prevS);
- }
- }
- }
-}
-
-
-void Dbacc::abortOperation(Signal* signal)
-{
- Uint32 opbits = operationRecPtr.p->m_op_bits;
-
- validate_lock_queue(operationRecPtr);
-
- if (opbits & Operationrec::OP_LOCK_OWNER)
- {
- takeOutLockOwnersList(signal, operationRecPtr);
- opbits &= ~(Uint32)Operationrec::OP_LOCK_OWNER;
- if (opbits & Operationrec::OP_INSERT_IS_DONE)
- {
- jam();
- opbits |= Operationrec::OP_ELEMENT_DISAPPEARED;
- }//if
- operationRecPtr.p->m_op_bits = opbits;
- const bool queue = (operationRecPtr.p->nextParallelQue != RNIL ||
- operationRecPtr.p->nextSerialQue != RNIL);
-
- if (queue)
- {
- jam();
- release_lockowner(signal, operationRecPtr, false);
- }
- else
- {
- /* -------------------------------------------------------------------
- * WE ARE OWNER OF THE LOCK AND NO OTHER OPERATIONS ARE QUEUED.
- * IF INSERT OR STANDBY WE DELETE THE ELEMENT OTHERWISE WE REMOVE
- * THE LOCK FROM THE ELEMENT.
- * ------------------------------------------------------------------ */
- if ((opbits & Operationrec::OP_ELEMENT_DISAPPEARED) == 0)
- {
- jam();
- Page8Ptr aboPageidptr;
- Uint32 taboElementptr;
- Uint32 tmp2Olq;
-
- taboElementptr = operationRecPtr.p->elementPointer;
- aboPageidptr.i = operationRecPtr.p->elementPage;
- tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart,
- operationRecPtr.p->scanBits);
- ptrCheckGuard(aboPageidptr, cpagesize, page8);
- dbgWord32(aboPageidptr, taboElementptr, tmp2Olq);
- arrGuard(taboElementptr, 2048);
- aboPageidptr.p->word32[taboElementptr] = tmp2Olq;
- return;
- }
- else
- {
- jam();
- commitdelete(signal);
- }//if
- }//if
- }
- else if (opbits & Operationrec::OP_RUN_QUEUE)
- {
- abortParallelQueueOperation(signal, operationRecPtr);
- }
- else
- {
- abortSerieQueueOperation(signal, operationRecPtr);
- }
-}
-
-void
-Dbacc::commitDeleteCheck()
-{
- OperationrecPtr opPtr;
- OperationrecPtr lastOpPtr;
- OperationrecPtr deleteOpPtr;
- Uint32 elementDeleted = 0;
- bool deleteCheckOngoing = true;
- Uint32 hashValue = 0;
- lastOpPtr = operationRecPtr;
- opPtr.i = operationRecPtr.p->nextParallelQue;
- while (opPtr.i != RNIL) {
- jam();
- ptrCheckGuard(opPtr, coprecsize, operationrec);
- lastOpPtr = opPtr;
- opPtr.i = opPtr.p->nextParallelQue;
- }//while
- deleteOpPtr = lastOpPtr;
- do {
- Uint32 opbits = deleteOpPtr.p->m_op_bits;
- Uint32 op = opbits & Operationrec::OP_MASK;
- if (op == ZDELETE) {
- jam();
- /* -------------------------------------------------------------------
- * IF THE CURRENT OPERATION TO BE COMMITTED IS A DELETE OPERATION DUE TO
- * A SCAN-TAKEOVER THE ACTUAL DELETE WILL BE PERFORMED BY THE PREVIOUS
- * OPERATION (SCAN) IN THE PARALLEL QUEUE WHICH OWNS THE LOCK.
- * THE PROBLEM IS THAT THE SCAN OPERATION DOES NOT HAVE A HASH VALUE
- * ASSIGNED TO IT SO WE COPY IT FROM THIS OPERATION.
- *
- * WE ASSUME THAT THIS SOLUTION WILL WORK BECAUSE THE ONLY WAY A
- * SCAN CAN PERFORM A DELETE IS BY BEING FOLLOWED BY A NORMAL
- * DELETE-OPERATION THAT HAS A HASH VALUE.
- * ----------------------------------------------------------------- */
- hashValue = deleteOpPtr.p->hashValue;
- elementDeleted = Operationrec::OP_ELEMENT_DISAPPEARED;
- deleteCheckOngoing = false;
- } else if (op == ZREAD || op == ZSCAN_OP) {
- /* -------------------------------------------------------------------
- * We are trying to find out whether the commit will in the end delete
- * the tuple. Normally the delete will be the last operation in the
- * list of operations on this. It is however possible to issue reads
- * and scans in the same savepoint as the delete operation was issued
- * and these can end up after the delete in the list of operations
- * in the parallel queue. Thus if we discover a read or a scan
- * we have to continue scanning the list looking for a delete operation.
- */
- deleteOpPtr.i = deleteOpPtr.p->prevParallelQue;
- if (opbits & Operationrec::OP_LOCK_OWNER) {
- jam();
- deleteCheckOngoing = false;
- } else {
- jam();
- ptrCheckGuard(deleteOpPtr, coprecsize, operationrec);
- }//if
- } else {
- jam();
- /* ------------------------------------------------------------------ */
- /* Finding an UPDATE or INSERT before finding a DELETE
- * means we cannot be deleting as the end result of this transaction.
- */
- deleteCheckOngoing = false;
- }//if
- } while (deleteCheckOngoing);
- opPtr = lastOpPtr;
- do {
- jam();
- opPtr.p->m_op_bits |= Operationrec::OP_COMMIT_DELETE_CHECK;
- if (elementDeleted) {
- jam();
- opPtr.p->m_op_bits |= elementDeleted;
- opPtr.p->hashValue = hashValue;
- }//if
- opPtr.i = opPtr.p->prevParallelQue;
- if (opPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) {
- jam();
- break;
- }//if
- ptrCheckGuard(opPtr, coprecsize, operationrec);
- } while (true);
-}//Dbacc::commitDeleteCheck()
-
-/* ------------------------------------------------------------------------- */
-/* COMMIT_OPERATION */
-/* INPUT: OPERATION_REC_PTR, POINTER TO AN OPERATION RECORD */
-/* DESCRIPTION: THE OPERATION RECORD WILL BE TAKE OUT OF ANY LOCK QUEUE. */
-/* IF IT OWNS THE ELEMENT LOCK. HEAD OF THE ELEMENT WILL BE UPDATED. */
-/* ------------------------------------------------------------------------- */
-void Dbacc::commitOperation(Signal* signal)
-{
- validate_lock_queue(operationRecPtr);
-
- Uint32 opbits = operationRecPtr.p->m_op_bits;
- Uint32 op = opbits & Operationrec::OP_MASK;
- ndbrequire((opbits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_EXECUTED);
- if ((opbits & Operationrec::OP_COMMIT_DELETE_CHECK) == 0 &&
- (op != ZREAD && op != ZSCAN_OP))
- {
- jam();
- /* This method is used to check whether the end result of the transaction
- will be to delete the tuple. In this case all operation will be marked
- with elementIsDisappeared = true to ensure that the last operation
- committed will remove the tuple. We only run this once per transaction
- (commitDeleteCheckFlag = true if performed earlier) and we don't
- execute this code when committing a scan operation since committing
- a scan operation only means that the scan is continuing and the scan
- lock is released.
- */
- commitDeleteCheck();
- opbits = operationRecPtr.p->m_op_bits;
- }//if
-
- ndbassert(opbits & Operationrec::OP_RUN_QUEUE);
-
- if (opbits & Operationrec::OP_LOCK_OWNER)
- {
- takeOutLockOwnersList(signal, operationRecPtr);
- opbits &= ~(Uint32)Operationrec::OP_LOCK_OWNER;
- operationRecPtr.p->m_op_bits = opbits;
-
- const bool queue = (operationRecPtr.p->nextParallelQue != RNIL ||
- operationRecPtr.p->nextSerialQue != RNIL);
-
- if (!queue && (opbits & Operationrec::OP_ELEMENT_DISAPPEARED) == 0)
- {
- /*
- * This is the normal path through the commit for operations owning the
- * lock without any queues and not a delete operation.
- */
- Page8Ptr coPageidptr;
- Uint32 tcoElementptr;
- Uint32 tmp2Olq;
-
- coPageidptr.i = operationRecPtr.p->elementPage;
- tcoElementptr = operationRecPtr.p->elementPointer;
- tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart,
- operationRecPtr.p->scanBits);
- ptrCheckGuard(coPageidptr, cpagesize, page8);
- dbgWord32(coPageidptr, tcoElementptr, tmp2Olq);
- arrGuard(tcoElementptr, 2048);
- coPageidptr.p->word32[tcoElementptr] = tmp2Olq;
- return;
- }
- else if (queue)
- {
- jam();
- /*
- * The case when there is a queue lined up.
- * Release the lock and pass it to the next operation lined up.
- */
- release_lockowner(signal, operationRecPtr, true);
- return;
- }
- else
- {
- jam();
- /*
- * No queue and elementIsDisappeared is true.
- * We perform the actual delete operation.
- */
- commitdelete(signal);
- return;
- }//if
- }
- else
- {
- /**
- * THE OPERATION DOES NOT OWN THE LOCK. IT MUST BE IN A LOCK QUEUE OF THE
- * ELEMENT.
- */
- jam();
- OperationrecPtr prev, next, lockOwner;
- prev.i = operationRecPtr.p->prevParallelQue;
- next.i = operationRecPtr.p->nextParallelQue;
- lockOwner.i = operationRecPtr.p->m_lock_owner_ptr_i;
- ptrCheckGuard(prev, coprecsize, operationrec);
-
- prev.p->nextParallelQue = next.i;
- if (next.i != RNIL)
- {
- jam();
- ptrCheckGuard(next, coprecsize, operationrec);
- next.p->prevParallelQue = prev.i;
- }
- else if (prev.p->m_op_bits & Operationrec::OP_LOCK_OWNER)
- {
- jam();
- ndbassert(lockOwner.i == prev.i);
- prev.p->m_lo_last_parallel_op_ptr_i = RNIL;
- next = prev;
- }
- else
- {
- jam();
- /**
- * Last operation in parallell queue
- */
- ndbassert(prev.i != lockOwner.i);
- ptrCheckGuard(lockOwner, coprecsize, operationrec);
- ndbassert(lockOwner.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
- lockOwner.p->m_lo_last_parallel_op_ptr_i = prev.i;
- prev.p->m_lock_owner_ptr_i = lockOwner.i;
- next = prev;
- }
-
- /**
- * Check possible lock upgrade
- */
- if(opbits & Operationrec::OP_ACC_LOCK_MODE)
- {
- jam();
-
- /**
- * Not lock owner...committing a exclusive operation...
- *
- * e.g
- * T1(R) T1(X)
- * T2(R/X)
- *
- * If T1(X) commits T2(R/X) is not supposed to run
- * as T1(R) should also commit
- *
- * e.g
- * T1(R) T1(X) T1*(R)
- * T2(R/X)
- *
- * If T1*(R) commits T2(R/X) is not supposed to run
- * as T1(R),T2(x) should also commit
- */
- validate_lock_queue(prev);
- return;
- }
-
- /**
- * We committed a shared lock
- * Check if we can start next...
- */
- while(next.p->nextParallelQue != RNIL)
- {
- jam();
- next.i = next.p->nextParallelQue;
- ptrCheckGuard(next, coprecsize, operationrec);
-
- if ((next.p->m_op_bits & Operationrec::OP_STATE_MASK) !=
- Operationrec::OP_STATE_EXECUTED)
- {
- jam();
- return;
- }
- }
-
- startNext(signal, next);
-
- validate_lock_queue(prev);
- }
-}//Dbacc::commitOperation()
-
-void
-Dbacc::release_lockowner(Signal* signal, OperationrecPtr opPtr, bool commit)
-{
- OperationrecPtr nextP;
- OperationrecPtr nextS;
- OperationrecPtr newOwner;
- OperationrecPtr lastP;
-
- Uint32 opbits = opPtr.p->m_op_bits;
- nextP.i = opPtr.p->nextParallelQue;
- nextS.i = opPtr.p->nextSerialQue;
- lastP.i = opPtr.p->m_lo_last_parallel_op_ptr_i;
- Uint32 lastS = opPtr.p->m_lo_last_serial_op_ptr_i;
-
- ndbassert(lastP.i != RNIL || lastS != RNIL);
- ndbassert(nextP.i != RNIL || nextS.i != RNIL);
-
- enum {
- NOTHING,
- CHECK_LOCK_UPGRADE,
- START_NEW
- } action = NOTHING;
-
- if (nextP.i != RNIL)
- {
- jam();
- ptrCheckGuard(nextP, coprecsize, operationrec);
- newOwner = nextP;
-
- if (lastP.i == newOwner.i)
- {
- newOwner.p->m_lo_last_parallel_op_ptr_i = RNIL;
- lastP = nextP;
- }
- else
- {
- ptrCheckGuard(lastP, coprecsize, operationrec);
- newOwner.p->m_lo_last_parallel_op_ptr_i = lastP.i;
- lastP.p->m_lock_owner_ptr_i = newOwner.i;
- }
-
- newOwner.p->m_lo_last_serial_op_ptr_i = lastS;
- newOwner.p->nextSerialQue = nextS.i;
-
- if (nextS.i != RNIL)
- {
- jam();
- ptrCheckGuard(nextS, coprecsize, operationrec);
- ndbassert(nextS.p->prevSerialQue == opPtr.i);
- nextS.p->prevSerialQue = newOwner.i;
- }
-
- if (commit)
- {
- if ((opbits & Operationrec::OP_ACC_LOCK_MODE) == ZREADLOCK)
- {
- jam();
- /**
- * Lock owner...committing a shared operation...
- * this can be a lock upgrade
- *
- * e.g
- * T1(R) T2(R)
- * T2(X)
- *
- * If T1(R) commits T2(X) is supposed to run
- *
- * e.g
- * T1(X) T1(R)
- * T2(R)
- *
- * If T1(X) commits, then T1(R) _should_ commit before T2(R) is
- * allowed to proceed
- */
- action = CHECK_LOCK_UPGRADE;
- }
- else
- {
- jam();
- newOwner.p->m_op_bits |= Operationrec::OP_LOCK_MODE;
- }
- }
- else
- {
- /**
- * Aborting an operation can *always* lead to lock upgrade
- */
- action = CHECK_LOCK_UPGRADE;
- Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
- if (opstate != Operationrec::OP_STATE_EXECUTED)
- {
- ndbassert(opstate == Operationrec::OP_STATE_RUNNING);
- if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
- {
- jam();
- report_dealloc(signal, opPtr.p);
- newOwner.p->localdata[0] = ~(Uint32)0;
- }
- else
- {
- jam();
- newOwner.p->localdata[0] = opPtr.p->localdata[0];
- newOwner.p->localdata[1] = opPtr.p->localdata[1];
- }
- action = START_NEW;
- }
-
- /**
- * Update ACC_LOCK_MODE
- */
- if (opbits & Operationrec::OP_LOCK_MODE)
- {
- Uint32 nextbits = nextP.p->m_op_bits;
- while ((nextbits & Operationrec::OP_LOCK_MODE) == 0)
- {
- ndbassert(nextbits & Operationrec::OP_ACC_LOCK_MODE);
- nextbits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
- nextP.p->m_op_bits = nextbits;
-
- if (nextP.p->nextParallelQue != RNIL)
- {
- nextP.i = nextP.p->nextParallelQue;
- ptrCheckGuard(nextP, coprecsize, operationrec);
- nextbits = nextP.p->m_op_bits;
- }
- else
- {
- break;
- }
- }
- }
- }
- }
- else
- {
- jam();
- ptrCheckGuard(nextS, coprecsize, operationrec);
- newOwner = nextS;
-
- newOwner.p->m_op_bits |= Operationrec::OP_RUN_QUEUE;
-
- if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
- {
- report_dealloc(signal, opPtr.p);
- newOwner.p->localdata[0] = ~(Uint32)0;
- }
- else
- {
- jam();
- newOwner.p->localdata[0] = opPtr.p->localdata[0];
- newOwner.p->localdata[1] = opPtr.p->localdata[1];
- }
-
- lastP = newOwner;
- while (lastP.p->nextParallelQue != RNIL)
- {
- lastP.i = lastP.p->nextParallelQue;
- ptrCheckGuard(lastP, coprecsize, operationrec);
- lastP.p->m_op_bits |= Operationrec::OP_RUN_QUEUE;
- }
-
- if (newOwner.i != lastP.i)
- {
- jam();
- newOwner.p->m_lo_last_parallel_op_ptr_i = lastP.i;
- }
- else
- {
- jam();
- newOwner.p->m_lo_last_parallel_op_ptr_i = RNIL;
- }
-
- if (newOwner.i != lastS)
- {
- jam();
- newOwner.p->m_lo_last_serial_op_ptr_i = lastS;
- }
- else
- {
- jam();
- newOwner.p->m_lo_last_serial_op_ptr_i = RNIL;
- }
-
- action = START_NEW;
- }
-
- insertLockOwnersList(signal, newOwner);
-
- /**
- * Copy op info, and store op in element
- *
- */
- {
- newOwner.p->elementPage = opPtr.p->elementPage;
- newOwner.p->elementIsforward = opPtr.p->elementIsforward;
- newOwner.p->elementPointer = opPtr.p->elementPointer;
- newOwner.p->elementContainer = opPtr.p->elementContainer;
- newOwner.p->scanBits = opPtr.p->scanBits;
- newOwner.p->hashvaluePart = opPtr.p->hashvaluePart;
- newOwner.p->m_op_bits |= (opbits & Operationrec::OP_ELEMENT_DISAPPEARED);
- if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
- {
- /* ------------------------------------------------------------------- */
- // If the elementIsDisappeared is set then we know that the
- // hashValue is also set since it always originates from a
- // committing abort or a aborting insert.
- // Scans do not initialise the hashValue and must have this
- // value initialised if they are
- // to successfully commit the delete.
- /* ------------------------------------------------------------------- */
- jam();
- newOwner.p->hashValue = opPtr.p->hashValue;
- }//if
-
- Page8Ptr pagePtr;
- pagePtr.i = newOwner.p->elementPage;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- const Uint32 tmp = ElementHeader::setLocked(newOwner.i);
- arrGuard(newOwner.p->elementPointer, 2048);
- pagePtr.p->word32[newOwner.p->elementPointer] = tmp;
- }
-
- switch(action){
- case NOTHING:
- validate_lock_queue(newOwner);
- return;
- case START_NEW:
- startNew(signal, newOwner);
- validate_lock_queue(newOwner);
- return;
- case CHECK_LOCK_UPGRADE:
- startNext(signal, lastP);
- validate_lock_queue(lastP);
- break;
- }
-
-}
-
-void
-Dbacc::startNew(Signal* signal, OperationrecPtr newOwner)
-{
- OperationrecPtr save = operationRecPtr;
- operationRecPtr = newOwner;
-
- Uint32 opbits = newOwner.p->m_op_bits;
- Uint32 op = opbits & Operationrec::OP_MASK;
- Uint32 opstate = (opbits & Operationrec::OP_STATE_MASK);
- ndbassert(opstate == Operationrec::OP_STATE_WAITING);
- ndbassert(opbits & Operationrec::OP_LOCK_OWNER);
- const bool deleted = opbits & Operationrec::OP_ELEMENT_DISAPPEARED;
- Uint32 errCode = 0;
-
- opbits &= opbits & ~(Uint32)Operationrec::OP_STATE_MASK;
- opbits |= Operationrec::OP_STATE_RUNNING;
-
- if (op == ZSCAN_OP && (opbits & Operationrec::OP_LOCK_REQ) == 0)
- goto scan;
-
- if (deleted)
- {
- jam();
- if (op != ZINSERT && op != ZWRITE)
- {
- errCode = ZREAD_ERROR;
- goto ref;
- }
-
- opbits &= ~(Uint32)Operationrec::OP_MASK;
- opbits &= ~(Uint32)Operationrec::OP_ELEMENT_DISAPPEARED;
- opbits |= (op = ZINSERT);
- opbits |= Operationrec::OP_INSERT_IS_DONE;
- goto conf;
- }
- else if (op == ZINSERT)
- {
- jam();
- errCode = ZWRITE_ERROR;
- goto ref;
- }
- else if (op == ZWRITE)
- {
- jam();
- opbits &= ~(Uint32)Operationrec::OP_MASK;
- opbits |= (op = ZUPDATE);
- goto conf;
- }
-
-conf:
- newOwner.p->m_op_bits = opbits;
-
- sendAcckeyconf(signal);
- sendSignal(newOwner.p->userblockref, GSN_ACCKEYCONF,
- signal, 6, JBB);
-
- operationRecPtr = save;
- return;
-
-scan:
- jam();
- newOwner.p->m_op_bits = opbits;
-
- takeOutScanLockQueue(newOwner.p->scanRecPtr);
- putReadyScanQueue(signal, newOwner.p->scanRecPtr);
-
- operationRecPtr = save;
- return;
-
-ref:
- newOwner.p->m_op_bits = opbits;
-
- signal->theData[0] = newOwner.p->userptr;
- signal->theData[1] = errCode;
- sendSignal(newOwner.p->userblockref, GSN_ACCKEYREF, signal,
- 2, JBB);
-
- operationRecPtr = save;
- return;
-}
-
-/**
- * takeOutLockOwnersList
- *
- * Description: Take out an operation from the doubly linked
- * lock owners list on the fragment.
- *
- */
-void Dbacc::takeOutLockOwnersList(Signal* signal,
- const OperationrecPtr& outOperPtr)
-{
- const Uint32 Tprev = outOperPtr.p->prevLockOwnerOp;
- const Uint32 Tnext = outOperPtr.p->nextLockOwnerOp;
-#ifdef VM_TRACE
- // Check that operation is already in the list
- OperationrecPtr tmpOperPtr;
- bool inList = false;
- tmpOperPtr.i = fragrecptr.p->lockOwnersList;
- while (tmpOperPtr.i != RNIL){
- ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
- if (tmpOperPtr.i == outOperPtr.i)
- inList = true;
- tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp;
- }
- ndbrequire(inList == true);
-#endif
-
- ndbassert(outOperPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
-
- // Fast path through the code for the common case.
- if ((Tprev == RNIL) && (Tnext == RNIL)) {
- ndbrequire(fragrecptr.p->lockOwnersList == outOperPtr.i);
- fragrecptr.p->lockOwnersList = RNIL;
- return;
- }
-
- // Check previous operation
- if (Tprev != RNIL) {
- jam();
- arrGuard(Tprev, coprecsize);
- operationrec[Tprev].nextLockOwnerOp = Tnext;
- } else {
- fragrecptr.p->lockOwnersList = Tnext;
- }//if
-
- // Check next operation
- if (Tnext == RNIL) {
- return;
- } else {
- jam();
- arrGuard(Tnext, coprecsize);
- operationrec[Tnext].prevLockOwnerOp = Tprev;
- }//if
-
- return;
-}//Dbacc::takeOutLockOwnersList()
-
-/**
- * insertLockOwnersList
- *
- * Description: Insert an operation first in the dubly linked lock owners
- * list on the fragment.
- *
- */
-void Dbacc::insertLockOwnersList(Signal* signal,
- const OperationrecPtr& insOperPtr)
-{
- OperationrecPtr tmpOperPtr;
-#ifdef VM_TRACE
- // Check that operation is not already in list
- tmpOperPtr.i = fragrecptr.p->lockOwnersList;
- while(tmpOperPtr.i != RNIL){
- ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
- ndbrequire(tmpOperPtr.i != insOperPtr.i);
- tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp;
- }
-#endif
- tmpOperPtr.i = fragrecptr.p->lockOwnersList;
-
- ndbrequire(! (insOperPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER));
-
- insOperPtr.p->m_op_bits |= Operationrec::OP_LOCK_OWNER;
- insOperPtr.p->prevLockOwnerOp = RNIL;
- insOperPtr.p->nextLockOwnerOp = tmpOperPtr.i;
-
- fragrecptr.p->lockOwnersList = insOperPtr.i;
- if (tmpOperPtr.i == RNIL) {
- return;
- } else {
- jam();
- ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
- tmpOperPtr.p->prevLockOwnerOp = insOperPtr.i;
- }//if
-}//Dbacc::insertLockOwnersList()
-
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF COMMIT AND ABORT MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* ALLOC_OVERFLOW_PAGE */
-/* DESCRIPTION: */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::allocOverflowPage(Signal* signal)
-{
- DirRangePtr aopDirRangePtr;
- DirectoryarrayPtr aopOverflowDirptr;
- OverflowRecordPtr aopOverflowRecPtr;
- Uint32 taopTmp1;
- Uint32 taopTmp2;
- Uint32 taopTmp3;
-
- tresult = 0;
- if ((cfirstfreepage == RNIL) &&
- (cfreepage >= cpagesize)) {
- jam();
- zpagesize_error("Dbacc::allocOverflowPage");
- tresult = ZPAGESIZE_ERROR;
- return;
- }//if
- if (fragrecptr.p->firstFreeDirindexRec != RNIL) {
- jam();
- /* FRAGRECPTR:FIRST_FREE_DIRINDEX_REC POINTS */
- /* TO THE FIRST ELEMENT IN A FREE LIST OF THE */
- /* DIRECTORY INDEX WICH HAVE NULL AS PAGE */
- aopOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
- ptrCheckGuard(aopOverflowRecPtr, coverflowrecsize, overflowRecord);
- troOverflowRecPtr.p = aopOverflowRecPtr.p;
- takeRecOutOfFreeOverdir(signal);
- } else if (cfirstfreeoverrec == RNIL) {
- jam();
- tresult = ZOVER_REC_ERROR;
- return;
- } else if ((cfirstfreedir == RNIL) &&
- (cdirarraysize <= cdirmemory)) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- } else {
- jam();
- seizeOverRec(signal);
- aopOverflowRecPtr = sorOverflowRecPtr;
- aopOverflowRecPtr.p->dirindex = fragrecptr.p->lastOverIndex;
- }//if
- aopOverflowRecPtr.p->nextOverRec = RNIL;
- aopOverflowRecPtr.p->prevOverRec = RNIL;
- fragrecptr.p->firstOverflowRec = aopOverflowRecPtr.i;
- fragrecptr.p->lastOverflowRec = aopOverflowRecPtr.i;
- taopTmp1 = aopOverflowRecPtr.p->dirindex;
- aopDirRangePtr.i = fragrecptr.p->overflowdir;
- taopTmp2 = taopTmp1 >> 8;
- taopTmp3 = taopTmp1 & 0xff;
- ptrCheckGuard(aopDirRangePtr, cdirrangesize, dirRange);
- arrGuard(taopTmp2, 256);
- if (aopDirRangePtr.p->dirArray[taopTmp2] == RNIL) {
- jam();
- seizeDirectory(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- aopDirRangePtr.p->dirArray[taopTmp2] = sdDirptr.i;
- }//if
- aopOverflowDirptr.i = aopDirRangePtr.p->dirArray[taopTmp2];
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- ptrCheckGuard(aopOverflowDirptr, cdirarraysize, directoryarray);
- aopOverflowDirptr.p->pagep[taopTmp3] = spPageptr.i;
- tiopPageId = aopOverflowRecPtr.p->dirindex;
- iopOverflowRecPtr = aopOverflowRecPtr;
- iopPageptr = spPageptr;
- initOverpage(signal);
- aopOverflowRecPtr.p->overpage = spPageptr.i;
- if (fragrecptr.p->lastOverIndex <= aopOverflowRecPtr.p->dirindex) {
- jam();
- ndbrequire(fragrecptr.p->lastOverIndex == aopOverflowRecPtr.p->dirindex);
- fragrecptr.p->lastOverIndex++;
- }//if
-}//Dbacc::allocOverflowPage()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* EXPAND/SHRINK MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/*EXPANDCHECK EXPAND BUCKET ORD */
-/* SENDER: ACC, LEVEL B */
-/* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */
-/* DESCRIPTION: A BUCKET OF A FRAGMENT PAGE WILL BE EXPAND INTO TWO BUCKETS */
-/* ACCORDING TO LH3. */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* EXPANDCHECK EXPAND BUCKET ORD */
-/* ******************------------------------------+ */
-/* SENDER: ACC, LEVEL B */
-/* A BUCKET OF THE FRAGMENT WILL */
-/* BE EXPANDED ACORDING TO LH3, */
-/* AND COMMIT TRANSACTION PROCESS */
-/* WILL BE CONTINUED */
-Uint32 Dbacc::checkScanExpand(Signal* signal)
-{
- Uint32 Ti;
- Uint32 TreturnCode = 0;
- Uint32 TPageIndex;
- Uint32 TDirInd;
- Uint32 TSplit;
- Uint32 TreleaseInd = 0;
- Uint32 TreleaseScanBucket;
- Uint32 TreleaseScanIndicator[4];
- DirectoryarrayPtr TDirptr;
- DirRangePtr TDirRangePtr;
- Page8Ptr TPageptr;
- ScanRecPtr TscanPtr;
-
- TSplit = fragrecptr.p->p;
- for (Ti = 0; Ti < 4; Ti++) {
- TreleaseScanIndicator[Ti] = 0;
- if (fragrecptr.p->scan[Ti] != RNIL) {
- //-------------------------------------------------------------
- // A scan is ongoing on this particular local fragment. We have
- // to check its current state.
- //-------------------------------------------------------------
- TscanPtr.i = fragrecptr.p->scan[Ti];
- ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
- if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
- if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
- if (TSplit == TscanPtr.p->nextBucketIndex) {
- jam();
- //-------------------------------------------------------------
- // We are currently scanning this bucket. We cannot split it
- // simultaneously with the scan. We have to pass this offer for
- // splitting the bucket.
- //-------------------------------------------------------------
- TreturnCode = 1;
- return TreturnCode;
- } else if (TSplit > TscanPtr.p->nextBucketIndex) {
- jam();
- //-------------------------------------------------------------
- // This bucket has not yet been scanned. We must reset the scanned
- // bit indicator for this scan on this bucket.
- //-------------------------------------------------------------
- TreleaseScanIndicator[Ti] = 1;
- TreleaseInd = 1;
- } else {
- jam();
- }//if
- } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
- jam();
- //-------------------------------------------------------------
- // We are performing a second lap to handle buckets that was
- // merged during the first lap of scanning. During this second
- // lap we do not allow any splits or merges.
- //-------------------------------------------------------------
- TreturnCode = 1;
- return TreturnCode;
- } else {
- ndbrequire(TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED);
- jam();
- //-------------------------------------------------------------
- // The scan is completed and we can thus go ahead and perform
- // the split.
- //-------------------------------------------------------------
- }//if
- }//if
- }//if
- }//for
- if (TreleaseInd == 1) {
- TreleaseScanBucket = TSplit;
- TDirRangePtr.i = fragrecptr.p->directory;
- TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
- TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
- ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange);
- arrGuard((TDirInd >> 8), 256);
- TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8];
- ptrCheckGuard(TDirptr, cdirarraysize, directoryarray);
- TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff];
- ptrCheckGuard(TPageptr, cpagesize, page8);
- for (Ti = 0; Ti < 4; Ti++) {
- if (TreleaseScanIndicator[Ti] == 1) {
- jam();
- scanPtr.i = fragrecptr.p->scan[Ti];
- ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
- rsbPageidptr = TPageptr;
- trsbPageindex = TPageIndex;
- releaseScanBucket(signal);
- }//if
- }//for
- }//if
- return TreturnCode;
-}//Dbacc::checkScanExpand()
-
-void Dbacc::execEXPANDCHECK2(Signal* signal)
-{
- jamEntry();
-
- if(refToBlock(signal->getSendersBlockRef()) == DBLQH)
- {
- jam();
- return;
- }
-
- DirectoryarrayPtr newDirptr;
-
- fragrecptr.i = signal->theData[0];
- tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
- Uint32 tmp = 1;
- tmp = tmp << 31;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- fragrecptr.p->expandFlag = 0;
- if (fragrecptr.p->slack < tmp) {
- jam();
- /* IT MEANS THAT IF SLACK > ZERO */
- /*--------------------------------------------------------------*/
- /* THE SLACK HAS IMPROVED AND IS NOW ACCEPTABLE AND WE */
- /* CAN FORGET ABOUT THE EXPAND PROCESS. */
- /*--------------------------------------------------------------*/
- return;
- }//if
- if (fragrecptr.p->firstOverflowRec == RNIL) {
- jam();
- allocOverflowPage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- /*--------------------------------------------------------------*/
- /* WE COULD NOT ALLOCATE ANY OVERFLOW PAGE. THUS WE HAVE TO STOP*/
- /* THE EXPAND SINCE WE CANNOT GUARANTEE ITS COMPLETION. */
- /*--------------------------------------------------------------*/
- return;
- }//if
- }//if
- if (cfirstfreepage == RNIL) {
- if (cfreepage >= cpagesize) {
- jam();
- /*--------------------------------------------------------------*/
- /* WE HAVE TO STOP THE EXPAND PROCESS SINCE THERE ARE NO FREE */
- /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */
- /* CANNOT COMPLETE THE EXPAND. TO AVOID THE CRASH WE EXIT HERE. */
- /*--------------------------------------------------------------*/
- return;
- }//if
- }//if
- if (checkScanExpand(signal) == 1) {
- jam();
- /*--------------------------------------------------------------*/
- // A scan state was inconsistent with performing an expand
- // operation.
- /*--------------------------------------------------------------*/
- return;
- }//if
-
- /*--------------------------------------------------------------------------*/
- /* WE START BY FINDING THE PAGE, THE PAGE INDEX AND THE PAGE DIRECTORY*/
- /* OF THE NEW BUCKET WHICH SHALL RECEIVE THE ELEMENT WHICH HAVE A 1 IN*/
- /* THE NEXT HASH BIT. THIS BIT IS USED IN THE SPLIT MECHANISM TO */
- /* DECIDE WHICH ELEMENT GOES WHERE. */
- /*--------------------------------------------------------------------------*/
- expDirRangePtr.i = fragrecptr.p->directory;
- texpReceivedBucket = (fragrecptr.p->maxp + fragrecptr.p->p) + 1; /* RECEIVED BUCKET */
- texpDirInd = texpReceivedBucket >> fragrecptr.p->k;
- newDirptr.i = RNIL;
- ptrNull(newDirptr);
- texpDirRangeIndex = texpDirInd >> 8;
- ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
- arrGuard(texpDirRangeIndex, 256);
- expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex];
- if (expDirptr.i == RNIL) {
- jam();
- seizeDirectory(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- return;
- } else {
- jam();
- newDirptr = sdDirptr;
- expDirptr = sdDirptr;
- expDirRangePtr.p->dirArray[texpDirRangeIndex] = sdDirptr.i;
- }//if
- } else {
- ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
- }//if
- texpDirPageIndex = texpDirInd & 0xff;
- expPageptr.i = expDirptr.p->pagep[texpDirPageIndex];
- if (expPageptr.i == RNIL) {
- jam();
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- if (newDirptr.i != RNIL) {
- jam();
- rdDirptr.i = newDirptr.i;
- releaseDirectory(signal);
- }//if
- return;
- }//if
- expDirptr.p->pagep[texpDirPageIndex] = spPageptr.i;
- tipPageId = texpDirInd;
- inpPageptr = spPageptr;
- initPage(signal);
- fragrecptr.p->dirsize++;
- expPageptr = spPageptr;
- } else {
- ptrCheckGuard(expPageptr, cpagesize, page8);
- }//if
-
- fragrecptr.p->expReceivePageptr = expPageptr.i;
- fragrecptr.p->expReceiveIndex = texpReceivedBucket & ((1 << fragrecptr.p->k) - 1);
- /*--------------------------------------------------------------------------*/
- /* THE NEXT ACTION IS TO FIND THE PAGE, THE PAGE INDEX AND THE PAGE */
- /* DIRECTORY OF THE BUCKET TO BE SPLIT. */
- /*--------------------------------------------------------------------------*/
- expDirRangePtr.i = fragrecptr.p->directory;
- cexcPageindex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
- texpDirInd = fragrecptr.p->p >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
- ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
- arrGuard((texpDirInd >> 8), 256);
- expDirptr.i = expDirRangePtr.p->dirArray[texpDirInd >> 8];
- ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
- excPageptr.i = expDirptr.p->pagep[texpDirInd & 0xff];
- fragrecptr.p->expSenderIndex = cexcPageindex;
- fragrecptr.p->expSenderPageptr = excPageptr.i;
- if (excPageptr.i == RNIL) {
- jam();
- endofexpLab(signal); /* EMPTY BUCKET */
- return;
- }//if
- fragrecptr.p->expReceiveForward = ZTRUE;
- ptrCheckGuard(excPageptr, cpagesize, page8);
- expandcontainer(signal);
- endofexpLab(signal);
- return;
-}//Dbacc::execEXPANDCHECK2()
-
-void Dbacc::endofexpLab(Signal* signal)
-{
- fragrecptr.p->p++;
- fragrecptr.p->slack += fragrecptr.p->maxloadfactor;
- fragrecptr.p->expandCounter++;
- if (fragrecptr.p->p > fragrecptr.p->maxp) {
- jam();
- fragrecptr.p->maxp = (fragrecptr.p->maxp << 1) | 1;
- fragrecptr.p->lhdirbits++;
- fragrecptr.p->hashcheckbit++;
- fragrecptr.p->p = 0;
- }//if
- Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p;
- Uint32 Thysteres = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor;
- fragrecptr.p->slackCheck = noOfBuckets * Thysteres;
- if (fragrecptr.p->slack > (1u << 31)) {
- jam();
- /* IT MEANS THAT IF SLACK < ZERO */
- /* --------------------------------------------------------------------------------- */
- /* IT IS STILL NECESSARY TO EXPAND THE FRAGMENT EVEN MORE. START IT FROM HERE */
- /* WITHOUT WAITING FOR NEXT COMMIT ON THE FRAGMENT. */
- /* --------------------------------------------------------------------------------- */
- fragrecptr.p->expandFlag = 2;
- signal->theData[0] = fragrecptr.i;
- signal->theData[1] = fragrecptr.p->p;
- signal->theData[2] = fragrecptr.p->maxp;
- sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
- }//if
- return;
-}//Dbacc::endofexpLab()
-
-void Dbacc::reenable_expand_after_redo_log_exection_complete(Signal* signal){
-
- tabptr.i = signal->theData[0];
- Uint32 fragId = signal->theData[1];
-
- ptrCheckGuard(tabptr, ctablesize, tabrec);
- ndbrequire(getfragmentrec(signal, fragrecptr, fragId));
-#if 0
- ndbout_c("reenable expand check for table %d fragment: %d",
- tabptr.i, fragId);
-#endif
-
- switch(fragrecptr.p->expandFlag){
- case 0:
- /**
- * Hmm... this means that it's alreay has been reenabled...
- */
- fragrecptr.p->expandFlag = 1;
- break;
- case 1:
- /**
- * Nothing is going on start expand check
- */
- case 2:
- /**
- * A shrink is running, do expand check anyway
- * (to reset expandFlag)
- */
- fragrecptr.p->expandFlag = 2;
- signal->theData[0] = fragrecptr.i;
- signal->theData[1] = fragrecptr.p->p;
- signal->theData[2] = fragrecptr.p->maxp;
- sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
- break;
- }
-}
-
-void Dbacc::execDEBUG_SIG(Signal* signal)
-{
- jamEntry();
- expPageptr.i = signal->theData[0];
-
- progError(__LINE__, NDBD_EXIT_SR_UNDOLOG);
- return;
-}//Dbacc::execDEBUG_SIG()
-
-/* --------------------------------------------------------------------------------- */
-/* EXPANDCONTAINER */
-/* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */
-/* CEXC_PAGEINDEX (INDEX OF THE BUCKET). */
-/* */
-/* DESCRIPTION: THE HASH VALUE OF ALL ELEMENTS IN THE CONTAINER WILL BE */
-/* CHECKED. SOME OF THIS ELEMENTS HAVE TO MOVE TO THE NEW CONTAINER */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::expandcontainer(Signal* signal)
-{
- Uint32 texcHashvalue;
- Uint32 texcTmp;
- Uint32 texcIndex;
- Uint32 guard20;
-
- cexcPrevpageptr = RNIL;
- cexcPrevconptr = 0;
- cexcForward = ZTRUE;
- EXP_CONTAINER_LOOP:
- cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
- if (cexcForward == ZTRUE) {
- jam();
- cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
- cexcElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
- } else {
- jam();
- cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
- cexcElementptr = cexcContainerptr - 1;
- }//if
- arrGuard(cexcContainerptr, 2048);
- cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
- cexcContainerlen = cexcContainerhead >> 26;
- cexcMovedLen = ZCON_HEAD_SIZE;
- if (cexcContainerlen <= ZCON_HEAD_SIZE) {
- ndbrequire(cexcContainerlen >= ZCON_HEAD_SIZE);
- jam();
- goto NEXT_ELEMENT;
- }//if
- NEXT_ELEMENT_LOOP:
- idrOperationRecPtr.i = RNIL;
- ptrNull(idrOperationRecPtr);
- /* --------------------------------------------------------------------------------- */
- /* CEXC_PAGEINDEX PAGE INDEX OF CURRENT CONTAINER BEING EXAMINED. */
- /* CEXC_CONTAINERPTR INDEX OF CURRENT CONTAINER BEING EXAMINED. */
- /* CEXC_ELEMENTPTR INDEX OF CURRENT ELEMENT BEING EXAMINED. */
- /* EXC_PAGEPTR PAGE WHERE CURRENT ELEMENT RESIDES. */
- /* CEXC_PREVPAGEPTR PAGE OF PREVIOUS CONTAINER. */
- /* CEXC_PREVCONPTR INDEX OF PREVIOUS CONTAINER */
- /* CEXC_FORWARD DIRECTION OF CURRENT CONTAINER */
- /* --------------------------------------------------------------------------------- */
- arrGuard(cexcElementptr, 2048);
- tidrElemhead = excPageptr.p->word32[cexcElementptr];
- if (ElementHeader::getUnlocked(tidrElemhead)){
- jam();
- texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead);
- } else {
- jam();
- idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
- ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
- texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
- }//if
- if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS ELEMENT IS NOT TO BE MOVED. WE CALCULATE THE WHEREABOUTS OF THE NEXT */
- /* ELEMENT AND PROCEED WITH THAT OR END THE SEARCH IF THERE ARE NO MORE */
- /* ELEMENTS IN THIS CONTAINER. */
- /* --------------------------------------------------------------------------------- */
- goto NEXT_ELEMENT;
- }//if
- /* --------------------------------------------------------------------------------- */
- /* THE HASH BIT WAS SET AND WE SHALL MOVE THIS ELEMENT TO THE NEW BUCKET. */
- /* WE START BY READING THE ELEMENT TO BE ABLE TO INSERT IT INTO THE NEW BUCKET.*/
- /* THEN WE INSERT THE ELEMENT INTO THE NEW BUCKET. THE NEXT STEP IS TO DELETE */
- /* THE ELEMENT FROM THIS BUCKET. THIS IS PERFORMED BY REPLACING IT WITH THE */
- /* LAST ELEMENT IN THE BUCKET. IF THIS ELEMENT IS TO BE MOVED WE MOVE IT AND */
- /* GET THE LAST ELEMENT AGAIN UNTIL WE EITHER FIND ONE THAT STAYS OR THIS */
- /* ELEMENT IS THE LAST ELEMENT. */
- /* --------------------------------------------------------------------------------- */
- texcTmp = cexcElementptr + cexcForward;
- guard20 = fragrecptr.p->localkeylen - 1;
- for (texcIndex = 0; texcIndex <= guard20; texcIndex++) {
- arrGuard(texcIndex, 2);
- arrGuard(texcTmp, 2048);
- clocalkey[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;
- insertElement(signal);
- fragrecptr.p->expReceiveIndex = tidrPageindex;
- fragrecptr.p->expReceivePageptr = idrPageptr.i;
- fragrecptr.p->expReceiveForward = tidrForward;
- REMOVE_LAST_LOOP:
- jam();
- lastPageptr.i = excPageptr.i;
- lastPageptr.p = excPageptr.p;
- tlastContainerptr = cexcContainerptr;
- lastPrevpageptr.i = cexcPrevpageptr;
- ptrCheck(lastPrevpageptr, cpagesize, page8);
- tlastPrevconptr = cexcPrevconptr;
- arrGuard(tlastContainerptr, 2048);
- tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
- tlastContainerlen = tlastContainerhead >> 26;
- tlastForward = cexcForward;
- tlastPageindex = cexcPageindex;
- getLastAndRemove(signal);
- if (excPageptr.i == lastPageptr.i) {
- if (cexcElementptr == tlastElementptr) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE CURRENT ELEMENT WAS ALSO THE LAST ELEMENT. */
- /* --------------------------------------------------------------------------------- */
- return;
- }//if
- }//if
- /* --------------------------------------------------------------------------------- */
- /* THE CURRENT ELEMENT WAS NOT THE LAST ELEMENT. IF THE LAST ELEMENT SHOULD */
- /* STAY WE COPY IT TO THE POSITION OF THE CURRENT ELEMENT, OTHERWISE WE INSERT */
- /* INTO THE NEW BUCKET, REMOVE IT AND TRY WITH THE NEW LAST ELEMENT. */
- /* --------------------------------------------------------------------------------- */
- idrOperationRecPtr.i = RNIL;
- ptrNull(idrOperationRecPtr);
- arrGuard(tlastElementptr, 2048);
- tidrElemhead = lastPageptr.p->word32[tlastElementptr];
- if (ElementHeader::getUnlocked(tidrElemhead)) {
- jam();
- texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead);
- } else {
- jam();
- idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
- ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
- texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
- }//if
- if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE LAST ELEMENT IS NOT TO BE MOVED. WE COPY IT TO THE CURRENT ELEMENT. */
- /* --------------------------------------------------------------------------------- */
- delPageptr = excPageptr;
- tdelContainerptr = cexcContainerptr;
- tdelForward = cexcForward;
- tdelElementptr = cexcElementptr;
- deleteElement(signal);
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE LAST ELEMENT IS ALSO TO BE MOVED. */
- /* --------------------------------------------------------------------------------- */
- texcTmp = tlastElementptr + tlastForward;
- for (texcIndex = 0; texcIndex < fragrecptr.p->localkeylen; texcIndex++) {
- arrGuard(texcIndex, 2);
- arrGuard(texcTmp, 2048);
- clocalkey[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;
- insertElement(signal);
- fragrecptr.p->expReceiveIndex = tidrPageindex;
- fragrecptr.p->expReceivePageptr = idrPageptr.i;
- fragrecptr.p->expReceiveForward = tidrForward;
- goto REMOVE_LAST_LOOP;
- }//if
- NEXT_ELEMENT:
- arrGuard(cexcContainerptr, 2048);
- cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
- cexcMovedLen = cexcMovedLen + fragrecptr.p->elementLength;
- if ((cexcContainerhead >> 26) > cexcMovedLen) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE NOT YET MOVED THE COMPLETE CONTAINER. WE PROCEED WITH THE NEXT */
- /* ELEMENT IN THE CONTAINER. IT IS IMPORTANT TO READ THE CONTAINER LENGTH */
- /* FROM THE CONTAINER HEADER SINCE IT MIGHT CHANGE BY REMOVING THE LAST */
- /* ELEMENT IN THE BUCKET. */
- /* --------------------------------------------------------------------------------- */
- cexcElementptr = cexcElementptr + (cexcForward * fragrecptr.p->elementLength);
- goto NEXT_ELEMENT_LOOP;
- }//if
- if (((cexcContainerhead >> 7) & 3) != 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE PROCEED TO THE NEXT CONTAINER IN THE BUCKET. */
- /* --------------------------------------------------------------------------------- */
- cexcPrevpageptr = excPageptr.i;
- cexcPrevconptr = cexcContainerptr;
- nextcontainerinfoExp(signal);
- goto EXP_CONTAINER_LOOP;
- }//if
-}//Dbacc::expandcontainer()
-
-/* ******************--------------------------------------------------------------- */
-/* SHRINKCHECK JOIN BUCKET ORD */
-/* SENDER: ACC, LEVEL B */
-/* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */
-/* DESCRIPTION: TWO BUCKET OF A FRAGMENT PAGE WILL BE JOINED TOGETHER */
-/* ACCORDING TO LH3. */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* SHRINKCHECK JOIN BUCKET ORD */
-/* ******************------------------------------+ */
-/* SENDER: ACC, LEVEL B */
-/* TWO BUCKETS OF THE FRAGMENT */
-/* WILL BE JOINED ACORDING TO LH3 */
-/* AND COMMIT TRANSACTION PROCESS */
-/* WILL BE CONTINUED */
-Uint32 Dbacc::checkScanShrink(Signal* signal)
-{
- Uint32 Ti;
- Uint32 TreturnCode = 0;
- Uint32 TPageIndex;
- Uint32 TDirInd;
- Uint32 TmergeDest;
- Uint32 TmergeSource;
- Uint32 TreleaseScanBucket;
- Uint32 TreleaseInd = 0;
- Uint32 TreleaseScanIndicator[4];
- DirectoryarrayPtr TDirptr;
- DirRangePtr TDirRangePtr;
- Page8Ptr TPageptr;
- ScanRecPtr TscanPtr;
-
- if (fragrecptr.p->p == 0) {
- jam();
- TmergeDest = fragrecptr.p->maxp >> 1;
- } else {
- jam();
- TmergeDest = fragrecptr.p->p - 1;
- }//if
- TmergeSource = fragrecptr.p->maxp + fragrecptr.p->p;
- for (Ti = 0; Ti < 4; Ti++) {
- TreleaseScanIndicator[Ti] = 0;
- if (fragrecptr.p->scan[Ti] != RNIL) {
- TscanPtr.i = fragrecptr.p->scan[Ti];
- ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
- if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
- //-------------------------------------------------------------
- // A scan is ongoing on this particular local fragment. We have
- // to check its current state.
- //-------------------------------------------------------------
- if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
- jam();
- if ((TmergeDest == TscanPtr.p->nextBucketIndex) ||
- (TmergeSource == TscanPtr.p->nextBucketIndex)) {
- jam();
- //-------------------------------------------------------------
- // We are currently scanning one of the buckets involved in the
- // merge. We cannot merge while simultaneously performing a scan.
- // We have to pass this offer for merging the buckets.
- //-------------------------------------------------------------
- TreturnCode = 1;
- return TreturnCode;
- } else if (TmergeDest < TscanPtr.p->nextBucketIndex) {
- jam();
- TreleaseScanIndicator[Ti] = 1;
- TreleaseInd = 1;
- }//if
- } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
- jam();
- //-------------------------------------------------------------
- // We are performing a second lap to handle buckets that was
- // merged during the first lap of scanning. During this second
- // lap we do not allow any splits or merges.
- //-------------------------------------------------------------
- TreturnCode = 1;
- return TreturnCode;
- } else if (TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) {
- jam();
- //-------------------------------------------------------------
- // The scan is completed and we can thus go ahead and perform
- // the split.
- //-------------------------------------------------------------
- } else {
- jam();
- sendSystemerror(signal, __LINE__);
- return TreturnCode;
- }//if
- }//if
- }//if
- }//for
- if (TreleaseInd == 1) {
- jam();
- TreleaseScanBucket = TmergeSource;
- TDirRangePtr.i = fragrecptr.p->directory;
- TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
- TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
- ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange);
- arrGuard((TDirInd >> 8), 256);
- TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8];
- ptrCheckGuard(TDirptr, cdirarraysize, directoryarray);
- TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff];
- ptrCheckGuard(TPageptr, cpagesize, page8);
- for (Ti = 0; Ti < 4; Ti++) {
- if (TreleaseScanIndicator[Ti] == 1) {
- jam();
- scanPtr.i = fragrecptr.p->scan[Ti];
- ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
- rsbPageidptr.i = TPageptr.i;
- rsbPageidptr.p = TPageptr.p;
- trsbPageindex = TPageIndex;
- releaseScanBucket(signal);
- if (TmergeDest < scanPtr.p->minBucketIndexToRescan) {
- jam();
- //-------------------------------------------------------------
- // We have to keep track of the starting bucket to Rescan in the
- // second lap.
- //-------------------------------------------------------------
- scanPtr.p->minBucketIndexToRescan = TmergeDest;
- }//if
- if (TmergeDest > scanPtr.p->maxBucketIndexToRescan) {
- jam();
- //-------------------------------------------------------------
- // We have to keep track of the ending bucket to Rescan in the
- // second lap.
- //-------------------------------------------------------------
- scanPtr.p->maxBucketIndexToRescan = TmergeDest;
- }//if
- }//if
- }//for
- }//if
- return TreturnCode;
-}//Dbacc::checkScanShrink()
-
-void Dbacc::execSHRINKCHECK2(Signal* signal)
-{
- Uint32 tshrTmp1;
-
- jamEntry();
- fragrecptr.i = signal->theData[0];
- Uint32 oldFlag = signal->theData[3];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- fragrecptr.p->expandFlag = oldFlag;
- tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
- if (fragrecptr.p->slack <= fragrecptr.p->slackCheck) {
- jam();
- /* TIME FOR JOIN BUCKETS PROCESS */
- /*--------------------------------------------------------------*/
- /* NO LONGER NECESSARY TO SHRINK THE FRAGMENT. */
- /*--------------------------------------------------------------*/
- return;
- }//if
- if (fragrecptr.p->slack > (1u << 31)) {
- jam();
- /*--------------------------------------------------------------*/
- /* THE SLACK IS NEGATIVE, IN THIS CASE WE WILL NOT NEED ANY */
- /* SHRINK. */
- /*--------------------------------------------------------------*/
- return;
- }//if
- texpDirInd = (fragrecptr.p->maxp + fragrecptr.p->p) >> fragrecptr.p->k;
- if (fragrecptr.p->firstOverflowRec == RNIL) {
- jam();
- allocOverflowPage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- return;
- }//if
- }//if
- if (cfirstfreepage == RNIL) {
- if (cfreepage >= cpagesize) {
- jam();
- /*--------------------------------------------------------------*/
- /* WE HAVE TO STOP THE SHRINK PROCESS SINCE THERE ARE NO FREE */
- /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */
- /* CANNOT COMPLETE THE SHRINK. TO AVOID THE CRASH WE EXIT HERE. */
- /*--------------------------------------------------------------*/
- return;
- }//if
- }//if
- if (checkScanShrink(signal) == 1) {
- jam();
- /*--------------------------------------------------------------*/
- // A scan state was inconsistent with performing a shrink
- // operation.
- /*--------------------------------------------------------------*/
- return;
- }//if
- if (fragrecptr.p->p == 0) {
- jam();
- fragrecptr.p->maxp = fragrecptr.p->maxp >> 1;
- fragrecptr.p->p = fragrecptr.p->maxp;
- fragrecptr.p->lhdirbits--;
- fragrecptr.p->hashcheckbit--;
- } else {
- jam();
- fragrecptr.p->p--;
- }//if
-
- /*--------------------------------------------------------------------------*/
- /* WE START BY FINDING THE NECESSARY INFORMATION OF THE BUCKET TO BE */
- /* REMOVED WHICH WILL SEND ITS ELEMENTS TO THE RECEIVING BUCKET. */
- /*--------------------------------------------------------------------------*/
- expDirRangePtr.i = fragrecptr.p->directory;
- cexcPageindex = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) & ((1 << fragrecptr.p->k) - 1);
- texpDirInd = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) >> fragrecptr.p->k;
- texpDirRangeIndex = texpDirInd >> 8;
- texpDirPageIndex = texpDirInd & 0xff;
- ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
- arrGuard(texpDirRangeIndex, 256);
- expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex];
- ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
- excPageptr.i = expDirptr.p->pagep[texpDirPageIndex];
- fragrecptr.p->expSenderDirptr = expDirptr.i;
- fragrecptr.p->expSenderIndex = cexcPageindex;
- fragrecptr.p->expSenderPageptr = excPageptr.i;
- fragrecptr.p->expSenderDirIndex = texpDirInd;
- /*--------------------------------------------------------------------------*/
- /* WE NOW PROCEED BY FINDING THE NECESSARY INFORMATION ABOUT THE */
- /* RECEIVING BUCKET. */
- /*--------------------------------------------------------------------------*/
- expDirRangePtr.i = fragrecptr.p->directory;
- texpReceivedBucket = fragrecptr.p->p >> fragrecptr.p->k;
- ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
- arrGuard((texpReceivedBucket >> 8), 256);
- expDirptr.i = expDirRangePtr.p->dirArray[texpReceivedBucket >> 8];
- ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
- fragrecptr.p->expReceivePageptr = expDirptr.p->pagep[texpReceivedBucket & 0xff];
- fragrecptr.p->expReceiveIndex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1);
- fragrecptr.p->expReceiveForward = ZTRUE;
- if (excPageptr.i == RNIL) {
- jam();
- endofshrinkbucketLab(signal); /* EMPTY BUCKET */
- return;
- }//if
- /*--------------------------------------------------------------------------*/
- /* INITIALISE THE VARIABLES FOR THE SHRINK PROCESS. */
- /*--------------------------------------------------------------------------*/
- ptrCheckGuard(excPageptr, cpagesize, page8);
- cexcForward = ZTRUE;
- cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
- cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
- arrGuard(cexcContainerptr, 2048);
- cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
- cexcContainerlen = cexcContainerhead >> 26;
- if (cexcContainerlen <= ZCON_HEAD_SIZE) {
- ndbrequire(cexcContainerlen == ZCON_HEAD_SIZE);
- } else {
- jam();
- shrinkcontainer(signal);
- }//if
- /*--------------------------------------------------------------------------*/
- /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */
- /*--------------------------------------------------------------------------*/
- if (((cexcContainerhead >> 10) & 1) == 1) {
- jam();
- rlPageptr = excPageptr;
- trlPageindex = cexcPageindex;
- trlRelCon = ZFALSE;
- turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
- releaseRightlist(signal);
- }//if
- tshrTmp1 = ZCON_HEAD_SIZE;
- tshrTmp1 = tshrTmp1 << 26;
- dbgWord32(excPageptr, cexcContainerptr, tshrTmp1);
- arrGuard(cexcContainerptr, 2048);
- excPageptr.p->word32[cexcContainerptr] = tshrTmp1;
- if (((cexcContainerhead >> 7) & 0x3) == 0) {
- jam();
- endofshrinkbucketLab(signal);
- return;
- }//if
- nextcontainerinfoExp(signal);
- do {
- cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
- if (cexcForward == ZTRUE) {
- jam();
- cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
- } else {
- jam();
- cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
- }//if
- arrGuard(cexcContainerptr, 2048);
- cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
- cexcContainerlen = cexcContainerhead >> 26;
- ndbrequire(cexcContainerlen > ZCON_HEAD_SIZE);
- /*--------------------------------------------------------------------------*/
- /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */
- /*--------------------------------------------------------------------------*/
- shrinkcontainer(signal);
- cexcPrevpageptr = excPageptr.i;
- cexcPrevpageindex = cexcPageindex;
- cexcPrevforward = cexcForward;
- if (((cexcContainerhead >> 7) & 0x3) != 0) {
- jam();
- /*--------------------------------------------------------------------------*/
- /* WE MUST CALL THE NEXT CONTAINER INFO ROUTINE BEFORE WE RELEASE THE */
- /* CONTAINER SINCE THE RELEASE WILL OVERWRITE THE NEXT POINTER. */
- /*--------------------------------------------------------------------------*/
- nextcontainerinfoExp(signal);
- }//if
- rlPageptr.i = cexcPrevpageptr;
- ptrCheckGuard(rlPageptr, cpagesize, page8);
- trlPageindex = cexcPrevpageindex;
- if (cexcPrevforward == ZTRUE) {
- jam();
- if (((cexcContainerhead >> 10) & 1) == 1) {
- jam();
- trlRelCon = ZFALSE;
- turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
- releaseRightlist(signal);
- }//if
- trlRelCon = ZTRUE;
- tullIndex = cexcContainerptr;
- releaseLeftlist(signal);
- } else {
- jam();
- if (((cexcContainerhead >> 10) & 1) == 1) {
- jam();
- trlRelCon = ZFALSE;
- tullIndex = cexcContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE);
- releaseLeftlist(signal);
- }//if
- trlRelCon = ZTRUE;
- turlIndex = cexcContainerptr;
- releaseRightlist(signal);
- }//if
- } while (((cexcContainerhead >> 7) & 0x3) != 0);
- endofshrinkbucketLab(signal);
- return;
-}//Dbacc::execSHRINKCHECK2()
-
-void Dbacc::endofshrinkbucketLab(Signal* signal)
-{
- fragrecptr.p->expandCounter--;
- fragrecptr.p->slack -= fragrecptr.p->maxloadfactor;
- if (fragrecptr.p->expSenderIndex == 0) {
- jam();
- fragrecptr.p->dirsize--;
- if (fragrecptr.p->expSenderPageptr != RNIL) {
- jam();
- rpPageptr.i = fragrecptr.p->expSenderPageptr;
- ptrCheckGuard(rpPageptr, cpagesize, page8);
- releasePage(signal);
- expDirptr.i = fragrecptr.p->expSenderDirptr;
- ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
- expDirptr.p->pagep[fragrecptr.p->expSenderDirIndex & 0xff] = RNIL;
- }//if
- if (((((fragrecptr.p->p + fragrecptr.p->maxp) + 1) >> fragrecptr.p->k) & 0xff) == 0) {
- jam();
- rdDirptr.i = fragrecptr.p->expSenderDirptr;
- releaseDirectory(signal);
- expDirRangePtr.i = fragrecptr.p->directory;
- ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
- arrGuard((fragrecptr.p->expSenderDirIndex >> 8), 256);
- expDirRangePtr.p->dirArray[fragrecptr.p->expSenderDirIndex >> 8] = RNIL;
- }//if
- }//if
- if (fragrecptr.p->slack < (1u << 31)) {
- jam();
- /*--------------------------------------------------------------*/
- /* THE SLACK IS POSITIVE, IN THIS CASE WE WILL CHECK WHETHER */
- /* WE WILL CONTINUE PERFORM ANOTHER SHRINK. */
- /*--------------------------------------------------------------*/
- Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p;
- Uint32 Thysteresis = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor;
- fragrecptr.p->slackCheck = noOfBuckets * Thysteresis;
- if (fragrecptr.p->slack > Thysteresis) {
- /*--------------------------------------------------------------*/
- /* IT IS STILL NECESSARY TO SHRINK THE FRAGMENT MORE. THIS*/
- /* CAN HAPPEN WHEN A NUMBER OF SHRINKS GET REJECTED */
- /* DURING A LOCAL CHECKPOINT. WE START A NEW SHRINK */
- /* IMMEDIATELY FROM HERE WITHOUT WAITING FOR A COMMIT TO */
- /* START IT. */
- /*--------------------------------------------------------------*/
- if (fragrecptr.p->expandCounter > 0) {
- jam();
- /*--------------------------------------------------------------*/
- /* IT IS VERY IMPORTANT TO NOT TRY TO SHRINK MORE THAN */
- /* WAS EXPANDED. IF MAXP IS SET TO A VALUE BELOW 63 THEN */
- /* WE WILL LOSE RECORDS SINCE GETDIRINDEX CANNOT HANDLE */
- /* SHRINKING BELOW 2^K - 1 (NOW 63). THIS WAS A BUG THAT */
- /* WAS REMOVED 2000-05-12. */
- /*--------------------------------------------------------------*/
- signal->theData[0] = fragrecptr.i;
- signal->theData[1] = fragrecptr.p->p;
- signal->theData[2] = fragrecptr.p->maxp;
- signal->theData[3] = fragrecptr.p->expandFlag;
- ndbrequire(fragrecptr.p->expandFlag < 2);
- fragrecptr.p->expandFlag = 2;
- sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
- }//if
- }//if
- }//if
- ndbrequire(fragrecptr.p->maxp >= (Uint32)((1 << fragrecptr.p->k) - 1));
- return;
-}//Dbacc::endofshrinkbucketLab()
-
-/* --------------------------------------------------------------------------------- */
-/* SHRINKCONTAINER */
-/* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */
-/* CEXC_CONTAINERLEN (LENGTH OF THE CONTAINER). */
-/* CEXC_CONTAINERPTR (ARRAY INDEX OF THE CONTAINER). */
-/* CEXC_FORWARD (CONTAINER FORWARD (+1) OR BACKWARD (-1)) */
-/* */
-/* DESCRIPTION: ALL ELEMENTS OF THE ACTIVE CONTAINER HAVE TO MOVE TO THE NEW */
-/* CONTAINER. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::shrinkcontainer(Signal* signal)
-{
- Uint32 tshrElementptr;
- Uint32 tshrRemLen;
- Uint32 tshrInc;
- Uint32 tshrTmp;
- Uint32 tshrIndex;
- Uint32 guard21;
-
- tshrRemLen = cexcContainerlen - ZCON_HEAD_SIZE;
- tshrInc = fragrecptr.p->elementLength;
- if (cexcForward == ZTRUE) {
- jam();
- tshrElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
- } else {
- jam();
- tshrElementptr = cexcContainerptr - 1;
- }//if
- SHR_LOOP:
- idrOperationRecPtr.i = RNIL;
- ptrNull(idrOperationRecPtr);
- /* --------------------------------------------------------------------------------- */
- /* THE CODE BELOW IS ALL USED TO PREPARE FOR THE CALL TO INSERT_ELEMENT AND */
- /* HANDLE THE RESULT FROM INSERT_ELEMENT. INSERT_ELEMENT INSERTS THE ELEMENT */
- /* INTO ANOTHER BUCKET. */
- /* --------------------------------------------------------------------------------- */
- arrGuard(tshrElementptr, 2048);
- tidrElemhead = excPageptr.p->word32[tshrElementptr];
- if (ElementHeader::getLocked(tidrElemhead)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IF THE ELEMENT IS LOCKED WE MUST UPDATE THE ELEMENT INFO IN THE OPERATION */
- /* RECORD OWNING THE LOCK. WE DO THIS BY READING THE OPERATION RECORD POINTER */
- /* FROM THE ELEMENT HEADER. */
- /* --------------------------------------------------------------------------------- */
- idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
- ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
- }//if
- tshrTmp = tshrElementptr + cexcForward;
- guard21 = fragrecptr.p->localkeylen - 1;
- for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) {
- arrGuard(tshrIndex, 2);
- arrGuard(tshrTmp, 2048);
- clocalkey[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;
- insertElement(signal);
- /* --------------------------------------------------------------------------------- */
- /* TAKE CARE OF RESULT FROM INSERT_ELEMENT. */
- /* --------------------------------------------------------------------------------- */
- fragrecptr.p->expReceiveIndex = tidrPageindex;
- fragrecptr.p->expReceivePageptr = idrPageptr.i;
- fragrecptr.p->expReceiveForward = tidrForward;
- if (tshrRemLen < tshrInc) {
- jam();
- sendSystemerror(signal, __LINE__);
- }//if
- tshrRemLen = tshrRemLen - tshrInc;
- if (tshrRemLen != 0) {
- jam();
- tshrElementptr = tshrTmp;
- goto SHR_LOOP;
- }//if
-}//Dbacc::shrinkcontainer()
-
-/* --------------------------------------------------------------------------------- */
-/* NEXTCONTAINERINFO_EXP */
-/* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */
-/* ABOUT NEXT CONTAINER IN THE BUCKET. */
-/* INPUT: CEXC_CONTAINERHEAD */
-/* CEXC_CONTAINERPTR */
-/* EXC_PAGEPTR */
-/* OUTPUT: */
-/* CEXC_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED. */
-/* EXC_PAGEPTR (PAGE REFERENCE OF NEXT CONTAINER) */
-/* CEXC_FORWARD */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::nextcontainerinfoExp(Signal* signal)
-{
- tnciNextSamePage = (cexcContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
- /* THE NEXT CONTAINER IS IN THE SAME PAGE */
- cexcPageindex = cexcContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
- if (((cexcContainerhead >> 7) & 3) == ZLEFT) {
- jam();
- cexcForward = ZTRUE;
- } else if (((cexcContainerhead >> 7) & 3) == ZRIGHT) {
- jam();
- cexcForward = cminusOne;
- } else {
- jam();
- sendSystemerror(signal, __LINE__);
- cexcForward = 0; /* DUMMY FOR COMPILER */
- }//if
- if (tnciNextSamePage == ZFALSE) {
- jam();
- /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
- arrGuard(cexcContainerptr + 1, 2048);
- tnciTmp = excPageptr.p->word32[cexcContainerptr + 1];
- nciOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tnciTmp >> 8), 256);
- nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8];
- ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray);
- excPageptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff];
- ptrCheckGuard(excPageptr, cpagesize, page8);
- }//if
-}//Dbacc::nextcontainerinfoExp()
-
-void Dbacc::initFragAdd(Signal* signal,
- FragmentrecPtr regFragPtr)
-{
- const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
- Uint32 lhFragBits = req->lhFragBits + 1;
- Uint32 minLoadFactor = (req->minLoadFactor * ZBUF_SIZE) / 100;
- Uint32 maxLoadFactor = (req->maxLoadFactor * ZBUF_SIZE) / 100;
- if (minLoadFactor >= maxLoadFactor) {
- jam();
- minLoadFactor = maxLoadFactor - 1;
- }//if
- regFragPtr.p->fragState = ACTIVEFRAG;
- // NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
- regFragPtr.p->myfid = req->fragId;
- regFragPtr.p->myTableId = req->tableId;
- ndbrequire(req->kValue == 6);
- regFragPtr.p->k = req->kValue; /* TK_SIZE = 6 IN THIS VERSION */
- regFragPtr.p->expandCounter = 0;
-
- /**
- * Only allow shrink during SR
- * - to make sure we don't run out of pages during REDO log execution
- *
- * Is later restored to 0 by LQH at end of REDO log execution
- */
- regFragPtr.p->expandFlag = 0;
- regFragPtr.p->p = 0;
- regFragPtr.p->maxp = (1 << req->kValue) - 1;
- regFragPtr.p->minloadfactor = minLoadFactor;
- regFragPtr.p->maxloadfactor = maxLoadFactor;
- regFragPtr.p->slack = (regFragPtr.p->maxp + 1) * maxLoadFactor;
- regFragPtr.p->lhfragbits = lhFragBits;
- regFragPtr.p->lhdirbits = 0;
- regFragPtr.p->hashcheckbit = 0; //lhFragBits;
- regFragPtr.p->localkeylen = req->localKeyLen;
- regFragPtr.p->nodetype = (req->reqInfo >> 4) & 0x3;
- regFragPtr.p->lastOverIndex = 0;
- regFragPtr.p->dirsize = 1;
- regFragPtr.p->keyLength = req->keyLength;
- 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;
- regFragPtr.p->mytabptr = req->tableId;
- regFragPtr.p->roothashcheck = req->kValue + req->lhFragBits;
- regFragPtr.p->noOfElements = 0;
- for (Uint32 i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
- regFragPtr.p->scan[i] = RNIL;
- }//for
-
- Uint32 hasCharAttr = g_key_descriptor_pool.getPtr(req->tableId)->hasCharAttr;
- regFragPtr.p->hasCharAttr = hasCharAttr;
-}//Dbacc::initFragAdd()
-
-void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
-{
- regFragPtr.p->directory = RNIL;
- regFragPtr.p->overflowdir = RNIL;
- regFragPtr.p->firstOverflowRec = RNIL;
- regFragPtr.p->lastOverflowRec = RNIL;
- regFragPtr.p->lockOwnersList = RNIL;
- regFragPtr.p->firstFreeDirindexRec = RNIL;
-
- regFragPtr.p->activeDataPage = 0;
- regFragPtr.p->hasCharAttr = ZFALSE;
- regFragPtr.p->nextAllocPage = 0;
- regFragPtr.p->fragState = FREEFRAG;
-}//Dbacc::initFragGeneral()
-
-
-void
-Dbacc::releaseLogicalPage(Fragmentrec * fragP, Uint32 logicalPageId){
- Ptr<struct DirRange> dirRangePtr;
- dirRangePtr.i = fragP->directory;
- ptrCheckGuard(dirRangePtr, cdirrangesize, dirRange);
-
- const Uint32 lp1 = logicalPageId >> 8;
- const Uint32 lp2 = logicalPageId & 0xFF;
- ndbrequire(lp1 < 256);
-
- Ptr<struct Directoryarray> dirArrPtr;
- dirArrPtr.i = dirRangePtr.p->dirArray[lp1];
- ptrCheckGuard(dirArrPtr, cdirarraysize, directoryarray);
-
- const Uint32 physicalPageId = dirArrPtr.p->pagep[lp2];
-
- rpPageptr.i = physicalPageId;
- ptrCheckGuard(rpPageptr, cpagesize, page8);
- releasePage(0);
-
- dirArrPtr.p->pagep[lp2] = RNIL;
-}
-
-void Dbacc::execACC_SCANREQ(Signal* signal)
-{
- jamEntry();
- AccScanReq * req = (AccScanReq*)&signal->theData[0];
- tuserptr = req->senderData;
- tuserblockref = req->senderRef;
- tabptr.i = req->tableId;
- tfid = req->fragmentNo;
- tscanFlag = req->requestInfo;
- tscanTrid1 = req->transId1;
- tscanTrid2 = req->transId2;
-
- tresult = 0;
- ptrCheckGuard(tabptr, ctablesize, tabrec);
- ndbrequire(getfragmentrec(signal, fragrecptr, tfid));
-
- Uint32 i;
- for (i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
- jam();
- if (fragrecptr.p->scan[i] == RNIL) {
- jam();
- break;
- }
- }
- ndbrequire(i != MAX_PARALLEL_SCANS_PER_FRAG);
- ndbrequire(cfirstFreeScanRec != RNIL);
- seizeScanRec(signal);
-
- fragrecptr.p->scan[i] = scanPtr.i;
- scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
- scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag);
- scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag);
-
- /* TWELVE BITS OF THE ELEMENT HEAD ARE SCAN */
- /* CHECK BITS. THE MASK NOTES WHICH BIT IS */
- /* ALLOCATED FOR THE ACTIVE SCAN */
- scanPtr.p->scanMask = 1 << i;
- scanPtr.p->scanUserptr = tuserptr;
- scanPtr.p->scanUserblockref = tuserblockref;
- scanPtr.p->scanTrid1 = tscanTrid1;
- scanPtr.p->scanTrid2 = tscanTrid2;
- scanPtr.p->scanLockHeld = 0;
- scanPtr.p->scanOpsAllocated = 0;
- scanPtr.p->scanFirstActiveOp = RNIL;
- scanPtr.p->scanFirstQueuedOp = RNIL;
- scanPtr.p->scanLastQueuedOp = RNIL;
- scanPtr.p->scanFirstLockedOp = RNIL;
- scanPtr.p->scanLastLockedOp = RNIL;
- scanPtr.p->scanState = ScanRec::WAIT_NEXT;
- initScanFragmentPart(signal);
-
- /*------------------------------------------------------*/
- /* We start the timeout loop for the scan process here. */
- /*------------------------------------------------------*/
- ndbrequire(scanPtr.p->scanTimer == 0);
- if (scanPtr.p->scanContinuebCounter == 0) {
- jam();
- scanPtr.p->scanContinuebCounter = 1;
- signal->theData[0] = ZSEND_SCAN_HBREP;
- signal->theData[1] = scanPtr.i;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 2);
- }//if
- scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
- /* ************************ */
- /* ACC_SCANCONF */
- /* ************************ */
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = scanPtr.i;
- signal->theData[2] = 1; /* NR OF LOCAL FRAGMENT */
- signal->theData[3] = fragrecptr.p->fragmentid;
- signal->theData[4] = RNIL;
- signal->theData[7] = AccScanConf::ZNOT_EMPTY_FRAGMENT;
- sendSignal(scanPtr.p->scanUserblockref, GSN_ACC_SCANCONF, signal, 8, JBB);
- /* NOT EMPTY FRAGMENT */
- return;
-}//Dbacc::execACC_SCANREQ()
-
-/* ******************--------------------------------------------------------------- */
-/* NEXT_SCANREQ REQUEST FOR NEXT ELEMENT OF */
-/* ******************------------------------------+ A FRAGMENT. */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execNEXT_SCANREQ(Signal* signal)
-{
- Uint32 tscanNextFlag;
- jamEntry();
- scanPtr.i = signal->theData[0];
- operationRecPtr.i = signal->theData[1];
- tscanNextFlag = signal->theData[2];
- /* ------------------------------------------ */
- /* 1 = ZCOPY_NEXT GET NEXT ELEMENT */
- /* 2 = ZCOPY_NEXT_COMMIT COMMIT THE */
- /* ACTIVE ELEMENT AND GET THE NEXT ONE */
- /* 3 = ZCOPY_COMMIT COMMIT THE ACTIVE ELEMENT */
- /* 4 = ZCOPY_REPEAT GET THE ACTIVE ELEMENT */
- /* 5 = ZCOPY_ABORT RELOCK THE ACTIVE ELEMENT */
- /* 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY */
- /* ------------------------------------------ */
- tresult = 0;
- ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
- ndbrequire(scanPtr.p->scanState == ScanRec::WAIT_NEXT);
-
- scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
- switch (tscanNextFlag) {
- case NextScanReq::ZSCAN_NEXT:
- jam();
- /*empty*/;
- break;
- case NextScanReq::ZSCAN_NEXT_COMMIT:
- case NextScanReq::ZSCAN_COMMIT:
- jam();
- /* --------------------------------------------------------------------- */
- /* COMMIT ACTIVE OPERATION.
- * SEND NEXT SCAN ELEMENT IF IT IS ZCOPY_NEXT_COMMIT.
- * --------------------------------------------------------------------- */
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (!scanPtr.p->scanReadCommittedFlag) {
- commitOperation(signal);
- }//if
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- takeOutActiveScanOp(signal);
- releaseOpRec(signal);
- scanPtr.p->scanOpsAllocated--;
- if (tscanNextFlag == NextScanReq::ZSCAN_COMMIT) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 1);
- return;
- }//if
- break;
- case NextScanReq::ZSCAN_CLOSE:
- jam();
- fragrecptr.i = scanPtr.p->activeLocalFrag;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- /* ---------------------------------------------------------------------
- * THE SCAN PROCESS IS FINISHED. RELOCK ALL LOCKED EL.
- * RELESE ALL INVOLVED REC.
- * ------------------------------------------------------------------- */
- releaseScanLab(signal);
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
- execACC_CHECK_SCAN(signal);
- return;
-}//Dbacc::execNEXT_SCANREQ()
-
-void Dbacc::checkNextBucketLab(Signal* signal)
-{
- DirRangePtr cscDirRangePtr;
- DirectoryarrayPtr cscDirptr;
- DirectoryarrayPtr tnsDirptr;
- Page8Ptr nsPageptr;
- Page8Ptr cscPageidptr;
- Page8Ptr gnsPageidptr;
- Page8Ptr tnsPageidptr;
- Uint32 tnsElementptr;
- Uint32 tnsContainerptr;
- Uint32 tnsIsLocked;
- Uint32 tnsTmp1;
- Uint32 tnsTmp2;
- Uint32 tnsCopyIndex1;
- Uint32 tnsCopyIndex2;
- Uint32 tnsCopyDir;
-
- tnsCopyDir = scanPtr.p->nextBucketIndex >> fragrecptr.p->k;
- tnsCopyIndex1 = tnsCopyDir >> 8;
- tnsCopyIndex2 = tnsCopyDir & 0xff;
- arrGuard(tnsCopyIndex1, 256);
- tnsDirptr.i = gnsDirRangePtr.p->dirArray[tnsCopyIndex1];
- ptrCheckGuard(tnsDirptr, cdirarraysize, directoryarray);
- tnsPageidptr.i = tnsDirptr.p->pagep[tnsCopyIndex2];
- ptrCheckGuard(tnsPageidptr, cpagesize, page8);
- gnsPageidptr.i = tnsPageidptr.i;
- gnsPageidptr.p = tnsPageidptr.p;
- tnsTmp1 = (1 << fragrecptr.p->k) - 1;
- tgsePageindex = scanPtr.p->nextBucketIndex & tnsTmp1;
- gsePageidptr.i = gnsPageidptr.i;
- gsePageidptr.p = gnsPageidptr.p;
- if (!getScanElement(signal)) {
- scanPtr.p->nextBucketIndex++;
- if (scanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
- if (scanPtr.p->nextBucketIndex > scanPtr.p->maxBucketIndexToRescan) {
- /* ---------------------------------------------------------------- */
- // We have finished the rescan phase.
- // We are ready to proceed with the next fragment part.
- /* ---------------------------------------------------------------- */
- jam();
- checkNextFragmentLab(signal);
- return;
- }//if
- } else if (scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
- if ((fragrecptr.p->p + fragrecptr.p->maxp) < scanPtr.p->nextBucketIndex) {
- /* ---------------------------------------------------------------- */
- // All buckets have been scanned a first time.
- /* ---------------------------------------------------------------- */
- if (scanPtr.p->minBucketIndexToRescan == 0xFFFFFFFF) {
- jam();
- /* -------------------------------------------------------------- */
- // We have not had any merges behind the scan.
- // Thus it is not necessary to perform any rescan any buckets
- // and we can proceed immediately with the next fragment part.
- /* --------------------------------------------------------------- */
- checkNextFragmentLab(signal);
- return;
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- // Some buckets are in the need of rescanning due to merges that have moved records
- // from in front of the scan to behind the scan. During the merges we kept track of
- // which buckets that need a rescan. We start with the minimum and end with maximum.
- /* --------------------------------------------------------------------------------- */
- scanPtr.p->nextBucketIndex = scanPtr.p->minBucketIndexToRescan;
- scanPtr.p->scanBucketState = ScanRec::SECOND_LAP;
- if (scanPtr.p->maxBucketIndexToRescan > (fragrecptr.p->p + fragrecptr.p->maxp)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- // If we have had so many merges that the maximum is bigger than the number of buckets
- // then we will simply satisfy ourselves with scanning to the end. This can only happen
- // after bringing down the total of buckets to less than half and the minimum should
- // be 0 otherwise there is some problem.
- /* --------------------------------------------------------------------------------- */
- if (scanPtr.p->minBucketIndexToRescan != 0) {
- jam();
- sendSystemerror(signal, __LINE__);
- return;
- }//if
- scanPtr.p->maxBucketIndexToRescan = fragrecptr.p->p + fragrecptr.p->maxp;
- }//if
- }//if
- }//if
- }//if
- if ((scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) &&
- (scanPtr.p->nextBucketIndex <= scanPtr.p->startNoOfBuckets)) {
- /* --------------------------------------------------------------------------------- */
- // We will only reset the scan indicator on the buckets that existed at the start of the
- // scan. The others will be handled by the split and merge code.
- /* --------------------------------------------------------------------------------- */
- tnsTmp2 = (1 << fragrecptr.p->k) - 1;
- trsbPageindex = scanPtr.p->nextBucketIndex & tnsTmp2;
- if (trsbPageindex != 0) {
- jam();
- rsbPageidptr.i = gnsPageidptr.i;
- rsbPageidptr.p = gnsPageidptr.p;
- } else {
- jam();
- cscDirRangePtr.i = fragrecptr.p->directory;
- tmpP = scanPtr.p->nextBucketIndex >> fragrecptr.p->k;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(cscDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- cscDirptr.i = cscDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(cscDirptr, cdirarraysize, directoryarray);
- cscPageidptr.i = cscDirptr.p->pagep[tmpP];
- ptrCheckGuard(cscPageidptr, cpagesize, page8);
- tmp1 = (1 << fragrecptr.p->k) - 1;
- trsbPageindex = scanPtr.p->nextBucketIndex & tmp1;
- rsbPageidptr.i = cscPageidptr.i;
- rsbPageidptr.p = cscPageidptr.p;
- }//if
- releaseScanBucket(signal);
- }//if
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- return;
- }//if
- /* ----------------------------------------------------------------------- */
- /* AN ELEMENT WHICH HAVE NOT BEEN SCANNED WAS FOUND. WE WILL PREPARE IT */
- /* TO BE SENT TO THE LQH BLOCK FOR FURTHER PROCESSING. */
- /* WE ASSUME THERE ARE OPERATION RECORDS AVAILABLE SINCE LQH SHOULD HAVE*/
- /* GUARANTEED THAT THROUGH EARLY BOOKING. */
- /* ----------------------------------------------------------------------- */
- tnsIsLocked = tgseIsLocked;
- tnsElementptr = tgseElementptr;
- tnsContainerptr = tgseContainerptr;
- nsPageptr.i = gsePageidptr.i;
- nsPageptr.p = gsePageidptr.p;
- seizeOpRec(signal);
- tisoIsforward = tgseIsforward;
- tisoContainerptr = tnsContainerptr;
- tisoElementptr = tnsElementptr;
- isoPageptr.i = nsPageptr.i;
- isoPageptr.p = nsPageptr.p;
- initScanOpRec(signal);
-
- if (!tnsIsLocked){
- if (!scanPtr.p->scanReadCommittedFlag) {
- jam();
- slPageidptr = nsPageptr;
- tslElementptr = tnsElementptr;
- setlock(signal);
- insertLockOwnersList(signal, operationRecPtr);
- operationRecPtr.p->m_op_bits |=
- Operationrec::OP_STATE_RUNNING | Operationrec::OP_RUN_QUEUE;
- }//if
- } else {
- arrGuard(tnsElementptr, 2048);
- queOperPtr.i =
- ElementHeader::getOpPtrI(nsPageptr.p->word32[tnsElementptr]);
- ptrCheckGuard(queOperPtr, coprecsize, operationrec);
- if (queOperPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED ||
- queOperPtr.p->localdata[0] == ~(Uint32)0)
- {
- jam();
- /* ------------------------------------------------------------------ */
- // If the lock owner indicates the element is disappeared then
- // we will not report this tuple. We will continue with the next tuple.
- /* ------------------------------------------------------------------ */
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- releaseOpRec(signal);
- scanPtr.p->scanOpsAllocated--;
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- return;
- }//if
- if (!scanPtr.p->scanReadCommittedFlag) {
- Uint32 return_result;
- if (scanPtr.p->scanLockMode == ZREADLOCK) {
- jam();
- return_result = placeReadInLockQueue(queOperPtr);
- } else {
- jam();
- return_result = placeWriteInLockQueue(queOperPtr);
- }//if
- if (return_result == ZSERIAL_QUEUE) {
- /* -----------------------------------------------------------------
- * WE PLACED THE OPERATION INTO A SERIAL QUEUE AND THUS WE HAVE TO
- * WAIT FOR THE LOCK TO BE RELEASED. WE CONTINUE WITH THE NEXT ELEMENT
- * ----------------------------------------------------------------- */
- putOpScanLockQue(); /* PUT THE OP IN A QUE IN THE SCAN REC */
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- return;
- } else if (return_result != ZPARALLEL_QUEUE) {
- jam();
- /* ----------------------------------------------------------------- */
- // The tuple is either not committed yet or a delete in
- // the same transaction (not possible here since we are a scan).
- // Thus we simply continue with the next tuple.
- /* ----------------------------------------------------------------- */
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- releaseOpRec(signal);
- scanPtr.p->scanOpsAllocated--;
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- return;
- }//if
- ndbassert(return_result == ZPARALLEL_QUEUE);
- }//if
- }//if
- /* ----------------------------------------------------------------------- */
- // Committed read proceed without caring for locks immediately
- // down here except when the tuple was deleted permanently
- // and no new operation has inserted it again.
- /* ----------------------------------------------------------------------- */
- putActiveScanOp(signal);
- sendNextScanConf(signal);
- return;
-}//Dbacc::checkNextBucketLab()
-
-
-void Dbacc::checkNextFragmentLab(Signal* signal)
-{
- scanPtr.p->scanBucketState = ScanRec::SCAN_COMPLETED;
- // The scan is completed. ACC_CHECK_SCAN will perform all the necessary
- // checks to see
- // what the next step is.
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- execACC_CHECK_SCAN(signal);
- return;
-}//Dbacc::checkNextFragmentLab()
-
-void Dbacc::initScanFragmentPart(Signal* signal)
-{
- DirRangePtr cnfDirRangePtr;
- DirectoryarrayPtr cnfDirptr;
- Page8Ptr cnfPageidptr;
- /* ----------------------------------------------------------------------- */
- // Set the active fragment part.
- // Set the current bucket scanned to the first.
- // Start with the first lap.
- // Remember the number of buckets at start of the scan.
- // Set the minimum and maximum to values that will always be smaller and
- // larger than.
- // Reset the scan indicator on the first bucket.
- /* ----------------------------------------------------------------------- */
- scanPtr.p->activeLocalFrag = fragrecptr.i;
- scanPtr.p->nextBucketIndex = 0; /* INDEX OF SCAN BUCKET */
- scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
- scanPtr.p->startNoOfBuckets = fragrecptr.p->p + fragrecptr.p->maxp;
- scanPtr.p->minBucketIndexToRescan = 0xFFFFFFFF;
- scanPtr.p->maxBucketIndexToRescan = 0;
- cnfDirRangePtr.i = fragrecptr.p->directory;
- ptrCheckGuard(cnfDirRangePtr, cdirrangesize, dirRange);
- cnfDirptr.i = cnfDirRangePtr.p->dirArray[0];
- ptrCheckGuard(cnfDirptr, cdirarraysize, directoryarray);
- cnfPageidptr.i = cnfDirptr.p->pagep[0];
- ptrCheckGuard(cnfPageidptr, cpagesize, page8);
- trsbPageindex = scanPtr.p->nextBucketIndex & ((1 << fragrecptr.p->k) - 1);
- rsbPageidptr.i = cnfPageidptr.i;
- rsbPageidptr.p = cnfPageidptr.p;
- releaseScanBucket(signal);
-}//Dbacc::initScanFragmentPart()
-
-/* -------------------------------------------------------------------------
- * FLAG = 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY OR ABORTED.
- * ALL OPERATION IN THE ACTIVE OR WAIT QUEUE ARE RELEASED,
- * SCAN FLAG OF ROOT FRAG IS RESET AND THE SCAN RECORD IS RELEASED.
- * ------------------------------------------------------------------------ */
-void Dbacc::releaseScanLab(Signal* signal)
-{
- releaseAndCommitActiveOps(signal);
- releaseAndCommitQueuedOps(signal);
- releaseAndAbortLockedOps(signal);
-
- fragrecptr.i = scanPtr.p->activeLocalFrag;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- for (tmp = 0; tmp < MAX_PARALLEL_SCANS_PER_FRAG; tmp++) {
- jam();
- if (fragrecptr.p->scan[tmp] == scanPtr.i) {
- jam();
- fragrecptr.p->scan[tmp] = RNIL;
- }//if
- }//for
- // Stops the heartbeat.
- scanPtr.p->scanTimer = 0;
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = RNIL;
- signal->theData[2] = RNIL;
- sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
- releaseScanRec(signal);
- return;
-}//Dbacc::releaseScanLab()
-
-
-void Dbacc::releaseAndCommitActiveOps(Signal* signal)
-{
- OperationrecPtr trsoOperPtr;
- operationRecPtr.i = scanPtr.p->scanFirstActiveOp;
- while (operationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- trsoOperPtr.i = operationRecPtr.p->nextOp;
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (!scanPtr.p->scanReadCommittedFlag) {
- jam();
- if ((operationRecPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
- Operationrec::OP_STATE_EXECUTED)
- {
- commitOperation(signal);
- }
- else
- {
- abortOperation(signal);
- }
- }//if
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- takeOutActiveScanOp(signal);
- releaseOpRec(signal);
- scanPtr.p->scanOpsAllocated--;
- operationRecPtr.i = trsoOperPtr.i;
- }//if
-}//Dbacc::releaseAndCommitActiveOps()
-
-
-void Dbacc::releaseAndCommitQueuedOps(Signal* signal)
-{
- OperationrecPtr trsoOperPtr;
- operationRecPtr.i = scanPtr.p->scanFirstQueuedOp;
- while (operationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- trsoOperPtr.i = operationRecPtr.p->nextOp;
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (!scanPtr.p->scanReadCommittedFlag) {
- jam();
- if ((operationRecPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
- Operationrec::OP_STATE_EXECUTED)
- {
- commitOperation(signal);
- }
- else
- {
- abortOperation(signal);
- }
- }//if
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- takeOutReadyScanQueue(signal);
- releaseOpRec(signal);
- scanPtr.p->scanOpsAllocated--;
- operationRecPtr.i = trsoOperPtr.i;
- }//if
-}//Dbacc::releaseAndCommitQueuedOps()
-
-void Dbacc::releaseAndAbortLockedOps(Signal* signal) {
-
- OperationrecPtr trsoOperPtr;
- operationRecPtr.i = scanPtr.p->scanFirstLockedOp;
- while (operationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- trsoOperPtr.i = operationRecPtr.p->nextOp;
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (!scanPtr.p->scanReadCommittedFlag) {
- jam();
- abortOperation(signal);
- }//if
- takeOutScanLockQueue(scanPtr.i);
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- releaseOpRec(signal);
- scanPtr.p->scanOpsAllocated--;
- operationRecPtr.i = trsoOperPtr.i;
- }//if
-}//Dbacc::releaseAndAbortLockedOps()
-
-/* 3.18.3 ACC_CHECK_SCAN */
-/* ******************--------------------------------------------------------------- */
-/* ACC_CHECK_SCAN */
-/* ENTER ACC_CHECK_SCAN WITH */
-/* SCAN_PTR */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACC_CHECK_SCAN */
-/* ******************------------------------------+ */
-void Dbacc::execACC_CHECK_SCAN(Signal* signal)
-{
- Uint32 TcheckLcpStop;
- jamEntry();
- scanPtr.i = signal->theData[0];
- TcheckLcpStop = signal->theData[1];
- ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
- while (scanPtr.p->scanFirstQueuedOp != RNIL) {
- jam();
- //---------------------------------------------------------------------
- // An operation has been released from the lock queue.
- // We are in the parallel queue of this tuple. We are
- // ready to report the tuple now.
- //------------------------------------------------------------------------
- operationRecPtr.i = scanPtr.p->scanFirstQueuedOp;
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- takeOutReadyScanQueue(signal);
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (operationRecPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED)
- {
- jam();
- abortOperation(signal);
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
- releaseOpRec(signal);
- scanPtr.p->scanOpsAllocated--;
- continue;
- }//if
- putActiveScanOp(signal);
- sendNextScanConf(signal);
- return;
- }//while
-
-
- if ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) &&
- (scanPtr.p->scanLockHeld == 0)) {
- jam();
- //----------------------------------------------------------------------------
- // The scan is now completed and there are no more locks outstanding. Thus we
- // we will report the scan as completed to LQH.
- //----------------------------------------------------------------------------
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = RNIL;
- signal->theData[2] = RNIL;
- sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
- return;
- }//if
- if (TcheckLcpStop == AccCheckScan::ZCHECK_LCP_STOP) {
- //---------------------------------------------------------------------------
- // To ensure that the block of the fragment occurring at the start of a local
- // checkpoint is not held for too long we insert a release and reacquiring of
- // that lock here. This is performed in LQH. If we are blocked or if we have
- // requested a sleep then we will receive RNIL in the returning signal word.
- //---------------------------------------------------------------------------
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] =
- ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) ||
- (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED));
- EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
- jamEntry();
- if (signal->theData[0] == RNIL) {
- jam();
- return;
- }//if
- }//if
- /**
- * If we have more than max locks held OR
- * scan is completed AND at least one lock held
- * - Inform LQH about this condition
- */
- if ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) ||
- (cfreeopRec == RNIL) ||
- ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) &&
- (scanPtr.p->scanLockHeld > 0))) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = RNIL; // No operation is returned
- signal->theData[2] = 512; // MASV
- sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
- return;
- }
- if (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) {
- jam();
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- execACC_CHECK_SCAN(signal);
- return;
- }//if
-
- scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
-
- fragrecptr.i = scanPtr.p->activeLocalFrag;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- gnsDirRangePtr.i = fragrecptr.p->directory;
- ptrCheckGuard(gnsDirRangePtr, cdirrangesize, dirRange);
- checkNextBucketLab(signal);
- return;
-}//Dbacc::execACC_CHECK_SCAN()
-
-/* ******************---------------------------------------------------- */
-/* ACC_TO_REQ PERFORM A TAKE OVER */
-/* ******************-------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execACC_TO_REQ(Signal* signal)
-{
- OperationrecPtr tatrOpPtr;
-
- jamEntry();
- tatrOpPtr.i = signal->theData[1]; /* OPER PTR OF ACC */
- ptrCheckGuard(tatrOpPtr, coprecsize, operationrec);
- if ((tatrOpPtr.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP)
- {
- tatrOpPtr.p->transId1 = signal->theData[2];
- tatrOpPtr.p->transId2 = signal->theData[3];
- validate_lock_queue(tatrOpPtr);
- } else {
- jam();
- signal->theData[0] = cminusOne;
- signal->theData[1] = ZTO_OP_STATE_ERROR;
- }//if
- return;
-}//Dbacc::execACC_TO_REQ()
-
-/* --------------------------------------------------------------------------------- */
-/* CONTAINERINFO */
-/* INPUT: */
-/* CI_PAGEIDPTR (PAGE POINTER WHERE CONTAINER RESIDES) */
-/* TCI_PAGEINDEX (INDEX OF CONTAINER, USED TO CALCULATE PAGE INDEX) */
-/* TCI_ISFORWARD (DIRECTION OF CONTAINER FORWARD OR BACKWARD) */
-/* */
-/* OUTPUT: */
-/* TCI_CONTAINERPTR (A POINTER TO THE HEAD OF THE CONTAINER) */
-/* TCI_CONTAINERLEN (LENGTH OF THE CONTAINER */
-/* TCI_CONTAINERHEAD (THE HEADER OF THE CONTAINER) */
-/* */
-/* DESCRIPTION: THE ADDRESS OF THE CONTAINER WILL BE CALCULATED AND */
-/* ALL INFORMATION ABOUT THE CONTAINER WILL BE READ */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::containerinfo(Signal* signal)
-{
- tciContainerptr = (tciPageindex << ZSHIFT_PLUS) - (tciPageindex << ZSHIFT_MINUS);
- if (tciIsforward == ZTRUE) {
- jam();
- tciContainerptr = tciContainerptr + ZHEAD_SIZE;
- } else {
- jam();
- tciContainerptr = ((tciContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
- }//if
- arrGuard(tciContainerptr, 2048);
- tciContainerhead = ciPageidptr.p->word32[tciContainerptr];
- tciContainerlen = tciContainerhead >> 26;
-}//Dbacc::containerinfo()
-
-/* --------------------------------------------------------------------------------- */
-/* GET_SCAN_ELEMENT */
-/* INPUT: GSE_PAGEIDPTR */
-/* TGSE_PAGEINDEX */
-/* OUTPUT: TGSE_IS_LOCKED (IF TRESULT /= ZFALSE) */
-/* GSE_PAGEIDPTR */
-/* TGSE_PAGEINDEX */
-/* --------------------------------------------------------------------------------- */
-bool Dbacc::getScanElement(Signal* signal)
-{
- tgseIsforward = ZTRUE;
- NEXTSEARCH_SCAN_LOOP:
- ciPageidptr.i = gsePageidptr.i;
- ciPageidptr.p = gsePageidptr.p;
- tciPageindex = tgsePageindex;
- tciIsforward = tgseIsforward;
- containerinfo(signal);
- sscPageidptr.i = gsePageidptr.i;
- sscPageidptr.p = gsePageidptr.p;
- tsscContainerlen = tciContainerlen;
- tsscContainerptr = tciContainerptr;
- tsscIsforward = tciIsforward;
- if (searchScanContainer(signal)) {
- jam();
- tgseIsLocked = tsscIsLocked;
- tgseElementptr = tsscElementptr;
- tgseContainerptr = tsscContainerptr;
- return true;
- }//if
- if (((tciContainerhead >> 7) & 0x3) != 0) {
- jam();
- nciPageidptr.i = gsePageidptr.i;
- nciPageidptr.p = gsePageidptr.p;
- tnciContainerhead = tciContainerhead;
- tnciContainerptr = tciContainerptr;
- nextcontainerinfo(signal);
- tgsePageindex = tnciPageindex;
- gsePageidptr.i = nciPageidptr.i;
- gsePageidptr.p = nciPageidptr.p;
- tgseIsforward = tnciIsforward;
- goto NEXTSEARCH_SCAN_LOOP;
- }//if
- return false;
-}//Dbacc::getScanElement()
-
-/* --------------------------------------------------------------------------------- */
-/* INIT_SCAN_OP_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initScanOpRec(Signal* signal)
-{
- Uint32 tisoTmp;
- Uint32 tisoLocalPtr;
- Uint32 guard24;
-
- scanPtr.p->scanOpsAllocated++;
-
- Uint32 opbits = 0;
- opbits |= ZSCAN_OP;
- opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_LOCK_MODE : 0;
- opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0;
- opbits |= (scanPtr.p->scanReadCommittedFlag ?
- (Uint32) Operationrec::OP_EXECUTED_DIRTY_READ : 0);
- opbits |= Operationrec::OP_COMMIT_DELETE_CHECK;
- operationRecPtr.p->userptr = RNIL;
- operationRecPtr.p->scanRecPtr = scanPtr.i;
- operationRecPtr.p->fid = fragrecptr.p->myfid;
- operationRecPtr.p->fragptr = fragrecptr.i;
- operationRecPtr.p->nextParallelQue = RNIL;
- operationRecPtr.p->prevParallelQue = RNIL;
- operationRecPtr.p->nextSerialQue = RNIL;
- operationRecPtr.p->prevSerialQue = RNIL;
- operationRecPtr.p->transId1 = scanPtr.p->scanTrid1;
- operationRecPtr.p->transId2 = scanPtr.p->scanTrid2;
- operationRecPtr.p->elementIsforward = tisoIsforward;
- operationRecPtr.p->elementContainer = tisoContainerptr;
- operationRecPtr.p->elementPointer = tisoElementptr;
- operationRecPtr.p->elementPage = isoPageptr.i;
- operationRecPtr.p->m_op_bits = opbits;
- tisoLocalPtr = tisoElementptr + tisoIsforward;
- guard24 = fragrecptr.p->localkeylen - 1;
- for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
- arrGuard(tisoTmp, 2);
- arrGuard(tisoLocalPtr, 2048);
- operationRecPtr.p->localdata[tisoTmp] = isoPageptr.p->word32[tisoLocalPtr];
- tisoLocalPtr = tisoLocalPtr + tisoIsforward;
- }//for
- arrGuard(tisoLocalPtr, 2048);
- operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
- operationRecPtr.p->xfrmtupkeylen = 0; // not used
-}//Dbacc::initScanOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* NEXTCONTAINERINFO */
-/* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */
-/* ABOUT NEXT CONTAINER IN THE BUCKET. */
-/* INPUT: TNCI_CONTAINERHEAD */
-/* NCI_PAGEIDPTR */
-/* TNCI_CONTAINERPTR */
-/* OUTPUT: */
-/* TNCI_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED). */
-/* TNCI_ISFORWARD (IS THE NEXT CONTAINER FORWARD (+1) OR BACKWARD (-1) */
-/* NCI_PAGEIDPTR (PAGE REFERENCE OF NEXT CONTAINER) */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::nextcontainerinfo(Signal* signal)
-{
- tnciNextSamePage = (tnciContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
- /* THE NEXT CONTAINER IS IN THE SAME PAGE */
- tnciPageindex = tnciContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
- if (((tnciContainerhead >> 7) & 3) == ZLEFT) {
- jam();
- tnciIsforward = ZTRUE;
- } else {
- jam();
- tnciIsforward = cminusOne;
- }//if
- if (tnciNextSamePage == ZFALSE) {
- jam();
- /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
- arrGuard(tnciContainerptr + 1, 2048);
- tnciTmp = nciPageidptr.p->word32[tnciContainerptr + 1];
- nciOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tnciTmp >> 8), 256);
- nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8];
- ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray);
- nciPageidptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff];
- ptrCheckGuard(nciPageidptr, cpagesize, page8);
- }//if
-}//Dbacc::nextcontainerinfo()
-
-/* --------------------------------------------------------------------------------- */
-/* PUT_ACTIVE_SCAN_OP */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::putActiveScanOp(Signal* signal)
-{
- OperationrecPtr pasOperationRecPtr;
- pasOperationRecPtr.i = scanPtr.p->scanFirstActiveOp;
- if (pasOperationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(pasOperationRecPtr, coprecsize, operationrec);
- pasOperationRecPtr.p->prevOp = operationRecPtr.i;
- }//if
- operationRecPtr.p->nextOp = pasOperationRecPtr.i;
- operationRecPtr.p->prevOp = RNIL;
- scanPtr.p->scanFirstActiveOp = operationRecPtr.i;
-}//Dbacc::putActiveScanOp()
-
-/**
- * putOpScanLockQueue
- *
- * Description: Put an operation in the doubly linked
- * lock list on a scan record. The list is used to
- * keep track of which operations belonging
- * to the scan are put in serial lock list of another
- * operation
- *
- * @note Use takeOutScanLockQueue to remove an operation
- * from the list
- *
- */
-void Dbacc::putOpScanLockQue()
-{
-
-#ifdef VM_TRACE
- // DEBUG CODE
- // Check that there are as many operations in the lockqueue as
- // scanLockHeld indicates
- OperationrecPtr tmpOp;
- int numLockedOpsBefore = 0;
- tmpOp.i = scanPtr.p->scanFirstLockedOp;
- while(tmpOp.i != RNIL){
- numLockedOpsBefore++;
- ptrCheckGuard(tmpOp, coprecsize, operationrec);
- if (tmpOp.p->nextOp == RNIL)
- ndbrequire(tmpOp.i == scanPtr.p->scanLastLockedOp);
- tmpOp.i = tmpOp.p->nextOp;
- }
- ndbrequire(numLockedOpsBefore==scanPtr.p->scanLockHeld);
-#endif
-
- OperationrecPtr pslOperationRecPtr;
- ScanRec theScanRec;
- theScanRec = *scanPtr.p;
-
- pslOperationRecPtr.i = scanPtr.p->scanLastLockedOp;
- operationRecPtr.p->prevOp = pslOperationRecPtr.i;
- operationRecPtr.p->nextOp = RNIL;
- if (pslOperationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(pslOperationRecPtr, coprecsize, operationrec);
- pslOperationRecPtr.p->nextOp = operationRecPtr.i;
- } else {
- jam();
- scanPtr.p->scanFirstLockedOp = operationRecPtr.i;
- }//if
- scanPtr.p->scanLastLockedOp = operationRecPtr.i;
- scanPtr.p->scanLockHeld++;
-
-}//Dbacc::putOpScanLockQue()
-
-/* --------------------------------------------------------------------------------- */
-/* PUT_READY_SCAN_QUEUE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::putReadyScanQueue(Signal* signal, Uint32 scanRecIndex)
-{
- OperationrecPtr prsOperationRecPtr;
- ScanRecPtr TscanPtr;
-
- TscanPtr.i = scanRecIndex;
- ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
-
- prsOperationRecPtr.i = TscanPtr.p->scanLastQueuedOp;
- operationRecPtr.p->prevOp = prsOperationRecPtr.i;
- operationRecPtr.p->nextOp = RNIL;
- TscanPtr.p->scanLastQueuedOp = operationRecPtr.i;
- if (prsOperationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(prsOperationRecPtr, coprecsize, operationrec);
- prsOperationRecPtr.p->nextOp = operationRecPtr.i;
- } else {
- jam();
- TscanPtr.p->scanFirstQueuedOp = operationRecPtr.i;
- }//if
-}//Dbacc::putReadyScanQueue()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_SCAN_BUCKET */
-// Input:
-// rsbPageidptr.i Index to page where buckets starts
-// rsbPageidptr.p Pointer to page where bucket starts
-// trsbPageindex Page index of starting container in bucket
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseScanBucket(Signal* signal)
-{
- Uint32 trsbIsforward;
-
- trsbIsforward = ZTRUE;
- NEXTRELEASESCANLOOP:
- ciPageidptr.i = rsbPageidptr.i;
- ciPageidptr.p = rsbPageidptr.p;
- tciPageindex = trsbPageindex;
- tciIsforward = trsbIsforward;
- containerinfo(signal);
- rscPageidptr.i = rsbPageidptr.i;
- rscPageidptr.p = rsbPageidptr.p;
- trscContainerlen = tciContainerlen;
- trscContainerptr = tciContainerptr;
- trscIsforward = trsbIsforward;
- releaseScanContainer(signal);
- if (((tciContainerhead >> 7) & 0x3) != 0) {
- jam();
- nciPageidptr.i = rsbPageidptr.i;
- nciPageidptr.p = rsbPageidptr.p;
- tnciContainerhead = tciContainerhead;
- tnciContainerptr = tciContainerptr;
- nextcontainerinfo(signal);
- rsbPageidptr.i = nciPageidptr.i;
- rsbPageidptr.p = nciPageidptr.p;
- trsbPageindex = tnciPageindex;
- trsbIsforward = tnciIsforward;
- goto NEXTRELEASESCANLOOP;
- }//if
-}//Dbacc::releaseScanBucket()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_SCAN_CONTAINER */
-/* INPUT: TRSC_CONTAINERLEN */
-/* RSC_PAGEIDPTR */
-/* TRSC_CONTAINERPTR */
-/* TRSC_ISFORWARD */
-/* SCAN_PTR */
-/* */
-/* DESCRIPTION: SEARCHS IN A CONTAINER, AND THE SCAN BIT OF THE ELEMENTS */
-/* OF THE CONTAINER IS RESET */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseScanContainer(Signal* signal)
-{
- OperationrecPtr rscOperPtr;
- Uint32 trscElemStep;
- Uint32 trscElementptr;
- Uint32 trscElemlens;
- Uint32 trscElemlen;
-
- if (trscContainerlen < 4) {
- if (trscContainerlen != ZCON_HEAD_SIZE) {
- jam();
- sendSystemerror(signal, __LINE__);
- }//if
- 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;
- trscElemStep = trscElemlen;
- } else {
- jam();
- trscElementptr = trscContainerptr - 1;
- trscElemStep = 0 - trscElemlen;
- }//if
- do {
- arrGuard(trscElementptr, 2048);
- const Uint32 eh = rscPageidptr.p->word32[trscElementptr];
- const Uint32 scanMask = scanPtr.p->scanMask;
- if (ElementHeader::getUnlocked(eh)) {
- jam();
- const Uint32 tmp = ElementHeader::clearScanBit(eh, scanMask);
- dbgWord32(rscPageidptr, trscElementptr, tmp);
- rscPageidptr.p->word32[trscElementptr] = tmp;
- } else {
- jam();
- rscOperPtr.i = ElementHeader::getOpPtrI(eh);
- ptrCheckGuard(rscOperPtr, coprecsize, operationrec);
- rscOperPtr.p->scanBits &= ~scanMask;
- }//if
- trscElemlens = trscElemlens - trscElemlen;
- trscElementptr = trscElementptr + trscElemStep;
- } while (trscElemlens > 1);
- if (trscElemlens != 0) {
- jam();
- sendSystemerror(signal, __LINE__);
- }//if
-}//Dbacc::releaseScanContainer()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_SCAN_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseScanRec(Signal* signal)
-{
- // Check that all ops this scan has allocated have been
- // released
- ndbrequire(scanPtr.p->scanOpsAllocated==0);
-
- // Check that all locks this scan might have aquired
- // have been properly released
- ndbrequire(scanPtr.p->scanLockHeld == 0);
- ndbrequire(scanPtr.p->scanFirstLockedOp == RNIL);
- ndbrequire(scanPtr.p->scanLastLockedOp == RNIL);
-
- // Check that all active operations have been
- // properly released
- ndbrequire(scanPtr.p->scanFirstActiveOp == RNIL);
-
- // Check that all queued operations have been
- // properly released
- ndbrequire(scanPtr.p->scanFirstQueuedOp == RNIL);
- ndbrequire(scanPtr.p->scanLastQueuedOp == RNIL);
-
- // Put scan record in free list
- scanPtr.p->scanNextfreerec = cfirstFreeScanRec;
- scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT;
- cfirstFreeScanRec = scanPtr.i;
-
-}//Dbacc::releaseScanRec()
-
-/* --------------------------------------------------------------------------------- */
-/* SEARCH_SCAN_CONTAINER */
-/* INPUT: TSSC_CONTAINERLEN */
-/* TSSC_CONTAINERPTR */
-/* TSSC_ISFORWARD */
-/* SSC_PAGEIDPTR */
-/* SCAN_PTR */
-/* OUTPUT: TSSC_IS_LOCKED */
-/* */
-/* DESCRIPTION: SEARCH IN A CONTAINER TO FIND THE NEXT SCAN ELEMENT. */
-/* TO DO THIS THE SCAN BIT OF THE ELEMENT HEADER IS CHECKED. IF */
-/* THIS BIT IS ZERO, IT IS SET TO ONE AND THE ELEMENT IS RETURNED.*/
-/* --------------------------------------------------------------------------------- */
-bool Dbacc::searchScanContainer(Signal* signal)
-{
- OperationrecPtr sscOperPtr;
- Uint32 tsscScanBits;
- Uint32 tsscElemlens;
- Uint32 tsscElemlen;
- Uint32 tsscElemStep;
-
- if (tsscContainerlen < 4) {
- jam();
- return false; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
- }//if
- tsscElemlens = tsscContainerlen - ZCON_HEAD_SIZE;
- tsscElemlen = fragrecptr.p->elementLength;
- /* LENGTH OF THE ELEMENT */
- if (tsscIsforward == 1) {
- jam();
- tsscElementptr = tsscContainerptr + ZCON_HEAD_SIZE;
- tsscElemStep = tsscElemlen;
- } else {
- jam();
- tsscElementptr = tsscContainerptr - 1;
- tsscElemStep = 0 - tsscElemlen;
- }//if
- SCANELEMENTLOOP001:
- arrGuard(tsscElementptr, 2048);
- const Uint32 eh = sscPageidptr.p->word32[tsscElementptr];
- tsscIsLocked = ElementHeader::getLocked(eh);
- if (!tsscIsLocked){
- jam();
- tsscScanBits = ElementHeader::getScanBits(eh);
- if ((scanPtr.p->scanMask & tsscScanBits) == 0) {
- jam();
- const Uint32 tmp = ElementHeader::setScanBit(eh, scanPtr.p->scanMask);
- dbgWord32(sscPageidptr, tsscElementptr, tmp);
- sscPageidptr.p->word32[tsscElementptr] = tmp;
- return true;
- }//if
- } else {
- jam();
- sscOperPtr.i = ElementHeader::getOpPtrI(eh);
- ptrCheckGuard(sscOperPtr, coprecsize, operationrec);
- if ((sscOperPtr.p->scanBits & scanPtr.p->scanMask) == 0) {
- jam();
- sscOperPtr.p->scanBits |= scanPtr.p->scanMask;
- return true;
- }//if
- }//if
- /* THE ELEMENT IS ALREADY SENT. */
- /* SEARCH FOR NEXT ONE */
- tsscElemlens = tsscElemlens - tsscElemlen;
- if (tsscElemlens > 1) {
- jam();
- tsscElementptr = tsscElementptr + tsscElemStep;
- goto SCANELEMENTLOOP001;
- }//if
- return false;
-}//Dbacc::searchScanContainer()
-
-/* --------------------------------------------------------------------------------- */
-/* SEND THE RESPONSE NEXT_SCANCONF AND POSSIBLE KEYINFO SIGNALS AS WELL. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::sendNextScanConf(Signal* signal)
-{
- scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
- Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
- 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;
-}//Dbacc::sendNextScanConf()
-
-/*---------------------------------------------------------------------------
- * sendScanHbRep
- * Description: Using Dispatcher::execute() to send a heartbeat to DBTC
- * from DBLQH telling the scan is alive. We use the sendScanHbRep()
- * in DBLQH, this needs to be done here in DBACC since it can take
- * a while before LQH receives an answer the normal way from ACC.
- *--------------------------------------------------------------------------*/
-void Dbacc::sendScanHbRep(Signal* signal, Uint32 scanPtrIndex)
-{
- scanPtr.i = scanPtrIndex;
- ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
-
- // If the timer status is on we continue with a new heartbeat in one second,
- // else the loop stops and we will not send a new CONTINUEB
- if (scanPtr.p->scanTimer != 0){
- if (scanPtr.p->scanTimer == scanPtr.p->scanContinuebCounter){
- jam();
- ndbrequire(scanPtr.p->scanState != ScanRec::SCAN_DISCONNECT);
-
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = scanPtr.p->scanTrid1;
- signal->theData[2] = scanPtr.p->scanTrid2;
- EXECUTE_DIRECT(DBLQH, GSN_SCAN_HBREP, signal, 3);
- jamEntry();
- }//if
- scanPtr.p->scanContinuebCounter++;
- signal->theData[0] = ZSEND_SCAN_HBREP;
- signal->theData[1] = scanPtr.i;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 2);
- } else {
- jam();
- scanPtr.p->scanContinuebCounter = 0;
- }//if
-}//Dbacc::sendScanHbRep()
-
-/* --------------------------------------------------------------------------------- */
-/* SETLOCK */
-/* DESCRIPTION:SETS LOCK ON AN ELEMENT. INFORMATION ABOUT THE ELEMENT IS */
-/* SAVED IN THE ELEMENT HEAD.A COPY OF THIS INFORMATION WILL */
-/* BE PUT IN THE OPERATION RECORD. A FIELD IN THE HEADER OF */
-/* THE ELEMENT POINTS TO THE OPERATION RECORD. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::setlock(Signal* signal)
-{
- Uint32 tselTmp1;
-
- arrGuard(tslElementptr, 2048);
- tselTmp1 = slPageidptr.p->word32[tslElementptr];
- operationRecPtr.p->scanBits = ElementHeader::getScanBits(tselTmp1);
- operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(tselTmp1);
-
- tselTmp1 = ElementHeader::setLocked(operationRecPtr.i);
- dbgWord32(slPageidptr, tslElementptr, tselTmp1);
- slPageidptr.p->word32[tslElementptr] = tselTmp1;
-}//Dbacc::setlock()
-
-/* --------------------------------------------------------------------------------- */
-/* TAKE_OUT_ACTIVE_SCAN_OP */
-/* DESCRIPTION: AN ACTIVE SCAN OPERATION IS BELOGED TO AN ACTIVE LIST OF THE */
-/* SCAN RECORD. BY THIS SUBRUTIN THE LIST IS UPDATED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::takeOutActiveScanOp(Signal* signal)
-{
- OperationrecPtr tasOperationRecPtr;
-
- if (operationRecPtr.p->prevOp != RNIL) {
- jam();
- tasOperationRecPtr.i = operationRecPtr.p->prevOp;
- ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec);
- tasOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
- } else {
- jam();
- scanPtr.p->scanFirstActiveOp = operationRecPtr.p->nextOp;
- }//if
- if (operationRecPtr.p->nextOp != RNIL) {
- jam();
- tasOperationRecPtr.i = operationRecPtr.p->nextOp;
- ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec);
- tasOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
- }//if
-}//Dbacc::takeOutActiveScanOp()
-
-/**
- * takeOutScanLockQueue
- *
- * Description: Take out an operation from the doubly linked
- * lock list on a scan record.
- *
- * @note Use putOpScanLockQue to insert a operation in
- * the list
- *
- */
-void Dbacc::takeOutScanLockQueue(Uint32 scanRecIndex)
-{
- OperationrecPtr tslOperationRecPtr;
- ScanRecPtr TscanPtr;
-
- TscanPtr.i = scanRecIndex;
- ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
-
- if (operationRecPtr.p->prevOp != RNIL) {
- jam();
- tslOperationRecPtr.i = operationRecPtr.p->prevOp;
- ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec);
- tslOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
- } else {
- jam();
- // Check that first are pointing at operation to take out
- ndbrequire(TscanPtr.p->scanFirstLockedOp==operationRecPtr.i);
- TscanPtr.p->scanFirstLockedOp = operationRecPtr.p->nextOp;
- }//if
- if (operationRecPtr.p->nextOp != RNIL) {
- jam();
- tslOperationRecPtr.i = operationRecPtr.p->nextOp;
- ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec);
- tslOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
- } else {
- jam();
- // Check that last are pointing at operation to take out
- ndbrequire(TscanPtr.p->scanLastLockedOp==operationRecPtr.i);
- TscanPtr.p->scanLastLockedOp = operationRecPtr.p->prevOp;
- }//if
- TscanPtr.p->scanLockHeld--;
-
-#ifdef VM_TRACE
- // DEBUG CODE
- // Check that there are as many operations in the lockqueue as
- // scanLockHeld indicates
- OperationrecPtr tmpOp;
- int numLockedOps = 0;
- tmpOp.i = TscanPtr.p->scanFirstLockedOp;
- while(tmpOp.i != RNIL){
- numLockedOps++;
- ptrCheckGuard(tmpOp, coprecsize, operationrec);
- if (tmpOp.p->nextOp == RNIL)
- ndbrequire(tmpOp.i == TscanPtr.p->scanLastLockedOp);
- tmpOp.i = tmpOp.p->nextOp;
- }
- ndbrequire(numLockedOps==TscanPtr.p->scanLockHeld);
-#endif
-}//Dbacc::takeOutScanLockQueue()
-
-/* --------------------------------------------------------------------------------- */
-/* TAKE_OUT_READY_SCAN_QUEUE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::takeOutReadyScanQueue(Signal* signal)
-{
- OperationrecPtr trsOperationRecPtr;
-
- if (operationRecPtr.p->prevOp != RNIL) {
- jam();
- trsOperationRecPtr.i = operationRecPtr.p->prevOp;
- ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec);
- trsOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
- } else {
- jam();
- scanPtr.p->scanFirstQueuedOp = operationRecPtr.p->nextOp;
- }//if
- if (operationRecPtr.p->nextOp != RNIL) {
- jam();
- trsOperationRecPtr.i = operationRecPtr.p->nextOp;
- ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec);
- trsOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
- } else {
- jam();
- scanPtr.p->scanLastQueuedOp = operationRecPtr.p->nextOp;
- }//if
-}//Dbacc::takeOutReadyScanQueue()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF SCAN MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-
-bool Dbacc::getfragmentrec(Signal* signal, FragmentrecPtr& rootPtr, Uint32 fid)
-{
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabptr.p->fragholder[i] == fid) {
- jam();
- fragrecptr.i = tabptr.p->fragptrholder[i];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- return true;
- }//if
- }//for
- return false;
-}//Dbacc::getrootfragmentrec()
-
-/* --------------------------------------------------------------------------------- */
-/* INIT_OVERPAGE */
-/* INPUT. IOP_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */
-/* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
-/* ACCORDING TO LH3 AND PAGE STRUCTOR DESCRIPTION OF NDBACC BLOCK */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initOverpage(Signal* signal)
-{
- Uint32 tiopTmp;
- Uint32 tiopPrevFree;
- Uint32 tiopNextFree;
-
- for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) {
- iopPageptr.p->word32[tiopIndex] = 0;
- }//for
- iopPageptr.p->word32[ZPOS_OVERFLOWREC] = iopOverflowRecPtr.i;
- iopPageptr.p->word32[ZPOS_CHECKSUM] = 0;
- iopPageptr.p->word32[ZPOS_PAGE_ID] = tiopPageId;
- iopPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0;
- tiopTmp = ZEMPTYLIST;
- tiopTmp = (tiopTmp << 16) + (tiopTmp << 23);
- iopPageptr.p->word32[ZPOS_EMPTY_LIST] = tiopTmp + (1 << ZPOS_PAGE_TYPE_BIT);
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
- /* --------------------------------------------------------------------------------- */
- tiopIndex = ZHEAD_SIZE + 1;
- iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST;
- for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) {
- tiopIndex = tiopIndex + ZBUF_SIZE;
- iopPageptr.p->word32[tiopIndex] = tiopPrevFree;
- }//for
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
- /* --------------------------------------------------------------------------------- */
- tiopIndex = ZHEAD_SIZE;
- for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) {
- iopPageptr.p->word32[tiopIndex] = tiopNextFree;
- tiopIndex = tiopIndex + ZBUF_SIZE;
- }//for
- iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* LEFT_LIST IS UPDATED */
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
- /* --------------------------------------------------------------------------------- */
- tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 1;
- iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST;
- for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) {
- tiopIndex = tiopIndex + ZBUF_SIZE;
- iopPageptr.p->word32[tiopIndex] = tiopPrevFree;
- }//for
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
- /* --------------------------------------------------------------------------------- */
- tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 2;
- for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) {
- iopPageptr.p->word32[tiopIndex] = tiopNextFree;
- tiopIndex = tiopIndex + ZBUF_SIZE;
- }//for
- iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* RIGHT_LIST IS UPDATED */
-}//Dbacc::initOverpage()
-
-/* --------------------------------------------------------------------------------- */
-/* INIT_PAGE */
-/* INPUT. INP_PAGEPTR, POINTER TO A 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::initPage(Signal* signal)
-{
- Uint32 tinpTmp1;
- Uint32 tinpIndex;
- Uint32 tinpTmp;
- Uint32 tinpPrevFree;
- Uint32 tinpNextFree;
-
- for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) {
- inpPageptr.p->word32[tiopIndex] = 0;
- }//for
- /* --------------------------------------------------------------------------------- */
- /* SET PAGE ID FOR USE OF CHECKPOINTER. */
- /* PREPARE CONTAINER HEADERS INDICATING EMPTY CONTAINERS WITHOUT NEXT. */
- /* --------------------------------------------------------------------------------- */
- inpPageptr.p->word32[ZPOS_PAGE_ID] = tipPageId;
- tinpTmp1 = ZCON_HEAD_SIZE;
- tinpTmp1 = tinpTmp1 << 26;
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE ZNO_CONTAINERS PREDEFINED HEADERS ON LEFT SIZE. */
- /* --------------------------------------------------------------------------------- */
- tinpIndex = ZHEAD_SIZE;
- for (tinpTmp = 0; tinpTmp <= ZNO_CONTAINERS - 1; tinpTmp++) {
- inpPageptr.p->word32[tinpIndex] = tinpTmp1;
- tinpIndex = tinpIndex + ZBUF_SIZE;
- }//for
- /* WORD32(ZPOS_EMPTY_LIST) DATA STRUCTURE:*/
- /*--------------------------------------- */
- /*| PAGE TYPE|LEFT FREE|RIGHT FREE */
- /*| 1 | LIST | LIST */
- /*| BIT | 7 BITS | 7 BITS */
- /*--------------------------------------- */
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE FIRST POINTER TO DOUBLY LINKED LIST OF FREE CONTAINERS. */
- /* INITIALISE EMPTY LISTS OF USED CONTAINERS. */
- /* INITIALISE LEFT FREE LIST TO 64 AND RIGHT FREE LIST TO ZERO. */
- /* ALSO INITIALISE PAGE TYPE TO NOT OVERFLOW PAGE. */
- /* --------------------------------------------------------------------------------- */
- tinpTmp = ZEMPTYLIST;
- tinpTmp = (tinpTmp << 16) + (tinpTmp << 23);
- tinpTmp = tinpTmp + (ZNO_CONTAINERS << 7);
- inpPageptr.p->word32[ZPOS_EMPTY_LIST] = tinpTmp;
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
- /* --------------------------------------------------------------------------------- */
- tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 1;
- inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
- for (tinpPrevFree = 0; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) {
- tinpIndex = tinpIndex + ZBUF_SIZE;
- inpPageptr.p->word32[tinpIndex] = tinpPrevFree;
- }//for
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
- /* --------------------------------------------------------------------------------- */
- tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 2;
- for (tinpNextFree = 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) {
- inpPageptr.p->word32[tinpIndex] = tinpNextFree;
- tinpIndex = tinpIndex + ZBUF_SIZE;
- }//for
- inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
- /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */
- /* PREDEFINED AS OCCUPIED. */
- /* --------------------------------------------------------------------------------- */
- tinpIndex = (ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE;
- for (tinpNextFree = ZNO_CONTAINERS + 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) {
- inpPageptr.p->word32[tinpIndex] = tinpNextFree;
- tinpIndex = tinpIndex + ZBUF_SIZE;
- }//for
- inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
- /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */
- /* PREDEFINED AS OCCUPIED. */
- /* --------------------------------------------------------------------------------- */
- tinpIndex = ((ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE) + 1;
- inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
- for (tinpPrevFree = ZNO_CONTAINERS; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) {
- tinpIndex = tinpIndex + ZBUF_SIZE;
- inpPageptr.p->word32[tinpIndex] = tinpPrevFree;
- }//for
- /* --------------------------------------------------------------------------------- */
- /* INITIALISE HEADER POSITIONS NOT CURRENTLY USED AND ENSURE USE OF OVERFLOW */
- /* RECORD POINTER ON THIS PAGE LEADS TO ERROR. */
- /* --------------------------------------------------------------------------------- */
- inpPageptr.p->word32[ZPOS_CHECKSUM] = 0;
- inpPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0;
- inpPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
-}//Dbacc::initPage()
-
-/* --------------------------------------------------------------------------------- */
-/* PUT_OVERFLOW_REC_IN_FRAG */
-/* DESCRIPTION: AN OVERFLOW RECORD WITCH IS USED TO KEEP INFORMATION ABOUT */
-/* OVERFLOW PAGE WILL BE PUT IN A LIST OF OVERFLOW RECORDS IN */
-/* THE FRAGMENT RECORD. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::putOverflowRecInFrag(Signal* signal)
-{
- OverflowRecordPtr tpifNextOverrecPtr;
- OverflowRecordPtr tpifPrevOverrecPtr;
-
- tpifNextOverrecPtr.i = fragrecptr.p->firstOverflowRec;
- LINT_INIT(tpifPrevOverrecPtr.p);
- tpifPrevOverrecPtr.i = RNIL;
- while (tpifNextOverrecPtr.i != RNIL) {
- ptrCheckGuard(tpifNextOverrecPtr, coverflowrecsize, overflowRecord);
- if (tpifNextOverrecPtr.p->dirindex < porOverflowRecPtr.p->dirindex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/
- /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */
- /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */
- /* PERFORMED. */
- /* --------------------------------------------------------------------------------- */
- tpifPrevOverrecPtr = tpifNextOverrecPtr;
- tpifNextOverrecPtr.i = tpifNextOverrecPtr.p->nextOverRec;
- } else {
- jam();
- ndbrequire(tpifNextOverrecPtr.p->dirindex != porOverflowRecPtr.p->dirindex);
- /* --------------------------------------------------------------------------------- */
- /* TRYING TO INSERT THE SAME PAGE TWICE. SYSTEM ERROR. */
- /* --------------------------------------------------------------------------------- */
- break;
- }//if
- }//while
- if (tpifNextOverrecPtr.i == RNIL) {
- jam();
- fragrecptr.p->lastOverflowRec = porOverflowRecPtr.i;
- } else {
- jam();
- tpifNextOverrecPtr.p->prevOverRec = porOverflowRecPtr.i;
- }//if
- if (tpifPrevOverrecPtr.i == RNIL) {
- jam();
- fragrecptr.p->firstOverflowRec = porOverflowRecPtr.i;
- } else {
- jam();
- tpifPrevOverrecPtr.p->nextOverRec = porOverflowRecPtr.i;
- }//if
- porOverflowRecPtr.p->prevOverRec = tpifPrevOverrecPtr.i;
- porOverflowRecPtr.p->nextOverRec = tpifNextOverrecPtr.i;
-}//Dbacc::putOverflowRecInFrag()
-
-/* --------------------------------------------------------------------------------- */
-/* PUT_REC_IN_FREE_OVERDIR */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::putRecInFreeOverdir(Signal* signal)
-{
- OverflowRecordPtr tpfoNextOverrecPtr;
- OverflowRecordPtr tpfoPrevOverrecPtr;
-
- tpfoNextOverrecPtr.i = fragrecptr.p->firstFreeDirindexRec;
- LINT_INIT(tpfoPrevOverrecPtr.p);
- tpfoPrevOverrecPtr.i = RNIL;
- while (tpfoNextOverrecPtr.i != RNIL) {
- ptrCheckGuard(tpfoNextOverrecPtr, coverflowrecsize, overflowRecord);
- if (tpfoNextOverrecPtr.p->dirindex < priOverflowRecPtr.p->dirindex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/
- /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */
- /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */
- /* PERFORMED. */
- /* --------------------------------------------------------------------------------- */
- tpfoPrevOverrecPtr = tpfoNextOverrecPtr;
- tpfoNextOverrecPtr.i = tpfoNextOverrecPtr.p->nextOverList;
- } else {
- jam();
- ndbrequire(tpfoNextOverrecPtr.p->dirindex != priOverflowRecPtr.p->dirindex);
- /* --------------------------------------------------------------------------------- */
- /* ENSURE WE ARE NOT TRYING TO INSERT THE SAME PAGE TWICE. */
- /* --------------------------------------------------------------------------------- */
- break;
- }//if
- }//while
- if (tpfoNextOverrecPtr.i != RNIL) {
- jam();
- tpfoNextOverrecPtr.p->prevOverList = priOverflowRecPtr.i;
- }//if
- if (tpfoPrevOverrecPtr.i == RNIL) {
- jam();
- fragrecptr.p->firstFreeDirindexRec = priOverflowRecPtr.i;
- } else {
- jam();
- tpfoPrevOverrecPtr.p->nextOverList = priOverflowRecPtr.i;
- }//if
- priOverflowRecPtr.p->prevOverList = tpfoPrevOverrecPtr.i;
- priOverflowRecPtr.p->nextOverList = tpfoNextOverrecPtr.i;
-}//Dbacc::putRecInFreeOverdir()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_DIRECTORY */
-/* --------------------------------------- ----------------------------------------- */
-void Dbacc::releaseDirectory(Signal* signal)
-{
- ptrCheckGuard(rdDirptr, cdirarraysize, directoryarray);
- rdDirptr.p->pagep[0] = cfirstfreedir;
- cfirstfreedir = rdDirptr.i;
-}//Dbacc::releaseDirectory()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_DIRRANGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseDirrange(Signal* signal)
-{
- ptrCheckGuard(rdDirRangePtr, cdirrangesize, dirRange);
- rdDirRangePtr.p->dirArray[0] = cfirstfreeDirrange;
- cfirstfreeDirrange = rdDirRangePtr.i;
-}//Dbacc::releaseDirrange()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE OP RECORD */
-/* PUT A FREE OPERATION IN A FREE LIST OF THE OPERATIONS */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseOpRec(Signal* signal)
-{
-#if 0
- // DEBUG CODE
- // Check that the operation to be released isn't
- // already in the list of free operations
- // Since this code loops through the entire list of free operations
- // it's only enabled in VM_TRACE mode
- OperationrecPtr opRecPtr;
- bool opInList = false;
- opRecPtr.i = cfreeopRec;
- while (opRecPtr.i != RNIL){
- if (opRecPtr.i == operationRecPtr.i){
- opInList = true;
- break;
- }
- ptrCheckGuard(opRecPtr, coprecsize, operationrec);
- opRecPtr.i = opRecPtr.p->nextOp;
- }
- ndbrequire(opInList == false);
-#endif
- ndbrequire(operationRecPtr.p->m_op_bits == Operationrec::OP_INITIAL);
-
- operationRecPtr.p->nextOp = cfreeopRec;
- cfreeopRec = operationRecPtr.i; /* UPDATE FREE LIST OF OP RECORDS */
- operationRecPtr.p->prevOp = RNIL;
- operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
-}//Dbacc::releaseOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_OVERFLOW_REC */
-/* PUT A FREE OVERFLOW REC IN A FREE LIST OF THE OVERFLOW RECORDS */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseOverflowRec(Signal* signal)
-{
- rorOverflowRecPtr.p->nextfreeoverrec = cfirstfreeoverrec;
- cfirstfreeoverrec = rorOverflowRecPtr.i;
-}//Dbacc::releaseOverflowRec()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_OVERPAGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseOverpage(Signal* signal)
-{
- DirRangePtr ropOverflowrangeptr;
- DirectoryarrayPtr ropOverflowDirptr;
- OverflowRecordPtr ropOverflowRecPtr;
- OverflowRecordPtr tuodOverflowRecPtr;
- Uint32 tropTmp;
- Uint32 tropTmp1;
- Uint32 tropTmp2;
-
- ropOverflowRecPtr.i = ropPageptr.p->word32[ZPOS_OVERFLOWREC];
- ndbrequire(ropOverflowRecPtr.i != RNIL);
- /* THE OVERFLOW REC WILL BE TAKEN OUT OF THE */
- /* FREELIST OF OVERFLOW PAGE WITH FREE */
- /* CONTAINER AND WILL BE PUT IN THE FREE LIST */
- /* OF THE FREE DIRECTORY INDEXES. */
- if ((fragrecptr.p->lastOverflowRec == ropOverflowRecPtr.i) &&
- (fragrecptr.p->firstOverflowRec == ropOverflowRecPtr.i)) {
- jam();
- return; /* THERE IS ONLY ONE OVERFLOW PAGE */
- }//if
-#if kalle
- logicalPage = 0;
-
- i = fragrecptr.p->directory;
- p = dirRange.getPtr(i);
-
- i1 = logicalPage >> 8;
- i2 = logicalPage & 0xFF;
-
- ndbrequire(i1 < 256);
-
- i = p->dirArray[i1];
- p = directoryarray.getPtr(i);
-
- physicPageId = p->pagep[i2];
- physicPageP = page8.getPtr(physicPageId);
-
- p->pagep[i2] = RNIL;
- rpPageptr = { physicPageId, physicPageP };
- releasePage(signal);
-
-#endif
-
- /* ----------------------------------------------------------------------- */
- /* IT WAS OK TO RELEASE THE PAGE. */
- /* ----------------------------------------------------------------------- */
- ptrCheckGuard(ropOverflowRecPtr, coverflowrecsize, overflowRecord);
- tfoOverflowRecPtr = ropOverflowRecPtr;
- takeRecOutOfFreeOverpage(signal);
- ropOverflowRecPtr.p->overpage = RNIL;
- priOverflowRecPtr = ropOverflowRecPtr;
- putRecInFreeOverdir(signal);
- tropTmp = ropPageptr.p->word32[ZPOS_PAGE_ID];
- ropOverflowrangeptr.i = fragrecptr.p->overflowdir;
- tropTmp1 = tropTmp >> 8;
- tropTmp2 = tropTmp & 0xff;
- ptrCheckGuard(ropOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard(tropTmp1, 256);
- ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1];
- ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray);
- ropOverflowDirptr.p->pagep[tropTmp2] = RNIL;
- rpPageptr = ropPageptr;
- releasePage(signal);
- if (ropOverflowRecPtr.p->dirindex != (fragrecptr.p->lastOverIndex - 1)) {
- jam();
- return;
- }//if
- /* ----------------------------------------------------------------------- */
- /* THE LAST PAGE IN THE DIRECTORY WAS RELEASED IT IS NOW NECESSARY
- * TO REMOVE ALL RELEASED OVERFLOW DIRECTORIES AT THE END OF THE LIST.
- * ---------------------------------------------------------------------- */
- do {
- fragrecptr.p->lastOverIndex--;
- if (tropTmp2 == 0) {
- jam();
- ndbrequire(tropTmp1 != 0);
- ropOverflowrangeptr.p->dirArray[tropTmp1] = RNIL;
- rdDirptr.i = ropOverflowDirptr.i;
- releaseDirectory(signal);
- tropTmp1--;
- tropTmp2 = 255;
- } else {
- jam();
- tropTmp2--;
- }//if
- ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1];
- ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray);
- } while (ropOverflowDirptr.p->pagep[tropTmp2] == RNIL);
- /* ----------------------------------------------------------------------- */
- /* RELEASE ANY OVERFLOW RECORDS THAT ARE PART OF THE FREE INDEX LIST WHICH */
- /* DIRECTORY INDEX NOW HAS BEEN RELEASED. */
- /* ----------------------------------------------------------------------- */
- tuodOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
- jam();
- while (tuodOverflowRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(tuodOverflowRecPtr, coverflowrecsize, overflowRecord);
- if (tuodOverflowRecPtr.p->dirindex >= fragrecptr.p->lastOverIndex) {
- jam();
- rorOverflowRecPtr = tuodOverflowRecPtr;
- troOverflowRecPtr.p = tuodOverflowRecPtr.p;
- tuodOverflowRecPtr.i = troOverflowRecPtr.p->nextOverList;
- takeRecOutOfFreeOverdir(signal);
- releaseOverflowRec(signal);
- } else {
- jam();
- tuodOverflowRecPtr.i = tuodOverflowRecPtr.p->nextOverList;
- }//if
- }//while
-}//Dbacc::releaseOverpage()
-
-/* ------------------------------------------------------------------------- */
-/* RELEASE_PAGE */
-/* ------------------------------------------------------------------------- */
-void Dbacc::releasePage(Signal* signal)
-{
-#ifdef VM_TRACE
- bool inList = false;
- Uint32 numInList = 0;
- Page8Ptr tmpPagePtr;
- tmpPagePtr.i = cfirstfreepage;
- while (tmpPagePtr.i != RNIL){
- ptrCheckGuard(tmpPagePtr, cpagesize, page8);
- if (tmpPagePtr.i == rpPageptr.i){
- jam(); inList = true;
- break;
- }
- numInList++;
- tmpPagePtr.i = tmpPagePtr.p->word32[0];
- }
- ndbrequire(inList == false);
- // ndbrequire(numInList == cnoOfAllocatedPages);
-#endif
- rpPageptr.p->word32[0] = cfirstfreepage;
- cfirstfreepage = rpPageptr.i;
- cnoOfAllocatedPages--;
-}//Dbacc::releasePage()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_DIRECTORY */
-/* DESCRIPTION: A DIRECTORY BLOCK (ZDIRBLOCKSIZE NUMBERS OF DIRECTORY */
-/* RECORDS WILL BE ALLOCATED AND RETURNED. */
-/* SIZE OF DIRECTORY ERROR_CODE, WILL BE RETURNED IF THERE IS NO ANY */
-/* FREE BLOCK */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeDirectory(Signal* signal)
-{
- Uint32 tsdyIndex;
-
- if (cfirstfreedir == RNIL) {
- jam();
- if (cdirarraysize <= cdirmemory) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- } else {
- jam();
- sdDirptr.i = cdirmemory;
- ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray);
- cdirmemory = cdirmemory + 1;
- }//if
- } else {
- jam();
- sdDirptr.i = cfirstfreedir;
- ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray);
- cfirstfreedir = sdDirptr.p->pagep[0];
- sdDirptr.p->pagep[0] = RNIL;
- }//if
- for (tsdyIndex = 0; tsdyIndex <= 255; tsdyIndex++) {
- sdDirptr.p->pagep[tsdyIndex] = RNIL;
- }//for
-}//Dbacc::seizeDirectory()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_DIRRANGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeDirrange(Signal* signal)
-{
- Uint32 tsdeIndex;
-
- newDirRangePtr.i = cfirstfreeDirrange;
- ptrCheckGuard(newDirRangePtr, cdirrangesize, dirRange);
- cfirstfreeDirrange = newDirRangePtr.p->dirArray[0];
- for (tsdeIndex = 0; tsdeIndex <= 255; tsdeIndex++) {
- newDirRangePtr.p->dirArray[tsdeIndex] = RNIL;
- }//for
-}//Dbacc::seizeDirrange()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE FRAGREC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeFragrec(Signal* signal)
-{
- fragrecptr.i = cfirstfreefrag;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- cfirstfreefrag = fragrecptr.p->nextfreefrag;
- fragrecptr.p->nextfreefrag = RNIL;
-}//Dbacc::seizeFragrec()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_OP_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeOpRec(Signal* signal)
-{
- operationRecPtr.i = cfreeopRec;
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- cfreeopRec = operationRecPtr.p->nextOp; /* UPDATE FREE LIST OF OP RECORDS */
- /* PUTS OPERTION RECORD PTR IN THE LIST */
- /* OF OPERATION IN CONNECTION RECORD */
- operationRecPtr.p->nextOp = RNIL;
-}//Dbacc::seizeOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE OVERFLOW RECORD */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeOverRec(Signal* signal) {
- sorOverflowRecPtr.i = cfirstfreeoverrec;
- ptrCheckGuard(sorOverflowRecPtr, coverflowrecsize, overflowRecord);
- cfirstfreeoverrec = sorOverflowRecPtr.p->nextfreeoverrec;
- sorOverflowRecPtr.p->nextfreeoverrec = RNIL;
- sorOverflowRecPtr.p->prevOverRec = RNIL;
- sorOverflowRecPtr.p->nextOverRec = RNIL;
-}//Dbacc::seizeOverRec()
-
-
-/**
- * A ZPAGESIZE_ERROR has occured, out of index pages
- * Print some debug info if debug compiled
- */
-void Dbacc::zpagesize_error(const char* where){
- DEBUG(where << endl
- << " ZPAGESIZE_ERROR" << endl
- << " cfirstfreepage=" << cfirstfreepage << endl
- << " cfreepage=" <<cfreepage<<endl
- << " cpagesize=" <<cpagesize<<endl
- << " cnoOfAllocatedPages="<<cnoOfAllocatedPages);
-}
-
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_PAGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizePage(Signal* signal)
-{
- tresult = 0;
- if (cfirstfreepage == RNIL) {
- if (cfreepage < cpagesize) {
- jam();
- spPageptr.i = cfreepage;
- ptrCheckGuard(spPageptr, cpagesize, page8);
- cfreepage++;
- cnoOfAllocatedPages++;
- } else {
- jam();
- zpagesize_error("Dbacc::seizePage");
- tresult = ZPAGESIZE_ERROR;
- }//if
- } else {
- jam();
- spPageptr.i = cfirstfreepage;
- ptrCheckGuard(spPageptr, cpagesize, page8);
- cfirstfreepage = spPageptr.p->word32[0];
- cnoOfAllocatedPages++;
- }//if
-}//Dbacc::seizePage()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_ROOTFRAGREC */
-/* --------------------------------------------------------------------------------- */
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_SCAN_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeScanRec(Signal* signal)
-{
- scanPtr.i = cfirstFreeScanRec;
- ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
- ndbrequire(scanPtr.p->scanState == ScanRec::SCAN_DISCONNECT);
- cfirstFreeScanRec = scanPtr.p->scanNextfreerec;
-}//Dbacc::seizeScanRec()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_SR_VERSION_REC */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* SEND_SYSTEMERROR */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::sendSystemerror(Signal* signal, int line)
-{
- progError(line, NDBD_EXIT_PRGERR);
-}//Dbacc::sendSystemerror()
-
-/* --------------------------------------------------------------------------------- */
-/* TAKE_REC_OUT_OF_FREE_OVERDIR */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::takeRecOutOfFreeOverdir(Signal* signal)
-{
- OverflowRecordPtr tofoOverrecPtr;
- if (troOverflowRecPtr.p->nextOverList != RNIL) {
- jam();
- tofoOverrecPtr.i = troOverflowRecPtr.p->nextOverList;
- ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord);
- tofoOverrecPtr.p->prevOverList = troOverflowRecPtr.p->prevOverList;
- }//if
- if (troOverflowRecPtr.p->prevOverList != RNIL) {
- jam();
- tofoOverrecPtr.i = troOverflowRecPtr.p->prevOverList;
- ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord);
- tofoOverrecPtr.p->nextOverList = troOverflowRecPtr.p->nextOverList;
- } else {
- jam();
- fragrecptr.p->firstFreeDirindexRec = troOverflowRecPtr.p->nextOverList;
- }//if
-}//Dbacc::takeRecOutOfFreeOverdir()
-
-/* --------------------------------------------------------------------------------- */
-/* TAKE_REC_OUT_OF_FREE_OVERPAGE */
-/* DESCRIPTION: AN OVERFLOW PAGE WHICH IS EMPTY HAVE TO BE TAKE OUT OF THE */
-/* FREE LIST OF OVERFLOW PAGE. BY THIS SUBROUTINE THIS LIST */
-/* WILL BE UPDATED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::takeRecOutOfFreeOverpage(Signal* signal)
-{
- OverflowRecordPtr tfoNextOverflowRecPtr;
- OverflowRecordPtr tfoPrevOverflowRecPtr;
-
- if (tfoOverflowRecPtr.p->nextOverRec != RNIL) {
- jam();
- tfoNextOverflowRecPtr.i = tfoOverflowRecPtr.p->nextOverRec;
- ptrCheckGuard(tfoNextOverflowRecPtr, coverflowrecsize, overflowRecord);
- tfoNextOverflowRecPtr.p->prevOverRec = tfoOverflowRecPtr.p->prevOverRec;
- } else {
- ndbrequire(fragrecptr.p->lastOverflowRec == tfoOverflowRecPtr.i);
- jam();
- fragrecptr.p->lastOverflowRec = tfoOverflowRecPtr.p->prevOverRec;
- }//if
- if (tfoOverflowRecPtr.p->prevOverRec != RNIL) {
- jam();
- tfoPrevOverflowRecPtr.i = tfoOverflowRecPtr.p->prevOverRec;
- ptrCheckGuard(tfoPrevOverflowRecPtr, coverflowrecsize, overflowRecord);
- tfoPrevOverflowRecPtr.p->nextOverRec = tfoOverflowRecPtr.p->nextOverRec;
- } else {
- ndbrequire(fragrecptr.p->firstOverflowRec == tfoOverflowRecPtr.i);
- jam();
- fragrecptr.p->firstOverflowRec = tfoOverflowRecPtr.p->nextOverRec;
- }//if
-}//Dbacc::takeRecOutOfFreeOverpage()
-
-void
-Dbacc::reportMemoryUsage(Signal* signal, int gth){
- signal->theData[0] = NDB_LE_MemoryUsage;
- signal->theData[1] = gth;
- signal->theData[2] = sizeof(* rpPageptr.p);
- signal->theData[3] = cnoOfAllocatedPages;
- signal->theData[4] = cpagesize;
- signal->theData[5] = DBACC;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB);
-}
-
-void
-Dbacc::execDUMP_STATE_ORD(Signal* signal)
-{
- DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
- if (dumpState->args[0] == DumpStateOrd::AccDumpOneScanRec){
- Uint32 recordNo = RNIL;
- if (signal->length() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- if (recordNo >= cscanRecSize)
- return;
-
- scanPtr.i = recordNo;
- ptrAss(scanPtr, scanRec);
- infoEvent("Dbacc::ScanRec[%d]: state=%d, transid(0x%x, 0x%x)",
- scanPtr.i, scanPtr.p->scanState,scanPtr.p->scanTrid1,
- scanPtr.p->scanTrid2);
- infoEvent(" timer=%d, continueBCount=%d, "
- "activeLocalFrag=%d, nextBucketIndex=%d",
- scanPtr.p->scanTimer,
- scanPtr.p->scanContinuebCounter,
- scanPtr.p->activeLocalFrag,
- scanPtr.p->nextBucketIndex);
- infoEvent(" scanNextfreerec=%d firstActOp=%d firstLockedOp=%d, "
- "scanLastLockedOp=%d firstQOp=%d lastQOp=%d",
- scanPtr.p->scanNextfreerec,
- scanPtr.p->scanFirstActiveOp,
- scanPtr.p->scanFirstLockedOp,
- scanPtr.p->scanLastLockedOp,
- scanPtr.p->scanFirstQueuedOp,
- scanPtr.p->scanLastQueuedOp);
- infoEvent(" scanUserP=%d, startNoBuck=%d, minBucketIndexToRescan=%d, "
- "maxBucketIndexToRescan=%d",
- scanPtr.p->scanUserptr,
- scanPtr.p->startNoOfBuckets,
- scanPtr.p->minBucketIndexToRescan,
- scanPtr.p->maxBucketIndexToRescan);
- infoEvent(" scanBucketState=%d, scanLockHeld=%d, userBlockRef=%d, "
- "scanMask=%d scanLockMode=%d",
- scanPtr.p->scanBucketState,
- scanPtr.p->scanLockHeld,
- scanPtr.p->scanUserblockref,
- scanPtr.p->scanMask,
- scanPtr.p->scanLockMode);
- return;
- }
-
- // Dump all ScanRec(ords)
- if (dumpState->args[0] == DumpStateOrd::AccDumpAllScanRec){
- Uint32 recordNo = 0;
- if (signal->length() == 1)
- infoEvent("ACC: Dump all ScanRec - size: %d",
- cscanRecSize);
- else if (signal->length() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
-
- if (recordNo < cscanRecSize-1){
- dumpState->args[0] = DumpStateOrd::AccDumpAllScanRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- return;
- }
-
- // Dump all active ScanRec(ords)
- if (dumpState->args[0] == DumpStateOrd::AccDumpAllActiveScanRec){
- Uint32 recordNo = 0;
- if (signal->length() == 1)
- infoEvent("ACC: Dump active ScanRec - size: %d",
- cscanRecSize);
- else if (signal->length() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- ScanRecPtr sp;
- sp.i = recordNo;
- ptrAss(sp, scanRec);
- if (sp.p->scanState != ScanRec::SCAN_DISCONNECT){
- dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
- }
-
- if (recordNo < cscanRecSize-1){
- dumpState->args[0] = DumpStateOrd::AccDumpAllActiveScanRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- return;
- }
-
- if(dumpState->args[0] == DumpStateOrd::DumpPageMemory &&
- signal->getLength() == 1){
- reportMemoryUsage(signal, 0);
- return;
- }
-
- if(dumpState->args[0] == DumpStateOrd::EnableUndoDelayDataWrite){
- ndbout << "Dbacc:: delay write of datapages for table = "
- << dumpState->args[1]<< endl;
- c_errorInsert3000_TableId = dumpState->args[1];
- SET_ERROR_INSERT_VALUE(3000);
- return;
- }
-
- if(dumpState->args[0] == DumpStateOrd::AccDumpOneOperationRec){
- Uint32 recordNo = RNIL;
- if (signal->length() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- if (recordNo >= coprecsize)
- return;
-
- OperationrecPtr tmpOpPtr;
- tmpOpPtr.i = recordNo;
- ptrAss(tmpOpPtr, operationrec);
- infoEvent("Dbacc::operationrec[%d]: transid(0x%x, 0x%x)",
- tmpOpPtr.i, tmpOpPtr.p->transId1,
- tmpOpPtr.p->transId2);
- infoEvent("elementIsforward=%d, elementPage=%d, elementPointer=%d ",
- tmpOpPtr.p->elementIsforward, tmpOpPtr.p->elementPage,
- tmpOpPtr.p->elementPointer);
- infoEvent("fid=%d, fragptr=%d, hashvaluePart=%d ",
- tmpOpPtr.p->fid, tmpOpPtr.p->fragptr,
- tmpOpPtr.p->hashvaluePart);
- infoEvent("hashValue=%d", tmpOpPtr.p->hashValue);
- infoEvent("nextLockOwnerOp=%d, nextOp=%d, nextParallelQue=%d ",
- tmpOpPtr.p->nextLockOwnerOp, tmpOpPtr.p->nextOp,
- tmpOpPtr.p->nextParallelQue);
- infoEvent("nextSerialQue=%d, prevOp=%d ",
- tmpOpPtr.p->nextSerialQue,
- tmpOpPtr.p->prevOp);
- infoEvent("prevLockOwnerOp=%d, prevParallelQue=%d",
- tmpOpPtr.p->prevLockOwnerOp, tmpOpPtr.p->nextParallelQue);
- infoEvent("prevSerialQue=%d, scanRecPtr=%d",
- tmpOpPtr.p->prevSerialQue, tmpOpPtr.p->scanRecPtr);
- infoEvent("m_op_bits=0x%x, scanBits=%d ",
- tmpOpPtr.p->m_op_bits, tmpOpPtr.p->scanBits);
- return;
- }
-
- if(dumpState->args[0] == DumpStateOrd::AccDumpNumOpRecs){
-
- Uint32 freeOpRecs = 0;
- OperationrecPtr opRecPtr;
- opRecPtr.i = cfreeopRec;
- while (opRecPtr.i != RNIL){
- freeOpRecs++;
- ptrCheckGuard(opRecPtr, coprecsize, operationrec);
- opRecPtr.i = opRecPtr.p->nextOp;
- }
-
- infoEvent("Dbacc::OperationRecords: num=%d, free=%d",
- coprecsize, freeOpRecs);
-
- return;
- }
- if(dumpState->args[0] == DumpStateOrd::AccDumpFreeOpRecs){
-
- OperationrecPtr opRecPtr;
- opRecPtr.i = cfreeopRec;
- while (opRecPtr.i != RNIL){
-
- dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec;
- dumpState->args[1] = opRecPtr.i;
- execDUMP_STATE_ORD(signal);
-
- ptrCheckGuard(opRecPtr, coprecsize, operationrec);
- opRecPtr.i = opRecPtr.p->nextOp;
- }
-
-
- return;
- }
-
- if(dumpState->args[0] == DumpStateOrd::AccDumpNotFreeOpRecs){
- Uint32 recordStart = RNIL;
- if (signal->length() == 2)
- recordStart = dumpState->args[1];
- else
- return;
-
- if (recordStart >= coprecsize)
- return;
-
- for (Uint32 i = recordStart; i < coprecsize; i++){
-
- bool inFreeList = false;
- OperationrecPtr opRecPtr;
- opRecPtr.i = cfreeopRec;
- while (opRecPtr.i != RNIL){
- if (opRecPtr.i == i){
- inFreeList = true;
- break;
- }
- ptrCheckGuard(opRecPtr, coprecsize, operationrec);
- opRecPtr.i = opRecPtr.p->nextOp;
- }
- if (inFreeList == false){
- dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec;
- dumpState->args[1] = i;
- execDUMP_STATE_ORD(signal);
- }
- }
- return;
- }
-
-#if 0
- if (type == 100) {
- RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
- req->primaryTableId = 2;
- req->secondaryTableId = RNIL;
- req->userPtr = 2;
- req->userRef = DBDICT_REF;
- sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
- RelTabMemReq::SignalLength, JBB);
- return;
- }//if
- if (type == 101) {
- RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
- req->primaryTableId = 4;
- req->secondaryTableId = 5;
- req->userPtr = 4;
- req->userRef = DBDICT_REF;
- sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
- RelTabMemReq::SignalLength, JBB);
- return;
- }//if
- if (type == 102) {
- RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
- req->primaryTableId = 6;
- req->secondaryTableId = 8;
- req->userPtr = 6;
- req->userRef = DBDICT_REF;
- sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
- RelTabMemReq::SignalLength, JBB);
- return;
- }//if
- if (type == 103) {
- DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
- req->primaryTableId = 2;
- req->secondaryTableId = RNIL;
- req->userPtr = 2;
- req->userRef = DBDICT_REF;
- sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
- DropTabFileReq::SignalLength, JBB);
- return;
- }//if
- if (type == 104) {
- DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
- req->primaryTableId = 4;
- req->secondaryTableId = 5;
- req->userPtr = 4;
- req->userRef = DBDICT_REF;
- sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
- DropTabFileReq::SignalLength, JBB);
- return;
- }//if
- if (type == 105) {
- DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
- req->primaryTableId = 6;
- req->secondaryTableId = 8;
- req->userPtr = 6;
- req->userRef = DBDICT_REF;
- sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
- DropTabFileReq::SignalLength, JBB);
- return;
- }//if
-#endif
-}//Dbacc::execDUMP_STATE_ORD()
-
-void
-Dbacc::execREAD_PSEUDO_REQ(Signal* signal){
- jamEntry();
- fragrecptr.i = signal->theData[0];
- Uint32 attrId = signal->theData[1];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- Uint64 tmp;
- switch(attrId){
- case AttributeHeader::ROW_COUNT:
- tmp = fragrecptr.p->noOfElements;
- break;
- case AttributeHeader::COMMIT_COUNT:
- tmp = fragrecptr.p->m_commit_count;
- break;
- default:
- tmp = 0;
- }
- memcpy(signal->theData, &tmp, 8); /* must be memcpy, gives strange results on
- * ithanium gcc (GCC) 3.4.1 smp linux 2.4
- * otherwise
- */
- // Uint32 * src = (Uint32*)&tmp;
- // signal->theData[0] = src[0];
- // signal->theData[1] = src[1];
-}
diff --git a/storage/ndb/src/kernel/blocks/dbdict/CreateIndex.txt b/storage/ndb/src/kernel/blocks/dbdict/CreateIndex.txt
deleted file mode 100644
index 3d11e501c07..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/CreateIndex.txt
+++ /dev/null
@@ -1,152 +0,0 @@
-Unique Hash Index
-=================
-
-unique hash index X on T(A1,...,An) becomes:
-table X with primary key A1,...,An and extra attribute NDB$PK
-
-NDB$PK is primary key of T concatenated at 4-byte boundaries
-
-Protocols:
-
-U - user, initiator of protocol
-C - coordinator
-P - participants, including coordinator node
-
-RT_ - request type, current state
-
-P always replies to C with current RT_ (initially RT_DICT_PREPARE)
-C replies to U at the end
-
-CREATE INDEX
-------------
-
-U: RT_USER
-
-C: forward request to P's
-P: check and reply
-
-C: invoke CREATE TABLE for index table
-
-C: invoke ALTER INDEX online
-
-C: send RT_DICT_COMMIT to P's
-P: reply
-
-C: reply to U
-
-DROP INDEX
-----------
-
-[ todo ]
-
-ALTER INDEX online
-------------------
-
-U: RT_USER, RT_CREATE_INDEX, RT_NODERESTART, RT_SYSTEMRESTART
-
-C: forward request to P's
-P: check and reply
-
-C: send RT_DICT_TC to P's
-P: create index in local TC, and reply
-
-C: invoke CREATE TRIGGER for insert/update/delete triggers
-
-C: invoke BUILD INDEX
-
-C: send RT_DICT_COMMIT to P's
-P: reply
-
-C: reply to U
-
-ALTER INDEX offline
--------------------
-
-[ todo ]
-
-BUILD INDEX
------------
-
-U: RT_USER, RT_ALTER_INDEX
-
-C: forward request to P's
-P: check and reply
-
-C: invoke CREATE TRIGGER for read-only constraint on NDB$PK
-
-C: send RT_DICT_TRIX to P's
-P: build index via local TRIX, and reply
-
-C: invoke DROP TRIGGER for read-only constraint on NDB$PK
-
-C: send RT_DICT_TC to P's
-P: online index in local TC, and reply
-
-CREATE TRIGGER
---------------
-
-U: RT_USER, RT_ALTER_INDEX, RT_BUILD_INDEX
-
-C: forward request to P's
-P: check and reply
-
-C: seize trigger id and send RT_DICT_CREATE to P's
-P: create trigger in DICT (also connect to index record), and reply
-
-C: invoke ALTER TRIGGER online [ not if subscription trigger ]
-
-C: send RT_DICT_COMMIT to P's
-P: reply
-
-C: reply to U
-
-DROP TRIGGER
-------------
-
-[ todo ]
-
-ALTER TRIGGER online
---------------------
-
-U: RT_USER, RT_CREATE_TRIGGER
-
-C: forward request to P's
-P: check and reply
-
-C: send RT_DICT_TC to P's
-P: create trigger in local TC, and reply
-
-C: send RT_DICT_LQH to P's
-P: create trigger in local LQH (which just forwards to TUP), and reply
-
-C: send RT_DICT_COMMIT to P's
-P: reply
-
-C: reply to U
-
-ALTER TRIGGER offline
----------------------
-
-[ todo ]
-
-Ordered Index << under work >>
-=============
-
-created as DICT table, as before, to reuse the code
-
-keep NDB$PK as last attribute (not used but logically correct)
-
-create fragments and attributes must be modified
-
-global metadata? implemented but will use signals anyway
-
-create (after-) insert/update/delete triggers as DICT objects, as before
-
-skip following:
-- create index in TC
-- create triggers in TC
-- read-only constraint on NDB$PK
-
-create (before-) commit trigger in TUP
-
-alter online (in TUX, instead of TC) is needed
diff --git a/storage/ndb/src/kernel/blocks/dbdict/CreateTable.new.txt b/storage/ndb/src/kernel/blocks/dbdict/CreateTable.new.txt
deleted file mode 100644
index d37732dcda1..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/CreateTable.new.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-1) Receive from client (sequence of DICTTABINFO)
-
-2) CREATE_FRAGMENTATION_REQ -> local DIH
- Returns all fragments for table + some other stuff
- NOTE without side effects in DIH
-
-3) Pack table description
-
-4) CREATE_TAB -> all DICTs (including table data)
- 1) Write schema file (ADD_STARTED)
- 2) Write table descriptor to file
- 3) CREATE_TAB (DIADDTABREQ) -> local DIH (including fragment info)
- 4) DIH
- 1) write table descriptor
- 2) For each local fragment
- ADD_FRAG -> local DICT
- LQHFRAGREQ -> local LQH
- LQHADDATTREQ -> local LQH
- 5) TAB_COMMITREQ -> local LQH
-
-5) WAIT_GCP
-
-6) ALTER_TAB (activate) -> all DICTs
- 1) Write schema file (CREATED)
- 2) TAB_COMMITREQ -> local DIH
- 3) TC_SCHVERREQ -> local TC
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbdict/CreateTable.txt b/storage/ndb/src/kernel/blocks/dbdict/CreateTable.txt
deleted file mode 100644
index 0b37e5d767f..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/CreateTable.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-1) Receive from client (sequence of DICTTABINFO)
-
-2) DICT_SCHEMAREQ -> all DICTs
- Write ADD_STARTED in schema file
-
-3) Pack table description
-
-4) DICTTABINFO -> all DICTs (but self) (containing packed table info)
- self -> Write 2 file
- 1) Write 2 file
-
-5) DICT_SCHEMAREQ -> all DICTs
- Write UPDATE_PAGE_COUNT in schema file
-
-6) DIADDTABREQ -> local DIH
- 1) Create fragments
- 2) For each fragment
- DIHADDFRAGREQ -> all DIH
- 3) For each fragment
- DICTFRAGSREQ -> local DICT
- 1) LQHFRAGREQ -> concerned LQH
- 2) For each attribute
- LQHADDATTREQ -> concerned LQH
-
-7) WAIT_GCP -> local DIH
-
-8) DICT_SCHEMAREQ -> all DICTs
- Write TABLE_ADD_COMMITTED in schema file
-
-9) TAB_COMMITREQ -> all LQH & DIH
-
-10) TC_SCHVERREQ -> all TC
-
-11) UNBLO_DICTREQ -> all DICT
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
deleted file mode 100644
index e0e0a496e0a..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ /dev/null
@@ -1,16702 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include <my_sys.h>
-
-#define DBDICT_C
-#include "Dbdict.hpp"
-#include "diskpage.hpp"
-
-#include <ndb_limits.h>
-#include <NdbOut.hpp>
-#include <Properties.hpp>
-#include <Configuration.hpp>
-#include <SectionReader.hpp>
-#include <SimpleProperties.hpp>
-#include <AttributeHeader.hpp>
-#include <KeyDescriptor.hpp>
-#include <signaldata/DictSchemaInfo.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/DropTabFile.hpp>
-
-#include <signaldata/EventReport.hpp>
-#include <signaldata/FsCloseReq.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/GetTableId.hpp>
-#include <signaldata/HotSpareRep.hpp>
-#include <signaldata/NFCompleteRep.hpp>
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/RelTabMem.hpp>
-#include <signaldata/WaitGCP.hpp>
-#include <signaldata/ListTables.hpp>
-
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/AlterTrig.hpp>
-#include <signaldata/DropTrig.hpp>
-#include <signaldata/CreateIndx.hpp>
-#include <signaldata/DropIndx.hpp>
-#include <signaldata/BuildIndx.hpp>
-
-#include <signaldata/DropFilegroup.hpp>
-#include <signaldata/CreateFilegroup.hpp>
-#include <signaldata/CreateFilegroupImpl.hpp>
-
-#include <signaldata/CreateEvnt.hpp>
-#include <signaldata/UtilPrepare.hpp>
-#include <signaldata/UtilExecute.hpp>
-#include <signaldata/UtilRelease.hpp>
-#include <signaldata/SumaImpl.hpp>
-
-#include <signaldata/LqhFrag.hpp>
-
-#include <signaldata/DiAddTab.hpp>
-#include <signaldata/DihStartTab.hpp>
-
-#include <signaldata/DropTable.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/PrepDropTab.hpp>
-
-#include <signaldata/CreateTable.hpp>
-#include <signaldata/AlterTable.hpp>
-#include <signaldata/AlterTab.hpp>
-#include <signaldata/CreateFragmentation.hpp>
-#include <signaldata/CreateTab.hpp>
-#include <NdbSleep.h>
-#include <signaldata/ApiBroadcast.hpp>
-
-#include <signaldata/DropObj.hpp>
-#include <signaldata/CreateObj.hpp>
-#include <SLList.hpp>
-
-#include <EventLogger.hpp>
-extern EventLogger g_eventLogger;
-
-#define ZNOT_FOUND 626
-#define ZALREADYEXIST 630
-
-//#define EVENT_PH2_DEBUG
-//#define EVENT_PH3_DEBUG
-//#define EVENT_DEBUG
-
-static const char EVENT_SYSTEM_TABLE_NAME[] = "sys/def/NDB$EVENTS_0";
-
-#define EVENT_TRACE \
-// ndbout_c("Event debug trace: File: %s Line: %u", __FILE__, __LINE__)
-
-#define DIV(x,y) (((x)+(y)-1)/(y))
-#define WORDS2PAGES(x) DIV(x, (ZSIZE_OF_PAGES_IN_WORDS - ZPAGE_HEADER_SIZE))
-#include <ndb_version.h>
-
-static
-struct {
- Uint32 m_gsn_user_req;
- Uint32 m_gsn_req;
- Uint32 m_gsn_ref;
- Uint32 m_gsn_conf;
- void (Dbdict::* m_trans_commit_start)(Signal*, Dbdict::SchemaTransaction*);
- void (Dbdict::* m_trans_commit_complete)(Signal*,Dbdict::SchemaTransaction*);
- void (Dbdict::* m_trans_abort_start)(Signal*, Dbdict::SchemaTransaction*);
- void (Dbdict::* m_trans_abort_complete)(Signal*, Dbdict::SchemaTransaction*);
-
- void (Dbdict::* m_prepare_start)(Signal*, Dbdict::SchemaOp*);
- void (Dbdict::* m_prepare_complete)(Signal*, Dbdict::SchemaOp*);
- void (Dbdict::* m_commit)(Signal*, Dbdict::SchemaOp*);
- void (Dbdict::* m_commit_start)(Signal*, Dbdict::SchemaOp*);
- void (Dbdict::* m_commit_complete)(Signal*, Dbdict::SchemaOp*);
- void (Dbdict::* m_abort)(Signal*, Dbdict::SchemaOp*);
- void (Dbdict::* m_abort_start)(Signal*, Dbdict::SchemaOp*);
- void (Dbdict::* m_abort_complete)(Signal*, Dbdict::SchemaOp*);
-
-} f_dict_op[] = {
- /**
- * Create filegroup
- */
- {
- GSN_CREATE_FILEGROUP_REQ,
- GSN_CREATE_OBJ_REQ, GSN_CREATE_OBJ_REF, GSN_CREATE_OBJ_CONF,
- 0, 0, 0, 0,
- &Dbdict::create_fg_prepare_start, &Dbdict::create_fg_prepare_complete,
- &Dbdict::createObj_commit,
- 0, 0,
- &Dbdict::createObj_abort,
- &Dbdict::create_fg_abort_start, &Dbdict::create_fg_abort_complete,
- }
-
- /**
- * Create file
- */
- ,{
- GSN_CREATE_FILE_REQ,
- GSN_CREATE_OBJ_REQ, GSN_CREATE_OBJ_REF, GSN_CREATE_OBJ_CONF,
- 0, 0, 0, 0,
- &Dbdict::create_file_prepare_start, &Dbdict::create_file_prepare_complete,
- &Dbdict::createObj_commit,
- &Dbdict::create_file_commit_start, 0,
- &Dbdict::createObj_abort,
- &Dbdict::create_file_abort_start, &Dbdict::create_file_abort_complete,
- }
-
- /**
- * Drop file
- */
- ,{
- GSN_DROP_FILE_REQ,
- GSN_DROP_OBJ_REQ, GSN_DROP_OBJ_REF, GSN_DROP_OBJ_CONF,
- 0, 0, 0, 0,
- &Dbdict::drop_file_prepare_start, 0,
- &Dbdict::dropObj_commit,
- &Dbdict::drop_file_commit_start, &Dbdict::drop_file_commit_complete,
- &Dbdict::dropObj_abort,
- &Dbdict::drop_file_abort_start, 0
- }
-
- /**
- * Drop filegroup
- */
- ,{
- GSN_DROP_FILEGROUP_REQ,
- GSN_DROP_OBJ_REQ, GSN_DROP_OBJ_REF, GSN_DROP_OBJ_CONF,
- 0, 0, 0, 0,
- &Dbdict::drop_fg_prepare_start, 0,
- &Dbdict::dropObj_commit,
- &Dbdict::drop_fg_commit_start, &Dbdict::drop_fg_commit_complete,
- &Dbdict::dropObj_abort,
- &Dbdict::drop_fg_abort_start, 0
- }
-
- /**
- * Drop undofile
- */
- ,{
- GSN_DROP_FILE_REQ,
- GSN_DROP_OBJ_REQ, GSN_DROP_OBJ_REF, GSN_DROP_OBJ_CONF,
- 0, 0, 0, 0,
- &Dbdict::drop_undofile_prepare_start, 0,
- 0,
- 0, &Dbdict::drop_undofile_commit_complete,
- 0, 0, 0
- }
-};
-
-Uint32
-alter_obj_inc_schema_version(Uint32 old)
-{
- return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000);
-}
-
-static
-Uint32
-alter_obj_dec_schema_version(Uint32 old)
-{
- return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000);
-}
-
-static
-Uint32
-create_obj_inc_schema_version(Uint32 old)
-{
- return (old + 0x00000001) & 0x00FFFFFF;
-}
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: GENERAL MODULE -------------------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains general stuff. Mostly debug signals and */
-/* general signals that go into a specific module after checking a */
-/* state variable. Also general subroutines used by many. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-/* ---------------------------------------------------------------- */
-// This signal is used to dump states of various variables in the
-// block by command.
-/* ---------------------------------------------------------------- */
-void
-Dbdict::execDUMP_STATE_ORD(Signal* signal)
-{
- jamEntry();
-
-#ifdef VM_TRACE
- if(signal->theData[0] == 1222){
- const Uint32 tab = signal->theData[1];
- PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
- req->senderRef = reference();
- req->senderData = 1222;
- req->tableId = tab;
- sendSignal(DBLQH_REF, GSN_PREP_DROP_TAB_REQ, signal,
- PrepDropTabReq::SignalLength, JBB);
- }
-
- if(signal->theData[0] == 1223){
- const Uint32 tab = signal->theData[1];
- PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
- req->senderRef = reference();
- req->senderData = 1222;
- req->tableId = tab;
- sendSignal(DBTC_REF, GSN_PREP_DROP_TAB_REQ, signal,
- PrepDropTabReq::SignalLength, JBB);
- }
-
- if(signal->theData[0] == 1224){
- const Uint32 tab = signal->theData[1];
- PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
- req->senderRef = reference();
- req->senderData = 1222;
- req->tableId = tab;
- sendSignal(DBDIH_REF, GSN_PREP_DROP_TAB_REQ, signal,
- PrepDropTabReq::SignalLength, JBB);
- }
-
- if(signal->theData[0] == 1225){
- const Uint32 tab = signal->theData[1];
- const Uint32 ver = signal->theData[2];
- TableRecordPtr tabRecPtr;
- c_tableRecordPool.getPtr(tabRecPtr, tab);
- DropTableReq * req = (DropTableReq*)signal->getDataPtr();
- req->senderData = 1225;
- req->senderRef = numberToRef(1,1);
- req->tableId = tab;
- req->tableVersion = tabRecPtr.p->tableVersion + ver;
- sendSignal(DBDICT_REF, GSN_DROP_TABLE_REQ, signal,
- DropTableReq::SignalLength, JBB);
- }
-#endif
-#define MEMINFO(x, y) infoEvent(x ": %d %d", y.getSize(), y.getNoOfFree())
- if(signal->theData[0] == 1226){
- MEMINFO("c_obj_pool", c_obj_pool);
- MEMINFO("c_opRecordPool", c_opRecordPool);
- MEMINFO("c_rope_pool", c_rope_pool);
- }
-
- if (signal->theData[0] == 1227)
- {
- DLHashTable<DictObject>::Iterator iter;
- bool ok = c_obj_hash.first(iter);
- for(; ok; ok = c_obj_hash.next(iter))
- {
- Rope name(c_rope_pool, iter.curr.p->m_name);
- char buf[1024];
- name.copy(buf);
- ndbout_c("%s m_ref_count: %d", buf, iter.curr.p->m_ref_count);
- }
- }
-
- return;
-}//Dbdict::execDUMP_STATE_ORD()
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-// CONTINUEB is used when a real-time break is needed for long
-// processes.
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-void Dbdict::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- switch (signal->theData[0]) {
- case ZPACK_TABLE_INTO_PAGES :
- jam();
- packTableIntoPages(signal);
- break;
-
- case ZSEND_GET_TAB_RESPONSE :
- jam();
- sendGetTabResponse(signal);
- break;
-
- case ZDICT_LOCK_POLL:
- jam();
- checkDictLockQueue(signal, true);
- break;
-
- default :
- ndbrequire(false);
- break;
- }//switch
- return;
-}//execCONTINUEB()
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-// Routine to handle pack table into pages.
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-
-void Dbdict::packTableIntoPages(Signal* signal)
-{
- const Uint32 tableId= signal->theData[1];
- const Uint32 type= signal->theData[2];
- const Uint32 pageId= signal->theData[3];
-
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, pageId);
-
- memset(&pagePtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
- LinearWriter w(&pagePtr.p->word[ZPAGE_HEADER_SIZE],
- ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS);
- w.first();
- switch((DictTabInfo::TableType)type) {
- case DictTabInfo::SystemTable:
- case DictTabInfo::UserTable:
- case DictTabInfo::UniqueHashIndex:
- case DictTabInfo::HashIndex:
- case DictTabInfo::UniqueOrderedIndex:
- case DictTabInfo::OrderedIndex:{
- jam();
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- packTableIntoPages(w, tablePtr, signal);
- break;
- }
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:{
- FilegroupPtr fg_ptr;
- ndbrequire(c_filegroup_hash.find(fg_ptr, tableId));
- const Uint32 free_hi= signal->theData[4];
- const Uint32 free_lo= signal->theData[5];
- packFilegroupIntoPages(w, fg_ptr, free_hi, free_lo);
- break;
- }
- case DictTabInfo::Datafile:{
- FilePtr fg_ptr;
- ndbrequire(c_file_hash.find(fg_ptr, tableId));
- const Uint32 free_extents= signal->theData[4];
- packFileIntoPages(w, fg_ptr, free_extents);
- break;
- }
- case DictTabInfo::Undofile:{
- FilePtr fg_ptr;
- ndbrequire(c_file_hash.find(fg_ptr, tableId));
- packFileIntoPages(w, fg_ptr, 0);
- break;
- }
- case DictTabInfo::UndefTableType:
- case DictTabInfo::HashIndexTrigger:
- case DictTabInfo::SubscriptionTrigger:
- case DictTabInfo::ReadOnlyConstraint:
- case DictTabInfo::IndexTrigger:
- ndbrequire(false);
- }
-
- Uint32 wordsOfTable = w.getWordsUsed();
- Uint32 pagesUsed = WORDS2PAGES(wordsOfTable);
- pagePtr.p->word[ZPOS_CHECKSUM] =
- computeChecksum(&pagePtr.p->word[0], pagesUsed * ZSIZE_OF_PAGES_IN_WORDS);
-
- switch (c_packTable.m_state) {
- case PackTable::PTS_IDLE:
- ndbrequire(false);
- break;
- case PackTable::PTS_GET_TAB:
- jam();
- c_retrieveRecord.retrievedNoOfPages = pagesUsed;
- c_retrieveRecord.retrievedNoOfWords = wordsOfTable;
- sendGetTabResponse(signal);
- return;
- break;
- }//switch
- ndbrequire(false);
- return;
-}//packTableIntoPages()
-
-void
-Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
- TableRecordPtr tablePtr,
- Signal* signal){
-
- union {
- char tableName[MAX_TAB_NAME_SIZE];
- char frmData[MAX_FRM_DATA_SIZE];
- char rangeData[16*MAX_NDB_PARTITIONS];
- char ngData[2*MAX_NDB_PARTITIONS];
- char tsData[2*2*MAX_NDB_PARTITIONS];
- char defaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
- char attributeName[MAX_ATTR_NAME_SIZE];
- };
- ConstRope r(c_rope_pool, tablePtr.p->tableName);
- r.copy(tableName);
- w.add(DictTabInfo::TableName, tableName);
- w.add(DictTabInfo::TableId, tablePtr.i);
- w.add(DictTabInfo::TableVersion, tablePtr.p->tableVersion);
- w.add(DictTabInfo::NoOfKeyAttr, tablePtr.p->noOfPrimkey);
- w.add(DictTabInfo::NoOfAttributes, tablePtr.p->noOfAttributes);
- w.add(DictTabInfo::NoOfNullable, tablePtr.p->noOfNullAttr);
- w.add(DictTabInfo::NoOfVariable, (Uint32)0);
- w.add(DictTabInfo::KeyLength, tablePtr.p->tupKeyLength);
-
- w.add(DictTabInfo::TableLoggedFlag,
- !!(tablePtr.p->m_bits & TableRecord::TR_Logged));
- w.add(DictTabInfo::RowGCIFlag,
- !!(tablePtr.p->m_bits & TableRecord::TR_RowGCI));
- w.add(DictTabInfo::RowChecksumFlag,
- !!(tablePtr.p->m_bits & TableRecord::TR_RowChecksum));
- w.add(DictTabInfo::TableTemporaryFlag,
- !!(tablePtr.p->m_bits & TableRecord::TR_Temporary));
- w.add(DictTabInfo::ForceVarPartFlag,
- !!(tablePtr.p->m_bits & TableRecord::TR_ForceVarPart));
-
- w.add(DictTabInfo::MinLoadFactor, tablePtr.p->minLoadFactor);
- w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
- w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
- w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType);
- w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType);
- w.add(DictTabInfo::MaxRowsLow, tablePtr.p->maxRowsLow);
- w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh);
- w.add(DictTabInfo::DefaultNoPartFlag, tablePtr.p->defaultNoPartFlag);
- w.add(DictTabInfo::LinearHashFlag, tablePtr.p->linearHashFlag);
- w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
- w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
- w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
- w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
-
- if(signal)
- {
- /* Denna branch körs vid GET_TABINFOREQ */
-
- Uint32 * theData = signal->getDataPtrSend();
- CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
- req->senderRef = 0;
- req->senderData = RNIL;
- req->fragmentationType = tablePtr.p->fragmentType;
- req->noOfFragments = 0;
- req->primaryTableId = tablePtr.i;
- EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
- CreateFragmentationReq::SignalLength);
- ndbrequire(signal->theData[0] == 0);
- Uint16 *data = (Uint16*)&signal->theData[25];
- Uint32 count = 2 + (1 + data[0]) * data[1];
- w.add(DictTabInfo::ReplicaDataLen, 2*count);
- for (Uint32 i = 0; i < count; i++)
- data[i] = htons(data[i]);
- w.add(DictTabInfo::ReplicaData, data, 2*count);
- }
- else
- {
- /* Denna del körs vid CREATE_TABLEREQ, ALTER_TABLEREQ */
- ;
- }
-
- if (tablePtr.p->primaryTableId != RNIL){
- TableRecordPtr primTab;
- c_tableRecordPool.getPtr(primTab, tablePtr.p->primaryTableId);
- ConstRope r2(c_rope_pool, primTab.p->tableName);
- r2.copy(tableName);
- w.add(DictTabInfo::PrimaryTable, tableName);
- w.add(DictTabInfo::PrimaryTableId, tablePtr.p->primaryTableId);
- w.add(DictTabInfo::IndexState, tablePtr.p->indexState);
- w.add(DictTabInfo::InsertTriggerId, tablePtr.p->insertTriggerId);
- w.add(DictTabInfo::UpdateTriggerId, tablePtr.p->updateTriggerId);
- w.add(DictTabInfo::DeleteTriggerId, tablePtr.p->deleteTriggerId);
- w.add(DictTabInfo::CustomTriggerId, tablePtr.p->customTriggerId);
- }
-
- ConstRope frm(c_rope_pool, tablePtr.p->frmData);
- frm.copy(frmData);
- w.add(DictTabInfo::FrmLen, frm.size());
- w.add(DictTabInfo::FrmData, frmData, frm.size());
-
- {
- jam();
- ConstRope ts(c_rope_pool, tablePtr.p->tsData);
- ts.copy(tsData);
- w.add(DictTabInfo::TablespaceDataLen, ts.size());
- w.add(DictTabInfo::TablespaceData, tsData, ts.size());
-
- ConstRope ng(c_rope_pool, tablePtr.p->ngData);
- ng.copy(ngData);
- w.add(DictTabInfo::FragmentDataLen, ng.size());
- w.add(DictTabInfo::FragmentData, ngData, ng.size());
-
- ConstRope range(c_rope_pool, tablePtr.p->rangeData);
- range.copy(rangeData);
- w.add(DictTabInfo::RangeListDataLen, range.size());
- w.add(DictTabInfo::RangeListData, rangeData, range.size());
- }
-
- if(tablePtr.p->m_tablespace_id != RNIL)
- {
- w.add(DictTabInfo::TablespaceId, tablePtr.p->m_tablespace_id);
- FilegroupPtr tsPtr;
- ndbrequire(c_filegroup_hash.find(tsPtr, tablePtr.p->m_tablespace_id));
- w.add(DictTabInfo::TablespaceVersion, tsPtr.p->m_version);
- }
-
- AttributeRecordPtr attrPtr;
- LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
- tablePtr.p->m_attributes);
- for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
- jam();
-
- ConstRope name(c_rope_pool, attrPtr.p->attributeName);
- name.copy(attributeName);
-
- w.add(DictTabInfo::AttributeName, attributeName);
- w.add(DictTabInfo::AttributeId, attrPtr.p->attributeId);
- w.add(DictTabInfo::AttributeKeyFlag, attrPtr.p->tupleKey > 0);
-
- const Uint32 desc = attrPtr.p->attributeDescriptor;
- const Uint32 attrType = AttributeDescriptor::getType(desc);
- const Uint32 attrSize = AttributeDescriptor::getSize(desc);
- const Uint32 arraySize = AttributeDescriptor::getArraySize(desc);
- const Uint32 arrayType = AttributeDescriptor::getArrayType(desc);
- const Uint32 nullable = AttributeDescriptor::getNullable(desc);
- const Uint32 DKey = AttributeDescriptor::getDKey(desc);
- const Uint32 disk= AttributeDescriptor::getDiskBased(desc);
-
-
- // AttributeType deprecated
- w.add(DictTabInfo::AttributeSize, attrSize);
- w.add(DictTabInfo::AttributeArraySize, arraySize);
- w.add(DictTabInfo::AttributeArrayType, arrayType);
- w.add(DictTabInfo::AttributeNullableFlag, nullable);
- w.add(DictTabInfo::AttributeDKey, DKey);
- 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);
- w.add(DictTabInfo::AttributeAutoIncrement,
- (Uint32)attrPtr.p->autoIncrement);
-
- if(disk)
- w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_DISK);
- else
- w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_MEMORY);
-
- ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
- def.copy(defaultValue);
- w.add(DictTabInfo::AttributeDefaultValue, defaultValue);
-
- w.add(DictTabInfo::AttributeEnd, 1);
- }
-
- w.add(DictTabInfo::TableEnd, 1);
-}
-
-void
-Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w,
- FilegroupPtr fg_ptr,
- const Uint32 undo_free_hi,
- const Uint32 undo_free_lo){
-
- DictFilegroupInfo::Filegroup fg; fg.init();
- ConstRope r(c_rope_pool, fg_ptr.p->m_name);
- r.copy(fg.FilegroupName);
-
- fg.FilegroupId = fg_ptr.p->key;
- fg.FilegroupType = fg_ptr.p->m_type;
- fg.FilegroupVersion = fg_ptr.p->m_version;
-
- switch(fg.FilegroupType){
- case DictTabInfo::Tablespace:
- //fg.TS_DataGrow = group.m_grow_spec;
- fg.TS_ExtentSize = fg_ptr.p->m_tablespace.m_extent_size;
- fg.TS_LogfileGroupId = fg_ptr.p->m_tablespace.m_default_logfile_group_id;
- FilegroupPtr lfg_ptr;
- ndbrequire(c_filegroup_hash.find(lfg_ptr, fg.TS_LogfileGroupId));
- fg.TS_LogfileGroupVersion = lfg_ptr.p->m_version;
- break;
- case DictTabInfo::LogfileGroup:
- fg.LF_UndoBufferSize = fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
- fg.LF_UndoFreeWordsHi= undo_free_hi;
- fg.LF_UndoFreeWordsLo= undo_free_lo;
- //fg.LF_UndoGrow = ;
- break;
- default:
- ndbrequire(false);
- }
-
- SimpleProperties::UnpackStatus s;
- s = SimpleProperties::pack(w,
- &fg,
- DictFilegroupInfo::Mapping,
- DictFilegroupInfo::MappingSize, true);
-
- ndbrequire(s == SimpleProperties::Eof);
-}
-
-void
-Dbdict::packFileIntoPages(SimpleProperties::Writer & w,
- FilePtr f_ptr, const Uint32 free_extents){
-
- DictFilegroupInfo::File f; f.init();
- ConstRope r(c_rope_pool, f_ptr.p->m_path);
- r.copy(f.FileName);
-
- f.FileType = f_ptr.p->m_type;
- f.FilegroupId = f_ptr.p->m_filegroup_id;; //group.m_id;
- f.FileSizeHi = (f_ptr.p->m_file_size >> 32);
- f.FileSizeLo = (f_ptr.p->m_file_size & 0xFFFFFFFF);
- f.FileFreeExtents= free_extents;
- f.FileId = f_ptr.p->key;
- f.FileVersion = f_ptr.p->m_version;
-
- FilegroupPtr lfg_ptr;
- ndbrequire(c_filegroup_hash.find(lfg_ptr, f.FilegroupId));
- f.FilegroupVersion = lfg_ptr.p->m_version;
-
- SimpleProperties::UnpackStatus s;
- s = SimpleProperties::pack(w,
- &f,
- DictFilegroupInfo::FileMapping,
- DictFilegroupInfo::FileMappingSize, true);
-
- ndbrequire(s == SimpleProperties::Eof);
-}
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-// The routines to handle responses from file system.
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-
-/* ---------------------------------------------------------------- */
-// A file was successfully closed.
-/* ---------------------------------------------------------------- */
-void Dbdict::execFSCLOSECONF(Signal* signal)
-{
- FsConnectRecordPtr fsPtr;
- FsConf * const fsConf = (FsConf *)&signal->theData[0];
- jamEntry();
- c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
- switch (fsPtr.p->fsState) {
- case FsConnectRecord::CLOSE_WRITE_SCHEMA:
- jam();
- closeWriteSchemaConf(signal, fsPtr);
- break;
- case FsConnectRecord::CLOSE_READ_SCHEMA:
- jam();
- closeReadSchemaConf(signal, fsPtr);
- break;
- case FsConnectRecord::CLOSE_READ_TAB_FILE:
- jam();
- closeReadTableConf(signal, fsPtr);
- break;
- case FsConnectRecord::CLOSE_WRITE_TAB_FILE:
- jam();
- closeWriteTableConf(signal, fsPtr);
- break;
- case FsConnectRecord::OPEN_READ_SCHEMA2:
- openSchemaFile(signal, 1, fsPtr.i, false, false);
- break;
- case FsConnectRecord::OPEN_READ_TAB_FILE2:
- openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
- break;
- default:
- jamLine((fsPtr.p->fsState & 0xFFF));
- ndbrequire(false);
- break;
- }//switch
-}//execFSCLOSECONF()
-
-
-/* ---------------------------------------------------------------- */
-// A file was successfully opened.
-/* ---------------------------------------------------------------- */
-void Dbdict::execFSOPENCONF(Signal* signal)
-{
- FsConnectRecordPtr fsPtr;
- jamEntry();
- FsConf * const fsConf = (FsConf *)&signal->theData[0];
- c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
-
- Uint32 filePointer = fsConf->filePointer;
- fsPtr.p->filePtr = filePointer;
- switch (fsPtr.p->fsState) {
- case FsConnectRecord::OPEN_WRITE_SCHEMA:
- jam();
- fsPtr.p->fsState = FsConnectRecord::WRITE_SCHEMA;
- writeSchemaFile(signal, filePointer, fsPtr.i);
- break;
- case FsConnectRecord::OPEN_READ_SCHEMA1:
- jam();
- fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA1;
- readSchemaFile(signal, filePointer, fsPtr.i);
- break;
- case FsConnectRecord::OPEN_READ_SCHEMA2:
- jam();
- fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA2;
- readSchemaFile(signal, filePointer, fsPtr.i);
- break;
- case FsConnectRecord::OPEN_READ_TAB_FILE1:
- jam();
- fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE1;
- readTableFile(signal, filePointer, fsPtr.i);
- break;
- case FsConnectRecord::OPEN_READ_TAB_FILE2:
- jam();
- fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE2;
- readTableFile(signal, filePointer, fsPtr.i);
- break;
- case FsConnectRecord::OPEN_WRITE_TAB_FILE:
- jam();
- fsPtr.p->fsState = FsConnectRecord::WRITE_TAB_FILE;
- writeTableFile(signal, filePointer, fsPtr.i);
- break;
- default:
- jamLine((fsPtr.p->fsState & 0xFFF));
- ndbrequire(false);
- break;
- }//switch
-}//execFSOPENCONF()
-
-/* ---------------------------------------------------------------- */
-// An open file was refused.
-/* ---------------------------------------------------------------- */
-void Dbdict::execFSOPENREF(Signal* signal)
-{
- jamEntry();
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- FsConnectRecordPtr fsPtr;
- c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
- switch (fsPtr.p->fsState) {
- case FsConnectRecord::OPEN_READ_SCHEMA1:
- jam();
- openReadSchemaRef(signal, fsPtr);
- return;
- case FsConnectRecord::OPEN_READ_TAB_FILE1:
- jam();
- openReadTableRef(signal, fsPtr);
- return;
- default:
- break;
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system open failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
- fsRefError(signal,__LINE__,msg);
- }
-}//execFSOPENREF()
-
-/* ---------------------------------------------------------------- */
-// A file was successfully read.
-/* ---------------------------------------------------------------- */
-void Dbdict::execFSREADCONF(Signal* signal)
-{
- jamEntry();
- FsConf * const fsConf = (FsConf *)&signal->theData[0];
- FsConnectRecordPtr fsPtr;
- c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
- switch (fsPtr.p->fsState) {
- case FsConnectRecord::READ_SCHEMA1:
- case FsConnectRecord::READ_SCHEMA2:
- readSchemaConf(signal ,fsPtr);
- break;
- case FsConnectRecord::READ_TAB_FILE1:
- if(ERROR_INSERTED(6007)){
- jam();
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = fsConf->userPointer;
- fsRef->setErrorCode(fsRef->errorCode, NDBD_EXIT_AFS_UNKNOWN);
- fsRef->osErrorCode = ~0; // Indicate local error
- execFSREADREF(signal);
- return;
- }//Testing how DICT behave if read of file 1 fails (Bug#28770)
- case FsConnectRecord::READ_TAB_FILE2:
- jam();
- readTableConf(signal ,fsPtr);
- break;
- default:
- jamLine((fsPtr.p->fsState & 0xFFF));
- ndbrequire(false);
- break;
- }//switch
-}//execFSREADCONF()
-
-/* ---------------------------------------------------------------- */
-// A read file was refused.
-/* ---------------------------------------------------------------- */
-void Dbdict::execFSREADREF(Signal* signal)
-{
- jamEntry();
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- FsConnectRecordPtr fsPtr;
- c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
- switch (fsPtr.p->fsState) {
- case FsConnectRecord::READ_SCHEMA1:
- jam();
- readSchemaRef(signal, fsPtr);
- return;
- case FsConnectRecord::READ_TAB_FILE1:
- jam();
- readTableRef(signal, fsPtr);
- return;
- default:
- break;
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system read failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
- fsRefError(signal,__LINE__,msg);
- }
-}//execFSREADREF()
-
-/* ---------------------------------------------------------------- */
-// A file was successfully written.
-/* ---------------------------------------------------------------- */
-void Dbdict::execFSWRITECONF(Signal* signal)
-{
- FsConf * const fsConf = (FsConf *)&signal->theData[0];
- FsConnectRecordPtr fsPtr;
- jamEntry();
- c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
- switch (fsPtr.p->fsState) {
- case FsConnectRecord::WRITE_TAB_FILE:
- writeTableConf(signal, fsPtr);
- break;
- case FsConnectRecord::WRITE_SCHEMA:
- jam();
- writeSchemaConf(signal, fsPtr);
- break;
- default:
- jamLine((fsPtr.p->fsState & 0xFFF));
- ndbrequire(false);
- break;
- }//switch
-}//execFSWRITECONF()
-
-
-/* ---------------------------------------------------------------- */
-// Routines to handle Read/Write of Table Files
-/* ---------------------------------------------------------------- */
-void
-Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
- SegmentedSectionPtr tabInfoPtr, Callback* callback){
-
- ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
-
- Uint32 pages = WORDS2PAGES(tabInfoPtr.sz);
- c_writeTableRecord.no_of_words = tabInfoPtr.sz;
- c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
- c_writeTableRecord.m_callback = * callback;
-
- c_writeTableRecord.pageId = 0;
- ndbrequire(pages == 1);
-
- PageRecordPtr pageRecPtr;
- c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
- copy(&pageRecPtr.p->word[ZPAGE_HEADER_SIZE], tabInfoPtr);
-
- memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
- pageRecPtr.p->word[ZPOS_CHECKSUM] =
- computeChecksum(&pageRecPtr.p->word[0],
- pages * ZSIZE_OF_PAGES_IN_WORDS);
-
- startWriteTableFile(signal, tableId);
-}
-
-void Dbdict::startWriteTableFile(Signal* signal, Uint32 tableId)
-{
- FsConnectRecordPtr fsPtr;
- c_writeTableRecord.tableId = tableId;
- c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
- fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
- openTableFile(signal, 0, fsPtr.i, tableId, true);
- c_writeTableRecord.noOfTableFilesHandled = 0;
-}//Dbdict::startWriteTableFile()
-
-void Dbdict::openTableFile(Signal* signal,
- Uint32 fileNo,
- Uint32 fsConPtr,
- Uint32 tableId,
- bool writeFlag)
-{
- FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
-
- fsOpenReq->userReference = reference();
- fsOpenReq->userPointer = fsConPtr;
- if (writeFlag) {
- jam();
- fsOpenReq->fileFlags =
- FsOpenReq::OM_WRITEONLY |
- FsOpenReq::OM_TRUNCATE |
- FsOpenReq::OM_CREATE |
- FsOpenReq::OM_SYNC;
- } else {
- jam();
- fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
- }//if
- fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
- FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
- FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_TABLELIST);
- FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
- FsOpenReq::v1_setTable(fsOpenReq->fileNumber, tableId);
- FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
- FsOpenReq::v1_setS(fsOpenReq->fileNumber, 0);
- FsOpenReq::v1_setP(fsOpenReq->fileNumber, 255);
-/* ---------------------------------------------------------------- */
-// File name : D1/DBDICT/T0/S1.TableList
-// D1 means Disk 1 (set by fileNo + 1)
-// T0 means table id = 0
-// S1 means tableVersion 1
-// TableList indicates that this is a file for a table description.
-/* ---------------------------------------------------------------- */
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-}//openTableFile()
-
-void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
-{
- FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
-
- fsRWReq->filePointer = filePtr;
- fsRWReq->userReference = reference();
- fsRWReq->userPointer = fsConPtr;
- fsRWReq->operationFlag = 0; // Initialise before bit changes
- FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
- FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
- FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZBAT_TABLE_FILE;
- fsRWReq->numberOfPages = WORDS2PAGES(c_writeTableRecord.no_of_words);
- fsRWReq->data.arrayOfPages.varIndex = c_writeTableRecord.pageId;
- fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
-}//writeTableFile()
-
-void Dbdict::writeTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_TAB_FILE;
- closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
- return;
-}//Dbdict::writeTableConf()
-
-void Dbdict::closeWriteTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- c_writeTableRecord.noOfTableFilesHandled++;
- if (c_writeTableRecord.noOfTableFilesHandled < 2) {
- jam();
- fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
- openTableFile(signal, 1, fsPtr.i, c_writeTableRecord.tableId, true);
- return;
- }
- ndbrequire(c_writeTableRecord.noOfTableFilesHandled == 2);
- c_fsConnectRecordPool.release(fsPtr);
- WriteTableRecord::TableWriteState state = c_writeTableRecord.tableWriteState;
- c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
- switch (state) {
- case WriteTableRecord::IDLE:
- case WriteTableRecord::WRITE_ADD_TABLE_MASTER :
- case WriteTableRecord::WRITE_ADD_TABLE_SLAVE :
- case WriteTableRecord::WRITE_RESTART_FROM_MASTER :
- case WriteTableRecord::WRITE_RESTART_FROM_OWN :
- ndbrequire(false);
- break;
- case WriteTableRecord::TWR_CALLBACK:
- jam();
- execute(signal, c_writeTableRecord.m_callback, 0);
- return;
- }
- ndbrequire(false);
-}//Dbdict::closeWriteTableConf()
-
-void Dbdict::startReadTableFile(Signal* signal, Uint32 tableId)
-{
- //globalSignalLoggers.log(number(), "startReadTableFile");
- ndbrequire(!c_readTableRecord.inUse);
-
- FsConnectRecordPtr fsPtr;
- c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
- c_readTableRecord.inUse = true;
- c_readTableRecord.tableId = tableId;
- fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE1;
- openTableFile(signal, 0, fsPtr.i, tableId, false);
-}//Dbdict::startReadTableFile()
-
-void Dbdict::openReadTableRef(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
- openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
- return;
-}//Dbdict::openReadTableConf()
-
-void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
-{
- FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
-
- fsRWReq->filePointer = filePtr;
- fsRWReq->userReference = reference();
- fsRWReq->userPointer = fsConPtr;
- fsRWReq->operationFlag = 0; // Initialise before bit changes
- FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
- FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
- FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZBAT_TABLE_FILE;
- fsRWReq->numberOfPages = WORDS2PAGES(c_readTableRecord.no_of_words);
- fsRWReq->data.arrayOfPages.varIndex = c_readTableRecord.pageId;
- fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
-}//readTableFile()
-
-void Dbdict::readTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- /* ---------------------------------------------------------------- */
- // Verify the data read from disk
- /* ---------------------------------------------------------------- */
- bool crashInd;
- if (fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1) {
- jam();
- crashInd = false;
- } else {
- jam();
- crashInd = true;
- }//if
-
- PageRecordPtr tmpPagePtr;
- c_pageRecordArray.getPtr(tmpPagePtr, c_readTableRecord.pageId);
- Uint32 sz =
- WORDS2PAGES(c_readTableRecord.no_of_words)*ZSIZE_OF_PAGES_IN_WORDS;
- Uint32 chk = computeChecksum((const Uint32*)tmpPagePtr.p, sz);
-
- ndbrequire((chk == 0) || !crashInd);
- if(chk != 0){
- jam();
- ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1);
- readTableRef(signal, fsPtr);
- return;
- }//if
-
- fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_TAB_FILE;
- closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
- return;
-}//Dbdict::readTableConf()
-
-void Dbdict::readTableRef(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- /**
- * First close corrupt file
- */
- fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
- closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
- return;
-}//Dbdict::readTableRef()
-
-void Dbdict::closeReadTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- c_fsConnectRecordPool.release(fsPtr);
- c_readTableRecord.inUse = false;
-
- execute(signal, c_readTableRecord.m_callback, 0);
- return;
-}//Dbdict::closeReadTableConf()
-
-/* ---------------------------------------------------------------- */
-// Routines to handle Read/Write of Schema Files
-/* ---------------------------------------------------------------- */
-void
-Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
- SchemaFile::TableEntry* te, Callback* callback,
- bool savetodisk){
- jam();
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
-
- SchemaFile::TableState newState =
- (SchemaFile::TableState)te->m_tableState;
- SchemaFile::TableState oldState =
- (SchemaFile::TableState)tableEntry->m_tableState;
-
- Uint32 newVersion = te->m_tableVersion;
- Uint32 oldVersion = tableEntry->m_tableVersion;
-
- bool ok = false;
- switch(newState){
- case SchemaFile::ADD_STARTED:
- jam();
- ok = true;
- ndbrequire(create_obj_inc_schema_version(oldVersion) == newVersion);
- ndbrequire(oldState == SchemaFile::INIT ||
- oldState == SchemaFile::DROP_TABLE_COMMITTED);
- break;
- case SchemaFile::TABLE_ADD_COMMITTED:
- jam();
- ok = true;
- ndbrequire(newVersion == oldVersion);
- ndbrequire(oldState == SchemaFile::ADD_STARTED ||
- oldState == SchemaFile::DROP_TABLE_STARTED);
- break;
- case SchemaFile::ALTER_TABLE_COMMITTED:
- jam();
- ok = true;
- ndbrequire(alter_obj_inc_schema_version(oldVersion) == newVersion);
- ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED ||
- oldState == SchemaFile::ALTER_TABLE_COMMITTED);
- break;
- case SchemaFile::DROP_TABLE_STARTED:
- jam();
- case SchemaFile::DROP_TABLE_COMMITTED:
- jam();
- ok = true;
- break;
- case SchemaFile::TEMPORARY_TABLE_COMMITTED:
- jam();
- ndbrequire(oldState == SchemaFile::ADD_STARTED ||
- oldState == SchemaFile::TEMPORARY_TABLE_COMMITTED);
- ok = true;
- break;
- case SchemaFile::INIT:
- jam();
- ok = true;
- ndbrequire((oldState == SchemaFile::ADD_STARTED));
- }//if
- ndbrequire(ok);
-
- * tableEntry = * te;
- computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
-
- if (savetodisk)
- {
- 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);
- }
- else
- {
- execute(signal, *callback, 0);
- }
-}
-
-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, c_writeSchemaRecord.newFile);
- c_writeSchemaRecord.noOfSchemaFilesHandled = 0;
-}//Dbdict::startWriteSchemaFile()
-
-void Dbdict::openSchemaFile(Signal* signal,
- Uint32 fileNo,
- Uint32 fsConPtr,
- bool writeFlag,
- bool newFile)
-{
- FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
- fsOpenReq->userReference = reference();
- fsOpenReq->userPointer = fsConPtr;
- if (writeFlag) {
- jam();
- fsOpenReq->fileFlags =
- FsOpenReq::OM_WRITEONLY |
- FsOpenReq::OM_SYNC;
- if (newFile)
- fsOpenReq->fileFlags |=
- FsOpenReq::OM_TRUNCATE |
- FsOpenReq::OM_CREATE;
- } else {
- jam();
- fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
- }//if
- fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
- FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
- FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_SCHEMALOG);
- FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
- FsOpenReq::v1_setTable(fsOpenReq->fileNumber, (Uint32)-1);
- FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
- FsOpenReq::v1_setS(fsOpenReq->fileNumber, (Uint32)-1);
- FsOpenReq::v1_setP(fsOpenReq->fileNumber, 0);
-/* ---------------------------------------------------------------- */
-// File name : D1/DBDICT/P0.SchemaLog
-// D1 means Disk 1 (set by fileNo + 1). Writes to both D1 and D2
-// SchemaLog indicates that this is a file giving a list of current tables.
-/* ---------------------------------------------------------------- */
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-}//openSchemaFile()
-
-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;
- fsRWReq->operationFlag = 0; // Initialise before bit changes
- FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
- FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
- FsReadWriteReq::fsFormatArrayOfPages);
- 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()
-
-void Dbdict::writeSchemaConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_SCHEMA;
- closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
- return;
-}//Dbdict::writeSchemaConf()
-
-void Dbdict::closeFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
-{
- FsCloseReq * const fsCloseReq = (FsCloseReq *)&signal->theData[0];
- fsCloseReq->filePointer = filePtr;
- fsCloseReq->userReference = reference();
- fsCloseReq->userPointer = fsConPtr;
- FsCloseReq::setRemoveFileFlag(fsCloseReq->fileFlag, false);
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
- return;
-}//closeFile()
-
-void Dbdict::closeWriteSchemaConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- c_writeSchemaRecord.noOfSchemaFilesHandled++;
- if (c_writeSchemaRecord.noOfSchemaFilesHandled < 2) {
- jam();
- fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
- openSchemaFile(signal, 1, fsPtr.i, true, c_writeSchemaRecord.newFile);
- return;
- }
- ndbrequire(c_writeSchemaRecord.noOfSchemaFilesHandled == 2);
-
- c_fsConnectRecordPool.release(fsPtr);
-
- c_writeSchemaRecord.inUse = false;
- execute(signal, c_writeSchemaRecord.m_callback, 0);
- return;
-}//Dbdict::closeWriteSchemaConf()
-
-void Dbdict::startReadSchemaFile(Signal* signal)
-{
- //globalSignalLoggers.log(number(), "startReadSchemaFile");
- FsConnectRecordPtr fsPtr;
- c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
- fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA1;
- 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, 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;
- fsRWReq->operationFlag = 0; // Initialise before bit changes
- FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
- FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
- FsReadWriteReq::fsFormatArrayOfPages);
- 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()
-
-void Dbdict::readSchemaConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
-/* ---------------------------------------------------------------- */
-// Verify the data read from disk
-/* ---------------------------------------------------------------- */
- bool crashInd;
- if (fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1) {
- jam();
- crashInd = false;
- } else {
- jam();
- crashInd = true;
- }//if
-
- ReadSchemaRecord & rr = c_readSchemaRecord;
- XSchemaFile * xsf = &c_schemaFile[rr.pageId != 0];
-
- 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 (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;
- }
-
- for (Uint32 n = 0; n < xsf->noOfPages; n++) {
- SchemaFile * sf = &xsf->schemaPage[n];
- bool ok = false;
- const char *reason;
- if (memcmp(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)) != 0)
- { jam(); reason = "magic code"; }
- else if (sf->FileSize == 0)
- { jam(); reason = "file size == 0"; }
- else if (sf->FileSize % NDB_SF_PAGE_SIZE != 0)
- { jam(); reason = "invalid size multiple"; }
- else if (sf->FileSize != sf0->FileSize)
- { jam(); reason = "invalid size"; }
- else if (sf->PageNumber != n)
- { jam(); reason = "invalid page number"; }
- else if (computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS) != 0)
- { jam(); reason = "invalid checksum"; }
- else
- ok = true;
-
- if (!ok)
- {
- char reason_msg[128];
- snprintf(reason_msg, sizeof(reason_msg),
- "schema file corrupt, page %u (%s, "
- "sz=%u sz0=%u pn=%u)",
- n, reason, sf->FileSize, sf0->FileSize, sf->PageNumber);
- if (crashInd)
- progError(__LINE__, NDBD_EXIT_SR_SCHEMAFILE, reason_msg);
- ndbrequireErr(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1,
- NDBD_EXIT_SR_SCHEMAFILE);
- jam();
- infoEvent("primary %s, trying backup", reason_msg);
- readSchemaRef(signal, fsPtr);
- return;
- }
- }
-
- fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_SCHEMA;
- closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
- return;
-}//Dbdict::readSchemaConf()
-
-void Dbdict::readSchemaRef(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- /**
- * First close corrupt file
- */
- fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
- closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
- return;
-}
-
-void Dbdict::closeReadSchemaConf(Signal* signal,
- FsConnectRecordPtr fsPtr)
-{
- c_fsConnectRecordPool.release(fsPtr);
- ReadSchemaRecord::SchemaReadState state = c_readSchemaRecord.schemaReadState;
- c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
-
- switch(state) {
- case ReadSchemaRecord::INITIAL_READ :
- jam();
- {
- // 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 :
- ndbrequire(false);
- break;
-
- }//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 ------------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains initialisation of data at start/restart. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-Dbdict::Dbdict(Block_context& ctx):
- SimulatedBlock(DBDICT, ctx),
- c_attributeRecordHash(c_attributeRecordPool),
- c_file_hash(c_file_pool),
- c_filegroup_hash(c_filegroup_pool),
- c_obj_hash(c_obj_pool),
- c_opCreateTable(c_opRecordPool),
- c_opDropTable(c_opRecordPool),
- c_opCreateIndex(c_opRecordPool),
- 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_schemaOp(c_opRecordPool),
- c_Trans(c_opRecordPool),
- c_opCreateObj(c_schemaOp),
- c_opDropObj(c_schemaOp),
- c_opRecordSequence(0),
- c_dictLockQueue(c_dictLockPool),
- c_dictLockPoll(false)
-{
- BLOCK_CONSTRUCTOR(Dbdict);
-
- // Transit signals
- addRecSignal(GSN_DUMP_STATE_ORD, &Dbdict::execDUMP_STATE_ORD);
- addRecSignal(GSN_GET_TABINFOREQ, &Dbdict::execGET_TABINFOREQ);
- addRecSignal(GSN_GET_TABLEID_REQ, &Dbdict::execGET_TABLEDID_REQ);
- addRecSignal(GSN_GET_TABINFO_CONF, &Dbdict::execGET_TABINFO_CONF);
- addRecSignal(GSN_CONTINUEB, &Dbdict::execCONTINUEB);
-
- addRecSignal(GSN_CREATE_TABLE_REQ, &Dbdict::execCREATE_TABLE_REQ);
- addRecSignal(GSN_CREATE_TAB_REQ, &Dbdict::execCREATE_TAB_REQ);
- addRecSignal(GSN_CREATE_TAB_REF, &Dbdict::execCREATE_TAB_REF);
- addRecSignal(GSN_CREATE_TAB_CONF, &Dbdict::execCREATE_TAB_CONF);
- addRecSignal(GSN_CREATE_FRAGMENTATION_REF, &Dbdict::execCREATE_FRAGMENTATION_REF);
- addRecSignal(GSN_CREATE_FRAGMENTATION_CONF, &Dbdict::execCREATE_FRAGMENTATION_CONF);
- addRecSignal(GSN_DIADDTABCONF, &Dbdict::execDIADDTABCONF);
- addRecSignal(GSN_DIADDTABREF, &Dbdict::execDIADDTABREF);
- addRecSignal(GSN_ADD_FRAGREQ, &Dbdict::execADD_FRAGREQ);
- addRecSignal(GSN_TAB_COMMITCONF, &Dbdict::execTAB_COMMITCONF);
- addRecSignal(GSN_TAB_COMMITREF, &Dbdict::execTAB_COMMITREF);
- addRecSignal(GSN_ALTER_TABLE_REQ, &Dbdict::execALTER_TABLE_REQ);
- addRecSignal(GSN_ALTER_TAB_REQ, &Dbdict::execALTER_TAB_REQ);
- addRecSignal(GSN_ALTER_TAB_REF, &Dbdict::execALTER_TAB_REF);
- addRecSignal(GSN_ALTER_TAB_CONF, &Dbdict::execALTER_TAB_CONF);
-
- // Index signals
- addRecSignal(GSN_CREATE_INDX_REQ, &Dbdict::execCREATE_INDX_REQ);
- addRecSignal(GSN_CREATE_INDX_CONF, &Dbdict::execCREATE_INDX_CONF);
- addRecSignal(GSN_CREATE_INDX_REF, &Dbdict::execCREATE_INDX_REF);
-
- addRecSignal(GSN_ALTER_INDX_REQ, &Dbdict::execALTER_INDX_REQ);
- addRecSignal(GSN_ALTER_INDX_CONF, &Dbdict::execALTER_INDX_CONF);
- addRecSignal(GSN_ALTER_INDX_REF, &Dbdict::execALTER_INDX_REF);
-
- addRecSignal(GSN_CREATE_TABLE_CONF, &Dbdict::execCREATE_TABLE_CONF);
- addRecSignal(GSN_CREATE_TABLE_REF, &Dbdict::execCREATE_TABLE_REF);
-
- addRecSignal(GSN_DROP_INDX_REQ, &Dbdict::execDROP_INDX_REQ);
- addRecSignal(GSN_DROP_INDX_CONF, &Dbdict::execDROP_INDX_CONF);
- addRecSignal(GSN_DROP_INDX_REF, &Dbdict::execDROP_INDX_REF);
-
- addRecSignal(GSN_DROP_TABLE_CONF, &Dbdict::execDROP_TABLE_CONF);
- addRecSignal(GSN_DROP_TABLE_REF, &Dbdict::execDROP_TABLE_REF);
-
- addRecSignal(GSN_BUILDINDXREQ, &Dbdict::execBUILDINDXREQ);
- 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_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);
- addRecSignal(GSN_CREATE_TRIG_REF, &Dbdict::execCREATE_TRIG_REF);
- addRecSignal(GSN_ALTER_TRIG_REQ, &Dbdict::execALTER_TRIG_REQ);
- addRecSignal(GSN_ALTER_TRIG_CONF, &Dbdict::execALTER_TRIG_CONF);
- addRecSignal(GSN_ALTER_TRIG_REF, &Dbdict::execALTER_TRIG_REF);
- addRecSignal(GSN_DROP_TRIG_REQ, &Dbdict::execDROP_TRIG_REQ);
- addRecSignal(GSN_DROP_TRIG_CONF, &Dbdict::execDROP_TRIG_CONF);
- addRecSignal(GSN_DROP_TRIG_REF, &Dbdict::execDROP_TRIG_REF);
-
- // Received signals
- addRecSignal(GSN_HOT_SPAREREP, &Dbdict::execHOT_SPAREREP);
- addRecSignal(GSN_GET_SCHEMA_INFOREQ, &Dbdict::execGET_SCHEMA_INFOREQ);
- addRecSignal(GSN_SCHEMA_INFO, &Dbdict::execSCHEMA_INFO);
- addRecSignal(GSN_SCHEMA_INFOCONF, &Dbdict::execSCHEMA_INFOCONF);
- addRecSignal(GSN_DICTSTARTREQ, &Dbdict::execDICTSTARTREQ);
- addRecSignal(GSN_READ_NODESCONF, &Dbdict::execREAD_NODESCONF);
- addRecSignal(GSN_FSOPENCONF, &Dbdict::execFSOPENCONF);
- addRecSignal(GSN_FSOPENREF, &Dbdict::execFSOPENREF, true);
- addRecSignal(GSN_FSCLOSECONF, &Dbdict::execFSCLOSECONF);
- addRecSignal(GSN_FSWRITECONF, &Dbdict::execFSWRITECONF);
- addRecSignal(GSN_FSREADCONF, &Dbdict::execFSREADCONF);
- addRecSignal(GSN_FSREADREF, &Dbdict::execFSREADREF, true);
- addRecSignal(GSN_LQHFRAGCONF, &Dbdict::execLQHFRAGCONF);
- addRecSignal(GSN_LQHADDATTCONF, &Dbdict::execLQHADDATTCONF);
- addRecSignal(GSN_LQHADDATTREF, &Dbdict::execLQHADDATTREF);
- addRecSignal(GSN_LQHFRAGREF, &Dbdict::execLQHFRAGREF);
- addRecSignal(GSN_NDB_STTOR, &Dbdict::execNDB_STTOR);
- addRecSignal(GSN_READ_CONFIG_REQ, &Dbdict::execREAD_CONFIG_REQ, true);
- addRecSignal(GSN_STTOR, &Dbdict::execSTTOR);
- addRecSignal(GSN_TC_SCHVERCONF, &Dbdict::execTC_SCHVERCONF);
- addRecSignal(GSN_NODE_FAILREP, &Dbdict::execNODE_FAILREP);
- addRecSignal(GSN_INCL_NODEREQ, &Dbdict::execINCL_NODEREQ);
- addRecSignal(GSN_API_FAILREQ, &Dbdict::execAPI_FAILREQ);
-
- addRecSignal(GSN_WAIT_GCP_REF, &Dbdict::execWAIT_GCP_REF);
- addRecSignal(GSN_WAIT_GCP_CONF, &Dbdict::execWAIT_GCP_CONF);
-
- addRecSignal(GSN_LIST_TABLES_REQ, &Dbdict::execLIST_TABLES_REQ);
-
- addRecSignal(GSN_DROP_TABLE_REQ, &Dbdict::execDROP_TABLE_REQ);
-
- addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdict::execPREP_DROP_TAB_REQ);
- addRecSignal(GSN_PREP_DROP_TAB_REF, &Dbdict::execPREP_DROP_TAB_REF);
- addRecSignal(GSN_PREP_DROP_TAB_CONF, &Dbdict::execPREP_DROP_TAB_CONF);
-
- addRecSignal(GSN_DROP_TAB_REQ, &Dbdict::execDROP_TAB_REQ);
- addRecSignal(GSN_DROP_TAB_REF, &Dbdict::execDROP_TAB_REF);
- addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF);
-
- addRecSignal(GSN_CREATE_FILE_REQ, &Dbdict::execCREATE_FILE_REQ);
- addRecSignal(GSN_CREATE_FILEGROUP_REQ, &Dbdict::execCREATE_FILEGROUP_REQ);
-
- addRecSignal(GSN_DROP_FILE_REQ, &Dbdict::execDROP_FILE_REQ);
- addRecSignal(GSN_DROP_FILE_REF, &Dbdict::execDROP_FILE_REF);
- addRecSignal(GSN_DROP_FILE_CONF, &Dbdict::execDROP_FILE_CONF);
-
- addRecSignal(GSN_DROP_FILEGROUP_REQ, &Dbdict::execDROP_FILEGROUP_REQ);
- addRecSignal(GSN_DROP_FILEGROUP_REF, &Dbdict::execDROP_FILEGROUP_REF);
- addRecSignal(GSN_DROP_FILEGROUP_CONF, &Dbdict::execDROP_FILEGROUP_CONF);
-
- addRecSignal(GSN_CREATE_OBJ_REQ, &Dbdict::execCREATE_OBJ_REQ);
- addRecSignal(GSN_CREATE_OBJ_REF, &Dbdict::execCREATE_OBJ_REF);
- addRecSignal(GSN_CREATE_OBJ_CONF, &Dbdict::execCREATE_OBJ_CONF);
- addRecSignal(GSN_DROP_OBJ_REQ, &Dbdict::execDROP_OBJ_REQ);
- addRecSignal(GSN_DROP_OBJ_REF, &Dbdict::execDROP_OBJ_REF);
- addRecSignal(GSN_DROP_OBJ_CONF, &Dbdict::execDROP_OBJ_CONF);
-
- addRecSignal(GSN_CREATE_FILE_REF, &Dbdict::execCREATE_FILE_REF);
- addRecSignal(GSN_CREATE_FILE_CONF, &Dbdict::execCREATE_FILE_CONF);
- addRecSignal(GSN_CREATE_FILEGROUP_REF, &Dbdict::execCREATE_FILEGROUP_REF);
- addRecSignal(GSN_CREATE_FILEGROUP_CONF, &Dbdict::execCREATE_FILEGROUP_CONF);
-
- addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Dbdict::execBACKUP_FRAGMENT_REQ);
-
- addRecSignal(GSN_DICT_COMMIT_REQ, &Dbdict::execDICT_COMMIT_REQ);
- addRecSignal(GSN_DICT_COMMIT_REF, &Dbdict::execDICT_COMMIT_REF);
- addRecSignal(GSN_DICT_COMMIT_CONF, &Dbdict::execDICT_COMMIT_CONF);
-
- addRecSignal(GSN_DICT_ABORT_REQ, &Dbdict::execDICT_ABORT_REQ);
- addRecSignal(GSN_DICT_ABORT_REF, &Dbdict::execDICT_ABORT_REF);
- addRecSignal(GSN_DICT_ABORT_CONF, &Dbdict::execDICT_ABORT_CONF);
-
- addRecSignal(GSN_DICT_LOCK_REQ, &Dbdict::execDICT_LOCK_REQ);
- addRecSignal(GSN_DICT_UNLOCK_ORD, &Dbdict::execDICT_UNLOCK_ORD);
-}//Dbdict::Dbdict()
-
-Dbdict::~Dbdict()
-{
-}//Dbdict::~Dbdict()
-
-BLOCK_FUNCTIONS(Dbdict)
-
-void Dbdict::initCommonData()
-{
-/* ---------------------------------------------------------------- */
-// Initialise all common variables.
-/* ---------------------------------------------------------------- */
- initRetrieveRecord(0, 0, 0);
- initSchemaRecord();
- initRestartRecord();
- initSendSchemaRecord();
- initReadTableRecord();
- initWriteTableRecord();
- initReadSchemaRecord();
- initWriteSchemaRecord();
-
- c_masterNodeId = ZNIL;
- c_numberNode = 0;
- c_noNodesFailed = 0;
- c_failureNr = 0;
- c_blockState = BS_IDLE;
- c_packTable.m_state = PackTable::PTS_IDLE;
- c_startPhase = 0;
- c_restartType = 255; //Ensure not used restartType
- c_tabinfoReceived = 0;
- c_initialStart = false;
- c_systemRestart = false;
- c_initialNodeRestart = false;
- c_nodeRestart = false;
-}//Dbdict::initCommonData()
-
-void Dbdict::initRecords()
-{
- initNodeRecords();
- initPageRecords();
- initTableRecords();
- initTriggerRecords();
-}//Dbdict::initRecords()
-
-void Dbdict::initSendSchemaRecord()
-{
- c_sendSchemaRecord.noOfWords = (Uint32)-1;
- c_sendSchemaRecord.pageId = RNIL;
- c_sendSchemaRecord.noOfWordsCurrentlySent = 0;
- c_sendSchemaRecord.noOfSignalsSentSinceDelay = 0;
- c_sendSchemaRecord.inUse = false;
- //c_sendSchemaRecord.sendSchemaState = SendSchemaRecord::IDLE;
-}//initSendSchemaRecord()
-
-void Dbdict::initReadTableRecord()
-{
- c_readTableRecord.no_of_words= 0;
- c_readTableRecord.pageId = RNIL;
- c_readTableRecord.tableId = ZNIL;
- c_readTableRecord.inUse = false;
-}//initReadTableRecord()
-
-void Dbdict::initWriteTableRecord()
-{
- c_writeTableRecord.no_of_words= 0;
- c_writeTableRecord.pageId = RNIL;
- c_writeTableRecord.noOfTableFilesHandled = 3;
- c_writeTableRecord.tableId = ZNIL;
- c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
-}//initWriteTableRecord()
-
-void Dbdict::initReadSchemaRecord()
-{
- c_readSchemaRecord.pageId = RNIL;
- c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
-}//initReadSchemaRecord()
-
-void Dbdict::initWriteSchemaRecord()
-{
- c_writeSchemaRecord.inUse = false;
- c_writeSchemaRecord.pageId = RNIL;
- c_writeSchemaRecord.noOfSchemaFilesHandled = 3;
-}//initWriteSchemaRecord()
-
-void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode)
-{
- c_retrieveRecord.busyState = false;
- c_retrieveRecord.blockRef = 0;
- c_retrieveRecord.m_senderData = RNIL;
- c_retrieveRecord.tableId = RNIL;
- c_retrieveRecord.currentSent = 0;
- c_retrieveRecord.retrievedNoOfPages = 0;
- c_retrieveRecord.retrievedNoOfWords = 0;
- c_retrieveRecord.m_useLongSig = false;
-}//initRetrieveRecord()
-
-void Dbdict::initSchemaRecord()
-{
- c_schemaRecord.schemaPage = RNIL;
- c_schemaRecord.oldSchemaPage = RNIL;
-}//Dbdict::initSchemaRecord()
-
-void Dbdict::initRestartRecord()
-{
- c_restartRecord.gciToRestart = 0;
- c_restartRecord.activeTable = ZNIL;
- c_restartRecord.m_pass = 0;
-}//Dbdict::initRestartRecord()
-
-void Dbdict::initNodeRecords()
-{
- jam();
- for (unsigned i = 1; i < MAX_NODES; i++) {
- NodeRecordPtr nodePtr;
- c_nodes.getPtr(nodePtr, i);
- nodePtr.p->hotSpare = false;
- nodePtr.p->nodeState = NodeRecord::API_NODE;
- }//for
-}//Dbdict::initNodeRecords()
-
-void Dbdict::initPageRecords()
-{
- 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()
-{
- TableRecordPtr tablePtr;
- while (1) {
- jam();
- refresh_watch_dog();
- c_tableRecordPool.seize(tablePtr);
- if (tablePtr.i == RNIL) {
- jam();
- break;
- }//if
- initialiseTableRecord(tablePtr);
- }//while
-}//Dbdict::initTableRecords()
-
-void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
-{
- new (tablePtr.p) TableRecord();
- tablePtr.p->activePage = RNIL;
- tablePtr.p->filePtr[0] = RNIL;
- tablePtr.p->filePtr[1] = RNIL;
- tablePtr.p->firstPage = RNIL;
- tablePtr.p->tableId = tablePtr.i;
- tablePtr.p->tableVersion = (Uint32)-1;
- tablePtr.p->tabState = TableRecord::NOT_DEFINED;
- tablePtr.p->tabReturnState = TableRecord::TRS_IDLE;
- tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
- tablePtr.p->gciTableCreated = 0;
- tablePtr.p->noOfAttributes = ZNIL;
- tablePtr.p->noOfNullAttr = 0;
- tablePtr.p->fragmentCount = 0;
- /*
- tablePtr.p->lh3PageIndexBits = 0;
- tablePtr.p->lh3DistrBits = 0;
- tablePtr.p->lh3PageBits = 6;
- */
- tablePtr.p->kValue = 6;
- tablePtr.p->localKeyLen = 1;
- tablePtr.p->maxLoadFactor = 80;
- tablePtr.p->minLoadFactor = 70;
- tablePtr.p->noOfPrimkey = 1;
- tablePtr.p->tupKeyLength = 1;
- tablePtr.p->maxRowsLow = 0;
- tablePtr.p->maxRowsHigh = 0;
- tablePtr.p->defaultNoPartFlag = true;
- tablePtr.p->linearHashFlag = true;
- tablePtr.p->m_bits = 0;
- tablePtr.p->minRowsLow = 0;
- tablePtr.p->minRowsHigh = 0;
- tablePtr.p->singleUserMode = 0;
- tablePtr.p->tableType = DictTabInfo::UserTable;
- tablePtr.p->primaryTableId = RNIL;
- // volatile elements
- tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
- tablePtr.p->insertTriggerId = RNIL;
- tablePtr.p->updateTriggerId = RNIL;
- tablePtr.p->deleteTriggerId = RNIL;
- tablePtr.p->customTriggerId = RNIL;
- tablePtr.p->buildTriggerId = RNIL;
- tablePtr.p->indexLocal = 0;
-}//Dbdict::initialiseTableRecord()
-
-void Dbdict::initTriggerRecords()
-{
- TriggerRecordPtr triggerPtr;
- while (1) {
- jam();
- refresh_watch_dog();
- c_triggerRecordPool.seize(triggerPtr);
- if (triggerPtr.i == RNIL) {
- jam();
- break;
- }//if
- initialiseTriggerRecord(triggerPtr);
- }//while
-}
-
-void Dbdict::initialiseTriggerRecord(TriggerRecordPtr triggerPtr)
-{
- new (triggerPtr.p) TriggerRecord();
- triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
- triggerPtr.p->triggerLocal = 0;
- triggerPtr.p->triggerId = RNIL;
- triggerPtr.p->tableId = RNIL;
- triggerPtr.p->triggerType = (TriggerType::Value)~0;
- triggerPtr.p->triggerActionTime = (TriggerActionTime::Value)~0;
- triggerPtr.p->triggerEvent = (TriggerEvent::Value)~0;
- triggerPtr.p->monitorReplicas = false;
- triggerPtr.p->monitorAllAttributes = false;
- triggerPtr.p->attributeMask.clear();
- triggerPtr.p->indexId = RNIL;
-}
-
-Uint32 Dbdict::getFsConnRecord()
-{
- FsConnectRecordPtr fsPtr;
- c_fsConnectRecordPool.seize(fsPtr);
- ndbrequire(fsPtr.i != RNIL);
- fsPtr.p->filePtr = (Uint32)-1;
- fsPtr.p->ownerPtr = RNIL;
- fsPtr.p->fsState = FsConnectRecord::IDLE;
- return fsPtr.i;
-}//Dbdict::getFsConnRecord()
-
-/*
- * Search schemafile for free entry. Its index is used as 'logical id'
- * of new disk-stored object.
- */
-Uint32 Dbdict::getFreeObjId(Uint32 minId)
-{
- const XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- Uint32 noOfPages = xsf->noOfPages;
- Uint32 n, i;
- for (n = 0; n < noOfPages; n++) {
- jam();
- const SchemaFile * sf = &xsf->schemaPage[n];
- for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
- const SchemaFile::TableEntry& te = sf->TableEntries[i];
- if (te.m_tableState == (Uint32)SchemaFile::INIT ||
- te.m_tableState == (Uint32)SchemaFile::DROP_TABLE_COMMITTED) {
- // minId is obsolete anyway
- if (minId <= n * NDB_SF_PAGE_ENTRIES + i)
- return n * NDB_SF_PAGE_ENTRIES + i;
- }
- }
- }
- return RNIL;
-}
-
-Uint32 Dbdict::getFreeTableRecord(Uint32 primaryTableId)
-{
- Uint32 minId = (primaryTableId == RNIL ? 0 : primaryTableId + 1);
- Uint32 i = getFreeObjId(minId);
- if (i == RNIL) {
- jam();
- return RNIL;
- }
- if (i >= c_tableRecordPool.getSize()) {
- jam();
- return RNIL;
- }
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, i);
- ndbrequire(tablePtr.p->tabState == TableRecord::NOT_DEFINED);
- initialiseTableRecord(tablePtr);
- tablePtr.p->tabState = TableRecord::DEFINING;
- return i;
-}
-
-Uint32 Dbdict::getFreeTriggerRecord()
-{
- const Uint32 size = c_triggerRecordPool.getSize();
- TriggerRecordPtr triggerPtr;
- for (triggerPtr.i = 0; triggerPtr.i < size; triggerPtr.i++) {
- jam();
- c_triggerRecordPool.getPtr(triggerPtr);
- if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED) {
- jam();
- initialiseTriggerRecord(triggerPtr);
- return triggerPtr.i;
- }
- }
- return RNIL;
-}
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: START/RESTART HANDLING ------------------------ */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains the code that is common for all */
-/* start/restart types. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-/* ---------------------------------------------------------------- */
-// This is sent as the first signal during start/restart.
-/* ---------------------------------------------------------------- */
-void Dbdict::execSTTOR(Signal* signal)
-{
- jamEntry();
- c_startPhase = signal->theData[1];
- switch (c_startPhase) {
- case 1:
- break;
- case 3:
- c_restartType = signal->theData[7]; /* valid if 3 */
- ndbrequire(c_restartType == NodeState::ST_INITIAL_START ||
- c_restartType == NodeState::ST_SYSTEM_RESTART ||
- c_restartType == NodeState::ST_INITIAL_NODE_RESTART ||
- c_restartType == NodeState::ST_NODE_RESTART);
- break;
- }
- sendSTTORRY(signal);
-}//execSTTOR()
-
-void Dbdict::sendSTTORRY(Signal* signal)
-{
- signal->theData[0] = 0; /* garbage SIGNAL KEY */
- signal->theData[1] = 0; /* garbage SIGNAL VERSION NUMBER */
- signal->theData[2] = 0; /* garbage */
- signal->theData[3] = 1; /* first wanted start phase */
- signal->theData[4] = 3; /* get type of start */
- signal->theData[5] = ZNOMOREPHASES;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
-}
-
-/* ---------------------------------------------------------------- */
-// We receive information about sizes of records.
-/* ---------------------------------------------------------------- */
-void Dbdict::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Uint32 attributesize, tablerecSize;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
- &c_maxNoOfTriggers));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_ATTRIBUTE,&attributesize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &tablerecSize));
-
- c_attributeRecordPool.setSize(attributesize);
- c_attributeRecordHash.setSize(64);
- 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);
- g_key_descriptor_pool.setSize(tablerecSize);
- c_triggerRecordPool.setSize(c_maxNoOfTriggers);
-
- c_obj_pool.setSize(tablerecSize+c_maxNoOfTriggers);
- c_obj_hash.setSize((tablerecSize+c_maxNoOfTriggers+1)/2);
-
- Pool_context pc;
- pc.m_block = this;
-
- c_file_hash.setSize(16);
- c_filegroup_hash.setSize(16);
-
- c_file_pool.init(RT_DBDICT_FILE, pc);
- c_filegroup_pool.init(RT_DBDICT_FILEGROUP, pc);
-
- c_opRecordPool.setSize(256); // XXX need config params
- c_opCreateTable.setSize(8);
- c_opDropTable.setSize(8);
- c_opCreateIndex.setSize(8);
- c_opCreateEvent.setSize(2);
- c_opSubEvent.setSize(2);
- c_opDropEvent.setSize(2);
- c_opSignalUtil.setSize(8);
- c_opDropIndex.setSize(8);
- c_opAlterIndex.setSize(8);
- c_opBuildIndex.setSize(8);
- c_opCreateTrigger.setSize(8);
- 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;
-
- c_schemaOp.setSize(8);
- //c_opDropObj.setSize(8);
- c_Trans.setSize(8);
-
- Uint32 rps = 0;
- rps += tablerecSize * (MAX_TAB_NAME_SIZE + MAX_FRM_DATA_SIZE);
- rps += attributesize * (MAX_ATTR_NAME_SIZE + MAX_ATTR_DEFAULT_VALUE_SIZE);
- rps += c_maxNoOfTriggers * MAX_TAB_NAME_SIZE;
- rps += (10 + 10) * MAX_TAB_NAME_SIZE;
-
- Uint32 sm = 5;
- ndb_mgm_get_int_parameter(p, CFG_DB_STRING_MEMORY, &sm);
- if (sm == 0)
- sm = 5;
-
- Uint32 sb = 0;
- if (sm < 100)
- {
- sb = (rps * sm) / 100;
- }
- else
- {
- sb = sm;
- }
-
- c_rope_pool.setSize(sb/28 + 100);
-
- // Initialize BAT for interface to file system
- NewVARIABLE* bat = allocateBat(2);
- 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
- bat[1].bits.v = 5; // 32 bits per element
-
- initCommonData();
- initRecords();
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-
- {
- Ptr<DictObject> ptr;
- SLList<DictObject> objs(c_obj_pool);
- while(objs.seize(ptr))
- new (ptr.p) DictObject();
- objs.release();
- }
-}//execSIZEALT_REP()
-
-/* ---------------------------------------------------------------- */
-// Start phase signals sent by CNTR. We reply with NDB_STTORRY when
-// we completed this phase.
-/* ---------------------------------------------------------------- */
-void Dbdict::execNDB_STTOR(Signal* signal)
-{
- jamEntry();
- c_startPhase = signal->theData[2];
- const Uint32 restartType = signal->theData[3];
- if (restartType == NodeState::ST_INITIAL_START) {
- jam();
- c_initialStart = true;
- } else if (restartType == NodeState::ST_SYSTEM_RESTART) {
- jam();
- c_systemRestart = true;
- } else if (restartType == NodeState::ST_INITIAL_NODE_RESTART) {
- jam();
- c_initialNodeRestart = true;
- } else if (restartType == NodeState::ST_NODE_RESTART) {
- jam();
- c_nodeRestart = true;
- } else {
- ndbrequire(false);
- }//if
- switch (c_startPhase) {
- case 1:
- jam();
- initSchemaFile(signal);
- break;
- case 3:
- jam();
- signal->theData[0] = reference();
- sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
- break;
- case 6:
- jam();
- c_initialStart = false;
- c_systemRestart = false;
- c_initialNodeRestart = false;
- c_nodeRestart = false;
- sendNDB_STTORRY(signal);
- break;
- case 7:
- // uses c_restartType
- if(restartType == NodeState::ST_SYSTEM_RESTART &&
- c_masterNodeId == getOwnNodeId()){
- rebuildIndexes(signal, 0);
- return;
- }
- sendNDB_STTORRY(signal);
- break;
- default:
- jam();
- sendNDB_STTORRY(signal);
- break;
- }//switch
-}//execNDB_STTOR()
-
-void Dbdict::sendNDB_STTORRY(Signal* signal)
-{
- signal->theData[0] = reference();
- sendSignal(NDBCNTR_REF, GSN_NDB_STTORRY, signal, 1, JBB);
- return;
-}//sendNDB_STTORRY()
-
-/* ---------------------------------------------------------------- */
-// We receive the information about which nodes that are up and down.
-/* ---------------------------------------------------------------- */
-void Dbdict::execREAD_NODESCONF(Signal* signal)
-{
- jamEntry();
-
- ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
- c_numberNode = readNodes->noOfNodes;
- c_masterNodeId = readNodes->masterNodeId;
-
- c_noNodesFailed = 0;
- c_aliveNodes.clear();
- for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
- jam();
- NodeRecordPtr nodePtr;
- c_nodes.getPtr(nodePtr, i);
-
- if (NodeBitmask::get(readNodes->allNodes, i)) {
- jam();
- nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
- if (NodeBitmask::get(readNodes->inactiveNodes, i)) {
- jam();
- /**-------------------------------------------------------------------
- *
- * THIS NODE IS DEFINED IN THE CLUSTER BUT IS NOT ALIVE CURRENTLY.
- * WE ADD THE NODE TO THE SET OF FAILED NODES AND ALSO SET THE
- * BLOCKSTATE TO BUSY TO AVOID ADDING TABLES WHILE NOT ALL NODES ARE
- * ALIVE.
- *------------------------------------------------------------------*/
- nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
- c_noNodesFailed++;
- } else {
- c_aliveNodes.set(i);
- }
- }//if
- }//for
- sendNDB_STTORRY(signal);
-}//execREAD_NODESCONF()
-
-/* ---------------------------------------------------------------- */
-// HOT_SPAREREP informs DBDICT about which nodes that have become
-// hot spare nodes.
-/* ---------------------------------------------------------------- */
-void Dbdict::execHOT_SPAREREP(Signal* signal)
-{
- Uint32 hotSpareNodes = 0;
- jamEntry();
- HotSpareRep * const hotSpare = (HotSpareRep*)&signal->theData[0];
- for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
- if (NodeBitmask::get(hotSpare->theHotSpareNodes, i)) {
- NodeRecordPtr nodePtr;
- c_nodes.getPtr(nodePtr, i);
- nodePtr.p->hotSpare = true;
- hotSpareNodes++;
- }//if
- }//for
- ndbrequire(hotSpareNodes == hotSpare->noHotSpareNodes);
- c_noHotSpareNodes = hotSpareNodes;
- return;
-}//execHOT_SPAREREP()
-
-void Dbdict::initSchemaFile(Signal* signal)
-{
- 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);
-
- startWriteSchemaFile(signal);
- } else if (c_systemRestart || c_nodeRestart) {
- jam();
- ndbrequire(c_readSchemaRecord.schemaReadState == ReadSchemaRecord::IDLE);
- c_readSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
- c_readSchemaRecord.firstPage = 0;
- c_readSchemaRecord.noOfPages = 1;
- c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ_HEAD;
- startReadSchemaFile(signal);
- } else {
- ndbrequire(false);
- }//if
-}//Dbdict::initSchemaFile()
-
-void
-Dbdict::initSchemaFile_conf(Signal* signal, Uint32 callbackData, Uint32 rv){
- jam();
- sendNDB_STTORRY(signal);
-}
-
-void
-Dbdict::activateIndexes(Signal* signal, Uint32 i)
-{
- AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
- TableRecordPtr tablePtr;
- for (; i < c_tableRecordPool.getSize(); i++) {
- tablePtr.i = i;
- c_tableRecordPool.getPtr(tablePtr);
- if (tablePtr.p->tabState != TableRecord::DEFINED)
- continue;
- if (! tablePtr.p->isIndex())
- continue;
- jam();
- req->setUserRef(reference());
- req->setConnectionPtr(i);
- req->setTableId(tablePtr.p->primaryTableId);
- req->setIndexId(tablePtr.i);
- req->setIndexVersion(tablePtr.p->tableVersion);
- req->setOnline(true);
- if (c_restartType == NodeState::ST_SYSTEM_RESTART) {
- if (c_masterNodeId != getOwnNodeId())
- continue;
- // from file index state is not defined currently
- req->setRequestType(AlterIndxReq::RT_SYSTEMRESTART);
- req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
- }
- else if (
- c_restartType == NodeState::ST_NODE_RESTART ||
- c_restartType == NodeState::ST_INITIAL_NODE_RESTART) {
- // from master index must be online
- if (tablePtr.p->indexState != TableRecord::IS_ONLINE)
- continue;
- req->setRequestType(AlterIndxReq::RT_NODERESTART);
- // activate locally, rebuild not needed
- req->addRequestFlag((Uint32)RequestFlag::RF_LOCAL);
- req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
- } else {
- ndbrequire(false);
- }
- sendSignal(reference(), GSN_ALTER_INDX_REQ,
- signal, AlterIndxReq::SignalLength, JBB);
- return;
- }
- signal->theData[0] = reference();
- sendSignal(c_restartRecord.returnBlockRef, GSN_DICTSTARTCONF,
- signal, 1, JBB);
-}
-
-void
-Dbdict::rebuildIndexes(Signal* signal, Uint32 i){
- BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
-
- TableRecordPtr indexPtr;
- for (; i < c_tableRecordPool.getSize(); i++) {
- indexPtr.i = i;
- c_tableRecordPool.getPtr(indexPtr);
- if (indexPtr.p->tabState != TableRecord::DEFINED)
- continue;
- if (! indexPtr.p->isIndex())
- continue;
-
- jam();
-
- req->setUserRef(reference());
- req->setConnectionPtr(i);
- req->setRequestType(BuildIndxReq::RT_SYSTEMRESTART);
- req->setBuildId(0); // not used
- req->setBuildKey(0); // not used
- req->setIndexType(indexPtr.p->tableType);
- req->setIndexId(indexPtr.i);
- req->setTableId(indexPtr.p->primaryTableId);
- req->setParallelism(16);
-
- // from file index state is not defined currently
- if (indexPtr.p->m_bits & TableRecord::TR_Logged) {
- // rebuild not needed
- req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
- }
-
- // send
- sendSignal(reference(), GSN_BUILDINDXREQ,
- signal, BuildIndxReq::SignalLength, JBB);
- return;
- }
- sendNDB_STTORRY(signal);
-}
-
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: SYSTEM RESTART MODULE ------------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains code specific for system restart */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-/* ---------------------------------------------------------------- */
-// DIH asks DICT to read in table data from disk during system
-// restart. DIH also asks DICT to send information about which
-// tables that should be started as part of this system restart.
-// DICT will also activate the tables in TC as part of this process.
-/* ---------------------------------------------------------------- */
-void Dbdict::execDICTSTARTREQ(Signal* signal)
-{
- jamEntry();
- c_restartRecord.gciToRestart = signal->theData[0];
- c_restartRecord.returnBlockRef = signal->theData[1];
- if (c_nodeRestart || c_initialNodeRestart) {
- jam();
-
- CRASH_INSERTION(6000);
-
- BlockReference dictRef = calcDictBlockRef(c_masterNodeId);
- signal->theData[0] = getOwnNodeId();
- sendSignal(dictRef, GSN_GET_SCHEMA_INFOREQ, signal, 1, JBB);
- return;
- }
- ndbrequire(c_systemRestart);
- ndbrequire(c_masterNodeId == getOwnNodeId());
-
- c_schemaRecord.m_callback.m_callbackData = 0;
- c_schemaRecord.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete);
-
- c_restartRecord.m_pass = 0;
- c_restartRecord.activeTable = 0;
- c_schemaRecord.schemaPage = c_schemaRecord.oldSchemaPage; // ugly
- checkSchemaStatus(signal);
-}//execDICTSTARTREQ()
-
-void
-Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
-
- c_schemaRecord.schemaPage = 0; // ugly
- XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
- ndbrequire(oldxsf->noOfPages != 0);
-
- LinearSectionPtr ptr[3];
- 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);
-
- rg.m_nodes.clear(getOwnNodeId());
- Callback c = { 0, 0 };
- sendFragmentedSignal(rg,
- GSN_SCHEMA_INFO,
- signal,
- 1, //SchemaInfo::SignalLength,
- JBB,
- ptr,
- 1,
- c);
-
- 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);
-}
-
-void
-Dbdict::execGET_SCHEMA_INFOREQ(Signal* signal){
-
- const Uint32 ref = signal->getSendersBlockRef();
- //const Uint32 senderData = signal->theData[0];
-
- ndbrequire(c_sendSchemaRecord.inUse == false);
- c_sendSchemaRecord.inUse = true;
-
- LinearSectionPtr ptr[3];
-
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- ndbrequire(xsf->noOfPages != 0);
-
- 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,
- GSN_SCHEMA_INFO,
- signal,
- 1, //GetSchemaInfoConf::SignalLength,
- JBB,
- ptr,
- 1,
- c);
-}//Dbdict::execGET_SCHEMA_INFOREQ()
-
-void
-Dbdict::sendSchemaComplete(Signal * signal,
- Uint32 callbackData,
- Uint32 returnCode){
- ndbrequire(c_sendSchemaRecord.inUse == true);
- c_sendSchemaRecord.inUse = false;
-
-}
-
-
-/* ---------------------------------------------------------------- */
-// We receive the schema info from master as part of all restarts
-// except the initial start where no tables exists.
-/* ---------------------------------------------------------------- */
-void Dbdict::execSCHEMA_INFO(Signal* signal)
-{
- jamEntry();
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- if(getNodeState().getNodeRestartInProgress()){
- CRASH_INSERTION(6001);
- }
-
- SegmentedSectionPtr schemaDataPtr;
- signal->getSection(schemaDataPtr, 0);
-
- 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(xsf);
-
- XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
- resizeSchemaFile(xsf, oldxsf->noOfPages);
-
- ndbrequire(signal->getSendersBlockRef() != reference());
-
- /* ---------------------------------------------------------------- */
- // Synchronise our view on data with other nodes in the cluster.
- // This is an important part of restart handling where we will handle
- // cases where the table have been added but only partially, where
- // tables have been deleted but not completed the deletion yet and
- // other scenarios needing synchronisation.
- /* ---------------------------------------------------------------- */
- c_schemaRecord.m_callback.m_callbackData = 0;
- c_schemaRecord.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restart_checkSchemaStatusComplete);
-
- c_restartRecord.m_pass= 0;
- c_restartRecord.activeTable = 0;
- checkSchemaStatus(signal);
-}//execSCHEMA_INFO()
-
-void
-Dbdict::restart_checkSchemaStatusComplete(Signal * signal,
- Uint32 callbackData,
- Uint32 returnCode){
-
- 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);
-
- for(Uint32 i = 0; i<xsf->noOfPages; i++)
- computeChecksum(xsf, i);
-
- startWriteSchemaFile(signal);
-}
-
-void
-Dbdict::restart_writeSchemaConf(Signal * signal,
- Uint32 callbackData,
- Uint32 returnCode){
-
- if(c_systemRestart){
- jam();
- signal->theData[0] = getOwnNodeId();
- sendSignal(calcDictBlockRef(c_masterNodeId), GSN_SCHEMA_INFOCONF,
- signal, 1, JBB);
- return;
- }
-
- ndbrequire(c_nodeRestart || c_initialNodeRestart);
- c_blockState = BS_IDLE;
- activateIndexes(signal, 0);
- return;
-}
-
-void Dbdict::execSCHEMA_INFOCONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 0);
-
-/* ---------------------------------------------------------------- */
-// This signal is received in the master as part of system restart
-// from all nodes (including the master) after they have synchronised
-// their data with the master node's schema information.
-/* ---------------------------------------------------------------- */
- const Uint32 nodeId = signal->theData[0];
- c_sendSchemaRecord.m_SCHEMAINFO_Counter.clearWaitingFor(nodeId);
-
- if (!c_sendSchemaRecord.m_SCHEMAINFO_Counter.done()){
- jam();
- return;
- }//if
- activateIndexes(signal, 0);
-}//execSCHEMA_INFOCONF()
-
-static bool
-checkSchemaStatus(Uint32 tableType, Uint32 pass)
-{
- switch(tableType){
- case DictTabInfo::UndefTableType:
- return true;
- case DictTabInfo::HashIndexTrigger:
- case DictTabInfo::SubscriptionTrigger:
- case DictTabInfo::ReadOnlyConstraint:
- case DictTabInfo::IndexTrigger:
- return false;
- case DictTabInfo::LogfileGroup:
- return pass == 0 || pass == 9 || pass == 10;
- case DictTabInfo::Tablespace:
- return pass == 1 || pass == 8 || pass == 11;
- case DictTabInfo::Datafile:
- case DictTabInfo::Undofile:
- return pass == 2 || pass == 7 || pass == 12;
- case DictTabInfo::SystemTable:
- case DictTabInfo::UserTable:
- return /* pass == 3 || pass == 6 || */ pass == 13;
- case DictTabInfo::UniqueHashIndex:
- case DictTabInfo::HashIndex:
- case DictTabInfo::UniqueOrderedIndex:
- case DictTabInfo::OrderedIndex:
- return /* pass == 4 || pass == 5 || */ pass == 14;
- }
-
- return false;
-}
-
-static const Uint32 CREATE_OLD_PASS = 4;
-static const Uint32 DROP_OLD_PASS = 9;
-static const Uint32 CREATE_NEW_PASS = 14;
-static const Uint32 LAST_PASS = 14;
-
-NdbOut&
-operator<<(NdbOut& out, const SchemaFile::TableEntry entry)
-{
- out << "[";
- out << " state: " << entry.m_tableState;
- out << " version: " << hex << entry.m_tableVersion << dec;
- out << " type: " << entry.m_tableType;
- out << " words: " << entry.m_info_words;
- out << " gcp: " << entry.m_gcp;
- out << " ]";
- return out;
-}
-
-/**
- * Pass 0 Create old LogfileGroup
- * Pass 1 Create old Tablespace
- * Pass 2 Create old Datafile/Undofile
- * Pass 3 Create old Table // NOT DONE DUE TO DIH
- * Pass 4 Create old Index // NOT DONE DUE TO DIH
-
- * Pass 5 Drop old Index // NOT DONE DUE TO DIH
- * Pass 6 Drop old Table // NOT DONE DUE TO DIH
- * Pass 7 Drop old Datafile/Undofile
- * Pass 8 Drop old Tablespace
- * Pass 9 Drop old Logfilegroup
-
- * Pass 10 Create new LogfileGroup
- * Pass 11 Create new Tablespace
- * Pass 12 Create new Datafile/Undofile
- * Pass 13 Create new Table
- * Pass 14 Create new Index
- */
-
-void Dbdict::checkSchemaStatus(Signal* signal)
-{
- 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 < noOfEntries;
- c_restartRecord.activeTable++) {
- jam();
-
- Uint32 tableId = c_restartRecord.activeTable;
- SchemaFile::TableEntry *newEntry = getTableEntry(newxsf, tableId);
- SchemaFile::TableEntry *oldEntry = getTableEntry(oldxsf, tableId);
- SchemaFile::TableState newSchemaState =
- (SchemaFile::TableState)newEntry->m_tableState;
- SchemaFile::TableState oldSchemaState =
- (SchemaFile::TableState)oldEntry->m_tableState;
-
- if (c_restartRecord.activeTable >= c_tableRecordPool.getSize()) {
- jam();
- ndbrequire(newSchemaState == SchemaFile::INIT);
- ndbrequire(oldSchemaState == SchemaFile::INIT);
- continue;
- }//if
-
-//#define PRINT_SCHEMA_RESTART
-#ifdef PRINT_SCHEMA_RESTART
- char buf[100];
- snprintf(buf, sizeof(buf), "checkSchemaStatus: pass: %d table: %d",
- c_restartRecord.m_pass, tableId);
-#endif
-
- if (c_restartRecord.m_pass <= CREATE_OLD_PASS)
- {
- if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
- continue;
-
- switch(oldSchemaState){
- case SchemaFile::INIT: jam();
- case SchemaFile::DROP_TABLE_COMMITTED: jam();
- case SchemaFile::ADD_STARTED: jam();
- case SchemaFile::DROP_TABLE_STARTED: jam();
- case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
- continue;
- case SchemaFile::TABLE_ADD_COMMITTED: jam();
- case SchemaFile::ALTER_TABLE_COMMITTED: jam();
- jam();
-#ifdef PRINT_SCHEMA_RESTART
- ndbout_c("%s -> restartCreateTab", buf);
- ndbout << *newEntry << " " << *oldEntry << endl;
-#endif
- restartCreateTab(signal, tableId, oldEntry, oldEntry, true);
- return;
- }
- }
-
- if (c_restartRecord.m_pass <= DROP_OLD_PASS)
- {
- if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
- continue;
-
- switch(oldSchemaState){
- case SchemaFile::INIT: jam();
- case SchemaFile::DROP_TABLE_COMMITTED: jam();
- case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
- continue;
- case SchemaFile::ADD_STARTED: jam();
- case SchemaFile::DROP_TABLE_STARTED: jam();
-#ifdef PRINT_SCHEMA_RESTART
- ndbout_c("%s -> restartDropTab", buf);
- ndbout << *newEntry << " " << *oldEntry << endl;
-#endif
- restartDropTab(signal, tableId, oldEntry, newEntry);
- return;
- case SchemaFile::TABLE_ADD_COMMITTED: jam();
- case SchemaFile::ALTER_TABLE_COMMITTED: jam();
- if (! (* oldEntry == * newEntry))
- {
-#ifdef PRINT_SCHEMA_RESTART
- ndbout_c("%s -> restartDropTab", buf);
- ndbout << *newEntry << " " << *oldEntry << endl;
-#endif
- restartDropTab(signal, tableId, oldEntry, newEntry);
- return;
- }
- continue;
- }
- }
-
- if (c_restartRecord.m_pass <= CREATE_NEW_PASS)
- {
- if (!::checkSchemaStatus(newEntry->m_tableType, c_restartRecord.m_pass))
- continue;
-
- switch(newSchemaState){
- case SchemaFile::INIT: jam();
- case SchemaFile::DROP_TABLE_COMMITTED: jam();
- case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
- * oldEntry = * newEntry;
- continue;
- case SchemaFile::ADD_STARTED: jam();
- case SchemaFile::DROP_TABLE_STARTED: jam();
- ndbrequire(DictTabInfo::isTable(newEntry->m_tableType) ||
- DictTabInfo::isIndex(newEntry->m_tableType));
- newEntry->m_tableState = SchemaFile::INIT;
- continue;
- case SchemaFile::TABLE_ADD_COMMITTED: jam();
- case SchemaFile::ALTER_TABLE_COMMITTED: jam();
- if (DictTabInfo::isIndex(newEntry->m_tableType) ||
- DictTabInfo::isTable(newEntry->m_tableType))
- {
- bool file = * oldEntry == *newEntry &&
- (!DictTabInfo::isIndex(newEntry->m_tableType) || c_systemRestart);
-
-#ifdef PRINT_SCHEMA_RESTART
- ndbout_c("%s -> restartCreateTab (file: %d)", buf, file);
- ndbout << *newEntry << " " << *oldEntry << endl;
-#endif
- restartCreateTab(signal, tableId, newEntry, newEntry, file);
- * oldEntry = * newEntry;
- return;
- }
- else if (! (* oldEntry == *newEntry))
- {
-#ifdef PRINT_SCHEMA_RESTART
- ndbout_c("%s -> restartCreateTab", buf);
- ndbout << *newEntry << " " << *oldEntry << endl;
-#endif
- restartCreateTab(signal, tableId, oldEntry, newEntry, false);
- * oldEntry = * newEntry;
- return;
- }
- * oldEntry = * newEntry;
- continue;
- }
- }
- }
-
- c_restartRecord.m_pass++;
- c_restartRecord.activeTable= 0;
- if(c_restartRecord.m_pass <= LAST_PASS)
- {
- checkSchemaStatus(signal);
- }
- else
- {
- execute(signal, c_schemaRecord.m_callback, 0);
- }
-}//checkSchemaStatus()
-
-void
-Dbdict::restartCreateTab(Signal* signal, Uint32 tableId,
- const SchemaFile::TableEntry * old_entry,
- const SchemaFile::TableEntry * new_entry,
- bool file){
- jam();
-
- switch(new_entry->m_tableType){
- case DictTabInfo::UndefTableType:
- case DictTabInfo::HashIndexTrigger:
- case DictTabInfo::SubscriptionTrigger:
- case DictTabInfo::ReadOnlyConstraint:
- case DictTabInfo::IndexTrigger:
- ndbrequire(false);
- case DictTabInfo::SystemTable:
- case DictTabInfo::UserTable:
- case DictTabInfo::UniqueHashIndex:
- case DictTabInfo::HashIndex:
- case DictTabInfo::UniqueOrderedIndex:
- case DictTabInfo::OrderedIndex:
- break;
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:
- case DictTabInfo::Datafile:
- case DictTabInfo::Undofile:
- restartCreateObj(signal, tableId, old_entry, new_entry, file);
- return;
- }
-
- CreateTableRecordPtr createTabPtr;
- c_opCreateTable.seize(createTabPtr);
- ndbrequire(!createTabPtr.isNull());
-
- createTabPtr.p->key = ++c_opRecordSequence;
- c_opCreateTable.add(createTabPtr);
-
- createTabPtr.p->m_errorCode = 0;
- createTabPtr.p->m_tablePtrI = tableId;
- createTabPtr.p->m_coordinatorRef = reference();
- createTabPtr.p->m_senderRef = 0;
- createTabPtr.p->m_senderData = RNIL;
- createTabPtr.p->m_tabInfoPtrI = RNIL;
- createTabPtr.p->m_dihAddFragPtr = RNIL;
-
- if(file && !ERROR_INSERTED(6002)){
- jam();
-
- c_readTableRecord.no_of_words = old_entry->m_info_words;
- c_readTableRecord.pageId = 0;
- c_readTableRecord.m_callback.m_callbackData = createTabPtr.p->key;
- c_readTableRecord.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateTab_readTableConf);
-
- startReadTableFile(signal, tableId);
- return;
- } else {
-
- ndbrequire(c_masterNodeId != getOwnNodeId());
-
- /**
- * Get from master
- */
- GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = createTabPtr.p->key;
- req->requestType = GetTabInfoReq::RequestById |
- GetTabInfoReq::LongSignalConf;
- req->tableId = tableId;
- sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB);
-
- if(ERROR_INSERTED(6002)){
- NdbSleep_MilliSleep(10);
- CRASH_INSERTION(6002);
- }
- }
-}
-
-void
-Dbdict::restartCreateTab_readTableConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- PageRecordPtr pageRecPtr;
- c_pageRecordArray.getPtr(pageRecPtr, c_readTableRecord.pageId);
-
- ParseDictTabInfoRecord parseRecord;
- parseRecord.requestType = DictTabInfo::GetTabInfoConf;
- parseRecord.errorCode = 0;
-
- Uint32 sz = c_readTableRecord.no_of_words;
- SimplePropertiesLinearReader r(pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz);
- handleTabInfoInit(r, &parseRecord);
- if (parseRecord.errorCode != 0)
- {
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Unable to restart, fail while creating table %d"
- " error: %d. Most likely change of configuration",
- c_readTableRecord.tableId,
- parseRecord.errorCode);
- progError(__LINE__,
- NDBD_EXIT_INVALID_CONFIG,
- buf);
- ndbrequire(parseRecord.errorCode == 0);
- }
-
- /* ---------------------------------------------------------------- */
- // We have read the table description from disk as part of system restart.
- // We will also write it back again to ensure that both copies are ok.
- /* ---------------------------------------------------------------- */
- ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
- c_writeTableRecord.no_of_words = c_readTableRecord.no_of_words;
- c_writeTableRecord.pageId = c_readTableRecord.pageId;
- c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
- c_writeTableRecord.m_callback.m_callbackData = callbackData;
- c_writeTableRecord.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateTab_writeTableConf);
- startWriteTableFile(signal, c_readTableRecord.tableId);
-}
-
-void
-Dbdict::execGET_TABINFO_CONF(Signal* signal){
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
-
- switch(conf->tableType){
- case DictTabInfo::UndefTableType:
- case DictTabInfo::HashIndexTrigger:
- case DictTabInfo::SubscriptionTrigger:
- case DictTabInfo::ReadOnlyConstraint:
- case DictTabInfo::IndexTrigger:
- ndbrequire(false);
- case DictTabInfo::SystemTable:
- case DictTabInfo::UserTable:
- case DictTabInfo::UniqueHashIndex:
- case DictTabInfo::HashIndex:
- case DictTabInfo::UniqueOrderedIndex:
- case DictTabInfo::OrderedIndex:
- break;
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:
- case DictTabInfo::Datafile:
- case DictTabInfo::Undofile:
- if(refToBlock(conf->senderRef) == TSMAN
- && (refToNode(conf->senderRef) == 0
- || refToNode(conf->senderRef) == getOwnNodeId()))
- {
- jam();
- FilePtr fg_ptr;
- ndbrequire(c_file_hash.find(fg_ptr, conf->tableId));
- const Uint32 free_extents= conf->freeExtents;
- const Uint32 id= conf->tableId;
- const Uint32 type= conf->tableType;
- const Uint32 data= conf->senderData;
- signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
- signal->theData[1]= id;
- signal->theData[2]= type;
- signal->theData[3]= data;
- signal->theData[4]= free_extents;
- sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
- }
- else if(refToBlock(conf->senderRef) == LGMAN
- && (refToNode(conf->senderRef) == 0
- || refToNode(conf->senderRef) == getOwnNodeId()))
- {
- jam();
- FilegroupPtr fg_ptr;
- ndbrequire(c_filegroup_hash.find(fg_ptr, conf->tableId));
- const Uint32 free_hi= conf->freeWordsHi;
- const Uint32 free_lo= conf->freeWordsLo;
- const Uint32 id= conf->tableId;
- const Uint32 type= conf->tableType;
- const Uint32 data= conf->senderData;
- signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
- signal->theData[1]= id;
- signal->theData[2]= type;
- signal->theData[3]= data;
- signal->theData[4]= free_hi;
- signal->theData[5]= free_lo;
- sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
- }
- else
- {
- jam();
- restartCreateObj_getTabInfoConf(signal);
- }
- return;
- }
-
- const Uint32 tableId = conf->tableId;
- const Uint32 senderData = conf->senderData;
-
- SegmentedSectionPtr tabInfoPtr;
- signal->getSection(tabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, senderData));
- ndbrequire(!createTabPtr.isNull());
- ndbrequire(createTabPtr.p->m_tablePtrI == tableId);
-
- /**
- * Put data into table record
- */
- ParseDictTabInfoRecord parseRecord;
- parseRecord.requestType = DictTabInfo::GetTabInfoConf;
- parseRecord.errorCode = 0;
-
- SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
- handleTabInfoInit(r, &parseRecord);
- ndbrequire(parseRecord.errorCode == 0);
-
- // save to disk
-
- ndbrequire(tableId < c_tableRecordPool.getSize());
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
- tableEntry->m_info_words= tabInfoPtr.sz;
-
- Callback callback;
- callback.m_callbackData = createTabPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateTab_writeTableConf);
-
- signal->header.m_noOfSections = 0;
- writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
- signal->setSection(tabInfoPtr, 0);
- releaseSections(signal);
-}
-
-void
-Dbdict::restartCreateTab_writeTableConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- Callback callback;
- callback.m_callbackData = callbackData;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateTab_dihComplete);
-
- SegmentedSectionPtr fragDataPtr;
- fragDataPtr.sz = 0;
- fragDataPtr.setNull();
- createTab_dih(signal, createTabPtr, fragDataPtr, &callback);
-}
-
-void
-Dbdict::restartCreateTab_dihComplete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- if(createTabPtr.p->m_errorCode)
- {
- char buf[100];
- BaseString::snprintf(buf, sizeof(buf), "Failed to create table during"
- " restart, Error: %u",
- createTabPtr.p->m_errorCode);
- progError(__LINE__, NDBD_EXIT_RESOURCE_ALLOC_ERROR, buf);
- }
-
- Callback callback;
- callback.m_callbackData = callbackData;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateTab_activateComplete);
-
- alterTab_activate(signal, createTabPtr, &callback);
-}
-
-void
-Dbdict::restartCreateTab_activateComplete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- tabPtr.p->tabState = TableRecord::DEFINED;
-
- releaseCreateTableOp(signal,createTabPtr);
-
- c_restartRecord.activeTable++;
- checkSchemaStatus(signal);
-}
-
-void
-Dbdict::releaseCreateTableOp(Signal* signal, CreateTableRecordPtr createTabPtr)
-{
- if (createTabPtr.p->m_tabInfoPtrI != RNIL)
- {
- jam();
- SegmentedSectionPtr tabInfoPtr;
- getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
- signal->setSection(tabInfoPtr, 0);
- releaseSections(signal);
- }
- c_opCreateTable.release(createTabPtr);
-}
-
-void
-Dbdict::restartDropTab(Signal* signal, Uint32 tableId,
- const SchemaFile::TableEntry * old_entry,
- const SchemaFile::TableEntry * new_entry)
-{
- switch(old_entry->m_tableType){
- case DictTabInfo::UndefTableType:
- case DictTabInfo::HashIndexTrigger:
- case DictTabInfo::SubscriptionTrigger:
- case DictTabInfo::ReadOnlyConstraint:
- case DictTabInfo::IndexTrigger:
- ndbrequire(false);
- case DictTabInfo::SystemTable:
- case DictTabInfo::UserTable:
- case DictTabInfo::UniqueHashIndex:
- case DictTabInfo::HashIndex:
- case DictTabInfo::UniqueOrderedIndex:
- case DictTabInfo::OrderedIndex:
- break;
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:
- case DictTabInfo::Datafile:
- case DictTabInfo::Undofile:
- restartDropObj(signal, tableId, old_entry);
- return;
- }
-
- const Uint32 key = ++c_opRecordSequence;
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.seize(dropTabPtr));
-
- dropTabPtr.p->key = key;
- c_opDropTable.add(dropTabPtr);
-
- dropTabPtr.p->m_errorCode = 0;
- dropTabPtr.p->m_request.tableId = tableId;
- dropTabPtr.p->m_coordinatorRef = 0;
- dropTabPtr.p->m_requestType = DropTabReq::RestartDropTab;
- dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
-
- dropTabPtr.p->m_participantData.m_block = 0;
- dropTabPtr.p->m_participantData.m_callback.m_callbackData = key;
- dropTabPtr.p->m_participantData.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartDropTab_complete);
- dropTab_nextStep(signal, dropTabPtr);
-}
-
-void
-Dbdict::restartDropTab_complete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
-
- //@todo check error
-
- releaseTableObject(c_restartRecord.activeTable);
- c_opDropTable.release(dropTabPtr);
-
- c_restartRecord.activeTable++;
- checkSchemaStatus(signal);
-}
-
-/**
- * Create Obj during NR/SR
- */
-void
-Dbdict::restartCreateObj(Signal* signal,
- Uint32 tableId,
- const SchemaFile::TableEntry * old_entry,
- const SchemaFile::TableEntry * new_entry,
- bool file){
- jam();
-
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.seize(createObjPtr));
-
- const Uint32 key = ++c_opRecordSequence;
- createObjPtr.p->key = key;
- c_opCreateObj.add(createObjPtr);
- createObjPtr.p->m_errorCode = 0;
- createObjPtr.p->m_senderRef = reference();
- createObjPtr.p->m_senderData = tableId;
- createObjPtr.p->m_clientRef = reference();
- createObjPtr.p->m_clientData = tableId;
-
- createObjPtr.p->m_obj_id = tableId;
- createObjPtr.p->m_obj_type = new_entry->m_tableType;
- createObjPtr.p->m_obj_version = new_entry->m_tableVersion;
-
- createObjPtr.p->m_callback.m_callbackData = key;
- createObjPtr.p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::restartCreateObj_prepare_start_done);
-
- createObjPtr.p->m_restart= file ? 1 : 2;
- switch(new_entry->m_tableType){
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:
- createObjPtr.p->m_vt_index = 0;
- break;
- case DictTabInfo::Datafile:
- case DictTabInfo::Undofile:
- createObjPtr.p->m_vt_index = 1;
- break;
- default:
- ndbrequire(false);
- }
-
- createObjPtr.p->m_obj_info_ptr_i = RNIL;
- if(file)
- {
- c_readTableRecord.no_of_words = old_entry->m_info_words;
- c_readTableRecord.pageId = 0;
- c_readTableRecord.m_callback.m_callbackData = key;
- c_readTableRecord.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateObj_readConf);
-
- startReadTableFile(signal, tableId);
- }
- else
- {
- /**
- * Get from master
- */
- GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = key;
- req->requestType = GetTabInfoReq::RequestById |
- GetTabInfoReq::LongSignalConf;
- req->tableId = tableId;
- sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB);
- }
-}
-
-void
-Dbdict::restartCreateObj_getTabInfoConf(Signal* signal)
-{
- jam();
-
- GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
-
- const Uint32 objId = conf->tableId;
- const Uint32 senderData = conf->senderData;
-
- SegmentedSectionPtr objInfoPtr;
- signal->getSection(objInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
-
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.find(createObjPtr, senderData));
- ndbrequire(createObjPtr.p->m_obj_id == objId);
-
- createObjPtr.p->m_obj_info_ptr_i= objInfoPtr.i;
- signal->header.m_noOfSections = 0;
-
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
- (signal, createObjPtr.p);
-}
-
-void
-Dbdict::restartCreateObj_readConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- ndbrequire(createObjPtr.p->m_errorCode == 0);
-
- PageRecordPtr pageRecPtr;
- c_pageRecordArray.getPtr(pageRecPtr, c_readTableRecord.pageId);
-
- Uint32 sz = c_readTableRecord.no_of_words;
-
- Ptr<SectionSegment> ptr;
- ndbrequire(import(ptr, pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz));
- createObjPtr.p->m_obj_info_ptr_i= ptr.i;
-
- if (f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
- (signal, createObjPtr.p);
- else
- execute(signal, createObjPtr.p->m_callback, 0);
-}
-
-void
-Dbdict::restartCreateObj_prepare_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- ndbrequire(createObjPtr.p->m_errorCode == 0);
-
- Callback callback;
- callback.m_callbackData = callbackData;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateObj_write_complete);
-
- SegmentedSectionPtr objInfoPtr;
- getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
-
- writeTableFile(signal, createObjPtr.p->m_obj_id, objInfoPtr, &callback);
-}
-
-void
-Dbdict::restartCreateObj_write_complete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- ndbrequire(returnCode == 0);
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- ndbrequire(createObjPtr.p->m_errorCode == 0);
-
- SegmentedSectionPtr objInfoPtr;
- getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
- signal->setSection(objInfoPtr, 0);
- releaseSections(signal);
- createObjPtr.p->m_obj_info_ptr_i = RNIL;
-
- createObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateObj_prepare_complete_done);
-
- if (f_dict_op[createObjPtr.p->m_vt_index].m_prepare_complete)
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_complete)
- (signal, createObjPtr.p);
- else
- execute(signal, createObjPtr.p->m_callback, 0);
-}
-
-void
-Dbdict::restartCreateObj_prepare_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- ndbrequire(createObjPtr.p->m_errorCode == 0);
-
- createObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateObj_commit_start_done);
-
- if (f_dict_op[createObjPtr.p->m_vt_index].m_commit_start)
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_commit_start)
- (signal, createObjPtr.p);
- else
- execute(signal, createObjPtr.p->m_callback, 0);
-}
-
-void
-Dbdict::restartCreateObj_commit_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- ndbrequire(createObjPtr.p->m_errorCode == 0);
-
- createObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartCreateObj_commit_complete_done);
-
- if (f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
- (signal, createObjPtr.p);
- else
- execute(signal, createObjPtr.p->m_callback, 0);
-}
-
-
-void
-Dbdict::restartCreateObj_commit_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- ndbrequire(createObjPtr.p->m_errorCode == 0);
-
- c_opCreateObj.release(createObjPtr);
-
- c_restartRecord.activeTable++;
- checkSchemaStatus(signal);
-}
-
-/**
- * Drop object during NR/SR
- */
-void
-Dbdict::restartDropObj(Signal* signal,
- Uint32 tableId,
- const SchemaFile::TableEntry * entry)
-{
- jam();
-
- DropObjRecordPtr dropObjPtr;
- ndbrequire(c_opDropObj.seize(dropObjPtr));
-
- const Uint32 key = ++c_opRecordSequence;
- dropObjPtr.p->key = key;
- c_opDropObj.add(dropObjPtr);
- dropObjPtr.p->m_errorCode = 0;
- dropObjPtr.p->m_senderRef = reference();
- dropObjPtr.p->m_senderData = tableId;
- dropObjPtr.p->m_clientRef = reference();
- dropObjPtr.p->m_clientData = tableId;
-
- dropObjPtr.p->m_obj_id = tableId;
- dropObjPtr.p->m_obj_type = entry->m_tableType;
- dropObjPtr.p->m_obj_version = entry->m_tableVersion;
-
- dropObjPtr.p->m_callback.m_callbackData = key;
- dropObjPtr.p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::restartDropObj_prepare_start_done);
-
- ndbout_c("Dropping %d %d", tableId, entry->m_tableType);
- switch(entry->m_tableType){
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:{
- jam();
- Ptr<Filegroup> fg_ptr;
- ndbrequire(c_filegroup_hash.find(fg_ptr, tableId));
- dropObjPtr.p->m_obj_ptr_i = fg_ptr.i;
- dropObjPtr.p->m_vt_index = 3;
- break;
- }
- case DictTabInfo::Datafile:{
- jam();
- Ptr<File> file_ptr;
- dropObjPtr.p->m_vt_index = 2;
- ndbrequire(c_file_hash.find(file_ptr, tableId));
- dropObjPtr.p->m_obj_ptr_i = file_ptr.i;
- break;
- }
- case DictTabInfo::Undofile:{
- jam();
- Ptr<File> file_ptr;
- dropObjPtr.p->m_vt_index = 4;
- ndbrequire(c_file_hash.find(file_ptr, tableId));
- dropObjPtr.p->m_obj_ptr_i = file_ptr.i;
-
- /**
- * Undofiles are only removed from logfile groups file list
- * as drop undofile is currently not supported...
- * file will be dropped by lgman when dropping filegroup
- */
- dropObjPtr.p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::restartDropObj_commit_complete_done);
-
- if (f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
- (signal, dropObjPtr.p);
- else
- execute(signal, dropObjPtr.p->m_callback, 0);
- return;
- }
- default:
- jamLine(entry->m_tableType);
- ndbrequire(false);
- }
-
- if (f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_start)
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_start)
- (signal, dropObjPtr.p);
- else
- execute(signal, dropObjPtr.p->m_callback, 0);
-}
-
-void
-Dbdict::restartDropObj_prepare_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- DropObjRecordPtr dropObjPtr;
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- ndbrequire(dropObjPtr.p->m_errorCode == 0);
-
- dropObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartDropObj_prepare_complete_done);
-
- if (f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
- (signal, dropObjPtr.p);
- else
- execute(signal, dropObjPtr.p->m_callback, 0);
-}
-
-void
-Dbdict::restartDropObj_prepare_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- DropObjRecordPtr dropObjPtr;
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- ndbrequire(dropObjPtr.p->m_errorCode == 0);
-
- dropObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartDropObj_commit_start_done);
-
- if (f_dict_op[dropObjPtr.p->m_vt_index].m_commit_start)
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_start)
- (signal, dropObjPtr.p);
- else
- execute(signal, dropObjPtr.p->m_callback, 0);
-}
-
-void
-Dbdict::restartDropObj_commit_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- DropObjRecordPtr dropObjPtr;
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- ndbrequire(dropObjPtr.p->m_errorCode == 0);
-
- dropObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::restartDropObj_commit_complete_done);
-
- if (f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
- (signal, dropObjPtr.p);
- else
- execute(signal, dropObjPtr.p->m_callback, 0);
-}
-
-
-void
-Dbdict::restartDropObj_commit_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- ndbrequire(returnCode == 0);
- DropObjRecordPtr dropObjPtr;
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- ndbrequire(dropObjPtr.p->m_errorCode == 0);
-
- c_opDropObj.release(dropObjPtr);
-
- c_restartRecord.activeTable++;
- checkSchemaStatus(signal);
-}
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: NODE FAILURE HANDLING ------------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains the code that is used when nodes */
-/* (kernel/api) fails. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-/* ---------------------------------------------------------------- */
-// We receive a report of an API that failed.
-/* ---------------------------------------------------------------- */
-void Dbdict::execAPI_FAILREQ(Signal* signal)
-{
- jamEntry();
- Uint32 failedApiNode = signal->theData[0];
- BlockReference retRef = signal->theData[1];
-
-#if 0
- Uint32 userNode = refToNode(c_connRecord.userBlockRef);
- if (userNode == failedApiNode) {
- jam();
- c_connRecord.userBlockRef = (Uint32)-1;
- }//if
-#endif
-
- signal->theData[0] = failedApiNode;
- signal->theData[1] = reference();
- sendSignal(retRef, GSN_API_FAILCONF, signal, 2, JBB);
-}//execAPI_FAILREQ()
-
-/* ---------------------------------------------------------------- */
-// We receive a report of one or more node failures of kernel nodes.
-/* ---------------------------------------------------------------- */
-void Dbdict::execNODE_FAILREP(Signal* signal)
-{
- jamEntry();
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
-
- c_failureNr = nodeFail->failNo;
- const Uint32 numberOfFailedNodes = nodeFail->noOfNodes;
- const bool masterFailed = (c_masterNodeId != nodeFail->masterNodeId);
- c_masterNodeId = nodeFail->masterNodeId;
-
- c_noNodesFailed += numberOfFailedNodes;
- Uint32 theFailedNodes[NodeBitmask::Size];
- memcpy(theFailedNodes, nodeFail->theNodes, sizeof(theFailedNodes));
-
- c_counterMgr.execNODE_FAILREP(signal);
-
- bool ok = false;
- switch(c_blockState){
- case BS_IDLE:
- jam();
- ok = true;
- if(c_opRecordPool.getSize() !=
- (c_opRecordPool.getNoOfFree() +
- c_opSubEvent.get_count() + c_opCreateEvent.get_count() +
- c_opDropEvent.get_count() + c_opSignalUtil.get_count()))
- {
- jam();
- c_blockState = BS_NODE_FAILURE;
- }
- break;
- case BS_CREATE_TAB:
- jam();
- ok = true;
- if(!masterFailed)
- break;
- // fall through
- case BS_BUSY:
- case BS_NODE_FAILURE:
- jam();
- c_blockState = BS_NODE_FAILURE;
- ok = true;
- break;
- case BS_NODE_RESTART:
- jam();
- ok = true;
- break;
- }
- ndbrequire(ok);
-
- for(unsigned i = 1; i < MAX_NDB_NODES; i++) {
- jam();
- if(NodeBitmask::get(theFailedNodes, i)) {
- jam();
- NodeRecordPtr nodePtr;
- c_nodes.getPtr(nodePtr, i);
-
- nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
- NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
- nfCompRep->blockNo = DBDICT;
- nfCompRep->nodeId = getOwnNodeId();
- nfCompRep->failedNodeId = nodePtr.i;
- sendSignal(DBDIH_REF, GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBB);
-
- c_aliveNodes.clear(i);
- }//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()
-
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: NODE START HANDLING --------------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains the code that is used when kernel nodes */
-/* starts. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-/* ---------------------------------------------------------------- */
-// Include a starting node in list of nodes to be part of adding
-// and dropping tables.
-/* ---------------------------------------------------------------- */
-void Dbdict::execINCL_NODEREQ(Signal* signal)
-{
- jamEntry();
- NodeRecordPtr nodePtr;
- BlockReference retRef = signal->theData[0];
- nodePtr.i = signal->theData[1];
-
- ndbrequire(c_noNodesFailed > 0);
- c_noNodesFailed--;
-
- c_nodes.getPtr(nodePtr);
- ndbrequire(nodePtr.p->nodeState == NodeRecord::NDB_NODE_DEAD);
- nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
- signal->theData[0] = nodePtr.i;
- signal->theData[1] = reference();
- sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
-
- c_aliveNodes.set(nodePtr.i);
-}//execINCL_NODEREQ()
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: ADD TABLE HANDLING ---------------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains the code that is used when adding a table. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-/* ---------------------------------------------------------------- */
-// This signal receives information about a table from either:
-// API, Ndbcntr or from other DICT.
-/* ---------------------------------------------------------------- */
-void
-Dbdict::execCREATE_TABLE_REQ(Signal* signal){
- jamEntry();
- if(!assembleFragments(signal)){
- return;
- }
-
- CreateTableReq* const req = (CreateTableReq*)signal->getDataPtr();
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
-
- ParseDictTabInfoRecord parseRecord;
- do {
- if(getOwnNodeId() != c_masterNodeId){
- jam();
- parseRecord.errorCode = CreateTableRef::NotMaster;
- break;
- }
-
- if (c_blockState == BS_NODE_RESTART){
- jam();
- parseRecord.errorCode = CreateTableRef::BusyWithNR;
- break;
- }
-
- if (c_blockState != BS_IDLE){
- jam();
- parseRecord.errorCode = CreateTableRef::Busy;
- break;
- }
-
- if (checkSingleUserMode(signal->getSendersBlockRef()))
- {
- jam();
- parseRecord.errorCode = CreateTableRef::SingleUser;
- break;
- }
-
- CreateTableRecordPtr createTabPtr;
- c_opCreateTable.seize(createTabPtr);
-
- if(createTabPtr.isNull()){
- jam();
- parseRecord.errorCode = CreateTableRef::Busy;
- break;
- }
-
- parseRecord.requestType = DictTabInfo::CreateTableFromAPI;
- parseRecord.errorCode = 0;
-
- SegmentedSectionPtr ptr;
- signal->getSection(ptr, CreateTableReq::DICT_TAB_INFO);
- SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
-
- handleTabInfoInit(r, &parseRecord);
- releaseSections(signal);
-
- if(parseRecord.errorCode != 0){
- jam();
- c_opCreateTable.release(createTabPtr);
- break;
- }
-
- createTabPtr.p->m_errorCode = 0;
- createTabPtr.p->m_senderRef = senderRef;
- createTabPtr.p->m_senderData = senderData;
- createTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
- createTabPtr.p->m_coordinatorRef = reference();
- createTabPtr.p->m_fragmentsPtrI = RNIL;
- createTabPtr.p->m_dihAddFragPtr = RNIL;
-
- Uint32 key = c_opRecordSequence + 1;
- Uint32 *theData = signal->getDataPtrSend();
- Uint16 *frag_data= (Uint16*)&signal->theData[25];
- CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
- req->senderRef = reference();
- req->senderData = key;
- req->primaryTableId = parseRecord.tablePtr.p->primaryTableId;
- req->noOfFragments = parseRecord.tablePtr.p->fragmentCount;
- req->fragmentationType = parseRecord.tablePtr.p->fragmentType;
- MEMCOPY_NO_WORDS(frag_data, c_fragData, c_fragDataLen);
-
- if (parseRecord.tablePtr.p->isOrderedIndex()) {
- jam();
- // ordered index has same fragmentation as the table
- req->primaryTableId = parseRecord.tablePtr.p->primaryTableId;
- req->fragmentationType = DictTabInfo::DistrKeyOrderedIndex;
- }
- else if (parseRecord.tablePtr.p->isHashIndex())
- {
- jam();
- /*
- Unique hash indexes has same amount of fragments as primary table
- and distributed in the same manner but has always a normal hash
- fragmentation.
- */
- req->primaryTableId = parseRecord.tablePtr.p->primaryTableId;
- req->fragmentationType = DictTabInfo::DistrKeyUniqueHashIndex;
- }
- else
- {
- jam();
- /*
- Blob tables come here with primaryTableId != RNIL but we only need
- it for creating the fragments so we set it to RNIL now that we got
- what we wanted from it to avoid other side effects.
- */
- parseRecord.tablePtr.p->primaryTableId = RNIL;
- }
- EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
- CreateFragmentationReq::SignalLength);
- jamEntry();
- if (signal->theData[0] != 0)
- {
- jam();
- parseRecord.errorCode= signal->theData[0];
- c_opCreateTable.release(createTabPtr);
- releaseTableObject(parseRecord.tablePtr.i, true);
- break;
- }
- createTabPtr.p->key = key;
- c_opRecordSequence++;
- c_opCreateTable.add(createTabPtr);
- c_blockState = BS_CREATE_TAB;
- return;
- } while(0);
-
- /**
- * Something went wrong
- */
-
- releaseSections(signal);
- CreateTableRef * ref = (CreateTableRef*)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->masterNodeId = c_masterNodeId;
- ref->errorCode = parseRecord.errorCode;
- ref->errorLine = parseRecord.errorLine;
- ref->errorKey = parseRecord.errorKey;
- ref->status = parseRecord.status;
- sendSignal(senderRef, GSN_CREATE_TABLE_REF, signal,
- CreateTableRef::SignalLength, JBB);
-}
-
-void
-Dbdict::execBACKUP_FRAGMENT_REQ(Signal* signal)
-{
- jamEntry();
- Uint32 tableId = signal->theData[0];
- Uint32 lock = signal->theData[1];
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId, true);
-
- if(lock)
- {
- ndbrequire(tablePtr.p->tabState == TableRecord::DEFINED);
- tablePtr.p->tabState = TableRecord::BACKUP_ONGOING;
- }
- else if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
- {
- tablePtr.p->tabState = TableRecord::DEFINED;
- }
-}
-
-bool
-Dbdict::check_ndb_versions() const
-{
- Uint32 node = 0;
- Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
- while((node = c_aliveNodes.find(node + 1)) != BitmaskImpl::NotFound)
- {
- if(getNodeInfo(node).m_version != version)
- {
- return false;
- }
- }
- return true;
-}
-
-void
-Dbdict::execALTER_TABLE_REQ(Signal* signal)
-{
- // Received by master
- jamEntry();
- if(!assembleFragments(signal)){
- return;
- }
- AlterTableReq* const req = (AlterTableReq*)signal->getDataPtr();
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
- const Uint32 changeMask = req->changeMask;
- const Uint32 tableId = req->tableId;
- const Uint32 tableVersion = req->tableVersion;
- ParseDictTabInfoRecord* aParseRecord;
-
- // Get table definition
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId, false);
- if(tablePtr.isNull()){
- jam();
- alterTableRef(signal, req, AlterTableRef::NoSuchTable);
- return;
- }
-
- if(getOwnNodeId() != c_masterNodeId){
- jam();
- alterTableRef(signal, req, AlterTableRef::NotMaster);
- 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);
- return;
- }
-
- if (!check_ndb_versions())
- {
- jam();
- alterTableRef(signal, req, AlterTableRef::IncompatibleVersions);
- return;
- }
-
- if (checkSingleUserMode(signal->getSendersBlockRef()))
- {
- jam();
- alterTableRef(signal, req, AlterTableRef::SingleUser);
- return;
- }
-
- const TableRecord::TabState tabState = tablePtr.p->tabState;
- bool ok = false;
- switch(tabState){
- case TableRecord::NOT_DEFINED:
- case TableRecord::DEFINING:
- jam();
- alterTableRef(signal, req, AlterTableRef::NoSuchTable);
- return;
- case TableRecord::DEFINED:
- ok = true;
- jam();
- break;
- case TableRecord::BACKUP_ONGOING:
- jam();
- alterTableRef(signal, req, AlterTableRef::BackupInProgress);
- return;
- case TableRecord::PREPARE_DROPPING:
- case TableRecord::DROPPING:
- jam();
- alterTableRef(signal, req, AlterTableRef::DropInProgress);
- return;
- }
- ndbrequire(ok);
-
- if(tablePtr.p->tableVersion != tableVersion){
- jam();
- alterTableRef(signal, req, AlterTableRef::InvalidTableVersion);
- return;
- }
- // Parse new table defintion
- ParseDictTabInfoRecord parseRecord;
- aParseRecord = &parseRecord;
-
- CreateTableRecordPtr alterTabPtr; // Reuse create table records
- c_opCreateTable.seize(alterTabPtr);
-
- if(alterTabPtr.isNull()){
- jam();
- alterTableRef(signal, req, AlterTableRef::Busy);
- return;
- }
-
- alterTabPtr.p->m_changeMask = changeMask;
- parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
- parseRecord.errorCode = 0;
-
- SegmentedSectionPtr ptr;
- signal->getSection(ptr, AlterTableReq::DICT_TAB_INFO);
- SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
-
- handleTabInfoInit(r, &parseRecord, false); // Will not save info
-
- if(parseRecord.errorCode != 0){
- jam();
- c_opCreateTable.release(alterTabPtr);
- alterTableRef(signal, req,
- (AlterTableRef::ErrorCode) parseRecord.errorCode,
- aParseRecord);
- return;
- }
-
- releaseSections(signal);
- alterTabPtr.p->key = ++c_opRecordSequence;
- c_opCreateTable.add(alterTabPtr);
- ndbrequire(c_opCreateTable.find(alterTabPtr, alterTabPtr.p->key));
- alterTabPtr.p->m_errorCode = 0;
- alterTabPtr.p->m_senderRef = senderRef;
- alterTabPtr.p->m_senderData = senderData;
- alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
- alterTabPtr.p->m_alterTableFailed = false;
- alterTabPtr.p->m_coordinatorRef = reference();
- alterTabPtr.p->m_fragmentsPtrI = RNIL;
- alterTabPtr.p->m_dihAddFragPtr = RNIL;
- alterTabPtr.p->m_alterTableId = tablePtr.p->tableId;
-
- // Send prepare request to all alive nodes
- SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPages(w, parseRecord.tablePtr);
-
- SegmentedSectionPtr tabInfoPtr;
- w.getPtr(tabInfoPtr);
-
- alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
-
- // Alter table on all nodes
- c_blockState = BS_BUSY;
-
- Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex);
- Callback c = { safe_cast(&Dbdict::alterTable_backup_mutex_locked),
- alterTabPtr.p->key };
-
- ndbrequire(mutex.lock(c));
-}
-
-void
-Dbdict::alterTable_backup_mutex_locked(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue)
-{
- jamEntry();
-
- ndbrequire(retValue == 0);
-
- CreateTableRecordPtr alterTabPtr;
- ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData));
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId, true);
-
- Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex);
- mutex.unlock(); // ignore response
-
- SegmentedSectionPtr tabInfoPtr;
- getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
- signal->setSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
-
- alterTabPtr.p->m_tabInfoPtrI = RNIL;
-
- if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
- {
- jam();
- AlterTableReq* req = (AlterTableReq*)signal->getDataPtr();
- req->senderData = alterTabPtr.p->m_senderData;
- req->senderRef = alterTabPtr.p->m_senderRef;
- alterTableRef(signal, req, AlterTableRef::BackupInProgress);
-
- c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_tablePtrI);
- releaseTableObject(tablePtr.i, false);
-
- c_opCreateTable.release(alterTabPtr);
- c_blockState = BS_IDLE;
- return;
- }
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
- SafeCounter safeCounter(c_counterMgr,
- alterTabPtr.p->m_coordinatorData.m_counter);
- safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
-
- AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
- lreq->senderRef = reference();
- lreq->senderData = alterTabPtr.p->key;
- lreq->clientRef = alterTabPtr.p->m_senderRef;
- lreq->clientData = alterTabPtr.p->m_senderData;
- lreq->changeMask = alterTabPtr.p->m_changeMask;
- lreq->tableId = tablePtr.p->tableId;
- lreq->tableVersion = alter_obj_inc_schema_version(tablePtr.p->tableVersion);
- lreq->gci = tablePtr.p->gciTableCreated;
- lreq->requestType = AlterTabReq::AlterTablePrepare;
-
- sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
-}
-
-void Dbdict::alterTableRef(Signal * signal,
- AlterTableReq * req,
- AlterTableRef::ErrorCode errCode,
- ParseDictTabInfoRecord* parseRecord)
-{
- jam();
- releaseSections(signal);
- AlterTableRef * ref = (AlterTableRef*)signal->getDataPtrSend();
- Uint32 senderRef = req->senderRef;
- ref->senderData = req->senderData;
- ref->senderRef = reference();
- ref->masterNodeId = c_masterNodeId;
- if (parseRecord) {
- ref->errorCode = parseRecord->errorCode;
- ref->errorLine = parseRecord->errorLine;
- ref->errorKey = parseRecord->errorKey;
- ref->status = parseRecord->status;
- }
- else {
- ref->errorCode = errCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
- ref->status = 0;
- }
- sendSignal(senderRef, GSN_ALTER_TABLE_REF, signal,
- AlterTableRef::SignalLength, JBB);
-}
-
-void
-Dbdict::execALTER_TAB_REQ(Signal * signal)
-{
- // Received in all nodes to handle change locally
- jamEntry();
-
- if(!assembleFragments(signal)){
- return;
- }
- AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
- const Uint32 changeMask = req->changeMask;
- const Uint32 tableId = req->tableId;
- const Uint32 tableVersion = req->tableVersion;
- const Uint32 gci = req->gci;
- AlterTabReq::RequestType requestType =
- (AlterTabReq::RequestType) req->requestType;
-
- SegmentedSectionPtr tabInfoPtr;
- signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
-
- CreateTableRecordPtr alterTabPtr; // Reuse create table records
-
- if (senderRef != reference()) {
- jam();
- c_blockState = BS_BUSY;
- }
- if ((requestType == AlterTabReq::AlterTablePrepare)
- && (senderRef != reference())) {
- jam();
- c_opCreateTable.seize(alterTabPtr);
- if(!alterTabPtr.isNull())
- alterTabPtr.p->m_changeMask = changeMask;
- }
- else {
- jam();
- ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
- }
- if(alterTabPtr.isNull()){
- jam();
- alterTabRef(signal, req, AlterTableRef::Busy);
- return;
- }
-
- if (!check_ndb_versions())
- {
- jam();
- alterTabRef(signal, req, AlterTableRef::IncompatibleVersions);
- return;
- }
-
- alterTabPtr.p->m_alterTableId = tableId;
- alterTabPtr.p->m_coordinatorRef = senderRef;
-
- // Get table definition
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId, false);
- if(tablePtr.isNull()){
- jam();
- alterTabRef(signal, req, AlterTableRef::NoSuchTable);
- return;
- }
-
- switch(requestType) {
- case(AlterTabReq::AlterTablePrepare): {
- ParseDictTabInfoRecord* aParseRecord;
-
- const TableRecord::TabState tabState = tablePtr.p->tabState;
- bool ok = false;
- switch(tabState){
- case TableRecord::NOT_DEFINED:
- case TableRecord::DEFINING:
- jam();
- alterTabRef(signal, req, AlterTableRef::NoSuchTable);
- return;
- case TableRecord::DEFINED:
- ok = true;
- jam();
- break;
- case TableRecord::PREPARE_DROPPING:
- case TableRecord::DROPPING:
- jam();
- alterTabRef(signal, req, AlterTableRef::DropInProgress);
- return;
- case TableRecord::BACKUP_ONGOING:
- jam();
- alterTabRef(signal, req, AlterTableRef::BackupInProgress);
- return;
- }
- ndbrequire(ok);
-
- if(alter_obj_inc_schema_version(tablePtr.p->tableVersion) != tableVersion){
- jam();
- alterTabRef(signal, req, AlterTableRef::InvalidTableVersion);
- return;
- }
- TableRecordPtr newTablePtr;
- if (senderRef != reference()) {
- jam();
- // Parse altered table defintion
- ParseDictTabInfoRecord parseRecord;
- aParseRecord = &parseRecord;
-
- parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
- parseRecord.errorCode = 0;
-
- SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
-
- handleTabInfoInit(r, &parseRecord, false); // Will not save info
-
- if(parseRecord.errorCode != 0){
- jam();
- c_opCreateTable.release(alterTabPtr);
- alterTabRef(signal, req,
- (AlterTableRef::ErrorCode) parseRecord.errorCode,
- aParseRecord);
- return;
- }
- alterTabPtr.p->key = senderData;
- c_opCreateTable.add(alterTabPtr);
- alterTabPtr.p->m_errorCode = 0;
- alterTabPtr.p->m_senderRef = senderRef;
- alterTabPtr.p->m_senderData = senderData;
- alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
- alterTabPtr.p->m_fragmentsPtrI = RNIL;
- alterTabPtr.p->m_dihAddFragPtr = RNIL;
- newTablePtr = parseRecord.tablePtr;
- newTablePtr.p->tableVersion = tableVersion;
- }
- else { // (req->senderRef == reference())
- jam();
- c_tableRecordPool.getPtr(newTablePtr, alterTabPtr.p->m_tablePtrI);
- newTablePtr.p->tableVersion = tableVersion;
- }
- if (handleAlterTab(req, alterTabPtr.p, tablePtr, newTablePtr) == -1) {
- jam();
- c_opCreateTable.release(alterTabPtr);
- alterTabRef(signal, req, AlterTableRef::UnsupportedChange);
- return;
- }
- releaseSections(signal);
- // Propagate alter table to other local blocks
- AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = senderData;
- req->changeMask = changeMask;
- req->tableId = tableId;
- req->tableVersion = tableVersion;
- req->gci = gci;
- req->requestType = requestType;
- sendSignal(DBLQH_REF, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
- return;
- }
- case(AlterTabReq::AlterTableCommit): {
- jam();
- // Write schema for altered table to disk
- SegmentedSectionPtr tabInfoPtr;
- signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
- alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
- bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
-
- signal->header.m_noOfSections = 0;
-
- // Update table record
- tablePtr.p->packedSize = tabInfoPtr.sz;
- tablePtr.p->tableVersion = tableVersion;
- tablePtr.p->gciTableCreated = gci;
-
- SchemaFile::TableEntry tabEntry;
- tabEntry.m_tableVersion = tableVersion;
- tabEntry.m_tableType = tablePtr.p->tableType;
- if (savetodisk)
- tabEntry.m_tableState = SchemaFile::ALTER_TABLE_COMMITTED;
- else
- tabEntry.m_tableState = SchemaFile::TEMPORARY_TABLE_COMMITTED;
- tabEntry.m_gcp = gci;
- tabEntry.m_info_words = tabInfoPtr.sz;
- memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
-
- Callback callback;
- callback.m_callbackData = senderData;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::alterTab_writeSchemaConf);
-
- updateSchemaState(signal, tableId, &tabEntry, &callback, savetodisk);
- break;
- }
- case(AlterTabReq::AlterTableRevert): {
- jam();
- // Revert failed alter table
- revertAlterTable(signal, changeMask, tableId, alterTabPtr.p);
- // Acknowledge the reverted alter table
- AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->changeMask = changeMask;
- conf->tableId = tableId;
- conf->tableVersion = tableVersion;
- conf->gci = gci;
- conf->requestType = requestType;
- sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
- AlterTabConf::SignalLength, JBB);
- break;
- }
- default: ndbrequire(false);
- }
-}
-
-void Dbdict::alterTabRef(Signal * signal,
- AlterTabReq * req,
- AlterTableRef::ErrorCode errCode,
- ParseDictTabInfoRecord* parseRecord)
-{
- jam();
- releaseSections(signal);
- AlterTabRef * ref = (AlterTabRef*)signal->getDataPtrSend();
- Uint32 senderRef = req->senderRef;
- ref->senderData = req->senderData;
- ref->senderRef = reference();
- if (parseRecord) {
- jam();
- ref->errorCode = parseRecord->errorCode;
- ref->errorLine = parseRecord->errorLine;
- ref->errorKey = parseRecord->errorKey;
- ref->errorStatus = parseRecord->status;
- }
- else {
- jam();
- ref->errorCode = errCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
- ref->errorStatus = 0;
- }
- sendSignal(senderRef, GSN_ALTER_TAB_REF, signal,
- AlterTabRef::SignalLength, JBB);
-
- c_blockState = BS_IDLE;
-}
-
-void Dbdict::execALTER_TAB_REF(Signal * signal){
- jamEntry();
-
- AlterTabRef * ref = (AlterTabRef*)signal->getDataPtr();
-
- Uint32 senderRef = ref->senderRef;
- Uint32 senderData = ref->senderData;
- Uint32 errorCode = ref->errorCode;
- Uint32 errorLine = ref->errorLine;
- Uint32 errorKey = ref->errorKey;
- Uint32 errorStatus = ref->errorStatus;
- AlterTabReq::RequestType requestType =
- (AlterTabReq::RequestType) ref->requestType;
- CreateTableRecordPtr alterTabPtr;
- ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
- Uint32 changeMask = alterTabPtr.p->m_changeMask;
- SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
- safeCounter.clearWaitingFor(refToNode(senderRef));
- switch (requestType) {
- case(AlterTabReq::AlterTablePrepare): {
- if (safeCounter.done()) {
- jam();
- // Send revert request to all alive nodes
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId);
- Uint32 tableId = tablePtr.p->tableId;
- Uint32 tableVersion = tablePtr.p->tableVersion;
- Uint32 gci = tablePtr.p->gciTableCreated;
- SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPages(w, tablePtr);
- SegmentedSectionPtr spDataPtr;
- w.getPtr(spDataPtr);
- signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
- safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
-
- AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
- lreq->senderRef = reference();
- lreq->senderData = alterTabPtr.p->key;
- lreq->clientRef = alterTabPtr.p->m_senderRef;
- lreq->clientData = alterTabPtr.p->m_senderData;
- lreq->changeMask = changeMask;
- lreq->tableId = tableId;
- lreq->tableVersion = tableVersion;
- lreq->gci = gci;
- lreq->requestType = AlterTabReq::AlterTableRevert;
-
- sendSignal(rg, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
- }
- else {
- jam();
- alterTabPtr.p->m_alterTableFailed = true;
- }
- break;
- }
- case(AlterTabReq::AlterTableCommit):
- jam();
- case(AlterTabReq::AlterTableRevert): {
- AlterTableRef * apiRef = (AlterTableRef*)signal->getDataPtrSend();
-
- apiRef->senderData = senderData;
- apiRef->senderRef = reference();
- apiRef->masterNodeId = c_masterNodeId;
- apiRef->errorCode = errorCode;
- apiRef->errorLine = errorLine;
- apiRef->errorKey = errorKey;
- apiRef->status = errorStatus;
- if (safeCounter.done()) {
- jam();
- sendSignal(senderRef, GSN_ALTER_TABLE_REF, signal,
- AlterTableRef::SignalLength, JBB);
- c_blockState = BS_IDLE;
- }
- else {
- jam();
- alterTabPtr.p->m_alterTableFailed = true;
- alterTabPtr.p->m_alterTableRef = *apiRef;
- }
- break;
- }
- default: ndbrequire(false);
- }
-}
-
-void
-Dbdict::execALTER_TAB_CONF(Signal * signal){
- jamEntry();
- AlterTabConf * const conf = (AlterTabConf*)signal->getDataPtr();
- Uint32 senderRef = conf->senderRef;
- Uint32 senderData = conf->senderData;
- Uint32 changeMask = conf->changeMask;
- Uint32 tableId = conf->tableId;
- Uint32 tableVersion = conf->tableVersion;
- Uint32 gci = conf->gci;
- AlterTabReq::RequestType requestType =
- (AlterTabReq::RequestType) conf->requestType;
- CreateTableRecordPtr alterTabPtr;
- ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
-
- switch (requestType) {
- case(AlterTabReq::AlterTablePrepare): {
- switch(refToBlock(signal->getSendersBlockRef())) {
- case DBLQH: {
- jam();
- AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = senderData;
- req->changeMask = changeMask;
- req->tableId = tableId;
- req->tableVersion = tableVersion;
- req->gci = gci;
- req->requestType = requestType;
- sendSignal(DBDIH_REF, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
- return;
- }
- case DBDIH: {
- jam();
- AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = senderData;
- req->changeMask = changeMask;
- req->tableId = tableId;
- req->tableVersion = tableVersion;
- req->gci = gci;
- req->requestType = requestType;
- sendSignal(DBTC_REF, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
- return;
- }
- case DBTC: {
- jam();
- // Participant is done with prepare phase, send conf to coordinator
- AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->changeMask = changeMask;
- conf->tableId = tableId;
- conf->tableVersion = tableVersion;
- conf->gci = gci;
- conf->requestType = requestType;
- sendSignal(alterTabPtr.p->m_coordinatorRef, GSN_ALTER_TAB_CONF, signal,
- AlterTabConf::SignalLength, JBB);
- return;
- }
- default :break;
- }
- // Coordinator only
- SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
- safeCounter.clearWaitingFor(refToNode(senderRef));
- if (safeCounter.done()) {
- jam();
- // We have received all local confirmations
- if (alterTabPtr.p->m_alterTableFailed) {
- jam();
- // Send revert request to all alive nodes
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId);
- Uint32 tableId = tablePtr.p->tableId;
- Uint32 tableVersion = tablePtr.p->tableVersion;
- Uint32 gci = tablePtr.p->gciTableCreated;
- SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPages(w, tablePtr);
- SegmentedSectionPtr spDataPtr;
- w.getPtr(spDataPtr);
- signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
- safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
-
- AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
- lreq->senderRef = reference();
- lreq->senderData = alterTabPtr.p->key;
- lreq->clientRef = alterTabPtr.p->m_senderRef;
- lreq->clientData = alterTabPtr.p->m_senderData;
- lreq->changeMask = changeMask;
- lreq->tableId = tableId;
- lreq->tableVersion = tableVersion;
- lreq->gci = gci;
- lreq->requestType = AlterTabReq::AlterTableRevert;
-
- sendSignal(rg, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
- }
- else {
- jam();
- // Send commit request to all alive nodes
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPages(w, tablePtr);
- SegmentedSectionPtr spDataPtr;
- w.getPtr(spDataPtr);
- signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
- safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
-
- AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
- lreq->senderRef = reference();
- lreq->senderData = alterTabPtr.p->key;
- lreq->clientRef = alterTabPtr.p->m_senderRef;
- lreq->clientData = alterTabPtr.p->m_senderData;
- lreq->changeMask = changeMask;
- lreq->tableId = tableId;
- lreq->tableVersion = tableVersion;
- lreq->gci = gci;
- lreq->requestType = AlterTabReq::AlterTableCommit;
-
- sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength, JBB);
- }
- }
- else {
- // (!safeCounter.done())
- jam();
- }
- break;
- }
- case(AlterTabReq::AlterTableRevert):
- jam();
- case(AlterTabReq::AlterTableCommit): {
- SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
- safeCounter.clearWaitingFor(refToNode(senderRef));
- if (safeCounter.done()) {
- jam();
- // We have received all local confirmations
- releaseSections(signal);
- if (alterTabPtr.p->m_alterTableFailed) {
- jam();
- AlterTableRef * apiRef =
- (AlterTableRef*)signal->getDataPtrSend();
- *apiRef = alterTabPtr.p->m_alterTableRef;
- sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_REF, signal,
- AlterTableRef::SignalLength, JBB);
- }
- else {
- jam();
- // Alter table completed, inform API
- AlterTableConf * const apiConf =
- (AlterTableConf*)signal->getDataPtrSend();
- apiConf->senderRef = reference();
- apiConf->senderData = alterTabPtr.p->m_senderData;
- apiConf->tableId = tableId;
- apiConf->tableVersion = tableVersion;
-
- //@todo check api failed
- sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_CONF, signal,
- AlterTableConf::SignalLength, JBB);
- }
-
- // Release resources
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI);
- releaseTableObject(tabPtr.i, false);
- releaseCreateTableOp(signal,alterTabPtr);
- c_blockState = BS_IDLE;
- }
- else {
- // (!safeCounter.done())
- jam();
- }
- break;
- }
- default: ndbrequire(false);
- }
-}
-
-// For debugging
-inline
-void Dbdict::printTables()
-{
- DLHashTable<DictObject>::Iterator iter;
- bool moreTables = c_obj_hash.first(iter);
- printf("OBJECTS IN DICT:\n");
- char name[MAX_TAB_NAME_SIZE];
- while (moreTables) {
- Ptr<DictObject> tablePtr = iter.curr;
- ConstRope r(c_rope_pool, tablePtr.p->m_name);
- r.copy(name);
- printf("%s ", name);
- moreTables = c_obj_hash.next(iter);
- }
- printf("\n");
-}
-
-int Dbdict::handleAlterTab(AlterTabReq * req,
- CreateTableRecord * alterTabPtrP,
- TableRecordPtr origTablePtr,
- TableRecordPtr newTablePtr)
-{
- bool supportedAlteration = false;
- Uint32 changeMask = req->changeMask;
-
- if (AlterTableReq::getNameFlag(changeMask)) {
- jam();
- // Table rename
- supportedAlteration = true;
- // Remove from hashtable
- Ptr<DictObject> obj_ptr;
- c_obj_pool.getPtr(obj_ptr, origTablePtr.p->m_obj_ptr_i);
- c_obj_hash.remove(obj_ptr);
- {
- Rope org(c_rope_pool, origTablePtr.p->tableName);
- org.copy(alterTabPtrP->previousTableName);
-
- ConstRope src(c_rope_pool, newTablePtr.p->tableName);
- char tmp[MAX_TAB_NAME_SIZE];
- const int len = src.size();
- src.copy(tmp);
- ndbrequire(org.assign(tmp, len));
- }
- obj_ptr.p->m_name = origTablePtr.p->tableName;
- // Put it back
- c_obj_hash.add(obj_ptr);
- }
-
- if (AlterTableReq::getFrmFlag(changeMask)) {
- // Table definition changed (new frm)
- supportedAlteration = true;
- // Save old definition
- Rope org(c_rope_pool, origTablePtr.p->frmData);
- org.copy(alterTabPtrP->previousFrmData);
- alterTabPtrP->previousFrmLen = org.size();
-
- // Set new definition
- ConstRope src(c_rope_pool, newTablePtr.p->frmData);
- char tmp[MAX_FRM_DATA_SIZE];
- src.copy(tmp);
- ndbrequire(org.assign(tmp, src.size()));
- }
-
-/*
- TODO RONM: Lite ny kod för FragmentData och RangeOrListData
-*/
- if (supportedAlteration)
- {
- // Set new schema version
- origTablePtr.p->tableVersion = newTablePtr.p->tableVersion;
- return 0;
- }
- else
- {
- jam();
- return -1;
- }
-}
-
-void Dbdict::revertAlterTable(Signal * signal,
- Uint32 changeMask,
- Uint32 tableId,
- CreateTableRecord * alterTabPtrP)
-{
- bool supportedAlteration = false;
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
-
- if (AlterTableReq::getNameFlag(changeMask)) {
- jam();
- // Table rename
- supportedAlteration = true;
- // Restore previous name
-
- Ptr<DictObject> obj_ptr;
- c_obj_pool.getPtr(obj_ptr, tablePtr.p->m_obj_ptr_i);
- c_obj_hash.remove(obj_ptr);
-
- {
- // Restore name
- Rope org(c_rope_pool, tablePtr.p->tableName);
- ndbrequire(org.assign(alterTabPtrP->previousTableName));
- }
- obj_ptr.p->m_name = tablePtr.p->tableName;
- // Put it back
- c_obj_hash.add(obj_ptr);
- }
-
- if (AlterTableReq::getFrmFlag(changeMask))
- {
- jam();
- // Table redefinition
- supportedAlteration = true;
- // Restore previous frm
- Rope org(c_rope_pool, tablePtr.p->tableName);
- ndbrequire(org.assign(alterTabPtrP->previousFrmData,
- alterTabPtrP->previousFrmLen));
-
- }
-
-
- if (supportedAlteration)
- {
- tablePtr.p->tableVersion =
- alter_obj_dec_schema_version(tablePtr.p->tableVersion);
- return;
- }
-
- ndbrequire(false);
-}
-
-void
-Dbdict::alterTab_writeSchemaConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- Uint32 key = callbackData;
- CreateTableRecordPtr alterTabPtr;
- ndbrequire(c_opCreateTable.find(alterTabPtr, key));
- Uint32 tableId = alterTabPtr.p->m_alterTableId;
-
- Callback callback;
- callback.m_callbackData = alterTabPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::alterTab_writeTableConf);
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
- if (savetodisk)
- {
- SegmentedSectionPtr tabInfoPtr;
- getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
- writeTableFile(signal, tableId, tabInfoPtr, &callback);
- }
- else
- {
- execute(signal, callback, 0);
- }
-}
-
-void
-Dbdict::alterTab_writeTableConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- CreateTableRecordPtr alterTabPtr;
- ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData));
- Uint32 coordinatorRef = alterTabPtr.p->m_coordinatorRef;
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_alterTableId);
- // Alter table commit request handled successfully
- // Inform Suma so it can send events to any subscribers of the table
- AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
- if (coordinatorRef == reference())
- req->senderRef = alterTabPtr.p->m_senderRef;
- else
- req->senderRef = 0;
- req->senderData = callbackData;
- req->tableId = tabPtr.p->tableId;
- req->tableVersion = tabPtr.p->tableVersion;
- req->gci = tabPtr.p->gciTableCreated;
- req->requestType = AlterTabReq::AlterTableCommit;
- req->changeMask = alterTabPtr.p->m_changeMask;
- SegmentedSectionPtr tabInfoPtr;
- getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
- signal->setSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
- EXECUTE_DIRECT(SUMA, GSN_ALTER_TAB_REQ, signal,
- AlterTabReq::SignalLength);
- releaseSections(signal);
- alterTabPtr.p->m_tabInfoPtrI = RNIL;
- jamEntry();
- AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = callbackData;
- conf->tableId = tabPtr.p->tableId;
- conf->tableVersion = tabPtr.p->tableVersion;
- conf->gci = tabPtr.p->gciTableCreated;
- conf->requestType = AlterTabReq::AlterTableCommit;
- conf->changeMask = alterTabPtr.p->m_changeMask;
- sendSignal(coordinatorRef, GSN_ALTER_TAB_CONF, signal,
- AlterTabConf::SignalLength, JBB);
-
-
- {
- ApiBroadcastRep* api= (ApiBroadcastRep*)signal->getDataPtrSend();
- api->gsn = GSN_ALTER_TABLE_REP;
- api->minVersion = MAKE_VERSION(4,1,15);
-
- AlterTableRep* rep = (AlterTableRep*)api->theData;
- rep->tableId = tabPtr.p->tableId;
- rep->tableVersion = alter_obj_dec_schema_version(tabPtr.p->tableVersion);
- rep->changeType = AlterTableRep::CT_ALTERED;
-
- LinearSectionPtr ptr[3];
- ptr[0].p = (Uint32*)alterTabPtr.p->previousTableName;
- ptr[0].sz = (sizeof(alterTabPtr.p->previousTableName) + 3) >> 2;
-
- sendSignal(QMGR_REF, GSN_API_BROADCAST_REP, signal,
- ApiBroadcastRep::SignalLength + AlterTableRep::SignalLength,
- JBB, ptr,1);
- }
-
- if(coordinatorRef != reference()) {
- jam();
- // Release resources
- c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI);
- releaseTableObject(tabPtr.i, false);
- releaseCreateTableOp(signal,alterTabPtr);
- c_blockState = BS_IDLE;
- }
-}
-
-void
-Dbdict::execCREATE_FRAGMENTATION_REF(Signal * signal){
- jamEntry();
- const Uint32 * theData = signal->getDataPtr();
- CreateFragmentationRef * const ref = (CreateFragmentationRef*)theData;
- (void)ref;
- ndbrequire(false);
-}
-
-void
-Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
- jamEntry();
- const Uint32 * theData = signal->getDataPtr();
- CreateFragmentationConf * const conf = (CreateFragmentationConf*)theData;
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
-
- ndbrequire(signal->getNoOfSections() == 1);
-
- SegmentedSectionPtr fragDataPtr;
- signal->getSection(fragDataPtr, CreateFragmentationConf::FRAGMENTS);
- signal->header.m_noOfSections = 0;
-
- /**
- * Get table
- */
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
-
- /**
- * Save fragment count
- */
- tabPtr.p->fragmentCount = conf->noOfFragments;
-
- /**
- * Update table version
- */
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry * tabEntry = getTableEntry(xsf, tabPtr.i);
-
- tabPtr.p->tableVersion =
- create_obj_inc_schema_version(tabEntry->m_tableVersion);
-
- /**
- * Pack
- */
- SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPages(w, tabPtr);
-
- SegmentedSectionPtr spDataPtr;
- w.getPtr(spDataPtr);
-
- signal->setSection(spDataPtr, CreateTabReq::DICT_TAB_INFO);
- signal->setSection(fragDataPtr, CreateTabReq::FRAGMENTATION);
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
- createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
- createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTablePrepare;
- tmp.init<CreateTabRef>(rg, GSN_CREATE_TAB_REF, createTabPtr.p->key);
-
- CreateTabReq * const req = (CreateTabReq*)theData;
- req->senderRef = reference();
- req->senderData = createTabPtr.p->key;
- req->clientRef = createTabPtr.p->m_senderRef;
- req->clientData = createTabPtr.p->m_senderData;
- req->requestType = CreateTabReq::CreateTablePrepare;
-
- req->gci = 0;
- req->tableId = tabPtr.i;
- req->tableVersion = create_obj_inc_schema_version(tabEntry->m_tableVersion);
-
- sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal,
- CreateTabReq::SignalLength, JBB);
-
- return;
-}
-
-void
-Dbdict::execCREATE_TAB_REF(Signal* signal){
- jamEntry();
-
- CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
-
- ndbrequire(createTabPtr.p->m_coordinatorRef == reference());
- ndbrequire(createTabPtr.p->m_coordinatorData.m_gsn == GSN_CREATE_TAB_REQ);
-
- if(ref->errorCode != CreateTabRef::NF_FakeErrorREF){
- createTabPtr.p->setErrorCode(ref->errorCode);
- }
- createTab_reply(signal, createTabPtr, refToNode(ref->senderRef));
-}
-
-void
-Dbdict::execCREATE_TAB_CONF(Signal* signal){
- jamEntry();
-
- ndbrequire(signal->getNoOfSections() == 0);
-
- CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
-
- ndbrequire(createTabPtr.p->m_coordinatorRef == reference());
- ndbrequire(createTabPtr.p->m_coordinatorData.m_gsn == GSN_CREATE_TAB_REQ);
-
- createTab_reply(signal, createTabPtr, refToNode(conf->senderRef));
-}
-
-void
-Dbdict::createTab_reply(Signal* signal,
- CreateTableRecordPtr createTabPtr,
- Uint32 nodeId)
-{
-
- SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
- if(!tmp.clearWaitingFor(nodeId)){
- jam();
- return;
- }
-
- switch(createTabPtr.p->m_coordinatorData.m_requestType){
- case CreateTabReq::CreateTablePrepare:{
-
- if(createTabPtr.p->m_errorCode != 0){
- jam();
- /**
- * Failed to prepare on atleast one node -> abort on all
- */
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
- createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTableDrop;
- ndbrequire(tmp.init<CreateTabRef>(rg, createTabPtr.p->key));
-
- CreateTabReq * const req = (CreateTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = createTabPtr.p->key;
- req->requestType = CreateTabReq::CreateTableDrop;
-
- sendSignal(rg, GSN_CREATE_TAB_REQ, signal,
- CreateTabReq::SignalLength, JBB);
- return;
- }
-
- /**
- * Lock mutex before commiting table
- */
- Mutex mutex(signal, c_mutexMgr, createTabPtr.p->m_startLcpMutex);
- Callback c = { safe_cast(&Dbdict::createTab_startLcpMutex_locked),
- createTabPtr.p->key};
-
- ndbrequire(mutex.lock(c));
- return;
- }
- case CreateTabReq::CreateTableCommit:{
- jam();
- ndbrequire(createTabPtr.p->m_errorCode == 0);
-
- /**
- * Unlock mutex before commiting table
- */
- Mutex mutex(signal, c_mutexMgr, createTabPtr.p->m_startLcpMutex);
- Callback c = { safe_cast(&Dbdict::createTab_startLcpMutex_unlocked),
- createTabPtr.p->key};
- mutex.unlock(c);
- return;
- }
- case CreateTabReq::CreateTableDrop:{
- jam();
- CreateTableRef * const ref = (CreateTableRef*)signal->getDataPtr();
- ref->senderRef = reference();
- ref->senderData = createTabPtr.p->m_senderData;
- ref->errorCode = createTabPtr.p->m_errorCode;
- ref->masterNodeId = c_masterNodeId;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = 0;
-
- //@todo check api failed
- sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_REF, signal,
- CreateTableRef::SignalLength, JBB);
- releaseCreateTableOp(signal,createTabPtr);
- c_blockState = BS_IDLE;
- return;
- }
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::createTab_startLcpMutex_locked(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue){
- jamEntry();
-
- ndbrequire(retValue == 0);
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
- createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTableCommit;
- SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
- tmp.init<CreateTabRef>(rg, GSN_CREATE_TAB_REF, createTabPtr.p->key);
-
- CreateTabReq * const req = (CreateTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = createTabPtr.p->key;
- req->requestType = CreateTabReq::CreateTableCommit;
-
- sendSignal(rg, GSN_CREATE_TAB_REQ, signal,
- CreateTabReq::SignalLength, JBB);
-}
-
-void
-Dbdict::createTab_startLcpMutex_unlocked(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue){
- jamEntry();
-
- ndbrequire(retValue == 0);
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- createTabPtr.p->m_startLcpMutex.release(c_mutexMgr);
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
-
- CreateTableConf * const conf = (CreateTableConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = createTabPtr.p->m_senderData;
- conf->tableId = createTabPtr.p->m_tablePtrI;
- conf->tableVersion = tabPtr.p->tableVersion;
-
- //@todo check api failed
- sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_CONF, signal,
- CreateTableConf::SignalLength, JBB);
- releaseCreateTableOp(signal,createTabPtr);
- c_blockState = BS_IDLE;
- return;
-}
-
-/***********************************************************
- * CreateTable participant code
- **********************************************************/
-void
-Dbdict::execCREATE_TAB_REQ(Signal* signal){
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- CreateTabReq * const req = (CreateTabReq*)signal->getDataPtr();
-
- CreateTabReq::RequestType rt = (CreateTabReq::RequestType)req->requestType;
- switch(rt){
- case CreateTabReq::CreateTablePrepare:
- CRASH_INSERTION2(6003, getOwnNodeId() != c_masterNodeId);
- createTab_prepare(signal, req);
- return;
- case CreateTabReq::CreateTableCommit:
- CRASH_INSERTION2(6004, getOwnNodeId() != c_masterNodeId);
- createTab_commit(signal, req);
- return;
- case CreateTabReq::CreateTableDrop:
- CRASH_INSERTION2(6005, getOwnNodeId() != c_masterNodeId);
- createTab_drop(signal, req);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::createTab_prepare(Signal* signal, CreateTabReq * req){
-
- const Uint32 gci = req->gci;
- const Uint32 tableId = req->tableId;
- const Uint32 tableVersion = req->tableVersion;
-
- SegmentedSectionPtr tabInfoPtr;
- signal->getSection(tabInfoPtr, CreateTabReq::DICT_TAB_INFO);
-
- CreateTableRecordPtr createTabPtr;
- if(req->senderRef == reference()){
- jam();
- ndbrequire(c_opCreateTable.find(createTabPtr, req->senderData));
- } else {
- jam();
- c_opCreateTable.seize(createTabPtr);
-
- ndbrequire(!createTabPtr.isNull());
-
- createTabPtr.p->key = req->senderData;
- c_opCreateTable.add(createTabPtr);
- createTabPtr.p->m_errorCode = 0;
- createTabPtr.p->m_tablePtrI = tableId;
- createTabPtr.p->m_coordinatorRef = req->senderRef;
- createTabPtr.p->m_senderRef = req->clientRef;
- createTabPtr.p->m_senderData = req->clientData;
- createTabPtr.p->m_dihAddFragPtr = RNIL;
-
- /**
- * Put data into table record
- */
- ParseDictTabInfoRecord parseRecord;
- parseRecord.requestType = DictTabInfo::AddTableFromDict;
- parseRecord.errorCode = 0;
-
- SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
-
- handleTabInfoInit(r, &parseRecord);
-
- ndbrequire(parseRecord.errorCode == 0);
- }
-
- ndbrequire(!createTabPtr.isNull());
-
- SegmentedSectionPtr fragPtr;
- signal->getSection(fragPtr, CreateTabReq::FRAGMENTATION);
-
- createTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
- createTabPtr.p->m_fragmentsPtrI = fragPtr.i;
-
- signal->header.m_noOfSections = 0;
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, tableId);
- tabPtr.p->packedSize = tabInfoPtr.sz;
- tabPtr.p->tableVersion = tableVersion;
- tabPtr.p->gciTableCreated = gci;
-
- SchemaFile::TableEntry tabEntry;
- tabEntry.m_tableVersion = tableVersion;
- tabEntry.m_tableType = tabPtr.p->tableType;
- tabEntry.m_tableState = SchemaFile::ADD_STARTED;
- tabEntry.m_gcp = gci;
- tabEntry.m_info_words = tabInfoPtr.sz;
- memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
-
- Callback callback;
- callback.m_callbackData = createTabPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::createTab_writeSchemaConf1);
-
- bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
- updateSchemaState(signal, tableId, &tabEntry, &callback, savetodisk);
-}
-
-void getSection(SegmentedSectionPtr & ptr, Uint32 i);
-
-void
-Dbdict::createTab_writeSchemaConf1(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- Callback callback;
- callback.m_callbackData = createTabPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::createTab_writeTableConf);
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
- if (savetodisk)
- {
- SegmentedSectionPtr tabInfoPtr;
- getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
- writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
- }
- else
- {
- execute(signal, callback, 0);
- }
-#if 0
- createTabPtr.p->m_tabInfoPtrI = RNIL;
- signal->setSection(tabInfoPtr, 0);
- releaseSections(signal);
-#endif
-}
-
-void
-Dbdict::createTab_writeTableConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- SegmentedSectionPtr fragDataPtr;
- getSection(fragDataPtr, createTabPtr.p->m_fragmentsPtrI);
-
- Callback callback;
- callback.m_callbackData = callbackData;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::createTab_dihComplete);
-
- createTab_dih(signal, createTabPtr, fragDataPtr, &callback);
-}
-
-void
-Dbdict::createTab_dih(Signal* signal,
- CreateTableRecordPtr createTabPtr,
- SegmentedSectionPtr fragDataPtr,
- Callback * c){
- jam();
-
- createTabPtr.p->m_callback = * c;
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
-
- DiAddTabReq * req = (DiAddTabReq*)signal->getDataPtrSend();
- req->connectPtr = createTabPtr.p->key;
- req->tableId = tabPtr.i;
- req->fragType = tabPtr.p->fragmentType;
- req->kValue = tabPtr.p->kValue;
- req->noOfReplicas = 0;
- req->loggedTable = !!(tabPtr.p->m_bits & TableRecord::TR_Logged);
- req->tableType = tabPtr.p->tableType;
- req->schemaVersion = tabPtr.p->tableVersion;
- req->primaryTableId = tabPtr.p->primaryTableId;
- req->temporaryTable = !!(tabPtr.p->m_bits & TableRecord::TR_Temporary);
-
-/*
- Behöver fiska upp fragDataPtr från table object istället
-*/
- if(!fragDataPtr.isNull()){
- signal->setSection(fragDataPtr, DiAddTabReq::FRAGMENTATION);
- }
-
- 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;
- Ptr<AttributeRecord> attrPtr;
- LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
- tabPtr.p->m_attributes);
- for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr))
- {
- AttributeRecord* aRec = attrPtr.p;
- if (aRec->tupleKey)
- {
- Uint32 attr = aRec->attributeDescriptor;
-
- desc->noOfKeyAttr ++;
- desc->keyAttr[key].attributeDescriptor = attr;
- Uint32 csNumber = (aRec->extPrecision >> 16);
- if (csNumber)
- {
- desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
- ndbrequire(all_charsets[csNumber] != 0);
- desc->hasCharAttr = 1;
- }
- else
- {
- desc->keyAttr[key].charsetInfo = 0;
- }
- if (AttributeDescriptor::getDKey(attr))
- {
- desc->noOfDistrKeys ++;
- }
- if (AttributeDescriptor::getArrayType(attr) != NDB_ARRAYTYPE_FIXED)
- {
- desc->noOfVarKeys ++;
- }
- key++;
- }
- }
- ndbrequire(key == tabPtr.p->noOfPrimkey);
-}
-
-static
-void
-calcLHbits(Uint32 * lhPageBits, Uint32 * lhDistrBits,
- Uint32 fid, Uint32 totalFragments)
-{
- Uint32 distrBits = 0;
- Uint32 pageBits = 0;
-
- Uint32 tmp = 1;
- while (tmp < totalFragments) {
- jam();
- tmp <<= 1;
- distrBits++;
- }//while
-#ifdef ndb_classical_lhdistrbits
- if (tmp != totalFragments) {
- tmp >>= 1;
- if ((fid >= (totalFragments - tmp)) && (fid < (tmp - 1))) {
- distrBits--;
- }//if
- }//if
-#endif
- * lhPageBits = pageBits;
- * lhDistrBits = distrBits;
-
-}//calcLHbits()
-
-
-void
-Dbdict::execADD_FRAGREQ(Signal* signal) {
- jamEntry();
-
- AddFragReq * const req = (AddFragReq*)signal->getDataPtr();
-
- Uint32 dihPtr = req->dihPtr;
- Uint32 senderData = req->senderData;
- Uint32 tableId = req->tableId;
- Uint32 fragId = req->fragmentId;
- Uint32 node = req->nodeId;
- Uint32 lcpNo = req->nextLCP;
- Uint32 fragCount = req->totalFragments;
- Uint32 requestInfo = req->requestInfo;
- Uint32 startGci = req->startGci;
- Uint32 logPart = req->logPartId;
-
- ndbrequire(node == getOwnNodeId());
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, senderData));
-
- createTabPtr.p->m_dihAddFragPtr = dihPtr;
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, tableId);
-
-#if 0
- tabPtr.p->gciTableCreated = (startGci > tabPtr.p->gciTableCreated ? startGci:
- startGci > tabPtr.p->gciTableCreated);
-#endif
-
- /**
- * Calc lh3PageBits
- */
- Uint32 lhDistrBits = 0;
- 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;
- req->senderRef = reference();
- req->fragmentId = fragId;
- req->requestInfo = requestInfo;
- req->tableId = tableId;
- req->localKeyLength = tabPtr.p->localKeyLen;
- req->maxLoadFactor = tabPtr.p->maxLoadFactor;
- req->minLoadFactor = tabPtr.p->minLoadFactor;
- req->kValue = tabPtr.p->kValue;
- req->lh3DistrBits = 0; //lhDistrBits;
- req->lh3PageBits = 0; //lhPageBits;
- req->noOfAttributes = tabPtr.p->noOfAttributes;
- 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; // wl-2066 no more "long keys"
- req->nextLCP = lcpNo;
-
- req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
- req->noOfCharsets = tabPtr.p->noOfCharsets;
- req->checksumIndicator = 1;
- req->GCPIndicator = 1;
- req->startGci = startGci;
- req->tableType = tabPtr.p->tableType;
- req->primaryTableId = tabPtr.p->primaryTableId;
- req->tablespace_id= tabPtr.p->m_tablespace_id;
- req->logPartId = logPart;
- req->forceVarPartFlag = !!(tabPtr.p->m_bits& TableRecord::TR_ForceVarPart);
- sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
- LqhFragReq::SignalLength, JBB);
- }
-}
-
-void
-Dbdict::execLQHFRAGREF(Signal * signal){
- jamEntry();
- LqhFragRef * const ref = (LqhFragRef*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
-
- createTabPtr.p->setErrorCode(ref->errorCode);
-
- {
- AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
- ref->dihPtr = createTabPtr.p->m_dihAddFragPtr;
- sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal,
- AddFragRef::SignalLength, JBB);
- }
-}
-
-void
-Dbdict::execLQHFRAGCONF(Signal * signal){
- jamEntry();
- LqhFragConf * const conf = (LqhFragConf*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
-
- createTabPtr.p->m_lqhFragPtr = conf->lqhFragPtr;
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- sendLQHADDATTRREQ(signal, createTabPtr, tabPtr.p->m_attributes.firstItem);
-}
-
-void
-Dbdict::sendLQHADDATTRREQ(Signal* signal,
- CreateTableRecordPtr createTabPtr,
- Uint32 attributePtrI){
- jam();
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- LqhAddAttrReq * const req = (LqhAddAttrReq*)signal->getDataPtrSend();
- Uint32 i = 0;
- for(i = 0; i<LqhAddAttrReq::MAX_ATTRIBUTES && attributePtrI != RNIL; i++){
- jam();
- AttributeRecordPtr attrPtr;
- c_attributeRecordPool.getPtr(attrPtr, attributePtrI);
- LqhAddAttrReq::Entry& entry = req->attributes[i];
- entry.attrId = attrPtr.p->attributeId;
- entry.attrDescriptor = attrPtr.p->attributeDescriptor;
- entry.extTypeInfo = 0;
- // charset number passed to TUP, TUX in upper half
- entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
- if (tabPtr.p->isIndex()) {
- Uint32 primaryAttrId;
- if (attrPtr.p->nextList != RNIL) {
- getIndexAttr(tabPtr, attributePtrI, &primaryAttrId);
- } else {
- primaryAttrId = ZNIL;
- if (tabPtr.p->isOrderedIndex())
- entry.attrId = 0; // attribute goes to TUP
- }
- entry.attrId |= (primaryAttrId << 16);
- }
- attributePtrI = attrPtr.p->nextList;
- }
- req->lqhFragPtr = createTabPtr.p->m_lqhFragPtr;
- req->senderData = createTabPtr.p->key;
- req->senderAttrPtr = attributePtrI;
- req->noOfAttributes = i;
-
- sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
- LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB);
-}
-
-void
-Dbdict::execLQHADDATTREF(Signal * signal){
- jamEntry();
- LqhAddAttrRef * const ref = (LqhAddAttrRef*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
-
- createTabPtr.p->setErrorCode(ref->errorCode);
-
- {
- AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
- ref->dihPtr = createTabPtr.p->m_dihAddFragPtr;
- sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal,
- AddFragRef::SignalLength, JBB);
- }
-
-}
-
-void
-Dbdict::execLQHADDATTCONF(Signal * signal){
- jamEntry();
- LqhAddAttrConf * const conf = (LqhAddAttrConf*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
-
- const Uint32 fragId = conf->fragId;
- const Uint32 nextAttrPtr = conf->senderAttrPtr;
- if(nextAttrPtr != RNIL){
- jam();
- sendLQHADDATTRREQ(signal, createTabPtr, nextAttrPtr);
- return;
- }
-
- {
- AddFragConf * const conf = (AddFragConf*)signal->getDataPtr();
- conf->dihPtr = createTabPtr.p->m_dihAddFragPtr;
- conf->fragId = fragId;
- sendSignal(DBDIH_REF, GSN_ADD_FRAGCONF, signal,
- AddFragConf::SignalLength, JBB);
- }
-}
-
-void
-Dbdict::execDIADDTABREF(Signal* signal){
- jam();
-
- DiAddTabRef * const ref = (DiAddTabRef*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
-
- createTabPtr.p->setErrorCode(ref->errorCode);
- execute(signal, createTabPtr.p->m_callback, 0);
-}
-
-void
-Dbdict::execDIADDTABCONF(Signal* signal){
- jam();
-
- DiAddTabConf * const conf = (DiAddTabConf*)signal->getDataPtr();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
-
- signal->theData[0] = createTabPtr.p->key;
- signal->theData[1] = reference();
- signal->theData[2] = createTabPtr.p->m_tablePtrI;
-
- if(createTabPtr.p->m_dihAddFragPtr != RNIL){
- jam();
-
- /**
- * We did perform at least one LQHFRAGREQ
- */
- sendSignal(DBLQH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
- return;
- } else {
- /**
- * No local fragment (i.e. no LQHFRAGREQ)
- */
- execute(signal, createTabPtr.p->m_callback, 0);
- return;
- //sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
- }
-}
-
-void
-Dbdict::execTAB_COMMITREF(Signal* signal) {
- jamEntry();
- ndbrequire(false);
-}//execTAB_COMMITREF()
-
-void
-Dbdict::execTAB_COMMITCONF(Signal* signal){
- jamEntry();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, signal->theData[0]));
-
- if(refToBlock(signal->getSendersBlockRef()) == DBLQH){
-
- execute(signal, createTabPtr.p->m_callback, 0);
- return;
- }
-
- if(refToBlock(signal->getSendersBlockRef()) == DBDIH){
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
-
- signal->theData[0] = tabPtr.i;
- signal->theData[1] = tabPtr.p->tableVersion;
- signal->theData[2] = (Uint32)!!(tabPtr.p->m_bits & TableRecord::TR_Logged);
- signal->theData[3] = reference();
- signal->theData[4] = (Uint32)tabPtr.p->tableType;
- signal->theData[5] = createTabPtr.p->key;
- signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
- signal->theData[7] = (Uint32)tabPtr.p->singleUserMode;
-
- sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 8, JBB);
- return;
- }
-
- ndbrequire(false);
-}
-
-void
-Dbdict::createTab_dihComplete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- //@todo check for master failed
-
- if(createTabPtr.p->m_errorCode == 0){
- jam();
-
- CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = createTabPtr.p->key;
- sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
- signal, CreateTabConf::SignalLength, JBB);
- return;
- }
-
- CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
- ref->senderRef = reference();
- ref->senderData = createTabPtr.p->key;
- ref->errorCode = createTabPtr.p->m_errorCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
- ref->errorStatus = 0;
-
- sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_REF,
- signal, CreateTabRef::SignalLength, JBB);
-}
-
-void
-Dbdict::createTab_commit(Signal * signal, CreateTabReq * req){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, req->senderData));
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
-
- SchemaFile::TableEntry tabEntry;
- tabEntry.m_tableVersion = tabPtr.p->tableVersion;
- tabEntry.m_tableType = tabPtr.p->tableType;
- if (savetodisk)
- tabEntry.m_tableState = SchemaFile::TABLE_ADD_COMMITTED;
- else
- tabEntry.m_tableState = SchemaFile::TEMPORARY_TABLE_COMMITTED;
-
- tabEntry.m_gcp = tabPtr.p->gciTableCreated;
- tabEntry.m_info_words = tabPtr.p->packedSize;
- memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
-
- Callback callback;
- callback.m_callbackData = createTabPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::createTab_writeSchemaConf2);
-
- updateSchemaState(signal, tabPtr.i, &tabEntry, &callback, savetodisk);
-}
-
-void
-Dbdict::createTab_writeSchemaConf2(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- Callback c;
- c.m_callbackData = callbackData;
- c.m_callbackFunction = safe_cast(&Dbdict::createTab_alterComplete);
- alterTab_activate(signal, createTabPtr, &c);
-}
-
-void
-Dbdict::createTab_alterComplete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- tabPtr.p->tabState = TableRecord::DEFINED;
-
- //@todo check error
- //@todo check master failed
-
- CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = createTabPtr.p->key;
- {
- CreateTabConf tmp= *conf;
- conf->senderData = createTabPtr.p->m_tablePtrI;
-#if 0
- signal->header.m_noOfSections = 1;
- SegmentedSectionPtr tabInfoPtr;
- getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
- signal->setSection(tabInfoPtr, 0);
-#endif
- sendSignal(SUMA_REF, GSN_CREATE_TAB_CONF, signal,
- CreateTabConf::SignalLength, JBB);
- *conf= tmp;
-#if 0
- signal->header.m_noOfSections = 0;
-#endif
- }
- sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
- signal, CreateTabConf::SignalLength, JBB);
-
- if(createTabPtr.p->m_coordinatorRef != reference()){
- jam();
- releaseCreateTableOp(signal,createTabPtr);
- }
-}
-
-void
-Dbdict::createTab_drop(Signal* signal, CreateTabReq * req){
- jam();
-
- const Uint32 key = req->senderData;
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, key));
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- tabPtr.p->tabState = TableRecord::DROPPING;
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.seize(dropTabPtr));
-
- dropTabPtr.p->key = key;
- c_opDropTable.add(dropTabPtr);
-
- dropTabPtr.p->m_errorCode = 0;
- dropTabPtr.p->m_request.tableId = createTabPtr.p->m_tablePtrI;
- dropTabPtr.p->m_requestType = DropTabReq::CreateTabDrop;
- dropTabPtr.p->m_coordinatorRef = createTabPtr.p->m_coordinatorRef;
- dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
-
- dropTabPtr.p->m_participantData.m_block = 0;
- dropTabPtr.p->m_participantData.m_callback.m_callbackData = req->senderData;
- dropTabPtr.p->m_participantData.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::createTab_dropComplete);
- dropTab_nextStep(signal, dropTabPtr);
-
- if (tabPtr.p->m_tablespace_id != RNIL)
- {
- FilegroupPtr ptr;
- ndbrequire(c_filegroup_hash.find(ptr, tabPtr.p->m_tablespace_id));
- decrease_ref_count(ptr.p->m_obj_ptr_i);
- }
-}
-
-void
-Dbdict::createTab_dropComplete(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode){
- jam();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
-
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
-
- releaseTableObject(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
- //@todo check master failed
-
- CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = createTabPtr.p->key;
- sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
- signal, CreateTabConf::SignalLength, JBB);
-
- if(createTabPtr.p->m_coordinatorRef != reference()){
- jam();
- releaseCreateTableOp(signal,createTabPtr);
- }
-
- c_opDropTable.release(dropTabPtr);
-}
-
-void
-Dbdict::alterTab_activate(Signal* signal, CreateTableRecordPtr createTabPtr,
- Callback * c){
-
- createTabPtr.p->m_callback = * c;
-
- signal->theData[0] = createTabPtr.p->key;
- signal->theData[1] = reference();
- signal->theData[2] = createTabPtr.p->m_tablePtrI;
- sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
-}
-
-void
-Dbdict::execTC_SCHVERCONF(Signal* signal){
- jamEntry();
-
- CreateTableRecordPtr createTabPtr;
- ndbrequire(c_opCreateTable.find(createTabPtr, signal->theData[1]));
-
- execute(signal, createTabPtr.p->m_callback, 0);
-}
-
-#define tabRequire(cond, error) \
- if (!(cond)) { \
- jam(); \
- parseP->errorCode = error; parseP->errorLine = __LINE__; \
- parseP->errorKey = it.getKey(); \
- return; \
- }//if
-
-// handleAddTableFailure(signal, __LINE__, allocatedTable);
-
-Dbdict::DictObject *
-Dbdict::get_object(const char * name, Uint32 len, Uint32 hash){
- DictObject key;
- key.m_key.m_name_ptr = name;
- key.m_key.m_name_len = len;
- key.m_key.m_pool = &c_rope_pool;
- key.m_name.m_hash = hash;
- Ptr<DictObject> old_ptr;
- c_obj_hash.find(old_ptr, key);
- return old_ptr.p;
-}
-
-void
-Dbdict::release_object(Uint32 obj_ptr_i, DictObject* obj_ptr_p){
- Rope name(c_rope_pool, obj_ptr_p->m_name);
- name.erase();
-
- Ptr<DictObject> ptr = { obj_ptr_p, obj_ptr_i };
- c_obj_hash.release(ptr);
-}
-
-void
-Dbdict::increase_ref_count(Uint32 obj_ptr_i)
-{
- DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
- ptr->m_ref_count++;
-}
-
-void
-Dbdict::decrease_ref_count(Uint32 obj_ptr_i)
-{
- DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
- ndbrequire(ptr->m_ref_count);
- ptr->m_ref_count--;
-}
-
-void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
- ParseDictTabInfoRecord * parseP,
- bool checkExist)
-{
-/* ---------------------------------------------------------------- */
-// We always start by handling table name since this must be the first
-// item in the list. Through the table name we can derive if it is a
-// correct name, a new name or an already existing table.
-/* ---------------------------------------------------------------- */
-
- it.first();
-
- SimpleProperties::UnpackStatus status;
- c_tableDesc.init();
- status = SimpleProperties::unpack(it, &c_tableDesc,
- DictTabInfo::TableMapping,
- DictTabInfo::TableMappingSize,
- true, true);
-
- if(status != SimpleProperties::Break){
- parseP->errorCode = CreateTableRef::InvalidFormat;
- parseP->status = status;
- parseP->errorKey = it.getKey();
- parseP->errorLine = __LINE__;
- return;
- }
-
- if(parseP->requestType == DictTabInfo::AlterTableFromAPI)
- {
- ndbrequire(!checkExist);
- }
- if(!checkExist)
- {
- ndbrequire(parseP->requestType == DictTabInfo::AlterTableFromAPI);
- }
-
- /* ---------------------------------------------------------------- */
- // Verify that table name is an allowed table name.
- // TODO
- /* ---------------------------------------------------------------- */
- const Uint32 tableNameLength = strlen(c_tableDesc.TableName) + 1;
- const Uint32 name_hash = Rope::hash(c_tableDesc.TableName, tableNameLength);
-
- if(checkExist){
- jam();
- tabRequire(get_object(c_tableDesc.TableName, tableNameLength) == 0,
- CreateTableRef::TableAlreadyExist);
- }
-
- TableRecordPtr tablePtr;
- switch (parseP->requestType) {
- case DictTabInfo::CreateTableFromAPI: {
- jam();
- }
- case DictTabInfo::AlterTableFromAPI:{
- jam();
- tablePtr.i = getFreeTableRecord(c_tableDesc.PrimaryTableId);
- /* ---------------------------------------------------------------- */
- // Check if no free tables existed.
- /* ---------------------------------------------------------------- */
- tabRequire(tablePtr.i != RNIL, CreateTableRef::NoMoreTableRecords);
-
- c_tableRecordPool.getPtr(tablePtr);
- break;
- }
- case DictTabInfo::AddTableFromDict:
- case DictTabInfo::ReadTableFromDiskSR:
- case DictTabInfo::GetTabInfoConf:
- {
-/* ---------------------------------------------------------------- */
-// Get table id and check that table doesn't already exist
-/* ---------------------------------------------------------------- */
- tablePtr.i = c_tableDesc.TableId;
-
- if (parseP->requestType == DictTabInfo::ReadTableFromDiskSR) {
- ndbrequire(tablePtr.i == c_restartRecord.activeTable);
- }//if
- if (parseP->requestType == DictTabInfo::GetTabInfoConf) {
- ndbrequire(tablePtr.i == c_restartRecord.activeTable);
- }//if
-
- c_tableRecordPool.getPtr(tablePtr);
- ndbrequire(tablePtr.p->tabState == TableRecord::NOT_DEFINED);
-
- //Uint32 oldTableVersion = tablePtr.p->tableVersion;
- initialiseTableRecord(tablePtr);
- if (parseP->requestType == DictTabInfo::AddTableFromDict) {
- jam();
- tablePtr.p->tabState = TableRecord::DEFINING;
- }//if
-
-/* ---------------------------------------------------------------- */
-// Set table version
-/* ---------------------------------------------------------------- */
- Uint32 tableVersion = c_tableDesc.TableVersion;
- tablePtr.p->tableVersion = tableVersion;
-
- break;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
- parseP->tablePtr = tablePtr;
-
- {
- Rope name(c_rope_pool, tablePtr.p->tableName);
- tabRequire(name.assign(c_tableDesc.TableName, tableNameLength, name_hash),
- CreateTableRef::OutOfStringBuffer);
- }
-
- Ptr<DictObject> obj_ptr;
- if (parseP->requestType != DictTabInfo::AlterTableFromAPI) {
- jam();
- ndbrequire(c_obj_hash.seize(obj_ptr));
- obj_ptr.p->m_id = tablePtr.i;
- obj_ptr.p->m_type = c_tableDesc.TableType;
- obj_ptr.p->m_name = tablePtr.p->tableName;
- obj_ptr.p->m_ref_count = 0;
- c_obj_hash.add(obj_ptr);
- tablePtr.p->m_obj_ptr_i = obj_ptr.i;
-
-#ifdef VM_TRACE
- ndbout_c("Dbdict: name=%s,id=%u,obj_ptr_i=%d",
- c_tableDesc.TableName, tablePtr.i, tablePtr.p->m_obj_ptr_i);
-#endif
- }
-
- // Disallow logging of a temporary table.
- tabRequire(!(c_tableDesc.TableTemporaryFlag && c_tableDesc.TableLoggedFlag),
- CreateTableRef::NoLoggingTemporaryTable);
-
- tablePtr.p->noOfAttributes = c_tableDesc.NoOfAttributes;
- tablePtr.p->m_bits |=
- (c_tableDesc.TableLoggedFlag ? TableRecord::TR_Logged : 0);
- tablePtr.p->m_bits |=
- (c_tableDesc.RowChecksumFlag ? TableRecord::TR_RowChecksum : 0);
- tablePtr.p->m_bits |=
- (c_tableDesc.RowGCIFlag ? TableRecord::TR_RowGCI : 0);
- tablePtr.p->m_bits |=
- (c_tableDesc.TableTemporaryFlag ? TableRecord::TR_Temporary : 0);
- tablePtr.p->m_bits |=
- (c_tableDesc.ForceVarPartFlag ? TableRecord::TR_ForceVarPart : 0);
- tablePtr.p->minLoadFactor = c_tableDesc.MinLoadFactor;
- tablePtr.p->maxLoadFactor = c_tableDesc.MaxLoadFactor;
- tablePtr.p->fragmentType = (DictTabInfo::FragmentType)c_tableDesc.FragmentType;
- tablePtr.p->tableType = (DictTabInfo::TableType)c_tableDesc.TableType;
- tablePtr.p->kValue = c_tableDesc.TableKValue;
- tablePtr.p->fragmentCount = c_tableDesc.FragmentCount;
- tablePtr.p->m_tablespace_id = c_tableDesc.TablespaceId;
- tablePtr.p->maxRowsLow = c_tableDesc.MaxRowsLow;
- tablePtr.p->maxRowsHigh = c_tableDesc.MaxRowsHigh;
- tablePtr.p->minRowsLow = c_tableDesc.MinRowsLow;
- tablePtr.p->minRowsHigh = c_tableDesc.MinRowsHigh;
- tablePtr.p->defaultNoPartFlag = c_tableDesc.DefaultNoPartFlag;
- tablePtr.p->linearHashFlag = c_tableDesc.LinearHashFlag;
- tablePtr.p->singleUserMode = c_tableDesc.SingleUserMode;
-
- {
- Rope frm(c_rope_pool, tablePtr.p->frmData);
- tabRequire(frm.assign(c_tableDesc.FrmData, c_tableDesc.FrmLen),
- CreateTableRef::OutOfStringBuffer);
- Rope range(c_rope_pool, tablePtr.p->rangeData);
- tabRequire(range.assign(c_tableDesc.RangeListData,
- c_tableDesc.RangeListDataLen),
- CreateTableRef::OutOfStringBuffer);
- Rope fd(c_rope_pool, tablePtr.p->ngData);
- tabRequire(fd.assign((const char*)c_tableDesc.FragmentData,
- c_tableDesc.FragmentDataLen),
- CreateTableRef::OutOfStringBuffer);
- Rope ts(c_rope_pool, tablePtr.p->tsData);
- tabRequire(ts.assign((const char*)c_tableDesc.TablespaceData,
- c_tableDesc.TablespaceDataLen),
- CreateTableRef::OutOfStringBuffer);
- }
-
- c_fragDataLen = c_tableDesc.FragmentDataLen;
- memcpy(c_fragData, c_tableDesc.FragmentData,
- c_tableDesc.FragmentDataLen);
-
- if(c_tableDesc.PrimaryTableId != RNIL) {
-
- tablePtr.p->primaryTableId = c_tableDesc.PrimaryTableId;
- tablePtr.p->indexState = (TableRecord::IndexState)c_tableDesc.IndexState;
- tablePtr.p->insertTriggerId = c_tableDesc.InsertTriggerId;
- tablePtr.p->updateTriggerId = c_tableDesc.UpdateTriggerId;
- tablePtr.p->deleteTriggerId = c_tableDesc.DeleteTriggerId;
- tablePtr.p->customTriggerId = c_tableDesc.CustomTriggerId;
- } else {
- tablePtr.p->primaryTableId = RNIL;
- tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
- tablePtr.p->insertTriggerId = RNIL;
- tablePtr.p->updateTriggerId = RNIL;
- tablePtr.p->deleteTriggerId = RNIL;
- tablePtr.p->customTriggerId = RNIL;
- }
- tablePtr.p->buildTriggerId = RNIL;
- tablePtr.p->indexLocal = 0;
-
- handleTabInfo(it, parseP, c_tableDesc);
-
- if(parseP->errorCode != 0)
- {
- /**
- * Release table
- */
- releaseTableObject(tablePtr.i, checkExist);
- return;
- }
-
- if (checkExist && tablePtr.p->m_tablespace_id != RNIL)
- {
- /**
- * Increase ref count
- */
- FilegroupPtr ptr;
- ndbrequire(c_filegroup_hash.find(ptr, tablePtr.p->m_tablespace_id));
- increase_ref_count(ptr.p->m_obj_ptr_i);
- }
-}//handleTabInfoInit()
-
-void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
- ParseDictTabInfoRecord * parseP,
- DictTabInfo::Table &tableDesc)
-{
- TableRecordPtr tablePtr = parseP->tablePtr;
-
- SimpleProperties::UnpackStatus status;
-
- Uint32 keyCount = 0;
- Uint32 keyLength = 0;
- Uint32 attrCount = tablePtr.p->noOfAttributes;
- Uint32 nullCount = 0;
- Uint32 nullBits = 0;
- Uint32 noOfCharsets = 0;
- Uint16 charsets[128];
- Uint32 recordLength = 0;
- AttributeRecordPtr attrPtr;
- c_attributeRecordHash.removeAll();
-
- LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
- tablePtr.p->m_attributes);
-
- Uint32 counts[] = {0,0,0,0,0};
-
- for(Uint32 i = 0; i<attrCount; i++){
- /**
- * Attribute Name
- */
- DictTabInfo::Attribute attrDesc; attrDesc.init();
- status = SimpleProperties::unpack(it, &attrDesc,
- DictTabInfo::AttributeMapping,
- DictTabInfo::AttributeMappingSize,
- true, true);
-
- if(status != SimpleProperties::Break){
- parseP->errorCode = CreateTableRef::InvalidFormat;
- parseP->status = status;
- parseP->errorKey = it.getKey();
- parseP->errorLine = __LINE__;
- return;
- }
-
- /**
- * Check that attribute is not defined twice
- */
- const size_t len = strlen(attrDesc.AttributeName)+1;
- const Uint32 name_hash = Rope::hash(attrDesc.AttributeName, len);
- {
- AttributeRecord key;
- key.m_key.m_name_ptr = attrDesc.AttributeName;
- key.m_key.m_name_len = len;
- key.attributeName.m_hash = name_hash;
- key.m_key.m_pool = &c_rope_pool;
- Ptr<AttributeRecord> old_ptr;
- c_attributeRecordHash.find(old_ptr, key);
-
- if(old_ptr.i != RNIL){
- parseP->errorCode = CreateTableRef::AttributeNameTwice;
- return;
- }
- }
-
- list.seize(attrPtr);
- if(attrPtr.i == RNIL){
- jam();
- parseP->errorCode = CreateTableRef::NoMoreAttributeRecords;
- return;
- }
-
- new (attrPtr.p) AttributeRecord();
- attrPtr.p->attributeDescriptor = 0x00012255; //Default value
- attrPtr.p->tupleKey = 0;
-
- /**
- * TmpAttrib to Attribute mapping
- */
- {
- Rope name(c_rope_pool, attrPtr.p->attributeName);
- if (!name.assign(attrDesc.AttributeName, len, name_hash))
- {
- jam();
- parseP->errorCode = CreateTableRef::OutOfStringBuffer;
- parseP->errorLine = __LINE__;
- return;
- }
- }
- attrPtr.p->attributeId = i;
- //attrPtr.p->attributeId = attrDesc.AttributeId;
- attrPtr.p->tupleKey = (keyCount + 1) * attrDesc.AttributeKeyFlag;
-
- 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)
- break;
- i++;
- }
- if (i == noOfCharsets) {
- noOfCharsets++;
- if (noOfCharsets > sizeof(charsets)/sizeof(charsets[0])) {
- parseP->errorCode = CreateTableRef::InvalidFormat;
- parseP->errorLine = __LINE__;
- return;
- }
- charsets[i] = csNumber;
- }
- }
-
- // compute attribute size and array size
- bool translateOk = attrDesc.translateExtType();
- tabRequire(translateOk, CreateTableRef::Inconsistency);
-
- if(attrDesc.AttributeArraySize > 65535){
- parseP->errorCode = CreateTableRef::ArraySizeTooBig;
- parseP->status = status;
- parseP->errorKey = it.getKey();
- parseP->errorLine = __LINE__;
- return;
- }
-
- // XXX old test option, remove
- if(!attrDesc.AttributeKeyFlag &&
- tablePtr.i > 1 &&
- !tablePtr.p->isIndex())
- {
- //attrDesc.AttributeStorageType= NDB_STORAGETYPE_DISK;
- }
-
- Uint32 desc = 0;
- AttributeDescriptor::setType(desc, attrDesc.AttributeExtType);
- AttributeDescriptor::setSize(desc, attrDesc.AttributeSize);
- AttributeDescriptor::setArraySize(desc, attrDesc.AttributeArraySize);
- AttributeDescriptor::setArrayType(desc, attrDesc.AttributeArrayType);
- AttributeDescriptor::setNullable(desc, attrDesc.AttributeNullableFlag);
- AttributeDescriptor::setDKey(desc, attrDesc.AttributeDKey);
- AttributeDescriptor::setPrimaryKey(desc, attrDesc.AttributeKeyFlag);
- AttributeDescriptor::setDiskBased(desc, attrDesc.AttributeStorageType == NDB_STORAGETYPE_DISK);
- attrPtr.p->attributeDescriptor = desc;
- attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
- {
- Rope defaultValue(c_rope_pool, attrPtr.p->defaultValue);
- defaultValue.assign(attrDesc.AttributeDefaultValue);
- }
-
- keyCount += attrDesc.AttributeKeyFlag;
- nullCount += attrDesc.AttributeNullableFlag;
-
- const Uint32 aSz = (1 << attrDesc.AttributeSize);
- 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){
- keyLength += sz;
-
- if(attrDesc.AttributeNullableFlag){
- parseP->errorCode = CreateTableRef::NullablePrimaryKey;
- parseP->status = status;
- parseP->errorKey = it.getKey();
- parseP->errorLine = __LINE__;
- return;
- }
- }
-
- c_attributeRecordHash.add(attrPtr);
-
- int a= AttributeDescriptor::getDiskBased(desc);
- int b= AttributeDescriptor::getArrayType(desc);
- Uint32 pos= 2*(a ? 1 : 0) + (b == NDB_ARRAYTYPE_FIXED ? 0 : 1);
- counts[pos+1]++;
-
- if(b != NDB_ARRAYTYPE_FIXED && sz == 0)
- {
- parseP->errorCode = CreateTableRef::VarsizeBitfieldNotSupported;
- parseP->status = status;
- parseP->errorKey = it.getKey();
- parseP->errorLine = __LINE__;
- return;
- }
-
- if(!it.next())
- break;
-
- if(it.getKey() != DictTabInfo::AttributeName)
- break;
- }//while
-
- tablePtr.p->noOfPrimkey = keyCount;
- 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);
- tabRequire(keyLength <= MAX_KEY_SIZE_IN_WORDS,
- CreateTableRef::InvalidPrimaryKeySize);
- tabRequire(keyLength > 0,
- CreateTableRef::InvalidPrimaryKeySize);
-
- if(tablePtr.p->m_tablespace_id != RNIL || counts[3] || counts[4])
- {
- FilegroupPtr tablespacePtr;
- if(!c_filegroup_hash.find(tablespacePtr, tablePtr.p->m_tablespace_id))
- {
- tabRequire(false, CreateTableRef::InvalidTablespace);
- }
-
- if(tablespacePtr.p->m_type != DictTabInfo::Tablespace)
- {
- tabRequire(false, CreateTableRef::NotATablespace);
- }
-
- if(tablespacePtr.p->m_version != tableDesc.TablespaceVersion)
- {
- tabRequire(false, CreateTableRef::InvalidTablespaceVersion);
- }
- }
-}//handleTabInfo()
-
-
-/* ---------------------------------------------------------------- */
-// DICTTABCONF is sent when participants have received all DICTTABINFO
-// and successfully handled it.
-// Also sent to self (DICT master) when index table creation ready.
-/* ---------------------------------------------------------------- */
-void Dbdict::execCREATE_TABLE_CONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 0);
-
- CreateTableConf * const conf = (CreateTableConf *)signal->getDataPtr();
- // assume part of create index operation
- OpCreateIndexPtr opPtr;
- c_opCreateIndex.find(opPtr, conf->senderData);
- ndbrequire(! opPtr.isNull());
- opPtr.p->m_request.setIndexId(conf->tableId);
- opPtr.p->m_request.setIndexVersion(conf->tableVersion);
- createIndex_fromCreateTable(signal, opPtr);
-}//execCREATE_TABLE_CONF()
-
-void Dbdict::execCREATE_TABLE_REF(Signal* signal)
-{
- jamEntry();
-
- CreateTableRef * const ref = (CreateTableRef *)signal->getDataPtr();
- // assume part of create index operation
- OpCreateIndexPtr opPtr;
- c_opCreateIndex.find(opPtr, ref->senderData);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- createIndex_fromCreateTable(signal, opPtr);
-}//execCREATE_TABLE_REF()
-
-/* ---------------------------------------------------------------- */
-// New global checkpoint created.
-/* ---------------------------------------------------------------- */
-void Dbdict::execWAIT_GCP_CONF(Signal* signal)
-{
-#if 0
- TableRecordPtr tablePtr;
- jamEntry();
- WaitGCPConf* const conf = (WaitGCPConf*)&signal->theData[0];
- c_tableRecordPool.getPtr(tablePtr, c_connRecord.connTableId);
- tablePtr.p->gciTableCreated = conf->gcp;
- sendUpdateSchemaState(signal,
- tablePtr.i,
- SchemaFile::TABLE_ADD_COMMITTED,
- c_connRecord.noOfPagesForTable,
- conf->gcp);
-#endif
-}//execWAIT_GCP_CONF()
-
-/* ---------------------------------------------------------------- */
-// Refused new global checkpoint.
-/* ---------------------------------------------------------------- */
-void Dbdict::execWAIT_GCP_REF(Signal* signal)
-{
- jamEntry();
- WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0];
-/* ---------------------------------------------------------------- */
-// Error Handling code needed
-/* ---------------------------------------------------------------- */
- char buf[32];
- BaseString::snprintf(buf, sizeof(buf), "WAIT_GCP_REF ErrorCode=%d",
- ref->errorCode);
- progError(__LINE__, NDBD_EXIT_NDBREQUIRE, buf);
-}//execWAIT_GCP_REF()
-
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: DROP TABLE -------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains the code used to drop a table. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-void
-Dbdict::execDROP_TABLE_REQ(Signal* signal){
- jamEntry();
- DropTableReq* req = (DropTableReq*)signal->getDataPtr();
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, req->tableId, false);
- if(tablePtr.isNull()){
- jam();
- dropTableRef(signal, req, DropTableRef::NoSuchTable);
- return;
- }
-
- if(getOwnNodeId() != c_masterNodeId){
- jam();
- dropTableRef(signal, req, DropTableRef::NotMaster);
- 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);
- return;
- }
-
- if (checkSingleUserMode(signal->getSendersBlockRef()))
- {
- jam();
- dropTableRef(signal, req, DropTableRef::SingleUser);
- return;
- }
-
- const TableRecord::TabState tabState = tablePtr.p->tabState;
- bool ok = false;
- switch(tabState){
- case TableRecord::NOT_DEFINED:
- case TableRecord::DEFINING:
- jam();
- dropTableRef(signal, req, DropTableRef::NoSuchTable);
- return;
- case TableRecord::DEFINED:
- ok = true;
- jam();
- break;
- case TableRecord::PREPARE_DROPPING:
- case TableRecord::DROPPING:
- jam();
- dropTableRef(signal, req, DropTableRef::DropInProgress);
- return;
- case TableRecord::BACKUP_ONGOING:
- jam();
- dropTableRef(signal, req, DropTableRef::BackupInProgress);
- return;
- }
- ndbrequire(ok);
-
- if(tablePtr.p->tableVersion != req->tableVersion){
- jam();
- dropTableRef(signal, req, DropTableRef::InvalidTableVersion);
- return;
- }
-
- /**
- * Seems ok
- */
- DropTableRecordPtr dropTabPtr;
- c_opDropTable.seize(dropTabPtr);
-
- if(dropTabPtr.isNull()){
- jam();
- dropTableRef(signal, req, DropTableRef::NoDropTableRecordAvailable);
- return;
- }
-
- c_blockState = BS_BUSY;
-
- dropTabPtr.p->key = ++c_opRecordSequence;
- c_opDropTable.add(dropTabPtr);
-
- dropTabPtr.p->m_request = * req;
- dropTabPtr.p->m_errorCode = 0;
- dropTabPtr.p->m_requestType = DropTabReq::OnlineDropTab;
- dropTabPtr.p->m_coordinatorRef = reference();
- dropTabPtr.p->m_coordinatorData.m_gsn = GSN_PREP_DROP_TAB_REQ;
- dropTabPtr.p->m_coordinatorData.m_block = 0;
-
- Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
- Callback c = { safe_cast(&Dbdict::dropTable_backup_mutex_locked),
- dropTabPtr.p->key};
-
- ndbrequire(mutex.lock(c));
-
-}
-
-void
-Dbdict::dropTable_backup_mutex_locked(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue){
- jamEntry();
-
- ndbrequire(retValue == 0);
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId, true);
-
- Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
- mutex.unlock(); // ignore response
-
- if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
- {
- jam();
- dropTableRef(signal, &dropTabPtr.p->m_request,
- DropTableRef::BackupInProgress);
-
- c_blockState = BS_IDLE;
- c_opDropTable.release(dropTabPtr);
- }
- else
- {
- jam();
- tablePtr.p->tabState = TableRecord::PREPARE_DROPPING;
- prepDropTab_nextStep(signal, dropTabPtr);
- }
-}
-
-void
-Dbdict::dropTableRef(Signal * signal,
- DropTableReq * req, DropTableRef::ErrorCode errCode){
-
- Uint32 tableId = req->tableId;
- Uint32 tabVersion = req->tableVersion;
- Uint32 senderData = req->senderData;
- Uint32 senderRef = req->senderRef;
-
- DropTableRef * ref = (DropTableRef*)signal->getDataPtrSend();
- ref->tableId = tableId;
- ref->tableVersion = tabVersion;
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->errorCode = errCode;
- ref->masterNodeId = c_masterNodeId;
- sendSignal(senderRef, GSN_DROP_TABLE_REF, signal,
- DropTableRef::SignalLength, JBB);
-}
-
-void
-Dbdict::prepDropTab_nextStep(Signal* signal, DropTableRecordPtr dropTabPtr){
-
- /**
- * No errors currently allowed
- */
- ndbrequire(dropTabPtr.p->m_errorCode == 0);
-
- Uint32 block = 0;
- switch(dropTabPtr.p->m_coordinatorData.m_block){
- case 0:
- jam();
- block = dropTabPtr.p->m_coordinatorData.m_block = DBDICT;
- break;
- case DBDICT:
- jam();
- block = dropTabPtr.p->m_coordinatorData.m_block = DBLQH;
- break;
- case DBLQH:
- jam();
- block = dropTabPtr.p->m_coordinatorData.m_block = DBTC;
- break;
- case DBTC:
- jam();
- block = dropTabPtr.p->m_coordinatorData.m_block = DBDIH;
- break;
- case DBDIH:
- jam();
- prepDropTab_complete(signal, dropTabPtr);
- return;
- default:
- ndbrequire(false);
- }
-
- PrepDropTabReq * prep = (PrepDropTabReq*)signal->getDataPtrSend();
- prep->senderRef = reference();
- prep->senderData = dropTabPtr.p->key;
- prep->tableId = dropTabPtr.p->m_request.tableId;
- prep->requestType = dropTabPtr.p->m_requestType;
-
- dropTabPtr.p->m_coordinatorData.m_signalCounter = c_aliveNodes;
- NodeReceiverGroup rg(block, c_aliveNodes);
- sendSignal(rg, GSN_PREP_DROP_TAB_REQ, signal,
- PrepDropTabReq::SignalLength, JBB);
-
-#if 0
- for (Uint32 i = 1; i < MAX_NDB_NODES; i++){
- if(c_aliveNodes.get(i)){
- jam();
- BlockReference ref = numberToRef(block, i);
-
- dropTabPtr.p->m_coordinatorData.m_signalCounter.setWaitingFor(i);
- }
- }
-#endif
-}
-
-void
-Dbdict::execPREP_DROP_TAB_CONF(Signal * signal){
- jamEntry();
-
- PrepDropTabConf * prep = (PrepDropTabConf*)signal->getDataPtr();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
-
- ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
- ndbrequire(dropTabPtr.p->m_request.tableId == prep->tableId);
- ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_PREP_DROP_TAB_REQ);
-
- Uint32 nodeId = refToNode(prep->senderRef);
- dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
-
- if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
- jam();
- return;
- }
- prepDropTab_nextStep(signal, dropTabPtr);
-}
-
-void
-Dbdict::execPREP_DROP_TAB_REF(Signal* signal){
- jamEntry();
-
- PrepDropTabRef * prep = (PrepDropTabRef*)signal->getDataPtr();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
-
- ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
- ndbrequire(dropTabPtr.p->m_request.tableId == prep->tableId);
- ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_PREP_DROP_TAB_REQ);
-
- Uint32 nodeId = refToNode(prep->senderRef);
- dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
-
- Uint32 block = refToBlock(prep->senderRef);
- if((prep->errorCode == PrepDropTabRef::NoSuchTable && block == DBLQH) ||
- (prep->errorCode == PrepDropTabRef::NF_FakeErrorREF)){
- jam();
- /**
- * Ignore errors:
- * 1) no such table and LQH, it might not exists in different LQH's
- * 2) node failure...
- */
- } else {
- dropTabPtr.p->setErrorCode((Uint32)prep->errorCode);
- }
-
- if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
- jam();
- return;
- }
- prepDropTab_nextStep(signal, dropTabPtr);
-}
-
-void
-Dbdict::prepDropTab_complete(Signal* signal, DropTableRecordPtr dropTabPtr){
- jam();
-
- dropTabPtr.p->m_coordinatorData.m_gsn = GSN_DROP_TAB_REQ;
- dropTabPtr.p->m_coordinatorData.m_block = DBDICT;
-
- DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = dropTabPtr.p->key;
- req->tableId = dropTabPtr.p->m_request.tableId;
- req->requestType = dropTabPtr.p->m_requestType;
-
- dropTabPtr.p->m_coordinatorData.m_signalCounter = c_aliveNodes;
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_DROP_TAB_REQ, signal,
- DropTabReq::SignalLength, JBB);
-}
-
-void
-Dbdict::execDROP_TAB_REF(Signal* signal){
- jamEntry();
-
- DropTabRef * const req = (DropTabRef*)signal->getDataPtr();
-
- Uint32 block = refToBlock(req->senderRef);
- ndbrequire(req->errorCode == DropTabRef::NF_FakeErrorREF ||
- (req->errorCode == DropTabRef::NoSuchTable &&
- (block == DBTUP || block == DBACC || block == DBLQH)));
-
- if(block != DBDICT){
- jam();
- ndbrequire(refToNode(req->senderRef) == getOwnNodeId());
- dropTab_localDROP_TAB_CONF(signal);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::execDROP_TAB_CONF(Signal* signal){
- jamEntry();
-
- DropTabConf * const req = (DropTabConf*)signal->getDataPtr();
-
- if(refToBlock(req->senderRef) != DBDICT){
- jam();
- ndbrequire(refToNode(req->senderRef) == getOwnNodeId());
- dropTab_localDROP_TAB_CONF(signal);
- return;
- }
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, req->senderData));
-
- ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
- ndbrequire(dropTabPtr.p->m_request.tableId == req->tableId);
- ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_DROP_TAB_REQ);
-
- Uint32 nodeId = refToNode(req->senderRef);
- dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
-
- if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
- jam();
- return;
- }
-
- DropTableConf* conf = (DropTableConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = dropTabPtr.p->m_request.senderData;
- conf->tableId = dropTabPtr.p->m_request.tableId;
- conf->tableVersion = dropTabPtr.p->m_request.tableVersion;
- Uint32 ref = dropTabPtr.p->m_request.senderRef;
- sendSignal(ref, GSN_DROP_TABLE_CONF, signal,
- DropTableConf::SignalLength, JBB);
-
- c_opDropTable.release(dropTabPtr);
- c_blockState = BS_IDLE;
-}
-
-/**
- * DROP TABLE PARTICIPANT CODE
- */
-void
-Dbdict::execPREP_DROP_TAB_REQ(Signal* signal){
- jamEntry();
- PrepDropTabReq * prep = (PrepDropTabReq*)signal->getDataPtrSend();
-
- DropTableRecordPtr dropTabPtr;
- if(prep->senderRef == reference()){
- jam();
- ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
- ndbrequire(dropTabPtr.p->m_requestType == prep->requestType);
- } else {
- jam();
- c_opDropTable.seize(dropTabPtr);
- if(!dropTabPtr.isNull()){
- dropTabPtr.p->key = prep->senderData;
- c_opDropTable.add(dropTabPtr);
- }
- }
-
- ndbrequire(!dropTabPtr.isNull());
-
- dropTabPtr.p->m_errorCode = 0;
- dropTabPtr.p->m_request.tableId = prep->tableId;
- dropTabPtr.p->m_requestType = prep->requestType;
- dropTabPtr.p->m_coordinatorRef = prep->senderRef;
- dropTabPtr.p->m_participantData.m_gsn = GSN_PREP_DROP_TAB_REQ;
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, prep->tableId);
- tablePtr.p->tabState = TableRecord::PREPARE_DROPPING;
-
- /**
- * Modify schema
- */
- 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 ||
- tabState == SchemaFile::TEMPORARY_TABLE_COMMITTED);
- tableEntry->m_tableState = SchemaFile::DROP_TABLE_STARTED;
- computeChecksum(xsf, tablePtr.i / NDB_SF_PAGE_ENTRIES);
-
- bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
- Callback callback;
- callback.m_callbackData = dropTabPtr.p->key;
- callback.m_callbackFunction = safe_cast(&Dbdict::prepDropTab_writeSchemaConf);
- if (savetodisk)
- {
- 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 = callback;
- startWriteSchemaFile(signal);
- }
- else
- {
- execute(signal, callback, 0);
- }
-}
-
-void
-Dbdict::prepDropTab_writeSchemaConf(Signal* signal,
- Uint32 dropTabPtrI,
- Uint32 returnCode){
- jam();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
-
- ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_PREP_DROP_TAB_REQ);
-
- /**
- * There probably should be node fail handlign here
- *
- * To check that coordinator hasn't died
- */
-
- PrepDropTabConf * prep = (PrepDropTabConf*)signal->getDataPtr();
- prep->senderRef = reference();
- prep->senderData = dropTabPtrI;
- prep->tableId = dropTabPtr.p->m_request.tableId;
-
- dropTabPtr.p->m_participantData.m_gsn = GSN_PREP_DROP_TAB_CONF;
- sendSignal(dropTabPtr.p->m_coordinatorRef, GSN_PREP_DROP_TAB_CONF, signal,
- PrepDropTabConf::SignalLength, JBB);
-}
-
-void
-Dbdict::execDROP_TAB_REQ(Signal* signal){
- jamEntry();
- DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, req->senderData));
-
- ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_PREP_DROP_TAB_CONF);
- dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
-
- ndbrequire(dropTabPtr.p->m_requestType == req->requestType);
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
- tablePtr.p->tabState = TableRecord::DROPPING;
-
- dropTabPtr.p->m_participantData.m_block = 0;
- dropTabPtr.p->m_participantData.m_callback.m_callbackData = dropTabPtr.p->key;
- dropTabPtr.p->m_participantData.m_callback.m_callbackFunction =
- safe_cast(&Dbdict::dropTab_complete);
- dropTab_nextStep(signal, dropTabPtr);
-
- if (tablePtr.p->m_tablespace_id != RNIL)
- {
- FilegroupPtr ptr;
- ndbrequire(c_filegroup_hash.find(ptr, tablePtr.p->m_tablespace_id));
- decrease_ref_count(ptr.p->m_obj_ptr_i);
- }
-}
-
-#include <DebuggerNames.hpp>
-
-void
-Dbdict::dropTab_nextStep(Signal* signal, DropTableRecordPtr dropTabPtr){
-
- /**
- * No errors currently allowed
- */
- ndbrequire(dropTabPtr.p->m_errorCode == 0);
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
-
- Uint32 block = 0;
- switch(dropTabPtr.p->m_participantData.m_block){
- case 0:
- jam();
- block = DBTC;
- break;
- case DBTC:
- jam();
- if (tablePtr.p->isTable() || tablePtr.p->isHashIndex())
- block = DBACC;
- if (tablePtr.p->isOrderedIndex())
- block = DBTUP;
- break;
- case DBACC:
- jam();
- block = DBTUP;
- break;
- case DBTUP:
- jam();
- if (tablePtr.p->isTable() || tablePtr.p->isHashIndex())
- block = DBLQH;
- if (tablePtr.p->isOrderedIndex())
- block = DBTUX;
- break;
- case DBTUX:
- jam();
- block = DBLQH;
- break;
- case DBLQH:
- jam();
- block = DBDIH;
- break;
- case DBDIH:
- jam();
- execute(signal, dropTabPtr.p->m_participantData.m_callback, 0);
- return;
- }
- ndbrequire(block != 0);
- dropTabPtr.p->m_participantData.m_block = block;
-
- DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = dropTabPtr.p->key;
- req->tableId = dropTabPtr.p->m_request.tableId;
- req->requestType = dropTabPtr.p->m_requestType;
-
- const Uint32 nodeId = getOwnNodeId();
- dropTabPtr.p->m_participantData.m_signalCounter.clearWaitingFor();
- dropTabPtr.p->m_participantData.m_signalCounter.setWaitingFor(nodeId);
- BlockReference ref = numberToRef(block, 0);
- sendSignal(ref, GSN_DROP_TAB_REQ, signal, DropTabReq::SignalLength, JBB);
-}
-
-void
-Dbdict::dropTab_localDROP_TAB_CONF(Signal* signal){
- jamEntry();
-
- DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, conf->senderData));
-
- ndbrequire(dropTabPtr.p->m_request.tableId == conf->tableId);
- ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_DROP_TAB_REQ);
-
- Uint32 nodeId = refToNode(conf->senderRef);
- dropTabPtr.p->m_participantData.m_signalCounter.clearWaitingFor(nodeId);
-
- if(!dropTabPtr.p->m_participantData.m_signalCounter.done()){
- jam();
- ndbrequire(false);
- return;
- }
- dropTab_nextStep(signal, dropTabPtr);
-}
-
-void
-Dbdict::dropTab_complete(Signal* signal,
- Uint32 dropTabPtrI,
- Uint32 returnCode){
- jam();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
-
- Uint32 tableId = dropTabPtr.p->m_request.tableId;
-
- /**
- * Write to schema file
- */
- 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(xsf, tableId / NDB_SF_PAGE_ENTRIES);
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
- Callback callback;
- callback.m_callbackData = dropTabPtr.p->key;
- callback.m_callbackFunction = safe_cast(&Dbdict::dropTab_writeSchemaConf);
- if (savetodisk)
- {
- 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 = callback;
- startWriteSchemaFile(signal);
- }
- else
- {
- execute(signal, callback, 0);
- }
-}
-
-void
-Dbdict::dropTab_writeSchemaConf(Signal* signal,
- Uint32 dropTabPtrI,
- Uint32 returnCode){
- jam();
-
- DropTableRecordPtr dropTabPtr;
- ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
-
- ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_DROP_TAB_REQ);
-
- dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_CONF;
-
- releaseTableObject(dropTabPtr.p->m_request.tableId);
-
- DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = dropTabPtrI;
- conf->tableId = dropTabPtr.p->m_request.tableId;
- {
- DropTabConf tmp= *conf;
- if (dropTabPtr.p->m_coordinatorRef == reference())
- conf->senderRef = dropTabPtr.p->m_request.senderRef;
- else
- conf->senderRef = 0;
- EXECUTE_DIRECT(SUMA, GSN_DROP_TAB_CONF, signal,
- DropTabConf::SignalLength);
- jamEntry();
- *conf= tmp;
- }
- dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_CONF;
- sendSignal(dropTabPtr.p->m_coordinatorRef, GSN_DROP_TAB_CONF, signal,
- DropTabConf::SignalLength, JBB);
-
- if(dropTabPtr.p->m_coordinatorRef != reference()){
- c_opDropTable.release(dropTabPtr);
- }
-}
-
-void Dbdict::releaseTableObject(Uint32 tableId, bool removeFromHash)
-{
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- if (removeFromHash)
- {
- jam();
- release_object(tablePtr.p->m_obj_ptr_i);
- }
- else
- {
- Rope tmp(c_rope_pool, tablePtr.p->tableName);
- tmp.erase();
- }
-
- {
- Rope tmp(c_rope_pool, tablePtr.p->frmData);
- tmp.erase();
- }
-
- {
- Rope tmp(c_rope_pool, tablePtr.p->tsData);
- tmp.erase();
- }
-
- {
- Rope tmp(c_rope_pool, tablePtr.p->ngData);
- tmp.erase();
- }
-
- {
- Rope tmp(c_rope_pool, tablePtr.p->rangeData);
- tmp.erase();
- }
-
- tablePtr.p->tabState = TableRecord::NOT_DEFINED;
-
- LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
- tablePtr.p->m_attributes);
- AttributeRecordPtr attrPtr;
- for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
- Rope name(c_rope_pool, attrPtr.p->attributeName);
- Rope def(c_rope_pool, attrPtr.p->defaultValue);
- name.erase();
- def.erase();
- }
- list.release();
-}//releaseTableObject()
-
-/**
- * DICT receives these on index create and drop.
- */
-void Dbdict::execDROP_TABLE_CONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 0);
-
- DropTableConf * const conf = (DropTableConf *)signal->getDataPtr();
- // assume part of drop index operation
- OpDropIndexPtr opPtr;
- c_opDropIndex.find(opPtr, conf->senderData);
- ndbrequire(! opPtr.isNull());
- ndbrequire(opPtr.p->m_request.getIndexId() == conf->tableId);
- ndbrequire(opPtr.p->m_request.getIndexVersion() == conf->tableVersion);
- dropIndex_fromDropTable(signal, opPtr);
-}
-
-void Dbdict::execDROP_TABLE_REF(Signal* signal)
-{
- jamEntry();
-
- DropTableRef * const ref = (DropTableRef *)signal->getDataPtr();
- // assume part of drop index operation
- OpDropIndexPtr opPtr;
- c_opDropIndex.find(opPtr, ref->senderData);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- opPtr.p->m_errorLine = __LINE__;
- dropIndex_fromDropTable(signal, opPtr);
-}
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* MODULE: EXTERNAL INTERFACE TO DATA -------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* This module contains the code that is used by other modules to. */
-/* access the data within DBDICT. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-void Dbdict::execGET_TABLEDID_REQ(Signal * signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 1);
- GetTableIdReq const * req = (GetTableIdReq *)signal->getDataPtr();
- Uint32 senderData = req->senderData;
- Uint32 senderRef = req->senderRef;
- Uint32 len = req->len;
-
- if(len>MAX_TAB_NAME_SIZE)
- {
- jam();
- sendGET_TABLEID_REF((Signal*)signal,
- (GetTableIdReq *)req,
- GetTableIdRef::TableNameTooLong);
- return;
- }
-
- char tableName[MAX_TAB_NAME_SIZE];
- SegmentedSectionPtr ssPtr;
- signal->getSection(ssPtr,GetTableIdReq::TABLE_NAME);
- copy((Uint32*)tableName, ssPtr);
- releaseSections(signal);
-
- DictObject * obj_ptr_p = get_object(tableName, len);
- if(obj_ptr_p == 0 || !DictTabInfo::isTable(obj_ptr_p->m_type)){
- jam();
- sendGET_TABLEID_REF(signal,
- (GetTableIdReq *)req,
- GetTableIdRef::TableNotDefined);
- return;
- }
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, obj_ptr_p->m_id);
-
- GetTableIdConf * conf = (GetTableIdConf *)req;
- conf->tableId = tablePtr.p->tableId;
- conf->schemaVersion = tablePtr.p->tableVersion;
- conf->senderData = senderData;
- sendSignal(senderRef, GSN_GET_TABLEID_CONF, signal,
- GetTableIdConf::SignalLength, JBB);
-}
-
-
-void Dbdict::sendGET_TABLEID_REF(Signal* signal,
- GetTableIdReq * req,
- GetTableIdRef::ErrorCode errorCode)
-{
- GetTableIdRef * const ref = (GetTableIdRef *)req;
- /**
- * The format of GetTabInfo Req/Ref is the same
- */
- BlockReference retRef = req->senderRef;
- ref->err = errorCode;
- sendSignal(retRef, GSN_GET_TABLEID_REF, signal,
- GetTableIdRef::SignalLength, JBB);
-}//sendGET_TABINFOREF()
-
-/* ---------------------------------------------------------------- */
-// Get a full table description.
-/* ---------------------------------------------------------------- */
-void Dbdict::execGET_TABINFOREQ(Signal* signal)
-{
- jamEntry();
- if(!assembleFragments(signal))
- {
- return;
- }
-
- GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
-
- /**
- * If I get a GET_TABINFO_REQ from myself
- * it's is a one from the time queue
- */
- bool fromTimeQueue = (signal->senderBlockRef() == reference());
-
- if (c_retrieveRecord.busyState && fromTimeQueue == true) {
- jam();
-
- sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
- signal->length());
- return;
- }//if
-
- const Uint32 MAX_WAITERS = 5;
-
- if(c_retrieveRecord.busyState && fromTimeQueue == false){
- jam();
- if(c_retrieveRecord.noOfWaiters < MAX_WAITERS){
- jam();
- c_retrieveRecord.noOfWaiters++;
-
- sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
- signal->length());
- return;
- }
-
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy);
- return;
- }
-
- if(fromTimeQueue){
- jam();
- c_retrieveRecord.noOfWaiters--;
- }
-
- const bool useLongSig = (req->requestType & GetTabInfoReq::LongSignalConf);
- const Uint32 reqType = req->requestType & (~GetTabInfoReq::LongSignalConf);
-
- Uint32 obj_id = RNIL;
- if(reqType == GetTabInfoReq::RequestByName){
- jam();
- ndbrequire(signal->getNoOfSections() == 1);
- const Uint32 len = req->tableNameLen;
-
- if(len > MAX_TAB_NAME_SIZE){
- jam();
- releaseSections(signal);
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNameTooLong);
- return;
- }
-
- char tableName[MAX_TAB_NAME_SIZE];
- SegmentedSectionPtr ssPtr;
- signal->getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
- r0.reset(); // undo implicit first()
- if(!r0.getWords((Uint32*)tableName, (len+3)/4)){
- jam();
- releaseSections(signal);
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
- return;
- }
- releaseSections(signal);
-
- DictObject * old_ptr_p = get_object(tableName, len);
- if(old_ptr_p)
- obj_id = old_ptr_p->m_id;
- } else {
- jam();
- obj_id = req->tableId;
- }
-
- SchemaFile::TableEntry *objEntry = 0;
- if(obj_id != RNIL){
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- objEntry = getTableEntry(xsf, obj_id);
- }
-
- // The table seached for was not found
- if(objEntry == 0){
- jam();
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
- return;
- }//if
-
- // If istable/index, allow ADD_STARTED (not to ref)
-
- if (objEntry->m_tableState != SchemaFile::TABLE_ADD_COMMITTED &&
- objEntry->m_tableState != SchemaFile::ALTER_TABLE_COMMITTED &&
- objEntry->m_tableState != SchemaFile::TEMPORARY_TABLE_COMMITTED){
- jam();
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
- return;
- }//if
-
- if (DictTabInfo::isTable(objEntry->m_tableType) ||
- DictTabInfo::isIndex(objEntry->m_tableType))
- {
- jam();
- TableRecordPtr tabPtr;
- c_tableRecordPool.getPtr(tabPtr, obj_id);
- if (tabPtr.p->tabState != TableRecord::DEFINED &&
- tabPtr.p->tabState != TableRecord::BACKUP_ONGOING)
- {
- jam();
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
- return;
- }
- ndbrequire(objEntry->m_tableState == SchemaFile::TEMPORARY_TABLE_COMMITTED ||
- !(tabPtr.p->m_bits & TableRecord::TR_Temporary));
- }
-
- c_retrieveRecord.busyState = true;
- c_retrieveRecord.blockRef = req->senderRef;
- c_retrieveRecord.m_senderData = req->senderData;
- c_retrieveRecord.tableId = obj_id;
- c_retrieveRecord.currentSent = 0;
- c_retrieveRecord.m_useLongSig = useLongSig;
- c_retrieveRecord.m_table_type = objEntry->m_tableType;
- c_packTable.m_state = PackTable::PTS_GET_TAB;
-
- if(objEntry->m_tableType==DictTabInfo::Datafile)
- {
- jam();
- GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
- req->senderData= c_retrieveRecord.retrievePage;
- req->senderRef= reference();
- req->requestType= GetTabInfoReq::RequestById;
- req->tableId= obj_id;
-
- sendSignal(TSMAN_REF, GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB);
- }
- else if(objEntry->m_tableType==DictTabInfo::LogfileGroup)
- {
- jam();
- GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
- req->senderData= c_retrieveRecord.retrievePage;
- req->senderRef= reference();
- req->requestType= GetTabInfoReq::RequestById;
- req->tableId= obj_id;
-
- sendSignal(LGMAN_REF, GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB);
- }
- else
- {
- jam();
- signal->theData[0] = ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = obj_id;
- signal->theData[2] = objEntry->m_tableType;
- signal->theData[3] = c_retrieveRecord.retrievePage;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
- }
- jam();
-}//execGET_TABINFOREQ()
-
-void Dbdict::sendGetTabResponse(Signal* signal)
-{
- PageRecordPtr pagePtr;
- DictTabInfo * const conf = (DictTabInfo *)&signal->theData[0];
- conf->senderRef = reference();
- conf->senderData = c_retrieveRecord.m_senderData;
- conf->requestType = DictTabInfo::GetTabInfoConf;
- conf->totalLen = c_retrieveRecord.retrievedNoOfWords;
-
- c_pageRecordArray.getPtr(pagePtr, c_retrieveRecord.retrievePage);
- Uint32* pagePointer = (Uint32*)&pagePtr.p->word[0] + ZPAGE_HEADER_SIZE;
-
- if(c_retrieveRecord.m_useLongSig){
- jam();
- GetTabInfoConf* conf = (GetTabInfoConf*)signal->getDataPtr();
- conf->gci = 0;
- conf->tableId = c_retrieveRecord.tableId;
- conf->senderData = c_retrieveRecord.m_senderData;
- conf->totalLen = c_retrieveRecord.retrievedNoOfWords;
- conf->tableType = c_retrieveRecord.m_table_type;
-
- Callback c = { safe_cast(&Dbdict::initRetrieveRecord), 0 };
- LinearSectionPtr ptr[3];
- ptr[0].p = pagePointer;
- ptr[0].sz = c_retrieveRecord.retrievedNoOfWords;
- sendFragmentedSignal(c_retrieveRecord.blockRef,
- GSN_GET_TABINFO_CONF,
- signal,
- GetTabInfoConf::SignalLength,
- JBB,
- ptr,
- 1,
- c);
- return;
- }
-
- ndbrequire(false);
-}//sendGetTabResponse()
-
-void Dbdict::sendGET_TABINFOREF(Signal* signal,
- GetTabInfoReq * req,
- GetTabInfoRef::ErrorCode errorCode)
-{
- jamEntry();
- GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
- /**
- * The format of GetTabInfo Req/Ref is the same
- */
- BlockReference retRef = req->senderRef;
- ref->errorCode = errorCode;
-
- sendSignal(retRef, GSN_GET_TABINFOREF, signal, signal->length(), JBB);
-}//sendGET_TABINFOREF()
-
-void
-Dbdict::execLIST_TABLES_REQ(Signal* signal)
-{
- jamEntry();
- ListTablesReq * req = (ListTablesReq*)signal->getDataPtr();
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- // save req flags
- const Uint32 reqTableId = req->getTableId();
- const Uint32 reqTableType = req->getTableType();
- const bool reqListNames = req->getListNames();
- const bool reqListIndexes = req->getListIndexes();
- // init the confs
- ListTablesConf * conf = (ListTablesConf *)signal->getDataPtrSend();
- conf->senderData = senderData;
- conf->counter = 0;
- Uint32 pos = 0;
-
- DLHashTable<DictObject>::Iterator iter;
- bool ok = c_obj_hash.first(iter);
- for(; ok; ok = c_obj_hash.next(iter)){
- Uint32 type = iter.curr.p->m_type;
- if ((reqTableType != (Uint32)0) && (reqTableType != type))
- continue;
-
- if (reqListIndexes && !DictTabInfo::isIndex(type))
- continue;
-
- TableRecordPtr tablePtr;
- if (DictTabInfo::isTable(type) || DictTabInfo::isIndex(type)){
- c_tableRecordPool.getPtr(tablePtr, iter.curr.p->m_id);
-
- if(reqListIndexes && (reqTableId != tablePtr.p->primaryTableId))
- continue;
-
- conf->tableData[pos] = 0;
- conf->setTableId(pos, tablePtr.i); // id
- conf->setTableType(pos, type); // type
- // state
-
- if(DictTabInfo::isTable(type)){
- switch (tablePtr.p->tabState) {
- case TableRecord::DEFINING:
- conf->setTableState(pos, DictTabInfo::StateBuilding);
- break;
- case TableRecord::PREPARE_DROPPING:
- case TableRecord::DROPPING:
- conf->setTableState(pos, DictTabInfo::StateDropping);
- break;
- case TableRecord::DEFINED:
- conf->setTableState(pos, DictTabInfo::StateOnline);
- break;
- case TableRecord::BACKUP_ONGOING:
- conf->setTableState(pos, DictTabInfo::StateBackup);
- break;
- default:
- conf->setTableState(pos, DictTabInfo::StateBroken);
- break;
- }
- }
- if (tablePtr.p->isIndex()) {
- switch (tablePtr.p->indexState) {
- case TableRecord::IS_OFFLINE:
- conf->setTableState(pos, DictTabInfo::StateOffline);
- break;
- case TableRecord::IS_BUILDING:
- conf->setTableState(pos, DictTabInfo::StateBuilding);
- break;
- case TableRecord::IS_DROPPING:
- conf->setTableState(pos, DictTabInfo::StateDropping);
- break;
- case TableRecord::IS_ONLINE:
- conf->setTableState(pos, DictTabInfo::StateOnline);
- break;
- default:
- conf->setTableState(pos, DictTabInfo::StateBroken);
- break;
- }
- }
- // Logging status
- if (! (tablePtr.p->m_bits & TableRecord::TR_Logged)) {
- conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
- } else {
- conf->setTableStore(pos, DictTabInfo::StorePermanent);
- }
- // Temporary status
- if (tablePtr.p->m_bits & TableRecord::TR_Temporary) {
- conf->setTableTemp(pos, NDB_TEMP_TAB_TEMPORARY);
- } else {
- conf->setTableTemp(pos, NDB_TEMP_TAB_PERMANENT);
- }
- pos++;
- }
- if(DictTabInfo::isTrigger(type)){
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, iter.curr.p->m_id);
-
- conf->tableData[pos] = 0;
- conf->setTableId(pos, triggerPtr.i);
- conf->setTableType(pos, type);
- switch (triggerPtr.p->triggerState) {
- case TriggerRecord::TS_OFFLINE:
- conf->setTableState(pos, DictTabInfo::StateOffline);
- break;
- case TriggerRecord::TS_ONLINE:
- conf->setTableState(pos, DictTabInfo::StateOnline);
- break;
- default:
- conf->setTableState(pos, DictTabInfo::StateBroken);
- break;
- }
- conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
- pos++;
- }
- if (DictTabInfo::isFilegroup(type)){
- jam();
- conf->tableData[pos] = 0;
- conf->setTableId(pos, iter.curr.p->m_id);
- conf->setTableType(pos, type); // type
- conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
- pos++;
- }
- if (DictTabInfo::isFile(type)){
- jam();
- conf->tableData[pos] = 0;
- conf->setTableId(pos, iter.curr.p->m_id);
- conf->setTableType(pos, type); // type
- conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
- pos++;
- }
-
- if (pos >= ListTablesConf::DataLength) {
- sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::SignalLength, JBB);
- conf->counter++;
- pos = 0;
- }
-
- if (! reqListNames)
- continue;
-
- Rope name(c_rope_pool, iter.curr.p->m_name);
- const Uint32 size = name.size();
- conf->tableData[pos] = size;
- pos++;
- if (pos >= ListTablesConf::DataLength) {
- sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::SignalLength, JBB);
- conf->counter++;
- pos = 0;
- }
- Uint32 i = 0;
- char tmp[MAX_TAB_NAME_SIZE];
- name.copy(tmp);
- while (i < size) {
- char* p = (char*)&conf->tableData[pos];
- for (Uint32 j = 0; j < 4; j++) {
- if (i < size)
- *p++ = tmp[i++];
- else
- *p++ = 0;
- }
- pos++;
- if (pos >= ListTablesConf::DataLength) {
- sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::SignalLength, JBB);
- conf->counter++;
- pos = 0;
- }
- }
- }
- // last signal must have less than max length
- sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::HeaderLength + pos, JBB);
-}
-
-/**
- * MODULE: Create index
- *
- * Create index in DICT via create table operation. Then invoke alter
- * index opearation to online the index.
- *
- * Request type in CREATE_INDX signals:
- *
- * RT_USER - from API to DICT master
- * RT_DICT_PREPARE - prepare participants
- * RT_DICT_COMMIT - commit participants
- * RT_TC - create index in TC (part of alter index operation)
- */
-
-void
-Dbdict::execCREATE_INDX_REQ(Signal* signal)
-{
- jamEntry();
- CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
- OpCreateIndexPtr opPtr;
- const Uint32 senderRef = signal->senderBlockRef();
- const CreateIndxReq::RequestType requestType = req->getRequestType();
- if (requestType == CreateIndxReq::RT_USER) {
- jam();
- if (! assembleFragments(signal)) {
- jam();
- return;
- }
- if (signal->getLength() == CreateIndxReq::SignalLength) {
- jam();
- CreateIndxRef::ErrorCode tmperr = CreateIndxRef::NoError;
- if (getOwnNodeId() != c_masterNodeId) {
- jam();
- tmperr = CreateIndxRef::NotMaster;
- } else if (c_blockState == BS_NODE_RESTART) {
- jam();
- tmperr = CreateIndxRef::BusyWithNR;
- } else if (c_blockState != BS_IDLE) {
- jam();
- tmperr = CreateIndxRef::Busy;
- }
- else if (checkSingleUserMode(senderRef))
- {
- jam();
- tmperr = CreateIndxRef::SingleUser;
- }
- if (tmperr != CreateIndxRef::NoError) {
- releaseSections(signal);
- OpCreateIndex opBusy;
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = 0;
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE;
- opPtr.p->m_errorCode = tmperr;
- opPtr.p->m_errorLine = __LINE__;
- opPtr.p->m_errorNode = c_masterNodeId;
- createIndex_sendReply(signal, opPtr, true);
- return;
- }
- // forward initial request plus operation key to all
- req->setOpKey(++c_opRecordSequence);
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_CREATE_INDX_REQ,
- signal, CreateIndxReq::SignalLength + 1, JBB);
- return;
- }
- // seize operation record
- ndbrequire(signal->getLength() == CreateIndxReq::SignalLength + 1);
- const Uint32 opKey = req->getOpKey();
- OpCreateIndex opBusy;
- if (! c_opCreateIndex.seize(opPtr))
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_coordinatorRef = senderRef;
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = opKey;
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE;
- if (opPtr.p == &opBusy) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::Busy;
- opPtr.p->m_errorLine = __LINE__;
- releaseSections(signal);
- createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- c_opCreateIndex.add(opPtr);
- // save attribute list
- SegmentedSectionPtr ssPtr;
- signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
- r0.reset(); // undo implicit first()
- if (! r0.getWord(&opPtr.p->m_attrList.sz) ||
- ! r0.getWords(opPtr.p->m_attrList.id, opPtr.p->m_attrList.sz)) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidName;
- opPtr.p->m_errorLine = __LINE__;
- releaseSections(signal);
- createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- // save name and index table properties
- signal->getSection(ssPtr, CreateIndxReq::INDEX_NAME_SECTION);
- SimplePropertiesSectionReader r1(ssPtr, getSectionSegmentPool());
- c_tableDesc.init();
- SimpleProperties::UnpackStatus status = SimpleProperties::unpack(
- r1, &c_tableDesc,
- DictTabInfo::TableMapping, DictTabInfo::TableMappingSize,
- true, true);
- if (status != SimpleProperties::Eof) {
- opPtr.p->m_errorCode = CreateIndxRef::InvalidName;
- opPtr.p->m_errorLine = __LINE__;
- releaseSections(signal);
- createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- memcpy(opPtr.p->m_indexName, c_tableDesc.TableName, MAX_TAB_NAME_SIZE);
- opPtr.p->m_loggedIndex = c_tableDesc.TableLoggedFlag;
- opPtr.p->m_temporaryIndex = c_tableDesc.TableTemporaryFlag;
- releaseSections(signal);
- // master expects to hear from all
- if (opPtr.p->m_isMaster)
- opPtr.p->m_signalCounter = c_aliveNodes;
- createIndex_slavePrepare(signal, opPtr);
- createIndex_sendReply(signal, opPtr, false);
- return;
- }
- c_opCreateIndex.find(opPtr, req->getConnectionPtr());
- if (! opPtr.isNull()) {
- opPtr.p->m_requestType = requestType;
- if (requestType == CreateIndxReq::RT_DICT_COMMIT ||
- requestType == CreateIndxReq::RT_DICT_ABORT) {
- jam();
- if (requestType == CreateIndxReq::RT_DICT_COMMIT) {
- opPtr.p->m_request.setIndexId(req->getIndexId());
- opPtr.p->m_request.setIndexVersion(req->getIndexVersion());
- createIndex_slaveCommit(signal, opPtr);
- } else {
- createIndex_slaveAbort(signal, opPtr);
- }
- createIndex_sendReply(signal, opPtr, false);
- // done in slave
- if (! opPtr.p->m_isMaster)
- c_opCreateIndex.release(opPtr);
- return;
- }
- }
- jam();
- // return to sender
- releaseSections(signal);
- OpCreateIndex opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
- opPtr.p->m_errorLine = __LINE__;
- createIndex_sendReply(signal, opPtr, true);
-}
-
-void
-Dbdict::execCREATE_INDX_CONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 0);
- CreateIndxConf* conf = (CreateIndxConf*)signal->getDataPtrSend();
- createIndex_recvReply(signal, conf, 0);
-}
-
-void
-Dbdict::execCREATE_INDX_REF(Signal* signal)
-{
- jamEntry();
- CreateIndxRef* ref = (CreateIndxRef*)signal->getDataPtrSend();
- createIndex_recvReply(signal, ref->getConf(), ref);
-}
-
-void
-Dbdict::createIndex_recvReply(Signal* signal, const CreateIndxConf* conf,
- const CreateIndxRef* ref)
-{
- jam();
- const Uint32 senderRef = signal->senderBlockRef();
- const CreateIndxReq::RequestType requestType = conf->getRequestType();
- const Uint32 key = conf->getConnectionPtr();
- if (requestType == CreateIndxReq::RT_TC) {
- jam();
- // part of alter index operation
- OpAlterIndexPtr opPtr;
- c_opAlterIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- alterIndex_fromCreateTc(signal, opPtr);
- return;
- }
- OpCreateIndexPtr opPtr;
- c_opCreateIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- ndbrequire(opPtr.p->m_isMaster);
- ndbrequire(opPtr.p->m_requestType == requestType);
- opPtr.p->setError(ref);
- opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
- if (! opPtr.p->m_signalCounter.done()) {
- jam();
- return;
- }
- if (requestType == CreateIndxReq::RT_DICT_COMMIT ||
- requestType == CreateIndxReq::RT_DICT_ABORT) {
- jam();
- // send reply to user
- createIndex_sendReply(signal, opPtr, true);
- c_opCreateIndex.release(opPtr);
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
- createIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == CreateIndxReq::RT_DICT_PREPARE) {
- jam();
- // start index table create
- createIndex_toCreateTable(signal, opPtr);
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
- createIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- return;
- }
- ndbrequire(false);
-}
-
-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)
-{
- union {
- char tableName[MAX_TAB_NAME_SIZE];
- char attributeName[MAX_ATTR_NAME_SIZE];
- };
- Uint32 k;
- Uint32 attrid_map[MAX_ATTRIBUTES_IN_INDEX];
-
- jam();
- const CreateIndxReq* const req = &opPtr.p->m_request;
- // signal data writer
- Uint32* wbuffer = &c_indexPage.word[0];
- LinearWriter w(wbuffer, sizeof(c_indexPage) >> 2);
- w.first();
- // get table being indexed
- if (! (req->getTableId() < c_tableRecordPool.getSize())) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, req->getTableId());
- if (tablePtr.p->tabState != TableRecord::DEFINED &&
- tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- if (! tablePtr.p->isTable()) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
-
- // Check that the temporary status of index is compatible with table.
- if (!opPtr.p->m_temporaryIndex &&
- tablePtr.p->m_bits & TableRecord::TR_Temporary)
- {
- jam();
- opPtr.p->m_errorCode= CreateIndxRef::TableIsTemporary;
- opPtr.p->m_errorLine= __LINE__;
- return;
- }
- if (opPtr.p->m_temporaryIndex &&
- !(tablePtr.p->m_bits & TableRecord::TR_Temporary))
- {
- // This could be implemented later, but mysqld does currently not detect
- // that the index disappears after SR, and it appears not too useful.
- jam();
- opPtr.p->m_errorCode= CreateIndxRef::TableIsNotTemporary;
- opPtr.p->m_errorLine= __LINE__;
- return;
- }
- if (opPtr.p->m_temporaryIndex && opPtr.p->m_loggedIndex)
- {
- jam();
- opPtr.p->m_errorCode= CreateIndxRef::NoLoggingTemporaryIndex;
- opPtr.p->m_errorLine= __LINE__;
- return;
- }
-
- // compute index table record
- TableRecord indexRec;
- TableRecordPtr indexPtr;
- indexPtr.i = RNIL; // invalid
- indexPtr.p = &indexRec;
- initialiseTableRecord(indexPtr);
- indexPtr.p->m_bits = TableRecord::TR_RowChecksum;
- if (req->getIndexType() == DictTabInfo::UniqueHashIndex) {
- indexPtr.p->m_bits |= (opPtr.p->m_loggedIndex ? TableRecord::TR_Logged:0);
- indexPtr.p->m_bits |=
- (opPtr.p->m_temporaryIndex ? TableRecord::TR_Temporary : 0);
- indexPtr.p->fragmentType = DictTabInfo::DistrKeyUniqueHashIndex;
- } else if (req->getIndexType() == DictTabInfo::OrderedIndex) {
- // first version will not supported logging
- if (opPtr.p->m_loggedIndex) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- indexPtr.p->m_bits |=
- (opPtr.p->m_temporaryIndex ? TableRecord::TR_Temporary : 0);
- indexPtr.p->fragmentType = DictTabInfo::DistrKeyOrderedIndex;
- } else {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- indexPtr.p->tableType = (DictTabInfo::TableType)req->getIndexType();
- indexPtr.p->primaryTableId = req->getTableId();
- indexPtr.p->noOfAttributes = opPtr.p->m_attrList.sz;
- indexPtr.p->tupKeyLength = 0;
- if (indexPtr.p->noOfAttributes == 0) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
-
- if (indexPtr.p->isOrderedIndex()) {
- // tree node size in words (make configurable later)
- indexPtr.p->tupKeyLength = MAX_TTREE_NODE_SIZE;
- }
-
- AttributeMask mask;
- mask.clear();
- for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
- jam();
- unsigned current_id= opPtr.p->m_attrList.id[k];
- Uint32 tAttr = tablePtr.p->m_attributes.firstItem;
- AttributeRecord* aRec = NULL;
- for (; tAttr != RNIL; )
- {
- aRec = c_attributeRecordPool.getPtr(tAttr);
- if (aRec->attributeId != current_id)
- {
- tAttr= aRec->nextList;
- continue;
- }
- jam();
- break;
- }
- if (tAttr == RNIL) {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- if (mask.get(current_id))
- {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::DuplicateAttributes;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- const Uint32 a = aRec->attributeDescriptor;
-
- if (AttributeDescriptor::getDiskBased(a))
- {
- jam();
- opPtr.p->m_errorCode = CreateIndxRef::IndexOnDiskAttributeError;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
-
- mask.set(current_id);
- 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;
-
- 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
- indexPtr.p->noOfAttributes += 1;
- indexPtr.p->noOfNullAttr = 0;
- // write index table
- w.add(DictTabInfo::TableName, opPtr.p->m_indexName);
- w.add(DictTabInfo::TableLoggedFlag, !!(indexPtr.p->m_bits & TableRecord::TR_Logged));
- w.add(DictTabInfo::TableTemporaryFlag, !!(indexPtr.p->m_bits & TableRecord::TR_Temporary));
- w.add(DictTabInfo::FragmentTypeVal, indexPtr.p->fragmentType);
- w.add(DictTabInfo::TableTypeVal, indexPtr.p->tableType);
- Rope name(c_rope_pool, tablePtr.p->tableName);
- name.copy(tableName);
- w.add(DictTabInfo::PrimaryTable, tableName);
- w.add(DictTabInfo::PrimaryTableId, tablePtr.i);
- w.add(DictTabInfo::NoOfAttributes, indexPtr.p->noOfAttributes);
- w.add(DictTabInfo::NoOfKeyAttr, indexPtr.p->noOfPrimkey);
- w.add(DictTabInfo::NoOfNullable, indexPtr.p->noOfNullAttr);
- w.add(DictTabInfo::KeyLength, indexPtr.p->tupKeyLength);
- w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
- // write index key attributes
- 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->m_attributes.firstItem; tAttr != RNIL; ) {
- AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
- tAttr = aRec->nextList;
- if (aRec->attributeId != current_id)
- continue;
- jam();
- const Uint32 a = aRec->attributeDescriptor;
- bool isNullable = AttributeDescriptor::getNullable(a);
- Uint32 arrayType = AttributeDescriptor::getArrayType(a);
- Rope attrName(c_rope_pool, aRec->attributeName);
- attrName.copy(attributeName);
- w.add(DictTabInfo::AttributeName, attributeName);
- Uint32 attrType = AttributeDescriptor::getType(a);
- // computed
- w.add(DictTabInfo::AttributeId, k);
- if (indexPtr.p->isHashIndex()) {
- w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
- w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
- }
- if (indexPtr.p->isOrderedIndex()) {
- w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
- w.add(DictTabInfo::AttributeNullableFlag, (Uint32)isNullable);
- }
- w.add(DictTabInfo::AttributeArrayType, arrayType);
- w.add(DictTabInfo::AttributeExtType, attrType);
- w.add(DictTabInfo::AttributeExtPrecision, aRec->extPrecision);
- w.add(DictTabInfo::AttributeExtScale, aRec->extScale);
- w.add(DictTabInfo::AttributeExtLength, aRec->extLength);
- w.add(DictTabInfo::AttributeEnd, (Uint32)true);
- }
- }
- if (indexPtr.p->isHashIndex()) {
- jam();
-
- Uint32 key_type = NDB_ARRAYTYPE_FIXED;
- AttributeRecordPtr attrPtr;
- LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
- tablePtr.p->m_attributes);
- for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
- {
- const Uint32 desc = attrPtr.p->attributeDescriptor;
- if (AttributeDescriptor::getPrimaryKey(desc) &&
- AttributeDescriptor::getArrayType(desc) != NDB_ARRAYTYPE_FIXED)
- {
- key_type = NDB_ARRAYTYPE_MEDIUM_VAR;
- break;
- }
- }
-
- // write concatenated primary table key attribute i.e. keyinfo
- w.add(DictTabInfo::AttributeName, "NDB$PK");
- w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
- w.add(DictTabInfo::AttributeArrayType, key_type);
- w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
- w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
- w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
- w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength+1);
- w.add(DictTabInfo::AttributeEnd, (Uint32)true);
- }
- if (indexPtr.p->isOrderedIndex()) {
- jam();
- // write index tree node as Uint32 array attribute
- w.add(DictTabInfo::AttributeName, "NDB$TNODE");
- w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
- // should not matter but VAR crashes in TUP
- w.add(DictTabInfo::AttributeArrayType, (Uint32)NDB_ARRAYTYPE_FIXED);
- w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
- w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
- w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
- w.add(DictTabInfo::AttributeExtLength, indexPtr.p->tupKeyLength);
- w.add(DictTabInfo::AttributeEnd, (Uint32)true);
- }
- // finish
- w.add(DictTabInfo::TableEnd, (Uint32)true);
- // remember to...
- releaseSections(signal);
- // send create index table request
- CreateTableReq * const cre = (CreateTableReq*)signal->getDataPtrSend();
- cre->senderRef = reference();
- cre->senderData = opPtr.p->key;
- LinearSectionPtr lsPtr[3];
- lsPtr[0].p = wbuffer;
- lsPtr[0].sz = w.getWordsUsed();
- sendSignal(DBDICT_REF, GSN_CREATE_TABLE_REQ,
- signal, CreateTableReq::SignalLength, JBB, lsPtr, 1);
-}
-
-void
-Dbdict::createIndex_fromCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
- createIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- if (! opPtr.p->m_request.getOnline()) {
- jam();
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_COMMIT;
- createIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- createIndex_toAlterIndex(signal, opPtr);
-}
-
-void
-Dbdict::createIndex_toAlterIndex(Signal* signal, OpCreateIndexPtr opPtr)
-{
- jam();
- AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(AlterIndxReq::RT_CREATE_INDEX);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- req->setTableId(opPtr.p->m_request.getTableId());
- req->setIndexId(opPtr.p->m_request.getIndexId());
- req->setIndexVersion(opPtr.p->m_request.getIndexVersion());
- req->setOnline(true);
- sendSignal(reference(), GSN_ALTER_INDX_REQ,
- signal, AlterIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::createIndex_fromAlterIndex(Signal* signal, OpCreateIndexPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
- createIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = CreateIndxReq::RT_DICT_COMMIT;
- createIndex_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::createIndex_slaveCommit(Signal* signal, OpCreateIndexPtr opPtr)
-{
- jam();
- const Uint32 indexId = opPtr.p->m_request.getIndexId();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, indexId);
- if (! opPtr.p->m_request.getOnline()) {
- ndbrequire(indexPtr.p->indexState == TableRecord::IS_UNDEFINED);
- indexPtr.p->indexState = TableRecord::IS_OFFLINE;
- } else {
- ndbrequire(indexPtr.p->indexState == TableRecord::IS_ONLINE);
- }
-}
-
-void
-Dbdict::createIndex_slaveAbort(Signal* signal, OpCreateIndexPtr opPtr)
-{
- jam();
- CreateIndxReq* const req = &opPtr.p->m_request;
- const Uint32 indexId = req->getIndexId();
- if (indexId >= c_tableRecordPool.getSize()) {
- jam();
- return;
- }
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, indexId);
- if (! indexPtr.p->isIndex()) {
- jam();
- return;
- }
- indexPtr.p->indexState = TableRecord::IS_BROKEN;
-}
-
-void
-Dbdict::createIndex_sendSlaveReq(Signal* signal, OpCreateIndexPtr opPtr)
-{
- jam();
- CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
- *req = opPtr.p->m_request;
- req->setUserRef(opPtr.p->m_coordinatorRef);
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(opPtr.p->m_requestType);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- opPtr.p->m_signalCounter = c_aliveNodes;
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_CREATE_INDX_REQ,
- signal, CreateIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::createIndex_sendReply(Signal* signal, OpCreateIndexPtr opPtr,
- bool toUser)
-{
- CreateIndxRef* rep = (CreateIndxRef*)signal->getDataPtrSend();
- Uint32 gsn = GSN_CREATE_INDX_CONF;
- Uint32 length = CreateIndxConf::InternalLength;
- bool sendRef;
- if (! toUser) {
- sendRef = opPtr.p->hasLastError();
- rep->setUserRef(opPtr.p->m_coordinatorRef);
- rep->setConnectionPtr(opPtr.p->key);
- rep->setRequestType(opPtr.p->m_requestType);
- if (opPtr.p->m_requestType == CreateIndxReq::RT_DICT_ABORT)
- sendRef = false;
- } else {
- sendRef = opPtr.p->hasError();
- rep->setUserRef(opPtr.p->m_request.getUserRef());
- rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
- rep->setRequestType(opPtr.p->m_request.getRequestType());
- length = CreateIndxConf::SignalLength;
- }
- rep->setTableId(opPtr.p->m_request.getTableId());
- rep->setIndexId(opPtr.p->m_request.getIndexId());
- rep->setIndexVersion(opPtr.p->m_request.getIndexVersion());
- if (sendRef) {
- if (opPtr.p->m_errorNode == 0)
- opPtr.p->m_errorNode = getOwnNodeId();
- rep->setErrorCode(opPtr.p->m_errorCode);
- rep->setErrorLine(opPtr.p->m_errorLine);
- rep->setErrorNode(opPtr.p->m_errorNode);
- gsn = GSN_CREATE_INDX_REF;
- length = CreateIndxRef::SignalLength;
- }
- sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
-}
-
-/**
- * MODULE: Drop index.
- *
- * Drop index. First alters the index offline (i.e. drops metadata in
- * other blocks) and then drops the index table.
- */
-
-void
-Dbdict::execDROP_INDX_REQ(Signal* signal)
-{
- jamEntry();
- DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
- OpDropIndexPtr opPtr;
-
- int err = DropIndxRef::BadRequestType;
- const Uint32 senderRef = signal->senderBlockRef();
- const DropIndxReq::RequestType requestType = req->getRequestType();
- if (requestType == DropIndxReq::RT_USER) {
- jam();
- if (signal->getLength() == DropIndxReq::SignalLength) {
- jam();
- DropIndxRef::ErrorCode tmperr = DropIndxRef::NoError;
- if (getOwnNodeId() != c_masterNodeId) {
- jam();
- tmperr = DropIndxRef::NotMaster;
- } else if (c_blockState == BS_NODE_RESTART) {
- jam();
- tmperr = DropIndxRef::BusyWithNR;
- } else if (c_blockState != BS_IDLE) {
- jam();
- tmperr = DropIndxRef::Busy;
- }
- else if (checkSingleUserMode(senderRef))
- {
- jam();
- tmperr = DropIndxRef::SingleUser;
- }
- if (tmperr != DropIndxRef::NoError) {
- err = tmperr;
- goto error;
- }
- // forward initial request plus operation key to all
- Uint32 indexId= req->getIndexId();
- Uint32 indexVersion= req->getIndexVersion();
-
- if(indexId >= c_tableRecordPool.getSize())
- {
- err = DropIndxRef::IndexNotFound;
- goto error;
- }
-
- TableRecordPtr tmp;
- c_tableRecordPool.getPtr(tmp, indexId);
- if(tmp.p->tabState == TableRecord::NOT_DEFINED ||
- tmp.p->tableVersion != indexVersion)
- {
- err = DropIndxRef::InvalidIndexVersion;
- goto error;
- }
-
- if (! tmp.p->isIndex()) {
- jam();
- err = DropIndxRef::NotAnIndex;
- goto error;
- }
-
- if (tmp.p->indexState != TableRecord::IS_ONLINE)
- req->addRequestFlag(RequestFlag::RF_FORCE);
-
- tmp.p->indexState = TableRecord::IS_DROPPING;
-
- req->setOpKey(++c_opRecordSequence);
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_DROP_INDX_REQ,
- signal, DropIndxReq::SignalLength + 1, JBB);
- return;
- }
- // seize operation record
- ndbrequire(signal->getLength() == DropIndxReq::SignalLength + 1);
- const Uint32 opKey = req->getOpKey();
- OpDropIndex opBusy;
- if (! c_opDropIndex.seize(opPtr))
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_coordinatorRef = senderRef;
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = opKey;
- opPtr.p->m_requestType = DropIndxReq::RT_DICT_PREPARE;
- if (opPtr.p == &opBusy) {
- jam();
- opPtr.p->m_errorCode = DropIndxRef::Busy;
- opPtr.p->m_errorLine = __LINE__;
- dropIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- c_opDropIndex.add(opPtr);
- // master expects to hear from all
- if (opPtr.p->m_isMaster)
- opPtr.p->m_signalCounter = c_aliveNodes;
- dropIndex_slavePrepare(signal, opPtr);
- dropIndex_sendReply(signal, opPtr, false);
- return;
- }
- c_opDropIndex.find(opPtr, req->getConnectionPtr());
- if (! opPtr.isNull()) {
- opPtr.p->m_requestType = requestType;
- if (requestType == DropIndxReq::RT_DICT_COMMIT ||
- requestType == DropIndxReq::RT_DICT_ABORT) {
- jam();
- if (requestType == DropIndxReq::RT_DICT_COMMIT)
- dropIndex_slaveCommit(signal, opPtr);
- else
- dropIndex_slaveAbort(signal, opPtr);
- dropIndex_sendReply(signal, opPtr, false);
- // done in slave
- if (! opPtr.p->m_isMaster)
- c_opDropIndex.release(opPtr);
- return;
- }
- }
-error:
- jam();
- // return to sender
- OpDropIndex opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = (DropIndxRef::ErrorCode)err;
- opPtr.p->m_errorLine = __LINE__;
- opPtr.p->m_errorNode = c_masterNodeId;
- dropIndex_sendReply(signal, opPtr, true);
-}
-
-void
-Dbdict::execDROP_INDX_CONF(Signal* signal)
-{
- jamEntry();
- DropIndxConf* conf = (DropIndxConf*)signal->getDataPtrSend();
- dropIndex_recvReply(signal, conf, 0);
-}
-
-void
-Dbdict::execDROP_INDX_REF(Signal* signal)
-{
- jamEntry();
- DropIndxRef* ref = (DropIndxRef*)signal->getDataPtrSend();
- dropIndex_recvReply(signal, ref->getConf(), ref);
-}
-
-void
-Dbdict::dropIndex_recvReply(Signal* signal, const DropIndxConf* conf,
- const DropIndxRef* ref)
-{
- jam();
- const Uint32 senderRef = signal->senderBlockRef();
- const DropIndxReq::RequestType requestType = conf->getRequestType();
- const Uint32 key = conf->getConnectionPtr();
- if (requestType == DropIndxReq::RT_TC) {
- jam();
- // part of alter index operation
- OpAlterIndexPtr opPtr;
- c_opAlterIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- alterIndex_fromDropTc(signal, opPtr);
- return;
- }
- OpDropIndexPtr opPtr;
- c_opDropIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- ndbrequire(opPtr.p->m_isMaster);
- ndbrequire(opPtr.p->m_requestType == requestType);
- opPtr.p->setError(ref);
- opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
- if (! opPtr.p->m_signalCounter.done()) {
- jam();
- return;
- }
- if (requestType == DropIndxReq::RT_DICT_COMMIT ||
- requestType == DropIndxReq::RT_DICT_ABORT) {
- jam();
- // send reply to user
- dropIndex_sendReply(signal, opPtr, true);
- c_opDropIndex.release(opPtr);
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
- dropIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == DropIndxReq::RT_DICT_PREPARE) {
- jam();
- // start alter offline
- dropIndex_toAlterIndex(signal, opPtr);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::dropIndex_slavePrepare(Signal* signal, OpDropIndexPtr opPtr)
-{
- jam();
- DropIndxReq* const req = &opPtr.p->m_request;
- // check index exists
- TableRecordPtr indexPtr;
- if (! (req->getIndexId() < c_tableRecordPool.getSize())) {
- jam();
- opPtr.p->m_errorCode = DropIndxRef::IndexNotFound;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- c_tableRecordPool.getPtr(indexPtr, req->getIndexId());
- if (indexPtr.p->tabState != TableRecord::DEFINED) {
- jam();
- opPtr.p->m_errorCode = DropIndxRef::IndexNotFound;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- if (! indexPtr.p->isIndex()) {
- jam();
- opPtr.p->m_errorCode = DropIndxRef::NotAnIndex;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- // ignore incoming primary table id
- req->setTableId(indexPtr.p->primaryTableId);
-}
-
-void
-Dbdict::dropIndex_toAlterIndex(Signal* signal, OpDropIndexPtr opPtr)
-{
- jam();
- AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(AlterIndxReq::RT_DROP_INDEX);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- req->setTableId(opPtr.p->m_request.getTableId());
- req->setIndexId(opPtr.p->m_request.getIndexId());
- req->setIndexVersion(opPtr.p->m_request.getIndexVersion());
- req->setOnline(false);
- sendSignal(reference(), GSN_ALTER_INDX_REQ,
- signal, AlterIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::dropIndex_fromAlterIndex(Signal* signal, OpDropIndexPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
- dropIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- dropIndex_toDropTable(signal, opPtr);
-}
-
-void
-Dbdict::dropIndex_toDropTable(Signal* signal, OpDropIndexPtr opPtr)
-{
- jam();
- DropTableReq* const req = (DropTableReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = opPtr.p->key;
- req->tableId = opPtr.p->m_request.getIndexId();
- req->tableVersion = opPtr.p->m_request.getIndexVersion();
- sendSignal(reference(), GSN_DROP_TABLE_REQ,
- signal,DropTableReq::SignalLength, JBB);
-}
-
-void
-Dbdict::dropIndex_fromDropTable(Signal* signal, OpDropIndexPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
- dropIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = DropIndxReq::RT_DICT_COMMIT;
- dropIndex_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::dropIndex_slaveCommit(Signal* signal, OpDropIndexPtr opPtr)
-{
- jam();
-}
-
-void
-Dbdict::dropIndex_slaveAbort(Signal* signal, OpDropIndexPtr opPtr)
-{
- jam();
- DropIndxReq* const req = &opPtr.p->m_request;
- const Uint32 indexId = req->getIndexId();
- if (indexId >= c_tableRecordPool.getSize()) {
- jam();
- return;
- }
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, indexId);
- indexPtr.p->indexState = TableRecord::IS_BROKEN;
-}
-
-void
-Dbdict::dropIndex_sendSlaveReq(Signal* signal, OpDropIndexPtr opPtr)
-{
- DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
- *req = opPtr.p->m_request;
- req->setUserRef(opPtr.p->m_coordinatorRef);
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(opPtr.p->m_requestType);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- opPtr.p->m_signalCounter = c_aliveNodes;
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_DROP_INDX_REQ,
- signal, DropIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::dropIndex_sendReply(Signal* signal, OpDropIndexPtr opPtr,
- bool toUser)
-{
- DropIndxRef* rep = (DropIndxRef*)signal->getDataPtrSend();
- Uint32 gsn = GSN_DROP_INDX_CONF;
- Uint32 length = DropIndxConf::InternalLength;
- bool sendRef;
- if (! toUser) {
- sendRef = opPtr.p->hasLastError();
- rep->setUserRef(opPtr.p->m_coordinatorRef);
- rep->setConnectionPtr(opPtr.p->key);
- rep->setRequestType(opPtr.p->m_requestType);
- if (opPtr.p->m_requestType == DropIndxReq::RT_DICT_ABORT)
- sendRef = false;
- } else {
- sendRef = opPtr.p->hasError();
- rep->setUserRef(opPtr.p->m_request.getUserRef());
- rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
- rep->setRequestType(opPtr.p->m_request.getRequestType());
- length = DropIndxConf::SignalLength;
- }
- rep->setTableId(opPtr.p->m_request.getTableId());
- rep->setIndexId(opPtr.p->m_request.getIndexId());
- rep->setIndexVersion(opPtr.p->m_request.getIndexVersion());
- if (sendRef) {
- if (opPtr.p->m_errorNode == 0)
- opPtr.p->m_errorNode = getOwnNodeId();
- rep->setErrorCode(opPtr.p->m_errorCode);
- rep->setErrorLine(opPtr.p->m_errorLine);
- rep->setErrorNode(opPtr.p->m_errorNode);
- gsn = GSN_DROP_INDX_REF;
- length = DropIndxRef::SignalLength;
- }
- 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)->TABLEID),
- sizeof(((sysTab_NDBEVENTS_0*)0)->TABLEVERSION),
- 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
- DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
- sizeof(EVENT_SYSTEM_TABLE_NAME));
-
- ndbrequire(opj_ptr_p != 0);
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, opj_ptr_p->m_id);
- 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();
-
- if (refToBlock(signal->senderBlockRef()) != DBDICT &&
- getOwnNodeId() != c_masterNodeId)
- {
- jam();
- releaseSections(signal);
-
- CreateEvntRef * ref = (CreateEvntRef *)signal->getDataPtrSend();
- ref->setUserRef(reference());
- ref->setErrorCode(CreateEvntRef::NotMaster);
- ref->setErrorLine(__LINE__);
- ref->setErrorNode(reference());
- ref->setMasterNode(c_masterNodeId);
- sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
- CreateEvntRef::SignalLength2, JBB);
- return;
- }
-
- 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(747);
- 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 = 1;
- 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();
- DBUG_ENTER("Dbdict::createEvent_RT_USER_CREATE");
- 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 = 1;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- DBUG_VOID_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 = 1;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- DBUG_VOID_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);
- }
-
- releaseSections(signal);
-
- // Send request to SUMA
-
- CreateSubscriptionIdReq * sumaIdReq =
- (CreateSubscriptionIdReq *)signal->getDataPtrSend();
-
- // make sure we save the original sender for later
- sumaIdReq->senderRef = reference();
- 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
- DBUG_VOID_RETURN;
-}
-
-void Dbdict::execCREATE_SUBID_REF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Dbdict::execCREATE_SUBID_REF");
- CreateSubscriptionIdRef * const ref =
- (CreateSubscriptionIdRef *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = ref->senderData;
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- if (ref->errorCode)
- {
- evntRecPtr.p->m_errorCode = ref->errorCode;
- evntRecPtr.p->m_errorLine = __LINE__;
- }
- else
- {
- evntRecPtr.p->m_errorCode = 1;
- evntRecPtr.p->m_errorLine = __LINE__;
- }
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- DBUG_VOID_RETURN;
-}
-
-void Dbdict::execCREATE_SUBID_CONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Dbdict::execCREATE_SUBID_CONF");
-
- 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);
- DBUG_VOID_RETURN;
-}
-
-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,
- Uint32& error, Uint32& line)
-{
- DBUG_ENTER("interpretUtilPrepareErrorCode");
- switch (errorCode) {
- case UtilPrepareRef::NO_ERROR:
- jam();
- error = 1;
- line = __LINE__;
- DBUG_VOID_RETURN;
- case UtilPrepareRef::PREPARE_SEIZE_ERROR:
- jam();
- error = 748;
- line = __LINE__;
- DBUG_VOID_RETURN;
- case UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR:
- jam();
- error = 1;
- line = __LINE__;
- DBUG_VOID_RETURN;
- case UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR:
- jam();
- error = 1;
- line = __LINE__;
- DBUG_VOID_RETURN;
- case UtilPrepareRef::DICT_TAB_INFO_ERROR:
- jam();
- error = 1;
- line = __LINE__;
- DBUG_VOID_RETURN;
- case UtilPrepareRef::MISSING_PROPERTIES_SECTION:
- jam();
- error = 1;
- line = __LINE__;
- DBUG_VOID_RETURN;
- default:
- jam();
- error = 1;
- line = __LINE__;
- DBUG_VOID_RETURN;
- }
- DBUG_VOID_RETURN;
-}
-
-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:
- jam();
- executeTransEventSysTable(&c, signal,
- evntRecPtr.i, evntRecPtr.p->m_eventRec,
- prepareId, UtilPrepareReq::Read);
- break;
- case CreateEvntReq::RT_USER_CREATE:
- {
- evntRecPtr.p->m_eventRec.EVENT_TYPE =
- evntRecPtr.p->m_request.getEventType() | evntRecPtr.p->m_request.getReportFlags();
- evntRecPtr.p->m_eventRec.TABLEID = evntRecPtr.p->m_request.getTableId();
- evntRecPtr.p->m_eventRec.TABLEVERSION=evntRecPtr.p->m_request.getTableVersion();
- 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();
- DBUG_PRINT("info",
- ("CREATE: event name: %s table name: %s table id: %u table version: %u",
- evntRecPtr.p->m_eventRec.NAME,
- evntRecPtr.p->m_eventRec.TABLE_NAME,
- evntRecPtr.p->m_eventRec.TABLEID,
- evntRecPtr.p->m_eventRec.TABLEVERSION));
-
- }
- 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);
-
- interpretUtilPrepareErrorCode(errorCode, evntRecPtr.p->m_errorCode,
- evntRecPtr.p->m_errorLine);
- 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]);
- 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]);
- 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: {
- parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
-
- evntRec->m_request.setEventType(evntRecPtr.p->m_eventRec.EVENT_TYPE);
- evntRec->m_request.setReportFlags(evntRecPtr.p->m_eventRec.EVENT_TYPE);
- evntRec->m_request.setTableId(evntRecPtr.p->m_eventRec.TABLEID);
- evntRec->m_request.setTableVersion(evntRecPtr.p->m_eventRec.TABLEVERSION);
- 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);
-
- DBUG_PRINT("info",
- ("GET: event name: %s table name: %s table id: %u table version: %u",
- evntRecPtr.p->m_eventRec.NAME,
- evntRecPtr.p->m_eventRec.TABLE_NAME,
- evntRecPtr.p->m_eventRec.TABLEID,
- evntRecPtr.p->m_eventRec.TABLEVERSION));
-
- // find table id for event table
- DictObject* obj_ptr_p = get_object(evntRecPtr.p->m_eventRec.TABLE_NAME);
- if(!obj_ptr_p){
- jam();
- evntRecPtr.p->m_errorCode = 723;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- return;
- }
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, obj_ptr_p->m_id);
- evntRec->m_request.setTableId(tablePtr.p->tableId);
- evntRec->m_request.setTableVersion(tablePtr.p->tableVersion);
-
- 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 = 4710;
- break;
- case ZALREADYEXIST:
- jam();
- evntRecPtr.p->m_errorCode = 746;
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
- break;
- }
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = ref->getErrorCode();
- 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 = 1;
- 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;
- if (!p.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF,
- evntRecPtr.i))
- {
- jam();
- evntRecPtr.p->m_errorCode = 701;
- createEvent_sendReply(signal, evntRecPtr);
- return;
- }
-
- 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){
- DBUG_ENTER("Dbdict::createEvent_RT_DICT_AFTER_GET");
- 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
-
- CRASH_INSERTION2(6009, getOwnNodeId() != c_masterNodeId);
-
- SubCreateReq * sumaReq = (SubCreateReq *)signal->getDataPtrSend();
-
- sumaReq->senderRef = reference(); // reference to DICT
- sumaReq->senderData = evntRecPtr.i;
- sumaReq->subscriptionId = evntRecPtr.p->m_request.getEventId();
- sumaReq->subscriptionKey = evntRecPtr.p->m_request.getEventKey();
- sumaReq->subscriptionType = SubCreateReq::TableEvent;
- if (evntRecPtr.p->m_request.getReportAll())
- sumaReq->subscriptionType|= SubCreateReq::ReportAll;
- if (evntRecPtr.p->m_request.getReportSubscribe())
- sumaReq->subscriptionType|= SubCreateReq::ReportSubscribe;
- 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, JBB);
- DBUG_VOID_RETURN;
-}
-
-void Dbdict::execSUB_CREATE_REF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Dbdict::execSUB_CREATE_REF");
-
- SubCreateRef * const ref = (SubCreateRef *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = ref->senderData;
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- if (ref->errorCode == 1415) {
- jam();
- createEvent_sendReply(signal, evntRecPtr);
- DBUG_VOID_RETURN;
- }
-
- if (ref->errorCode)
- {
- evntRecPtr.p->m_errorCode = ref->errorCode;
- evntRecPtr.p->m_errorLine = __LINE__;
- }
- else
- {
- evntRecPtr.p->m_errorCode = 1;
- evntRecPtr.p->m_errorLine = __LINE__;
- }
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- DBUG_VOID_RETURN;
-}
-
-void Dbdict::execSUB_CREATE_CONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Dbdict::execSUB_CREATE_CONF");
- EVENT_TRACE;
-
- SubCreateConf * const sumaConf = (SubCreateConf *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
- evntRecPtr.i = sumaConf->senderData;
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- createEvent_sendReply(signal, evntRecPtr);
-
- DBUG_VOID_RETURN;
-}
-
-/****************************************************
- *
- * 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 = 1;
- 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->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
- 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->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
- 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();
-
- if (refToBlock(origSenderRef) != DBDICT &&
- getOwnNodeId() != c_masterNodeId)
- {
- /*
- * Coordinator but not master
- */
- SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = SubStartRef::NotMaster;
- ref->m_masterNodeId = c_masterNodeId;
- sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
- SubStartRef::SignalLength2, JBB);
- return;
- }
- OpSubEventPtr subbPtr;
- Uint32 errCode = 0;
-
- DictLockPtr loopPtr;
- if (c_dictLockQueue.first(loopPtr) &&
- loopPtr.p->lt->lockType == DictLockReq::NodeRestartLock)
- {
- jam();
- errCode = 1405;
- goto busy;
- }
-
- if (!c_opSubEvent.seize(subbPtr)) {
- errCode = SubStartRef::Busy;
-busy:
- jam();
- 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->errorCode = errCode;
-
- 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;
- if (!p.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i))
- {
- c_opSubEvent.release(subbPtr);
- errCode = SubStartRef::Busy;
- goto busy;
- }
-
- 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);
-
- CRASH_INSERTION(6007);
-
- {
- 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;
- Uint32 err = ref->errorCode;
-
- 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
-
- jam();
- SubStartRef* ref = (SubStartRef*) signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = subbPtr.p->m_senderData;
- ref->errorCode = err;
- 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 (err == SubStartRef::NF_FakeErrorREF){
- jam();
- subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
- } else {
- jam();
- if (subbPtr.p->m_errorCode == 0)
- {
- subbPtr.p->m_errorCode= err ? err : 1;
- }
- 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_sub_start_conf = *conf;
- 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
- SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = subbPtr.p->m_errorCode;
- 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
-
- SubStartConf* conf = (SubStartConf*)signal->getDataPtrSend();
- * conf = subbPtr.p->m_sub_start_conf;
- 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();
-
- if (refToBlock(origSenderRef) != DBDICT &&
- getOwnNodeId() != c_masterNodeId)
- {
- /*
- * Coordinator but not master
- */
- SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = SubStopRef::NotMaster;
- ref->m_masterNodeId = c_masterNodeId;
- sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal,
- SubStopRef::SignalLength2, JBB);
- return;
- }
- OpSubEventPtr subbPtr;
- Uint32 errCode = 0;
- if (!c_opSubEvent.seize(subbPtr)) {
- errCode = SubStopRef::Busy;
-busy:
- SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
- jam();
- // ret->setErrorCode(SubStartRef::SeizeError);
- // ret->setErrorLine(__LINE__);
- // ret->setErrorNode(reference());
- ref->senderRef = reference();
- ref->errorCode = errCode;
-
- 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;
- if (!p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i))
- {
- jam();
- c_opSubEvent.release(subbPtr);
- errCode = SubStopRef::Busy;
- goto busy;
- }
-
- 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);
-
- CRASH_INSERTION(6008);
-
- {
- 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;
- Uint32 err = ref->errorCode;
-
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, ref->senderData);
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
- SubStopRef* ref = (SubStopRef*) signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = subbPtr.p->m_senderData;
- ref->errorCode = err;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
- signal, SubStopRef::SignalLength, JBB);
- c_opSubEvent.release(subbPtr);
- return;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
- if (err == SubStopRef::NF_FakeErrorREF){
- jam();
- subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
- } else {
- jam();
- if (subbPtr.p->m_errorCode == 0)
- {
- subbPtr.p->m_errorCode= err ? err : 1;
- }
- 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_sub_stop_conf = *conf;
- 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->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
- SubStopConf* conf = (SubStopConf*)signal->getDataPtrSend();
- * conf = subbPtr.p->m_sub_stop_conf;
- 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();
- DBUG_ENTER("Dbdict::execDROP_EVNT_REQ");
-
- DropEvntReq *req = (DropEvntReq*)signal->getDataPtr();
- const Uint32 senderRef = signal->senderBlockRef();
- OpDropEventPtr evntRecPtr;
-
- if (refToBlock(senderRef) != DBDICT &&
- getOwnNodeId() != c_masterNodeId)
- {
- jam();
- releaseSections(signal);
-
- DropEvntRef * ref = (DropEvntRef *)signal->getDataPtrSend();
- ref->setUserRef(reference());
- ref->setErrorCode(DropEvntRef::NotMaster);
- ref->setErrorLine(__LINE__);
- ref->setErrorNode(reference());
- ref->setMasterNode(c_masterNodeId);
- sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
- DropEvntRef::SignalLength2, JBB);
- return;
- }
-
- // 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(747);
- ret->setErrorLine(__LINE__);
- ret->setErrorNode(reference());
- sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
- DropEvntRef::SignalLength, JBB);
- DBUG_VOID_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 = 1;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- dropEvent_sendReply(signal, evntRecPtr);
- DBUG_VOID_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);
- DBUG_VOID_RETURN;
-}
-
-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;
- if (!p.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF,
- evntRecPtr.i))
- {
- evntRecPtr.p->m_errorCode = 701;
- dropEvent_sendReply(signal, evntRecPtr);
- return;
- }
-
- 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();
- DBUG_ENTER("Dbdict::execSUB_REMOVE_REQ");
-
- Uint32 origSenderRef = signal->senderBlockRef();
-
- OpSubEventPtr subbPtr;
- if (!c_opSubEvent.seize(subbPtr)) {
- SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
- jam();
- ref->senderRef = reference();
- ref->errorCode = SubRemoveRef::Busy;
-
- sendSignal(origSenderRef, GSN_SUB_REMOVE_REF, signal,
- SubRemoveRef::SignalLength, JBB);
- DBUG_VOID_RETURN;
- }
-
- {
- const SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtr();
- subbPtr.p->m_senderRef = req->senderRef;
- subbPtr.p->m_senderData = req->senderData;
- subbPtr.p->m_errorCode = 0;
- }
-
- CRASH_INSERTION2(6010, getOwnNodeId() != c_masterNodeId);
-
- SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = subbPtr.i;
-
- sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
- DBUG_VOID_RETURN;
-}
-
-/*
- * Coordintor/Participant
- */
-
-void
-Dbdict::execSUB_REMOVE_REF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Dbdict::execSUB_REMOVE_REF");
-
- const SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtr();
- Uint32 senderRef = ref->senderRef;
- Uint32 err= ref->errorCode;
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, ref->senderData);
- if (err == 1407) {
- // conf this since this may occur if a nodefailure 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;
- ref->errorCode = err;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_REF,
- signal, SubRemoveRef::SignalLength, JBB);
- }
- c_opSubEvent.release(subbPtr);
- DBUG_VOID_RETURN;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
- OpDropEventPtr eventRecPtr;
- c_opDropEvent.getPtr(eventRecPtr, ref->senderData);
- if (err == SubRemoveRef::NF_FakeErrorREF){
- jam();
- eventRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
- } else {
- jam();
- if (eventRecPtr.p->m_errorCode == 0)
- {
- eventRecPtr.p->m_errorCode= err ? err : 1;
- eventRecPtr.p->m_errorLine= __LINE__;
- eventRecPtr.p->m_errorNode= reference();
- }
- eventRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
- }
- completeSubRemoveReq(signal,eventRecPtr.i,0);
- DBUG_VOID_RETURN;
-}
-
-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();
- if ( evntRecPtr.p->m_errorCode == 0 )
- {
- evntRecPtr.p->m_errorNode = reference();
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorCode = 1;
- }
- 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);
-
- interpretUtilPrepareErrorCode((UtilPrepareRef::ErrorCode)ref->getErrorCode(),
- evntRecPtr.p->m_errorCode, evntRecPtr.p->m_errorLine);
- 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 = 4710;
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
- break;
- }
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = ref->getErrorCode();
- 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
- *
- * Alter index state. Alter online creates the index in each TC and
- * then invokes create trigger and alter trigger protocols to activate
- * the 3 triggers. Alter offline does the opposite.
- *
- * Request type received in REQ and returned in CONF/REF:
- *
- * RT_USER - from API to DICT master
- * RT_CREATE_INDEX - part of create index operation
- * RT_DROP_INDEX - part of drop index operation
- * RT_NODERESTART - node restart, activate locally only
- * RT_SYSTEMRESTART - system restart, activate and build if not logged
- * RT_DICT_PREPARE - prepare participants
- * RT_DICT_TC - to local TC via each participant
- * RT_DICT_COMMIT - commit in each participant
- */
-
-void
-Dbdict::execALTER_INDX_REQ(Signal* signal)
-{
- jamEntry();
- AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
- OpAlterIndexPtr opPtr;
- const Uint32 senderRef = signal->senderBlockRef();
- const AlterIndxReq::RequestType requestType = req->getRequestType();
- if (requestType == AlterIndxReq::RT_USER ||
- requestType == AlterIndxReq::RT_CREATE_INDEX ||
- requestType == AlterIndxReq::RT_DROP_INDEX ||
- requestType == AlterIndxReq::RT_NODERESTART ||
- requestType == AlterIndxReq::RT_SYSTEMRESTART) {
- jam();
- const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
- NdbNodeBitmask receiverNodes = c_aliveNodes;
- if (isLocal) {
- receiverNodes.clear();
- receiverNodes.set(getOwnNodeId());
- }
- if (signal->getLength() == AlterIndxReq::SignalLength) {
- jam();
- if (! isLocal && getOwnNodeId() != c_masterNodeId) {
- jam();
-
- releaseSections(signal);
- OpAlterIndex opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = AlterIndxRef::NotMaster;
- opPtr.p->m_errorLine = __LINE__;
- opPtr.p->m_errorNode = c_masterNodeId;
- alterIndex_sendReply(signal, opPtr, true);
- return;
- }
- // forward initial request plus operation key to all
- req->setOpKey(++c_opRecordSequence);
- NodeReceiverGroup rg(DBDICT, receiverNodes);
- sendSignal(rg, GSN_ALTER_INDX_REQ,
- signal, AlterIndxReq::SignalLength + 1, JBB);
- return;
- }
- // seize operation record
- ndbrequire(signal->getLength() == AlterIndxReq::SignalLength + 1);
- const Uint32 opKey = req->getOpKey();
- OpAlterIndex opBusy;
- if (! c_opAlterIndex.seize(opPtr))
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_coordinatorRef = senderRef;
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = opKey;
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_PREPARE;
- if (opPtr.p == &opBusy) {
- jam();
- opPtr.p->m_errorCode = AlterIndxRef::Busy;
- opPtr.p->m_errorLine = __LINE__;
- alterIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- c_opAlterIndex.add(opPtr);
- // master expects to hear from all
- if (opPtr.p->m_isMaster)
- opPtr.p->m_signalCounter = receiverNodes;
- // check request in all participants
- alterIndex_slavePrepare(signal, opPtr);
- alterIndex_sendReply(signal, opPtr, false);
- return;
- }
- c_opAlterIndex.find(opPtr, req->getConnectionPtr());
- if (! opPtr.isNull()) {
- opPtr.p->m_requestType = requestType;
- if (requestType == AlterIndxReq::RT_DICT_TC) {
- jam();
- if (opPtr.p->m_request.getOnline())
- alterIndex_toCreateTc(signal, opPtr);
- else
- alterIndex_toDropTc(signal, opPtr);
- return;
- }
- if (requestType == AlterIndxReq::RT_DICT_COMMIT ||
- requestType == AlterIndxReq::RT_DICT_ABORT) {
- jam();
- if (requestType == AlterIndxReq::RT_DICT_COMMIT)
- alterIndex_slaveCommit(signal, opPtr);
- else
- alterIndex_slaveAbort(signal, opPtr);
- alterIndex_sendReply(signal, opPtr, false);
- // done in slave
- if (! opPtr.p->m_isMaster)
- c_opAlterIndex.release(opPtr);
- return;
- }
- }
- jam();
- // return to sender
- OpAlterIndex opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = AlterIndxRef::BadRequestType;
- opPtr.p->m_errorLine = __LINE__;
- alterIndex_sendReply(signal, opPtr, true);
-}
-
-void
-Dbdict::execALTER_INDX_CONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 0);
- AlterIndxConf* conf = (AlterIndxConf*)signal->getDataPtrSend();
- alterIndex_recvReply(signal, conf, 0);
-}
-
-void
-Dbdict::execALTER_INDX_REF(Signal* signal)
-{
- jamEntry();
- AlterIndxRef* ref = (AlterIndxRef*)signal->getDataPtrSend();
- alterIndex_recvReply(signal, ref->getConf(), ref);
-}
-
-void
-Dbdict::alterIndex_recvReply(Signal* signal, const AlterIndxConf* conf,
- const AlterIndxRef* ref)
-{
- jam();
- const Uint32 senderRef = signal->senderBlockRef();
- const AlterIndxReq::RequestType requestType = conf->getRequestType();
- const Uint32 key = conf->getConnectionPtr();
- if (requestType == AlterIndxReq::RT_CREATE_INDEX) {
- jam();
- // part of create index operation
- OpCreateIndexPtr opPtr;
- c_opCreateIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- createIndex_fromAlterIndex(signal, opPtr);
- return;
- }
- if (requestType == AlterIndxReq::RT_DROP_INDEX) {
- jam();
- // part of drop index operation
- OpDropIndexPtr opPtr;
- c_opDropIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- dropIndex_fromAlterIndex(signal, opPtr);
- return;
- }
- if (requestType == AlterIndxReq::RT_TC ||
- requestType == AlterIndxReq::RT_TUX) {
- jam();
- // part of build index operation
- OpBuildIndexPtr opPtr;
- c_opBuildIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- buildIndex_fromOnline(signal, opPtr);
- return;
- }
- if (requestType == AlterIndxReq::RT_NODERESTART) {
- jam();
- if (ref == 0) {
- infoEvent("DICT: index %u activated", (unsigned)key);
- } else {
- warningEvent("DICT: index %u activation failed: code=%d line=%d",
- (unsigned)key,
- ref->getErrorCode(), ref->getErrorLine());
- }
- activateIndexes(signal, key + 1);
- return;
- }
- if (requestType == AlterIndxReq::RT_SYSTEMRESTART) {
- jam();
- if (ref == 0) {
- infoEvent("DICT: index %u activated done", (unsigned)key);
- } else {
- warningEvent("DICT: index %u activated failed: code=%d line=%d node=%d",
- (unsigned)key,
- ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode());
- }
- activateIndexes(signal, key + 1);
- return;
- }
- OpAlterIndexPtr opPtr;
- c_opAlterIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- ndbrequire(opPtr.p->m_isMaster);
- ndbrequire(opPtr.p->m_requestType == requestType);
- opPtr.p->setError(ref);
- opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
- if (! opPtr.p->m_signalCounter.done()) {
- jam();
- return;
- }
- if (requestType == AlterIndxReq::RT_DICT_COMMIT ||
- requestType == AlterIndxReq::RT_DICT_ABORT) {
- jam();
- // send reply to user
- alterIndex_sendReply(signal, opPtr, true);
- c_opAlterIndex.release(opPtr);
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
- alterIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- if (indexPtr.p->isHashIndex()) {
- if (requestType == AlterIndxReq::RT_DICT_PREPARE) {
- jam();
- if (opPtr.p->m_request.getOnline()) {
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_TC;
- alterIndex_sendSlaveReq(signal, opPtr);
- } else {
- // start drop triggers
- alterIndex_toDropTrigger(signal, opPtr);
- }
- return;
- }
- if (requestType == AlterIndxReq::RT_DICT_TC) {
- jam();
- if (opPtr.p->m_request.getOnline()) {
- // start create triggers
- alterIndex_toCreateTrigger(signal, opPtr);
- } else {
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
- alterIndex_sendSlaveReq(signal, opPtr);
- }
- return;
- }
- }
- if (indexPtr.p->isOrderedIndex()) {
- if (requestType == AlterIndxReq::RT_DICT_PREPARE) {
- jam();
- if (opPtr.p->m_request.getOnline()) {
- // start create triggers
- alterIndex_toCreateTrigger(signal, opPtr);
- } else {
- // start drop triggers
- alterIndex_toDropTrigger(signal, opPtr);
- }
- return;
- }
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::alterIndex_slavePrepare(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- const AlterIndxReq* const req = &opPtr.p->m_request;
- if (! (req->getIndexId() < c_tableRecordPool.getSize())) {
- jam();
- opPtr.p->m_errorCode = AlterIndxRef::Inconsistency;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, req->getIndexId());
- if (indexPtr.p->tabState != TableRecord::DEFINED) {
- jam();
- opPtr.p->m_errorCode = AlterIndxRef::IndexNotFound;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- if (! indexPtr.p->isIndex()) {
- jam();
- opPtr.p->m_errorCode = AlterIndxRef::NotAnIndex;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- if (req->getOnline())
- indexPtr.p->indexState = TableRecord::IS_BUILDING;
- else
- indexPtr.p->indexState = TableRecord::IS_DROPPING;
-}
-
-void
-Dbdict::alterIndex_toCreateTc(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- // request to create index in local TC
- CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(CreateIndxReq::RT_TC);
- req->setIndexType(indexPtr.p->tableType);
- req->setTableId(indexPtr.p->primaryTableId);
- req->setIndexId(indexPtr.i);
- req->setOnline(true);
- getIndexAttrList(indexPtr, opPtr.p->m_attrList);
- // send
- LinearSectionPtr lsPtr[3];
- lsPtr[0].p = (Uint32*)&opPtr.p->m_attrList;
- lsPtr[0].sz = 1 + opPtr.p->m_attrList.sz;
- sendSignal(calcTcBlockRef(getOwnNodeId()), GSN_CREATE_INDX_REQ,
- signal, CreateIndxReq::SignalLength, JBB, lsPtr, 1);
-}
-
-void
-Dbdict::alterIndex_fromCreateTc(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- // mark created in local TC
- if (! opPtr.p->hasLastError()) {
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- indexPtr.p->indexLocal |= TableRecord::IL_CREATED_TC;
- }
- // forward CONF or REF to master
- ndbrequire(opPtr.p->m_requestType == AlterIndxReq::RT_DICT_TC);
- alterIndex_sendReply(signal, opPtr, false);
-}
-
-void
-Dbdict::alterIndex_toDropTc(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- // broken index allowed if force
- if (! (indexPtr.p->indexLocal & TableRecord::IL_CREATED_TC)) {
- jam();
- ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
- alterIndex_sendReply(signal, opPtr, false);
- return;
- }
- // request to drop in local TC
- DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(DropIndxReq::RT_TC);
- req->setTableId(indexPtr.p->primaryTableId);
- req->setIndexId(indexPtr.i);
- req->setIndexVersion(indexPtr.p->tableVersion);
- // send
- sendSignal(calcTcBlockRef(getOwnNodeId()), GSN_DROP_INDX_REQ,
- signal, DropIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::alterIndex_fromDropTc(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- ndbrequire(opPtr.p->m_requestType == AlterIndxReq::RT_DICT_TC);
- // mark dropped locally
- if (! opPtr.p->hasLastError()) {
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- indexPtr.p->indexLocal &= ~TableRecord::IL_CREATED_TC;
- }
- // forward CONF or REF to master
- alterIndex_sendReply(signal, opPtr, false);
-}
-
-void
-Dbdict::alterIndex_toCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- // start creation of index triggers
- CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(CreateTrigReq::RT_ALTER_INDEX);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- req->setTableId(opPtr.p->m_request.getTableId());
- req->setIndexId(opPtr.p->m_request.getIndexId());
- req->setTriggerId(RNIL);
- req->setTriggerActionTime(TriggerActionTime::TA_AFTER);
- req->setMonitorAllAttributes(false);
- req->setOnline(true); // alter online after create
- req->setReceiverRef(0); // implicit for index triggers
- getIndexAttrMask(indexPtr, req->getAttributeMask());
- // name section
- char triggerName[MAX_TAB_NAME_SIZE];
- Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
- LinearWriter w(buffer, sizeof(buffer) >> 2);
- LinearSectionPtr lsPtr[3];
- if (indexPtr.p->isHashIndex()) {
- req->setTriggerType(TriggerType::SECONDARY_INDEX);
- req->setMonitorReplicas(false);
- req->setReportAllMonitoredAttributes(true);
- // insert
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
- req->setTriggerId(indexPtr.p->insertTriggerId);
- req->setTriggerEvent(TriggerEvent::TE_INSERT);
- sprintf(triggerName, "NDB$INDEX_%u_INSERT", opPtr.p->m_request.getIndexId());
- w.reset();
- w.add(CreateTrigReq::TriggerNameKey, triggerName);
- lsPtr[0].p = buffer;
- lsPtr[0].sz = w.getWordsUsed();
- sendSignal(reference(), GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
- // update
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
- req->setTriggerId(indexPtr.p->updateTriggerId);
- req->setTriggerEvent(TriggerEvent::TE_UPDATE);
- sprintf(triggerName, "NDB$INDEX_%u_UPDATE", opPtr.p->m_request.getIndexId());
- w.reset();
- w.add(CreateTrigReq::TriggerNameKey, triggerName);
- lsPtr[0].p = buffer;
- lsPtr[0].sz = w.getWordsUsed();
- sendSignal(reference(), GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
- // delete
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
- req->setTriggerId(indexPtr.p->deleteTriggerId);
- req->setTriggerEvent(TriggerEvent::TE_DELETE);
- sprintf(triggerName, "NDB$INDEX_%u_DELETE", opPtr.p->m_request.getIndexId());
- w.reset();
- w.add(CreateTrigReq::TriggerNameKey, triggerName);
- lsPtr[0].p = buffer;
- lsPtr[0].sz = w.getWordsUsed();
- sendSignal(reference(), GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
- // triggers left to create
- opPtr.p->m_triggerCounter = 3;
- return;
- }
- if (indexPtr.p->isOrderedIndex()) {
- req->addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
- req->setTriggerType(TriggerType::ORDERED_INDEX);
- req->setTriggerActionTime(TriggerActionTime::TA_CUSTOM);
- req->setMonitorReplicas(true);
- req->setReportAllMonitoredAttributes(true);
- // one trigger for 5 events (insert, update, delete, commit, abort)
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
- req->setTriggerId(indexPtr.p->customTriggerId);
- req->setTriggerEvent(TriggerEvent::TE_CUSTOM);
- sprintf(triggerName, "NDB$INDEX_%u_CUSTOM", opPtr.p->m_request.getIndexId());
- w.reset();
- w.add(CreateTrigReq::TriggerNameKey, triggerName);
- lsPtr[0].p = buffer;
- lsPtr[0].sz = w.getWordsUsed();
- sendSignal(reference(), GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
- // triggers left to create
- opPtr.p->m_triggerCounter = 1;
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::alterIndex_fromCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- ndbrequire(opPtr.p->m_triggerCounter != 0);
- if (--opPtr.p->m_triggerCounter != 0) {
- jam();
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
- alterIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- if(opPtr.p->m_requestType != AlterIndxReq::RT_SYSTEMRESTART){
- // send build request
- alterIndex_toBuildIndex(signal, opPtr);
- return;
- }
-
- /**
- * During system restart,
- * leave index in activated but not build state.
- *
- * Build a bit later when REDO has been run
- */
- alterIndex_sendReply(signal, opPtr, true);
-}
-
-void
-Dbdict::alterIndex_toDropTrigger(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- // start drop of index triggers
- DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(DropTrigReq::RT_ALTER_INDEX);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- req->setTableId(opPtr.p->m_request.getTableId());
- req->setIndexId(opPtr.p->m_request.getIndexId());
- req->setTriggerInfo(0); // not used
- opPtr.p->m_triggerCounter = 0;
- if (indexPtr.p->isHashIndex()) {
- // insert
- req->setTriggerId(indexPtr.p->insertTriggerId);
- sendSignal(reference(), GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- opPtr.p->m_triggerCounter++;
- // update
- req->setTriggerId(indexPtr.p->updateTriggerId);
- sendSignal(reference(), GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- opPtr.p->m_triggerCounter++;
- // delete
- req->setTriggerId(indexPtr.p->deleteTriggerId);
- sendSignal(reference(), GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- opPtr.p->m_triggerCounter++;
- // build
- if (indexPtr.p->buildTriggerId != RNIL) {
- req->setTriggerId(indexPtr.p->buildTriggerId);
- sendSignal(reference(), GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- opPtr.p->m_triggerCounter++;
- }
- return;
- }
- if (indexPtr.p->isOrderedIndex()) {
- // custom
- req->addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
- req->setTriggerId(indexPtr.p->customTriggerId);
- sendSignal(reference(), GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- opPtr.p->m_triggerCounter++;
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::alterIndex_fromDropTrigger(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- ndbrequire(opPtr.p->m_triggerCounter != 0);
- if (--opPtr.p->m_triggerCounter != 0) {
- jam();
- return;
- }
- // finally drop index in each TC
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- const bool isHashIndex = indexPtr.p->isHashIndex();
- const bool isOrderedIndex = indexPtr.p->isOrderedIndex();
- ndbrequire(isHashIndex != isOrderedIndex); // xor
- if (isHashIndex)
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_TC;
- if (isOrderedIndex)
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
- alterIndex_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::alterIndex_toBuildIndex(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- // get index and table records
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
- // build request to self (short signal)
- BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(BuildIndxReq::RT_ALTER_INDEX);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- req->setBuildId(0); // not used
- req->setBuildKey(0); // not used
- req->setIndexType(indexPtr.p->tableType);
- req->setIndexId(indexPtr.i);
- req->setTableId(indexPtr.p->primaryTableId);
- req->setParallelism(16);
- // send
- sendSignal(reference(), GSN_BUILDINDXREQ,
- signal, BuildIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::alterIndex_fromBuildIndex(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
- alterIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
- alterIndex_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::alterIndex_slaveCommit(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- // get index record
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- indexPtr.p->indexState = TableRecord::IS_ONLINE;
-}
-
-void
-Dbdict::alterIndex_slaveAbort(Signal* signal, OpAlterIndexPtr opPtr)
-{
- jam();
- // find index record
- const Uint32 indexId = opPtr.p->m_request.getIndexId();
- if (indexId >= c_tableRecordPool.getSize())
- return;
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, indexId);
- if (! indexPtr.p->isIndex())
- return;
- // mark broken
- indexPtr.p->indexState = TableRecord::IS_BROKEN;
-}
-
-void
-Dbdict::alterIndex_sendSlaveReq(Signal* signal, OpAlterIndexPtr opPtr)
-{
- AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
- *req = opPtr.p->m_request;
- req->setUserRef(opPtr.p->m_coordinatorRef);
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(opPtr.p->m_requestType);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- NdbNodeBitmask receiverNodes = c_aliveNodes;
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
- receiverNodes.clear();
- receiverNodes.set(getOwnNodeId());
- }
- opPtr.p->m_signalCounter = receiverNodes;
- NodeReceiverGroup rg(DBDICT, receiverNodes);
- sendSignal(rg, GSN_ALTER_INDX_REQ,
- signal, AlterIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::alterIndex_sendReply(Signal* signal, OpAlterIndexPtr opPtr,
- bool toUser)
-{
- AlterIndxRef* rep = (AlterIndxRef*)signal->getDataPtrSend();
- Uint32 gsn = GSN_ALTER_INDX_CONF;
- Uint32 length = AlterIndxConf::InternalLength;
- bool sendRef;
- if (! toUser) {
- sendRef = opPtr.p->hasLastError();
- rep->setUserRef(opPtr.p->m_coordinatorRef);
- rep->setConnectionPtr(opPtr.p->key);
- rep->setRequestType(opPtr.p->m_requestType);
- if (opPtr.p->m_requestType == AlterIndxReq::RT_DICT_ABORT)
- sendRef = false;
- } else {
- sendRef = opPtr.p->hasError();
- rep->setUserRef(opPtr.p->m_request.getUserRef());
- rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
- rep->setRequestType(opPtr.p->m_request.getRequestType());
- length = AlterIndxConf::SignalLength;
- }
- rep->setTableId(opPtr.p->m_request.getTableId());
- rep->setIndexId(opPtr.p->m_request.getIndexId());
- if (sendRef) {
- if (opPtr.p->m_errorNode == 0)
- opPtr.p->m_errorNode = getOwnNodeId();
- rep->setErrorCode(opPtr.p->m_errorCode);
- rep->setErrorLine(opPtr.p->m_errorLine);
- rep->setErrorNode(opPtr.p->m_errorNode);
- gsn = GSN_ALTER_INDX_REF;
- length = AlterIndxRef::SignalLength;
- }
- sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
-}
-
-/**
- * MODULE: Build index
- *
- * Build index or all indexes on a table. Request type:
- *
- * RT_USER - normal user request, not yet used
- * RT_ALTER_INDEX - from alter index
- * RT_SYSTEM_RESTART -
- * RT_DICT_PREPARE - prepare participants
- * RT_DICT_TRIX - to participant on way to local TRIX
- * RT_DICT_COMMIT - commit in each participant
- * RT_DICT_ABORT - abort
- * RT_TRIX - to local TRIX
- */
-
-void
-Dbdict::execBUILDINDXREQ(Signal* signal)
-{
- jamEntry();
- BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
- OpBuildIndexPtr opPtr;
- const Uint32 senderRef = signal->senderBlockRef();
- const BuildIndxReq::RequestType requestType = req->getRequestType();
- if (requestType == BuildIndxReq::RT_USER ||
- requestType == BuildIndxReq::RT_ALTER_INDEX ||
- requestType == BuildIndxReq::RT_SYSTEMRESTART) {
- jam();
-
- const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
- NdbNodeBitmask receiverNodes = c_aliveNodes;
- if (isLocal) {
- receiverNodes.clear();
- receiverNodes.set(getOwnNodeId());
- }
-
- if (signal->getLength() == BuildIndxReq::SignalLength) {
- jam();
-
- if (!isLocal && getOwnNodeId() != c_masterNodeId) {
- jam();
-
- releaseSections(signal);
- OpBuildIndex opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = BuildIndxRef::NotMaster;
- opPtr.p->m_errorLine = __LINE__;
- opPtr.p->m_errorNode = c_masterNodeId;
- buildIndex_sendReply(signal, opPtr, true);
- return;
- }
- // forward initial request plus operation key to all
- req->setOpKey(++c_opRecordSequence);
- NodeReceiverGroup rg(DBDICT, receiverNodes);
- sendSignal(rg, GSN_BUILDINDXREQ,
- signal, BuildIndxReq::SignalLength + 1, JBB);
- return;
- }
- // seize operation record
- ndbrequire(signal->getLength() == BuildIndxReq::SignalLength + 1);
- const Uint32 opKey = req->getOpKey();
- OpBuildIndex opBusy;
- if (! c_opBuildIndex.seize(opPtr))
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_coordinatorRef = senderRef;
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = opKey;
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_PREPARE;
- if (opPtr.p == &opBusy) {
- jam();
- opPtr.p->m_errorCode = BuildIndxRef::Busy;
- opPtr.p->m_errorLine = __LINE__;
- buildIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- c_opBuildIndex.add(opPtr);
- // master expects to hear from all
- opPtr.p->m_signalCounter = receiverNodes;
- buildIndex_sendReply(signal, opPtr, false);
- return;
- }
- c_opBuildIndex.find(opPtr, req->getConnectionPtr());
- if (! opPtr.isNull()) {
- opPtr.p->m_requestType = requestType;
- if (requestType == BuildIndxReq::RT_DICT_TRIX) {
- jam();
- buildIndex_buildTrix(signal, opPtr);
- return;
- }
- if (requestType == BuildIndxReq::RT_DICT_TC ||
- requestType == BuildIndxReq::RT_DICT_TUX) {
- jam();
- buildIndex_toOnline(signal, opPtr);
- return;
- }
- if (requestType == BuildIndxReq::RT_DICT_COMMIT ||
- requestType == BuildIndxReq::RT_DICT_ABORT) {
- jam();
- buildIndex_sendReply(signal, opPtr, false);
- // done in slave
- if (! opPtr.p->m_isMaster)
- c_opBuildIndex.release(opPtr);
- return;
- }
- }
- jam();
- // return to sender
- OpBuildIndex opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = BuildIndxRef::BadRequestType;
- opPtr.p->m_errorLine = __LINE__;
- buildIndex_sendReply(signal, opPtr, true);
-}
-
-void
-Dbdict::execBUILDINDXCONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 0);
- BuildIndxConf* conf = (BuildIndxConf*)signal->getDataPtrSend();
- buildIndex_recvReply(signal, conf, 0);
-}
-
-void
-Dbdict::execBUILDINDXREF(Signal* signal)
-{
- jamEntry();
- BuildIndxRef* ref = (BuildIndxRef*)signal->getDataPtrSend();
- buildIndex_recvReply(signal, ref->getConf(), ref);
-}
-
-void
-Dbdict::buildIndex_recvReply(Signal* signal, const BuildIndxConf* conf,
- const BuildIndxRef* ref)
-{
- jam();
- const Uint32 senderRef = signal->senderBlockRef();
- const BuildIndxReq::RequestType requestType = conf->getRequestType();
- const Uint32 key = conf->getConnectionPtr();
- if (requestType == BuildIndxReq::RT_ALTER_INDEX) {
- jam();
- // part of alter index operation
- OpAlterIndexPtr opPtr;
- c_opAlterIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- alterIndex_fromBuildIndex(signal, opPtr);
- return;
- }
-
- if (requestType == BuildIndxReq::RT_SYSTEMRESTART) {
- jam();
- if (ref == 0) {
- infoEvent("DICT: index %u rebuild done", (unsigned)key);
- } else {
- warningEvent("DICT: index %u rebuild failed: code=%d line=%d node=%d",
- (unsigned)key, ref->getErrorCode());
- }
- rebuildIndexes(signal, key + 1);
- return;
- }
-
- OpBuildIndexPtr opPtr;
- c_opBuildIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- if (requestType == BuildIndxReq::RT_TRIX) {
- jam();
- // forward to master
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
- buildIndex_sendReply(signal, opPtr, false);
- return;
- }
- ndbrequire(opPtr.p->m_isMaster);
- ndbrequire(opPtr.p->m_requestType == requestType);
- opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
- if (! opPtr.p->m_signalCounter.done()) {
- jam();
- return;
- }
- if (requestType == BuildIndxReq::RT_DICT_COMMIT ||
- requestType == BuildIndxReq::RT_DICT_ABORT) {
- jam();
- // send reply to user
- buildIndex_sendReply(signal, opPtr, true);
- c_opBuildIndex.release(opPtr);
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
- buildIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- if (indexPtr.p->isHashIndex()) {
- if (requestType == BuildIndxReq::RT_DICT_PREPARE) {
- jam();
- if (! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD)) {
- buildIndex_toCreateConstr(signal, opPtr);
- } else {
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TC;
- buildIndex_sendSlaveReq(signal, opPtr);
- }
- return;
- }
- if (requestType == BuildIndxReq::RT_DICT_TRIX) {
- jam();
- ndbrequire(! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD));
- buildIndex_toDropConstr(signal, opPtr);
- return;
- }
- if (requestType == BuildIndxReq::RT_DICT_TC) {
- jam();
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_COMMIT;
- buildIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- }
- if (indexPtr.p->isOrderedIndex()) {
- if (requestType == BuildIndxReq::RT_DICT_PREPARE) {
- jam();
- if (! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD)) {
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
- buildIndex_sendSlaveReq(signal, opPtr);
- } else {
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TUX;
- buildIndex_sendSlaveReq(signal, opPtr);
- }
- return;
- }
- if (requestType == BuildIndxReq::RT_DICT_TRIX) {
- jam();
- ndbrequire(! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD));
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TUX;
- buildIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == BuildIndxReq::RT_DICT_TUX) {
- jam();
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_COMMIT;
- buildIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::buildIndex_toCreateConstr(Signal* signal, OpBuildIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- // request to create constraint trigger
- CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(CreateTrigReq::RT_BUILD_INDEX);
- req->addRequestFlag(0); // none
- req->setTableId(indexPtr.i);
- req->setIndexId(RNIL);
- req->setTriggerId(RNIL);
- req->setTriggerType(TriggerType::READ_ONLY_CONSTRAINT);
- req->setTriggerActionTime(TriggerActionTime::TA_AFTER);
- req->setTriggerEvent(TriggerEvent::TE_UPDATE);
- req->setMonitorReplicas(false);
- req->setMonitorAllAttributes(false);
- req->setReportAllMonitoredAttributes(true);
- req->setOnline(true); // alter online after create
- req->setReceiverRef(0); // no receiver, REF-ed by TUP
- req->getAttributeMask().clear();
- // NDB$PK is last attribute
- req->getAttributeMask().set(indexPtr.p->noOfAttributes - 1);
- // name section
- char triggerName[MAX_TAB_NAME_SIZE];
- Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
- LinearWriter w(buffer, sizeof(buffer) >> 2);
- LinearSectionPtr lsPtr[3];
- sprintf(triggerName, "NDB$INDEX_%u_BUILD", indexPtr.i);
- w.reset();
- w.add(CreateTrigReq::TriggerNameKey, triggerName);
- lsPtr[0].p = buffer;
- lsPtr[0].sz = w.getWordsUsed();
- sendSignal(reference(), GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
-}
-
-void
-Dbdict::buildIndex_fromCreateConstr(Signal* signal, OpBuildIndexPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
- buildIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
- buildIndex_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::buildIndex_buildTrix(Signal* signal, OpBuildIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
- // build request
- BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(BuildIndxReq::RT_TRIX);
- req->setBuildId(0); // not yet..
- req->setBuildKey(0); // ..in use
- req->setIndexType(indexPtr.p->tableType);
- req->setIndexId(indexPtr.i);
- req->setTableId(indexPtr.p->primaryTableId);
- req->setParallelism(16);
- if (indexPtr.p->isHashIndex()) {
- jam();
- getIndexAttrList(indexPtr, opPtr.p->m_attrList);
- getTableKeyList(tablePtr, opPtr.p->m_tableKeyList);
- // send
- LinearSectionPtr lsPtr[3];
- lsPtr[0].sz = opPtr.p->m_attrList.sz;
- lsPtr[0].p = opPtr.p->m_attrList.id;
- lsPtr[1].sz = opPtr.p->m_tableKeyList.sz;
- lsPtr[1].p = opPtr.p->m_tableKeyList.id;
- sendSignal(calcTrixBlockRef(getOwnNodeId()), GSN_BUILDINDXREQ,
- signal, BuildIndxReq::SignalLength, JBB, lsPtr, 2);
- return;
- }
- if (indexPtr.p->isOrderedIndex()) {
- jam();
- sendSignal(calcTupBlockRef(getOwnNodeId()), GSN_BUILDINDXREQ,
- signal, BuildIndxReq::SignalLength, JBB);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::buildIndex_toDropConstr(Signal* signal, OpBuildIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- // request to drop constraint trigger
- DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(DropTrigReq::RT_BUILD_INDEX);
- req->addRequestFlag(0); // none
- req->setTableId(indexPtr.i);
- req->setIndexId(RNIL);
- req->setTriggerId(opPtr.p->m_constrTriggerId);
- req->setTriggerInfo(0); // not used
- sendSignal(reference(), GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::buildIndex_fromDropConstr(Signal* signal, OpBuildIndexPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
- buildIndex_sendSlaveReq(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TC;
- buildIndex_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::buildIndex_toOnline(Signal* signal, OpBuildIndexPtr opPtr)
-{
- jam();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
- // request to set index online in TC or TUX
- AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
- jam();
- req->setRequestType(AlterIndxReq::RT_TC);
- } else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
- jam();
- req->setRequestType(AlterIndxReq::RT_TUX);
- } else {
- ndbrequire(false);
- }
- req->setTableId(tablePtr.i);
- req->setIndexId(indexPtr.i);
- req->setIndexVersion(indexPtr.p->tableVersion);
- req->setOnline(true);
- BlockReference blockRef = 0;
- if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
- jam();
- blockRef = calcTcBlockRef(getOwnNodeId());
- } else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
- jam();
- blockRef = calcTuxBlockRef(getOwnNodeId());
- } else {
- ndbrequire(false);
- }
- // send
- sendSignal(blockRef, GSN_ALTER_INDX_REQ,
- signal, BuildIndxReq::SignalLength, JBB);
-}
-
-void
-Dbdict::buildIndex_fromOnline(Signal* signal, OpBuildIndexPtr opPtr)
-{
- jam();
- // forward to master
- buildIndex_sendReply(signal, opPtr, false);
-}
-
-void
-Dbdict::buildIndex_sendSlaveReq(Signal* signal, OpBuildIndexPtr opPtr)
-{
- BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
- *req = opPtr.p->m_request;
- req->setUserRef(opPtr.p->m_coordinatorRef);
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(opPtr.p->m_requestType);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- if(opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
- jam();
- opPtr.p->m_signalCounter.clearWaitingFor();
- opPtr.p->m_signalCounter.setWaitingFor(getOwnNodeId());
- sendSignal(reference(), GSN_BUILDINDXREQ,
- signal, BuildIndxReq::SignalLength, JBB);
- } else {
- jam();
- opPtr.p->m_signalCounter = c_aliveNodes;
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_BUILDINDXREQ,
- signal, BuildIndxReq::SignalLength, JBB);
- }
-}
-
-void
-Dbdict::buildIndex_sendReply(Signal* signal, OpBuildIndexPtr opPtr,
- bool toUser)
-{
- BuildIndxRef* rep = (BuildIndxRef*)signal->getDataPtrSend();
- Uint32 gsn = GSN_BUILDINDXCONF;
- Uint32 length = BuildIndxConf::InternalLength;
- bool sendRef;
- if (! toUser) {
- sendRef = opPtr.p->hasLastError();
- rep->setUserRef(opPtr.p->m_coordinatorRef);
- rep->setConnectionPtr(opPtr.p->key);
- rep->setRequestType(opPtr.p->m_requestType);
- if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_ABORT)
- sendRef = false;
- } else {
- sendRef = opPtr.p->hasError();
- rep->setUserRef(opPtr.p->m_request.getUserRef());
- rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
- rep->setRequestType(opPtr.p->m_request.getRequestType());
- length = BuildIndxConf::SignalLength;
- }
- rep->setIndexType(opPtr.p->m_request.getIndexType());
- rep->setTableId(opPtr.p->m_request.getTableId());
- rep->setIndexId(opPtr.p->m_request.getIndexId());
- if (sendRef) {
- rep->setErrorCode(opPtr.p->m_errorCode);
- rep->masterNodeId = opPtr.p->m_errorNode;
- gsn = GSN_BUILDINDXREF;
- length = BuildIndxRef::SignalLength;
- }
- sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
-}
-
-/**
- * MODULE: Create trigger
- *
- * Create trigger in all DICT blocks. Optionally start alter trigger
- * operation to set the trigger online.
- *
- * Request type received in REQ and returned in CONF/REF:
- *
- * RT_USER - normal user e.g. BACKUP
- * RT_ALTER_INDEX - from alter index online
- * RT_DICT_PREPARE - seize operation in each DICT
- * RT_DICT_COMMIT - commit create in each DICT
- * RT_TC - sending to TC (operation alter trigger)
- * RT_LQH - sending to LQH (operation alter trigger)
- */
-
-void
-Dbdict::execCREATE_TRIG_REQ(Signal* signal)
-{
- jamEntry();
- CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
- OpCreateTriggerPtr opPtr;
- const Uint32 senderRef = signal->senderBlockRef();
- const CreateTrigReq::RequestType requestType = req->getRequestType();
- if (requestType == CreateTrigReq::RT_USER ||
- requestType == CreateTrigReq::RT_ALTER_INDEX ||
- requestType == CreateTrigReq::RT_BUILD_INDEX) {
- jam();
- if (! assembleFragments(signal)) {
- jam();
- return;
- }
- const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
- NdbNodeBitmask receiverNodes = c_aliveNodes;
- if (isLocal) {
- receiverNodes.clear();
- receiverNodes.set(getOwnNodeId());
- }
- if (signal->getLength() == CreateTrigReq::SignalLength) {
- jam();
- if (! isLocal && getOwnNodeId() != c_masterNodeId) {
- jam();
-
- releaseSections(signal);
- OpCreateTrigger opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = CreateTrigRef::NotMaster;
- opPtr.p->m_errorLine = __LINE__;
- opPtr.p->m_errorNode = c_masterNodeId;
- createTrigger_sendReply(signal, opPtr, true);
- return;
- }
- // forward initial request plus operation key to all
- req->setOpKey(++c_opRecordSequence);
- NodeReceiverGroup rg(DBDICT, receiverNodes);
- sendSignal(rg, GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength + 1, JBB);
- return;
- }
- // seize operation record
- ndbrequire(signal->getLength() == CreateTrigReq::SignalLength + 1);
- const Uint32 opKey = req->getOpKey();
- OpCreateTrigger opBusy;
- if (! c_opCreateTrigger.seize(opPtr))
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_coordinatorRef = senderRef;
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = opKey;
- opPtr.p->m_requestType = CreateTrigReq::RT_DICT_PREPARE;
- if (opPtr.p == &opBusy) {
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::Busy;
- opPtr.p->m_errorLine = __LINE__;
- releaseSections(signal);
- createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- c_opCreateTrigger.add(opPtr);
- {
- // save name
- SegmentedSectionPtr ssPtr;
- signal->getSection(ssPtr, CreateTrigReq::TRIGGER_NAME_SECTION);
- SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
- if (ssReader.getKey() != CreateTrigReq::TriggerNameKey ||
- ! ssReader.getString(opPtr.p->m_triggerName)) {
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::InvalidName;
- opPtr.p->m_errorLine = __LINE__;
- releaseSections(signal);
- createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- }
- releaseSections(signal);
- if(get_object(opPtr.p->m_triggerName) != 0){
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::TriggerExists;
- opPtr.p->m_errorLine = __LINE__;
- createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
-
- // master expects to hear from all
- if (opPtr.p->m_isMaster)
- opPtr.p->m_signalCounter = receiverNodes;
- // check request in all participants
- createTrigger_slavePrepare(signal, opPtr);
- createTrigger_sendReply(signal, opPtr, false);
- return;
- }
- c_opCreateTrigger.find(opPtr, req->getConnectionPtr());
- if (! opPtr.isNull()) {
- opPtr.p->m_requestType = requestType;
- if (requestType == CreateTrigReq::RT_DICT_CREATE) {
- jam();
- // master has set trigger id
- opPtr.p->m_request.setTriggerId(req->getTriggerId());
- createTrigger_slaveCreate(signal, opPtr);
- createTrigger_sendReply(signal, opPtr, false);
- return;
- }
- if (requestType == CreateTrigReq::RT_DICT_COMMIT ||
- requestType == CreateTrigReq::RT_DICT_ABORT) {
- jam();
- if (requestType == CreateTrigReq::RT_DICT_COMMIT)
- createTrigger_slaveCommit(signal, opPtr);
- else
- createTrigger_slaveAbort(signal, opPtr);
- createTrigger_sendReply(signal, opPtr, false);
- // done in slave
- if (! opPtr.p->m_isMaster)
- c_opCreateTrigger.release(opPtr);
- return;
- }
- }
- jam();
- // return to sender
- releaseSections(signal);
- OpCreateTrigger opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = CreateTrigRef::BadRequestType;
- opPtr.p->m_errorLine = __LINE__;
- createTrigger_sendReply(signal, opPtr, true);
-}
-
-void
-Dbdict::execCREATE_TRIG_CONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(signal->getNoOfSections() == 0);
- CreateTrigConf* conf = (CreateTrigConf*)signal->getDataPtrSend();
- createTrigger_recvReply(signal, conf, 0);
-}
-
-void
-Dbdict::execCREATE_TRIG_REF(Signal* signal)
-{
- jamEntry();
- CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtrSend();
- createTrigger_recvReply(signal, ref->getConf(), ref);
-}
-
-void
-Dbdict::createTrigger_recvReply(Signal* signal, const CreateTrigConf* conf,
- const CreateTrigRef* ref)
-{
- jam();
- const Uint32 senderRef = signal->senderBlockRef();
- const CreateTrigReq::RequestType requestType = conf->getRequestType();
- const Uint32 key = conf->getConnectionPtr();
- if (requestType == CreateTrigReq::RT_ALTER_INDEX) {
- jam();
- // part of alter index operation
- OpAlterIndexPtr opPtr;
- c_opAlterIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- alterIndex_fromCreateTrigger(signal, opPtr);
- return;
- }
- if (requestType == CreateTrigReq::RT_BUILD_INDEX) {
- jam();
- // part of build index operation
- OpBuildIndexPtr opPtr;
- c_opBuildIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- // fill in trigger id
- opPtr.p->m_constrTriggerId = conf->getTriggerId();
- buildIndex_fromCreateConstr(signal, opPtr);
- return;
- }
- if (requestType == CreateTrigReq::RT_TC ||
- requestType == CreateTrigReq::RT_LQH) {
- jam();
- // part of alter trigger operation
- OpAlterTriggerPtr opPtr;
- c_opAlterTrigger.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- alterTrigger_fromCreateLocal(signal, opPtr);
- return;
- }
- OpCreateTriggerPtr opPtr;
- c_opCreateTrigger.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- ndbrequire(opPtr.p->m_isMaster);
- ndbrequire(opPtr.p->m_requestType == requestType);
- opPtr.p->setError(ref);
- opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
- if (! opPtr.p->m_signalCounter.done()) {
- jam();
- return;
- }
- if (requestType == CreateTrigReq::RT_DICT_COMMIT ||
- requestType == CreateTrigReq::RT_DICT_ABORT) {
- jam();
- // send reply to user
- createTrigger_sendReply(signal, opPtr, true);
- c_opCreateTrigger.release(opPtr);
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
- createTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == CreateTrigReq::RT_DICT_PREPARE) {
- jam();
- // seize trigger id in master
- createTrigger_masterSeize(signal, opPtr);
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
- createTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = CreateTrigReq::RT_DICT_CREATE;
- createTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == CreateTrigReq::RT_DICT_CREATE) {
- jam();
- if (opPtr.p->m_request.getOnline()) {
- jam();
- // start alter online
- createTrigger_toAlterTrigger(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = CreateTrigReq::RT_DICT_COMMIT;
- createTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::createTrigger_slavePrepare(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- jam();
- const CreateTrigReq* const req = &opPtr.p->m_request;
- // check trigger type
- if (req->getRequestType() == CreateTrigReq::RT_USER &&
- req->getTriggerType() == TriggerType::SUBSCRIPTION ||
- req->getRequestType() == CreateTrigReq::RT_ALTER_INDEX &&
- req->getTriggerType() == TriggerType::SECONDARY_INDEX ||
- req->getRequestType() == CreateTrigReq::RT_ALTER_INDEX &&
- req->getTriggerType() == TriggerType::ORDERED_INDEX ||
- req->getRequestType() == CreateTrigReq::RT_BUILD_INDEX &&
- req->getTriggerType() == TriggerType::READ_ONLY_CONSTRAINT) {
- ;
- } else {
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::UnsupportedTriggerType;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- // check the table
- const Uint32 tableId = req->getTableId();
- if (! (tableId < c_tableRecordPool.getSize())) {
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::InvalidTable;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- if (tablePtr.p->tabState != TableRecord::DEFINED &&
- tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) {
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::InvalidTable;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
-}
-
-void
-Dbdict::createTrigger_masterSeize(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- TriggerRecordPtr triggerPtr;
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
- triggerPtr.i = opPtr.p->m_request.getTriggerId();
- } else {
- triggerPtr.i = getFreeTriggerRecord();
- if (triggerPtr.i == RNIL) {
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::TooManyTriggers;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- }
- c_triggerRecordPool.getPtr(triggerPtr);
- initialiseTriggerRecord(triggerPtr);
- triggerPtr.p->triggerState = TriggerRecord::TS_DEFINING;
- opPtr.p->m_request.setTriggerId(triggerPtr.i);
-}
-
-void
-Dbdict::createTrigger_slaveCreate(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- jam();
- const CreateTrigReq* const req = &opPtr.p->m_request;
- // get the trigger record
- const Uint32 triggerId = req->getTriggerId();
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, triggerId);
- initialiseTriggerRecord(triggerPtr);
- // fill in trigger data
- {
- Rope name(c_rope_pool, triggerPtr.p->triggerName);
- if(!name.assign(opPtr.p->m_triggerName))
- {
- opPtr.p->m_errorCode = (CreateTrigRef::ErrorCode)CreateTableRef::OutOfStringBuffer;
- return;
- }
- }
- triggerPtr.p->triggerId = triggerId;
- triggerPtr.p->tableId = req->getTableId();
- triggerPtr.p->indexId = RNIL;
- triggerPtr.p->triggerType = req->getTriggerType();
- triggerPtr.p->triggerActionTime = req->getTriggerActionTime();
- triggerPtr.p->triggerEvent = req->getTriggerEvent();
- triggerPtr.p->monitorReplicas = req->getMonitorReplicas();
- triggerPtr.p->monitorAllAttributes = req->getMonitorAllAttributes();
- triggerPtr.p->reportAllMonitoredAttributes = req->getReportAllMonitoredAttributes();
- triggerPtr.p->attributeMask = req->getAttributeMask();
- triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
- // add to hash table
- // ndbout_c("++++++++++++ Adding trigger id %u, %s", triggerPtr.p->triggerId, triggerPtr.p->triggerName);
- {
- Ptr<DictObject> obj_ptr;
- ndbrequire(c_obj_hash.seize(obj_ptr));
- obj_ptr.p->m_name = triggerPtr.p->triggerName;
- obj_ptr.p->m_id = triggerId;
- obj_ptr.p->m_type = triggerPtr.p->triggerType;
- obj_ptr.p->m_ref_count = 0;
- c_obj_hash.add(obj_ptr);
- triggerPtr.p->m_obj_ptr_i = obj_ptr.i;
- }
- if (triggerPtr.p->triggerType == TriggerType::SECONDARY_INDEX ||
- triggerPtr.p->triggerType == TriggerType::ORDERED_INDEX) {
- jam();
- // connect to index record XXX should be done in caller instead
- triggerPtr.p->indexId = req->getIndexId();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
- switch (triggerPtr.p->triggerEvent) {
- case TriggerEvent::TE_INSERT:
- indexPtr.p->insertTriggerId = triggerPtr.p->triggerId;
- break;
- case TriggerEvent::TE_UPDATE:
- indexPtr.p->updateTriggerId = triggerPtr.p->triggerId;
- break;
- case TriggerEvent::TE_DELETE:
- indexPtr.p->deleteTriggerId = triggerPtr.p->triggerId;
- break;
- case TriggerEvent::TE_CUSTOM:
- indexPtr.p->customTriggerId = triggerPtr.p->triggerId;
- break;
- default:
- ndbrequire(false);
- break;
- }
- }
- if (triggerPtr.p->triggerType == TriggerType::READ_ONLY_CONSTRAINT) {
- jam();
- // connect to index record XXX should be done in caller instead
- triggerPtr.p->indexId = req->getTableId();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
- indexPtr.p->buildTriggerId = triggerPtr.p->triggerId;
- }
-}
-
-void
-Dbdict::createTrigger_toAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- jam();
- AlterTrigReq* req = (AlterTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(AlterTrigReq::RT_CREATE_TRIGGER);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- req->setTableId(opPtr.p->m_request.getTableId());
- req->setTriggerId(opPtr.p->m_request.getTriggerId());
- req->setTriggerInfo(0); // not used
- req->setOnline(true);
- req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
- sendSignal(reference(), GSN_ALTER_TRIG_REQ,
- signal, AlterTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::createTrigger_fromAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- jam();
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
- createTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- opPtr.p->m_requestType = CreateTrigReq::RT_DICT_COMMIT;
- createTrigger_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::createTrigger_slaveCommit(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- jam();
- const CreateTrigReq* const req = &opPtr.p->m_request;
- // get the trigger record
- const Uint32 triggerId = req->getTriggerId();
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, triggerId);
- if (! req->getOnline()) {
- triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
- } else {
- ndbrequire(triggerPtr.p->triggerState == TriggerRecord::TS_ONLINE);
- }
-}
-
-void
-Dbdict::createTrigger_slaveAbort(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- jam();
-}
-
-void
-Dbdict::createTrigger_sendSlaveReq(Signal* signal, OpCreateTriggerPtr opPtr)
-{
- CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
- *req = opPtr.p->m_request;
- req->setUserRef(opPtr.p->m_coordinatorRef);
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(opPtr.p->m_requestType);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- NdbNodeBitmask receiverNodes = c_aliveNodes;
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
- receiverNodes.clear();
- receiverNodes.set(getOwnNodeId());
- }
- opPtr.p->m_signalCounter = receiverNodes;
- NodeReceiverGroup rg(DBDICT, receiverNodes);
- sendSignal(rg, GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::createTrigger_sendReply(Signal* signal, OpCreateTriggerPtr opPtr,
- bool toUser)
-{
- CreateTrigRef* rep = (CreateTrigRef*)signal->getDataPtrSend();
- Uint32 gsn = GSN_CREATE_TRIG_CONF;
- Uint32 length = CreateTrigConf::InternalLength;
- bool sendRef;
- if (! toUser) {
- sendRef = opPtr.p->hasLastError();
- rep->setUserRef(opPtr.p->m_coordinatorRef);
- rep->setConnectionPtr(opPtr.p->key);
- rep->setRequestType(opPtr.p->m_requestType);
- if (opPtr.p->m_requestType == CreateTrigReq::RT_DICT_ABORT)
- sendRef = false;
- } else {
- sendRef = opPtr.p->hasError();
- rep->setUserRef(opPtr.p->m_request.getUserRef());
- rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
- rep->setRequestType(opPtr.p->m_request.getRequestType());
- length = CreateTrigConf::SignalLength;
- }
- rep->setTableId(opPtr.p->m_request.getTableId());
- rep->setIndexId(opPtr.p->m_request.getIndexId());
- rep->setTriggerId(opPtr.p->m_request.getTriggerId());
- rep->setTriggerInfo(opPtr.p->m_request.getTriggerInfo());
- if (sendRef) {
- if (opPtr.p->m_errorNode == 0)
- opPtr.p->m_errorNode = getOwnNodeId();
- rep->setErrorCode(opPtr.p->m_errorCode);
- rep->setErrorLine(opPtr.p->m_errorLine);
- rep->setErrorNode(opPtr.p->m_errorNode);
- gsn = GSN_CREATE_TRIG_REF;
- length = CreateTrigRef::SignalLength;
- }
- sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
-}
-
-/**
- * MODULE: Drop trigger.
- */
-
-void
-Dbdict::execDROP_TRIG_REQ(Signal* signal)
-{
- jamEntry();
- DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
- OpDropTriggerPtr opPtr;
- const Uint32 senderRef = signal->senderBlockRef();
- const DropTrigReq::RequestType requestType = req->getRequestType();
-
- if (signal->getNoOfSections() > 0) {
- ndbrequire(signal->getNoOfSections() == 1);
- jam();
- char triggerName[MAX_TAB_NAME_SIZE];
- OpDropTrigger opTmp;
- opPtr.p=&opTmp;
-
- SegmentedSectionPtr ssPtr;
- signal->getSection(ssPtr, DropTrigReq::TRIGGER_NAME_SECTION);
- SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
- if (ssReader.getKey() != DropTrigReq::TriggerNameKey ||
- ! ssReader.getString(triggerName)) {
- jam();
- opPtr.p->m_errorCode = DropTrigRef::InvalidName;
- opPtr.p->m_errorLine = __LINE__;
- releaseSections(signal);
- dropTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- releaseSections(signal);
-
- //ndbout_c("++++++++++++++ Looking for trigger %s", keyRecord.triggerName);
- DictObject * obj_ptr_p = get_object(triggerName);
- if (obj_ptr_p == 0){
- jam();
- req->setTriggerId(RNIL);
- } else {
- jam();
- //ndbout_c("++++++++++ Found trigger %s", triggerPtr.p->triggerName);
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, obj_ptr_p->m_id);
- req->setTriggerId(triggerPtr.p->triggerId);
- req->setTableId(triggerPtr.p->tableId);
- }
- }
- if (requestType == DropTrigReq::RT_USER ||
- requestType == DropTrigReq::RT_ALTER_INDEX ||
- requestType == DropTrigReq::RT_BUILD_INDEX) {
- jam();
- if (signal->getLength() == DropTrigReq::SignalLength) {
- if (getOwnNodeId() != c_masterNodeId) {
- jam();
- // forward to DICT master
- sendSignal(calcDictBlockRef(c_masterNodeId), GSN_DROP_TRIG_REQ,
- signal, signal->getLength(), JBB);
- return;
- }
- if (!c_triggerRecordPool.findId(req->getTriggerId())) {
- jam();
- // return to sender
- OpDropTrigger opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- if (! (req->getRequestFlag() & RequestFlag::RF_FORCE)) {
- opPtr.p->m_errorCode = DropTrigRef::TriggerNotFound;
- opPtr.p->m_errorLine = __LINE__;
- }
- dropTrigger_sendReply(signal, opPtr, true);
- return;
- }
- // forward initial request plus operation key to all
- req->setOpKey(++c_opRecordSequence);
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength + 1, JBB);
- return;
- }
- // seize operation record
- ndbrequire(signal->getLength() == DropTrigReq::SignalLength + 1);
- const Uint32 opKey = req->getOpKey();
- OpDropTrigger opBusy;
- if (! c_opDropTrigger.seize(opPtr))
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_coordinatorRef = senderRef;
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = opKey;
- opPtr.p->m_requestType = DropTrigReq::RT_DICT_PREPARE;
- if (opPtr.p == &opBusy) {
- jam();
- opPtr.p->m_errorCode = DropTrigRef::Busy;
- opPtr.p->m_errorLine = __LINE__;
- dropTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- c_opDropTrigger.add(opPtr);
- // master expects to hear from all
- if (opPtr.p->m_isMaster)
- opPtr.p->m_signalCounter = c_aliveNodes;
- dropTrigger_slavePrepare(signal, opPtr);
- dropTrigger_sendReply(signal, opPtr, false);
- return;
- }
- c_opDropTrigger.find(opPtr, req->getConnectionPtr());
- if (! opPtr.isNull()) {
- opPtr.p->m_requestType = requestType;
- if (requestType == DropTrigReq::RT_DICT_COMMIT ||
- requestType == DropTrigReq::RT_DICT_ABORT) {
- jam();
- if (requestType == DropTrigReq::RT_DICT_COMMIT)
- dropTrigger_slaveCommit(signal, opPtr);
- else
- dropTrigger_slaveAbort(signal, opPtr);
- dropTrigger_sendReply(signal, opPtr, false);
- // done in slave
- if (! opPtr.p->m_isMaster)
- c_opDropTrigger.release(opPtr);
- return;
- }
- }
- jam();
- // return to sender
- OpDropTrigger opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = DropTrigRef::BadRequestType;
- opPtr.p->m_errorLine = __LINE__;
- dropTrigger_sendReply(signal, opPtr, true);
-}
-
-void
-Dbdict::execDROP_TRIG_CONF(Signal* signal)
-{
- jamEntry();
- DropTrigConf* conf = (DropTrigConf*)signal->getDataPtrSend();
- dropTrigger_recvReply(signal, conf, 0);
-}
-
-void
-Dbdict::execDROP_TRIG_REF(Signal* signal)
-{
- jamEntry();
- DropTrigRef* ref = (DropTrigRef*)signal->getDataPtrSend();
- dropTrigger_recvReply(signal, ref->getConf(), ref);
-}
-
-void
-Dbdict::dropTrigger_recvReply(Signal* signal, const DropTrigConf* conf,
- const DropTrigRef* ref)
-{
- jam();
- const Uint32 senderRef = signal->senderBlockRef();
- const DropTrigReq::RequestType requestType = conf->getRequestType();
- const Uint32 key = conf->getConnectionPtr();
- if (requestType == DropTrigReq::RT_ALTER_INDEX) {
- jam();
- // part of alter index operation
- OpAlterIndexPtr opPtr;
- c_opAlterIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- alterIndex_fromDropTrigger(signal, opPtr);
- return;
- }
- if (requestType == DropTrigReq::RT_BUILD_INDEX) {
- jam();
- // part of build index operation
- OpBuildIndexPtr opPtr;
- c_opBuildIndex.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- buildIndex_fromDropConstr(signal, opPtr);
- return;
- }
- if (requestType == DropTrigReq::RT_TC ||
- requestType == DropTrigReq::RT_LQH) {
- jam();
- // part of alter trigger operation
- OpAlterTriggerPtr opPtr;
- c_opAlterTrigger.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- alterTrigger_fromDropLocal(signal, opPtr);
- return;
- }
- OpDropTriggerPtr opPtr;
- c_opDropTrigger.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- ndbrequire(opPtr.p->m_isMaster);
- ndbrequire(opPtr.p->m_requestType == requestType);
- opPtr.p->setError(ref);
- opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
- if (! opPtr.p->m_signalCounter.done()) {
- jam();
- return;
- }
- if (requestType == DropTrigReq::RT_DICT_COMMIT ||
- requestType == DropTrigReq::RT_DICT_ABORT) {
- jam();
- // send reply to user
- dropTrigger_sendReply(signal, opPtr, true);
- c_opDropTrigger.release(opPtr);
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = DropTrigReq::RT_DICT_ABORT;
- dropTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == DropTrigReq::RT_DICT_PREPARE) {
- jam();
- // start alter offline
- dropTrigger_toAlterTrigger(signal, opPtr);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::dropTrigger_slavePrepare(Signal* signal, OpDropTriggerPtr opPtr)
-{
- jam();
-}
-
-void
-Dbdict::dropTrigger_toAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr)
-{
- jam();
- AlterTrigReq* req = (AlterTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(AlterTrigReq::RT_DROP_TRIGGER);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- req->setTableId(opPtr.p->m_request.getTableId());
- req->setTriggerId(opPtr.p->m_request.getTriggerId());
- req->setTriggerInfo(0); // not used
- req->setOnline(false);
- req->setReceiverRef(0);
- sendSignal(reference(), GSN_ALTER_TRIG_REQ,
- signal, AlterTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::dropTrigger_fromAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr)
-{
- jam();
- // remove in all
- opPtr.p->m_requestType = DropTrigReq::RT_DICT_COMMIT;
- dropTrigger_sendSlaveReq(signal, opPtr);
-}
-
-void
-Dbdict::dropTrigger_sendSlaveReq(Signal* signal, OpDropTriggerPtr opPtr)
-{
- DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
- *req = opPtr.p->m_request;
- req->setUserRef(opPtr.p->m_coordinatorRef);
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(opPtr.p->m_requestType);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- opPtr.p->m_signalCounter = c_aliveNodes;
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- sendSignal(rg, GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::dropTrigger_slaveCommit(Signal* signal, OpDropTriggerPtr opPtr)
-{
- jam();
- const DropTrigReq* const req = &opPtr.p->m_request;
- // get trigger record
- const Uint32 triggerId = req->getTriggerId();
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, triggerId);
- if (triggerPtr.p->triggerType == TriggerType::SECONDARY_INDEX ||
- triggerPtr.p->triggerType == TriggerType::ORDERED_INDEX) {
- jam();
- // disconnect from index if index trigger XXX move to drop index
- triggerPtr.p->indexId = req->getIndexId();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
- ndbrequire(! indexPtr.isNull());
- switch (triggerPtr.p->triggerEvent) {
- case TriggerEvent::TE_INSERT:
- indexPtr.p->insertTriggerId = RNIL;
- break;
- case TriggerEvent::TE_UPDATE:
- indexPtr.p->updateTriggerId = RNIL;
- break;
- case TriggerEvent::TE_DELETE:
- indexPtr.p->deleteTriggerId = RNIL;
- break;
- case TriggerEvent::TE_CUSTOM:
- indexPtr.p->customTriggerId = RNIL;
- break;
- default:
- ndbrequire(false);
- break;
- }
- }
- if (triggerPtr.p->triggerType == TriggerType::READ_ONLY_CONSTRAINT) {
- jam();
- // disconnect from index record XXX should be done in caller instead
- triggerPtr.p->indexId = req->getTableId();
- TableRecordPtr indexPtr;
- c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
- indexPtr.p->buildTriggerId = RNIL;
- }
- //remove trigger
- //ndbout_c("++++++++++++ Removing trigger id %u, %s", triggerPtr.p->triggerId, triggerPtr.p->triggerName);
- release_object(triggerPtr.p->m_obj_ptr_i);
- triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
-}
-
-void
-Dbdict::dropTrigger_slaveAbort(Signal* signal, OpDropTriggerPtr opPtr)
-{
- jam();
-}
-
-void
-Dbdict::dropTrigger_sendReply(Signal* signal, OpDropTriggerPtr opPtr,
- bool toUser)
-{
- DropTrigRef* rep = (DropTrigRef*)signal->getDataPtrSend();
- Uint32 gsn = GSN_DROP_TRIG_CONF;
- Uint32 length = DropTrigConf::InternalLength;
- bool sendRef;
- if (! toUser) {
- sendRef = opPtr.p->hasLastError();
- rep->setUserRef(opPtr.p->m_coordinatorRef);
- rep->setConnectionPtr(opPtr.p->key);
- rep->setRequestType(opPtr.p->m_requestType);
- if (opPtr.p->m_requestType == DropTrigReq::RT_DICT_ABORT)
- sendRef = false;
- } else {
- sendRef = opPtr.p->hasError();
- rep->setUserRef(opPtr.p->m_request.getUserRef());
- rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
- rep->setRequestType(opPtr.p->m_request.getRequestType());
- length = DropTrigConf::SignalLength;
- }
- rep->setTableId(opPtr.p->m_request.getTableId());
- rep->setIndexId(opPtr.p->m_request.getIndexId());
- rep->setTriggerId(opPtr.p->m_request.getTriggerId());
- if (sendRef) {
- if (opPtr.p->m_errorNode == 0)
- opPtr.p->m_errorNode = getOwnNodeId();
- rep->setErrorCode(opPtr.p->m_errorCode);
- rep->setErrorLine(opPtr.p->m_errorLine);
- rep->setErrorNode(opPtr.p->m_errorNode);
- gsn = GSN_DROP_TRIG_REF;
- length = CreateTrigRef::SignalLength;
- }
- sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
-}
-
-/**
- * MODULE: Alter trigger.
- *
- * Alter trigger state. Alter online creates the trigger first in all
- * TC (if index trigger) and then in all LQH-TUP.
- *
- * Request type received in REQ and returned in CONF/REF:
- *
- * RT_USER - normal user e.g. BACKUP
- * RT_CREATE_TRIGGER - from create trigger
- * RT_DROP_TRIGGER - from drop trigger
- * RT_DICT_PREPARE - seize operations and check request
- * RT_DICT_TC - master to each DICT on way to TC
- * RT_DICT_LQH - master to each DICT on way to LQH-TUP
- * RT_DICT_COMMIT - commit state change in each DICT (no reply)
- */
-
-void
-Dbdict::execALTER_TRIG_REQ(Signal* signal)
-{
- jamEntry();
- AlterTrigReq* const req = (AlterTrigReq*)signal->getDataPtrSend();
- OpAlterTriggerPtr opPtr;
- const Uint32 senderRef = signal->senderBlockRef();
- const AlterTrigReq::RequestType requestType = req->getRequestType();
- if (requestType == AlterTrigReq::RT_USER ||
- requestType == AlterTrigReq::RT_CREATE_TRIGGER ||
- requestType == AlterTrigReq::RT_DROP_TRIGGER) {
- jam();
- const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
- NdbNodeBitmask receiverNodes = c_aliveNodes;
- if (isLocal) {
- receiverNodes.clear();
- receiverNodes.set(getOwnNodeId());
- }
- if (signal->getLength() == AlterTrigReq::SignalLength) {
- jam();
- if (! isLocal && getOwnNodeId() != c_masterNodeId) {
- jam();
- // forward to DICT master
- sendSignal(calcDictBlockRef(c_masterNodeId), GSN_ALTER_TRIG_REQ,
- signal, AlterTrigReq::SignalLength, JBB);
- return;
- }
- // forward initial request plus operation key to all
- req->setOpKey(++c_opRecordSequence);
- NodeReceiverGroup rg(DBDICT, receiverNodes);
- sendSignal(rg, GSN_ALTER_TRIG_REQ,
- signal, AlterTrigReq::SignalLength + 1, JBB);
- return;
- }
- // seize operation record
- ndbrequire(signal->getLength() == AlterTrigReq::SignalLength + 1);
- const Uint32 opKey = req->getOpKey();
- OpAlterTrigger opBusy;
- if (! c_opAlterTrigger.seize(opPtr))
- opPtr.p = &opBusy;
- opPtr.p->save(req);
- opPtr.p->m_coordinatorRef = senderRef;
- opPtr.p->m_isMaster = (senderRef == reference());
- opPtr.p->key = opKey;
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_PREPARE;
- if (opPtr.p == &opBusy) {
- jam();
- opPtr.p->m_errorCode = AlterTrigRef::Busy;
- opPtr.p->m_errorLine = __LINE__;
- alterTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
- c_opAlterTrigger.add(opPtr);
- // master expects to hear from all
- if (opPtr.p->m_isMaster) {
- opPtr.p->m_nodes = receiverNodes;
- opPtr.p->m_signalCounter = receiverNodes;
- }
- alterTrigger_slavePrepare(signal, opPtr);
- alterTrigger_sendReply(signal, opPtr, false);
- return;
- }
- c_opAlterTrigger.find(opPtr, req->getConnectionPtr());
- if (! opPtr.isNull()) {
- opPtr.p->m_requestType = requestType;
- if (requestType == AlterTrigReq::RT_DICT_TC ||
- requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- if (req->getOnline())
- alterTrigger_toCreateLocal(signal, opPtr);
- else
- alterTrigger_toDropLocal(signal, opPtr);
- return;
- }
- if (requestType == AlterTrigReq::RT_DICT_COMMIT ||
- requestType == AlterTrigReq::RT_DICT_ABORT) {
- jam();
- if (requestType == AlterTrigReq::RT_DICT_COMMIT)
- alterTrigger_slaveCommit(signal, opPtr);
- else
- alterTrigger_slaveAbort(signal, opPtr);
- alterTrigger_sendReply(signal, opPtr, false);
- // done in slave
- if (! opPtr.p->m_isMaster)
- c_opAlterTrigger.release(opPtr);
- return;
- }
- }
- jam();
- // return to sender
- OpAlterTrigger opBad;
- opPtr.p = &opBad;
- opPtr.p->save(req);
- opPtr.p->m_errorCode = AlterTrigRef::BadRequestType;
- opPtr.p->m_errorLine = __LINE__;
- alterTrigger_sendReply(signal, opPtr, true);
- return;
-}
-
-void
-Dbdict::execALTER_TRIG_CONF(Signal* signal)
-{
- jamEntry();
- AlterTrigConf* conf = (AlterTrigConf*)signal->getDataPtrSend();
- alterTrigger_recvReply(signal, conf, 0);
-}
-
-void
-Dbdict::execALTER_TRIG_REF(Signal* signal)
-{
- jamEntry();
- AlterTrigRef* ref = (AlterTrigRef*)signal->getDataPtrSend();
- alterTrigger_recvReply(signal, ref->getConf(), ref);
-}
-
-void
-Dbdict::alterTrigger_recvReply(Signal* signal, const AlterTrigConf* conf,
- const AlterTrigRef* ref)
-{
- jam();
- const Uint32 senderRef = signal->senderBlockRef();
- const AlterTrigReq::RequestType requestType = conf->getRequestType();
- const Uint32 key = conf->getConnectionPtr();
- if (requestType == AlterTrigReq::RT_CREATE_TRIGGER) {
- jam();
- // part of create trigger operation
- OpCreateTriggerPtr opPtr;
- c_opCreateTrigger.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- createTrigger_fromAlterTrigger(signal, opPtr);
- return;
- }
- if (requestType == AlterTrigReq::RT_DROP_TRIGGER) {
- jam();
- // part of drop trigger operation
- OpDropTriggerPtr opPtr;
- c_opDropTrigger.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- opPtr.p->setError(ref);
- dropTrigger_fromAlterTrigger(signal, opPtr);
- return;
- }
- OpAlterTriggerPtr opPtr;
- c_opAlterTrigger.find(opPtr, key);
- ndbrequire(! opPtr.isNull());
- ndbrequire(opPtr.p->m_isMaster);
- ndbrequire(opPtr.p->m_requestType == requestType);
- /*
- * If refuse on drop trig, because of non-existent trigger,
- * comes from anyone but the master node - ignore it and
- * remove the node from forter ALTER_TRIG communication
- * This will happen if a new node has started since the
- * trigger whas created.
- */
- if (ref &&
- refToNode(senderRef) != refToNode(reference()) &&
- opPtr.p->m_request.getRequestType() == AlterTrigReq::RT_DROP_TRIGGER &&
- ref->getErrorCode() == AlterTrigRef::TriggerNotFound) {
- jam();
- ref = 0; // ignore this error
- opPtr.p->m_nodes.clear(refToNode(senderRef)); // remove this from group
- }
- opPtr.p->setError(ref);
- opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
- if (! opPtr.p->m_signalCounter.done()) {
- jam();
- return;
- }
- if (requestType == AlterTrigReq::RT_DICT_COMMIT ||
- requestType == AlterTrigReq::RT_DICT_ABORT) {
- jam();
- // send reply to user
- alterTrigger_sendReply(signal, opPtr, true);
- c_opAlterTrigger.release(opPtr);
- return;
- }
- if (opPtr.p->hasError()) {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_ABORT;
- alterTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- if (! (opPtr.p->m_request.getRequestFlag() & RequestFlag::RF_NOTCTRIGGER)) {
- if (requestType == AlterTrigReq::RT_DICT_PREPARE) {
- jam();
- if (opPtr.p->m_request.getOnline()) {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
- } else {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
- }
- alterTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == AlterTrigReq::RT_DICT_TC) {
- jam();
- if (opPtr.p->m_request.getOnline()) {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
- } else {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
- }
- alterTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- if (opPtr.p->m_request.getOnline()) {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
- } else {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
- }
- alterTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- } else {
- if (requestType == AlterTrigReq::RT_DICT_PREPARE) {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
- alterTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- if (requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
- alterTrigger_sendSlaveReq(signal, opPtr);
- return;
- }
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::alterTrigger_slavePrepare(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- jam();
- const AlterTrigReq* const req = &opPtr.p->m_request;
- const Uint32 triggerId = req->getTriggerId();
- TriggerRecordPtr triggerPtr;
- if (! (triggerId < c_triggerRecordPool.getSize())) {
- jam();
- opPtr.p->m_errorCode = AlterTrigRef::TriggerNotFound;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
- c_triggerRecordPool.getPtr(triggerPtr, triggerId);
- if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED) {
- jam();
- opPtr.p->m_errorCode = AlterTrigRef::TriggerNotFound;
- opPtr.p->m_errorLine = __LINE__;
- return;
- }
-
- if (triggerPtr.p->triggerType == TriggerType::SUBSCRIPTION)
- {
- opPtr.p->m_request.addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
- }
-}
-
-void
-Dbdict::alterTrigger_toCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- jam();
- // find trigger record
- const Uint32 triggerId = opPtr.p->m_request.getTriggerId();
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, triggerId);
- CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
- jam();
- req->setRequestType(CreateTrigReq::RT_TC);
- } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- req->setRequestType(CreateTrigReq::RT_LQH);
- } else {
- ndbassert(false);
- }
- req->setTableId(triggerPtr.p->tableId);
- req->setIndexId(triggerPtr.p->indexId);
- req->setTriggerId(triggerPtr.i);
- req->setTriggerType(triggerPtr.p->triggerType);
- req->setTriggerActionTime(triggerPtr.p->triggerActionTime);
- req->setTriggerEvent(triggerPtr.p->triggerEvent);
- req->setMonitorReplicas(triggerPtr.p->monitorReplicas);
- req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
- req->setReportAllMonitoredAttributes(triggerPtr.p->reportAllMonitoredAttributes);
- req->setOnline(true);
- req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
- BlockReference blockRef = 0;
- if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
- jam();
- blockRef = calcTcBlockRef(getOwnNodeId());
- } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- blockRef = calcLqhBlockRef(getOwnNodeId());
- } else {
- ndbassert(false);
- }
- req->setAttributeMask(triggerPtr.p->attributeMask);
- sendSignal(blockRef, GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::alterTrigger_fromCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- jam();
- if (! opPtr.p->hasLastError()) {
- // mark created locally
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
- if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
- jam();
- triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_TC;
- } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_LQH;
- } else {
- ndbrequire(false);
- }
- }
- // forward CONF or REF to master
- alterTrigger_sendReply(signal, opPtr, false);
-}
-
-void
-Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- jam();
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
- DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
- req->setUserRef(reference());
- req->setConnectionPtr(opPtr.p->key);
- if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
- jam();
- // broken trigger allowed if force
- if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_TC)) {
- jam();
- ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
- alterTrigger_sendReply(signal, opPtr, false);
- return;
- }
- req->setRequestType(DropTrigReq::RT_TC);
- } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- // 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;
- }
- req->setRequestType(DropTrigReq::RT_LQH);
- } else {
- ndbassert(false);
- }
- req->setTableId(triggerPtr.p->tableId);
- req->setIndexId(triggerPtr.p->indexId);
- req->setTriggerId(triggerPtr.i);
- req->setTriggerType(triggerPtr.p->triggerType);
- req->setTriggerActionTime(triggerPtr.p->triggerActionTime);
- req->setTriggerEvent(triggerPtr.p->triggerEvent);
- req->setMonitorReplicas(triggerPtr.p->monitorReplicas);
- req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
- BlockReference blockRef = 0;
- if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
- jam();
- blockRef = calcTcBlockRef(getOwnNodeId());
- } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- blockRef = calcLqhBlockRef(getOwnNodeId());
- } else {
- ndbassert(false);
- }
- sendSignal(blockRef, GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::alterTrigger_fromDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- jam();
- if (! opPtr.p->hasLastError()) {
- // mark dropped locally
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
- if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
- jam();
- triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_TC;
- } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
- jam();
- triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_LQH;
- } else {
- ndbrequire(false);
- }
- }
- // forward CONF or REF to master
- alterTrigger_sendReply(signal, opPtr, false);
-}
-
-void
-Dbdict::alterTrigger_slaveCommit(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- jam();
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
- // set state
- triggerPtr.p->triggerState = TriggerRecord::TS_ONLINE;
-}
-
-void
-Dbdict::alterTrigger_slaveAbort(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- jam();
-}
-
-void
-Dbdict::alterTrigger_sendSlaveReq(Signal* signal, OpAlterTriggerPtr opPtr)
-{
- AlterTrigReq* const req = (AlterTrigReq*)signal->getDataPtrSend();
- *req = opPtr.p->m_request;
- req->setUserRef(opPtr.p->m_coordinatorRef);
- req->setConnectionPtr(opPtr.p->key);
- req->setRequestType(opPtr.p->m_requestType);
- req->addRequestFlag(opPtr.p->m_requestFlag);
- NdbNodeBitmask receiverNodes = c_aliveNodes;
- if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
- receiverNodes.clear();
- receiverNodes.set(getOwnNodeId());
- } else {
- opPtr.p->m_nodes.bitAND(receiverNodes);
- receiverNodes = opPtr.p->m_nodes;
- }
- opPtr.p->m_signalCounter = receiverNodes;
- NodeReceiverGroup rg(DBDICT, receiverNodes);
- sendSignal(rg, GSN_ALTER_TRIG_REQ,
- signal, AlterTrigReq::SignalLength, JBB);
-}
-
-void
-Dbdict::alterTrigger_sendReply(Signal* signal, OpAlterTriggerPtr opPtr,
- bool toUser)
-{
- jam();
- AlterTrigRef* rep = (AlterTrigRef*)signal->getDataPtrSend();
- Uint32 gsn = GSN_ALTER_TRIG_CONF;
- Uint32 length = AlterTrigConf::InternalLength;
- bool sendRef;
- if (! toUser) {
- sendRef = opPtr.p->hasLastError();
- rep->setUserRef(opPtr.p->m_coordinatorRef);
- rep->setConnectionPtr(opPtr.p->key);
- rep->setRequestType(opPtr.p->m_requestType);
- if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_ABORT) {
- jam();
- sendRef = false;
- } else {
- jam();
- }
- } else {
- sendRef = opPtr.p->hasError();
- jam();
- rep->setUserRef(opPtr.p->m_request.getUserRef());
- rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
- rep->setRequestType(opPtr.p->m_request.getRequestType());
- length = AlterTrigConf::SignalLength;
- }
- rep->setTableId(opPtr.p->m_request.getTableId());
- rep->setTriggerId(opPtr.p->m_request.getTriggerId());
- if (sendRef) {
- if (opPtr.p->m_errorNode == 0) {
- jam();
- opPtr.p->m_errorNode = getOwnNodeId();
- } else {
- jam();
- }
- rep->setErrorCode(opPtr.p->m_errorCode);
- rep->setErrorLine(opPtr.p->m_errorLine);
- rep->setErrorNode(opPtr.p->m_errorNode);
- gsn = GSN_ALTER_TRIG_REF;
- length = AlterTrigRef::SignalLength;
- }
- sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
-}
-
-/**
- * MODULE: Support routines for index and trigger.
- */
-
-/*
- This routine is used to set-up the primary key attributes of the unique
- hash index. Since we store fragment id as part of the primary key here
- we insert the pseudo column for getting fragment id first in the array.
- This routine is used as part of the building of the index.
-*/
-
-void
-Dbdict::getTableKeyList(TableRecordPtr tablePtr,
- Id_array<MAX_ATTRIBUTES_IN_INDEX+1>& list)
-{
- jam();
- list.sz = 0;
- list.id[list.sz++] = AttributeHeader::FRAGMENT;
- LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
- tablePtr.p->m_attributes);
- AttributeRecordPtr attrPtr;
- for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
- if (attrPtr.p->tupleKey) {
- list.id[list.sz++] = attrPtr.p->attributeId;
- }
- }
- ndbrequire(list.sz == (uint)(tablePtr.p->noOfPrimkey + 1));
- ndbrequire(list.sz <= MAX_ATTRIBUTES_IN_INDEX + 1);
-}
-
-// XXX should store the primary attribute id
-void
-Dbdict::getIndexAttr(TableRecordPtr indexPtr, Uint32 itAttr, Uint32* id)
-{
- jam();
-
- Uint32 len;
- char name[MAX_ATTR_NAME_SIZE];
- TableRecordPtr tablePtr;
- AttributeRecordPtr attrPtr;
-
- c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
- AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
- {
- ConstRope tmp(c_rope_pool, iaRec->attributeName);
- tmp.copy(name);
- len = tmp.size();
- }
- LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
- tablePtr.p->m_attributes);
- for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)){
- ConstRope tmp(c_rope_pool, attrPtr.p->attributeName);
- if(tmp.compare(name, len) == 0){
- id[0] = attrPtr.p->attributeId;
- return;
- }
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::getIndexAttrList(TableRecordPtr indexPtr, AttributeList& list)
-{
- jam();
- list.sz = 0;
- memset(list.id, 0, sizeof(list.id));
- ndbrequire(indexPtr.p->noOfAttributes >= 2);
-
- LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
- indexPtr.p->m_attributes);
- AttributeRecordPtr attrPtr;
- for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
- // skip last
- AttributeRecordPtr tempPtr = attrPtr;
- if (! alist.next(tempPtr))
- break;
- getIndexAttr(indexPtr, attrPtr.i, &list.id[list.sz++]);
- }
- ndbrequire(indexPtr.p->noOfAttributes == list.sz + 1);
-}
-
-void
-Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
-{
- jam();
- mask.clear();
- ndbrequire(indexPtr.p->noOfAttributes >= 2);
-
- AttributeRecordPtr attrPtr, currPtr;
- LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
- indexPtr.p->m_attributes);
-
-
- for (alist.first(attrPtr); currPtr = attrPtr, alist.next(attrPtr); ){
- Uint32 id;
- getIndexAttr(indexPtr, currPtr.i, &id);
- mask.set(id);
- }
-}
-
-// DICT lock master
-
-const Dbdict::DictLockType*
-Dbdict::getDictLockType(Uint32 lockType)
-{
- static const DictLockType lt[] = {
- { DictLockReq::NodeRestartLock, BS_NODE_RESTART, "NodeRestart" }
- };
- for (unsigned int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
- if ((Uint32) 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");
-}
-
-// only table and index ops are checked
-bool
-Dbdict::hasDictLockSchemaOp()
-{
- return
- ! c_opCreateTable.isEmpty() ||
- ! c_opDropTable.isEmpty() ||
- ! c_opCreateIndex.isEmpty() ||
- ! c_opDropIndex.isEmpty();
-}
-
-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 (hasDictLockSchemaOp()) {
- jam();
- break;
- }
-
- if (c_blockState != BS_IDLE)
- {
- /**
- * If state is BS_NODE_FAILURE, it might be that no op is running
- */
- 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((Uint32) lockPtr.p->lt->lockType == ord->lockType);
-
- if (lockPtr.p->locked) {
- jam();
- ndbrequire(c_blockState == lockPtr.p->lt->blockState);
- ndbrequire(! hasDictLockSchemaOp());
- 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(! hasDictLockSchemaOp());
- 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---------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* General module used to store the schema file on disk and */
-/* similar function to restore it from disk. */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-void
-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;
-
- 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::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((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
-}
-
-bool
-Dbdict::validateChecksum(const XSchemaFile * xsf){
-
- 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
-Dbdict::computeChecksum(const Uint32 * src, Uint32 len){
- Uint32 ret = 0;
- for(Uint32 i = 0; i<len; i++)
- ret ^= src[i];
- return ret;
-}
-
-SchemaFile::TableEntry *
-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];
-}
-
-//******************************************
-void
-Dbdict::execCREATE_FILE_REQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- CreateFileReq * req = (CreateFileReq*)signal->getDataPtr();
- CreateFileRef * ref = (CreateFileRef*)signal->getDataPtrSend();
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- Uint32 type = req->objType;
- Uint32 requestInfo = req->requestInfo;
-
- do {
- if(getOwnNodeId() != c_masterNodeId){
- jam();
- ref->errorCode = CreateFileRef::NotMaster;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (c_blockState != BS_IDLE){
- jam();
- ref->errorCode = CreateFileRef::Busy;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (checkSingleUserMode(senderRef))
- {
- ref->errorCode = CreateFileRef::SingleUser;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- Ptr<SchemaTransaction> trans_ptr;
- if (! c_Trans.seize(trans_ptr)){
- jam();
- ref->errorCode = CreateFileRef::Busy;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
- jam();
- const Uint32 trans_key = ++c_opRecordSequence;
- trans_ptr.p->key = trans_key;
- trans_ptr.p->m_senderRef = senderRef;
- trans_ptr.p->m_senderData = senderData;
- trans_ptr.p->m_nodes = c_aliveNodes;
- trans_ptr.p->m_errorCode = 0;
-// trans_ptr.p->m_nodes.clear();
-// trans_ptr.p->m_nodes.set(getOwnNodeId());
- c_Trans.add(trans_ptr);
-
- const Uint32 op_key = ++c_opRecordSequence;
- trans_ptr.p->m_op.m_key = op_key;
- trans_ptr.p->m_op.m_vt_index = 1;
- trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
-
- CreateObjReq* create_obj = (CreateObjReq*)signal->getDataPtrSend();
- create_obj->op_key = op_key;
- create_obj->senderRef = reference();
- create_obj->senderData = trans_key;
- create_obj->clientRef = senderRef;
- create_obj->clientData = senderData;
-
- create_obj->objType = type;
- create_obj->requestInfo = requestInfo;
-
- {
- Uint32 objId = getFreeObjId(0);
- if (objId == RNIL) {
- jam();
- ref->errorCode = CreateFileRef::NoMoreObjectRecords;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- create_obj->objId = objId;
- trans_ptr.p->m_op.m_obj_id = objId;
- create_obj->gci = 0;
-
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry *objEntry = getTableEntry(xsf, objId);
- create_obj->objVersion =
- create_obj_inc_schema_version(objEntry->m_tableVersion);
- }
-
- NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
- SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
- tmp.init<CreateObjRef>(rg, GSN_CREATE_OBJ_REF, trans_key);
- sendSignal(rg, GSN_CREATE_OBJ_REQ, signal,
- CreateObjReq::SignalLength, JBB);
-
- c_blockState = BS_CREATE_TAB;
- return;
- } while(0);
-
- ref->senderData = senderData;
- ref->masterNodeId = c_masterNodeId;
- sendSignal(senderRef, GSN_CREATE_FILE_REF,signal,
- CreateFileRef::SignalLength, JBB);
-}
-
-void
-Dbdict::execCREATE_FILEGROUP_REQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- CreateFilegroupReq * req = (CreateFilegroupReq*)signal->getDataPtr();
- CreateFilegroupRef * ref = (CreateFilegroupRef*)signal->getDataPtrSend();
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- Uint32 type = req->objType;
-
- do {
- if(getOwnNodeId() != c_masterNodeId){
- jam();
- ref->errorCode = CreateFilegroupRef::NotMaster;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (c_blockState != BS_IDLE){
- jam();
- ref->errorCode = CreateFilegroupRef::Busy;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (checkSingleUserMode(senderRef))
- {
- ref->errorCode = CreateFilegroupRef::SingleUser;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- Ptr<SchemaTransaction> trans_ptr;
- if (! c_Trans.seize(trans_ptr)){
- jam();
- ref->errorCode = CreateFilegroupRef::Busy;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
- jam();
- const Uint32 trans_key = ++c_opRecordSequence;
- trans_ptr.p->key = trans_key;
- trans_ptr.p->m_senderRef = senderRef;
- trans_ptr.p->m_senderData = senderData;
- trans_ptr.p->m_nodes = c_aliveNodes;
- trans_ptr.p->m_errorCode = 0;
- c_Trans.add(trans_ptr);
-
- const Uint32 op_key = ++c_opRecordSequence;
- trans_ptr.p->m_op.m_key = op_key;
- trans_ptr.p->m_op.m_vt_index = 0;
- trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
-
- CreateObjReq* create_obj = (CreateObjReq*)signal->getDataPtrSend();
- create_obj->op_key = op_key;
- create_obj->senderRef = reference();
- create_obj->senderData = trans_key;
- create_obj->clientRef = senderRef;
- create_obj->clientData = senderData;
-
- create_obj->objType = type;
-
- {
- Uint32 objId = getFreeObjId(0);
- if (objId == RNIL) {
- jam();
- ref->errorCode = CreateFilegroupRef::NoMoreObjectRecords;
- ref->status = 0;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- create_obj->objId = objId;
- trans_ptr.p->m_op.m_obj_id = objId;
- create_obj->gci = 0;
-
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry *objEntry = getTableEntry(xsf, objId);
- create_obj->objVersion =
- create_obj_inc_schema_version(objEntry->m_tableVersion);
- }
-
- NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
- SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
- tmp.init<CreateObjRef>(rg, GSN_CREATE_OBJ_REF, trans_key);
- sendSignal(rg, GSN_CREATE_OBJ_REQ, signal,
- CreateObjReq::SignalLength, JBB);
-
- c_blockState = BS_CREATE_TAB;
- return;
- } while(0);
-
- ref->senderData = senderData;
- ref->masterNodeId = c_masterNodeId;
- sendSignal(senderRef, GSN_CREATE_FILEGROUP_REF,signal,
- CreateFilegroupRef::SignalLength, JBB);
-}
-
-void
-Dbdict::execDROP_FILE_REQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- DropFileReq * req = (DropFileReq*)signal->getDataPtr();
- DropFileRef * ref = (DropFileRef*)signal->getDataPtrSend();
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- Uint32 objId = req->file_id;
- Uint32 version = req->file_version;
-
- do {
- if(getOwnNodeId() != c_masterNodeId){
- jam();
- ref->errorCode = DropFileRef::NotMaster;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (c_blockState != BS_IDLE)
- {
- jam();
- ref->errorCode = DropFileRef::Busy;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (checkSingleUserMode(senderRef))
- {
- jam();
- ref->errorCode = DropFileRef::SingleUser;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- Ptr<File> file_ptr;
- if (!c_file_hash.find(file_ptr, objId))
- {
- jam();
- ref->errorCode = DropFileRef::NoSuchFile;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (file_ptr.p->m_version != version)
- {
- jam();
- ref->errorCode = DropFileRef::InvalidSchemaObjectVersion;
- ref->errorLine = __LINE__;
- break;
- }
-
- Ptr<SchemaTransaction> trans_ptr;
- if (! c_Trans.seize(trans_ptr))
- {
- jam();
- ref->errorCode = DropFileRef::Busy;
- ref->errorLine = __LINE__;
- break;
- }
- jam();
-
- const Uint32 trans_key = ++c_opRecordSequence;
- trans_ptr.p->key = trans_key;
- trans_ptr.p->m_senderRef = senderRef;
- trans_ptr.p->m_senderData = senderData;
- trans_ptr.p->m_nodes = c_aliveNodes;
- trans_ptr.p->m_errorCode = 0;
- c_Trans.add(trans_ptr);
-
- const Uint32 op_key = ++c_opRecordSequence;
- trans_ptr.p->m_op.m_key = op_key;
- trans_ptr.p->m_op.m_vt_index = 2;
- trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
-
- DropObjReq* drop_obj = (DropObjReq*)signal->getDataPtrSend();
- drop_obj->op_key = op_key;
- drop_obj->objVersion = version;
- drop_obj->objId = objId;
- drop_obj->objType = file_ptr.p->m_type;
- trans_ptr.p->m_op.m_obj_id = objId;
-
- drop_obj->senderRef = reference();
- drop_obj->senderData = trans_key;
- drop_obj->clientRef = senderRef;
- drop_obj->clientData = senderData;
-
- drop_obj->requestInfo = 0;
-
- NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
- SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
- tmp.init<CreateObjRef>(rg, GSN_DROP_OBJ_REF, trans_key);
- sendSignal(rg, GSN_DROP_OBJ_REQ, signal,
- DropObjReq::SignalLength, JBB);
-
- c_blockState = BS_CREATE_TAB;
- return;
- } while(0);
-
- ref->senderData = senderData;
- ref->masterNodeId = c_masterNodeId;
- sendSignal(senderRef, GSN_DROP_FILE_REF,signal,
- DropFileRef::SignalLength, JBB);
-}
-
-void
-Dbdict::execDROP_FILEGROUP_REQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- DropFilegroupReq * req = (DropFilegroupReq*)signal->getDataPtr();
- DropFilegroupRef * ref = (DropFilegroupRef*)signal->getDataPtrSend();
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- Uint32 objId = req->filegroup_id;
- Uint32 version = req->filegroup_version;
-
- do {
- if(getOwnNodeId() != c_masterNodeId)
- {
- jam();
- ref->errorCode = DropFilegroupRef::NotMaster;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (c_blockState != BS_IDLE)
- {
- jam();
- ref->errorCode = DropFilegroupRef::Busy;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (checkSingleUserMode(senderRef))
- {
- jam();
- ref->errorCode = DropFilegroupRef::SingleUser;
- ref->errorKey = 0;
- ref->errorLine = __LINE__;
- break;
- }
-
- Ptr<Filegroup> filegroup_ptr;
- if (!c_filegroup_hash.find(filegroup_ptr, objId))
- {
- jam();
- ref->errorCode = DropFilegroupRef::NoSuchFilegroup;
- ref->errorLine = __LINE__;
- break;
- }
-
- if (filegroup_ptr.p->m_version != version)
- {
- jam();
- ref->errorCode = DropFilegroupRef::InvalidSchemaObjectVersion;
- ref->errorLine = __LINE__;
- break;
- }
-
- Ptr<SchemaTransaction> trans_ptr;
- if (! c_Trans.seize(trans_ptr))
- {
- jam();
- ref->errorCode = DropFilegroupRef::Busy;
- ref->errorLine = __LINE__;
- break;
- }
- jam();
-
- const Uint32 trans_key = ++c_opRecordSequence;
- trans_ptr.p->key = trans_key;
- trans_ptr.p->m_senderRef = senderRef;
- trans_ptr.p->m_senderData = senderData;
- trans_ptr.p->m_nodes = c_aliveNodes;
- trans_ptr.p->m_errorCode = 0;
- c_Trans.add(trans_ptr);
-
- const Uint32 op_key = ++c_opRecordSequence;
- trans_ptr.p->m_op.m_key = op_key;
- trans_ptr.p->m_op.m_vt_index = 3;
- trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
-
- DropObjReq* drop_obj = (DropObjReq*)signal->getDataPtrSend();
- drop_obj->op_key = op_key;
- drop_obj->objVersion = version;
- drop_obj->objId = objId;
- drop_obj->objType = filegroup_ptr.p->m_type;
- trans_ptr.p->m_op.m_obj_id = objId;
-
- drop_obj->senderRef = reference();
- drop_obj->senderData = trans_key;
- drop_obj->clientRef = senderRef;
- drop_obj->clientData = senderData;
-
- drop_obj->requestInfo = 0;
-
- NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
- SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
- tmp.init<CreateObjRef>(rg, GSN_DROP_OBJ_REF, trans_key);
- sendSignal(rg, GSN_DROP_OBJ_REQ, signal,
- DropObjReq::SignalLength, JBB);
-
- c_blockState = BS_CREATE_TAB;
- return;
- } while(0);
-
- ref->senderData = senderData;
- ref->masterNodeId = c_masterNodeId;
- sendSignal(senderRef, GSN_DROP_FILEGROUP_REF,signal,
- DropFilegroupRef::SignalLength, JBB);
-}
-
-void
-Dbdict::execCREATE_OBJ_REF(Signal* signal)
-{
- CreateObjRef * const ref = (CreateObjRef*)signal->getDataPtr();
- Ptr<SchemaTransaction> trans_ptr;
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
- if(ref->errorCode != CreateObjRef::NF_FakeErrorREF){
- jam();
- trans_ptr.p->setErrorCode(ref->errorCode);
- }
- Uint32 node = refToNode(ref->senderRef);
- schemaOp_reply(signal, trans_ptr.p, node);
-}
-
-void
-Dbdict::execCREATE_OBJ_CONF(Signal* signal)
-{
- Ptr<SchemaTransaction> trans_ptr;
- CreateObjConf * const conf = (CreateObjConf*)signal->getDataPtr();
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
- schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
-}
-
-void
-Dbdict::schemaOp_reply(Signal* signal,
- SchemaTransaction * trans_ptr_p,
- Uint32 nodeId)
-{
- jam();
- {
- SafeCounter tmp(c_counterMgr, trans_ptr_p->m_counter);
- if(!tmp.clearWaitingFor(nodeId)){
- jam();
- return;
- }
- }
-
- switch(trans_ptr_p->m_op.m_state){
- case DictObjOp::Preparing:{
- if(trans_ptr_p->m_errorCode != 0)
- {
- /**
- * Failed to prepare on atleast one node -> abort on all
- */
- trans_ptr_p->m_op.m_state = DictObjOp::Aborting;
- trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
- trans_ptr_p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::trans_abort_start_done);
-
- if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_start)
- {
- jam();
- (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_start)
- (signal, trans_ptr_p);
- }
- else
- {
- jam();
- execute(signal, trans_ptr_p->m_callback, 0);
- }
- return;
- }
-
- trans_ptr_p->m_op.m_state = DictObjOp::Prepared;
- trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
- trans_ptr_p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::trans_commit_start_done);
-
- if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_start)
- {
- jam();
- (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_start)
- (signal, trans_ptr_p);
- }
- else
- {
- jam();
- execute(signal, trans_ptr_p->m_callback, 0);
- }
- return;
- }
- case DictObjOp::Committing: {
- ndbrequire(trans_ptr_p->m_errorCode == 0);
-
- trans_ptr_p->m_op.m_state = DictObjOp::Committed;
- trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
- trans_ptr_p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::trans_commit_complete_done);
-
- if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_complete)
- {
- jam();
- (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_complete)
- (signal, trans_ptr_p);
- }
- else
- {
- jam();
- execute(signal, trans_ptr_p->m_callback, 0);
- }
- return;
- }
- case DictObjOp::Aborting:{
- trans_ptr_p->m_op.m_state = DictObjOp::Committed;
- trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
- trans_ptr_p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::trans_abort_complete_done);
-
- if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_complete)
- {
- jam();
- (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_complete)
- (signal, trans_ptr_p);
- }
- else
- {
- jam();
- execute(signal, trans_ptr_p->m_callback, 0);
- }
- return;
- }
- case DictObjOp::Defined:
- case DictObjOp::Prepared:
- case DictObjOp::Committed:
- case DictObjOp::Aborted:
- jam();
- break;
- }
- ndbrequire(false);
-}
-
-void
-Dbdict::trans_commit_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue)
-{
- Ptr<SchemaTransaction> trans_ptr;
-
- jam();
- ndbrequire(retValue == 0);
- ndbrequire(c_Trans.find(trans_ptr, callbackData));
- NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
- SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
- tmp.init<DictCommitRef>(rg, GSN_DICT_COMMIT_REF, trans_ptr.p->key);
-
- DictCommitReq * const req = (DictCommitReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = trans_ptr.p->key;
- req->op_key = trans_ptr.p->m_op.m_key;
- sendSignal(rg, GSN_DICT_COMMIT_REQ, signal, DictCommitReq::SignalLength,
- JBB);
- trans_ptr.p->m_op.m_state = DictObjOp::Committing;
-}
-
-void
-Dbdict::trans_commit_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue)
-{
- Ptr<SchemaTransaction> trans_ptr;
-
- jam();
- ndbrequire(retValue == 0);
- ndbrequire(c_Trans.find(trans_ptr, callbackData));
-
- switch(f_dict_op[trans_ptr.p->m_op.m_vt_index].m_gsn_user_req){
- case GSN_CREATE_FILEGROUP_REQ:{
- FilegroupPtr fg_ptr;
- jam();
- ndbrequire(c_filegroup_hash.find(fg_ptr, trans_ptr.p->m_op.m_obj_id));
-
- CreateFilegroupConf * conf = (CreateFilegroupConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = trans_ptr.p->m_senderData;
- conf->filegroupId = fg_ptr.p->key;
- conf->filegroupVersion = fg_ptr.p->m_version;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILEGROUP_CONF, signal,
- CreateFilegroupConf::SignalLength, JBB);
- break;
- }
- case GSN_CREATE_FILE_REQ:{
- FilePtr f_ptr;
- jam();
- ndbrequire(c_file_hash.find(f_ptr, trans_ptr.p->m_op.m_obj_id));
- CreateFileConf * conf = (CreateFileConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = trans_ptr.p->m_senderData;
- conf->fileId = f_ptr.p->key;
- conf->fileVersion = f_ptr.p->m_version;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileConf::SignalLength, JBB);
- break;
- }
- case GSN_DROP_FILE_REQ:{
- DropFileConf * conf = (DropFileConf*)signal->getDataPtr();
- jam();
- conf->senderRef = reference();
- conf->senderData = trans_ptr.p->m_senderData;
- conf->fileId = trans_ptr.p->m_op.m_obj_id;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILE_CONF, signal,
- DropFileConf::SignalLength, JBB);
- break;
- }
- case GSN_DROP_FILEGROUP_REQ:{
- DropFilegroupConf * conf = (DropFilegroupConf*)signal->getDataPtr();
- jam();
- conf->senderRef = reference();
- conf->senderData = trans_ptr.p->m_senderData;
- conf->filegroupId = trans_ptr.p->m_op.m_obj_id;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILEGROUP_CONF, signal,
- DropFilegroupConf::SignalLength, JBB);
- break;
- }
- default:
- ndbrequire(false);
- }
-
- c_Trans.release(trans_ptr);
- ndbrequire(c_blockState == BS_CREATE_TAB);
- c_blockState = BS_IDLE;
- return;
-}
-
-void
-Dbdict::trans_abort_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue)
-{
- Ptr<SchemaTransaction> trans_ptr;
-
- jam();
- ndbrequire(retValue == 0);
- ndbrequire(c_Trans.find(trans_ptr, callbackData));
-
- NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
- SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
- ndbrequire(tmp.init<DictAbortRef>(rg, trans_ptr.p->key));
-
- DictAbortReq * const req = (DictAbortReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = trans_ptr.p->key;
- req->op_key = trans_ptr.p->m_op.m_key;
-
- sendSignal(rg, GSN_DICT_ABORT_REQ, signal, DictAbortReq::SignalLength, JBB);
-}
-
-void
-Dbdict::trans_abort_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 retValue)
-{
- Ptr<SchemaTransaction> trans_ptr;
-
- jam();
- ndbrequire(retValue == 0);
- ndbrequire(c_Trans.find(trans_ptr, callbackData));
-
- switch(f_dict_op[trans_ptr.p->m_op.m_vt_index].m_gsn_user_req){
- case GSN_CREATE_FILEGROUP_REQ:
- {
- //
- CreateFilegroupRef * ref = (CreateFilegroupRef*)signal->getDataPtr();
- jam();
- ref->senderRef = reference();
- ref->senderData = trans_ptr.p->m_senderData;
- ref->masterNodeId = c_masterNodeId;
- ref->errorCode = trans_ptr.p->m_errorCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
- ref->status = 0;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILEGROUP_REF, signal,
- CreateFilegroupRef::SignalLength, JBB);
- break;
- }
- case GSN_CREATE_FILE_REQ:
- {
- CreateFileRef * ref = (CreateFileRef*)signal->getDataPtr();
- jam();
- ref->senderRef = reference();
- ref->senderData = trans_ptr.p->m_senderData;
- ref->masterNodeId = c_masterNodeId;
- ref->errorCode = trans_ptr.p->m_errorCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
- ref->status = 0;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILE_REF, signal,
- CreateFileRef::SignalLength, JBB);
- break;
- }
- case GSN_DROP_FILE_REQ:
- {
- DropFileRef * ref = (DropFileRef*)signal->getDataPtr();
- jam();
- ref->senderRef = reference();
- ref->senderData = trans_ptr.p->m_senderData;
- ref->masterNodeId = c_masterNodeId;
- ref->errorCode = trans_ptr.p->m_errorCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILE_REF, signal,
- DropFileRef::SignalLength, JBB);
- break;
- }
- case GSN_DROP_FILEGROUP_REQ:
- {
- //
- DropFilegroupRef * ref = (DropFilegroupRef*)signal->getDataPtr();
- jam();
- ref->senderRef = reference();
- ref->senderData = trans_ptr.p->m_senderData;
- ref->masterNodeId = c_masterNodeId;
- ref->errorCode = trans_ptr.p->m_errorCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
-
- //@todo check api failed
- sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILEGROUP_REF, signal,
- DropFilegroupRef::SignalLength, JBB);
- break;
- }
- default:
- ndbrequire(false);
- }
-
- c_Trans.release(trans_ptr);
- ndbrequire(c_blockState == BS_CREATE_TAB);
- c_blockState = BS_IDLE;
- return;
-}
-
-void
-Dbdict::execCREATE_OBJ_REQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- CreateObjReq * const req = (CreateObjReq*)signal->getDataPtr();
- const Uint32 gci = req->gci;
- const Uint32 objId = req->objId;
- const Uint32 objVersion = req->objVersion;
- const Uint32 objType = req->objType;
- const Uint32 requestInfo = req->requestInfo;
-
- SegmentedSectionPtr objInfoPtr;
- signal->getSection(objInfoPtr, CreateObjReq::DICT_OBJ_INFO);
-
- CreateObjRecordPtr createObjPtr;
- ndbrequire(c_opCreateObj.seize(createObjPtr));
-
- const Uint32 key = req->op_key;
- createObjPtr.p->key = key;
- c_opCreateObj.add(createObjPtr);
- createObjPtr.p->m_errorCode = 0;
- createObjPtr.p->m_senderRef = req->senderRef;
- createObjPtr.p->m_senderData = req->senderData;
- createObjPtr.p->m_clientRef = req->clientRef;
- createObjPtr.p->m_clientData = req->clientData;
-
- createObjPtr.p->m_gci = gci;
- createObjPtr.p->m_obj_id = objId;
- createObjPtr.p->m_obj_type = objType;
- createObjPtr.p->m_obj_version = objVersion;
- createObjPtr.p->m_obj_info_ptr_i = objInfoPtr.i;
- createObjPtr.p->m_obj_ptr_i = RNIL;
-
- createObjPtr.p->m_callback.m_callbackData = key;
- createObjPtr.p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::createObj_prepare_start_done);
-
- createObjPtr.p->m_restart= 0;
- switch(objType){
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:
- jam();
- createObjPtr.p->m_vt_index = 0;
- break;
- case DictTabInfo::Datafile:
- case DictTabInfo::Undofile:
- /**
- * Use restart code to impl. ForceCreateFile
- */
- if (requestInfo & CreateFileReq::ForceCreateFile)
- {
- jam();
- createObjPtr.p->m_restart= 2;
- }
- jam();
- createObjPtr.p->m_vt_index = 1;
- break;
- default:
- ndbrequire(false);
- }
-
- signal->header.m_noOfSections = 0;
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
- (signal, createObjPtr.p);
-}
-
-void
-Dbdict::execDICT_COMMIT_REQ(Signal* signal)
-{
- DictCommitReq* req = (DictCommitReq*)signal->getDataPtr();
- Ptr<SchemaOp> op;
-
- jamEntry();
- ndbrequire(c_schemaOp.find(op, req->op_key));
- (this->*f_dict_op[op.p->m_vt_index].m_commit)(signal, op.p);
-}
-
-void
-Dbdict::execDICT_ABORT_REQ(Signal* signal)
-{
- DictAbortReq* req = (DictAbortReq*)signal->getDataPtr();
- Ptr<SchemaOp> op;
-
- jamEntry();
- ndbrequire(c_schemaOp.find(op, req->op_key));
- (this->*f_dict_op[op.p->m_vt_index].m_abort)(signal, op.p);
-}
-
-void
-Dbdict::execDICT_COMMIT_REF(Signal* signal)
-{
- DictCommitRef * const ref = (DictCommitRef*)signal->getDataPtr();
- Ptr<SchemaTransaction> trans_ptr;
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
- if(ref->errorCode != DictCommitRef::NF_FakeErrorREF){
- jam();
- trans_ptr.p->setErrorCode(ref->errorCode);
- }
- Uint32 node = refToNode(ref->senderRef);
- schemaOp_reply(signal, trans_ptr.p, node);
-}
-
-void
-Dbdict::execDICT_COMMIT_CONF(Signal* signal)
-{
- Ptr<SchemaTransaction> trans_ptr;
- DictCommitConf * const conf = (DictCommitConf*)signal->getDataPtr();
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
- schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
-}
-
-void
-Dbdict::execDICT_ABORT_REF(Signal* signal)
-{
- DictAbortRef * const ref = (DictAbortRef*)signal->getDataPtr();
- Ptr<SchemaTransaction> trans_ptr;
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
- if(ref->errorCode != DictAbortRef::NF_FakeErrorREF){
- jam();
- trans_ptr.p->setErrorCode(ref->errorCode);
- }
- Uint32 node = refToNode(ref->senderRef);
- schemaOp_reply(signal, trans_ptr.p, node);
-}
-
-void
-Dbdict::execDICT_ABORT_CONF(Signal* signal)
-{
- DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
- Ptr<SchemaTransaction> trans_ptr;
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
- schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
-}
-
-void
-Dbdict::createObj_prepare_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
- SegmentedSectionPtr objInfoPtr;
-
- ndbrequire(returnCode == 0);
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- jam();
- getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
- if(createObjPtr.p->m_errorCode != 0){
- jam();
- createObjPtr.p->m_obj_info_ptr_i= RNIL;
- signal->setSection(objInfoPtr, 0);
- releaseSections(signal);
- createObj_prepare_complete_done(signal, callbackData, 0);
- return;
- }
-
- SchemaFile::TableEntry tabEntry;
- bzero(&tabEntry, sizeof(tabEntry));
- tabEntry.m_tableVersion = createObjPtr.p->m_obj_version;
- tabEntry.m_tableType = createObjPtr.p->m_obj_type;
- tabEntry.m_tableState = SchemaFile::ADD_STARTED;
- tabEntry.m_gcp = createObjPtr.p->m_gci;
- tabEntry.m_info_words = objInfoPtr.sz;
-
- Callback cb;
- cb.m_callbackData = createObjPtr.p->key;
- cb.m_callbackFunction = safe_cast(&Dbdict::createObj_writeSchemaConf1);
-
- updateSchemaState(signal, createObjPtr.p->m_obj_id, &tabEntry, &cb);
-}
-
-void
-Dbdict::createObj_writeSchemaConf1(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
- Callback callback;
- SegmentedSectionPtr objInfoPtr;
-
- jam();
- ndbrequire(returnCode == 0);
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
-
- callback.m_callbackData = createObjPtr.p->key;
- callback.m_callbackFunction = safe_cast(&Dbdict::createObj_writeObjConf);
-
- getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
- writeTableFile(signal, createObjPtr.p->m_obj_id, objInfoPtr, &callback);
-
- signal->setSection(objInfoPtr, 0);
- releaseSections(signal);
- createObjPtr.p->m_obj_info_ptr_i = RNIL;
-}
-
-void
-Dbdict::createObj_writeObjConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- jam();
- ndbrequire(returnCode == 0);
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- createObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::createObj_prepare_complete_done);
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_complete)
- (signal, createObjPtr.p);
-}
-
-void
-Dbdict::createObj_prepare_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- jam();
- ndbrequire(returnCode == 0);
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
-
- //@todo check for master failed
-
- if(createObjPtr.p->m_errorCode == 0){
- jam();
-
- CreateObjConf * const conf = (CreateObjConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = createObjPtr.p->m_senderData;
- sendSignal(createObjPtr.p->m_senderRef, GSN_CREATE_OBJ_CONF,
- signal, CreateObjConf::SignalLength, JBB);
- return;
- }
-
- CreateObjRef * const ref = (CreateObjRef*)signal->getDataPtr();
- ref->senderRef = reference();
- ref->senderData = createObjPtr.p->m_senderData;
- ref->errorCode = createObjPtr.p->m_errorCode;
- ref->errorLine = 0;
- ref->errorKey = 0;
- ref->errorStatus = 0;
-
- sendSignal(createObjPtr.p->m_senderRef, GSN_CREATE_OBJ_REF,
- signal, CreateObjRef::SignalLength, JBB);
-}
-
-void
-Dbdict::createObj_commit(Signal * signal, SchemaOp * op)
-{
- OpCreateObj * createObj = (OpCreateObj*)op;
-
- createObj->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::createObj_commit_start_done);
- if (f_dict_op[createObj->m_vt_index].m_commit_start)
- {
- jam();
- (this->*f_dict_op[createObj->m_vt_index].m_commit_start)(signal, createObj);
- }
- else
- {
- jam();
- execute(signal, createObj->m_callback, 0);
- }
-}
-
-void
-Dbdict::createObj_commit_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- jam();
- ndbrequire(returnCode == 0);
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
-
- Uint32 objId = createObjPtr.p->m_obj_id;
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry objEntry = * getTableEntry(xsf, objId);
- objEntry.m_tableState = SchemaFile::TABLE_ADD_COMMITTED;
-
- Callback callback;
- callback.m_callbackData = createObjPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::createObj_writeSchemaConf2);
-
- updateSchemaState(signal, createObjPtr.p->m_obj_id, &objEntry, &callback);
-
-}
-
-void
-Dbdict::createObj_writeSchemaConf2(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- createObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::createObj_commit_complete_done);
- if (f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
- {
- jam();
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
- (signal, createObjPtr.p);
- }
- else
- {
- jam();
- execute(signal, createObjPtr.p->m_callback, 0);
- }
-
-}
-
-void
-Dbdict::createObj_commit_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- jam();
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
-
- //@todo check error
- //@todo check master failed
-
- DictCommitConf * const conf = (DictCommitConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = createObjPtr.p->m_senderData;
- sendSignal(createObjPtr.p->m_senderRef, GSN_DICT_COMMIT_CONF,
- signal, DictCommitConf::SignalLength, JBB);
-
- c_opCreateObj.release(createObjPtr);
-}
-
-void
-Dbdict::createObj_abort(Signal* signal, SchemaOp* op)
-{
- OpCreateObj * createObj = (OpCreateObj*)op;
-
- createObj->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::createObj_abort_start_done);
- if (f_dict_op[createObj->m_vt_index].m_abort_start)
- {
- jam();
- (this->*f_dict_op[createObj->m_vt_index].m_abort_start)(signal, createObj);
- }
- else
- {
- jam();
- execute(signal, createObj->m_callback, 0);
- }
-}
-
-void
-Dbdict::createObj_abort_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- jam();
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry objEntry = * getTableEntry(xsf,
- createObjPtr.p->m_obj_id);
- objEntry.m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
-
- Callback callback;
- callback.m_callbackData = createObjPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::createObj_abort_writeSchemaConf);
-
- updateSchemaState(signal, createObjPtr.p->m_obj_id, &objEntry, &callback);
-}
-
-void
-Dbdict::createObj_abort_writeSchemaConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
- createObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::createObj_abort_complete_done);
-
- if (f_dict_op[createObjPtr.p->m_vt_index].m_abort_complete)
- {
- jam();
- (this->*f_dict_op[createObjPtr.p->m_vt_index].m_abort_complete)
- (signal, createObjPtr.p);
- }
- else
- {
- jam();
- execute(signal, createObjPtr.p->m_callback, 0);
- }
-}
-
-void
-Dbdict::createObj_abort_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- CreateObjRecordPtr createObjPtr;
-
- jam();
- ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
-
- DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = createObjPtr.p->m_senderData;
- sendSignal(createObjPtr.p->m_senderRef, GSN_DICT_ABORT_CONF,
- signal, DictAbortConf::SignalLength, JBB);
-
- c_opCreateObj.release(createObjPtr);
-}
-
-void
-Dbdict::execDROP_OBJ_REQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- DropObjReq * const req = (DropObjReq*)signal->getDataPtr();
-
- const Uint32 objId = req->objId;
- const Uint32 objVersion = req->objVersion;
- const Uint32 objType = req->objType;
-
- DropObjRecordPtr dropObjPtr;
- ndbrequire(c_opDropObj.seize(dropObjPtr));
-
- const Uint32 key = req->op_key;
- dropObjPtr.p->key = key;
- c_opDropObj.add(dropObjPtr);
- dropObjPtr.p->m_errorCode = 0;
- dropObjPtr.p->m_senderRef = req->senderRef;
- dropObjPtr.p->m_senderData = req->senderData;
- dropObjPtr.p->m_clientRef = req->clientRef;
- dropObjPtr.p->m_clientData = req->clientData;
-
- dropObjPtr.p->m_obj_id = objId;
- dropObjPtr.p->m_obj_type = objType;
- dropObjPtr.p->m_obj_version = objVersion;
-
- dropObjPtr.p->m_callback.m_callbackData = key;
- dropObjPtr.p->m_callback.m_callbackFunction=
- safe_cast(&Dbdict::dropObj_prepare_start_done);
-
- switch(objType){
- case DictTabInfo::Tablespace:
- case DictTabInfo::LogfileGroup:
- {
- Ptr<Filegroup> fg_ptr;
- jam();
- dropObjPtr.p->m_vt_index = 3;
- ndbrequire(c_filegroup_hash.find(fg_ptr, objId));
- dropObjPtr.p->m_obj_ptr_i = fg_ptr.i;
- break;
-
- }
- case DictTabInfo::Datafile:
- {
- Ptr<File> file_ptr;
- jam();
- dropObjPtr.p->m_vt_index = 2;
- ndbrequire(c_file_hash.find(file_ptr, objId));
- dropObjPtr.p->m_obj_ptr_i = file_ptr.i;
- break;
- }
- case DictTabInfo::Undofile:
- {
- jam();
- dropObjPtr.p->m_vt_index = 4;
- return;
- }
- default:
- ndbrequire(false);
- }
-
- signal->header.m_noOfSections = 0;
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_start)
- (signal, dropObjPtr.p);
-}
-
-void
-Dbdict::dropObj_prepare_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
- Callback cb;
-
- ndbrequire(returnCode == 0);
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
-
- cb.m_callbackData = callbackData;
- cb.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_prepare_writeSchemaConf);
-
- if(dropObjPtr.p->m_errorCode != 0)
- {
- jam();
- dropObj_prepare_complete_done(signal, callbackData, 0);
- return;
- }
- jam();
- Uint32 objId = dropObjPtr.p->m_obj_id;
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry objEntry = *getTableEntry(xsf, objId);
- objEntry.m_tableState = SchemaFile::DROP_TABLE_STARTED;
- updateSchemaState(signal, objId, &objEntry, &cb);
-}
-
-void
-Dbdict::dropObj_prepare_writeSchemaConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
-
- ndbrequire(returnCode == 0);
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- dropObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_prepare_complete_done);
- if(f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
- {
- jam();
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
- (signal, dropObjPtr.p);
- }
- else
- {
- jam();
- execute(signal, dropObjPtr.p->m_callback, 0);
- }
-}
-
-void
-Dbdict::dropObj_prepare_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
-
- ndbrequire(returnCode == 0);
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- jam();
-
- //@todo check for master failed
-
- if(dropObjPtr.p->m_errorCode == 0){
- jam();
-
- DropObjConf * const conf = (DropObjConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = dropObjPtr.p->m_senderData;
- sendSignal(dropObjPtr.p->m_senderRef, GSN_DROP_OBJ_CONF,
- signal, DropObjConf::SignalLength, JBB);
- return;
- }
-
- DropObjRef * const ref = (DropObjRef*)signal->getDataPtr();
- ref->senderRef = reference();
- ref->senderData = dropObjPtr.p->m_senderData;
- ref->errorCode = dropObjPtr.p->m_errorCode;
-
- sendSignal(dropObjPtr.p->m_senderRef, GSN_DROP_OBJ_REF,
- signal, DropObjRef::SignalLength, JBB);
-
-}
-
-void
-Dbdict::dropObj_commit(Signal * signal, SchemaOp * op)
-{
- OpDropObj * dropObj = (OpDropObj*)op;
-
- dropObj->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_commit_start_done);
- if (f_dict_op[dropObj->m_vt_index].m_commit_start)
- {
- jam();
- (this->*f_dict_op[dropObj->m_vt_index].m_commit_start)(signal, dropObj);
- }
- else
- {
- jam();
- execute(signal, dropObj->m_callback, 0);
- }
-}
-
-void
-Dbdict::dropObj_commit_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
-
- jam();
- ndbrequire(returnCode == 0);
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
-
- Uint32 objId = dropObjPtr.p->m_obj_id;
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry objEntry = * getTableEntry(xsf, objId);
- objEntry.m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
-
- Callback callback;
- callback.m_callbackData = dropObjPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_commit_writeSchemaConf);
-
- updateSchemaState(signal, objId, &objEntry, &callback);
-}
-
-void
-Dbdict::dropObj_commit_writeSchemaConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
-
- jam();
- ndbrequire(returnCode == 0);
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- dropObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_commit_complete_done);
-
- if(f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
- {
- jam();
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
- (signal, dropObjPtr.p);
- }
- else
- {
- jam();
- execute(signal, dropObjPtr.p->m_callback, 0);
- }
-}
-
-void
-Dbdict::dropObj_commit_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
-
- jam();
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
-
- //@todo check error
- //@todo check master failed
-
- DictCommitConf * const conf = (DictCommitConf*)signal->getDataPtr();
- conf->senderRef = reference();
- conf->senderData = dropObjPtr.p->m_senderData;
- sendSignal(dropObjPtr.p->m_senderRef, GSN_DICT_COMMIT_CONF,
- signal, DictCommitConf::SignalLength, JBB);
- c_opDropObj.release(dropObjPtr);
-}
-
-void
-Dbdict::dropObj_abort(Signal * signal, SchemaOp * op)
-{
- OpDropObj * dropObj = (OpDropObj*)op;
-
- dropObj->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_abort_start_done);
- if (f_dict_op[dropObj->m_vt_index].m_abort_start)
- {
- jam();
- (this->*f_dict_op[dropObj->m_vt_index].m_abort_start)(signal, dropObj);
- }
- else
- {
- jam();
- execute(signal, dropObj->m_callback, 0);
- }
-}
-
-void
-Dbdict::dropObj_abort_start_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
-
- jam();
- ndbrequire(returnCode == 0);
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
-
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- SchemaFile::TableEntry objEntry = * getTableEntry(xsf,
- dropObjPtr.p->m_obj_id);
-
- Callback callback;
- callback.m_callbackData = dropObjPtr.p->key;
- callback.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_abort_writeSchemaConf);
-
- if (objEntry.m_tableState == SchemaFile::DROP_TABLE_STARTED)
- {
- jam();
- objEntry.m_tableState = SchemaFile::TABLE_ADD_COMMITTED;
-
- updateSchemaState(signal, dropObjPtr.p->m_obj_id, &objEntry, &callback);
- }
- else
- {
- jam();
- execute(signal, callback, 0);
- }
-}
-
-void
-Dbdict::dropObj_abort_writeSchemaConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
-
- ndbrequire(returnCode == 0);
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- dropObjPtr.p->m_callback.m_callbackFunction =
- safe_cast(&Dbdict::dropObj_abort_complete_done);
-
- if(f_dict_op[dropObjPtr.p->m_vt_index].m_abort_complete)
- {
- jam();
- (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_abort_complete)
- (signal, dropObjPtr.p);
- }
- else
- {
- jam();
- execute(signal, dropObjPtr.p->m_callback, 0);
- }
-}
-
-void
-Dbdict::dropObj_abort_complete_done(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- DropObjRecordPtr dropObjPtr;
- DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
-
- ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
- jam();
- conf->senderRef = reference();
- conf->senderData = dropObjPtr.p->m_senderData;
- sendSignal(dropObjPtr.p->m_senderRef, GSN_DICT_ABORT_CONF,
- signal, DictAbortConf::SignalLength, JBB);
- c_opDropObj.release(dropObjPtr);
-}
-
-void
-Dbdict::create_fg_prepare_start(Signal* signal, SchemaOp* op)
-{
- /**
- * Put data into table record
- */
- SegmentedSectionPtr objInfoPtr;
- jam();
- getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
- SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
-
- Ptr<DictObject> obj_ptr; obj_ptr.setNull();
- FilegroupPtr fg_ptr; fg_ptr.setNull();
-
- SimpleProperties::UnpackStatus status;
- DictFilegroupInfo::Filegroup fg; fg.init();
- do {
- status = SimpleProperties::unpack(it, &fg,
- DictFilegroupInfo::Mapping,
- DictFilegroupInfo::MappingSize,
- true, true);
-
- if(status != SimpleProperties::Eof)
- {
- jam();
- op->m_errorCode = CreateTableRef::InvalidFormat;
- break;
- }
-
- if(fg.FilegroupType == DictTabInfo::Tablespace)
- {
- if(!fg.TS_ExtentSize)
- {
- jam();
- op->m_errorCode = CreateFilegroupRef::InvalidExtentSize;
- break;
- }
- }
- else if(fg.FilegroupType == DictTabInfo::LogfileGroup)
- {
- /**
- * undo_buffer_size can't be less than 96KB in LGMAN block
- */
- if(fg.LF_UndoBufferSize < 3 * File_formats::NDB_PAGE_SIZE)
- {
- jam();
- op->m_errorCode = CreateFilegroupRef::InvalidUndoBufferSize;
- break;
- }
- }
-
- Uint32 len = strlen(fg.FilegroupName) + 1;
- Uint32 hash = Rope::hash(fg.FilegroupName, len);
- if(get_object(fg.FilegroupName, len, hash) != 0){
- jam();
- op->m_errorCode = CreateTableRef::TableAlreadyExist;
- break;
- }
-
- if(!c_obj_pool.seize(obj_ptr)){
- jam();
- op->m_errorCode = CreateTableRef::NoMoreTableRecords;
- break;
- }
-
- if(!c_filegroup_pool.seize(fg_ptr)){
- jam();
- op->m_errorCode = CreateTableRef::NoMoreTableRecords;
- break;
- }
-
- new (fg_ptr.p) Filegroup();
-
- {
- Rope name(c_rope_pool, obj_ptr.p->m_name);
- if(!name.assign(fg.FilegroupName, len, hash)){
- jam();
- op->m_errorCode = CreateTableRef::OutOfStringBuffer;
- break;
- }
- }
-
- fg_ptr.p->key = op->m_obj_id;
- fg_ptr.p->m_obj_ptr_i = obj_ptr.i;
- fg_ptr.p->m_type = fg.FilegroupType;
- fg_ptr.p->m_version = op->m_obj_version;
- fg_ptr.p->m_name = obj_ptr.p->m_name;
-
- switch(fg.FilegroupType){
- case DictTabInfo::Tablespace:
- {
- //fg.TS_DataGrow = group.m_grow_spec;
- fg_ptr.p->m_tablespace.m_extent_size = fg.TS_ExtentSize;
- fg_ptr.p->m_tablespace.m_default_logfile_group_id = fg.TS_LogfileGroupId;
-
- Ptr<Filegroup> lg_ptr;
- if (!c_filegroup_hash.find(lg_ptr, fg.TS_LogfileGroupId))
- {
- jam();
- op->m_errorCode = CreateFilegroupRef::NoSuchLogfileGroup;
- goto error;
- }
-
- if (lg_ptr.p->m_version != fg.TS_LogfileGroupVersion)
- {
- jam();
- op->m_errorCode = CreateFilegroupRef::InvalidFilegroupVersion;
- goto error;
- }
- increase_ref_count(lg_ptr.p->m_obj_ptr_i);
- break;
- }
- case DictTabInfo::LogfileGroup:
- {
- jam();
- fg_ptr.p->m_logfilegroup.m_undo_buffer_size = fg.LF_UndoBufferSize;
- fg_ptr.p->m_logfilegroup.m_files.init();
- //fg.LF_UndoGrow = ;
- break;
- }
- default:
- ndbrequire(false);
- }
-
- obj_ptr.p->m_id = op->m_obj_id;
- obj_ptr.p->m_type = fg.FilegroupType;
- obj_ptr.p->m_ref_count = 0;
- c_obj_hash.add(obj_ptr);
- c_filegroup_hash.add(fg_ptr);
-
- op->m_obj_ptr_i = fg_ptr.i;
- } while(0);
-
-error:
- if (op->m_errorCode)
- {
- jam();
- if (!fg_ptr.isNull())
- {
- jam();
- c_filegroup_pool.release(fg_ptr);
- }
-
- if (!obj_ptr.isNull())
- {
- jam();
- c_obj_pool.release(obj_ptr);
- }
- }
-
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::create_fg_prepare_complete(Signal* signal, SchemaOp* op)
-{
- /**
- * CONTACT TSMAN LGMAN PGMAN
- */
- CreateFilegroupImplReq* req =
- (CreateFilegroupImplReq*)signal->getDataPtrSend();
- jam();
- req->senderData = op->key;
- req->senderRef = reference();
- req->filegroup_id = op->m_obj_id;
- req->filegroup_version = op->m_obj_version;
-
- FilegroupPtr fg_ptr;
- c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
-
- Uint32 ref= 0;
- Uint32 len= 0;
- switch(op->m_obj_type){
- case DictTabInfo::Tablespace:
- {
- jam();
- ref = TSMAN_REF;
- len = CreateFilegroupImplReq::TablespaceLength;
- req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
- req->tablespace.logfile_group_id =
- fg_ptr.p->m_tablespace.m_default_logfile_group_id;
- break;
- }
- case DictTabInfo::LogfileGroup:
- {
- jam();
- ref = LGMAN_REF;
- len = CreateFilegroupImplReq::LogfileGroupLength;
- req->logfile_group.buffer_size =
- fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
- break;
- }
- default:
- ndbrequire(false);
- }
-
- sendSignal(ref, GSN_CREATE_FILEGROUP_REQ, signal, len, JBB);
-}
-
-void
-Dbdict::execCREATE_FILEGROUP_REF(Signal* signal)
-{
- CreateFilegroupImplRef * ref = (CreateFilegroupImplRef*)signal->getDataPtr();
- CreateObjRecordPtr op_ptr;
- jamEntry();
- ndbrequire(c_opCreateObj.find(op_ptr, ref->senderData));
- op_ptr.p->m_errorCode = ref->errorCode;
-
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::execCREATE_FILEGROUP_CONF(Signal* signal)
-{
- CreateFilegroupImplConf * rep =
- (CreateFilegroupImplConf*)signal->getDataPtr();
- CreateObjRecordPtr op_ptr;
- jamEntry();
- ndbrequire(c_opCreateObj.find(op_ptr, rep->senderData));
-
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::create_fg_abort_start(Signal* signal, SchemaOp* op){
- (void) signal->getDataPtrSend();
-
- if (op->m_obj_ptr_i != RNIL)
- {
- jam();
- send_drop_fg(signal, op, DropFilegroupImplReq::Commit);
- return;
- }
- jam();
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::create_fg_abort_complete(Signal* signal, SchemaOp* op)
-{
- if (op->m_obj_ptr_i != RNIL)
- {
- jam();
- FilegroupPtr fg_ptr;
- c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
-
- release_object(fg_ptr.p->m_obj_ptr_i);
- c_filegroup_hash.release(fg_ptr);
- }
- jam();
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::create_file_prepare_start(Signal* signal, SchemaOp* op)
-{
- /**
- * Put data into table record
- */
- SegmentedSectionPtr objInfoPtr;
- getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
- SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
-
- Ptr<DictObject> obj_ptr; obj_ptr.setNull();
- FilePtr filePtr; filePtr.setNull();
-
- DictFilegroupInfo::File f; f.init();
- SimpleProperties::UnpackStatus status;
- status = SimpleProperties::unpack(it, &f,
- DictFilegroupInfo::FileMapping,
- DictFilegroupInfo::FileMappingSize,
- true, true);
-
- do {
- if(status != SimpleProperties::Eof){
- jam();
- op->m_errorCode = CreateFileRef::InvalidFormat;
- break;
- }
-
- // Get Filegroup
- FilegroupPtr fg_ptr;
- if(!c_filegroup_hash.find(fg_ptr, f.FilegroupId)){
- jam();
- op->m_errorCode = CreateFileRef::NoSuchFilegroup;
- break;
- }
-
- if(fg_ptr.p->m_version != f.FilegroupVersion){
- jam();
- op->m_errorCode = CreateFileRef::InvalidFilegroupVersion;
- break;
- }
-
- switch(f.FileType){
- case DictTabInfo::Datafile:
- {
- if(fg_ptr.p->m_type != DictTabInfo::Tablespace)
- {
- jam();
- op->m_errorCode = CreateFileRef::InvalidFileType;
- }
- jam();
- break;
- }
- case DictTabInfo::Undofile:
- {
- if(fg_ptr.p->m_type != DictTabInfo::LogfileGroup)
- {
- jam();
- op->m_errorCode = CreateFileRef::InvalidFileType;
- }
- jam();
- break;
- }
- default:
- jam();
- op->m_errorCode = CreateFileRef::InvalidFileType;
- }
-
- if(op->m_errorCode)
- {
- jam();
- break;
- }
-
- Uint32 len = strlen(f.FileName) + 1;
- Uint32 hash = Rope::hash(f.FileName, len);
- if(get_object(f.FileName, len, hash) != 0){
- jam();
- op->m_errorCode = CreateFileRef::FilenameAlreadyExists;
- break;
- }
-
- {
- Uint32 dl;
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- if(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl)
- {
- jam();
- op->m_errorCode = CreateFileRef::NotSupportedWhenDiskless;
- break;
- }
- }
-
- // Loop through all filenames...
- if(!c_obj_pool.seize(obj_ptr)){
- jam();
- op->m_errorCode = CreateTableRef::NoMoreTableRecords;
- break;
- }
-
- if (! c_file_pool.seize(filePtr)){
- jam();
- op->m_errorCode = CreateFileRef::OutOfFileRecords;
- break;
- }
-
- new (filePtr.p) File();
-
- {
- Rope name(c_rope_pool, obj_ptr.p->m_name);
- if(!name.assign(f.FileName, len, hash)){
- jam();
- op->m_errorCode = CreateTableRef::OutOfStringBuffer;
- break;
- }
- }
-
- switch(fg_ptr.p->m_type){
- case DictTabInfo::Tablespace:
- {
- jam();
- increase_ref_count(fg_ptr.p->m_obj_ptr_i);
- break;
- }
- case DictTabInfo::LogfileGroup:
- {
- jam();
- Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
- list.add(filePtr);
- break;
- }
- default:
- ndbrequire(false);
- }
-
- /**
- * Init file
- */
- filePtr.p->key = op->m_obj_id;
- filePtr.p->m_file_size = ((Uint64)f.FileSizeHi) << 32 | f.FileSizeLo;
- filePtr.p->m_path = obj_ptr.p->m_name;
- filePtr.p->m_obj_ptr_i = obj_ptr.i;
- filePtr.p->m_filegroup_id = f.FilegroupId;
- filePtr.p->m_type = f.FileType;
- filePtr.p->m_version = op->m_obj_version;
-
- obj_ptr.p->m_id = op->m_obj_id;
- obj_ptr.p->m_type = f.FileType;
- obj_ptr.p->m_ref_count = 0;
- c_obj_hash.add(obj_ptr);
- c_file_hash.add(filePtr);
-
- op->m_obj_ptr_i = filePtr.i;
- } while(0);
-
- if (op->m_errorCode)
- {
- jam();
- if (!filePtr.isNull())
- {
- jam();
- c_file_pool.release(filePtr);
- }
-
- if (!obj_ptr.isNull())
- {
- jam();
- c_obj_pool.release(obj_ptr);
- }
- }
- execute(signal, op->m_callback, 0);
-}
-
-
-void
-Dbdict::create_file_prepare_complete(Signal* signal, SchemaOp* op)
-{
- /**
- * CONTACT TSMAN LGMAN PGMAN
- */
- CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
- FilePtr f_ptr;
- FilegroupPtr fg_ptr;
-
- jam();
- c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
- ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
-
- req->senderData = op->key;
- req->senderRef = reference();
- switch(((OpCreateObj*)op)->m_restart){
- case 0:
- {
- jam();
- req->requestInfo = CreateFileImplReq::Create;
- break;
- }
- case 1:
- {
- jam();
- req->requestInfo = CreateFileImplReq::Open;
- break;
- }
- case 2:
- {
- jam();
- req->requestInfo = CreateFileImplReq::CreateForce;
- break;
- }
- }
-
- req->file_id = f_ptr.p->key;
- req->filegroup_id = f_ptr.p->m_filegroup_id;
- req->filegroup_version = fg_ptr.p->m_version;
- req->file_size_hi = f_ptr.p->m_file_size >> 32;
- req->file_size_lo = f_ptr.p->m_file_size & 0xFFFFFFFF;
-
- Uint32 ref= 0;
- Uint32 len= 0;
- switch(op->m_obj_type){
- case DictTabInfo::Datafile:
- {
- jam();
- ref = TSMAN_REF;
- len = CreateFileImplReq::DatafileLength;
- req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
- break;
- }
- case DictTabInfo::Undofile:
- {
- jam();
- ref = LGMAN_REF;
- len = CreateFileImplReq::UndofileLength;
- break;
- }
- default:
- ndbrequire(false);
- }
-
- char name[MAX_TAB_NAME_SIZE];
- ConstRope tmp(c_rope_pool, f_ptr.p->m_path);
- tmp.copy(name);
- LinearSectionPtr ptr[3];
- ptr[0].p = (Uint32*)&name[0];
- ptr[0].sz = (strlen(name)+1+3)/4;
- sendSignal(ref, GSN_CREATE_FILE_REQ, signal, len, JBB, ptr, 1);
-}
-
-void
-Dbdict::execCREATE_FILE_REF(Signal* signal)
-{
- CreateFileImplRef * ref = (CreateFileImplRef*)signal->getDataPtr();
- CreateObjRecordPtr op_ptr;
-
- jamEntry();
- ndbrequire(c_opCreateObj.find(op_ptr, ref->senderData));
- op_ptr.p->m_errorCode = ref->errorCode;
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::execCREATE_FILE_CONF(Signal* signal)
-{
- CreateFileImplConf * rep =
- (CreateFileImplConf*)signal->getDataPtr();
- CreateObjRecordPtr op_ptr;
-
- jamEntry();
- ndbrequire(c_opCreateObj.find(op_ptr, rep->senderData));
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::create_file_commit_start(Signal* signal, SchemaOp* op)
-{
- /**
- * CONTACT TSMAN LGMAN PGMAN
- */
- CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
- FilePtr f_ptr;
- FilegroupPtr fg_ptr;
-
- jam();
- c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
- ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
-
- req->senderData = op->key;
- req->senderRef = reference();
- req->requestInfo = CreateFileImplReq::Commit;
-
- req->file_id = f_ptr.p->key;
- req->filegroup_id = f_ptr.p->m_filegroup_id;
- req->filegroup_version = fg_ptr.p->m_version;
-
- Uint32 ref= 0;
- switch(op->m_obj_type){
- case DictTabInfo::Datafile:
- {
- jam();
- ref = TSMAN_REF;
- break;
- }
- case DictTabInfo::Undofile:
- {
- jam();
- ref = LGMAN_REF;
- break;
- }
- default:
- ndbrequire(false);
- }
- sendSignal(ref, GSN_CREATE_FILE_REQ, signal,
- CreateFileImplReq::CommitLength, JBB);
-}
-
-void
-Dbdict::create_file_abort_start(Signal* signal, SchemaOp* op)
-{
- CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
-
- if (op->m_obj_ptr_i != RNIL)
- {
- FilePtr f_ptr;
- FilegroupPtr fg_ptr;
-
- jam();
- c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
-
- ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
-
- req->senderData = op->key;
- req->senderRef = reference();
- req->requestInfo = CreateFileImplReq::Abort;
-
- req->file_id = f_ptr.p->key;
- req->filegroup_id = f_ptr.p->m_filegroup_id;
- req->filegroup_version = fg_ptr.p->m_version;
-
- Uint32 ref= 0;
- switch(op->m_obj_type){
- case DictTabInfo::Datafile:
- {
- jam();
- ref = TSMAN_REF;
- break;
- }
- case DictTabInfo::Undofile:
- {
- jam();
- ref = LGMAN_REF;
- break;
- }
- default:
- ndbrequire(false);
- }
- sendSignal(ref, GSN_CREATE_FILE_REQ, signal,
- CreateFileImplReq::AbortLength, JBB);
- return;
- }
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::create_file_abort_complete(Signal* signal, SchemaOp* op)
-{
- if (op->m_obj_ptr_i != RNIL)
- {
- FilePtr f_ptr;
- FilegroupPtr fg_ptr;
-
- jam();
- c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
- ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
- switch(fg_ptr.p->m_type){
- case DictTabInfo::Tablespace:
- {
- jam();
- decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
- break;
- }
- case DictTabInfo::LogfileGroup:
- {
- jam();
- Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
- list.remove(f_ptr);
- break;
- }
- default:
- ndbrequire(false);
- }
-
- release_object(f_ptr.p->m_obj_ptr_i);
- c_file_hash.release(f_ptr);
- }
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::drop_file_prepare_start(Signal* signal, SchemaOp* op)
-{
- jam();
- send_drop_file(signal, op, DropFileImplReq::Prepare);
-}
-
-void
-Dbdict::drop_undofile_prepare_start(Signal* signal, SchemaOp* op)
-{
- jam();
- op->m_errorCode = DropFileRef::DropUndoFileNotSupported;
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::drop_file_commit_start(Signal* signal, SchemaOp* op)
-{
- jam();
- send_drop_file(signal, op, DropFileImplReq::Commit);
-}
-
-void
-Dbdict::drop_file_commit_complete(Signal* signal, SchemaOp* op)
-{
- FilePtr f_ptr;
- FilegroupPtr fg_ptr;
-
- jam();
- c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
- ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
- decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
- release_object(f_ptr.p->m_obj_ptr_i);
- c_file_hash.release(f_ptr);
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::drop_undofile_commit_complete(Signal* signal, SchemaOp* op)
-{
- FilePtr f_ptr;
- FilegroupPtr fg_ptr;
-
- jam();
- c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
- ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
- Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
- list.remove(f_ptr);
- release_object(f_ptr.p->m_obj_ptr_i);
- c_file_hash.release(f_ptr);
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::drop_file_abort_start(Signal* signal, SchemaOp* op)
-{
- jam();
- send_drop_file(signal, op, DropFileImplReq::Abort);
-}
-
-void
-Dbdict::send_drop_file(Signal* signal, SchemaOp* op,
- DropFileImplReq::RequestInfo type)
-{
- DropFileImplReq* req = (DropFileImplReq*)signal->getDataPtrSend();
- FilePtr f_ptr;
- FilegroupPtr fg_ptr;
-
- jam();
- c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
- ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
-
- req->senderData = op->key;
- req->senderRef = reference();
- req->requestInfo = type;
-
- req->file_id = f_ptr.p->key;
- req->filegroup_id = f_ptr.p->m_filegroup_id;
- req->filegroup_version = fg_ptr.p->m_version;
-
- Uint32 ref= 0;
- switch(op->m_obj_type){
- case DictTabInfo::Datafile:
- {
- jam();
- ref = TSMAN_REF;
- break;
- }
- case DictTabInfo::Undofile:
- {
- jam();
- ref = LGMAN_REF;
- break;
- }
- default:
- ndbrequire(false);
- }
- sendSignal(ref, GSN_DROP_FILE_REQ, signal,
- DropFileImplReq::SignalLength, JBB);
-}
-
-void
-Dbdict::execDROP_OBJ_REF(Signal* signal)
-{
- DropObjRef * const ref = (DropObjRef*)signal->getDataPtr();
- Ptr<SchemaTransaction> trans_ptr;
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
- if(ref->errorCode != DropObjRef::NF_FakeErrorREF){
- jam();
- trans_ptr.p->setErrorCode(ref->errorCode);
- }
- Uint32 node = refToNode(ref->senderRef);
- schemaOp_reply(signal, trans_ptr.p, node);
-}
-
-void
-Dbdict::execDROP_OBJ_CONF(Signal* signal)
-{
- DropObjConf * const conf = (DropObjConf*)signal->getDataPtr();
- Ptr<SchemaTransaction> trans_ptr;
-
- jamEntry();
- ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
- schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
-}
-
-void
-Dbdict::execDROP_FILE_REF(Signal* signal)
-{
- DropFileImplRef * ref = (DropFileImplRef*)signal->getDataPtr();
- DropObjRecordPtr op_ptr;
-
- jamEntry();
- ndbrequire(c_opDropObj.find(op_ptr, ref->senderData));
- op_ptr.p->m_errorCode = ref->errorCode;
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::execDROP_FILE_CONF(Signal* signal)
-{
- DropFileImplConf * rep =
- (DropFileImplConf*)signal->getDataPtr();
- DropObjRecordPtr op_ptr;
-
- jamEntry();
- ndbrequire(c_opDropObj.find(op_ptr, rep->senderData));
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::execDROP_FILEGROUP_REF(Signal* signal)
-{
- DropFilegroupImplRef * ref = (DropFilegroupImplRef*)signal->getDataPtr();
- DropObjRecordPtr op_ptr;
-
- jamEntry();
- ndbrequire(c_opDropObj.find(op_ptr, ref->senderData));
- op_ptr.p->m_errorCode = ref->errorCode;
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::execDROP_FILEGROUP_CONF(Signal* signal)
-{
- DropFilegroupImplConf * rep =
- (DropFilegroupImplConf*)signal->getDataPtr();
- DropObjRecordPtr op_ptr;
-
- jamEntry();
- ndbrequire(c_opDropObj.find(op_ptr, rep->senderData));
- execute(signal, op_ptr.p->m_callback, 0);
-}
-
-void
-Dbdict::drop_fg_prepare_start(Signal* signal, SchemaOp* op)
-{
- FilegroupPtr fg_ptr;
- c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
-
- DictObject * obj = c_obj_pool.getPtr(fg_ptr.p->m_obj_ptr_i);
- if (obj->m_ref_count)
- {
- jam();
- op->m_errorCode = DropFilegroupRef::FilegroupInUse;
- execute(signal, op->m_callback, 0);
- }
- else
- {
- jam();
- send_drop_fg(signal, op, DropFilegroupImplReq::Prepare);
- }
-}
-
-void
-Dbdict::drop_fg_commit_start(Signal* signal, SchemaOp* op)
-{
- FilegroupPtr fg_ptr;
- c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
- if (op->m_obj_type == DictTabInfo::LogfileGroup)
- {
- jam();
- /**
- * Mark all undofiles as dropped
- */
- Ptr<File> filePtr;
- Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
- XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
- for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
- {
- jam();
- Uint32 objId = filePtr.p->key;
- SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, objId);
- tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
- computeChecksum(xsf, objId / NDB_SF_PAGE_ENTRIES);
- release_object(filePtr.p->m_obj_ptr_i);
- c_file_hash.remove(filePtr);
- }
- list.release();
- }
- else if(op->m_obj_type == DictTabInfo::Tablespace)
- {
- FilegroupPtr lg_ptr;
- jam();
- ndbrequire(c_filegroup_hash.
- find(lg_ptr,
- fg_ptr.p->m_tablespace.m_default_logfile_group_id));
-
- decrease_ref_count(lg_ptr.p->m_obj_ptr_i);
- }
- jam();
- send_drop_fg(signal, op, DropFilegroupImplReq::Commit);
-}
-
-void
-Dbdict::drop_fg_commit_complete(Signal* signal, SchemaOp* op)
-{
- FilegroupPtr fg_ptr;
- c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
-
- jam();
- release_object(fg_ptr.p->m_obj_ptr_i);
- c_filegroup_hash.release(fg_ptr);
- execute(signal, op->m_callback, 0);
-}
-
-void
-Dbdict::drop_fg_abort_start(Signal* signal, SchemaOp* op)
-{
- jam();
- send_drop_fg(signal, op, DropFilegroupImplReq::Abort);
-}
-
-void
-Dbdict::send_drop_fg(Signal* signal, SchemaOp* op,
- DropFilegroupImplReq::RequestInfo type)
-{
- DropFilegroupImplReq* req = (DropFilegroupImplReq*)signal->getDataPtrSend();
-
- FilegroupPtr fg_ptr;
- c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
-
- req->senderData = op->key;
- req->senderRef = reference();
- req->requestInfo = type;
-
- req->filegroup_id = fg_ptr.p->key;
- req->filegroup_version = fg_ptr.p->m_version;
-
- Uint32 ref= 0;
- switch(op->m_obj_type){
- case DictTabInfo::Tablespace:
- ref = TSMAN_REF;
- break;
- case DictTabInfo::LogfileGroup:
- ref = LGMAN_REF;
- break;
- default:
- ndbrequire(false);
- }
-
- sendSignal(ref, GSN_DROP_FILEGROUP_REQ, signal,
- DropFilegroupImplReq::SignalLength, JBB);
-}
-
-/*
- return 1 if all of the below is true
- a) node in single user mode
- b) senderRef is not a db node
- c) senderRef nodeid is not the singleUserApi
-*/
-int Dbdict::checkSingleUserMode(Uint32 senderRef)
-{
- Uint32 nodeId = refToNode(senderRef);
- return
- getNodeState().getSingleUserMode() &&
- (getNodeInfo(nodeId).m_type != NodeInfo::DB) &&
- (nodeId != getNodeState().getSingleUserApi());
-}
-
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
deleted file mode 100644
index 6d738740e87..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ /dev/null
@@ -1,2707 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBDICT_H
-#define DBDICT_H
-
-/**
- * Dict : Dictionary Block
- */
-#include <ndb_limits.h>
-#include <trigger_definitions.h>
-#include <pc.hpp>
-#include <DLHashTable.hpp>
-#include <DLFifoList.hpp>
-#include <CArray.hpp>
-#include <KeyTable.hpp>
-#include <KeyTable2.hpp>
-#include <KeyTable2Ref.hpp>
-#include <SimulatedBlock.hpp>
-#include <SimpleProperties.hpp>
-#include <SignalCounter.hpp>
-#include <Bitmask.hpp>
-#include <AttributeList.hpp>
-#include <signaldata/GetTableId.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/CreateTable.hpp>
-#include <signaldata/CreateTab.hpp>
-#include <signaldata/DropTable.hpp>
-#include <signaldata/AlterTable.hpp>
-#include <signaldata/AlterTab.hpp>
-#include <signaldata/CreateIndx.hpp>
-#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 <signaldata/SumaImpl.hpp>
-#include "SchemaFile.hpp"
-#include <blocks/mutexes.hpp>
-#include <SafeCounter.hpp>
-#include <RequestTracker.hpp>
-#include <Rope.hpp>
-#include <signaldata/DictObjOp.hpp>
-#include <signaldata/DropFilegroupImpl.hpp>
-#include <SLList.hpp>
-
-#ifdef DBDICT_C
-// Debug Macros
-
-/*--------------------------------------------------------------*/
-// Constants for CONTINUEB
-/*--------------------------------------------------------------*/
-#define ZPACK_TABLE_INTO_PAGES 0
-#define ZSEND_GET_TAB_RESPONSE 3
-#define ZDICT_LOCK_POLL 4
-
-
-/*--------------------------------------------------------------*/
-// Other constants in alphabetical order
-/*--------------------------------------------------------------*/
-#define ZNOMOREPHASES 255
-
-/*--------------------------------------------------------------*/
-// Schema file defines
-/*--------------------------------------------------------------*/
-#define ZSCHEMA_WORDS 4
-
-/*--------------------------------------------------------------*/
-// Page constants
-/*--------------------------------------------------------------*/
-#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
-#define ZPOS_VERSION 18
-#define ZPOS_PAGE_HEADER_SIZE 19
-
-/*--------------------------------------------------------------*/
-// Size constants
-/*--------------------------------------------------------------*/
-#define ZFS_CONNECT_SIZE 4
-#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 (ZMAX_PAGES_OF_TABLE_DEFINITION + 1)
-#define ZNO_OF_FRAGRECORD 5
-
-/*--------------------------------------------------------------*/
-// Error codes
-/*--------------------------------------------------------------*/
-#define ZNODE_FAILURE_ERROR 704
-#endif
-
-/**
- * Systable NDB$EVENTS_0
- */
-#define EVENT_SYSTEM_TABLE_LENGTH 8
-
-struct sysTab_NDBEVENTS_0 {
- char NAME[MAX_TAB_NAME_SIZE];
- Uint32 EVENT_TYPE;
- Uint32 TABLEID;
- Uint32 TABLEVERSION;
- char TABLE_NAME[MAX_TAB_NAME_SIZE];
- Uint32 ATTRIBUTE_MASK[MAXNROFATTRIBUTESINWORDS];
- Uint32 SUBID;
- Uint32 SUBKEY;
-};
-
-/**
- * DICT - This blocks handles all metadata
- */
-class Dbdict: public SimulatedBlock {
-public:
- /*
- * 2.3 RECORD AND FILESIZES
- */
-
- /**
- * Table attributes. Permanent data.
- *
- * Indexes have an attribute list which duplicates primary table
- * attributes. This is wrong but convenient.
- */
- struct AttributeRecord {
- AttributeRecord(){}
-
- /* attribute id */
- Uint16 attributeId;
-
- /* Attribute number within tuple key (counted from 1) */
- Uint16 tupleKey;
-
- /* Attribute name (unique within table) */
- RopeHandle attributeName;
-
- /* Attribute description (old-style packed descriptor) */
- Uint32 attributeDescriptor;
-
- /* Extended attributes */
- Uint32 extType;
- Uint32 extPrecision;
- Uint32 extScale;
- Uint32 extLength;
-
- /* Autoincrement flag, only for ODBC/SQL */
- bool autoIncrement;
-
- /* Default value as null-terminated string, only for ODBC/SQL */
- RopeHandle defaultValue;
-
- struct {
- Uint32 m_name_len;
- const char * m_name_ptr;
- RopePool * m_pool;
- } m_key;
-
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- Uint32 nextHash;
- Uint32 prevHash;
-
- Uint32 hashValue() const { return attributeName.hashValue();}
- bool equal(const AttributeRecord& obj) const {
- if(obj.hashValue() == hashValue()){
- ConstRope r(* m_key.m_pool, obj.attributeName);
- return r.compare(m_key.m_name_ptr, m_key.m_name_len) == 0;
- }
- return false;
- }
-
- /** Singly linked in internal (attributeId) order */
- // TODO use DL template when possible to have more than 1
- Uint32 nextAttributeIdPtrI;
- };
- typedef Ptr<AttributeRecord> AttributeRecordPtr;
- ArrayPool<AttributeRecord> c_attributeRecordPool;
- DLHashTable<AttributeRecord> c_attributeRecordHash;
-
- /**
- * Shared table / index record. Most of this is permanent data stored
- * on disk. Index trigger ids are volatile.
- */
- struct TableRecord {
- TableRecord(){}
- Uint32 maxRowsLow;
- Uint32 maxRowsHigh;
- Uint32 minRowsLow;
- Uint32 minRowsHigh;
- /* Table id (array index in DICT and other blocks) */
- Uint32 tableId;
- Uint32 m_obj_ptr_i;
-
- /* Table version (incremented when tableId is re-used) */
- Uint32 tableVersion;
-
- /* Table name (may not be unique under "alter table") */
- RopeHandle tableName;
-
- /* Type of table or index */
- DictTabInfo::TableType tableType;
-
- /* Is table or index online (this flag is not used in DICT) */
- bool online;
-
- /* Primary table of index otherwise RNIL */
- Uint32 primaryTableId;
-
- /* Type of fragmentation (small/medium/large) */
- DictTabInfo::FragmentType fragmentType;
-
- /* Global checkpoint identity when table created */
- Uint32 gciTableCreated;
-
- /* Is the table logged (i.e. data survives system restart) */
- enum Bits
- {
- TR_Logged = 0x1,
- TR_RowGCI = 0x2,
- TR_RowChecksum = 0x4,
- TR_Temporary = 0x8,
- TR_ForceVarPart = 0x10
- };
- Uint16 m_bits;
-
- /* Number of attibutes in table */
- Uint16 noOfAttributes;
-
- /* Number of null attributes in table (should be computed) */
- Uint16 noOfNullAttr;
-
- /* Number of primary key attributes (should be computed) */
- Uint16 noOfPrimkey;
-
- /* Length of primary key in words (should be computed) */
- /* For ordered index this is tree node size in words */
- Uint16 tupKeyLength;
-
- /** */
- Uint16 noOfCharsets;
-
- /* K value for LH**3 algorithm (only 6 allowed currently) */
- Uint8 kValue;
-
- /* Local key length in words (currently 1) */
- Uint8 localKeyLen;
-
- /*
- * Parameter for hash algorithm that specifies the load factor in
- * percentage of fill level in buckets. A high value means we are
- * splitting early and that buckets are only lightly used. A high
- * value means that we have fill the buckets more and get more
- * likelihood of overflow buckets.
- */
- Uint8 maxLoadFactor;
-
- /*
- Flag to indicate default number of partitions
- */
- bool defaultNoPartFlag;
-
- /*
- Flag to indicate using linear hash function
- */
- bool linearHashFlag;
-
- /*
- * Used when shrinking to decide when to merge buckets. Hysteresis
- * is thus possible. Should be smaller but not much smaller than
- * maxLoadFactor
- */
- Uint8 minLoadFactor;
-
- /* Convenience routines */
- bool isTable() const;
- bool isIndex() const;
- bool isUniqueIndex() const;
- bool isNonUniqueIndex() const;
- bool isHashIndex() const;
- bool isOrderedIndex() const;
-
- /****************************************************
- * Support variables for table handling
- ****************************************************/
-
- /* Active page which is sent to disk */
- Uint32 activePage;
-
- /** File pointer received from disk */
- Uint32 filePtr[2];
-
- /** Pointer to first attribute in table */
- DLFifoList<AttributeRecord>::Head m_attributes;
-
- /* Pointer to first page of table description */
- Uint32 firstPage;
-
- Uint32 nextPool;
-
- enum TabState {
- NOT_DEFINED = 0,
- DEFINING = 2,
- DEFINED = 4,
- PREPARE_DROPPING = 5,
- DROPPING = 6,
- BACKUP_ONGOING = 7
- };
- TabState tabState;
-
- /* State when returning from TC_SCHVERREQ */
- enum TabReturnState {
- TRS_IDLE = 0,
- ADD_TABLE = 1,
- SLAVE_SYSTEM_RESTART = 2,
- MASTER_SYSTEM_RESTART = 3
- };
- TabReturnState tabReturnState;
-
- /** Number of words */
- Uint32 packedSize;
-
- /** Index state (volatile data) */
- enum IndexState {
- IS_UNDEFINED = 0, // initial
- IS_OFFLINE = 1, // index table created
- IS_BUILDING = 2, // building (local state)
- IS_DROPPING = 3, // dropping (local state)
- IS_ONLINE = 4, // online
- IS_BROKEN = 9 // build or drop aborted
- };
- IndexState indexState;
-
- /** Trigger ids of index (volatile data) */
- Uint32 insertTriggerId;
- Uint32 updateTriggerId;
- Uint32 deleteTriggerId;
- Uint32 customTriggerId; // ordered index
- Uint32 buildTriggerId; // temp during build
-
- /** Index state in other blocks on this node */
- enum IndexLocal {
- IL_CREATED_TC = 1 << 0 // created in TC
- };
- Uint32 indexLocal;
-
- Uint32 noOfNullBits;
-
- /** frm data for this table */
- RopeHandle frmData;
- RopeHandle tsData;
- RopeHandle ngData;
- RopeHandle rangeData;
-
- Uint32 fragmentCount;
- Uint32 m_tablespace_id;
-
- /*
- * Access rights to table during single user mode
- */
- Uint8 singleUserMode;
- };
-
- typedef Ptr<TableRecord> TableRecordPtr;
- ArrayPool<TableRecord> c_tableRecordPool;
-
- /** Node Group and Tablespace id+version + range or list data.
- * This is only stored temporarily in DBDICT during an ongoing
- * change.
- * TODO RONM: Look into improvements of this
- */
- Uint32 c_fragDataLen;
- Uint16 c_fragData[MAX_NDB_PARTITIONS];
- Uint32 c_tsIdData[2*MAX_NDB_PARTITIONS];
-
- /**
- * Triggers. This is volatile data not saved on disk. Setting a
- * trigger online creates the trigger in TC (if index) and LQH-TUP.
- */
- struct TriggerRecord {
- TriggerRecord() {}
-
- /** Trigger state */
- enum TriggerState {
- TS_NOT_DEFINED = 0,
- TS_DEFINING = 1,
- TS_OFFLINE = 2, // created globally in DICT
- TS_BUILDING = 3,
- TS_DROPPING = 4,
- TS_ONLINE = 5 // activated globally
- };
- TriggerState triggerState;
-
- /** Trigger state in other blocks on this node */
- enum IndexLocal {
- TL_CREATED_TC = 1 << 0, // created in TC
- TL_CREATED_LQH = 1 << 1 // created in LQH-TUP
- };
- Uint32 triggerLocal;
-
- /** Trigger name, used by DICT to identify the trigger */
- RopeHandle triggerName;
-
- /** Trigger id, used by TRIX, TC, LQH, and TUP to identify the trigger */
- Uint32 triggerId;
- Uint32 m_obj_ptr_i;
-
- /** Table id, the table the trigger is defined on */
- Uint32 tableId;
-
- /** Trigger type, defines what the trigger is used for */
- TriggerType::Value triggerType;
-
- /** Trigger action time, defines when the trigger should fire */
- TriggerActionTime::Value triggerActionTime;
-
- /** Trigger event, defines what events the trigger should monitor */
- TriggerEvent::Value triggerEvent;
-
- /** Monitor all replicas */
- bool monitorReplicas;
-
- /** Monitor all, the trigger monitors changes of all attributes in table */
- bool monitorAllAttributes;
-
- /** Monitor all, the trigger monitors changes of all attributes in table */
- bool reportAllMonitoredAttributes;
-
- /**
- * Attribute mask, defines what attributes are to be monitored.
- * Can be seen as a compact representation of SQL column name list.
- */
- AttributeMask attributeMask;
-
- /** Index id, only used by secondary_index triggers */
- Uint32 indexId;
-
- /** Pointer to the next attribute used by ArrayPool */
- Uint32 nextPool;
- };
-
- Uint32 c_maxNoOfTriggers;
- typedef Ptr<TriggerRecord> TriggerRecordPtr;
- ArrayPool<TriggerRecord> c_triggerRecordPool;
-
- /**
- * Information for each FS connection.
- ***************************************************************************/
- struct FsConnectRecord {
- enum FsState {
- IDLE = 0,
- OPEN_WRITE_SCHEMA = 1,
- WRITE_SCHEMA = 2,
- CLOSE_WRITE_SCHEMA = 3,
- OPEN_READ_SCHEMA1 = 4,
- OPEN_READ_SCHEMA2 = 5,
- READ_SCHEMA1 = 6,
- READ_SCHEMA2 = 7,
- CLOSE_READ_SCHEMA = 8,
- OPEN_READ_TAB_FILE1 = 9,
- OPEN_READ_TAB_FILE2 = 10,
- READ_TAB_FILE1 = 11,
- READ_TAB_FILE2 = 12,
- CLOSE_READ_TAB_FILE = 13,
- OPEN_WRITE_TAB_FILE = 14,
- WRITE_TAB_FILE = 15,
- CLOSE_WRITE_TAB_FILE = 16
- };
- /** File Pointer for this file system connection */
- Uint32 filePtr;
-
- /** Reference of owner record */
- Uint32 ownerPtr;
-
- /** State of file system connection */
- FsState fsState;
-
- /** Used by Array Pool for free list handling */
- Uint32 nextPool;
- };
-
- typedef Ptr<FsConnectRecord> FsConnectRecordPtr;
- ArrayPool<FsConnectRecord> c_fsConnectRecordPool;
-
- /**
- * This record stores all the information about a node and all its attributes
- ***************************************************************************/
- struct NodeRecord {
- enum NodeState {
- API_NODE = 0,
- NDB_NODE_ALIVE = 1,
- NDB_NODE_DEAD = 2
- };
- bool hotSpare;
- NodeState nodeState;
- };
-
- typedef Ptr<NodeRecord> NodeRecordPtr;
- CArray<NodeRecord> c_nodes;
- NdbNodeBitmask c_aliveNodes;
-
- struct PageRecord {
- Uint32 word[8192];
- };
-
- typedef Ptr<PageRecord> PageRecordPtr;
- CArray<PageRecord> c_pageRecordArray;
-
- struct SchemaPageRecord {
- Uint32 word[NDB_SF_PAGE_SIZE_IN_WORDS];
- };
-
- CArray<SchemaPageRecord> c_schemaPageRecordArray;
-
- DictTabInfo::Table c_tableDesc;
-
- /**
- * A page for create index table signal.
- */
- PageRecord c_indexPage;
-
- struct File {
- File() {}
-
- Uint32 key;
- Uint32 m_magic;
- Uint32 m_version;
- Uint32 m_obj_ptr_i;
- Uint32 m_filegroup_id;
- Uint32 m_type;
- Uint64 m_file_size;
- Uint64 m_file_free;
- RopeHandle m_path;
-
- Uint32 nextList;
- union {
- Uint32 prevList;
- Uint32 nextPool;
- };
- Uint32 nextHash, prevHash;
-
- Uint32 hashValue() const { return key;}
- bool equal(const File& obj) const { return key == obj.key;}
- };
- typedef Ptr<File> FilePtr;
- typedef RecordPool<File, RWPool> File_pool;
- typedef DLListImpl<File_pool, File> File_list;
- typedef LocalDLListImpl<File_pool, File> Local_file_list;
- typedef KeyTableImpl<File_pool, File> File_hash;
-
- struct Filegroup {
- Filegroup(){}
-
- Uint32 key;
- Uint32 m_obj_ptr_i;
- Uint32 m_magic;
-
- Uint32 m_type;
- Uint32 m_version;
- RopeHandle m_name;
-
- union {
- struct {
- Uint32 m_extent_size;
- Uint32 m_default_logfile_group_id;
- } m_tablespace;
-
- struct {
- Uint32 m_undo_buffer_size;
- File_list::HeadPOD m_files;
- } m_logfilegroup;
- };
-
- union {
- Uint32 nextPool;
- Uint32 nextList;
- Uint32 nextHash;
- };
- Uint32 prevHash;
-
- Uint32 hashValue() const { return key;}
- bool equal(const Filegroup& obj) const { return key == obj.key;}
- };
- typedef Ptr<Filegroup> FilegroupPtr;
- typedef RecordPool<Filegroup, RWPool> Filegroup_pool;
- typedef KeyTableImpl<Filegroup_pool, Filegroup> Filegroup_hash;
-
- File_pool c_file_pool;
- Filegroup_pool c_filegroup_pool;
- File_hash c_file_hash;
- Filegroup_hash c_filegroup_hash;
-
- RopePool c_rope_pool;
-
- struct DictObject {
- DictObject() {}
- Uint32 m_id;
- Uint32 m_type;
- Uint32 m_ref_count;
- RopeHandle m_name;
- union {
- struct {
- Uint32 m_name_len;
- const char * m_name_ptr;
- RopePool * m_pool;
- } m_key;
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 nextHash;
- Uint32 prevHash;
-
- Uint32 hashValue() const { return m_name.hashValue();}
- bool equal(const DictObject& obj) const {
- if(obj.hashValue() == hashValue()){
- ConstRope r(* m_key.m_pool, obj.m_name);
- return r.compare(m_key.m_name_ptr, m_key.m_name_len) == 0;
- }
- return false;
- }
- };
-
- DLHashTable<DictObject> c_obj_hash; // Name
- ArrayPool<DictObject> c_obj_pool;
-
- DictObject * get_object(const char * name){
- return get_object(name, strlen(name) + 1);
- }
-
- DictObject * get_object(const char * name, Uint32 len){
- return get_object(name, len, Rope::hash(name, len));
- }
-
- DictObject * get_object(const char * name, Uint32 len, Uint32 hash);
-
- void release_object(Uint32 obj_ptr_i){
- release_object(obj_ptr_i, c_obj_pool.getPtr(obj_ptr_i));
- }
-
- void release_object(Uint32 obj_ptr_i, DictObject* obj_ptr_p);
-
- void increase_ref_count(Uint32 obj_ptr_i);
- void decrease_ref_count(Uint32 obj_ptr_i);
-
-public:
- Dbdict(Block_context& ctx);
- virtual ~Dbdict();
-
-private:
- BLOCK_DEFINES(Dbdict);
-
- // Signal receivers
- void execDICTSTARTREQ(Signal* signal);
-
- void execGET_TABINFOREQ(Signal* signal);
- void execGET_TABLEDID_REQ(Signal* signal);
- void execGET_TABINFO_REF(Signal* signal);
- void execGET_TABINFO_CONF(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- void execDUMP_STATE_ORD(Signal* signal);
- void execHOT_SPAREREP(Signal* signal);
- void execDIADDTABCONF(Signal* signal);
- void execDIADDTABREF(Signal* signal);
- void execTAB_COMMITCONF(Signal* signal);
- void execTAB_COMMITREF(Signal* signal);
- void execGET_SCHEMA_INFOREQ(Signal* signal);
- void execSCHEMA_INFO(Signal* signal);
- void execSCHEMA_INFOCONF(Signal* signal);
- void execREAD_NODESCONF(Signal* signal);
- void execFSCLOSECONF(Signal* signal);
- void execFSOPENCONF(Signal* signal);
- void execFSOPENREF(Signal* signal);
- void execFSREADCONF(Signal* signal);
- void execFSREADREF(Signal* signal);
- void execFSWRITECONF(Signal* signal);
- void execNDB_STTOR(Signal* signal);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execSTTOR(Signal* signal);
- void execTC_SCHVERCONF(Signal* signal);
- void execNODE_FAILREP(Signal* signal);
- void execINCL_NODEREQ(Signal* signal);
- void execAPI_FAILREQ(Signal* signal);
-
- void execWAIT_GCP_REF(Signal* signal);
- void execWAIT_GCP_CONF(Signal* signal);
-
- void execLIST_TABLES_REQ(Signal* signal);
-
- // Index signals
- void execCREATE_INDX_REQ(Signal* signal);
- void execCREATE_INDX_CONF(Signal* signal);
- void execCREATE_INDX_REF(Signal* signal);
-
- void execALTER_INDX_REQ(Signal* signal);
- void execALTER_INDX_CONF(Signal* signal);
- void execALTER_INDX_REF(Signal* signal);
-
- void execCREATE_TABLE_CONF(Signal* signal);
- void execCREATE_TABLE_REF(Signal* signal);
-
- void execDROP_INDX_REQ(Signal* signal);
- void execDROP_INDX_CONF(Signal* signal);
- void execDROP_INDX_REF(Signal* signal);
-
- void execDROP_TABLE_CONF(Signal* signal);
- void execDROP_TABLE_REF(Signal* signal);
-
- void execBUILDINDXREQ(Signal* signal);
- void execBUILDINDXCONF(Signal* signal);
- void execBUILDINDXREF(Signal* signal);
-
- 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_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);
- void execCREATE_TRIG_REF(Signal* signal);
- void execALTER_TRIG_REQ(Signal* signal);
- void execALTER_TRIG_CONF(Signal* signal);
- void execALTER_TRIG_REF(Signal* signal);
- void execDROP_TRIG_REQ(Signal* signal);
- void execDROP_TRIG_CONF(Signal* signal);
- void execDROP_TRIG_REF(Signal* signal);
-
- void execDROP_TABLE_REQ(Signal* signal);
-
- void execPREP_DROP_TAB_REQ(Signal* signal);
- void execPREP_DROP_TAB_REF(Signal* signal);
- void execPREP_DROP_TAB_CONF(Signal* signal);
-
- void execDROP_TAB_REQ(Signal* signal);
- void execDROP_TAB_REF(Signal* signal);
- void execDROP_TAB_CONF(Signal* signal);
-
- void execCREATE_TABLE_REQ(Signal* signal);
- void execALTER_TABLE_REQ(Signal* signal);
- void execCREATE_FRAGMENTATION_REF(Signal*);
- void execCREATE_FRAGMENTATION_CONF(Signal*);
- void execCREATE_TAB_REQ(Signal* signal);
- void execADD_FRAGREQ(Signal* signal);
- void execLQHFRAGREF(Signal* signal);
- void execLQHFRAGCONF(Signal* signal);
- void execLQHADDATTREF(Signal* signal);
- void execLQHADDATTCONF(Signal* signal);
- void execCREATE_TAB_REF(Signal* signal);
- void execCREATE_TAB_CONF(Signal* signal);
- void execALTER_TAB_REQ(Signal* signal);
- void execALTER_TAB_REF(Signal* signal);
- void execALTER_TAB_CONF(Signal* signal);
- bool check_ndb_versions() const;
-
- void execCREATE_FILE_REQ(Signal* signal);
- void execCREATE_FILEGROUP_REQ(Signal* signal);
- void execDROP_FILE_REQ(Signal* signal);
- void execDROP_FILEGROUP_REQ(Signal* signal);
-
- // Internal
- void execCREATE_FILE_REF(Signal* signal);
- void execCREATE_FILE_CONF(Signal* signal);
- void execCREATE_FILEGROUP_REF(Signal* signal);
- void execCREATE_FILEGROUP_CONF(Signal* signal);
- void execDROP_FILE_REF(Signal* signal);
- void execDROP_FILE_CONF(Signal* signal);
- void execDROP_FILEGROUP_REF(Signal* signal);
- void execDROP_FILEGROUP_CONF(Signal* signal);
-
- void execDICT_LOCK_REQ(Signal* signal);
- void execDICT_UNLOCK_ORD(Signal* signal);
-
- /*
- * 2.4 COMMON STORED VARIABLES
- */
-
- /**
- * This record stores all the state needed
- * when the schema page is being sent to other nodes
- ***************************************************************************/
- struct SendSchemaRecord {
- /** Number of words of schema data */
- Uint32 noOfWords;
- /** Page Id of schema data */
- Uint32 pageId;
-
- Uint32 nodeId;
- SignalCounter m_SCHEMAINFO_Counter;
-
- Uint32 noOfWordsCurrentlySent;
- Uint32 noOfSignalsSentSinceDelay;
-
- bool inUse;
- };
- SendSchemaRecord c_sendSchemaRecord;
-
- /**
- * This record stores all the state needed
- * when a table file is being read from disk
- ****************************************************************************/
- struct ReadTableRecord {
- /** Number of Pages */
- Uint32 no_of_words;
- /** Page Id*/
- Uint32 pageId;
- /** Table Id of read table */
- Uint32 tableId;
-
- bool inUse;
- Callback m_callback;
- };
- ReadTableRecord c_readTableRecord;
-
- /**
- * This record stores all the state needed
- * when a table file is being written to disk
- ****************************************************************************/
- struct WriteTableRecord {
- /** Number of Pages */
- Uint32 no_of_words;
- /** Page Id*/
- Uint32 pageId;
- /** Table Files Handled, local state variable */
- Uint32 noOfTableFilesHandled;
- /** Table Id of written table */
- Uint32 tableId;
- /** State, indicates from where it was called */
- enum TableWriteState {
- IDLE = 0,
- WRITE_ADD_TABLE_MASTER = 1,
- WRITE_ADD_TABLE_SLAVE = 2,
- WRITE_RESTART_FROM_MASTER = 3,
- WRITE_RESTART_FROM_OWN = 4,
- TWR_CALLBACK = 5
- };
- TableWriteState tableWriteState;
- Callback m_callback;
- };
- WriteTableRecord c_writeTableRecord;
-
- /**
- * This record stores all the state needed
- * when a schema file is being read from disk
- ****************************************************************************/
- 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_HEAD = 1,
- INITIAL_READ = 2
- };
- SchemaReadState schemaReadState;
- };
- ReadSchemaRecord c_readSchemaRecord;
-
- /**
- * This record stores all the state needed
- * when a schema file is being written to disk
- ****************************************************************************/
- 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;
-
- bool inUse;
- Callback m_callback;
- };
- WriteSchemaRecord c_writeSchemaRecord;
-
- /**
- * This record stores all the information needed
- * when a file is being read from disk
- ****************************************************************************/
- struct RestartRecord {
- /** Global check point identity */
- Uint32 gciToRestart;
-
- /** The active table at restart process */
- Uint32 activeTable;
-
- /** The active table at restart process */
- BlockReference returnBlockRef;
-
- Uint32 m_pass; // 0 tablespaces/logfilegroups, 1 tables, 2 indexes
- };
- RestartRecord c_restartRecord;
-
- /**
- * This record stores all the information needed
- * when a file is being read from disk
- ****************************************************************************/
- struct RetrieveRecord {
- RetrieveRecord(){ noOfWaiters = 0;}
-
- /** Only one retrieve table definition at a time */
- bool busyState;
-
- /**
- * No of waiting in time queue
- */
- Uint32 noOfWaiters;
-
- /** Block Reference of retriever */
- BlockReference blockRef;
-
- /** Id of retriever */
- Uint32 m_senderData;
-
- /** Table id of retrieved table */
- Uint32 tableId;
-
- Uint32 m_table_type;
-
- /** Starting page to retrieve data from */
- Uint32 retrievePage;
-
- /** Number of pages retrieved */
- Uint32 retrievedNoOfPages;
-
- /** Number of words retrieved */
- Uint32 retrievedNoOfWords;
-
- /** Number of words sent currently */
- Uint32 currentSent;
-
- /**
- * Long signal stuff
- */
- bool m_useLongSig;
- };
- RetrieveRecord c_retrieveRecord;
-
- /**
- * This record stores all the information needed
- * when a file is being read from disk
- *
- * This is the info stored in one entry of the schema
- * page. Each table has 4 words of info.
- * Word 1: Schema version (upper 16 bits)
- * Table State (lower 16 bits)
- * Word 2: Number of pages of table description
- * Word 3: Global checkpoint id table was created
- * Word 4: Currently zero
- ****************************************************************************/
- struct SchemaRecord {
- /** Schema file first page (0) */
- Uint32 schemaPage;
-
- /** Old Schema file first page (used at node restart) */
- Uint32 oldSchemaPage;
-
- Callback m_callback;
- };
- SchemaRecord c_schemaRecord;
-
- /*
- * 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);
-
-
- /* ----------------------------------------------------------------------- */
- // Node References
- /* ----------------------------------------------------------------------- */
- Uint16 c_masterNodeId;
-
- /* ----------------------------------------------------------------------- */
- // Various current system properties
- /* ----------------------------------------------------------------------- */
- Uint16 c_numberNode;
- Uint16 c_noHotSpareNodes;
- Uint16 c_noNodesFailed;
- Uint32 c_failureNr;
-
- /* ----------------------------------------------------------------------- */
- // 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_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);
- globalSignalLoggers.log(DBDICT, "bs %d->%d", m_value, bs.m_value);
- m_value = bs.m_value;
- return *this;
- }
- int m_value;
- };
-#endif
- BlockState c_blockState;
-
- struct PackTable {
-
- enum PackTableState {
- PTS_IDLE = 0,
- PTS_GET_TAB = 3
- } m_state;
-
- } c_packTable;
-
- Uint32 c_startPhase;
- Uint32 c_restartType;
- bool c_initialStart;
- bool c_systemRestart;
- bool c_nodeRestart;
- bool c_initialNodeRestart;
- Uint32 c_tabinfoReceived;
-
- /**
- * Temporary structure used when parsing table info
- */
- struct ParseDictTabInfoRecord {
- DictTabInfo::RequestType requestType;
- Uint32 errorCode;
- Uint32 errorLine;
-
- SimpleProperties::UnpackStatus status;
- Uint32 errorKey;
- TableRecordPtr tablePtr;
- };
-
- // Operation records
-
- /**
- * Common part of operation records. Uses KeyTable2. Note that each
- * seize/release invokes ctor/dtor automatically.
- */
- struct OpRecordCommon {
- OpRecordCommon() {}
- Uint32 key; // key shared between master and slaves
- Uint32 nextHash;
- Uint32 prevHash;
- Uint32 hashValue() const {
- return key;
- }
- bool equal(const OpRecordCommon& rec) const {
- return key == rec.key;
- }
- };
-
- /**
- * Create table record
- */
- struct CreateTableRecord : OpRecordCommon {
- CreateTableRecord() {}
- Uint32 m_senderRef;
- Uint32 m_senderData;
- Uint32 m_coordinatorRef;
-
- Uint32 m_errorCode;
- void setErrorCode(Uint32 c){ if(m_errorCode == 0) m_errorCode = c;}
-
- // For alter table
- Uint32 m_changeMask;
- bool m_alterTableFailed;
- AlterTableRef m_alterTableRef;
- Uint32 m_alterTableId;
-
- /* Previous table name (used for reverting failed table rename) */
- char previousTableName[MAX_TAB_NAME_SIZE];
-
- /* Previous table definition, frm (used for reverting) */
- /** TODO Could preferrably be made dynamic size */
- Uint32 previousFrmLen;
- char previousFrmData[MAX_FRM_DATA_SIZE];
-
- Uint32 m_tablePtrI;
- Uint32 m_tabInfoPtrI;
- Uint32 m_fragmentsPtrI;
-
- Uint32 m_dihAddFragPtr; // Connect ptr towards DIH
- Uint32 m_lqhFragPtr; // Connect ptr towards LQH
-
- Callback m_callback; // Who's using local create tab
- MutexHandle2<DIH_START_LCP_MUTEX> m_startLcpMutex;
-
- struct CoordinatorData {
- Uint32 m_gsn;
- SafeCounterHandle m_counter;
- CreateTabReq::RequestType m_requestType;
- } m_coordinatorData;
- };
- typedef Ptr<CreateTableRecord> CreateTableRecordPtr;
-
- /**
- * Drop table record
- */
- struct DropTableRecord : OpRecordCommon {
- DropTableRecord() {}
- DropTableReq m_request;
-
- Uint32 m_requestType;
- Uint32 m_coordinatorRef;
-
- Uint32 m_errorCode;
- void setErrorCode(Uint32 c){ if(m_errorCode == 0) m_errorCode = c;}
-
- MutexHandle2<BACKUP_DEFINE_MUTEX> m_define_backup_mutex;
-
- /**
- * When sending stuff around
- */
- struct CoordinatorData {
- Uint32 m_gsn;
- Uint32 m_block;
- SignalCounter m_signalCounter;
- } m_coordinatorData;
-
- struct ParticipantData {
- Uint32 m_gsn;
- Uint32 m_block;
- SignalCounter m_signalCounter;
-
- Callback m_callback;
- } m_participantData;
- };
- typedef Ptr<DropTableRecord> DropTableRecordPtr;
-
- /**
- * Request flags passed in signals along with request type and
- * propagated across operations.
- */
- struct RequestFlag {
- enum {
- RF_LOCAL = 1 << 0, // create on local node only
- RF_NOBUILD = 1 << 1, // no need to build index
- RF_NOTCTRIGGER = 1 << 2, // alter trigger: no trigger in TC
- RF_FORCE = 1 << 4 // force drop
- };
- };
-
- /**
- * Operation record for create index.
- */
- struct OpCreateIndex : OpRecordCommon {
- // original request (index id will be added)
- CreateIndxReq m_request;
- AttributeList m_attrList;
- char m_indexName[MAX_TAB_NAME_SIZE];
- bool m_loggedIndex;
- bool m_temporaryIndex;
- // coordinator DICT
- Uint32 m_coordinatorRef;
- bool m_isMaster;
- // state info
- CreateIndxReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- // error info
- CreateIndxRef::ErrorCode m_lastError;
- CreateIndxRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // counters
- SignalCounter m_signalCounter;
- // ctor
- OpCreateIndex() {
- memset(&m_request, 0, sizeof(m_request));
- m_coordinatorRef = 0;
- m_requestType = CreateIndxReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_lastError = CreateIndxRef::NoError;
- m_errorCode = CreateIndxRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void save(const CreateIndxReq* req) {
- m_request = *req;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasLastError() {
- return m_lastError != CreateIndxRef::NoError;
- }
- bool hasError() {
- return m_errorCode != CreateIndxRef::NoError;
- }
- void setError(const CreateIndxRef* ref) {
- m_lastError = CreateIndxRef::NoError;
- if (ref != 0) {
- m_lastError = ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const CreateTableRef* ref) {
- m_lastError = CreateIndxRef::NoError;
- if (ref != 0) {
- switch (ref->getErrorCode()) {
- case CreateTableRef::TableAlreadyExist:
- m_lastError = CreateIndxRef::IndexExists;
- break;
- default:
- m_lastError = (CreateIndxRef::ErrorCode)ref->getErrorCode();
- break;
- }
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- }
- }
- }
- void setError(const AlterIndxRef* ref) {
- m_lastError = CreateIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (CreateIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- };
- typedef Ptr<OpCreateIndex> OpCreateIndexPtr;
-
- /**
- * Operation record for drop index.
- */
- struct OpDropIndex : OpRecordCommon {
- // original request
- DropIndxReq m_request;
- // coordinator DICT
- Uint32 m_coordinatorRef;
- bool m_isMaster;
- // state info
- DropIndxReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- // error info
- DropIndxRef::ErrorCode m_lastError;
- DropIndxRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // counters
- SignalCounter m_signalCounter;
- // ctor
- OpDropIndex() {
- memset(&m_request, 0, sizeof(m_request));
- m_coordinatorRef = 0;
- m_requestType = DropIndxReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_lastError = DropIndxRef::NoError;
- m_errorCode = DropIndxRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void save(const DropIndxReq* req) {
- m_request = *req;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasLastError() {
- return m_lastError != DropIndxRef::NoError;
- }
- bool hasError() {
- return m_errorCode != DropIndxRef::NoError;
- }
- void setError(const DropIndxRef* ref) {
- m_lastError = DropIndxRef::NoError;
- if (ref != 0) {
- m_lastError = ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const AlterIndxRef* ref) {
- m_lastError = DropIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (DropIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const DropTableRef* ref) {
- m_lastError = DropIndxRef::NoError;
- if (ref != 0) {
- switch (ref->errorCode) {
- case DropTableRef::Busy:
- m_lastError = DropIndxRef::Busy;
- break;
- case DropTableRef::NoSuchTable:
- m_lastError = DropIndxRef::IndexNotFound;
- break;
- case DropTableRef::DropInProgress:
- m_lastError = DropIndxRef::Busy;
- break;
- case DropTableRef::NoDropTableRecordAvailable:
- m_lastError = DropIndxRef::Busy;
- break;
- default:
- m_lastError = (DropIndxRef::ErrorCode)ref->errorCode;
- break;
- }
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- }
- }
- };
- typedef Ptr<OpDropIndex> OpDropIndexPtr;
-
- /**
- * Operation record for alter index.
- */
- struct OpAlterIndex : OpRecordCommon {
- // original request plus buffer for attribute lists
- AlterIndxReq m_request;
- AttributeList m_attrList;
- AttributeList m_tableKeyList;
- // coordinator DICT
- Uint32 m_coordinatorRef;
- bool m_isMaster;
- // state info
- AlterIndxReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- // error info
- AlterIndxRef::ErrorCode m_lastError;
- AlterIndxRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // counters
- SignalCounter m_signalCounter;
- Uint32 m_triggerCounter;
- // ctor
- OpAlterIndex() {
- memset(&m_request, 0, sizeof(m_request));
- m_coordinatorRef = 0;
- m_requestType = AlterIndxReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_lastError = AlterIndxRef::NoError;
- m_errorCode = AlterIndxRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- m_triggerCounter = 0;
- }
- void save(const AlterIndxReq* req) {
- m_request = *req;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasLastError() {
- return m_lastError != AlterIndxRef::NoError;
- }
- bool hasError() {
- return m_errorCode != AlterIndxRef::NoError;
- }
- void setError(const AlterIndxRef* ref) {
- m_lastError = AlterIndxRef::NoError;
- if (ref != 0) {
- m_lastError = ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const CreateIndxRef* ref) {
- m_lastError = AlterIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const DropIndxRef* ref) {
- m_lastError = AlterIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const BuildIndxRef* ref) {
- m_lastError = AlterIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- }
- }
- void setError(const CreateTrigRef* ref) {
- m_lastError = AlterIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const DropTrigRef* ref) {
- m_lastError = AlterIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- };
- typedef Ptr<OpAlterIndex> OpAlterIndexPtr;
-
- /**
- * Operation record for build index.
- */
- struct OpBuildIndex : OpRecordCommon {
- // original request plus buffer for attribute lists
- BuildIndxReq m_request;
- AttributeList m_attrList;
- Id_array<MAX_ATTRIBUTES_IN_INDEX+1> m_tableKeyList;
- // coordinator DICT
- Uint32 m_coordinatorRef;
- bool m_isMaster;
- // state info
- BuildIndxReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- Uint32 m_constrTriggerId;
- // error info
- BuildIndxRef::ErrorCode m_lastError;
- BuildIndxRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // counters
- SignalCounter m_signalCounter;
- // ctor
- OpBuildIndex() {
- memset(&m_request, 0, sizeof(m_request));
- m_coordinatorRef = 0;
- m_requestType = BuildIndxReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_lastError = BuildIndxRef::NoError;
- m_errorCode = BuildIndxRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void save(const BuildIndxReq* req) {
- m_request = *req;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasLastError() {
- return m_lastError != BuildIndxRef::NoError;
- }
- bool hasError() {
- return m_errorCode != BuildIndxRef::NoError;
- }
- void setError(const BuildIndxRef* ref) {
- m_lastError = BuildIndxRef::NoError;
- if (ref != 0) {
- m_lastError = ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- }
- }
- void setError(const AlterIndxRef* ref) {
- m_lastError = BuildIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (BuildIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const CreateTrigRef* ref) {
- m_lastError = BuildIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (BuildIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const DropTrigRef* ref) {
- m_lastError = BuildIndxRef::NoError;
- if (ref != 0) {
- m_lastError = (BuildIndxRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- };
- 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;
- union {
- SubStartConf m_sub_start_conf;
- SubStopConf m_sub_stop_conf;
- };
- 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;
- // error info
- Uint32 m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode; /* also used to store master node id
- in case of NotMaster */
- // ctor
- OpCreateEvent() {
- memset(&m_request, 0, sizeof(m_request));
- m_requestType = CreateEvntReq::RT_UNDEFINED;
- 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();
- }
- 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
- Uint32 m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // ctor
- OpDropEvent() {
- memset(&m_request, 0, sizeof(m_request));
- m_errorCode = 0;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void init(const DropEvntReq* req) {
- m_request = *req;
- m_errorCode = 0;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- bool hasError() {
- return m_errorCode != 0;
- }
- 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 {
- // original request (trigger id will be added)
- CreateTrigReq m_request;
- char m_triggerName[MAX_TAB_NAME_SIZE];
- // coordinator DICT
- Uint32 m_coordinatorRef;
- bool m_isMaster;
- // state info
- CreateTrigReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- // error info
- CreateTrigRef::ErrorCode m_lastError;
- CreateTrigRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // counters
- SignalCounter m_signalCounter;
- // ctor
- OpCreateTrigger() {
- memset(&m_request, 0, sizeof(m_request));
- m_coordinatorRef = 0;
- m_requestType = CreateTrigReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_lastError = CreateTrigRef::NoError;
- m_errorCode = CreateTrigRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void save(const CreateTrigReq* req) {
- m_request = *req;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasLastError() {
- return m_lastError != CreateTrigRef::NoError;
- }
- bool hasError() {
- return m_errorCode != CreateTrigRef::NoError;
- }
- void setError(const CreateTrigRef* ref) {
- m_lastError = CreateTrigRef::NoError;
- if (ref != 0) {
- m_lastError = ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const AlterTrigRef* ref) {
- m_lastError = CreateTrigRef::NoError;
- if (ref != 0) {
- m_lastError = (CreateTrigRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- };
- typedef Ptr<OpCreateTrigger> OpCreateTriggerPtr;
-
- /**
- * Operation record for drop trigger.
- */
- struct OpDropTrigger : OpRecordCommon {
- // original request
- DropTrigReq m_request;
- // coordinator DICT
- Uint32 m_coordinatorRef;
- bool m_isMaster;
- // state info
- DropTrigReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- // error info
- DropTrigRef::ErrorCode m_lastError;
- DropTrigRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // counters
- SignalCounter m_signalCounter;
- // ctor
- OpDropTrigger() {
- memset(&m_request, 0, sizeof(m_request));
- m_coordinatorRef = 0;
- m_requestType = DropTrigReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_lastError = DropTrigRef::NoError;
- m_errorCode = DropTrigRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void save(const DropTrigReq* req) {
- m_request = *req;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasLastError() {
- return m_lastError != DropTrigRef::NoError;
- }
- bool hasError() {
- return m_errorCode != DropTrigRef::NoError;
- }
- void setError(const DropTrigRef* ref) {
- m_lastError = DropTrigRef::NoError;
- if (ref != 0) {
- m_lastError = ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const AlterTrigRef* ref) {
- m_lastError = DropTrigRef::NoError;
- if (ref != 0) {
- m_lastError = (DropTrigRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- };
- typedef Ptr<OpDropTrigger> OpDropTriggerPtr;
-
- /**
- * Operation record for alter trigger.
- */
- struct OpAlterTrigger : OpRecordCommon {
- // original request
- AlterTrigReq m_request;
- // nodes participating in operation
- NdbNodeBitmask m_nodes;
- // coordinator DICT
- Uint32 m_coordinatorRef;
- bool m_isMaster;
- // state info
- AlterTrigReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- // error info
- AlterTrigRef::ErrorCode m_lastError;
- AlterTrigRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // counters
- SignalCounter m_signalCounter;
- // ctor
- OpAlterTrigger() {
- memset(&m_request, 0, sizeof(m_request));
- m_coordinatorRef = 0;
- m_requestType = AlterTrigReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_lastError = AlterTrigRef::NoError;
- m_errorCode = AlterTrigRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void save(const AlterTrigReq* req) {
- m_request = *req;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasLastError() {
- return m_lastError != AlterTrigRef::NoError;
- }
- bool hasError() {
- return m_errorCode != AlterTrigRef::NoError;
- }
- void setError(const AlterTrigRef* ref) {
- m_lastError = AlterTrigRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterTrigRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const CreateTrigRef* ref) {
- m_lastError = AlterTrigRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterTrigRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- void setError(const DropTrigRef* ref) {
- m_lastError = AlterTrigRef::NoError;
- if (ref != 0) {
- m_lastError = (AlterTrigRef::ErrorCode)ref->getErrorCode();
- if (! hasError()) {
- m_errorCode = m_lastError;
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- }
- };
- typedef Ptr<OpAlterTrigger> OpAlterTriggerPtr;
-
-public:
- struct SchemaOp : OpRecordCommon {
-
- Uint32 m_clientRef; // API (for take-over)
- Uint32 m_clientData;// API
-
- Uint32 m_senderRef; //
- Uint32 m_senderData;// transaction key value
-
- Uint32 m_errorCode;
-
- Uint32 m_obj_id;
- Uint32 m_obj_type;
- Uint32 m_obj_version;
- Uint32 m_obj_ptr_i;
- Uint32 m_vt_index;
- Callback m_callback;
- };
- typedef Ptr<SchemaOp> SchemaOpPtr;
-
- struct SchemaTransaction : OpRecordCommon {
- Uint32 m_senderRef; // API
- Uint32 m_senderData;// API
-
- Callback m_callback;
- SafeCounterHandle m_counter;
- NodeBitmask m_nodes;
-
- Uint32 m_errorCode;
- SchemaTransaction() {}
- void setErrorCode(Uint32 c){ if(m_errorCode == 0) m_errorCode = c;}
-
- /**
- * This should contain "lists" with operations
- */
- struct {
- Uint32 m_key; // Operation key
- Uint32 m_vt_index; // Operation type
- Uint32 m_obj_id;
- DictObjOp::State m_state;
- } m_op;
- };
-private:
-
- struct OpCreateObj : public SchemaOp {
- Uint32 m_gci;
- Uint32 m_obj_info_ptr_i;
- Uint32 m_restart;
- };
- typedef Ptr<OpCreateObj> CreateObjRecordPtr;
-
- struct OpDropObj : public SchemaOp
- {
- };
- typedef Ptr<OpDropObj> DropObjRecordPtr;
-
- /**
- * Only used at coordinator/master
- */
- // Common operation record pool
-public:
- STATIC_CONST( opCreateTableSize = sizeof(CreateTableRecord) );
- STATIC_CONST( opDropTableSize = sizeof(DropTableRecord) );
- STATIC_CONST( opCreateIndexSize = sizeof(OpCreateIndex) );
- 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) );
- STATIC_CONST( opCreateObjSize = sizeof(OpCreateObj) );
-private:
-#define PTR_ALIGN(n) ((((n)+sizeof(void*)-1)>>2)&~((sizeof(void*)-1)>>2))
- union OpRecordUnion {
- Uint32 u_opCreateTable [PTR_ALIGN(opCreateTableSize)];
- 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)];
- Uint32 u_opDropTrigger [PTR_ALIGN(opDropTriggerSize)];
- Uint32 u_opAlterTrigger [PTR_ALIGN(opAlterTriggerSize)];
- Uint32 u_opCreateObj [PTR_ALIGN(opCreateObjSize)];
- Uint32 nextPool;
- };
- ArrayPool<OpRecordUnion> c_opRecordPool;
-
- // Operation records
- KeyTable2<CreateTableRecord, OpRecordUnion> c_opCreateTable;
- KeyTable2<DropTableRecord, OpRecordUnion> c_opDropTable;
- KeyTable2<OpCreateIndex, OpRecordUnion> c_opCreateIndex;
- KeyTable2<OpDropIndex, OpRecordUnion> c_opDropIndex;
- KeyTable2<OpAlterIndex, OpRecordUnion> c_opAlterIndex;
- KeyTable2<OpBuildIndex, OpRecordUnion> c_opBuildIndex;
- KeyTable2C<OpCreateEvent, OpRecordUnion> c_opCreateEvent;
- KeyTable2C<OpSubEvent, OpRecordUnion> c_opSubEvent;
- KeyTable2C<OpDropEvent, OpRecordUnion> c_opDropEvent;
- KeyTable2C<OpSignalUtil, OpRecordUnion> c_opSignalUtil;
- KeyTable2<OpCreateTrigger, OpRecordUnion> c_opCreateTrigger;
- KeyTable2<OpDropTrigger, OpRecordUnion> c_opDropTrigger;
- KeyTable2<OpAlterTrigger, OpRecordUnion> c_opAlterTrigger;
- KeyTable2<SchemaOp, OpRecordUnion> c_schemaOp;
- KeyTable2<SchemaTransaction, OpRecordUnion> c_Trans;
- KeyTable2Ref<OpCreateObj, SchemaOp, OpRecordUnion> c_opCreateObj;
- KeyTable2Ref<OpDropObj, SchemaOp, OpRecordUnion> c_opDropObj;
-
- // 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);
-
- // check if any schema op exists (conflicting with dict lock)
- bool hasDictLockSchemaOp();
-
- 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
-
- /* ------------------------------------------------------------ */
- // Start/Restart Handling
- /* ------------------------------------------------------------ */
- void sendSTTORRY(Signal* signal);
- void sendNDB_STTORRY(Signal* signal);
- void initSchemaFile(Signal* signal);
-
- /* ------------------------------------------------------------ */
- // Drop Table Handling
- /* ------------------------------------------------------------ */
- void releaseTableObject(Uint32 tableId, bool removeFromHash = true);
-
- /* ------------------------------------------------------------ */
- // General Stuff
- /* ------------------------------------------------------------ */
- Uint32 getFreeObjId(Uint32 minId);
- Uint32 getFreeTableRecord(Uint32 primaryTableId);
- Uint32 getFreeTriggerRecord();
- bool getNewAttributeRecord(TableRecordPtr tablePtr,
- AttributeRecordPtr & attrPtr);
- void packTableIntoPages(Signal* signal);
- void packTableIntoPages(SimpleProperties::Writer &, TableRecordPtr, Signal* =0);
- void packFilegroupIntoPages(SimpleProperties::Writer &,
- FilegroupPtr,
- const Uint32 undo_free_hi,
- const Uint32 undo_free_lo);
- void packFileIntoPages(SimpleProperties::Writer &, FilePtr, const Uint32);
-
- void sendGET_TABINFOREQ(Signal* signal,
- Uint32 tableId);
- void sendTC_SCHVERREQ(Signal* signal,
- Uint32 tableId,
- BlockReference tcRef);
-
- /* ------------------------------------------------------------ */
- // System Restart Handling
- /* ------------------------------------------------------------ */
- void initSendSchemaData(Signal* signal);
- void sendSchemaData(Signal* signal);
- Uint32 sendSCHEMA_INFO(Signal* signal, Uint32 nodeId, Uint32* pagePointer);
- void checkSchemaStatus(Signal* signal);
- void sendDIHSTARTTAB_REQ(Signal* signal);
-
- /* ------------------------------------------------------------ */
- // Receive Table Handling
- /* ------------------------------------------------------------ */
- void handleTabInfoInit(SimpleProperties::Reader &,
- ParseDictTabInfoRecord *,
- bool checkExist = true);
- void handleTabInfo(SimpleProperties::Reader & it, ParseDictTabInfoRecord *,
- DictTabInfo::Table & tableDesc);
-
- void handleAddTableFailure(Signal* signal,
- Uint32 failureLine,
- Uint32 tableId);
- bool verifyTableCorrect(Signal* signal, Uint32 tableId);
-
- /* ------------------------------------------------------------ */
- // Add Table Handling
- /* ------------------------------------------------------------ */
- void releaseCreateTableOp(Signal* signal, CreateTableRecordPtr createTabPtr);
-
- /* ------------------------------------------------------------ */
- // Add Fragment Handling
- /* ------------------------------------------------------------ */
- void sendLQHADDATTRREQ(Signal*, CreateTableRecordPtr, Uint32 attributePtrI);
-
- /* ------------------------------------------------------------ */
- // Read/Write Schema and Table files
- /* ------------------------------------------------------------ */
- void updateSchemaState(Signal* signal, Uint32 tableId,
- SchemaFile::TableEntry*, Callback*,
- bool savetodisk = 1);
- void startWriteSchemaFile(Signal* signal);
- void openSchemaFile(Signal* signal,
- Uint32 fileNo,
- Uint32 fsPtr,
- bool writeFlag,
- bool newFile);
- void writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
- void writeSchemaConf(Signal* signal,
- FsConnectRecordPtr fsPtr);
- void closeFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
- void closeWriteSchemaConf(Signal* signal,
- FsConnectRecordPtr fsPtr);
- void initSchemaFile_conf(Signal* signal, Uint32 i, Uint32 returnCode);
-
- void writeTableFile(Signal* signal, Uint32 tableId,
- SegmentedSectionPtr tabInfo, Callback*);
- void startWriteTableFile(Signal* signal, Uint32 tableId);
- void openTableFile(Signal* signal,
- Uint32 fileNo,
- Uint32 fsPtr,
- Uint32 tableId,
- bool writeFlag);
- void writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
- void writeTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr);
- void closeWriteTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr);
-
- void startReadTableFile(Signal* signal, Uint32 tableId);
- void openReadTableRef(Signal* signal,
- FsConnectRecordPtr fsPtr);
- void readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
- void readTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr);
- void readTableRef(Signal* signal,
- FsConnectRecordPtr fsPtr);
- void closeReadTableConf(Signal* signal,
- FsConnectRecordPtr fsPtr);
-
- void startReadSchemaFile(Signal* signal);
- void openReadSchemaRef(Signal* signal,
- FsConnectRecordPtr fsPtr);
- void readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
- void readSchemaConf(Signal* signal, FsConnectRecordPtr fsPtr);
- void readSchemaRef(Signal* signal, FsConnectRecordPtr fsPtr);
- void closeReadSchemaConf(Signal* signal,
- FsConnectRecordPtr fsPtr);
- bool convertSchemaFileTo_5_0_6(XSchemaFile*);
-
- /* ------------------------------------------------------------ */
- // Get table definitions
- /* ------------------------------------------------------------ */
- void sendGET_TABINFOREF(Signal* signal,
- GetTabInfoReq*,
- GetTabInfoRef::ErrorCode errorCode);
-
- void sendGET_TABLEID_REF(Signal* signal,
- GetTableIdReq * req,
- GetTableIdRef::ErrorCode errorCode);
-
- void sendGetTabResponse(Signal* signal);
-
- /* ------------------------------------------------------------ */
- // Indexes and triggers
- /* ------------------------------------------------------------ */
-
- // reactivate and rebuild indexes on start up
- void activateIndexes(Signal* signal, Uint32 i);
- void rebuildIndexes(Signal* signal, Uint32 i);
-
- // create index
- void createIndex_recvReply(Signal* signal, const CreateIndxConf* conf,
- const CreateIndxRef* ref);
- void createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_fromCreateTable(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_toAlterIndex(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_fromAlterIndex(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_slaveCommit(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_slaveAbort(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_sendSlaveReq(Signal* signal, OpCreateIndexPtr opPtr);
- void createIndex_sendReply(Signal* signal, OpCreateIndexPtr opPtr, bool);
- // drop index
- void dropIndex_recvReply(Signal* signal, const DropIndxConf* conf,
- const DropIndxRef* ref);
- void dropIndex_slavePrepare(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_toAlterIndex(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_fromAlterIndex(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_toDropTable(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_fromDropTable(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_slaveCommit(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_slaveAbort(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_sendSlaveReq(Signal* signal, OpDropIndexPtr opPtr);
- void dropIndex_sendReply(Signal* signal, OpDropIndexPtr opPtr, bool);
- // alter index
- void alterIndex_recvReply(Signal* signal, const AlterIndxConf* conf,
- const AlterIndxRef* ref);
- void alterIndex_slavePrepare(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_toCreateTc(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_fromCreateTc(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_toDropTc(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_fromDropTc(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_toCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_fromCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_toDropTrigger(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_fromDropTrigger(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_toBuildIndex(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_fromBuildIndex(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_slaveCommit(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_slaveAbort(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_sendSlaveReq(Signal* signal, OpAlterIndexPtr opPtr);
- void alterIndex_sendReply(Signal* signal, OpAlterIndexPtr opPtr, bool);
- // build index
- void buildIndex_recvReply(Signal* signal, const BuildIndxConf* conf,
- const BuildIndxRef* ref);
- void buildIndex_toCreateConstr(Signal* signal, OpBuildIndexPtr opPtr);
- void buildIndex_fromCreateConstr(Signal* signal, OpBuildIndexPtr opPtr);
- void buildIndex_buildTrix(Signal* signal, OpBuildIndexPtr opPtr);
- void buildIndex_toDropConstr(Signal* signal, OpBuildIndexPtr opPtr);
- void buildIndex_fromDropConstr(Signal* signal, OpBuildIndexPtr opPtr);
- void buildIndex_toOnline(Signal* signal, OpBuildIndexPtr opPtr);
- void buildIndex_fromOnline(Signal* signal, OpBuildIndexPtr opPtr);
- 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);
- void createTrigger_slavePrepare(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_masterSeize(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_slaveCreate(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_toAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_fromAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_slaveCommit(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_slaveAbort(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_sendSlaveReq(Signal* signal, OpCreateTriggerPtr opPtr);
- void createTrigger_sendReply(Signal* signal, OpCreateTriggerPtr opPtr, bool);
- // drop trigger
- void dropTrigger_recvReply(Signal* signal, const DropTrigConf* conf,
- const DropTrigRef* ref);
- void dropTrigger_slavePrepare(Signal* signal, OpDropTriggerPtr opPtr);
- void dropTrigger_toAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr);
- void dropTrigger_fromAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr);
- void dropTrigger_slaveCommit(Signal* signal, OpDropTriggerPtr opPtr);
- void dropTrigger_slaveAbort(Signal* signal, OpDropTriggerPtr opPtr);
- void dropTrigger_sendSlaveReq(Signal* signal, OpDropTriggerPtr opPtr);
- void dropTrigger_sendReply(Signal* signal, OpDropTriggerPtr opPtr, bool);
- // alter trigger
- void alterTrigger_recvReply(Signal* signal, const AlterTrigConf* conf,
- const AlterTrigRef* ref);
- void alterTrigger_slavePrepare(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_toCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_fromCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_fromDropLocal(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_slaveCommit(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_slaveAbort(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_sendSlaveReq(Signal* signal, OpAlterTriggerPtr opPtr);
- void alterTrigger_sendReply(Signal* signal, OpAlterTriggerPtr opPtr, bool);
- // support
- void getTableKeyList(TableRecordPtr,
- Id_array<MAX_ATTRIBUTES_IN_INDEX+1>& list);
- void getIndexAttr(TableRecordPtr indexPtr, Uint32 itAttr, Uint32* id);
- void getIndexAttrList(TableRecordPtr indexPtr, AttributeList& list);
- void getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask);
-
- /* ------------------------------------------------------------ */
- // Initialisation
- /* ------------------------------------------------------------ */
- void initCommonData();
- void initRecords();
- void initConnectRecord();
- void initRetrieveRecord(Signal*, Uint32, Uint32 returnCode);
- void initSchemaRecord();
- void initRestartRecord();
- void initSendSchemaRecord();
- void initReadTableRecord();
- void initWriteTableRecord();
- void initReadSchemaRecord();
- void initWriteSchemaRecord();
-
- void initNodeRecords();
- void initTableRecords();
- void initialiseTableRecord(TableRecordPtr tablePtr);
- void initTriggerRecords();
- void initialiseTriggerRecord(TriggerRecordPtr triggerPtr);
- void initPageRecords();
-
- Uint32 getFsConnRecord();
-
- bool getIsFailed(Uint32 nodeId) const;
-
- void dropTable_backup_mutex_locked(Signal* signal, Uint32, Uint32);
- void dropTableRef(Signal * signal, DropTableReq *, DropTableRef::ErrorCode);
- void printTables(); // For debugging only
- int handleAlterTab(AlterTabReq * req,
- CreateTableRecord * regAlterTabPtr,
- TableRecordPtr origTablePtr,
- TableRecordPtr newTablePtr);
- void revertAlterTable(Signal * signal,
- Uint32 changeMask,
- Uint32 tableId,
- CreateTableRecord * regAlterTabPtr);
- void alterTable_backup_mutex_locked(Signal* signal, Uint32, Uint32);
- void alterTableRef(Signal * signal,
- AlterTableReq *, AlterTableRef::ErrorCode,
- ParseDictTabInfoRecord* parseRecord = NULL);
- void alterTabRef(Signal * signal,
- AlterTabReq *, AlterTableRef::ErrorCode,
- ParseDictTabInfoRecord* parseRecord = NULL);
- void alterTab_writeSchemaConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void alterTab_writeTableConf(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
-
- void prepDropTab_nextStep(Signal* signal, DropTableRecordPtr);
- void prepDropTab_complete(Signal* signal, DropTableRecordPtr);
- void prepDropTab_writeSchemaConf(Signal* signal, Uint32 dropTabPtrI, Uint32);
-
- void dropTab_localDROP_TAB_CONF(Signal* signal);
- void dropTab_nextStep(Signal* signal, DropTableRecordPtr);
- void dropTab_complete(Signal* signal, Uint32 dropTabPtrI, Uint32);
- void dropTab_writeSchemaConf(Signal* signal, Uint32 dropTabPtrI, Uint32);
-
- void createTab_prepare(Signal* signal, CreateTabReq * req);
- void createTab_writeSchemaConf1(Signal* signal, Uint32 callback, Uint32);
- void createTab_writeTableConf(Signal* signal, Uint32 callbackData, Uint32);
- void createTab_dih(Signal*, CreateTableRecordPtr,
- SegmentedSectionPtr, Callback*);
- void createTab_dihComplete(Signal* signal, Uint32 callbackData, Uint32);
-
- void createTab_startLcpMutex_locked(Signal* signal, Uint32, Uint32);
- void createTab_startLcpMutex_unlocked(Signal* signal, Uint32, Uint32);
-
- void createTab_commit(Signal* signal, CreateTabReq * req);
- void createTab_writeSchemaConf2(Signal* signal, Uint32 callbackData, Uint32);
- void createTab_alterComplete(Signal*, Uint32 callbackData, Uint32);
-
- void createTab_drop(Signal* signal, CreateTabReq * req);
- void createTab_dropComplete(Signal* signal, Uint32 callbackData, Uint32);
-
- void createTab_reply(Signal* signal, CreateTableRecordPtr, Uint32 nodeId);
- void alterTab_activate(Signal*, CreateTableRecordPtr, Callback*);
-
- void restartCreateTab(Signal*, Uint32,
- const SchemaFile::TableEntry *,
- const SchemaFile::TableEntry *, bool);
- void restartCreateTab_readTableConf(Signal* signal, Uint32 callback, Uint32);
- void restartCreateTab_writeTableConf(Signal* signal, Uint32 callback, Uint32);
- void restartCreateTab_dihComplete(Signal* signal, Uint32 callback, Uint32);
- void restartCreateTab_activateComplete(Signal*, Uint32 callback, Uint32);
-
- void restartDropTab(Signal* signal, Uint32 tableId,
- const SchemaFile::TableEntry *,
- const SchemaFile::TableEntry *);
- void restartDropTab_complete(Signal*, Uint32 callback, Uint32);
-
- void restartDropObj(Signal*, Uint32, const SchemaFile::TableEntry *);
- void restartDropObj_prepare_start_done(Signal*, Uint32, Uint32);
- void restartDropObj_prepare_complete_done(Signal*, Uint32, Uint32);
- void restartDropObj_commit_start_done(Signal*, Uint32, Uint32);
- void restartDropObj_commit_complete_done(Signal*, Uint32, Uint32);
-
- void restart_checkSchemaStatusComplete(Signal*, Uint32 callback, Uint32);
- void restart_writeSchemaConf(Signal*, Uint32 callbackData, Uint32);
- void masterRestart_checkSchemaStatusComplete(Signal*, Uint32, Uint32);
-
- void sendSchemaComplete(Signal*, Uint32 callbackData, Uint32);
-
- void execCREATE_OBJ_REQ(Signal* signal);
- void execCREATE_OBJ_REF(Signal* signal);
- void execCREATE_OBJ_CONF(Signal* signal);
-
- void createObj_prepare_start_done(Signal* signal, Uint32 callback, Uint32);
- void createObj_writeSchemaConf1(Signal* signal, Uint32 callback, Uint32);
- void createObj_writeObjConf(Signal* signal, Uint32 callbackData, Uint32);
- void createObj_prepare_complete_done(Signal*, Uint32 callbackData, Uint32);
- void createObj_commit_start_done(Signal* signal, Uint32 callback, Uint32);
- void createObj_writeSchemaConf2(Signal* signal, Uint32 callbackData, Uint32);
- void createObj_commit_complete_done(Signal*, Uint32 callbackData, Uint32);
- void createObj_abort(Signal*, struct CreateObjReq*);
- void createObj_abort_start_done(Signal*, Uint32 callbackData, Uint32);
- void createObj_abort_writeSchemaConf(Signal*, Uint32 callbackData, Uint32);
- void createObj_abort_complete_done(Signal*, Uint32 callbackData, Uint32);
-
- void schemaOp_reply(Signal* signal, SchemaTransaction *, Uint32);
- void trans_commit_start_done(Signal*, Uint32 callbackData, Uint32);
- void trans_commit_complete_done(Signal*, Uint32 callbackData, Uint32);
- void trans_abort_start_done(Signal*, Uint32 callbackData, Uint32);
- void trans_abort_complete_done(Signal*, Uint32 callbackData, Uint32);
-
- void execDROP_OBJ_REQ(Signal* signal);
- void execDROP_OBJ_REF(Signal* signal);
- void execDROP_OBJ_CONF(Signal* signal);
-
- void dropObj_prepare_start_done(Signal* signal, Uint32 callback, Uint32);
- void dropObj_prepare_writeSchemaConf(Signal*, Uint32 callback, Uint32);
- void dropObj_prepare_complete_done(Signal*, Uint32 callbackData, Uint32);
- void dropObj_commit_start_done(Signal*, Uint32 callbackData, Uint32);
- void dropObj_commit_writeSchemaConf(Signal*, Uint32 callback, Uint32);
- void dropObj_commit_complete_done(Signal*, Uint32 callbackData, Uint32);
- void dropObj_abort_start_done(Signal*, Uint32 callbackData, Uint32);
- void dropObj_abort_writeSchemaConf(Signal*, Uint32 callback, Uint32);
- void dropObj_abort_complete_done(Signal*, Uint32 callbackData, Uint32);
-
- void restartCreateObj(Signal*, Uint32,
- const SchemaFile::TableEntry *,
- const SchemaFile::TableEntry *, bool);
- void restartCreateObj_readConf(Signal*, Uint32, Uint32);
- void restartCreateObj_getTabInfoConf(Signal*);
- void restartCreateObj_prepare_start_done(Signal*, Uint32, Uint32);
- void restartCreateObj_write_complete(Signal*, Uint32, Uint32);
- void restartCreateObj_prepare_complete_done(Signal*, Uint32, Uint32);
- void restartCreateObj_commit_start_done(Signal*, Uint32, Uint32);
- void restartCreateObj_commit_complete_done(Signal*, Uint32, Uint32);
-
- void execDICT_COMMIT_REQ(Signal*);
- void execDICT_COMMIT_REF(Signal*);
- void execDICT_COMMIT_CONF(Signal*);
-
- void execDICT_ABORT_REQ(Signal*);
- void execDICT_ABORT_REF(Signal*);
- void execDICT_ABORT_CONF(Signal*);
-
-public:
- void createObj_commit(Signal*, struct SchemaOp*);
- void createObj_abort(Signal*, struct SchemaOp*);
-
- void create_fg_prepare_start(Signal* signal, SchemaOp*);
- void create_fg_prepare_complete(Signal* signal, SchemaOp*);
- void create_fg_abort_start(Signal* signal, SchemaOp*);
- void create_fg_abort_complete(Signal* signal, SchemaOp*);
-
- void create_file_prepare_start(Signal* signal, SchemaOp*);
- void create_file_prepare_complete(Signal* signal, SchemaOp*);
- void create_file_commit_start(Signal* signal, SchemaOp*);
- void create_file_abort_start(Signal* signal, SchemaOp*);
- void create_file_abort_complete(Signal* signal, SchemaOp*);
-
- void dropObj_commit(Signal*, struct SchemaOp*);
- void dropObj_abort(Signal*, struct SchemaOp*);
- void drop_file_prepare_start(Signal* signal, SchemaOp*);
- void drop_file_commit_start(Signal* signal, SchemaOp*);
- void drop_file_commit_complete(Signal* signal, SchemaOp*);
- void drop_file_abort_start(Signal* signal, SchemaOp*);
- void send_drop_file(Signal*, SchemaOp*, DropFileImplReq::RequestInfo);
-
- void drop_fg_prepare_start(Signal* signal, SchemaOp*);
- void drop_fg_commit_start(Signal* signal, SchemaOp*);
- void drop_fg_commit_complete(Signal* signal, SchemaOp*);
- void drop_fg_abort_start(Signal* signal, SchemaOp*);
- void send_drop_fg(Signal*, SchemaOp*, DropFilegroupImplReq::RequestInfo);
-
- void drop_undofile_prepare_start(Signal* signal, SchemaOp*);
- void drop_undofile_commit_complete(Signal* signal, SchemaOp*);
-
- int checkSingleUserMode(Uint32 senderRef);
-};
-
-inline bool
-Dbdict::TableRecord::isTable() const
-{
- return DictTabInfo::isTable(tableType);
-}
-
-inline bool
-Dbdict::TableRecord::isIndex() const
-{
- return DictTabInfo::isIndex(tableType);
-}
-
-inline bool
-Dbdict::TableRecord::isUniqueIndex() const
-{
- return DictTabInfo::isUniqueIndex(tableType);
-}
-
-inline bool
-Dbdict::TableRecord::isNonUniqueIndex() const
-{
- return DictTabInfo::isNonUniqueIndex(tableType);
-}
-
-inline bool
-Dbdict::TableRecord::isHashIndex() const
-{
- return DictTabInfo::isHashIndex(tableType);
-}
-
-inline bool
-Dbdict::TableRecord::isOrderedIndex() const
-{
- return DictTabInfo::isOrderedIndex(tableType);
-}
-
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.txt b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.txt
deleted file mode 100644
index 8d4267a1c42..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-
-Event creation
-
-USER DICT(Master) UTIL SUMA
-================================================================================
-CREATE_EVENT_REQ::create
--------------------------->
- - Get ID
- CREATE_SUBID
- ----------------------------------------------->
- <-----------------------------------------------
- - insert into system table
- UTIL_PREPARE::insert
- ------------------------>
- <------------------------
- UTIL_EXECUTE
- ------------------------>
- <------------------------
-CREATE_EVENT_CONF
-<--------------------------
-
-
-Event dropping
-
-USER DICT(Master) UTIL SUMA
-================================================================================
-DROP_EVENT_REQ
--------------------------->
- - remove from system table
- UTIL_PREPARE::delete
- ------------------------>
- <------------------------
- UTIL_EXECUTE
- ------------------------>
- <------------------------
-DROP_EVENT_CONF
-<--------------------------
-
-
-
-create NdbEventOperation
-
-USER DICT(Master) (Slaves) UTIL
-=======================================================================
-CREATE_EVENT_REQ::get
--------------------------->
- - read from system table
- UTIL_PREPARE::read
- ---------------------------------------->
- <----------------------------------------
- UTIL_EXECUTE
- ---------------------------------------->
- <----------------------------------------
- SUMA
- CREATE_EVENT_REQ::after_get ======
- ---------------------->
- SUB_CREATE
- ------------------>
- <------------------
- SUB_SYNC
- ------------------>
- <------------------
- CREATE_EVENT_CONF
- <----------------------
-CREATE_EVENT_CONF
-<-------------------------
-
-
-
-USER DICT(Master) (Slaves) SUMA
-=======================================================================
-SUB_START_REQ
--------------------------->
- SUB_START_REQ
- ---------------------->
- SUB_START
- ------------------>
- <------------------
- SUB_START_CONF
- <----------------------
-SUB_START_CONF
-<-------------------------
-
-
-SUB_STOP analogous to SUB_STOP
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbdict/DictLock.txt b/storage/ndb/src/kernel/blocks/dbdict/DictLock.txt
deleted file mode 100644
index 72e23ed15a5..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/DictLock.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-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/storage/ndb/src/kernel/blocks/dbdict/DropTable.txt b/storage/ndb/src/kernel/blocks/dbdict/DropTable.txt
deleted file mode 100644
index 8d364d15c57..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/DropTable.txt
+++ /dev/null
@@ -1,140 +0,0 @@
-DROP TABLE DESCRIPTION
-----------------------
-
-Drop table is controlled by DICT.
-
-Drop table is used in the following cases in some sort.
- - Drop Table
- - Abort Add Table
- - Drop table in node restart
- - Drop table in system restart
-
-Sequence of Drop Table:
------------------------
-
-1) PREP_DROP_TAB_REQ -> all DICT
- Update schema files on disk
- Table status = DROPPING
-
-2) Controlling DICT only
- Report Table Dropped secured but not yet completed.
-
------- PREP DROP
-
-4) PREP_DROP_TAB_REQ -> all LQHs
-
-5) PREP_DROP_TAB_REQ -> all TCs
-
-6) PREP_DROP_TAB_REQ -> all DIHs
-
-
---- LQH::PREP_DROP_TAB_REQ
-
-*) Mark the table so that no new operations will start
-*) Mark all fragments so that new LCP_FRAG_ORD gets replied directly
- w.o actually checkpointing the fragment
-2) Start waiting for completion
-3) Reply PREP_DROP_TAB_CONF
-
-- After this LQH accepts WAIT_DROP_TAB_REQ
-
---- TC::PREP_DROP_TAB_REQ
-
-1) Mark the table so that no new transactions will start on the table
-2) Send WAIT_DROP_TAB_REQ -> all connected LQH's
-3) Wait for CONF (including NF-handling) from LQH:s
-4) Reply PREP_DROP_TAB_CONF
-
---- DIH::PREP_DROP_TAB_REQ
-
-1) Mark the table so that no new LCP will start on the table
-2) If master (unlink any queued LCP_FRAG_ORD)
-3) Send WAIT_DROP_TAB_REQ -> all connected LQH's
-4) Wait for CONF (including NF-handling) from LQH:s
-5) Reply PREP_DROP_TAB_CONF
-
---- LQH::WAIT_DROP_TAB_REQ
-
-1) Wait for running operations
- Wait for running LCP
-
-2) Reply
-
------- PREP_DROP
-
-7) DROP_TAB_REQ -> all DICT's
- *) DROP_TAB_REQ -> TC
- *) DROP_TAB_REQ -> ACC
- *) DROP_TAB_REQ -> TUP
- *) DROP_TAB_REQ -> DIH
- *) DROP_TAB_REQ -> LQH
- *) Update schema files on disk DROPPED
-
-8) DICT_SCHEMAREQ -> all DICT
- Table status = DROPPED
-
----------------------------------
-
-Sequence of Drop table in node/system restart
----------------------------------------------
-
-In both node and system restart the node receives the schema information from
-the master. If the table is in a state where it needs to complete the drop
-table activity then DBACC, DBTUP, DBDIH, DBDICT is contacted to drop all files
-related to the table. After this the schema information is updated with the new
-state. Since all nodes receive the same schema information there is no risk of
-different behaviour in the various NDB nodes.
-
-API Requirements for Drop Table
--------------------------------
-Definition:
-
- Two tables are NOT the same if they were created with two create
- tables at different points in time, even if the two create tables
- had exactly the same definition.
-
-Requirements:
-
-1. Each operation in a transaction refering to a table (by name or by id)
- should operate on the same table. (This is probably necessary.)
-
-2. Each operation in a transaction refering to a table (by name or by
- id) should operate on the same table as were defined at the
- startTransaction timepoint. (This is not strictly necessary for
- API consistency.)
-
- Example 1:
-
- startTransaction()
-
- drop("TableName1")
- create("TableName1")
-
- getNdbOperation("TableName1")
-
- execute(commit)
-
- - If both requirements 1 and 2 are fulfilled, then this should lead
- to "Error: Invalid Schema Version" or similar error
-
- - If only requirement 1 is fulfilled, then this may be executed
- without any errors.
-
-
- Example 2:
-
- startTransaction()
-
- getNdbOperation("TableName1")
- execute(NoCommit)
-
- drop("TableName1")
- create("TableName1")
-
- getNdbOperation("TableName1")
-
- execute(commit)
-
- - This should always lead to "Error: Invalid Schema Version" or
- similar error.
-
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Event.txt b/storage/ndb/src/kernel/blocks/dbdict/Event.txt
deleted file mode 100644
index 553c915d9c5..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/Event.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-
-Event creation
-
-USER DICT(Master) UTIL SUMA
-================================================================================
-CREATE_EVENT_REQ::create
--------------------------->
- - Get ID
- CREATE_SUBID
- ----------------------------------------------->
- <-----------------------------------------------
- - insert into system table
- UTIL_PREPARE::insert
- ------------------------>
- <------------------------
- UTIL_EXECUTE
- ------------------------>
- <------------------------
-CREATE_EVENT_CONF
-<--------------------------
-
-
-Event dropping
-
-USER DICT(Master) (Slaves) UTIL SUMA
-================================================================================
-DROP_EVENT_REQ
--------------------------->
- - read from system table
- UTIL_PREPARE::read
- ------------------------------------>
- <------------------------------------
- UTIL_EXECUTE
- ------------------------------------>
- <------------------------------------
- SUB_REMOVE_REQ
- -------------------->
- SUB_REMOVE
- ------------------------------>
- <------------------------------
- SUB_REMOVE_CONF
- <--------------------
- - remove from system table
- UTIL_PREPARE::delete
- ------------------------------------>
- <------------------------------------
- UTIL_EXECUTE
- ------------------------------------>
- <------------------------------------
-DROP_EVENT_CONF
-<--------------------------
-
-
-
-create NdbEventOperation
-
-USER DICT(Master) (Slaves) UTIL
-=======================================================================
-CREATE_EVENT_REQ::get
--------------------------->
- - read from system table
- UTIL_PREPARE::read
- ---------------------------------------->
- <----------------------------------------
- UTIL_EXECUTE
- ---------------------------------------->
- <----------------------------------------
- SUMA
- CREATE_EVENT_REQ::after_get ======
- ---------------------->
- SUB_CREATE
- ------------------>
- <------------------
- SUB_SYNC
- ------------------>
- <------------------
- CREATE_EVENT_CONF
- <----------------------
-CREATE_EVENT_CONF
-<-------------------------
-
-
-
-USER DICT(Master) (Slaves) SUMA
-=======================================================================
-SUB_START_REQ
--------------------------->
- SUB_START_REQ
- ---------------------->
- SUB_START
- ------------------>
- <------------------
- SUB_START_CONF
- <----------------------
-SUB_START_CONF
-<-------------------------
-
-
-SUB_STOP analogous to SUB_STOP
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Makefile.am b/storage/ndb/src/kernel/blocks/dbdict/Makefile.am
deleted file mode 100644
index 6b900369b10..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/Makefile.am
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2004-2005 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
-
-LDADD += \
- $(top_builddir)/storage/ndb/src/common/util/libgeneral.la \
- $(top_builddir)/storage/ndb/src/common/portlib/libportlib.la \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a
-
-ndbtools_PROGRAMS = ndb_print_schema_file
-ndb_print_schema_file_SOURCES = printSchemaFile.cpp
-ndb_print_schema_file_LDFLAGS = @ndb_bin_am_ldflags@ \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Master_AddTable.sfl b/storage/ndb/src/kernel/blocks/dbdict/Master_AddTable.sfl
deleted file mode 100644
index 69fbb973133..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/Master_AddTable.sfl
+++ /dev/null
@@ -1,765 +0,0 @@
-// Copyright (C) 2004 MySQL AB
-// Use is subject to license terms
-//
-// 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; version 2 of the License.
-//
-// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-// ---------------------------------------------------------------------------
-// This file contains a signal log trace for DBDICT at the master for a
-// create table. Another file contains the signal log for the participant
-// node. Master node is 2, participant node 4 and api node is 3.
-
-// ---------------------------------------------------------------------------
-// First arrives the table description in a number of DICTTABINFO signals.
-// These have a header of 5 words (see DictTabInfo.hpp for details) and
-// upto 20 words of property data per signal. The property data is packed
-// by the SimpleProperties class.
-// ---------------------------------------------------------------------------
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57069 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 0 "API", s.proc: 3, s.sigId: 940284 length: 25 trace: 0
- H'00010003 H'00047700 H'00000001 H'00000042 H'00000000 H'4e444250 H'524f5053
- H'00010000 H'00000000 H'1c0a1203 H'524f4c46 H'00020001 H'0000000a H'56504e5f
- H'55534552 H'53000000 H'0001000a H'0000004b H'000203e8 H'00000007 H'56504e5f
- H'49440000 H'000103ee H'00000001 H'000203e8
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57069 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 0 "API", s.proc: 3, s.sigId: 940284 length: 25 trace: 0
- H'00010003 H'00047700 H'00000001 H'00000042 H'00000014 H'00000007 H'56504e5f
- H'4e420000 H'000103ee H'00000001 H'000203e8 H'0000000d H'44495245 H'43544f52
- H'595f4e42 H'00000000 H'000103eb H'00000003 H'000103ed H'0000000a H'000103ec
- H'00000002 H'000203e8 H'00000010 H'4c415354
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57069 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 0 "API", s.proc: 3, s.sigId: 940284 length: 25 trace: 0
- H'00010003 H'00047700 H'00000001 H'00000042 H'00000028 H'5f43414c H'4c5f5041
- H'52545900 H'000103eb H'00000003 H'000103ed H'0000000a H'000103ec H'00000002
- H'000203e8 H'00000006 H'44455343 H'52000000 H'000103eb H'00000003 H'000103ed
- H'00000064 H'000103ec H'00000002 H'00010005
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57069 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 0 "API", s.proc: 3, s.sigId: 940284 length: 11 trace: 0
- H'00010003 H'00047700 H'00000001 H'00000042 H'0000003c H'00000002 H'00010006
- H'00000005 H'0001000c H'00000002 H'0000ffff
-
-// ---------------------------------------------------------------------------
-// Send DICT_SCHEMAREQ to all nodes including ourselves to write the state
-// ADD_STARTED in the schema file for the new table.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57069 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000000 H'00000000 H'00000001
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57069 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000000 H'00000000 H'00000001
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57069 gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57077 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000000 H'00000000 H'00000001
-
-// ---------------------------------------------------------------------------
-// Write both schema files with new state of table added.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57069 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050100
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57081 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57082 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 99
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57081 length: 8 trace: 0
- FilePointer: 99
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57090 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57091 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57090 length: 4 trace: 0
- FilePointer: 99
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57099 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57100 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57099 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050200
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57111 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57112 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 100
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57111 length: 8 trace: 0
- FilePointer: 100
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57123 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57124 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57123 length: 4 trace: 0
- FilePointer: 100
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57133 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 1 trace: 0
- H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57135 length: 1 trace: 0
- H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, s.sigId: 46718 length: 1 trace: 0
- H'00000004
-
-// ---------------------------------------------------------------------------
-// Pack Table description into pages in DICT using SimpleProperties class.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 3 trace: 0
- H'00000001 H'00000002 H'00000000
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57140 length: 3 trace: 0
- H'00000001 H'00000002 H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 2 trace: 0
- H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57141 length: 2 trace: 0
- H'00000002 H'00000002
-
-// ---------------------------------------------------------------------------
-// Send the table description over to the other NDB nodes.
-// A CONTINUEB is sent for each signal sent to avoid overloading the
-// transporters.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000000 H'4e444250 H'524f5053
- H'00002000 H'0000001c H'1c0a1203 H'524f4c46 H'00020001 H'0000000a H'56504e5f
- H'55534552 H'53000000 H'0001000a H'0000004b H'000203e8 H'00000007 H'56504e5f
- H'49440000 H'1cc03924 H'00000001 H'000203e8
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 2 trace: 0
- H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57142 length: 2 trace: 0
- H'00000002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000014 H'00000007 H'56504e5f
- H'4e420000 H'000103ee H'00000001 H'000203e8 H'0000000d H'44495245 H'43544f52
- H'595f4e42 H'00000000 H'000103eb H'00000003 H'524f4c46 H'00020001 H'0000000a
- H'56504e5f H'55534552 H'53000010 H'00010002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 2 trace: 0
- H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57143 length: 2 trace: 0
- H'00000002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000028 H'00000002 H'00010011
- H'00000003 H'00010003 H'00000001 H'00010005 H'00000002 H'00010006 H'00000005
- H'0001000a H'0000004b H'0001000c H'00000002 H'000203e8 H'00000007 H'56504e5f
- H'49440064 H'000103e9 H'00000000 H'000103ee
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 2 trace: 0
- H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57144 length: 2 trace: 0
- H'00000002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'0000003c H'00000001 H'000203e8
- H'00000007 H'56504e5f H'4e420002 H'000103e9 H'00000001 H'000103ee H'00000001
- H'000203e8 H'0000000d H'44495245 H'43544f52 H'595f4e42 H'00000000 H'000103e9
- H'00000002 H'000103eb H'00000003 H'000103ec
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 2 trace: 0
- H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57145 length: 2 trace: 0
- H'00000002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000050 H'00000002 H'000103ed
- H'0000000a H'000203e8 H'00000010 H'4c415354 H'5f43414c H'4c5f5041 H'52545900
- H'000103e9 H'00000003 H'000103eb H'00000003 H'000103ec H'00000002 H'000103ed
- H'0000000a H'000203e8 H'00000006 H'44455343
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 2 trace: 0
- H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57132 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57146 length: 2 trace: 0
- H'00000002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 15 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000064 H'52000000 H'000103e9
- H'00000004 H'000103eb H'00000003 H'000103ec H'00000002 H'000103ed H'00000064
- H'0000ffff
-
-// ---------------------------------------------------------------------------
-// In parallel with sending the table description to other nodes we will also
-// write the table description to our local file system.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57132 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'00000002 H'ffffffff H'00000001 H'010401ff
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57165 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57166 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 101
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57165 length: 8 trace: 0
- FilePointer: 101
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000000, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57177 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57178 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57177 length: 4 trace: 0
- FilePointer: 101
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57186 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57187 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57186 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'00000002 H'ffffffff H'00000001 H'010402ff
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57195 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57196 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 102
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57195 length: 8 trace: 0
- FilePointer: 102
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000000, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57204 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57205 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57204 length: 4 trace: 0
- FilePointer: 102
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57218 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57219 length: 1 trace: 0
- UserPointer: H'00000000
-
-// ---------------------------------------------------------------------------
-// Completed writing to our file system the table description.
-// ---------------------------------------------------------------------------
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57229 gsn: 24 "DICTTABCONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, s.sigId: 46803 length: 2 trace: 0
- H'00000002 H'00000004
-
-// ---------------------------------------------------------------------------
-// Also the participant have completed writing the table description to file.
-// ---------------------------------------------------------------------------
-
-// ---------------------------------------------------------------------------
-// Write the state UPDATE_PAGE_COUNT to schema file for the new table.
-// This also contains the number of pages used for the table description.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57229 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'00000000 H'00000002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57229 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'00000000 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57229 gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57234 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'00000000 H'00000002
-
-// ---------------------------------------------------------------------------
-// Write schema file to disk
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57229 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050100
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57238 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57239 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 103
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57238 length: 8 trace: 0
- FilePointer: 103
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57247 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57248 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57247 length: 4 trace: 0
- FilePointer: 103
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57257 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57258 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57257 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050200
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57267 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57268 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 104
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57267 length: 8 trace: 0
- FilePointer: 104
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57279 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57283 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57279 length: 4 trace: 0
- FilePointer: 104
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57290 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 57291 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57290 length: 1 trace: 0
- H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57290 gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57293 length: 1 trace: 0
- H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57299 gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, s.sigId: 46860 length: 1 trace: 0
- H'00000004
-
-// ---------------------------------------------------------------------------
-// All schema files in the system have been updated.
-// ---------------------------------------------------------------------------
-
-// ---------------------------------------------------------------------------
-// Now control is given to DIH for adding the fragments needed by this table.
-// We first seize a record in DIH and then we send the add table request with
-// the needed table parameters.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 246 "DBDIH", r.proc: 2, gsn: 238 "DISEIZEREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57299 length: 2 trace: 0
- H'00000000 H'00fa0002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57299 gsn: 236 "DISEIZECONF" prio: 1
-s.bn: 246 "DBDIH", s.proc: 2, s.sigId: 57304 length: 2 trace: 0
- H'00000000 H'00000210
----- Send ----- Signal ----------------
-r.bn: 246 "DBDIH", r.proc: 2, gsn: 187 "DIADDTABREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57299 length: 6 trace: 0
- H'00000210 H'00000002 H'00000000 H'00000006 H'00000000 H'00000001
-
-// ---------------------------------------------------------------------------
-// DIH requests us to add a certain fragment replica.
-// ---------------------------------------------------------------------------
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57400 gsn: 195 "DICTFRAGSREQ" prio: 1
-s.bn: 246 "DBDIH", s.proc: 2, s.sigId: 57418 length: 7 trace: 0
- H'00000000 H'00000000 H'00000000 H'00000002 H'00150040 H'00000001 H'00000002
-
-// ---------------------------------------------------------------------------
-// We add the fragment by contacting LQH through sending a LQHFRAGREQ and
-// a number of LQHADDATTREQ (in this case only one since not more than 8
-// attributes).
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 247 "DBLQH", r.proc: 2, gsn: 313 "LQHFRAGREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57400 length: 17 trace: 0
- H'00000000 H'00fa0002 H'00000000 H'00000000 H'00000002 H'00000001 H'00000050
- H'0000004b H'00000006 H'00000001 H'00000000 H'00000005 H'00000000 H'00000000
- H'00000001 H'00000002 H'00000000
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57400 gsn: 311 "LQHFRAGCONF" prio: 1
-s.bn: 247 "DBLQH", s.proc: 2, s.sigId: 57428 length: 2 trace: 0
- H'00000000 H'00000000
----- Send ----- Signal ----------------
-r.bn: 247 "DBLQH", r.proc: 2, gsn: 310 "LQHADDATTREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57400 length: 12 trace: 0
- H'00000000 H'00000005 H'00000000 H'00012255 H'00000001 H'00012255 H'00000002
- H'000a2236 H'00000003 H'000a2236 H'00000004 H'00642236
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57400 gsn: 308 "LQHADDATTCONF" prio: 1
-s.bn: 247 "DBLQH", s.proc: 2, s.sigId: 57450 length: 1 trace: 0
- H'00000000
-
-// ---------------------------------------------------------------------------
-// When we have completed adding the fragment we send DINEXTNODEREQ (should
-// change name to DICTFRAGSCONF) to DIH indicate we have completed the task.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 246 "DBDIH", r.proc: 2, gsn: 231 "DINEXTNODEREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57400 length: 4 trace: 0
- H'00000210 H'00000000 H'00000001 H'00000000
-
-// ---------------------------------------------------------------------------
-// We continue by performing the same task again for the next fragment replica.
-// We skip this from this log since they contain no more interesting stuff.
-// ---------------------------------------------------------------------------
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 57618 gsn: 185 "DIADDTABCONF" prio: 1
-s.bn: 246 "DBDIH", s.proc: 2, s.sigId: 57655 length: 2 trace: 0
- H'00000000 H'00000002
-
-// ---------------------------------------------------------------------------
-// Now that we have added all fragments DIH gives back control to DICT by
-// sending DIADDTABCONF.
-// ---------------------------------------------------------------------------
-
-// ---------------------------------------------------------------------------
-// It is now time to decide which global checkpoint this table will be born.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 246 "DBDIH", r.proc: 2, gsn: 499 "WAIT_GCP_REQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 57618 length: 3 trace: 0
- H'00fa0002 H'00000000 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58288 gsn: 501 "WAIT_GCP_CONF" prio: 1
-s.bn: 246 "DBDIH", s.proc: 2, s.sigId: 58296 length: 2 trace: 0
- H'00000000 H'0000000c
-
-// ---------------------------------------------------------------------------
-// We can update all schema files in the system with this global checkpoint
-// number. We are certain that no transaction will be performed on the table
-// before this global checkpoint.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58288 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'0000000c H'00000003
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58288 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'0000000c H'00000003
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58288 gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 58298 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'0000000c H'00000003
-
-// ---------------------------------------------------------------------------
-// Write schema files as usual when updating schema file state.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58288 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050100
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58304 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 58305 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 117
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58304 length: 8 trace: 0
- FilePointer: 117
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58315 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 58316 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58315 length: 4 trace: 0
- FilePointer: 117
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58326 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 58327 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58326 length: 7 trace: 0
- UserReference: H'00fa0002, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050200
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58339 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 58340 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 118
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58339 length: 8 trace: 0
- FilePointer: 118
- UserReference: H'00fa0002, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58348 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 58349 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 2, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58348 length: 4 trace: 0
- FilePointer: 118
- UserReference: H'00fa0002, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 2, s.sigId: 58360 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 1 trace: 0
- H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 58364 length: 1 trace: 0
- H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, s.sigId: 47846 length: 1 trace: 0
- H'00000004
-
-// ---------------------------------------------------------------------------
-// Commit the table for usage in DIH and LQH in all nodes.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 247 "DBLQH", r.proc: 2, gsn: 398 "TAB_COMMITREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 3 trace: 0
- H'00000000 H'00fa0002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 246 "DBDIH", r.proc: 2, gsn: 398 "TAB_COMMITREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 3 trace: 0
- H'00000001 H'00fa0002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 247 "DBLQH", r.proc: 4, gsn: 398 "TAB_COMMITREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 3 trace: 0
- H'00000000 H'00fa0002 H'00000002
----- Send ----- Signal ----------------
-r.bn: 246 "DBDIH", r.proc: 4, gsn: 398 "TAB_COMMITREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 3 trace: 0
- H'00000001 H'00fa0002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 396 "TAB_COMMITCONF" prio: 1
-s.bn: 247 "DBLQH", s.proc: 2, s.sigId: 58370 length: 3 trace: 0
- H'00000000 H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 396 "TAB_COMMITCONF" prio: 1
-s.bn: 246 "DBDIH", s.proc: 2, s.sigId: 58371 length: 3 trace: 0
- H'00000001 H'00000002 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 396 "TAB_COMMITCONF" prio: 1
-s.bn: 247 "DBLQH", s.proc: 4, s.sigId: 47846 length: 3 trace: 0
- H'00000000 H'00000004 H'00000002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 396 "TAB_COMMITCONF" prio: 1
-s.bn: 246 "DBDIH", s.proc: 4, s.sigId: 47846 length: 3 trace: 0
- H'00000001 H'00000004 H'00000002
-
-// ---------------------------------------------------------------------------
-// Finally also open the table for usage from TC in all nodes.
-// After this signal is received in TC it is ok to execute transactions on
-// this new empty table.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 245 "DBTC", r.proc: 2, gsn: 404 "TC_SCHVERREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 5 trace: 0
- H'00000002 H'00000001 H'00000001 H'00fa0002 H'00000000
----- Send ----- Signal ----------------
-r.bn: 245 "DBTC", r.proc: 4, gsn: 404 "TC_SCHVERREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 5 trace: 0
- H'00000002 H'00000001 H'00000001 H'00fa0002 H'00000000
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 403 "TC_SCHVERCONF" prio: 1
-s.bn: 245 "DBTC", s.proc: 2, s.sigId: 58376 length: 2 trace: 0
- H'00000002 H'00000000
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 403 "TC_SCHVERCONF" prio: 1
-s.bn: 245 "DBTC", s.proc: 4, s.sigId: 47846 length: 2 trace: 0
- H'00000002 H'00000001
-
-// ---------------------------------------------------------------------------
-// Unblock dictionary to allow for another add table.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 444 "UNBLO_DICTREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 1 trace: 0
- H'00fa0002
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 444 "UNBLO_DICTREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 1 trace: 0
- H'00fa0002
-
-// ---------------------------------------------------------------------------
-// Send the confirmation to the requesting application process.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 1 "API", r.proc: 3, gsn: 24 "DICTTABCONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 3 trace: 0
- H'00047700 H'00000002 H'00000001
-
-// ---------------------------------------------------------------------------
-// Also release the connection in DIH that was previously established.
-// ---------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 246 "DBDIH", r.proc: 2, gsn: 234 "DIRELEASEREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, sigId: 58359 length: 3 trace: 0
- H'00000210 H'00000000 H'00fa0002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 444 "UNBLO_DICTREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 58378 length: 1 trace: 0
- H'00fa0002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, sigId: 58359 gsn: 232 "DIRELEASECONF" prio: 1
-s.bn: 246 "DBDIH", s.proc: 2, s.sigId: 58380 length: 1 trace: 0
- H'00000000
-
-// ---------------------------------------------------------------------------
-// Now all actions regarding this add table have completed.
-// ---------------------------------------------------------------------------
diff --git a/storage/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp b/storage/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
deleted file mode 100644
index 42c6e30792f..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBDICT_SCHEMA_FILE_HPP
-#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 PageNumber;
- Uint32 CheckSum; // Of this page
- Uint32 NoOfTableEntries; // On this page (NDB_SF_PAGE_ENTRIES)
-
- enum TableState {
- INIT = 0,
- ADD_STARTED = 1,
- TABLE_ADD_COMMITTED = 2,
- DROP_TABLE_STARTED = 3,
- DROP_TABLE_COMMITTED = 4,
- ALTER_TABLE_COMMITTED = 5,
- TEMPORARY_TABLE_COMMITTED = 6
- };
-
- // entry size 32 bytes
- struct TableEntry {
- Uint32 m_tableState;
- Uint32 m_tableVersion;
- Uint32 m_tableType;
- 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;
- };
-
- union {
- TableEntry TableEntries[NDB_SF_PAGE_ENTRIES];
- TableEntry_old TableEntries_old[1];
- };
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Slave_AddTable.sfl b/storage/ndb/src/kernel/blocks/dbdict/Slave_AddTable.sfl
deleted file mode 100644
index 20512b6f975..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/Slave_AddTable.sfl
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright (C) 2004 MySQL AB
-// Use is subject to license terms
-//
-// 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; version 2 of the License.
-//
-// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-// ---------------------------------------------------------------------------
-// This file contains a signal log trace for DBDICT at the master for a
-// create table. Another file contains the signal log for the participant
-// node. Master node is 2, participant node 4 and api node is 3.
-
-// ---------------------------------------------------------------------------
-// This file contains a signal log trace for DBDICT at the participant for a
-// add table. Another file contains the signal log for the master
-// node. Master node is 2, participant node 4 and api node is 3.
-//
-
-// ---------------------------------------------------------------------------
-//--------------------------------------------------------------------------
-// Master requests us to save a new state of the table in the schema file
-// == ADD_STARTED
-//--------------------------------------------------------------------------
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46661 gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57069 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000000 H'00000000 H'00000001
-
-//--------------------------------------------------------------------------
-// Write the new state to the schema files.
-//--------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46661 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050100
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46669 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46670 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 99
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46669 length: 8 trace: 0
- FilePointer: 99
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46679 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46680 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46679 length: 4 trace: 0
- FilePointer: 99
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46690 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46691 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46690 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050200
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46700 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46701 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 100
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46700 length: 8 trace: 0
- FilePointer: 100
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46709 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46710 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46709 length: 4 trace: 0
- FilePointer: 100
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46719 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46718 length: 1 trace: 0
- H'00000004
-
-//--------------------------------------------------------------------------
-// We receive the table description from the master node.
-// We set the data in the DICT block. (table and attribute records).
-//--------------------------------------------------------------------------
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000000 H'4e444250 H'524f5053
- H'00002000 H'0000001c H'1c0a1203 H'524f4c46 H'00020001 H'0000000a H'56504e5f
- H'55534552 H'53000000 H'0001000a H'0000004b H'000203e8 H'00000007 H'56504e5f
- H'49440000 H'1cc03924 H'00000001 H'000203e8
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000014 H'00000007 H'56504e5f
- H'4e420000 H'000103ee H'00000001 H'000203e8 H'0000000d H'44495245 H'43544f52
- H'595f4e42 H'00000000 H'000103eb H'00000003 H'524f4c46 H'00020001 H'0000000a
- H'56504e5f H'55534552 H'53000010 H'00010002
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000028 H'00000002 H'00010011
- H'00000003 H'00010003 H'00000001 H'00010005 H'00000002 H'00010006 H'00000005
- H'0001000a H'0000004b H'0001000c H'00000002 H'000203e8 H'00000007 H'56504e5f
- H'49440064 H'000103e9 H'00000000 H'000103ee
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'0000003c H'00000001 H'000203e8
- H'00000007 H'56504e5f H'4e420002 H'000103e9 H'00000001 H'000103ee H'00000001
- H'000203e8 H'0000000d H'44495245 H'43544f52 H'595f4e42 H'00000000 H'000103e9
- H'00000002 H'000103eb H'00000003 H'000103ec
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57132 length: 25 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000050 H'00000002 H'000103ed
- H'0000000a H'000203e8 H'00000010 H'4c415354 H'5f43414c H'4c5f5041 H'52545900
- H'000103e9 H'00000003 H'000103eb H'00000003 H'000103ec H'00000002 H'000103ed
- H'0000000a H'000203e8 H'00000006 H'44455343
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 204 "DICTTABINFO" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57132 length: 15 trace: 0
- H'00fa0002 H'00000000 H'00000002 H'0000006e H'00000064 H'52000000 H'000103e9
- H'00000004 H'000103eb H'00000003 H'000103ec H'00000002 H'000103ed H'00000064
- H'0000ffff
-
-//--------------------------------------------------------------------------
-// Pack the table description into pages.
-//--------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46718 length: 3 trace: 0
- H'00000001 H'00000002 H'00000000
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46718 gsn: 164 "CONTINUEB" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, s.sigId: 46730 length: 3 trace: 0
- H'00000001 H'00000002 H'00000000
-
-//--------------------------------------------------------------------------
-// Write the pages of the table description to disk.
-//--------------------------------------------------------------------------
-
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46718 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'00000002 H'ffffffff H'00000001 H'010401ff
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46748 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46749 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 101
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46748 length: 8 trace: 0
- FilePointer: 101
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000000, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46757 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46758 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46757 length: 4 trace: 0
- FilePointer: 101
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46766 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46767 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46766 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'00000002 H'ffffffff H'00000001 H'010402ff
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46783 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46784 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 102
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46783 length: 8 trace: 0
- FilePointer: 102
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000000, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46794 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46795 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46794 length: 4 trace: 0
- FilePointer: 102
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46803 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46804 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 24 "DICTTABCONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46803 length: 2 trace: 0
- H'00000002 H'00000004
-
-//--------------------------------------------------------------------------
-// Update schema file ín memory and on disk to UPDATE_PAGE_COUNT.
-//--------------------------------------------------------------------------
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46803 gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 57229 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'00000000 H'00000002
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46803 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050100
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46813 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46814 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 103
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46813 length: 8 trace: 0
- FilePointer: 103
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46823 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46824 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46823 length: 4 trace: 0
- FilePointer: 103
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46833 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46834 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46833 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050200
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46842 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46843 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 104
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46842 length: 8 trace: 0
- FilePointer: 104
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46851 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46852 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46851 length: 4 trace: 0
- FilePointer: 104
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 46860 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 46861 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 46860 length: 1 trace: 0
- H'00000004
-
-//--------------------------------------------------------------------------
-// Update schema file with information about the starting global checkpoint
-// identity.
-//--------------------------------------------------------------------------
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47782 gsn: 132 "DICT_SCHEMAREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 58288 length: 7 trace: 0
- H'00010003 H'00047700 H'00000002 H'00000001 H'00000001 H'0000000c H'00000003
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 47782 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050100
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47793 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 47794 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 117
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 47793 length: 8 trace: 0
- FilePointer: 117
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47804 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 47805 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 47804 length: 4 trace: 0
- FilePointer: 117
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47817 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 47818 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 261 "FSOPENREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 47817 length: 7 trace: 0
- UserReference: H'00fa0004, userPointer: H'00000000
- FileNumber[1-4]: H'ffffffff H'ffffffff H'ffffffff H'01050200
- FileFlags: H'00000311 Open write only, Create new file, Truncate existing file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47826 gsn: 259 "FSOPENCONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 47827 length: 3 trace: 0
- UserPointer: H'00000000
- FilePointer: 118
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 272 "FSWRITEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 47826 length: 8 trace: 0
- FilePointer: 118
- UserReference: H'00fa0004, UserPointer: H'00000000
- Operation flag: H'00000011, Sync, Format=Array of pages
- varIndex: 1
- numberOfPages: 1
- pageData: H'00000008, H'00000000
-
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47836 gsn: 270 "FSWRITECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 47837 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 253 "NDBFS", r.proc: 4, gsn: 257 "FSCLOSEREQ" prio: 0
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 47836 length: 4 trace: 0
- FilePointer: 118
- UserReference: H'00fa0004, userPointer: H'00000000
- Flags: H'00000000, Don't remove file
----- Received - Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47846 gsn: 255 "FSCLOSECONF" prio: 1
-s.bn: 253 "NDBFS", s.proc: 4, s.sigId: 47847 length: 1 trace: 0
- UserPointer: H'00000000
----- Send ----- Signal ----------------
-r.bn: 250 "DBDICT", r.proc: 2, gsn: 133 "DICT_SCHEMACONF" prio: 1
-s.bn: 250 "DBDICT", s.proc: 4, sigId: 47846 length: 1 trace: 0
- H'00000004
----- Received - Signal ----------------
-
-//--------------------------------------------------------------------------
-// Finally unblock the DICT block so that it can handle add table as master
-// if it becomes master in the future.
-//--------------------------------------------------------------------------
-
-r.bn: 250 "DBDICT", r.proc: 4, sigId: 47846 gsn: 444 "UNBLO_DICTREQ" prio: 1
-s.bn: 250 "DBDICT", s.proc: 2, s.sigId: 58359 length: 1 trace: 0
- H'00fa0002
-
-//--------------------------------------------------------------------------
-// We completed the add table operation.
-//--------------------------------------------------------------------------
-
diff --git a/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp b/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
deleted file mode 100644
index 55c42ee88e7..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-#include <util/version.h>
-
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <SchemaFile.hpp>
-#include <kernel_types.h>
-
-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;
-}
-
-#ifdef NOT_USED
-
-static void
-fill(const char * buf, int mod)
-{
- int len = strlen(buf)+1;
- ndbout << buf << " ";
- while((len % mod) != 0){
- ndbout << " ";
- len++;
- }
-}
-#endif
-
-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",
- (int) 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;
-}
-
-inline
-Uint32
-table_version_minor(Uint32 ver)
-{
- return ver >> 24;
-}
-
-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 = " << table_version_major(te.m_tableVersion)
- << "(" << table_version_minor(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;
-
- if (print_head(filename, xsf) != 0)
- retcode = 1;
-
- 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;
- }
- 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 = " << table_version_major(te.m_tableVersion)
- << "(" << table_version_minor(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;
- }
- }
- }
-
- 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++;
- }
-
- 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 [] prevbuf;
- return exitcode;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
deleted file mode 100644
index f27287b79a4..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ /dev/null
@@ -1,1673 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBDIH_H
-#define DBDIH_H
-
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <SimulatedBlock.hpp>
-#include "Sysfile.hpp"
-#include <SignalCounter.hpp>
-
-#include <signaldata/MasterLCP.hpp>
-#include <signaldata/CopyGCIReq.hpp>
-#include <blocks/mutexes.hpp>
-
-#ifdef DBDIH_C
-
-/*###################*/
-/* FILE SYSTEM FLAGS */
-/*###################*/
-#define ZLIST_OF_PAIRS 0
-#define ZLIST_OF_PAIRS_SYNCH 16
-#define ZOPEN_READ_WRITE 2
-#define ZCREATE_READ_WRITE 0x302
-#define ZCLOSE_NO_DELETE 0
-#define ZCLOSE_DELETE 1
-
-/*###############*/
-/* NODE STATES */
-/*###############*/
-#define ZIDLE 0
-#define ZACTIVE 1
-
-/*#########*/
-/* GENERAL */
-/*#########*/
-#define ZVAR_NO_WORD 1
-#define ZVAR_NO_CRESTART_INFO 20
-#define ZVAR_NO_CRESTART_INFO_TO_FILE 21
-#define ZVALID 1
-#define ZINVALID 2
-
-/*###############*/
-/* ERROR CODES */
-/*###############*/
-// ------------------------------------------
-// Error Codes for Transactions (None sofar)
-// ------------------------------------------
-#define ZUNDEFINED_FRAGMENT_ERROR 311
-
-// --------------------------------------
-// Error Codes for Add Table
-// --------------------------------------
-#define ZREPLERROR1 306
-
-// --------------------------------------
-// Crash Codes
-// --------------------------------------
-#define ZCOULD_NOT_OCCUR_ERROR 300
-#define ZNOT_MASTER_ERROR 301
-#define ZWRONG_FAILURE_NUMBER_ERROR 302
-#define ZWRONG_START_NODE_ERROR 303
-#define ZNO_REPLICA_FOUND_ERROR 304
-
-// --------------------------------------
-// Codes from LQH
-// --------------------------------------
-#define ZNODE_FAILURE_ERROR 400
-
-
-/*#########*/
-/* PHASES */
-/*#########*/
-#define ZNDB_SPH1 1
-#define ZNDB_SPH2 2
-#define ZNDB_SPH3 3
-#define ZNDB_SPH4 4
-#define ZNDB_SPH5 5
-#define ZNDB_SPH6 6
-#define ZNDB_SPH7 7
-#define ZNDB_SPH8 8
-/*#########*/
-/* SIZES */
-/*#########*/
-#define ZPAGEREC 100
-#define ZCREATE_REPLICA_FILE_SIZE 4
-#define ZPROXY_MASTER_FILE_SIZE 10
-#define ZPROXY_FILE_SIZE 10
-#endif
-
-class Dbdih: public SimulatedBlock {
-public:
-
- // Records
-
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
- * THE API CONNECT RECORD IS THE SAME RECORD POINTER AS USED IN THE TC BLOCK
- *
- * IT KEEPS TRACK OF ALL THE OPERATIONS CONNECTED TO THIS TRANSACTION.
- * IT IS LINKED INTO A QUEUE IN CASE THE GLOBAL CHECKPOINT IS CURRENTLY
- * ONGOING */
- struct ApiConnectRecord {
- Uint32 apiGci;
- Uint32 nextApi;
- };
- typedef Ptr<ApiConnectRecord> ApiConnectRecordPtr;
-
- /*############## CONNECT_RECORD ##############*/
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* THE CONNECT RECORD IS CREATED WHEN A TRANSACTION HAS TO START. IT KEEPS
- ALL INTERMEDIATE INFORMATION NECESSARY FOR THE TRANSACTION FROM THE
- DISTRIBUTED MANAGER. THE RECORD KEEPS INFORMATION ABOUT THE
- OPERATIONS THAT HAVE TO BE CARRIED OUT BY THE TRANSACTION AND
- ALSO THE TRAIL OF NODES FOR EACH OPERATION IN THE THE
- TRANSACTION.
- */
- struct ConnectRecord {
- enum ConnectState {
- INUSE = 0,
- FREE = 1,
- STARTED = 2
- };
- Uint32 nodes[MAX_REPLICAS];
- ConnectState connectState;
- Uint32 nfConnect;
- Uint32 table;
- Uint32 userpointer;
- BlockReference userblockref;
- };
- typedef Ptr<ConnectRecord> ConnectRecordPtr;
-
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* THESE RECORDS ARE USED WHEN CREATING REPLICAS DURING SYSTEM */
- /* RESTART. I NEED A COMPLEX DATA STRUCTURE DESCRIBING THE REPLICAS */
- /* I WILL TRY TO CREATE FOR EACH FRAGMENT. */
- /* */
- /* I STORE A REFERENCE TO THE FOUR POSSIBLE CREATE REPLICA RECORDS */
- /* IN A COMMON STORED VARIABLE. I ALLOW A MAXIMUM OF 4 REPLICAS TO */
- /* BE RESTARTED PER FRAGMENT. */
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- struct CreateReplicaRecord {
- Uint32 logStartGci[MAX_LOG_EXEC];
- Uint32 logStopGci[MAX_LOG_EXEC];
- Uint16 logNodeId[MAX_LOG_EXEC];
- Uint32 createLcpId;
-
- bool hotSpareUse;
- Uint32 replicaRec;
- Uint16 dataNodeId;
- Uint16 lcpNo;
- Uint16 noLogNodes;
- };
- typedef Ptr<CreateReplicaRecord> CreateReplicaRecordPtr;
-
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* THIS RECORD CONTAINS A FILE DESCRIPTION. THERE ARE TWO */
- /* FILES PER TABLE TO RAISE SECURITY LEVEL AGAINST DISK CRASHES. */
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- struct FileRecord {
- enum FileStatus {
- CLOSED = 0,
- CRASHED = 1,
- OPEN = 2
- };
- enum FileType {
- TABLE_FILE = 0,
- GCP_FILE = 1
- };
- enum ReqStatus {
- IDLE = 0,
- CREATING_GCP = 1,
- OPENING_GCP = 2,
- OPENING_COPY_GCI = 3,
- WRITING_COPY_GCI = 4,
- CREATING_COPY_GCI = 5,
- OPENING_TABLE = 6,
- READING_GCP = 7,
- READING_TABLE = 8,
- WRITE_INIT_GCP = 9,
- TABLE_CREATE = 10,
- TABLE_WRITE = 11,
- TABLE_CLOSE = 12,
- CLOSING_GCP = 13,
- CLOSING_TABLE_CRASH = 14,
- CLOSING_TABLE_SR = 15,
- CLOSING_GCP_CRASH = 16,
- TABLE_OPEN_FOR_DELETE = 17,
- TABLE_CLOSE_DELETE = 18
- };
- Uint32 fileName[4];
- Uint32 fileRef;
- FileStatus fileStatus;
- FileType fileType;
- Uint32 nextFile;
- ReqStatus reqStatus;
- Uint32 tabRef;
- };
- typedef Ptr<FileRecord> FileRecordPtr;
-
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* THIS RECORD KEEPS THE STORAGE AND DECISIONS INFORMATION OF A FRAGMENT */
- /* AND ITS REPLICAS. IF FRAGMENT HAS MORE THAN ONE BACK UP */
- /* REPLICA THEN A LIST OF MORE NODES IS ATTACHED TO THIS RECORD. */
- /* EACH RECORD IN MORE LIST HAS INFORMATION ABOUT ONE BACKUP. THIS RECORD */
- /* ALSO HAVE THE STATUS OF THE FRAGMENT. */
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* */
- /* FRAGMENTSTORE RECORD ALIGNED TO BE 64 BYTES */
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- struct Fragmentstore {
- Uint16 activeNodes[MAX_REPLICAS];
- Uint32 preferredPrimary;
-
- Uint32 oldStoredReplicas; /* "DEAD" STORED REPLICAS */
- Uint32 storedReplicas; /* "ALIVE" STORED REPLICAS */
- Uint32 nextFragmentChunk;
-
- Uint32 m_log_part_id;
-
- Uint8 distributionKey;
- Uint8 fragReplicas;
- Uint8 noOldStoredReplicas; /* NUMBER OF "DEAD" STORED REPLICAS */
- Uint8 noStoredReplicas; /* NUMBER OF "ALIVE" STORED REPLICAS*/
- Uint8 noLcpReplicas; ///< No of replicas remaining to be LCP:ed
- };
- typedef Ptr<Fragmentstore> FragmentstorePtr;
-
- /*########### PAGE RECORD ############*/
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* THIS RECORD KEEPS INFORMATION ABOUT NODE GROUPS. */
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- struct NodeGroupRecord {
- Uint32 nodesInGroup[MAX_REPLICAS + 1];
- Uint32 nextReplicaNode;
- Uint32 nodeCount;
- bool activeTakeOver;
- };
- typedef Ptr<NodeGroupRecord> NodeGroupRecordPtr;
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* THIS RECORD KEEPS INFORMATION ABOUT NODES. */
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- /* RECORD ALIGNED TO BE 64 BYTES. */
- /*¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤*/
- enum NodefailHandlingStep {
- NF_REMOVE_NODE_FROM_TABLE = 1,
- NF_GCP_TAKE_OVER = 2,
- NF_LCP_TAKE_OVER = 4
- };
-
- struct NodeRecord {
- NodeRecord();
-
- enum NodeStatus {
- NOT_IN_CLUSTER = 0,
- ALIVE = 1,
- STARTING = 2,
- DIED_NOW = 3,
- DYING = 4,
- DEAD = 5
- };
-
- struct FragmentCheckpointInfo {
- Uint32 tableId;
- Uint32 fragId;
- Uint32 replicaPtr;
- };
-
- enum GcpState {
- READY = 0,
- PREPARE_SENT = 1,
- PREPARE_RECEIVED = 2,
- COMMIT_SENT = 3,
- NODE_FINISHED = 4,
- SAVE_REQ_SENT = 5,
- SAVE_RECEIVED = 6,
- COPY_GCI_SENT = 7
- };
-
- GcpState gcpstate;
- Sysfile::ActiveStatus activeStatus;
-
- NodeStatus nodeStatus;
- bool useInTransactions;
- bool allowNodeStart;
- bool copyCompleted;
- bool m_inclDihLcp;
-
- FragmentCheckpointInfo startedChkpt[2];
- FragmentCheckpointInfo queuedChkpt[2];
-
- Bitmask<1> m_nodefailSteps;
- Uint32 activeTabptr;
- Uint32 nextNode;
- Uint32 nodeGroup;
-
- SignalCounter m_NF_COMPLETE_REP;
-
- Uint8 dbtcFailCompleted;
- Uint8 dblqhFailCompleted;
- Uint8 dbdihFailCompleted;
- Uint8 dbdictFailCompleted;
- Uint8 recNODE_FAILREP;
-
- Uint8 noOfQueuedChkpt;
- Uint8 noOfStartedChkpt;
-
- MasterLCPConf::State lcpStateAtTakeOver;
- Uint32 m_remove_node_from_table_lcp_id;
- };
- typedef Ptr<NodeRecord> NodeRecordPtr;
- /**********************************************************************/
- /* THIS RECORD KEEPS THE INFORMATION ABOUT A TABLE AND ITS FRAGMENTS */
- /**********************************************************************/
- struct PageRecord {
- Uint32 word[2048];
- /* 8 KBYTE PAGE*/
- Uint32 nextfreepage;
- };
- typedef Ptr<PageRecord> PageRecordPtr;
-
- /************ REPLICA RECORD *************/
- /**********************************************************************/
- /* THIS RECORD KEEPS THE INFORMATION ABOUT A REPLICA OF A FRAGMENT */
- /**********************************************************************/
- struct ReplicaRecord {
- /* -------------------------------------------------------------------- */
- /* THE GLOBAL CHECKPOINT IDENTITY WHEN THIS REPLICA WAS CREATED. */
- /* THERE IS ONE INDEX PER REPLICA. A REPLICA INDEX IS CREATED WHEN ANODE*/
- /* CRASH OCCURS. */
- /* -------------------------------------------------------------------- */
- Uint32 createGci[8];
- /* -------------------------------------------------------------------- */
- /* THE LAST GLOBAL CHECKPOINT IDENTITY WHICH HAS BEEN SAVED ON DISK. */
- /* THIS VARIABLE IS ONLY VALID FOR REPLICAS WHICH HAVE "DIED". A REPLICA*/
- /* "DIES" EITHER WHEN THE NODE CRASHES THAT KEPT THE REPLICA OR BY BEING*/
- /* STOPPED IN A CONTROLLED MANNER. */
- /* THERE IS ONE INDEX PER REPLICA. A REPLICA INDEX IS CREATED WHEN ANODE*/
- /* CRASH OCCURS. */
- /* -------------------------------------------------------------------- */
- Uint32 replicaLastGci[8];
- /* -------------------------------------------------------------------- */
- /* THE LOCAL CHECKPOINT IDENTITY OF A LOCAL CHECKPOINT. */
- /* -------------------------------------------------------------------- */
- Uint32 lcpId[MAX_LCP_STORED];
- /* -------------------------------------------------------------------- */
- /* THIS VARIABLE KEEPS TRACK OF THE MAXIMUM GLOBAL CHECKPOINT COMPLETED */
- /* FOR EACH OF THE LOCAL CHECKPOINTS IN THIS FRAGMENT REPLICA. */
- /* -------------------------------------------------------------------- */
- Uint32 maxGciCompleted[MAX_LCP_STORED];
- /* -------------------------------------------------------------------- */
- /* THIS VARIABLE KEEPS TRACK OF THE MINIMUM GLOBAL CHECKPOINT STARTEDFOR*/
- /* EACH OF THE LOCAL CHECKPOINTS IN THIS FRAGMENT REPLICA. */
- /* -------------------------------------------------------------------- */
- Uint32 maxGciStarted[MAX_LCP_STORED];
- /* -------------------------------------------------------------------- */
- /* THE GLOBAL CHECKPOINT IDENTITY WHEN THE TABLE WAS CREATED. */
- /* -------------------------------------------------------------------- */
- Uint32 initialGci;
-
- /* -------------------------------------------------------------------- */
- /* THE REFERENCE TO THE NEXT REPLICA. EITHER IT REFERS TO THE NEXT IN */
- /* THE FREE LIST OR IT REFERS TO THE NEXT IN A LIST OF REPLICAS ON A */
- /* FRAGMENT. */
- /* -------------------------------------------------------------------- */
- Uint32 nextReplica;
-
- /* -------------------------------------------------------------------- */
- /* THE NODE ID WHERE THIS REPLICA IS STORED. */
- /* -------------------------------------------------------------------- */
- Uint16 procNode;
-
- /* -------------------------------------------------------------------- */
- /* The last local checkpoint id started or queued on this replica. */
- /* -------------------------------------------------------------------- */
- Uint32 lcpIdStarted; // Started or queued
-
- /* -------------------------------------------------------------------- */
- /* THIS VARIABLE SPECIFIES WHAT THE STATUS OF THE LOCAL CHECKPOINT IS.IT*/
- /* CAN EITHER BE VALID OR INVALID. AT CREATION OF A FRAGMENT REPLICA ALL*/
- /* LCP'S ARE INVALID. ALSO IF IF INDEX >= NO_LCP THEN THELOCALCHECKPOINT*/
- /* IS ALWAYS INVALID. IF THE LCP BEFORE THE NEXT_LCP HAS LCP_ID THAT */
- /* DIFFERS FROM THE LATEST LCP_ID STARTED THEN THE NEXT_LCP IS ALSO */
- /* INVALID */
- /* -------------------------------------------------------------------- */
- Uint8 lcpStatus[MAX_LCP_STORED];
-
- /* -------------------------------------------------------------------- */
- /* THE NEXT LOCAL CHECKPOINT TO EXECUTE IN THIS FRAGMENT REPLICA. */
- /* -------------------------------------------------------------------- */
- Uint8 nextLcp;
-
- /* -------------------------------------------------------------------- */
- /* THE NUMBER OF CRASHED REPLICAS IN THIS REPLICAS SO FAR. */
- /* -------------------------------------------------------------------- */
- Uint8 noCrashedReplicas;
-
- /**
- * Is a LCP currently ongoing on fragment
- */
- Uint8 lcpOngoingFlag;
- };
- typedef Ptr<ReplicaRecord> ReplicaRecordPtr;
-
- /*************************************************************************
- * TAB_DESCRIPTOR IS A DESCRIPTOR OF THE LOCATION OF THE FRAGMENTS BELONGING
- * TO THE TABLE.THE INFORMATION ABOUT FRAGMENTS OF A TABLE ARE STORED IN
- * CHUNKS OF FRAGMENTSTORE RECORDS.
- * THIS RECORD ALSO HAS THE NECESSARY INFORMATION TO LOCATE A FRAGMENT AND
- * TO LOCATE A FRAGMENT AND TO TRANSLATE A KEY OF A TUPLE TO THE FRAGMENT IT
- * BELONGS
- */
- struct TabRecord {
- /**
- * State for copying table description into pages
- */
- enum CopyStatus {
- CS_IDLE,
- CS_SR_PHASE1_READ_PAGES,
- CS_SR_PHASE2_READ_TABLE,
- CS_SR_PHASE3_COPY_TABLE,
- CS_REMOVE_NODE,
- CS_LCP_READ_TABLE,
- CS_COPY_TAB_REQ,
- CS_COPY_NODE_STATE,
- CS_ADD_TABLE_MASTER,
- CS_ADD_TABLE_SLAVE,
- CS_INVALIDATE_NODE_LCP
- };
- /**
- * State for copying pages to disk
- */
- enum UpdateState {
- US_IDLE,
- US_LOCAL_CHECKPOINT,
- US_REMOVE_NODE,
- US_COPY_TAB_REQ,
- US_ADD_TABLE_MASTER,
- US_ADD_TABLE_SLAVE,
- US_INVALIDATE_NODE_LCP
- };
- enum TabLcpStatus {
- TLS_ACTIVE = 1,
- TLS_WRITING_TO_FILE = 2,
- TLS_COMPLETED = 3
- };
- enum TabStatus {
- TS_IDLE = 0,
- TS_ACTIVE = 1,
- TS_CREATING = 2,
- TS_DROPPING = 3
- };
- enum Method {
- LINEAR_HASH = 0,
- NOTDEFINED = 1,
- NORMAL_HASH = 2,
- USER_DEFINED = 3
- };
- enum Storage {
- ST_NOLOGGING = 0, // Table is not logged, but survives SR
- ST_NORMAL = 1, // Normal table, logged and durable
- ST_TEMPORARY = 2 // Table is lost after SR, not logged
- };
- CopyStatus tabCopyStatus;
- UpdateState tabUpdateState;
- TabLcpStatus tabLcpStatus;
- TabStatus tabStatus;
- Method method;
- Storage tabStorage;
-
- Uint32 pageRef[8];
-//-----------------------------------------------------------------------------
-// Each entry in this array contains a reference to 16 fragment records in a
-// row. Thus finding the correct record is very quick provided the fragment id.
-//-----------------------------------------------------------------------------
- Uint32 startFid[MAX_NDB_NODES];
-
- Uint32 tabFile[2];
- Uint32 connectrec;
- Uint32 hashpointer;
- Uint32 mask;
- Uint32 noOfWords;
- Uint32 schemaVersion;
- Uint32 tabRemoveNode;
- Uint32 totalfragments;
- Uint32 noOfFragChunks;
- Uint32 tabErrorCode;
- struct {
- Uint32 tabUserRef;
- Uint32 tabUserPtr;
- } m_dropTab;
-
- struct DropTable {
- Uint32 senderRef;
- Uint32 senderData;
- SignalCounter waitDropTabCount;
- } m_prepDropTab;
-
- Uint8 kvalue;
- Uint8 noOfBackups;
- Uint8 noPages;
- Uint16 tableType;
- Uint16 primaryTableId;
- };
- typedef Ptr<TabRecord> TabRecordPtr;
-
- /***************************************************************************/
- /* THIS RECORD IS USED TO KEEP TRACK OF TAKE OVER AND STARTING A NODE. */
- /* WE KEEP IT IN A RECORD TO ENABLE IT TO BE PARALLELISED IN THE FUTURE. */
- /**************************************************************************/
- struct TakeOverRecord {
- enum ToMasterStatus {
- IDLE = 0,
- TO_WAIT_START_TAKE_OVER = 1,
- TO_START_COPY = 2,
- TO_START_COPY_ONGOING = 3,
- TO_WAIT_START = 4,
- STARTING = 5,
- SELECTING_NEXT = 6,
- TO_WAIT_PREPARE_CREATE = 9,
- PREPARE_CREATE = 10,
- COPY_FRAG = 11,
- TO_WAIT_UPDATE_TO = 12,
- TO_UPDATE_TO = 13,
- COPY_ACTIVE = 14,
- TO_WAIT_COMMIT_CREATE = 15,
- LOCK_MUTEX = 23,
- COMMIT_CREATE = 16,
- TO_COPY_COMPLETED = 17,
- WAIT_LCP = 18,
- TO_END_COPY = 19,
- TO_END_COPY_ONGOING = 20,
- TO_WAIT_ENDING = 21,
- ENDING = 22,
-
- STARTING_LOCAL_FRAGMENTS = 24,
- PREPARE_COPY = 25
- };
- enum ToSlaveStatus {
- TO_SLAVE_IDLE = 0,
- TO_SLAVE_STARTED = 1,
- TO_SLAVE_CREATE_PREPARE = 2,
- TO_SLAVE_COPY_FRAG_COMPLETED = 3,
- TO_SLAVE_CREATE_COMMIT = 4,
- TO_SLAVE_COPY_COMPLETED = 5
- };
- Uint32 startGci;
- Uint32 maxPage;
- Uint32 toCopyNode;
- Uint32 toCurrentFragid;
- Uint32 toCurrentReplica;
- Uint32 toCurrentTabref;
- Uint32 toFailedNode;
- Uint32 toStartingNode;
- Uint32 nextTakeOver;
- Uint32 prevTakeOver;
- bool toNodeRestart;
- ToMasterStatus toMasterStatus;
- ToSlaveStatus toSlaveStatus;
- MutexHandle2<DIH_SWITCH_PRIMARY_MUTEX> m_switchPrimaryMutexHandle;
- };
- typedef Ptr<TakeOverRecord> TakeOverRecordPtr;
-
-public:
- Dbdih(Block_context& ctx);
- virtual ~Dbdih();
-
- struct RWFragment {
- Uint32 pageIndex;
- Uint32 wordIndex;
- Uint32 fragId;
- TabRecordPtr rwfTabPtr;
- PageRecordPtr rwfPageptr;
- };
- struct CopyTableNode {
- Uint32 pageIndex;
- Uint32 wordIndex;
- Uint32 noOfWords;
- TabRecordPtr ctnTabPtr;
- PageRecordPtr ctnPageptr;
- };
-
-private:
- BLOCK_DEFINES(Dbdih);
-
- void execDUMP_STATE_ORD(Signal *);
- void execNDB_TAMPER(Signal *);
- void execDEBUG_SIG(Signal *);
- void execEMPTY_LCP_CONF(Signal *);
- void execMASTER_GCPREF(Signal *);
- void execMASTER_GCPREQ(Signal *);
- void execMASTER_GCPCONF(Signal *);
- void execMASTER_LCPREF(Signal *);
- void execMASTER_LCPREQ(Signal *);
- void execMASTER_LCPCONF(Signal *);
- void execNF_COMPLETEREP(Signal *);
- void execSTART_PERMREQ(Signal *);
- void execSTART_PERMCONF(Signal *);
- void execSTART_PERMREF(Signal *);
- void execINCL_NODEREQ(Signal *);
- void execINCL_NODECONF(Signal *);
- void execEND_TOREQ(Signal *);
- void execEND_TOCONF(Signal *);
- void execSTART_TOREQ(Signal *);
- void execSTART_TOCONF(Signal *);
- void execSTART_MEREQ(Signal *);
- void execSTART_MECONF(Signal *);
- void execSTART_MEREF(Signal *);
- void execSTART_COPYREQ(Signal *);
- void execSTART_COPYCONF(Signal *);
- void execSTART_COPYREF(Signal *);
- void execCREATE_FRAGREQ(Signal *);
- void execCREATE_FRAGCONF(Signal *);
- void execDIVERIFYREQ(Signal *);
- void execGCP_SAVECONF(Signal *);
- void execGCP_PREPARECONF(Signal *);
- void execGCP_PREPARE(Signal *);
- void execGCP_NODEFINISH(Signal *);
- void execGCP_COMMIT(Signal *);
- void execDIHNDBTAMPER(Signal *);
- void execCONTINUEB(Signal *);
- void execCOPY_GCIREQ(Signal *);
- void execCOPY_GCICONF(Signal *);
- void execCOPY_TABREQ(Signal *);
- void execCOPY_TABCONF(Signal *);
- void execTCGETOPSIZECONF(Signal *);
- void execTC_CLOPSIZECONF(Signal *);
-
- int handle_invalid_lcp_no(const class LcpFragRep*, ReplicaRecordPtr);
- void execLCP_FRAG_REP(Signal *);
- void execLCP_COMPLETE_REP(Signal *);
- void execSTART_LCP_REQ(Signal *);
- void execSTART_LCP_CONF(Signal *);
- MutexHandle2<DIH_START_LCP_MUTEX> c_startLcpMutexHandle;
- void startLcpMutex_locked(Signal* signal, Uint32, Uint32);
- void startLcpMutex_unlocked(Signal* signal, Uint32, Uint32);
-
- MutexHandle2<DIH_SWITCH_PRIMARY_MUTEX> c_switchPrimaryMutexHandle;
- void switchPrimaryMutex_locked(Signal* signal, Uint32, Uint32);
- void switchPrimaryMutex_unlocked(Signal* signal, Uint32, Uint32);
- void switch_primary_stop_node(Signal* signal, Uint32, Uint32);
-
- void execBLOCK_COMMIT_ORD(Signal *);
- void execUNBLOCK_COMMIT_ORD(Signal *);
-
- void execDIH_SWITCH_REPLICA_REQ(Signal *);
- void execDIH_SWITCH_REPLICA_REF(Signal *);
- void execDIH_SWITCH_REPLICA_CONF(Signal *);
-
- void execSTOP_PERM_REQ(Signal *);
- void execSTOP_PERM_REF(Signal *);
- void execSTOP_PERM_CONF(Signal *);
-
- void execSTOP_ME_REQ(Signal *);
- void execSTOP_ME_REF(Signal *);
- void execSTOP_ME_CONF(Signal *);
-
- void execREAD_CONFIG_REQ(Signal *);
- void execUNBLO_DICTCONF(Signal *);
- void execCOPY_ACTIVECONF(Signal *);
- void execTAB_COMMITREQ(Signal *);
- void execNODE_FAILREP(Signal *);
- void execCOPY_FRAGCONF(Signal *);
- void execCOPY_FRAGREF(Signal *);
- void execPREPARE_COPY_FRAG_REF(Signal*);
- void execPREPARE_COPY_FRAG_CONF(Signal*);
- void execDIADDTABREQ(Signal *);
- void execDIGETNODESREQ(Signal *);
- void execDIRELEASEREQ(Signal *);
- void execDISEIZEREQ(Signal *);
- void execSTTOR(Signal *);
- void execDI_FCOUNTREQ(Signal *);
- void execDIGETPRIMREQ(Signal *);
- void execGCP_SAVEREF(Signal *);
- void execGCP_TCFINISHED(Signal *);
- void execREAD_NODESCONF(Signal *);
- void execNDB_STTOR(Signal *);
- void execDICTSTARTCONF(Signal *);
- void execNDB_STARTREQ(Signal *);
- void execGETGCIREQ(Signal *);
- void execDIH_RESTARTREQ(Signal *);
- void execSTART_RECCONF(Signal *);
- void execSTART_FRAGREF(Signal *);
- void execSTART_FRAGCONF(Signal *);
- void execADD_FRAGCONF(Signal *);
- void execADD_FRAGREF(Signal *);
- void execFSOPENCONF(Signal *);
- void execFSOPENREF(Signal *);
- void execFSCLOSECONF(Signal *);
- void execFSCLOSEREF(Signal *);
- void execFSREADCONF(Signal *);
- void execFSREADREF(Signal *);
- void execFSWRITECONF(Signal *);
- void execFSWRITEREF(Signal *);
- void execCHECKNODEGROUPSREQ(Signal *);
- void execSTART_INFOREQ(Signal*);
- void execSTART_INFOREF(Signal*);
- void execSTART_INFOCONF(Signal*);
- void execWAIT_GCP_REQ(Signal* signal);
- void execWAIT_GCP_REF(Signal* signal);
- void execWAIT_GCP_CONF(Signal* signal);
- void execUPDATE_TOREQ(Signal* signal);
- void execUPDATE_TOCONF(Signal* signal);
-
- void execPREP_DROP_TAB_REQ(Signal* signal);
- void execWAIT_DROP_TAB_REF(Signal* signal);
- void execWAIT_DROP_TAB_CONF(Signal* signal);
- void execDROP_TAB_REQ(Signal* signal);
-
- void execALTER_TAB_REQ(Signal* signal);
-
- void execCREATE_FRAGMENTATION_REQ(Signal*);
-
- void waitDropTabWritingToFile(Signal *, TabRecordPtr tabPtr);
- 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
-//------------------------------------
- void nullRoutine(Signal *, Uint32 nodeId);
- void sendCOPY_GCIREQ(Signal *, Uint32 nodeId);
- void sendDIH_SWITCH_REPLICA_REQ(Signal *, Uint32 nodeId);
- void sendEMPTY_LCP_REQ(Signal *, Uint32 nodeId);
- void sendEND_TOREQ(Signal *, Uint32 nodeId);
- void sendGCP_COMMIT(Signal *, Uint32 nodeId);
- void sendGCP_PREPARE(Signal *, Uint32 nodeId);
- void sendGCP_SAVEREQ(Signal *, Uint32 nodeId);
- void sendINCL_NODEREQ(Signal *, Uint32 nodeId);
- void sendMASTER_GCPREQ(Signal *, Uint32 nodeId);
- void sendMASTER_LCPREQ(Signal *, Uint32 nodeId);
- void sendMASTER_LCPCONF(Signal * signal);
- void sendSTART_RECREQ(Signal *, Uint32 nodeId);
- void sendSTART_INFOREQ(Signal *, Uint32 nodeId);
- void sendSTART_TOREQ(Signal *, Uint32 nodeId);
- void sendSTOP_ME_REQ(Signal *, Uint32 nodeId);
- void sendTC_CLOPSIZEREQ(Signal *, Uint32 nodeId);
- void sendTCGETOPSIZEREQ(Signal *, Uint32 nodeId);
- void sendUPDATE_TOREQ(Signal *, Uint32 nodeId);
- void sendSTART_LCP_REQ(Signal *, Uint32 nodeId);
-
- void sendLCP_FRAG_ORD(Signal*, NodeRecord::FragmentCheckpointInfo info);
- void sendLastLCP_FRAG_ORD(Signal *);
-
- void sendCopyTable(Signal *, CopyTableNode* ctn,
- BlockReference ref, Uint32 reqinfo);
- void sendCreateFragReq(Signal *,
- Uint32 startGci,
- Uint32 storedType,
- Uint32 takeOverPtr);
- void sendDihfragreq(Signal *,
- TabRecordPtr regTabPtr,
- Uint32 fragId);
- void sendStartFragreq(Signal *,
- TabRecordPtr regTabPtr,
- Uint32 fragId);
- void sendHOT_SPAREREP(Signal *);
- void sendAddFragreq(Signal *,
- TabRecordPtr regTabPtr,
- Uint32 fragId,
- Uint32 lcpNo,
- Uint32 param);
-
- void sendAddFragreq(Signal*, ConnectRecordPtr, TabRecordPtr, Uint32 fragId);
- void addTable_closeConf(Signal* signal, Uint32 tabPtrI);
- void resetReplicaSr(TabRecordPtr tabPtr);
- void resetReplicaLcp(ReplicaRecord * replicaP, Uint32 stopGci);
-
-//------------------------------------
-// Methods for LCP functionality
-//------------------------------------
- void checkKeepGci(TabRecordPtr, Uint32, Fragmentstore*, Uint32);
- void checkLcpStart(Signal *, Uint32 lineNo);
- void checkStartMoreLcp(Signal *, Uint32 nodeId);
- bool reportLcpCompletion(const class LcpFragRep *);
- void sendLCP_COMPLETE_REP(Signal *);
-
-//------------------------------------
-// Methods for Delete Table Files
-//------------------------------------
- void startDeleteFile(Signal* signal, TabRecordPtr tabPtr);
- void openTableFileForDelete(Signal* signal, Uint32 fileIndex);
- void tableOpenLab(Signal* signal, FileRecordPtr regFilePtr);
- void tableDeleteLab(Signal* signal, FileRecordPtr regFilePtr);
-
-//------------------------------------
-// File Record specific methods
-//------------------------------------
- void closeFile(Signal *, FileRecordPtr regFilePtr);
- void closeFileDelete(Signal *, FileRecordPtr regFilePtr);
- void createFileRw(Signal *, FileRecordPtr regFilePtr);
- void openFileRw(Signal *, FileRecordPtr regFilePtr);
- void openFileRo(Signal *, FileRecordPtr regFilePtr);
- void seizeFile(FileRecordPtr& regFilePtr);
- void releaseFile(Uint32 fileIndex);
-
-//------------------------------------
-// Methods called when completing file
-// operation.
-//------------------------------------
- void creatingGcpLab(Signal *, FileRecordPtr regFilePtr);
- void openingGcpLab(Signal *, FileRecordPtr regFilePtr);
- void openingTableLab(Signal *, FileRecordPtr regFilePtr);
- void tableCreateLab(Signal *, FileRecordPtr regFilePtr);
- void creatingGcpErrorLab(Signal *, FileRecordPtr regFilePtr);
- void openingCopyGciErrorLab(Signal *, FileRecordPtr regFilePtr);
- void creatingCopyGciErrorLab(Signal *, FileRecordPtr regFilePtr);
- void openingGcpErrorLab(Signal *, FileRecordPtr regFilePtr);
- void openingTableErrorLab(Signal *, FileRecordPtr regFilePtr);
- void tableCreateErrorLab(Signal *, FileRecordPtr regFilePtr);
- void closingGcpLab(Signal *, FileRecordPtr regFilePtr);
- void closingGcpCrashLab(Signal *, FileRecordPtr regFilePtr);
- void closingTableCrashLab(Signal *, FileRecordPtr regFilePtr);
- void closingTableSrLab(Signal *, FileRecordPtr regFilePtr);
- void tableCloseLab(Signal *, FileRecordPtr regFilePtr);
- void tableCloseErrorLab(FileRecordPtr regFilePtr);
- void readingGcpLab(Signal *, FileRecordPtr regFilePtr);
- void readingTableLab(Signal *, FileRecordPtr regFilePtr);
- void readingGcpErrorLab(Signal *, FileRecordPtr regFilePtr);
- void readingTableErrorLab(Signal *, FileRecordPtr regFilePtr);
- void writingCopyGciLab(Signal *, FileRecordPtr regFilePtr);
- void writeInitGcpLab(Signal *, FileRecordPtr regFilePtr);
- void tableWriteLab(Signal *, FileRecordPtr regFilePtr);
- void writeInitGcpErrorLab(Signal *, FileRecordPtr regFilePtr);
-
-
- void calculateHotSpare();
- void checkEscalation();
- void clearRestartInfoBits(Signal *);
- void invalidateLcpInfoAfterSr();
-
- bool isMaster();
- bool isActiveMaster();
-
- void emptyverificbuffer(Signal *, bool aContintueB);
- Uint32 findHotSpare();
- void handleGcpStateInMaster(Signal *, NodeRecordPtr failedNodeptr);
- void initRestartInfo();
- void initRestorableGciFiles();
- void makeNodeGroups(Uint32 nodeArray[]);
- void makePrnList(class ReadNodesConf * readNodes, Uint32 nodeArray[]);
- void nodeResetStart();
- void releaseTabPages(Uint32 tableId);
- void replication(Uint32 noOfReplicas,
- NodeGroupRecordPtr NGPtr,
- FragmentstorePtr regFragptr);
- void selectMasterCandidateAndSend(Signal *);
- void setInitialActiveStatus();
- void setLcpActiveStatusEnd();
- void setLcpActiveStatusStart(Signal *);
- void setNodeActiveStatus();
- void setNodeGroups();
- void setNodeInfo(Signal *);
- void setNodeLcpActiveStatus();
- void setNodeRestartInfoBits();
- void startGcp(Signal *);
-
- void readFragment(RWFragment* rf, FragmentstorePtr regFragptr);
- Uint32 readPageWord(RWFragment* rf);
- void readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr);
- void readReplicas(RWFragment* rf, FragmentstorePtr regFragptr);
- void readRestorableGci(Signal *, FileRecordPtr regFilePtr);
- void readTabfile(Signal *, TabRecord* tab, FileRecordPtr regFilePtr);
- void writeFragment(RWFragment* wf, FragmentstorePtr regFragptr);
- void writePageWord(RWFragment* wf, Uint32 dataWord);
- void writeReplicas(RWFragment* wf, Uint32 replicaStartIndex);
- void writeRestorableGci(Signal *, FileRecordPtr regFilePtr);
- void writeTabfile(Signal *, TabRecord* tab, FileRecordPtr regFilePtr);
- void copyTabReq_complete(Signal* signal, TabRecordPtr tabPtr);
-
- void gcpcommitreqLab(Signal *);
- void gcpsavereqLab(Signal *);
- void copyGciLab(Signal *, CopyGCIReq::CopyReason reason);
- void storeNewLcpIdLab(Signal *);
- void startLcpRoundLoopLab(Signal *, Uint32 startTableId, Uint32 startFragId);
-
- void nodeFailCompletedCheckLab(Signal*, NodeRecordPtr failedNodePtr);
-
- /**
- *
- */
- void setLocalNodefailHandling(Signal*, Uint32 failedNodeId,
- NodefailHandlingStep step);
- void checkLocalNodefailComplete(Signal*, Uint32 failedNodeId,
- NodefailHandlingStep step);
-
- void ndbsttorry10Lab(Signal *, Uint32 _line);
- void createMutexes(Signal* signal, Uint32 no);
- void createMutex_done(Signal* signal, Uint32 no, Uint32 retVal);
- void crashSystemAtGcpStop(Signal *, bool);
- void sendFirstDictfragsreq(Signal *, TabRecordPtr regTabPtr);
- void addtabrefuseLab(Signal *, ConnectRecordPtr regConnectPtr, Uint32 errorCode);
- void GCP_SAVEhandling(Signal *, Uint32 nodeId);
- void packTableIntoPagesLab(Signal *, Uint32 tableId);
- void readPagesIntoTableLab(Signal *, Uint32 tableId);
- void readPagesIntoFragLab(Signal *, RWFragment* rf);
- void readTabDescriptionLab(Signal *, Uint32 tableId);
- void copyTableLab(Signal *, Uint32 tableId);
- void breakCopyTableLab(Signal *,
- TabRecordPtr regTabPtr,
- Uint32 nodeId);
- void checkAddfragCompletedLab(Signal *,
- TabRecordPtr regTabPtr,
- Uint32 fragId);
- void completeRestartLab(Signal *);
- void readTableFromPagesLab(Signal *, TabRecordPtr regTabPtr);
- void srPhase2ReadTableLab(Signal *, TabRecordPtr regTabPtr);
- void checkTcCounterLab(Signal *);
- void calculateKeepGciLab(Signal *, Uint32 tableId, Uint32 fragId);
- void tableUpdateLab(Signal *, TabRecordPtr regTabPtr);
- void checkLcpCompletedLab(Signal *);
- void initLcpLab(Signal *, Uint32 masterRef, Uint32 tableId);
- void startGcpLab(Signal *, Uint32 aWaitTime);
- void checkGcpStopLab(Signal *);
- void MASTER_GCPhandling(Signal *, Uint32 failedNodeId);
- void MASTER_LCPhandling(Signal *, Uint32 failedNodeId);
- void rnfTableNotReadyLab(Signal *, TabRecordPtr regTabPtr, Uint32 removeNodeId);
- void startLcpTakeOverLab(Signal *, Uint32 failedNodeId);
-
- void startLcpMasterTakeOver(Signal *, Uint32 failedNodeId);
- void startGcpMasterTakeOver(Signal *, Uint32 failedNodeId);
- void checkGcpOutstanding(Signal*, Uint32 failedNodeId);
-
- void checkEmptyLcpComplete(Signal *);
- void lcpBlockedLab(Signal *);
- void breakCheckTabCompletedLab(Signal *, TabRecordPtr regTabptr);
- void readGciFileLab(Signal *);
- void openingCopyGciSkipInitLab(Signal *, FileRecordPtr regFilePtr);
- void startLcpRoundLab(Signal *);
- void gcpBlockedLab(Signal *);
- void initialStartCompletedLab(Signal *);
- void allNodesLcpCompletedLab(Signal *);
- void nodeRestartPh2Lab(Signal *);
- void nodeRestartPh2Lab2(Signal *);
- void initGciFilesLab(Signal *);
- void dictStartConfLab(Signal *);
- void nodeDictStartConfLab(Signal *);
- void ndbStartReqLab(Signal *, BlockReference ref);
- void nodeRestartStartRecConfLab(Signal *);
- void dihCopyCompletedLab(Signal *);
- void release_connect(ConnectRecordPtr ptr);
- void copyTableNode(Signal *,
- CopyTableNode* ctn,
- NodeRecordPtr regNodePtr);
- void startFragment(Signal *, Uint32 tableId, Uint32 fragId);
- bool checkLcpAllTablesDoneInLqh();
-
- void lcpStateAtNodeFailureLab(Signal *, Uint32 nodeId);
- void copyNodeLab(Signal *, Uint32 tableId);
- void copyGciReqLab(Signal *);
- void allLab(Signal *,
- ConnectRecordPtr regConnectPtr,
- TabRecordPtr regTabPtr);
- void tableCopyNodeLab(Signal *, TabRecordPtr regTabPtr);
-
- void removeNodeFromTables(Signal *, Uint32 tableId, Uint32 nodeId);
- void removeNodeFromTable(Signal *, Uint32 tableId, TabRecordPtr tabPtr);
- void removeNodeFromTablesComplete(Signal* signal, Uint32 nodeId);
-
- void packFragIntoPagesLab(Signal *, RWFragment* wf);
- void startNextChkpt(Signal *);
- void failedNodeLcpHandling(Signal*, NodeRecordPtr failedNodePtr);
- void failedNodeSynchHandling(Signal *, NodeRecordPtr failedNodePtr);
- void checkCopyTab(NodeRecordPtr failedNodePtr);
-
- void initCommonData();
- void initialiseRecordsLab(Signal *, Uint32 stepNo, Uint32, Uint32);
-
- void findReplica(ReplicaRecordPtr& regReplicaPtr,
- Fragmentstore* fragPtrP,
- Uint32 nodeId,
- bool oldStoredReplicas = false);
-//------------------------------------
-// Node failure handling methods
-//------------------------------------
- void startRemoveFailedNode(Signal *, NodeRecordPtr failedNodePtr);
- void handleGcpTakeOver(Signal *, NodeRecordPtr failedNodePtr);
- void handleLcpTakeOver(Signal *, NodeRecordPtr failedNodePtr);
- void handleNewMaster(Signal *, NodeRecordPtr failedNodePtr);
- void checkTakeOverInMasterAllNodeFailure(Signal*, NodeRecordPtr failedNode);
- void checkTakeOverInMasterCopyNodeFailure(Signal*, Uint32 failedNodeId);
- void checkTakeOverInMasterStartNodeFailure(Signal*, Uint32 takeOverPtr);
- void checkTakeOverInNonMasterStartNodeFailure(Signal*, Uint32 takeOverPtr);
- void handleLcpMasterTakeOver(Signal *, Uint32 nodeId);
-
-//------------------------------------
-// Replica record specific methods
-//------------------------------------
- Uint32 findLogInterval(ConstPtr<ReplicaRecord> regReplicaPtr,
- Uint32 startGci);
- void findMinGci(ReplicaRecordPtr fmgReplicaPtr,
- Uint32& keeGci,
- Uint32& oldestRestorableGci);
- bool findStartGci(ConstPtr<ReplicaRecord> fstReplicaPtr,
- Uint32 tfstStopGci,
- Uint32& tfstStartGci,
- Uint32& tfstLcp);
- void newCrashedReplica(Uint32 nodeId, ReplicaRecordPtr ncrReplicaPtr);
- void packCrashedReplicas(ReplicaRecordPtr pcrReplicaPtr);
- void releaseReplicas(Uint32 replicaPtr);
- void removeOldCrashedReplicas(ReplicaRecordPtr rocReplicaPtr);
- void removeTooNewCrashedReplicas(ReplicaRecordPtr rtnReplicaPtr);
- void seizeReplicaRec(ReplicaRecordPtr& replicaPtr);
-
-//------------------------------------
-// Methods operating on a fragment and
-// its connected replicas and nodes.
-//------------------------------------
- void allocStoredReplica(FragmentstorePtr regFragptr,
- ReplicaRecordPtr& newReplicaPtr,
- Uint32 nodeId);
- Uint32 extractNodeInfo(const Fragmentstore * fragPtr, Uint32 nodes[]);
- bool findBestLogNode(CreateReplicaRecord* createReplica,
- FragmentstorePtr regFragptr,
- Uint32 startGci,
- Uint32 stopGci,
- Uint32 logNode,
- Uint32& fblStopGci);
- bool findLogNodes(CreateReplicaRecord* createReplica,
- FragmentstorePtr regFragptr,
- Uint32 startGci,
- Uint32 stopGci);
- void findToReplica(TakeOverRecord* regTakeOver,
- Uint32 replicaType,
- FragmentstorePtr regFragptr,
- ReplicaRecordPtr& ftrReplicaPtr);
- void initFragstore(FragmentstorePtr regFragptr);
- void insertBackup(FragmentstorePtr regFragptr, Uint32 nodeId);
- void insertfraginfo(FragmentstorePtr regFragptr,
- Uint32 noOfBackups,
- Uint32* nodeArray);
- void linkOldStoredReplica(FragmentstorePtr regFragptr,
- ReplicaRecordPtr replicaPtr);
- void linkStoredReplica(FragmentstorePtr regFragptr,
- ReplicaRecordPtr replicaPtr);
- void prepareReplicas(FragmentstorePtr regFragptr);
- void removeNodeFromStored(Uint32 nodeId,
- FragmentstorePtr regFragptr,
- ReplicaRecordPtr replicaPtr,
- bool temporary);
- void removeOldStoredReplica(FragmentstorePtr regFragptr,
- ReplicaRecordPtr replicaPtr);
- void removeStoredReplica(FragmentstorePtr regFragptr,
- ReplicaRecordPtr replicaPtr);
- void searchStoredReplicas(FragmentstorePtr regFragptr);
- bool setup_create_replica(FragmentstorePtr, CreateReplicaRecord*,
- ConstPtr<ReplicaRecord>);
- void updateNodeInfo(FragmentstorePtr regFragptr);
-
-//------------------------------------
-// Fragment allocation, deallocation and
-// find methods
-//------------------------------------
- void allocFragments(Uint32 noOfFragments, TabRecordPtr regTabPtr);
- void releaseFragments(TabRecordPtr regTabPtr);
- void getFragstore(TabRecord *, Uint32 fragNo, FragmentstorePtr & ptr);
- void initialiseFragstore();
-
-//------------------------------------
-// Page Record specific methods
-//------------------------------------
- void allocpage(PageRecordPtr& regPagePtr);
- void releasePage(Uint32 pageIndex);
-
-//------------------------------------
-// Table Record specific methods
-//------------------------------------
- void initTable(TabRecordPtr regTabPtr);
- void initTableFile(TabRecordPtr regTabPtr);
- void releaseTable(TabRecordPtr tabPtr);
- Uint32 findTakeOver(Uint32 failedNodeId);
- void handleTakeOverMaster(Signal *, Uint32 takeOverPtr);
- void handleTakeOverNewMaster(Signal *, Uint32 takeOverPtr);
-
-//------------------------------------
-// TakeOver Record specific methods
-//------------------------------------
- void initTakeOver(TakeOverRecordPtr regTakeOverptr);
- void seizeTakeOver(TakeOverRecordPtr& regTakeOverptr);
- void allocateTakeOver(TakeOverRecordPtr& regTakeOverptr);
- void releaseTakeOver(Uint32 takeOverPtr);
- bool anyActiveTakeOver();
- void checkToCopy();
- void checkToCopyCompleted(Signal *);
- bool checkToInterrupted(TakeOverRecordPtr& regTakeOverptr);
- Uint32 getStartNode(Uint32 takeOverPtr);
-
-//------------------------------------
-// Methods for take over functionality
-//------------------------------------
- void changeNodeGroups(Uint32 startNode, Uint32 nodeTakenOver);
- void endTakeOver(Uint32 takeOverPtr);
- void initStartTakeOver(const class StartToReq *,
- TakeOverRecordPtr regTakeOverPtr);
-
- void nodeRestartTakeOver(Signal *, Uint32 startNodeId);
- void systemRestartTakeOverLab(Signal *);
- void startTakeOver(Signal *,
- Uint32 takeOverPtr,
- Uint32 startNode,
- Uint32 toNode);
- void sendStartTo(Signal *, Uint32 takeOverPtr);
- void startNextCopyFragment(Signal *, Uint32 takeOverPtr);
- void toCopyFragLab(Signal *, Uint32 takeOverPtr);
- void toStartCopyFrag(Signal *, TakeOverRecordPtr);
- void startHsAddFragConfLab(Signal *);
- void prepareSendCreateFragReq(Signal *, Uint32 takeOverPtr);
- void sendUpdateTo(Signal *, Uint32 takeOverPtr, Uint32 updateState);
- void toCopyCompletedLab(Signal *, TakeOverRecordPtr regTakeOverptr);
- void takeOverCompleted(Uint32 aNodeId);
- void sendEndTo(Signal *, Uint32 takeOverPtr);
-
-//------------------------------------
-// Node Record specific methods
-//------------------------------------
- void checkStartTakeOver(Signal *);
- void insertAlive(NodeRecordPtr newNodePtr);
- void insertDeadNode(NodeRecordPtr removeNodePtr);
- void removeAlive(NodeRecordPtr removeNodePtr);
- void removeDeadNode(NodeRecordPtr removeNodePtr);
-
- NodeRecord::NodeStatus getNodeStatus(Uint32 nodeId);
- void setNodeStatus(Uint32 nodeId, NodeRecord::NodeStatus);
- Sysfile::ActiveStatus getNodeActiveStatus(Uint32 nodeId);
- void setNodeActiveStatus(Uint32 nodeId, Sysfile::ActiveStatus newStatus);
- void setNodeLcpActiveStatus(Uint32 nodeId, bool newState);
- bool getNodeLcpActiveStatus(Uint32 nodeId);
- bool getAllowNodeStart(Uint32 nodeId);
- void setAllowNodeStart(Uint32 nodeId, bool newState);
- bool getNodeCopyCompleted(Uint32 nodeId);
- void setNodeCopyCompleted(Uint32 nodeId, bool newState);
- bool checkNodeAlive(Uint32 nodeId);
-
- void nr_start_fragments(Signal*, TakeOverRecordPtr);
- void nr_start_fragment(Signal*, TakeOverRecordPtr, ReplicaRecordPtr);
- void nr_run_redo(Signal*, TakeOverRecordPtr);
-
- // Initialisation
- void initData();
- void initRecords();
-
- // Variables to support record structures and their free lists
-
- ApiConnectRecord *apiConnectRecord;
- Uint32 capiConnectFileSize;
-
- ConnectRecord *connectRecord;
- Uint32 cfirstconnect;
- Uint32 cconnectFileSize;
-
- CreateReplicaRecord *createReplicaRecord;
- Uint32 cnoOfCreateReplicas;
-
- FileRecord *fileRecord;
- Uint32 cfirstfreeFile;
- Uint32 cfileFileSize;
-
- Fragmentstore *fragmentstore;
- Uint32 cfirstfragstore;
- Uint32 cfragstoreFileSize;
-
- Uint32 c_nextNodeGroup;
- NodeGroupRecord *nodeGroupRecord;
- Uint32 c_nextLogPart;
-
- NodeRecord *nodeRecord;
-
- PageRecord *pageRecord;
- Uint32 cfirstfreepage;
- Uint32 cpageFileSize;
-
- ReplicaRecord *replicaRecord;
- Uint32 cfirstfreeReplica;
- Uint32 cnoFreeReplicaRec;
- Uint32 creplicaFileSize;
-
- TabRecord *tabRecord;
- Uint32 ctabFileSize;
-
- TakeOverRecord *takeOverRecord;
- Uint32 cfirstfreeTakeOver;
-
- /*
- 2.4 C O M M O N S T O R E D V A R I A B L E S
- ----------------------------------------------------
- */
- Uint32 cfirstVerifyQueue;
- Uint32 clastVerifyQueue;
- Uint32 cverifyQueueCounter;
-
- /*------------------------------------------------------------------------*/
- /* THIS VARIABLE KEEPS THE REFERENCES TO FILE RECORDS THAT DESCRIBE */
- /* THE TWO FILES THAT ARE USED TO STORE THE VARIABLE CRESTART_INFO */
- /* ON DISK. */
- /*------------------------------------------------------------------------*/
- Uint32 crestartInfoFile[2];
- /*------------------------------------------------------------------------*/
- /* THIS VARIABLE KEEPS TRACK OF THE STATUS OF A GLOBAL CHECKPOINT */
- /* PARTICIPANT. THIS IS NEEDED TO HANDLE A NODE FAILURE. WHEN A NODE*/
- /* FAILURE OCCURS IT IS EASY THAT THE PROTOCOL STOPS IF NO ACTION IS*/
- /* TAKEN TO PREVENT THIS. THIS VARIABLE ENSURES SUCH ACTION CAN BE */
- /* TAKEN. */
- /*------------------------------------------------------------------------*/
- enum GcpParticipantState {
- GCP_PARTICIPANT_READY = 0,
- GCP_PARTICIPANT_PREPARE_RECEIVED = 1,
- GCP_PARTICIPANT_COMMIT_RECEIVED = 2,
- GCP_PARTICIPANT_TC_FINISHED = 3,
- GCP_PARTICIPANT_COPY_GCI_RECEIVED = 4
- };
- GcpParticipantState cgcpParticipantState;
- /*------------------------------------------------------------------------*/
- /* THESE VARIABLES ARE USED TO CONTROL THAT GCP PROCESSING DO NOT */
- /*STOP FOR SOME REASON. */
- /*------------------------------------------------------------------------*/
- enum GcpStatus {
- GCP_READY = 0,
- GCP_PREPARE_SENT = 1,
- GCP_COMMIT_SENT = 2,
- GCP_NODE_FINISHED = 3,
- GCP_SAVE_LQH_FINISHED = 4
- };
- GcpStatus cgcpStatus;
- Uint32 cgcpStartCounter;
- Uint32 coldGcpStatus;
- Uint32 coldGcpId;
- /*------------------------------------------------------------------------*/
- /* THIS VARIABLE KEEPS TRACK OF THE STATE OF THIS NODE AS MASTER. */
- /*------------------------------------------------------------------------*/
- enum MasterState {
- MASTER_IDLE = 0,
- MASTER_ACTIVE = 1,
- MASTER_TAKE_OVER_GCP = 2
- };
- MasterState cmasterState;
- Uint16 cmasterTakeOverNode;
- /* NODE IS NOT MASTER */
- /* NODE IS ACTIVE AS MASTER */
- /* NODE IS TAKING OVER AS MASTER */
-
- struct CopyGCIMaster {
- CopyGCIMaster(){ m_copyReason = m_waiting = CopyGCIReq::IDLE;}
- /*------------------------------------------------------------------------*/
- /* THIS STATE VARIABLE IS USED TO INDICATE IF COPYING OF RESTART */
- /* INFO WAS STARTED BY A LOCAL CHECKPOINT OR AS PART OF A SYSTEM */
- /* RESTART. */
- /*------------------------------------------------------------------------*/
- CopyGCIReq::CopyReason m_copyReason;
-
- /*------------------------------------------------------------------------*/
- /* COPYING RESTART INFO CAN BE STARTED BY LOCAL CHECKPOINTS AND BY */
- /* GLOBAL CHECKPOINTS. WE CAN HOWEVER ONLY HANDLE ONE SUCH COPY AT */
- /* THE TIME. THUS WE HAVE TO KEEP WAIT INFORMATION IN THIS VARIABLE.*/
- /*------------------------------------------------------------------------*/
- CopyGCIReq::CopyReason m_waiting;
- } c_copyGCIMaster;
-
- struct CopyGCISlave {
- CopyGCISlave(){ m_copyReason = CopyGCIReq::IDLE; m_expectedNextWord = 0;}
- /*------------------------------------------------------------------------*/
- /* THIS STATE VARIABLE IS USED TO INDICATE IF COPYING OF RESTART */
- /* INFO WAS STARTED BY A LOCAL CHECKPOINT OR AS PART OF A SYSTEM */
- /* RESTART. THIS VARIABLE IS USED BY THE NODE THAT RECEIVES */
- /* COPY_GCI_REQ. */
- /*------------------------------------------------------------------------*/
- Uint32 m_senderData;
- BlockReference m_senderRef;
- CopyGCIReq::CopyReason m_copyReason;
-
- Uint32 m_expectedNextWord;
- } c_copyGCISlave;
-
- /*------------------------------------------------------------------------*/
- /* THIS VARIABLE IS USED TO KEEP TRACK OF THE STATE OF LOCAL */
- /* CHECKPOINTS. */
- /*------------------------------------------------------------------------*/
-public:
- enum LcpStatus {
- LCP_STATUS_IDLE = 0,
- LCP_TCGET = 1, // Only master
- LCP_STATUS_ACTIVE = 2,
- LCP_CALCULATE_KEEP_GCI = 4, // Only master
- LCP_COPY_GCI = 5,
- LCP_INIT_TABLES = 6,
- LCP_TC_CLOPSIZE = 7, // Only master
- LCP_START_LCP_ROUND = 8,
- LCP_TAB_COMPLETED = 9,
- LCP_TAB_SAVED = 10
- };
-private:
-
- struct LcpState {
- LcpState() {}
- LcpStatus lcpStatus;
- Uint32 lcpStatusUpdatedPlace;
-
- struct Save {
- LcpStatus m_status;
- Uint32 m_place;
- } m_saveState[10];
-
- void setLcpStatus(LcpStatus status, Uint32 line){
- for (Uint32 i = 9; i > 0; i--)
- m_saveState[i] = m_saveState[i-1];
- m_saveState[0].m_status = lcpStatus;
- m_saveState[0].m_place = lcpStatusUpdatedPlace;
-
- lcpStatus = status;
- lcpStatusUpdatedPlace = line;
- }
-
- Uint32 lcpStart;
- Uint32 lcpStopGcp;
- Uint32 keepGci; /* USED TO CALCULATE THE GCI TO KEEP AFTER A LCP */
- Uint32 oldestRestorableGci;
-
- struct CurrentFragment {
- Uint32 tableId;
- Uint32 fragmentId;
- } currentFragment;
-
- Uint32 noOfLcpFragRepOutstanding;
-
- /*------------------------------------------------------------------------*/
- /* USED TO ENSURE THAT LCP'S ARE EXECUTED WITH CERTAIN TIMEINTERVALS*/
- /* EVEN WHEN SYSTEM IS NOT DOING ANYTHING. */
- /*------------------------------------------------------------------------*/
- Uint32 ctimer;
- Uint32 ctcCounter;
- Uint32 clcpDelay; /* MAX. 2^(CLCP_DELAY - 2) SEC BETWEEN LCP'S */
-
- /*------------------------------------------------------------------------*/
- /* THIS STATE IS USED TO TELL IF THE FIRST LCP AFTER START/RESTART */
- /* HAS BEEN RUN. AFTER A NODE RESTART THE NODE DOES NOT ENTER */
- /* STARTED STATE BEFORE THIS IS DONE. */
- /*------------------------------------------------------------------------*/
- bool immediateLcpStart;
- bool m_LCP_COMPLETE_REP_From_Master_Received;
- SignalCounter m_LCP_COMPLETE_REP_Counter_DIH;
- SignalCounter m_LCP_COMPLETE_REP_Counter_LQH;
- SignalCounter m_LAST_LCP_FRAG_ORD;
- NdbNodeBitmask m_participatingLQH;
- NdbNodeBitmask m_participatingDIH;
-
- Uint32 m_masterLcpDihRef;
- bool m_MASTER_LCPREQ_Received;
- Uint32 m_MASTER_LCPREQ_FailedNodeId;
- } c_lcpState;
-
- /*------------------------------------------------------------------------*/
- /* THIS VARIABLE KEEPS TRACK OF HOW MANY TABLES ARE ACTIVATED WHEN */
- /* STARTING A LOCAL CHECKPOINT WE SHOULD AVOID STARTING A CHECKPOINT*/
- /* WHEN NO TABLES ARE ACTIVATED. */
- /*------------------------------------------------------------------------*/
- Uint32 cnoOfActiveTables;
- Uint32 cgcpDelay; /* Delay between global checkpoints */
-
- BlockReference cdictblockref; /* DICTIONARY BLOCK REFERENCE */
- Uint32 cfailurenr; /* EVERY TIME WHEN A NODE FAILURE IS REPORTED
- THIS NUMBER IS INCREMENTED. AT THE START OF
- THE SYSTEM THIS NUMBER MUST BE INITIATED TO
- ZERO */
- bool cgckptflag; /* A FLAG WHICH IS SET WHILE A NEW GLOBAL CHECK
- POINT IS BEING CREATED. NO VERIFICATION IS ALLOWED
- IF THE FLAG IS SET*/
- Uint32 cgcpOrderBlocked;
- BlockReference clocallqhblockref;
- BlockReference clocaltcblockref;
- BlockReference cmasterdihref;
- Uint16 cownNodeId;
- Uint32 cnewgcp;
- BlockReference cndbStartReqBlockref;
- BlockReference cntrlblockref;
- Uint32 cgcpSameCounter;
- Uint32 coldgcp;
- Uint32 con_lineNodes;
- Uint32 creceivedfrag;
- Uint32 cremainingfrags;
- Uint32 cstarttype;
- Uint32 csystemnodes;
- Uint32 currentgcp;
- Uint32 c_newest_restorable_gci;
- Uint32 c_set_initial_start_flag;
-
- enum GcpMasterTakeOverState {
- GMTOS_IDLE = 0,
- GMTOS_INITIAL = 1,
- ALL_READY = 2,
- ALL_PREPARED = 3,
- COMMIT_STARTED_NOT_COMPLETED = 4,
- COMMIT_COMPLETED = 5,
- PREPARE_STARTED_NOT_COMMITTED = 6,
- SAVE_STARTED_NOT_COMPLETED = 7
- };
- GcpMasterTakeOverState cgcpMasterTakeOverState;
-
-public:
- enum LcpMasterTakeOverState {
- LMTOS_IDLE = 0,
- LMTOS_WAIT_EMPTY_LCP = 1, // Currently doing empty LCP
- LMTOS_WAIT_LCP_FRAG_REP = 2,// Currently waiting for outst. LCP_FRAG_REP
- LMTOS_INITIAL = 3,
- LMTOS_ALL_IDLE = 4,
- LMTOS_ALL_ACTIVE = 5,
- LMTOS_LCP_CONCLUDING = 6,
- LMTOS_COPY_ONGOING = 7
- };
-private:
- class MasterTakeOverState {
- public:
- MasterTakeOverState() {}
- void set(LcpMasterTakeOverState s, Uint32 line) {
- state = s; updatePlace = line;
- }
-
- LcpMasterTakeOverState state;
- Uint32 updatePlace;
-
- Uint32 minTableId;
- Uint32 minFragId;
- Uint32 failedNodeId;
- } c_lcpMasterTakeOverState;
-
- Uint16 cmasterNodeId;
- Uint8 cnoHotSpare;
-
- struct NodeStartMasterRecord {
- Uint32 startNode;
- Uint32 wait;
- Uint32 failNr;
- bool activeState;
- bool blockLcp;
- bool blockGcp;
- Uint32 startInfoErrorCode;
- Uint32 m_outstandingGsn;
- };
- NodeStartMasterRecord c_nodeStartMaster;
-
- struct NodeStartSlaveRecord {
- NodeStartSlaveRecord() { nodeId = 0;}
-
- Uint32 nodeId;
- };
- NodeStartSlaveRecord c_nodeStartSlave;
-
- Uint32 cfirstAliveNode;
- Uint32 cfirstDeadNode;
- Uint32 cstartPhase;
- Uint32 cnoReplicas;
-
- Uint32 c_startToLock;
- Uint32 c_endToLock;
- Uint32 c_createFragmentLock;
- Uint32 c_updateToLock;
-
- bool cwaitLcpSr;
- Uint32 cnoOfNodeGroups;
- bool cstartGcpNow;
-
- Uint32 crestartGci; /* VALUE OF GCI WHEN SYSTEM RESTARTED OR STARTED */
- Uint32 cminHotSpareNodes;
-
- /**
- * Counter variables keeping track of the number of outstanding signals
- * for particular signals in various protocols.
- */
- SignalCounter c_COPY_GCIREQ_Counter;
- SignalCounter c_COPY_TABREQ_Counter;
- SignalCounter c_CREATE_FRAGREQ_Counter;
- SignalCounter c_DIH_SWITCH_REPLICA_REQ_Counter;
- SignalCounter c_EMPTY_LCP_REQ_Counter;
- SignalCounter c_END_TOREQ_Counter;
- SignalCounter c_GCP_COMMIT_Counter;
- SignalCounter c_GCP_PREPARE_Counter;
- SignalCounter c_GCP_SAVEREQ_Counter;
- SignalCounter c_INCL_NODEREQ_Counter;
- SignalCounter c_MASTER_GCPREQ_Counter;
- SignalCounter c_MASTER_LCPREQ_Counter;
- SignalCounter c_START_INFOREQ_Counter;
- SignalCounter c_START_RECREQ_Counter;
- SignalCounter c_START_TOREQ_Counter;
- SignalCounter c_STOP_ME_REQ_Counter;
- SignalCounter c_TC_CLOPSIZEREQ_Counter;
- SignalCounter c_TCGETOPSIZEREQ_Counter;
- SignalCounter c_UPDATE_TOREQ_Counter;
- SignalCounter c_START_LCP_REQ_Counter;
-
- bool c_blockCommit;
- Uint32 c_blockCommitNo;
-
- bool getBlockCommit() const {
- return c_blockCommit || cgckptflag;
- }
-
- /**
- * SwitchReplicaRecord - Should only be used by master
- */
- struct SwitchReplicaRecord {
- SwitchReplicaRecord() {}
- void clear(){}
-
- Uint32 nodeId;
- Uint32 tableId;
- Uint32 fragNo;
- };
- SwitchReplicaRecord c_switchReplicas;
-
- struct StopPermProxyRecord {
- StopPermProxyRecord() { clientRef = 0; }
-
- Uint32 clientData;
- BlockReference clientRef;
- BlockReference masterRef;
- };
-
- struct StopPermMasterRecord {
- StopPermMasterRecord() { clientRef = 0;}
-
- Uint32 returnValue;
-
- Uint32 clientData;
- BlockReference clientRef;
- };
-
- StopPermProxyRecord c_stopPermProxy;
- StopPermMasterRecord c_stopPermMaster;
-
- void checkStopPermProxy(Signal*, NodeId failedNodeId);
- void checkStopPermMaster(Signal*, NodeRecordPtr failedNodePtr);
-
- void switchReplica(Signal*,
- Uint32 nodeId,
- Uint32 tableId,
- Uint32 fragNo);
-
- void switchReplicaReply(Signal*, NodeId nodeId);
-
- /**
- * Wait GCP (proxy)
- */
- struct WaitGCPProxyRecord {
- WaitGCPProxyRecord() { clientRef = 0;}
-
- Uint32 clientData;
- BlockReference clientRef;
- BlockReference masterRef;
-
- union { Uint32 nextPool; Uint32 nextList; };
- Uint32 prevList;
- };
- typedef Ptr<WaitGCPProxyRecord> WaitGCPProxyPtr;
-
- /**
- * Wait GCP (master)
- */
- struct WaitGCPMasterRecord {
- WaitGCPMasterRecord() { clientRef = 0;}
- Uint32 clientData;
- BlockReference clientRef;
-
- union { Uint32 nextPool; Uint32 nextList; };
- Uint32 prevList;
- };
- typedef Ptr<WaitGCPMasterRecord> WaitGCPMasterPtr;
-
- /**
- * Pool/list of WaitGCPProxyRecord record
- */
- ArrayPool<WaitGCPProxyRecord> waitGCPProxyPool;
- DLList<WaitGCPProxyRecord> c_waitGCPProxyList;
-
- /**
- * Pool/list of WaitGCPMasterRecord record
- */
- ArrayPool<WaitGCPMasterRecord> waitGCPMasterPool;
- DLList<WaitGCPMasterRecord> c_waitGCPMasterList;
-
- void checkWaitGCPProxy(Signal*, NodeId failedNodeId);
- void checkWaitGCPMaster(Signal*, NodeId failedNodeId);
- void emptyWaitGCPMasterQueue(Signal*);
-
- /**
- * Stop me
- */
- struct StopMeRecord {
- StopMeRecord() { clientRef = 0;}
-
- BlockReference clientRef;
- Uint32 clientData;
- };
- StopMeRecord c_stopMe;
-
- void checkStopMe(Signal *, NodeRecordPtr failedNodePtr);
-
-#define DIH_CDATA_SIZE 128
- /**
- * This variable must be atleast the size of Sysfile::SYSFILE_SIZE32
- */
- Uint32 cdata[DIH_CDATA_SIZE]; /* TEMPORARY ARRAY VARIABLE */
-
- /**
- * Sys file data
- */
- Uint32 sysfileData[DIH_CDATA_SIZE];
- Uint32 sysfileDataToFile[DIH_CDATA_SIZE];
-
- /**
- * When a node comes up without filesystem
- * we have to clear all LCP for that node
- */
- void invalidateNodeLCP(Signal *, Uint32 nodeId, Uint32 tableId);
- void invalidateNodeLCP(Signal *, Uint32 nodeId, TabRecordPtr);
-
- /**
- * Reply from nodeId
- */
- void startInfoReply(Signal *, Uint32 nodeId);
-
- void dump_replica_info();
-
- // DIH specifics for execNODE_START_REP (sendDictUnlockOrd)
- void execNODE_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);
-
- Uint32 c_error_7181_ref;
-};
-
-#if (DIH_CDATA_SIZE < _SYSFILE_SIZE32)
-#error "cdata is to small compared to Sysfile size"
-#endif
-
-#endif
-
diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
deleted file mode 100644
index 5560c94cbfa..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBDIH_C
-#include "Dbdih.hpp"
-#include <ndb_limits.h>
-
-#define DEBUG(x) { ndbout << "DIH::" << x << endl; }
-
-void Dbdih::initData()
-{
- cpageFileSize = ZPAGEREC;
-
- // Records with constant sizes
- createReplicaRecord = (CreateReplicaRecord*)
- allocRecord("CreateReplicaRecord", sizeof(CreateReplicaRecord),
- ZCREATE_REPLICA_FILE_SIZE);
-
- nodeGroupRecord = (NodeGroupRecord*)
- allocRecord("NodeGroupRecord", sizeof(NodeGroupRecord), MAX_NDB_NODES);
-
- nodeRecord = (NodeRecord*)
- allocRecord("NodeRecord", sizeof(NodeRecord), MAX_NDB_NODES);
-
- Uint32 i;
- for(i = 0; i<MAX_NDB_NODES; i++){
- new (&nodeRecord[i]) NodeRecord();
- }
-
- takeOverRecord = (TakeOverRecord*)allocRecord("TakeOverRecord",
- sizeof(TakeOverRecord),
- MAX_NDB_NODES);
- for(i = 0; i<MAX_NDB_NODES; i++)
- new (&takeOverRecord[i]) TakeOverRecord();
-
- for(i = 0; i<MAX_NDB_NODES; i++)
- new (&takeOverRecord[i]) TakeOverRecord();
-
- 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;
- c_set_initial_start_flag = FALSE;
-}//Dbdih::initData()
-
-void Dbdih::initRecords()
-{
- // Records with dynamic sizes
- apiConnectRecord = (ApiConnectRecord*)
- allocRecord("ApiConnectRecord",
- sizeof(ApiConnectRecord),
- capiConnectFileSize);
-
- connectRecord = (ConnectRecord*)allocRecord("ConnectRecord",
- sizeof(ConnectRecord),
- cconnectFileSize);
-
- fileRecord = (FileRecord*)allocRecord("FileRecord",
- sizeof(FileRecord),
- cfileFileSize);
-
- fragmentstore = (Fragmentstore*)allocRecord("Fragmentstore",
- sizeof(Fragmentstore),
- cfragstoreFileSize);
-
- pageRecord = (PageRecord*)allocRecord("PageRecord",
- sizeof(PageRecord),
- cpageFileSize);
-
- replicaRecord = (ReplicaRecord*)allocRecord("ReplicaRecord",
- sizeof(ReplicaRecord),
- creplicaFileSize);
-
- tabRecord = (TabRecord*)allocRecord("TabRecord",
- sizeof(TabRecord),
- ctabFileSize);
-
- // Initialize BAT for interface to file system
- NewVARIABLE* bat = allocateBat(22);
- bat[1].WA = &pageRecord->word[0];
- bat[1].nrr = cpageFileSize;
- bat[1].ClusterSize = sizeof(PageRecord);
- bat[1].bits.q = 11;
- bat[1].bits.v = 5;
- bat[20].WA = &sysfileData[0];
- bat[20].nrr = 1;
- bat[20].ClusterSize = sizeof(sysfileData);
- bat[20].bits.q = 7;
- bat[20].bits.v = 5;
- bat[21].WA = &sysfileDataToFile[0];
- bat[21].nrr = 1;
- bat[21].ClusterSize = sizeof(sysfileDataToFile);
- bat[21].bits.q = 7;
- bat[21].bits.v = 5;
-}//Dbdih::initRecords()
-
-Dbdih::Dbdih(Block_context& ctx):
- SimulatedBlock(DBDIH, ctx),
- c_waitGCPProxyList(waitGCPProxyPool),
- c_waitGCPMasterList(waitGCPMasterPool)
-{
- BLOCK_CONSTRUCTOR(Dbdih);
-
- addRecSignal(GSN_DUMP_STATE_ORD, &Dbdih::execDUMP_STATE_ORD);
- addRecSignal(GSN_NDB_TAMPER, &Dbdih::execNDB_TAMPER, true);
- addRecSignal(GSN_DEBUG_SIG, &Dbdih::execDEBUG_SIG);
- addRecSignal(GSN_MASTER_GCPREQ, &Dbdih::execMASTER_GCPREQ);
- addRecSignal(GSN_MASTER_GCPREF, &Dbdih::execMASTER_GCPREF);
- addRecSignal(GSN_MASTER_GCPCONF, &Dbdih::execMASTER_GCPCONF);
- addRecSignal(GSN_EMPTY_LCP_CONF, &Dbdih::execEMPTY_LCP_CONF);
- addRecSignal(GSN_MASTER_LCPREQ, &Dbdih::execMASTER_LCPREQ);
- addRecSignal(GSN_MASTER_LCPREF, &Dbdih::execMASTER_LCPREF);
- addRecSignal(GSN_MASTER_LCPCONF, &Dbdih::execMASTER_LCPCONF);
- addRecSignal(GSN_NF_COMPLETEREP, &Dbdih::execNF_COMPLETEREP);
- addRecSignal(GSN_START_PERMREQ, &Dbdih::execSTART_PERMREQ);
- addRecSignal(GSN_START_PERMCONF, &Dbdih::execSTART_PERMCONF);
- addRecSignal(GSN_START_PERMREF, &Dbdih::execSTART_PERMREF);
- addRecSignal(GSN_INCL_NODEREQ, &Dbdih::execINCL_NODEREQ);
- addRecSignal(GSN_INCL_NODECONF, &Dbdih::execINCL_NODECONF);
- addRecSignal(GSN_END_TOREQ, &Dbdih::execEND_TOREQ);
- addRecSignal(GSN_END_TOCONF, &Dbdih::execEND_TOCONF);
- addRecSignal(GSN_START_TOREQ, &Dbdih::execSTART_TOREQ);
- addRecSignal(GSN_START_TOCONF, &Dbdih::execSTART_TOCONF);
- addRecSignal(GSN_START_MEREQ, &Dbdih::execSTART_MEREQ);
- addRecSignal(GSN_START_MECONF, &Dbdih::execSTART_MECONF);
- addRecSignal(GSN_START_MEREF, &Dbdih::execSTART_MEREF);
- addRecSignal(GSN_START_COPYREQ, &Dbdih::execSTART_COPYREQ);
- addRecSignal(GSN_START_COPYCONF, &Dbdih::execSTART_COPYCONF);
- addRecSignal(GSN_START_COPYREF, &Dbdih::execSTART_COPYREF);
- addRecSignal(GSN_CREATE_FRAGREQ, &Dbdih::execCREATE_FRAGREQ);
- addRecSignal(GSN_CREATE_FRAGCONF, &Dbdih::execCREATE_FRAGCONF);
- addRecSignal(GSN_DIVERIFYREQ, &Dbdih::execDIVERIFYREQ);
- addRecSignal(GSN_GCP_SAVECONF, &Dbdih::execGCP_SAVECONF);
- addRecSignal(GSN_GCP_PREPARECONF, &Dbdih::execGCP_PREPARECONF);
- addRecSignal(GSN_GCP_PREPARE, &Dbdih::execGCP_PREPARE);
- addRecSignal(GSN_GCP_NODEFINISH, &Dbdih::execGCP_NODEFINISH);
- addRecSignal(GSN_GCP_COMMIT, &Dbdih::execGCP_COMMIT);
- addRecSignal(GSN_DIHNDBTAMPER, &Dbdih::execDIHNDBTAMPER);
- addRecSignal(GSN_CONTINUEB, &Dbdih::execCONTINUEB);
- addRecSignal(GSN_COPY_GCIREQ, &Dbdih::execCOPY_GCIREQ);
- addRecSignal(GSN_COPY_GCICONF, &Dbdih::execCOPY_GCICONF);
- addRecSignal(GSN_COPY_TABREQ, &Dbdih::execCOPY_TABREQ);
- addRecSignal(GSN_COPY_TABCONF, &Dbdih::execCOPY_TABCONF);
- addRecSignal(GSN_TCGETOPSIZECONF, &Dbdih::execTCGETOPSIZECONF);
- addRecSignal(GSN_TC_CLOPSIZECONF, &Dbdih::execTC_CLOPSIZECONF);
-
- addRecSignal(GSN_LCP_COMPLETE_REP, &Dbdih::execLCP_COMPLETE_REP);
- addRecSignal(GSN_LCP_FRAG_REP, &Dbdih::execLCP_FRAG_REP);
- addRecSignal(GSN_START_LCP_REQ, &Dbdih::execSTART_LCP_REQ);
- addRecSignal(GSN_START_LCP_CONF, &Dbdih::execSTART_LCP_CONF);
-
- addRecSignal(GSN_READ_CONFIG_REQ, &Dbdih::execREAD_CONFIG_REQ, true);
- addRecSignal(GSN_UNBLO_DICTCONF, &Dbdih::execUNBLO_DICTCONF);
- addRecSignal(GSN_COPY_ACTIVECONF, &Dbdih::execCOPY_ACTIVECONF);
- addRecSignal(GSN_TAB_COMMITREQ, &Dbdih::execTAB_COMMITREQ);
- addRecSignal(GSN_NODE_FAILREP, &Dbdih::execNODE_FAILREP);
- addRecSignal(GSN_COPY_FRAGCONF, &Dbdih::execCOPY_FRAGCONF);
- addRecSignal(GSN_COPY_FRAGREF, &Dbdih::execCOPY_FRAGREF);
- addRecSignal(GSN_DIADDTABREQ, &Dbdih::execDIADDTABREQ);
- addRecSignal(GSN_DIGETNODESREQ, &Dbdih::execDIGETNODESREQ);
- addRecSignal(GSN_DIRELEASEREQ, &Dbdih::execDIRELEASEREQ);
- addRecSignal(GSN_DISEIZEREQ, &Dbdih::execDISEIZEREQ);
- addRecSignal(GSN_STTOR, &Dbdih::execSTTOR);
- addRecSignal(GSN_DI_FCOUNTREQ, &Dbdih::execDI_FCOUNTREQ);
- addRecSignal(GSN_DIGETPRIMREQ, &Dbdih::execDIGETPRIMREQ);
- addRecSignal(GSN_GCP_SAVEREF, &Dbdih::execGCP_SAVEREF);
- addRecSignal(GSN_GCP_TCFINISHED, &Dbdih::execGCP_TCFINISHED);
- addRecSignal(GSN_READ_NODESCONF, &Dbdih::execREAD_NODESCONF);
- addRecSignal(GSN_NDB_STTOR, &Dbdih::execNDB_STTOR);
- addRecSignal(GSN_DICTSTARTCONF, &Dbdih::execDICTSTARTCONF);
- addRecSignal(GSN_NDB_STARTREQ, &Dbdih::execNDB_STARTREQ);
- addRecSignal(GSN_GETGCIREQ, &Dbdih::execGETGCIREQ);
- addRecSignal(GSN_DIH_RESTARTREQ, &Dbdih::execDIH_RESTARTREQ);
- addRecSignal(GSN_START_RECCONF, &Dbdih::execSTART_RECCONF);
- addRecSignal(GSN_START_FRAGCONF, &Dbdih::execSTART_FRAGCONF);
- addRecSignal(GSN_ADD_FRAGCONF, &Dbdih::execADD_FRAGCONF);
- addRecSignal(GSN_ADD_FRAGREF, &Dbdih::execADD_FRAGREF);
- addRecSignal(GSN_FSOPENCONF, &Dbdih::execFSOPENCONF);
- addRecSignal(GSN_FSOPENREF, &Dbdih::execFSOPENREF, true);
- addRecSignal(GSN_FSCLOSECONF, &Dbdih::execFSCLOSECONF);
- addRecSignal(GSN_FSCLOSEREF, &Dbdih::execFSCLOSEREF, true);
- addRecSignal(GSN_FSREADCONF, &Dbdih::execFSREADCONF);
- addRecSignal(GSN_FSREADREF, &Dbdih::execFSREADREF, true);
- addRecSignal(GSN_FSWRITECONF, &Dbdih::execFSWRITECONF);
- addRecSignal(GSN_FSWRITEREF, &Dbdih::execFSWRITEREF, true);
-
- addRecSignal(GSN_START_INFOREQ,
- &Dbdih::execSTART_INFOREQ);
- addRecSignal(GSN_START_INFOREF,
- &Dbdih::execSTART_INFOREF);
- addRecSignal(GSN_START_INFOCONF,
- &Dbdih::execSTART_INFOCONF);
-
- addRecSignal(GSN_CHECKNODEGROUPSREQ, &Dbdih::execCHECKNODEGROUPSREQ);
-
- addRecSignal(GSN_BLOCK_COMMIT_ORD,
- &Dbdih::execBLOCK_COMMIT_ORD);
- addRecSignal(GSN_UNBLOCK_COMMIT_ORD,
- &Dbdih::execUNBLOCK_COMMIT_ORD);
-
- addRecSignal(GSN_DIH_SWITCH_REPLICA_REQ,
- &Dbdih::execDIH_SWITCH_REPLICA_REQ);
-
- addRecSignal(GSN_DIH_SWITCH_REPLICA_REF,
- &Dbdih::execDIH_SWITCH_REPLICA_REF);
-
- addRecSignal(GSN_DIH_SWITCH_REPLICA_CONF,
- &Dbdih::execDIH_SWITCH_REPLICA_CONF);
-
- addRecSignal(GSN_STOP_PERM_REQ, &Dbdih::execSTOP_PERM_REQ);
- addRecSignal(GSN_STOP_PERM_REF, &Dbdih::execSTOP_PERM_REF);
- addRecSignal(GSN_STOP_PERM_CONF, &Dbdih::execSTOP_PERM_CONF);
-
- addRecSignal(GSN_STOP_ME_REQ, &Dbdih::execSTOP_ME_REQ);
- addRecSignal(GSN_STOP_ME_REF, &Dbdih::execSTOP_ME_REF);
- addRecSignal(GSN_STOP_ME_CONF, &Dbdih::execSTOP_ME_CONF);
-
- addRecSignal(GSN_WAIT_GCP_REQ, &Dbdih::execWAIT_GCP_REQ);
- addRecSignal(GSN_WAIT_GCP_REF, &Dbdih::execWAIT_GCP_REF);
- addRecSignal(GSN_WAIT_GCP_CONF, &Dbdih::execWAIT_GCP_CONF);
-
- addRecSignal(GSN_UPDATE_TOREQ, &Dbdih::execUPDATE_TOREQ);
- addRecSignal(GSN_UPDATE_TOCONF, &Dbdih::execUPDATE_TOCONF);
-
- addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdih::execPREP_DROP_TAB_REQ);
- addRecSignal(GSN_WAIT_DROP_TAB_REF, &Dbdih::execWAIT_DROP_TAB_REF);
- addRecSignal(GSN_WAIT_DROP_TAB_CONF, &Dbdih::execWAIT_DROP_TAB_CONF);
- addRecSignal(GSN_DROP_TAB_REQ, &Dbdih::execDROP_TAB_REQ);
-
- addRecSignal(GSN_ALTER_TAB_REQ, &Dbdih::execALTER_TAB_REQ);
-
- addRecSignal(GSN_CREATE_FRAGMENTATION_REQ,
- &Dbdih::execCREATE_FRAGMENTATION_REQ);
-
- addRecSignal(GSN_DICT_LOCK_CONF, &Dbdih::execDICT_LOCK_CONF);
- addRecSignal(GSN_DICT_LOCK_REF, &Dbdih::execDICT_LOCK_REF);
- addRecSignal(GSN_NODE_START_REP, &Dbdih::execNODE_START_REP, true);
-
- addRecSignal(GSN_START_FRAGREF,
- &Dbdih::execSTART_FRAGREF);
-
- addRecSignal(GSN_PREPARE_COPY_FRAG_REF,
- &Dbdih::execPREPARE_COPY_FRAG_REF);
- addRecSignal(GSN_PREPARE_COPY_FRAG_CONF,
- &Dbdih::execPREPARE_COPY_FRAG_CONF);
-
- apiConnectRecord = 0;
- connectRecord = 0;
- fileRecord = 0;
- fragmentstore = 0;
- pageRecord = 0;
- replicaRecord = 0;
- tabRecord = 0;
- takeOverRecord = 0;
- createReplicaRecord = 0;
- nodeGroupRecord = 0;
- nodeRecord = 0;
- c_nextNodeGroup = 0;
-}//Dbdih::Dbdih()
-
-Dbdih::~Dbdih()
-{
- deallocRecord((void **)&apiConnectRecord, "ApiConnectRecord",
- sizeof(ApiConnectRecord),
- capiConnectFileSize);
-
- deallocRecord((void **)&connectRecord, "ConnectRecord",
- sizeof(ConnectRecord),
- cconnectFileSize);
-
- deallocRecord((void **)&fileRecord, "FileRecord",
- sizeof(FileRecord),
- cfileFileSize);
-
- deallocRecord((void **)&fragmentstore, "Fragmentstore",
- sizeof(Fragmentstore),
- cfragstoreFileSize);
-
- deallocRecord((void **)&pageRecord, "PageRecord",
- sizeof(PageRecord),
- cpageFileSize);
-
- deallocRecord((void **)&replicaRecord, "ReplicaRecord",
- sizeof(ReplicaRecord),
- creplicaFileSize);
-
- deallocRecord((void **)&tabRecord, "TabRecord",
- sizeof(TabRecord),
- ctabFileSize);
-
- // Records with constant sizes
- deallocRecord((void **)&createReplicaRecord,
- "CreateReplicaRecord", sizeof(CreateReplicaRecord),
- ZCREATE_REPLICA_FILE_SIZE);
-
- deallocRecord((void **)&nodeGroupRecord, "NodeGroupRecord",
- sizeof(NodeGroupRecord), MAX_NDB_NODES);
-
- deallocRecord((void **)&nodeRecord, "NodeRecord",
- sizeof(NodeRecord), MAX_NDB_NODES);
-
- deallocRecord((void **)&takeOverRecord, "TakeOverRecord",
- sizeof(TakeOverRecord),
- MAX_NDB_NODES);
-
-}//Dbdih::~Dbdih()
-
-BLOCK_FUNCTIONS(Dbdih)
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
deleted file mode 100644
index fb936fed464..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ /dev/null
@@ -1,15878 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBDIH_C
-#include <ndb_limits.h>
-#include <ndb_version.h>
-#include <NdbOut.hpp>
-
-#include "Dbdih.hpp"
-#include "Configuration.hpp"
-
-#include <signaldata/BlockCommitOrd.hpp>
-#include <signaldata/CheckNodeGroups.hpp>
-#include <signaldata/CreateFrag.hpp>
-#include <signaldata/CopyActive.hpp>
-#include <signaldata/CopyFrag.hpp>
-#include <signaldata/CopyGCIReq.hpp>
-#include <signaldata/DiAddTab.hpp>
-#include <signaldata/DictStart.hpp>
-#include <signaldata/DiGetNodes.hpp>
-#include <signaldata/DihContinueB.hpp>
-#include <signaldata/DihSwitchReplica.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/EmptyLcp.hpp>
-#include <signaldata/EndTo.hpp>
-#include <signaldata/EventReport.hpp>
-#include <signaldata/GCPSave.hpp>
-#include <signaldata/HotSpareRep.hpp>
-#include <signaldata/MasterGCP.hpp>
-#include <signaldata/MasterLCP.hpp>
-#include <signaldata/NFCompleteRep.hpp>
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/StartFragReq.hpp>
-#include <signaldata/StartInfo.hpp>
-#include <signaldata/StartMe.hpp>
-#include <signaldata/StartPerm.hpp>
-#include <signaldata/StartRec.hpp>
-#include <signaldata/StartTo.hpp>
-#include <signaldata/StopPerm.hpp>
-#include <signaldata/StopMe.hpp>
-#include <signaldata/TestOrd.hpp>
-#include <signaldata/UpdateTo.hpp>
-#include <signaldata/WaitGCP.hpp>
-#include <signaldata/DihStartTab.hpp>
-#include <signaldata/LCP.hpp>
-#include <signaldata/SystemError.hpp>
-
-#include <signaldata/DropTab.hpp>
-#include <signaldata/AlterTab.hpp>
-#include <signaldata/PrepDropTab.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/CreateFragmentation.hpp>
-#include <signaldata/LqhFrag.hpp>
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/DihFragCount.hpp>
-#include <signaldata/DictLock.hpp>
-#include <DebuggerNames.hpp>
-
-#include <EventLogger.hpp>
-extern EventLogger g_eventLogger;
-
-#define SYSFILE ((Sysfile *)&sysfileData[0])
-
-#define RETURN_IF_NODE_NOT_ALIVE(node) \
- if (!checkNodeAlive((node))) { \
- jam(); \
- return; \
- } \
-
-#define RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverIndex, regTOPtr) \
- regTOPtr.i = takeOverIndex; \
- ptrCheckGuard(regTOPtr, MAX_NDB_NODES, takeOverRecord); \
- if (checkToInterrupted(regTOPtr)) { \
- jam(); \
- return; \
- } \
-
-#define receiveLoopMacro(sigName, receiveNodeId)\
-{ \
- c_##sigName##_Counter.clearWaitingFor(receiveNodeId); \
- if(c_##sigName##_Counter.done() == false){ \
- jam(); \
- return; \
- } \
-}
-
-#define sendLoopMacro(sigName, signalRoutine) \
-{ \
- c_##sigName##_Counter.clearWaitingFor(); \
- NodeRecordPtr specNodePtr; \
- specNodePtr.i = cfirstAliveNode; \
- do { \
- jam(); \
- ptrCheckGuard(specNodePtr, MAX_NDB_NODES, nodeRecord); \
- c_##sigName##_Counter.setWaitingFor(specNodePtr.i); \
- signalRoutine(signal, specNodePtr.i); \
- specNodePtr.i = specNodePtr.p->nextNode; \
- } while (specNodePtr.i != RNIL); \
-}
-
-static
-Uint32
-prevLcpNo(Uint32 lcpNo){
- if(lcpNo == 0)
- return MAX_LCP_STORED - 1;
- return lcpNo - 1;
-}
-
-static
-Uint32
-nextLcpNo(Uint32 lcpNo){
- lcpNo++;
- if(lcpNo == MAX_LCP_STORED)
- return 0;
- return lcpNo;
-}
-
-#define gth(x, y) ndbrequire(((int)x)>((int)y))
-
-void Dbdih::nullRoutine(Signal* signal, Uint32 nodeId)
-{
-}//Dbdih::nullRoutine()
-
-void Dbdih::sendCOPY_GCIREQ(Signal* signal, Uint32 nodeId)
-{
- ndbrequire(c_copyGCIMaster.m_copyReason != CopyGCIReq::IDLE);
-
- const BlockReference ref = calcDihBlockRef(nodeId);
- const Uint32 wordPerSignal = CopyGCIReq::DATA_SIZE;
- const Uint32 noOfSignals = ((Sysfile::SYSFILE_SIZE32 + (wordPerSignal - 1)) /
- wordPerSignal);
-
- CopyGCIReq * const copyGCI = (CopyGCIReq *)&signal->theData[0];
- copyGCI->anyData = nodeId;
- copyGCI->copyReason = c_copyGCIMaster.m_copyReason;
- copyGCI->startWord = 0;
-
- for(Uint32 i = 0; i < noOfSignals; i++) {
- jam();
- { // Do copy
- const int startWord = copyGCI->startWord;
- for(Uint32 j = 0; j < wordPerSignal; j++) {
- copyGCI->data[j] = sysfileData[j+startWord];
- }//for
- }
- sendSignal(ref, GSN_COPY_GCIREQ, signal, 25, JBB);
- copyGCI->startWord += wordPerSignal;
- }//for
-}//Dbdih::sendCOPY_GCIREQ()
-
-
-void Dbdih::sendDIH_SWITCH_REPLICA_REQ(Signal* signal, Uint32 nodeId)
-{
- const BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_DIH_SWITCH_REPLICA_REQ, signal,
- DihSwitchReplicaReq::SignalLength, JBB);
-}//Dbdih::sendDIH_SWITCH_REPLICA_REQ()
-
-void Dbdih::sendEMPTY_LCP_REQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcLqhBlockRef(nodeId);
- sendSignal(ref, GSN_EMPTY_LCP_REQ, signal, EmptyLcpReq::SignalLength, JBB);
-}//Dbdih::sendEMPTY_LCPREQ()
-
-void Dbdih::sendEND_TOREQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_END_TOREQ, signal, EndToReq::SignalLength, JBB);
-}//Dbdih::sendEND_TOREQ()
-
-void Dbdih::sendGCP_COMMIT(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcDihBlockRef(nodeId);
- signal->theData[0] = cownNodeId;
- signal->theData[1] = cnewgcp;
- sendSignal(ref, GSN_GCP_COMMIT, signal, 2, JBA);
-}//Dbdih::sendGCP_COMMIT()
-
-void Dbdih::sendGCP_PREPARE(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcDihBlockRef(nodeId);
- signal->theData[0] = cownNodeId;
- signal->theData[1] = cnewgcp;
- sendSignal(ref, GSN_GCP_PREPARE, signal, 2, JBA);
-}//Dbdih::sendGCP_PREPARE()
-
-void Dbdih::sendGCP_SAVEREQ(Signal* signal, Uint32 nodeId)
-{
- GCPSaveReq * const saveReq = (GCPSaveReq*)&signal->theData[0];
- BlockReference ref = calcLqhBlockRef(nodeId);
- saveReq->dihBlockRef = reference();
- saveReq->dihPtr = nodeId;
- saveReq->gci = coldgcp;
- sendSignal(ref, GSN_GCP_SAVEREQ, signal, GCPSaveReq::SignalLength, JBB);
-}//Dbdih::sendGCP_SAVEREQ()
-
-void Dbdih::sendINCL_NODEREQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference nodeDihRef = calcDihBlockRef(nodeId);
- signal->theData[0] = reference();
- signal->theData[1] = c_nodeStartMaster.startNode;
- signal->theData[2] = c_nodeStartMaster.failNr;
- signal->theData[3] = 0;
- signal->theData[4] = currentgcp;
- sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 5, JBA);
-}//Dbdih::sendINCL_NODEREQ()
-
-void Dbdih::sendMASTER_GCPREQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_MASTER_GCPREQ, signal, MasterGCPReq::SignalLength, JBB);
-}//Dbdih::sendMASTER_GCPREQ()
-
-void Dbdih::sendMASTER_LCPREQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_MASTER_LCPREQ, signal, MasterLCPReq::SignalLength, JBB);
-}//Dbdih::sendMASTER_LCPREQ()
-
-void Dbdih::sendSTART_INFOREQ(Signal* signal, Uint32 nodeId)
-{
- const BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_START_INFOREQ, signal, StartInfoReq::SignalLength, JBB);
-}//sendSTART_INFOREQ()
-
-void Dbdih::sendSTART_RECREQ(Signal* signal, Uint32 nodeId)
-{
- StartRecReq * const req = (StartRecReq*)&signal->theData[0];
- BlockReference ref = calcLqhBlockRef(nodeId);
- req->receivingNodeId = nodeId;
- req->senderRef = reference();
- req->keepGci = SYSFILE->keepGCI;
- req->lastCompletedGci = SYSFILE->lastCompletedGCI[nodeId];
- req->newestGci = SYSFILE->newestRestorableGCI;
- sendSignal(ref, GSN_START_RECREQ, signal, StartRecReq::SignalLength, JBB);
-
- signal->theData[0] = NDB_LE_StartREDOLog;
- signal->theData[1] = nodeId;
- signal->theData[2] = SYSFILE->keepGCI;
- signal->theData[3] = SYSFILE->lastCompletedGCI[nodeId];
- signal->theData[4] = SYSFILE->newestRestorableGCI;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 5, JBB);
-}//Dbdih::sendSTART_RECREQ()
-
-void Dbdih::sendSTART_TOREQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_START_TOREQ, signal, StartToReq::SignalLength, JBB);
-}//Dbdih::sendSTART_TOREQ()
-
-void Dbdih::sendSTOP_ME_REQ(Signal* signal, Uint32 nodeId)
-{
- if (nodeId != getOwnNodeId()) {
- jam();
- const BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_STOP_ME_REQ, signal, StopMeReq::SignalLength, JBB);
- }//if
-}//Dbdih::sendSTOP_ME_REQ()
-
-void Dbdih::sendTC_CLOPSIZEREQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcTcBlockRef(nodeId);
- signal->theData[0] = nodeId;
- signal->theData[1] = reference();
- sendSignal(ref, GSN_TC_CLOPSIZEREQ, signal, 2, JBB);
-}//Dbdih::sendTC_CLOPSIZEREQ()
-
-void Dbdih::sendTCGETOPSIZEREQ(Signal* signal, Uint32 nodeId)
-{
- BlockReference ref = calcTcBlockRef(nodeId);
- signal->theData[0] = nodeId;
- signal->theData[1] = reference();
- sendSignal(ref, GSN_TCGETOPSIZEREQ, signal, 2, JBB);
-}//Dbdih::sendTCGETOPSIZEREQ()
-
-void Dbdih::sendUPDATE_TOREQ(Signal* signal, Uint32 nodeId)
-{
- const BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_UPDATE_TOREQ, signal, UpdateToReq::SignalLength, JBB);
-}//sendUPDATE_TOREQ()
-
-void Dbdih::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- switch ((DihContinueB::Type)signal->theData[0]) {
- case DihContinueB::ZPACK_TABLE_INTO_PAGES:
- {
- jam();
- Uint32 tableId = signal->theData[1];
- packTableIntoPagesLab(signal, tableId);
- return;
- break;
- }
- case DihContinueB::ZPACK_FRAG_INTO_PAGES:
- {
- RWFragment wf;
- jam();
- wf.rwfTabPtr.i = signal->theData[1];
- ptrCheckGuard(wf.rwfTabPtr, ctabFileSize, tabRecord);
- wf.fragId = signal->theData[2];
- wf.pageIndex = signal->theData[3];
- wf.wordIndex = signal->theData[4];
- packFragIntoPagesLab(signal, &wf);
- return;
- break;
- }
- case DihContinueB::ZREAD_PAGES_INTO_TABLE:
- {
- jam();
- Uint32 tableId = signal->theData[1];
- readPagesIntoTableLab(signal, tableId);
- return;
- break;
- }
- case DihContinueB::ZREAD_PAGES_INTO_FRAG:
- {
- RWFragment rf;
- jam();
- rf.rwfTabPtr.i = signal->theData[1];
- ptrCheckGuard(rf.rwfTabPtr, ctabFileSize, tabRecord);
- rf.fragId = signal->theData[2];
- rf.pageIndex = signal->theData[3];
- rf.wordIndex = signal->theData[4];
- readPagesIntoFragLab(signal, &rf);
- return;
- break;
- }
- case DihContinueB::ZCOPY_TABLE:
- {
- jam();
- Uint32 tableId = signal->theData[1];
- copyTableLab(signal, tableId);
- return;
- }
- case DihContinueB::ZCOPY_TABLE_NODE:
- {
- NodeRecordPtr nodePtr;
- CopyTableNode ctn;
- jam();
- ctn.ctnTabPtr.i = signal->theData[1];
- ptrCheckGuard(ctn.ctnTabPtr, ctabFileSize, tabRecord);
- nodePtr.i = signal->theData[2];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- ctn.pageIndex = signal->theData[3];
- ctn.wordIndex = signal->theData[4];
- ctn.noOfWords = signal->theData[5];
- copyTableNode(signal, &ctn, nodePtr);
- return;
- }
- case DihContinueB::ZSTART_FRAGMENT:
- {
- jam();
- Uint32 tableId = signal->theData[1];
- Uint32 fragId = signal->theData[2];
- startFragment(signal, tableId, fragId);
- return;
- }
- case DihContinueB::ZCOMPLETE_RESTART:
- jam();
- completeRestartLab(signal);
- return;
- case DihContinueB::ZREAD_TABLE_FROM_PAGES:
- {
- TabRecordPtr tabPtr;
- jam();
- tabPtr.i = signal->theData[1];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- readTableFromPagesLab(signal, tabPtr);
- return;
- }
- case DihContinueB::ZSR_PHASE2_READ_TABLE:
- {
- TabRecordPtr tabPtr;
- jam();
- tabPtr.i = signal->theData[1];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- srPhase2ReadTableLab(signal, tabPtr);
- return;
- }
- case DihContinueB::ZCHECK_TC_COUNTER:
- jam();
-#ifndef NO_LCP
- checkTcCounterLab(signal);
-#endif
- return;
- case DihContinueB::ZCALCULATE_KEEP_GCI:
- {
- jam();
- Uint32 tableId = signal->theData[1];
- Uint32 fragId = signal->theData[2];
- calculateKeepGciLab(signal, tableId, fragId);
- return;
- }
- case DihContinueB::ZSTORE_NEW_LCP_ID:
- jam();
- storeNewLcpIdLab(signal);
- return;
- case DihContinueB::ZTABLE_UPDATE:
- {
- TabRecordPtr tabPtr;
- jam();
- tabPtr.i = signal->theData[1];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- tableUpdateLab(signal, tabPtr);
- return;
- }
- case DihContinueB::ZCHECK_LCP_COMPLETED:
- {
- jam();
- checkLcpCompletedLab(signal);
- return;
- }
- case DihContinueB::ZINIT_LCP:
- {
- jam();
- Uint32 senderRef = signal->theData[1];
- Uint32 tableId = signal->theData[2];
- initLcpLab(signal, senderRef, tableId);
- return;
- }
- case DihContinueB::ZADD_TABLE_MASTER_PAGES:
- {
- TabRecordPtr tabPtr;
- jam();
- tabPtr.i = signal->theData[1];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- tabPtr.p->tabUpdateState = TabRecord::US_ADD_TABLE_MASTER;
- tableUpdateLab(signal, tabPtr);
- return;
- break;
- }
- case DihContinueB::ZDIH_ADD_TABLE_MASTER:
- {
- jam();
- addTable_closeConf(signal, signal->theData[1]);
- return;
- }
- case DihContinueB::ZADD_TABLE_SLAVE_PAGES:
- {
- TabRecordPtr tabPtr;
- jam();
- tabPtr.i = signal->theData[1];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- tabPtr.p->tabUpdateState = TabRecord::US_ADD_TABLE_SLAVE;
- tableUpdateLab(signal, tabPtr);
- return;
- }
- case DihContinueB::ZDIH_ADD_TABLE_SLAVE:
- {
- ndbrequire(false);
- return;
- }
- case DihContinueB::ZSTART_GCP:
- jam();
-#ifndef NO_GCP
- startGcpLab(signal, signal->theData[1]);
-#endif
- return;
- break;
- case DihContinueB::ZCOPY_GCI:{
- jam();
- CopyGCIReq::CopyReason reason = (CopyGCIReq::CopyReason)signal->theData[1];
- ndbrequire(c_copyGCIMaster.m_copyReason == reason);
- sendLoopMacro(COPY_GCIREQ, sendCOPY_GCIREQ);
- return;
- }
- break;
- case DihContinueB::ZEMPTY_VERIFY_QUEUE:
- jam();
- emptyverificbuffer(signal, true);
- return;
- break;
- case DihContinueB::ZCHECK_GCP_STOP:
- jam();
-#ifndef NO_GCP
- checkGcpStopLab(signal);
-#endif
- return;
- break;
- case DihContinueB::ZREMOVE_NODE_FROM_TABLE:
- {
- jam();
- Uint32 nodeId = signal->theData[1];
- Uint32 tableId = signal->theData[2];
- removeNodeFromTables(signal, nodeId, tableId);
- return;
- }
- case DihContinueB::ZCOPY_NODE:
- {
- jam();
- Uint32 tableId = signal->theData[1];
- copyNodeLab(signal, tableId);
- return;
- }
- case DihContinueB::ZSTART_TAKE_OVER:
- {
- jam();
- Uint32 takeOverPtrI = signal->theData[1];
- Uint32 startNode = signal->theData[2];
- Uint32 toNode = signal->theData[3];
- startTakeOver(signal, takeOverPtrI, startNode, toNode);
- return;
- break;
- }
- case DihContinueB::ZCHECK_START_TAKE_OVER:
- jam();
- checkStartTakeOver(signal);
- break;
- case DihContinueB::ZTO_START_COPY_FRAG:
- {
- jam();
- Uint32 takeOverPtrI = signal->theData[1];
- startNextCopyFragment(signal, takeOverPtrI);
- return;
- }
- case DihContinueB::ZINVALIDATE_NODE_LCP:
- {
- jam();
- const Uint32 nodeId = signal->theData[1];
- const Uint32 tableId = signal->theData[2];
- invalidateNodeLCP(signal, nodeId, tableId);
- return;
- }
- case DihContinueB::ZINITIALISE_RECORDS:
- jam();
- initialiseRecordsLab(signal,
- signal->theData[1],
- signal->theData[2],
- signal->theData[3]);
- return;
- break;
- case DihContinueB::ZSTART_PERMREQ_AGAIN:
- jam();
- nodeRestartPh2Lab2(signal);
- return;
- break;
- case DihContinueB::SwitchReplica:
- {
- jam();
- const Uint32 nodeId = signal->theData[1];
- const Uint32 tableId = signal->theData[2];
- const Uint32 fragNo = signal->theData[3];
- switchReplica(signal, nodeId, tableId, fragNo);
- return;
- }
- case DihContinueB::ZSEND_START_TO:
- {
- jam();
- Uint32 takeOverPtrI = signal->theData[1];
- sendStartTo(signal, takeOverPtrI);
- return;
- }
- case DihContinueB::ZSEND_ADD_FRAG:
- {
- jam();
- Uint32 takeOverPtrI = signal->theData[1];
- toCopyFragLab(signal, takeOverPtrI);
- return;
- }
- case DihContinueB::ZSEND_UPDATE_TO:
- {
- jam();
- Uint32 takeOverPtrI = signal->theData[1];
- Uint32 updateState = signal->theData[4];
- sendUpdateTo(signal, takeOverPtrI, updateState);
- return;
- }
- case DihContinueB::ZSEND_END_TO:
- {
- jam();
- Uint32 takeOverPtrI = signal->theData[1];
- sendEndTo(signal, takeOverPtrI);
- return;
- }
- case DihContinueB::ZSEND_CREATE_FRAG:
- {
- jam();
- Uint32 takeOverPtrI = signal->theData[1];
- Uint32 storedType = signal->theData[2];
- Uint32 startGci = signal->theData[3];
- sendCreateFragReq(signal, startGci, storedType, takeOverPtrI);
- return;
- }
- case DihContinueB::WAIT_DROP_TAB_WRITING_TO_FILE:{
- jam();
- TabRecordPtr tabPtr;
- tabPtr.i = signal->theData[1];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- waitDropTabWritingToFile(signal, tabPtr);
- return;
- }
- case DihContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH:{
- jam();
- Uint32 nodeId = signal->theData[1];
- Uint32 tableId = signal->theData[2];
- checkWaitDropTabFailedLqh(signal, nodeId, tableId);
- return;
- }
- case DihContinueB::ZTO_START_FRAGMENTS:
- {
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = signal->theData[1];
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- nr_start_fragments(signal, takeOverPtr);
- return;
- }
- }//switch
-
- ndbrequire(false);
- return;
-}//Dbdih::execCONTINUEB()
-
-void Dbdih::execCOPY_GCIREQ(Signal* signal)
-{
- CopyGCIReq * const copyGCI = (CopyGCIReq *)&signal->theData[0];
- jamEntry();
- CopyGCIReq::CopyReason reason = (CopyGCIReq::CopyReason)copyGCI->copyReason;
- const Uint32 tstart = copyGCI->startWord;
-
- ndbrequire(cmasterdihref == signal->senderBlockRef()) ;
- ndbrequire(c_copyGCISlave.m_copyReason == CopyGCIReq::IDLE);
- ndbrequire(c_copyGCISlave.m_expectedNextWord == tstart);
- ndbrequire(reason != CopyGCIReq::IDLE);
- bool isdone = (tstart + CopyGCIReq::DATA_SIZE) >= Sysfile::SYSFILE_SIZE32;
-
- if (ERROR_INSERTED(7177))
- {
- jam();
-
- if (signal->getLength() == 3)
- {
- jam();
- goto done;
- }
- }
-
- arrGuard(tstart + CopyGCIReq::DATA_SIZE, sizeof(sysfileData)/4);
- for(Uint32 i = 0; i<CopyGCIReq::DATA_SIZE; i++)
- cdata[tstart+i] = copyGCI->data[i];
-
- if (ERROR_INSERTED(7177) && isMaster() && isdone)
- {
- sendSignalWithDelay(reference(), GSN_COPY_GCIREQ, signal, 1000, 3);
- return;
- }
-
-done:
- if (isdone)
- {
- jam();
- c_copyGCISlave.m_expectedNextWord = 0;
- }
- else
- {
- jam();
- c_copyGCISlave.m_expectedNextWord += CopyGCIReq::DATA_SIZE;
- return;
- }
-
- if (cmasterdihref != reference())
- {
- jam();
- Uint32 tmp= SYSFILE->m_restart_seq;
- memcpy(sysfileData, cdata, sizeof(sysfileData));
- SYSFILE->m_restart_seq = tmp;
-
- if (c_set_initial_start_flag)
- {
- jam();
- Sysfile::setInitialStartOngoing(SYSFILE->systemRestartBits);
- }
- }
-
- c_copyGCISlave.m_copyReason = reason;
- c_copyGCISlave.m_senderRef = signal->senderBlockRef();
- c_copyGCISlave.m_senderData = copyGCI->anyData;
-
- CRASH_INSERTION2(7020, reason==CopyGCIReq::LOCAL_CHECKPOINT);
- CRASH_INSERTION2(7008, reason==CopyGCIReq::GLOBAL_CHECKPOINT);
-
- /* -------------------------------------------------------------------------*/
- /* WE SET THE REQUESTER OF THE COPY GCI TO THE CURRENT MASTER. IF THE */
- /* CURRENT MASTER WE DO NOT WANT THE NEW MASTER TO RECEIVE CONFIRM OF */
- /* SOMETHING HE HAS NOT SENT. THE TAKE OVER MUST BE CAREFUL. */
- /* -------------------------------------------------------------------------*/
- bool ok = false;
- switch(reason){
- case CopyGCIReq::IDLE:
- ok = true;
- jam();
- ndbrequire(false);
- break;
- case CopyGCIReq::LOCAL_CHECKPOINT: {
- ok = true;
- jam();
- c_lcpState.setLcpStatus(LCP_COPY_GCI, __LINE__);
- c_lcpState.m_masterLcpDihRef = cmasterdihref;
- setNodeInfo(signal);
- break;
- }
- case CopyGCIReq::RESTART: {
- ok = true;
- jam();
- coldgcp = SYSFILE->newestRestorableGCI;
- crestartGci = SYSFILE->newestRestorableGCI;
- c_newest_restorable_gci = SYSFILE->newestRestorableGCI;
- Sysfile::setRestartOngoing(SYSFILE->systemRestartBits);
- currentgcp = coldgcp + 1;
- cnewgcp = coldgcp + 1;
- setNodeInfo(signal);
- if ((Sysfile::getLCPOngoing(SYSFILE->systemRestartBits))) {
- jam();
- /* -------------------------------------------------------------------- */
- // IF THERE WAS A LOCAL CHECKPOINT ONGOING AT THE CRASH MOMENT WE WILL
- // INVALIDATE THAT LOCAL CHECKPOINT.
- /* -------------------------------------------------------------------- */
- invalidateLcpInfoAfterSr();
- }//if
- break;
- }
- case CopyGCIReq::GLOBAL_CHECKPOINT: {
- ok = true;
- jam();
- cgcpParticipantState = GCP_PARTICIPANT_COPY_GCI_RECEIVED;
- c_newest_restorable_gci = SYSFILE->newestRestorableGCI;
- setNodeInfo(signal);
- break;
- }//if
- case CopyGCIReq::INITIAL_START_COMPLETED:
- ok = true;
- jam();
- break;
- }
- ndbrequire(ok);
-
- CRASH_INSERTION(7183);
-
- if (ERROR_INSERTED(7185) && reason==CopyGCIReq::GLOBAL_CHECKPOINT)
- {
- jam();
- return;
- }
-
- /* ----------------------------------------------------------------------- */
- /* WE START BY TRYING TO OPEN THE FIRST RESTORABLE GCI FILE. */
- /* ----------------------------------------------------------------------- */
- FileRecordPtr filePtr;
- filePtr.i = crestartInfoFile[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- if (filePtr.p->fileStatus == FileRecord::OPEN) {
- jam();
- openingCopyGciSkipInitLab(signal, filePtr);
- return;
- }//if
- openFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::OPENING_COPY_GCI;
- return;
-}//Dbdih::execCOPY_GCIREQ()
-
-void Dbdih::execDICTSTARTCONF(Signal* signal)
-{
- jamEntry();
- Uint32 nodeId = refToNode(signal->getSendersBlockRef());
- if (nodeId != getOwnNodeId()) {
- jam();
- nodeDictStartConfLab(signal);
- } else {
- jam();
- dictStartConfLab(signal);
- }//if
-}//Dbdih::execDICTSTARTCONF()
-
-void Dbdih::execFSCLOSECONF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- filePtr.p->fileStatus = FileRecord::CLOSED;
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::CLOSING_GCP:
- jam();
- closingGcpLab(signal, filePtr);
- break;
- case FileRecord::CLOSING_GCP_CRASH:
- jam();
- closingGcpCrashLab(signal, filePtr);
- break;
- case FileRecord::CLOSING_TABLE_CRASH:
- jam();
- closingTableCrashLab(signal, filePtr);
- break;
- case FileRecord::CLOSING_TABLE_SR:
- jam();
- closingTableSrLab(signal, filePtr);
- break;
- case FileRecord::TABLE_CLOSE:
- jam();
- tableCloseLab(signal, filePtr);
- break;
- case FileRecord::TABLE_CLOSE_DELETE:
- jam();
- tableDeleteLab(signal, filePtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbdih::execFSCLOSECONF()
-
-void Dbdih::execFSCLOSEREF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::CLOSING_GCP:
- jam();
- break;
- case FileRecord::CLOSING_GCP_CRASH:
- jam();
- closingGcpCrashLab(signal, filePtr);
- return;
- case FileRecord::CLOSING_TABLE_CRASH:
- jam();
- closingTableCrashLab(signal, filePtr);
- return;
- case FileRecord::CLOSING_TABLE_SR:
- jam();
- break;
- case FileRecord::TABLE_CLOSE:
- jam();
- break;
- case FileRecord::TABLE_CLOSE_DELETE:
- jam();
- break;
- default:
- jam();
- break;
-
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system close failed during FileRecord status %d", (Uint32)status);
- fsRefError(signal,__LINE__,msg);
- }
-
- return;
-}//Dbdih::execFSCLOSEREF()
-
-void Dbdih::execFSOPENCONF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- filePtr.p->fileRef = signal->theData[1];
- filePtr.p->fileStatus = FileRecord::OPEN;
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::CREATING_GCP:
- jam();
- creatingGcpLab(signal, filePtr);
- break;
- case FileRecord::OPENING_COPY_GCI:
- jam();
- openingCopyGciSkipInitLab(signal, filePtr);
- break;
- case FileRecord::CREATING_COPY_GCI:
- jam();
- openingCopyGciSkipInitLab(signal, filePtr);
- break;
- case FileRecord::OPENING_GCP:
- jam();
- openingGcpLab(signal, filePtr);
- break;
- case FileRecord::OPENING_TABLE:
- jam();
- openingTableLab(signal, filePtr);
- break;
- case FileRecord::TABLE_CREATE:
- jam();
- tableCreateLab(signal, filePtr);
- break;
- case FileRecord::TABLE_OPEN_FOR_DELETE:
- jam();
- tableOpenLab(signal, filePtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbdih::execFSOPENCONF()
-
-void Dbdih::execFSOPENREF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::CREATING_GCP:
- /* --------------------------------------------------------------------- */
- /* WE DID NOT MANAGE TO CREATE A GLOBAL CHECKPOINT FILE. SERIOUS ERROR */
- /* WHICH CAUSES A SYSTEM RESTART. */
- /* --------------------------------------------------------------------- */
- jam();
- break;
- case FileRecord::OPENING_COPY_GCI:
- jam();
- openingCopyGciErrorLab(signal, filePtr);
- return;
- case FileRecord::CREATING_COPY_GCI:
- jam();
- break;
- case FileRecord::OPENING_GCP:
- jam();
- openingGcpErrorLab(signal, filePtr);
- return;
- case FileRecord::OPENING_TABLE:
- jam();
- openingTableErrorLab(signal, filePtr);
- return;
- case FileRecord::TABLE_CREATE:
- jam();
- break;
- case FileRecord::TABLE_OPEN_FOR_DELETE:
- jam();
- tableDeleteLab(signal, filePtr);
- return;
- default:
- jam();
- break;
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system open failed during FileRecord status %d", (Uint32)status);
- fsRefError(signal,__LINE__,msg);
- }
- return;
-}//Dbdih::execFSOPENREF()
-
-void Dbdih::execFSREADCONF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::READING_GCP:
- jam();
- readingGcpLab(signal, filePtr);
- break;
- case FileRecord::READING_TABLE:
- jam();
- readingTableLab(signal, filePtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbdih::execFSREADCONF()
-
-void Dbdih::execFSREADREF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::READING_GCP:
- jam();
- readingGcpErrorLab(signal, filePtr);
- return;
- case FileRecord::READING_TABLE:
- jam();
- readingTableErrorLab(signal, filePtr);
- return;
- default:
- break;
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system read failed during FileRecord status %d", (Uint32)status);
- fsRefError(signal,__LINE__,msg);
- }
-}//Dbdih::execFSREADREF()
-
-void Dbdih::execFSWRITECONF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::WRITING_COPY_GCI:
- jam();
- writingCopyGciLab(signal, filePtr);
- break;
- case FileRecord::WRITE_INIT_GCP:
- jam();
- writeInitGcpLab(signal, filePtr);
- break;
- case FileRecord::TABLE_WRITE:
- jam();
- tableWriteLab(signal, filePtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbdih::execFSWRITECONF()
-
-void Dbdih::execFSWRITEREF(Signal* signal)
-{
- FileRecordPtr filePtr;
- jamEntry();
- filePtr.i = signal->theData[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- FileRecord::ReqStatus status = filePtr.p->reqStatus;
- filePtr.p->reqStatus = FileRecord::IDLE;
- switch (status) {
- case FileRecord::WRITING_COPY_GCI:
- /* --------------------------------------------------------------------- */
- /* EVEN CREATING THE FILE DID NOT WORK. WE WILL THEN CRASH. */
- /* ERROR IN WRITING FILE. WE WILL NOT CONTINUE FROM HERE. */
- /* --------------------------------------------------------------------- */
- jam();
- break;
- case FileRecord::WRITE_INIT_GCP:
- /* --------------------------------------------------------------------- */
- /* AN ERROR OCCURRED IN WRITING A GCI FILE WHICH IS A SERIOUS ERROR */
- /* THAT CAUSE A SYSTEM RESTART. */
- /* --------------------------------------------------------------------- */
- jam();
- break;
- case FileRecord::TABLE_WRITE:
- jam();
- break;
- default:
- jam();
- break;
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system write failed during FileRecord status %d", (Uint32)status);
- fsRefError(signal,__LINE__,msg);
- }
- return;
-}//Dbdih::execFSWRITEREF()
-
-void Dbdih::execGETGCIREQ(Signal* signal)
-{
-
- jamEntry();
- Uint32 userPtr = signal->theData[0];
- BlockReference userRef = signal->theData[1];
-
- signal->theData[0] = userPtr;
- signal->theData[1] = SYSFILE->newestRestorableGCI;
- sendSignal(userRef, GSN_GETGCICONF, signal, 2, JBB);
-}//Dbdih::execGETGCIREQ()
-
-void Dbdih::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 =
- m_ctx.m_config.getOwnConfigIterator();
- 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;
-}//Dbdih::execSIZEALT_REP()
-
-void Dbdih::execSTART_COPYREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dbdih::execSTART_COPYREF()
-
-void Dbdih::execSTART_FRAGCONF(Signal* signal)
-{
- (void)signal; // Don't want compiler warning
- /* ********************************************************************* */
- /* If anyone wants to add functionality in this method, be aware that */
- /* for temporary tables no START_FRAGREQ is sent and therefore no */
- /* START_FRAGCONF signal will be received for those tables!! */
- /* ********************************************************************* */
- jamEntry();
- return;
-}//Dbdih::execSTART_FRAGCONF()
-
-void Dbdih::execSTART_FRAGREF(Signal* signal)
-{
- jamEntry();
-
- /**
- * Kill starting node
- */
- Uint32 errCode = signal->theData[1];
- Uint32 nodeId = signal->theData[2];
-
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::StartFragRefError;
- sysErr->errorRef = reference();
- sysErr->data1 = errCode;
- sysErr->data2 = 0;
- sendSignal(calcNdbCntrBlockRef(nodeId), GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBB);
- return;
-}//Dbdih::execSTART_FRAGCONF()
-
-void Dbdih::execSTART_MEREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dbdih::execSTART_MEREF()
-
-void Dbdih::execTAB_COMMITREQ(Signal* signal)
-{
- TabRecordPtr tabPtr;
- jamEntry();
- Uint32 tdictPtr = signal->theData[0];
- BlockReference tdictBlockref = signal->theData[1];
- tabPtr.i = signal->theData[2];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_CREATING);
- tabPtr.p->tabStatus = TabRecord::TS_ACTIVE;
- signal->theData[0] = tdictPtr;
- signal->theData[1] = cownNodeId;
- signal->theData[2] = tabPtr.i;
- sendSignal(tdictBlockref, GSN_TAB_COMMITCONF, signal, 3, JBB);
- return;
-}//Dbdih::execTAB_COMMITREQ()
-
-/*
- 3.2 S T A N D A R D S U B P R O G R A M S I N P L E X
- *************************************************************
- */
-/*
- 3.2.1 S T A R T / R E S T A R T
- **********************************
- */
-/*****************************************************************************/
-/* ********** START / RESTART MODULE *************/
-/*****************************************************************************/
-/*
- 3.2.1.1 LOADING O W N B L O C K R E F E R E N C E (ABSOLUTE PHASE 1)
- *****************************************************************************
- */
-void Dbdih::execDIH_RESTARTREQ(Signal* signal)
-{
- jamEntry();
- if (signal->theData[0])
- {
- jam();
- cntrlblockref = signal->theData[0];
- if(m_ctx.m_config.getInitialStart()){
- sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
- } else {
- readGciFileLab(signal);
- }
- }
- else
- {
- /**
- * Precondition, (not checked)
- * atleast 1 node in each node group
- */
- Uint32 i;
- NdbNodeBitmask mask;
- mask.assign(NdbNodeBitmask::Size, signal->theData + 1);
- Uint32 *node_gcis = signal->theData+1+NdbNodeBitmask::Size;
- Uint32 node_group_gcis[MAX_NDB_NODES+1];
- bzero(node_group_gcis, sizeof(node_group_gcis));
- for (i = 0; i<MAX_NDB_NODES; i++)
- {
- if (mask.get(i))
- {
- jam();
- Uint32 ng = Sysfile::getNodeGroup(i, SYSFILE->nodeGroups);
- ndbrequire(ng < MAX_NDB_NODES);
- Uint32 gci = node_gcis[i];
- if (gci < SYSFILE->lastCompletedGCI[i])
- {
- jam();
- /**
- * Handle case, where *I* know that node complete GCI
- * but node does not...bug#29167
- * i.e node died before it wrote own sysfile
- */
- gci = SYSFILE->lastCompletedGCI[i];
- }
-
- if (gci > node_group_gcis[ng])
- {
- jam();
- node_group_gcis[ng] = gci;
- }
- }
- }
- for (i = 0; i<MAX_NDB_NODES && node_group_gcis[i] == 0; i++);
-
- Uint32 gci = node_group_gcis[i];
- for (i++ ; i<MAX_NDB_NODES; i++)
- {
- jam();
- if (node_group_gcis[i] && node_group_gcis[i] != gci)
- {
- jam();
- signal->theData[0] = i;
- return;
- }
- }
- signal->theData[0] = MAX_NDB_NODES;
- return;
- }
- return;
-}//Dbdih::execDIH_RESTARTREQ()
-
-void Dbdih::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- signal->theData[0] = 0;
- signal->theData[1] = 0;
- signal->theData[2] = 0;
- signal->theData[3] = 1; // Next start phase
- signal->theData[4] = 255; // Next start phase
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
- return;
-}//Dbdih::execSTTOR()
-
-void Dbdih::initialStartCompletedLab(Signal* signal)
-{
- /*-------------------------------------------------------------------------*/
- /* NOW THAT (RE)START IS COMPLETED WE CAN START THE LCP.*/
- /*-------------------------------------------------------------------------*/
- return;
-}//Dbdih::initialStartCompletedLab()
-
-/*
- * ***************************************************************************
- * S E N D I N G R E P L Y T O S T A R T / R E S T A R T R E Q U E S T S
- * ****************************************************************************
- */
-void Dbdih::ndbsttorry10Lab(Signal* signal, Uint32 _line)
-{
- /*-------------------------------------------------------------------------*/
- // AN NDB START PHASE HAS BEEN COMPLETED. WHEN START PHASE 6 IS COMPLETED WE
- // RECORD THAT THE SYSTEM IS RUNNING.
- /*-------------------------------------------------------------------------*/
- signal->theData[0] = reference();
- sendSignal(cntrlblockref, GSN_NDB_STTORRY, signal, 1, JBB);
- return;
-}//Dbdih::ndbsttorry10Lab()
-
-/*
-****************************************
-I N T E R N A L P H A S E S
-****************************************
-*/
-/*---------------------------------------------------------------------------*/
-/*NDB_STTOR START SIGNAL AT START/RESTART */
-/*---------------------------------------------------------------------------*/
-void Dbdih::execNDB_STTOR(Signal* signal)
-{
- jamEntry();
- BlockReference cntrRef = signal->theData[0]; /* SENDERS BLOCK REFERENCE */
- Uint32 ownNodeId = signal->theData[1]; /* OWN PROCESSOR ID*/
- Uint32 phase = signal->theData[2]; /* INTERNAL START PHASE*/
- Uint32 typestart = signal->theData[3];
-
- cstarttype = typestart;
- cstartPhase = phase;
-
- switch (phase){
- case ZNDB_SPH1:
- jam();
- /*----------------------------------------------------------------------*/
- /* Set the delay between local checkpoints in ndb startphase 1. */
- /*----------------------------------------------------------------------*/
- cownNodeId = ownNodeId;
- /*-----------------------------------------------------------------------*/
- // Compute all static block references in this node as part of
- // ndb start phase 1.
- /*-----------------------------------------------------------------------*/
- cntrlblockref = cntrRef;
- clocaltcblockref = calcTcBlockRef(ownNodeId);
- clocallqhblockref = calcLqhBlockRef(ownNodeId);
- cdictblockref = calcDictBlockRef(ownNodeId);
- ndbsttorry10Lab(signal, __LINE__);
- break;
-
- case ZNDB_SPH2:
- jam();
- /*-----------------------------------------------------------------------*/
- // Set the number of replicas, maximum is 4 replicas.
- // Read the ndb nodes from the configuration.
- /*-----------------------------------------------------------------------*/
-
- /*-----------------------------------------------------------------------*/
- // For node restarts we will also add a request for permission
- // to continue the system restart.
- // The permission is given by the master node in the alive set.
- /*-----------------------------------------------------------------------*/
- createMutexes(signal, 0);
- if (cstarttype == NodeState::ST_INITIAL_NODE_RESTART)
- {
- jam();
- c_set_initial_start_flag = TRUE; // In sysfile...
- }
- break;
-
- case ZNDB_SPH3:
- jam();
- /*-----------------------------------------------------------------------*/
- // Non-master nodes performing an initial start will execute
- // the start request here since the
- // initial start do not synchronise so much from the master.
- // In the master nodes the start
- // request will be sent directly to dih (in ndb_startreq) when all
- // nodes have completed phase 3 of the start.
- /*-----------------------------------------------------------------------*/
- cmasterState = MASTER_IDLE;
- if(cstarttype == NodeState::ST_INITIAL_START ||
- cstarttype == NodeState::ST_SYSTEM_RESTART){
- jam();
- cmasterState = isMaster() ? MASTER_ACTIVE : MASTER_IDLE;
- }
- if (!isMaster() && cstarttype == NodeState::ST_INITIAL_START) {
- jam();
- ndbStartReqLab(signal, cntrRef);
- return;
- }//if
- ndbsttorry10Lab(signal, __LINE__);
- break;
-
- case ZNDB_SPH4:
- jam();
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
- cmasterTakeOverNode = ZNIL;
- switch(typestart){
- case NodeState::ST_INITIAL_START:
- jam();
- ndbsttorry10Lab(signal, __LINE__);
- return;
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- if (isMaster()) {
- jam();
- systemRestartTakeOverLab(signal);
- if (anyActiveTakeOver())
- {
- jam();
- return;
- }
- }
- ndbsttorry10Lab(signal, __LINE__);
- return;
- 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.
- * When this signal is confirmed the master has also copied the
- * dictionary and the distribution information.
- */
- StartMeReq * req = (StartMeReq*)&signal->theData[0];
- req->startingRef = reference();
- req->startingVersion = 0; // Obsolete
- sendSignal(cmasterdihref, GSN_START_MEREQ, signal,
- StartMeReq::SignalLength, JBB);
- return;
- }
- ndbrequire(false);
- break;
- case ZNDB_SPH5:
- jam();
- switch(typestart){
- case NodeState::ST_INITIAL_START:
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- jam();
- /*---------------------------------------------------------------------*/
- // WE EXECUTE A LOCAL CHECKPOINT AS A PART OF A SYSTEM RESTART.
- // THE IDEA IS THAT WE NEED TO
- // ENSURE THAT WE CAN RECOVER FROM PROBLEMS CAUSED BY MANY NODE
- // CRASHES THAT CAUSES THE LOG
- // TO GROW AND THE NUMBER OF LOG ROUNDS TO EXECUTE TO GROW.
- // THIS CAN OTHERWISE GET US INTO
- // A SITUATION WHICH IS UNREPAIRABLE. THUS WE EXECUTE A CHECKPOINT
- // BEFORE ALLOWING ANY TRANSACTIONS TO START.
- /*---------------------------------------------------------------------*/
- if (!isMaster()) {
- jam();
- ndbsttorry10Lab(signal, __LINE__);
- return;
- }//if
-
- c_lcpState.immediateLcpStart = true;
- cwaitLcpSr = true;
- checkLcpStart(signal, __LINE__);
- return;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
- signal->theData[0] = cownNodeId;
- signal->theData[1] = reference();
- sendSignal(cmasterdihref, GSN_START_COPYREQ, signal, 2, JBB);
- return;
- }
- ndbrequire(false);
- case ZNDB_SPH6:
- jam();
- switch(typestart){
- case NodeState::ST_INITIAL_START:
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- if(isMaster()){
- jam();
- startGcp(signal);
- }
- ndbsttorry10Lab(signal, __LINE__);
- return;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- ndbsttorry10Lab(signal, __LINE__);
- return;
- }
- ndbrequire(false);
- break;
- default:
- jam();
- ndbsttorry10Lab(signal, __LINE__);
- break;
- }//switch
-}//Dbdih::execNDB_STTOR()
-
-void
-Dbdih::execNODE_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 };
-
- switch(count){
- case 0:{
- Mutex mutex(signal, c_mutexMgr, c_startLcpMutexHandle);
- mutex.create(c);
- return;
- }
- case 1:{
- Mutex mutex(signal, c_mutexMgr, c_switchPrimaryMutexHandle);
- mutex.create(c);
- return;
- }
- }
-
- signal->theData[0] = reference();
- sendSignal(cntrlblockref, GSN_READ_NODESREQ, signal, 1, JBB);
-}
-
-void
-Dbdih::createMutex_done(Signal* signal, Uint32 senderData, Uint32 retVal){
- jamEntry();
- ndbrequire(retVal == 0);
-
- switch(senderData){
- case 0:{
- Mutex mutex(signal, c_mutexMgr, c_startLcpMutexHandle);
- mutex.release();
- }
- case 1:{
- Mutex mutex(signal, c_mutexMgr, c_switchPrimaryMutexHandle);
- mutex.release();
- }
- }
-
- createMutexes(signal, senderData + 1);
-}
-
-/*****************************************************************************/
-/* ------------------------------------------------------------------------- */
-/* WE HAVE BEEN REQUESTED BY NDBCNTR TO PERFORM A RESTART OF THE */
-/* DATABASE TABLES. */
-/* THIS SIGNAL IS SENT AFTER COMPLETING PHASE 3 IN ALL BLOCKS IN A */
-/* SYSTEM RESTART. WE WILL ALSO JUMP TO THIS LABEL FROM PHASE 3 IN AN */
-/* INITIAL START. */
-/* ------------------------------------------------------------------------- */
-/*****************************************************************************/
-void Dbdih::execNDB_STARTREQ(Signal* signal)
-{
- jamEntry();
- BlockReference ref = signal->theData[0];
- cstarttype = signal->theData[1];
- ndbStartReqLab(signal, ref);
-}//Dbdih::execNDB_STARTREQ()
-
-void Dbdih::ndbStartReqLab(Signal* signal, BlockReference ref)
-{
- cndbStartReqBlockref = ref;
- if (cstarttype == NodeState::ST_INITIAL_START) {
- jam();
- initRestartInfo();
- initGciFilesLab(signal);
- return;
- }
-
- NodeRecordPtr nodePtr;
- Uint32 gci = SYSFILE->lastCompletedGCI[getOwnNodeId()];
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++)
- {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (SYSFILE->lastCompletedGCI[nodePtr.i] > gci)
- {
- jam();
- /**
- * Since we're starting(is master) and there
- * there are other nodes with higher GCI...
- * there gci's must be invalidated...
- * and they _must_ do an initial start
- * indicate this by setting lastCompletedGCI = 0
- */
- SYSFILE->lastCompletedGCI[nodePtr.i] = 0;
- ndbrequire(nodePtr.p->nodeStatus != NodeRecord::ALIVE);
- warningEvent("Making filesystem for node %d unusable (need --initial)",
- nodePtr.i);
- }
- else if (nodePtr.p->nodeStatus == NodeRecord::ALIVE &&
- SYSFILE->lastCompletedGCI[nodePtr.i] == 0)
- {
- jam();
- CRASH_INSERTION(7170);
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Cluster requires this node to be started "
- " with --initial as partial start has been performed"
- " and this filesystem is unusable");
- progError(__LINE__,
- NDBD_EXIT_SR_RESTARTCONFLICT,
- buf);
- ndbrequire(false);
- }
- }
-
- /**
- * This set which GCI we will try to restart to
- */
- SYSFILE->newestRestorableGCI = gci;
-
- ndbrequire(isMaster());
- copyGciLab(signal, CopyGCIReq::RESTART); // We have already read the file!
-}//Dbdih::ndbStartReqLab()
-
-void Dbdih::execREAD_NODESCONF(Signal* signal)
-{
- unsigned i;
- ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
- jamEntry();
- Uint32 nodeArray[MAX_NDB_NODES];
-
- csystemnodes = readNodes->noOfNodes;
- cmasterNodeId = readNodes->masterNodeId;
- int index = 0;
- NdbNodeBitmask tmp; tmp.assign(2, readNodes->allNodes);
- for (i = 1; i < MAX_NDB_NODES; i++){
- jam();
- if(tmp.get(i)){
- jam();
- nodeArray[index] = i;
- if(NodeBitmask::get(readNodes->inactiveNodes, i) == false){
- jam();
- con_lineNodes++;
- }//if
- index++;
- }//if
- }//for
-
- if(cstarttype == NodeState::ST_SYSTEM_RESTART ||
- cstarttype == NodeState::ST_NODE_RESTART){
-
- for(i = 1; i<MAX_NDB_NODES; i++){
- const Uint32 stat = Sysfile::getNodeStatus(i, SYSFILE->nodeStatus);
- if(stat == Sysfile::NS_NotDefined && !tmp.get(i)){
- jam();
- continue;
- }
-
- if(tmp.get(i) && stat != Sysfile::NS_NotDefined){
- jam();
- continue;
- }
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Illegal configuration change."
- " Initial start needs to be performed "
- " when changing no of storage nodes (node %d)", i);
- progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf);
- }
- }
-
- ndbrequire(csystemnodes >= 1 && csystemnodes < MAX_NDB_NODES);
- if (cstarttype == NodeState::ST_INITIAL_START) {
- jam();
- ndbrequire(cnoReplicas <= csystemnodes);
- calculateHotSpare();
- ndbrequire(cnoReplicas <= (csystemnodes - cnoHotSpare));
- }//if
-
- cmasterdihref = calcDihBlockRef(cmasterNodeId);
- /*-------------------------------------------------------------------------*/
- /* MAKE THE LIST OF PRN-RECORD WHICH IS ONE OF THE NODES-LIST IN THIS BLOCK*/
- /*-------------------------------------------------------------------------*/
- makePrnList(readNodes, nodeArray);
- if (cstarttype == NodeState::ST_INITIAL_START) {
- jam();
- /**----------------------------------------------------------------------
- * WHEN WE INITIALLY START A DATABASE WE WILL CREATE NODE GROUPS.
- * ALL NODES ARE PUT INTO NODE GROUPS ALTHOUGH HOT SPARE NODES ARE PUT
- * INTO A SPECIAL NODE GROUP. IN EACH NODE GROUP WE HAVE THE SAME AMOUNT
- * OF NODES AS THERE ARE NUMBER OF REPLICAS.
- * ONE POSSIBLE USAGE OF NODE GROUPS ARE TO MAKE A NODE GROUP A COMPLETE
- * FRAGMENT OF THE DATABASE. THIS MEANS THAT ALL REPLICAS WILL BE STORED
- * IN THE NODE GROUP.
- *-----------------------------------------------------------------------*/
- makeNodeGroups(nodeArray);
- }//if
- ndbrequire(checkNodeAlive(cmasterNodeId));
- if (cstarttype == NodeState::ST_INITIAL_START) {
- jam();
- /**-----------------------------------------------------------------------
- * INITIALISE THE SECOND NODE-LIST AND SET NODE BITS AND SOME NODE STATUS.
- * VERY CONNECTED WITH MAKE_NODE_GROUPS. CHANGING ONE WILL AFFECT THE
- * OTHER AS WELL.
- *-----------------------------------------------------------------------*/
- setInitialActiveStatus();
- } else if (cstarttype == NodeState::ST_SYSTEM_RESTART) {
- jam();
- /*empty*/;
- } else if ((cstarttype == NodeState::ST_NODE_RESTART) ||
- (cstarttype == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- nodeRestartPh2Lab(signal);
- return;
- } else {
- ndbrequire(false);
- }//if
- /**------------------------------------------------------------------------
- * ESTABLISH CONNECTIONS WITH THE OTHER DIH BLOCKS AND INITIALISE THIS
- * NODE-LIST THAT HANDLES CONNECTION WITH OTHER DIH BLOCKS.
- *-------------------------------------------------------------------------*/
- ndbsttorry10Lab(signal, __LINE__);
-}//Dbdih::execREAD_NODESCONF()
-
-/*---------------------------------------------------------------------------*/
-/* START NODE LOGIC FOR NODE RESTART */
-/*---------------------------------------------------------------------------*/
-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.
- /*------------------------------------------------------------------------*/
- StartPermReq * const req = (StartPermReq *)&signal->theData[0];
-
- req->blockRef = reference();
- req->nodeId = cownNodeId;
- req->startType = cstarttype;
- sendSignal(cmasterdihref, GSN_START_PERMREQ, signal, 3, JBB);
-}
-
-void Dbdih::execSTART_PERMCONF(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(7121);
- Uint32 nodeId = signal->theData[0];
- cfailurenr = signal->theData[1];
- ndbrequire(nodeId == cownNodeId);
- ndbsttorry10Lab(signal, __LINE__);
-}//Dbdih::execSTART_PERMCONF()
-
-void Dbdih::execSTART_PERMREF(Signal* signal)
-{
- jamEntry();
- Uint32 errorCode = signal->theData[1];
- if (errorCode == StartPermRef::ZNODE_ALREADY_STARTING_ERROR ||
- errorCode == StartPermRef::ZNODE_START_DISALLOWED_ERROR) {
- jam();
- /*-----------------------------------------------------------------------*/
- // The master was busy adding another node. We will wait for a second and
- // try again.
- /*-----------------------------------------------------------------------*/
- signal->theData[0] = DihContinueB::ZSTART_PERMREQ_AGAIN;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000, 1);
- return;
- }//if
-
- if (errorCode == StartPermRef::InitialStartRequired)
- {
- CRASH_INSERTION(7170);
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Cluster requires this node to be started "
- " with --initial as partial start has been performed"
- " and this filesystem is unusable");
- progError(__LINE__,
- NDBD_EXIT_SR_RESTARTCONFLICT,
- buf);
- ndbrequire(false);
- }
- /*------------------------------------------------------------------------*/
- // Some node process in another node involving our node was still active. We
- // will recover from this by crashing here.
- // This is controlled restart using the
- // already existing features of node crashes. It is not a bug getting here.
- /*-------------------------------------------------------------------------*/
- ndbrequire(false);
- return;
-}//Dbdih::execSTART_PERMREF()
-
-/*---------------------------------------------------------------------------*/
-/* THIS SIGNAL IS RECEIVED IN THE STARTING NODE WHEN THE START_MEREQ */
-/* HAS BEEN EXECUTED IN THE MASTER NODE. */
-/*---------------------------------------------------------------------------*/
-void Dbdih::execSTART_MECONF(Signal* signal)
-{
- jamEntry();
- StartMeConf * const startMe = (StartMeConf *)&signal->theData[0];
- Uint32 nodeId = startMe->startingNodeId;
- const Uint32 startWord = startMe->startWord;
- Uint32 i;
-
- CRASH_INSERTION(7130);
- ndbrequire(nodeId == cownNodeId);
- arrGuard(startWord + StartMeConf::DATA_SIZE, sizeof(cdata)/4);
- for(i = 0; i < StartMeConf::DATA_SIZE; i++)
- cdata[startWord+i] = startMe->data[i];
-
- if(startWord + StartMeConf::DATA_SIZE < Sysfile::SYSFILE_SIZE32){
- jam();
- /**
- * We are still waiting for data
- */
- return;
- }
- jam();
-
- /**
- * Copy into sysfile
- *
- * But dont copy lastCompletedGCI:s
- */
- Uint32 key = SYSFILE->m_restart_seq;
- Uint32 tempGCP[MAX_NDB_NODES];
- for(i = 0; i < MAX_NDB_NODES; i++)
- tempGCP[i] = SYSFILE->lastCompletedGCI[i];
-
- for(i = 0; i < Sysfile::SYSFILE_SIZE32; i++)
- sysfileData[i] = cdata[i];
-
- SYSFILE->m_restart_seq = key;
- for(i = 0; i < MAX_NDB_NODES; i++)
- SYSFILE->lastCompletedGCI[i] = tempGCP[i];
-
- setNodeActiveStatus();
- setNodeGroups();
- ndbsttorry10Lab(signal, __LINE__);
-}//Dbdih::execSTART_MECONF()
-
-void Dbdih::execSTART_COPYCONF(Signal* signal)
-{
- jamEntry();
- Uint32 nodeId = signal->theData[0];
- ndbrequire(nodeId == cownNodeId);
- CRASH_INSERTION(7132);
- ndbsttorry10Lab(signal, __LINE__);
- return;
-}//Dbdih::execSTART_COPYCONF()
-
-/*---------------------------------------------------------------------------*/
-/* MASTER LOGIC FOR NODE RESTART */
-/*---------------------------------------------------------------------------*/
-/* NODE RESTART PERMISSION REQUEST */
-/*---------------------------------------------------------------------------*/
-// A REQUEST FROM A STARTING NODE TO PERFORM A NODE RESTART. IF NO OTHER NODE
-// IS ACTIVE IN PERFORMING A NODE RESTART AND THERE ARE NO ACTIVE PROCESSES IN
-// THIS NODE INVOLVING THE STARTING NODE THIS REQUEST WILL BE GRANTED.
-/*---------------------------------------------------------------------------*/
-void Dbdih::execSTART_PERMREQ(Signal* signal)
-{
- StartPermReq * const req = (StartPermReq*)&signal->theData[0];
- jamEntry();
- 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) ||
- ERROR_INSERTED_CLEAR(7175)) {
- jam();
- signal->theData[0] = nodeId;
- signal->theData[1] = StartPermRef::ZNODE_ALREADY_STARTING_ERROR;
- sendSignal(retRef, GSN_START_PERMREF, signal, 2, JBB);
- return;
- }//if
- if (getNodeStatus(nodeId) != NodeRecord::DEAD){
- g_eventLogger.error("nodeStatus in START_PERMREQ = %u",
- (Uint32) getNodeStatus(nodeId));
- ndbrequire(false);
- }//if
-
- if (SYSFILE->lastCompletedGCI[nodeId] == 0 &&
- typeStart != NodeState::ST_INITIAL_NODE_RESTART)
- {
- jam();
- signal->theData[0] = nodeId;
- signal->theData[1] = StartPermRef::InitialStartRequired;
- sendSignal(retRef, GSN_START_PERMREF, signal, 2, JBB);
- return;
- }
-
- /*----------------------------------------------------------------------
- * WE START THE INCLUSION PROCEDURE
- * ---------------------------------------------------------------------*/
- c_nodeStartMaster.failNr = cfailurenr;
- c_nodeStartMaster.wait = ZFALSE;
- c_nodeStartMaster.startInfoErrorCode = 0;
- c_nodeStartMaster.startNode = nodeId;
- c_nodeStartMaster.activeState = true;
- c_nodeStartMaster.m_outstandingGsn = GSN_START_INFOREQ;
-
- setNodeStatus(nodeId, NodeRecord::STARTING);
- /**
- * But if it's a NodeState::ST_INITIAL_NODE_RESTART
- *
- * We first have to clear LCP's
- * For normal node restart we simply ensure that all nodes
- * are informed of the node restart
- */
- StartInfoReq *const r =(StartInfoReq*)&signal->theData[0];
- r->startingNodeId = nodeId;
- r->typeStart = typeStart;
- r->systemFailureNo = cfailurenr;
- sendLoopMacro(START_INFOREQ, sendSTART_INFOREQ);
-}//Dbdih::execSTART_PERMREQ()
-
-void Dbdih::execSTART_INFOREF(Signal* signal)
-{
- StartInfoRef * ref = (StartInfoRef*)&signal->theData[0];
- if (getNodeStatus(ref->startingNodeId) != NodeRecord::STARTING) {
- jam();
- return;
- }//if
- ndbrequire(c_nodeStartMaster.startNode == ref->startingNodeId);
- c_nodeStartMaster.startInfoErrorCode = ref->errorCode;
- startInfoReply(signal, ref->sendingNodeId);
-}//Dbdih::execSTART_INFOREF()
-
-void Dbdih::execSTART_INFOCONF(Signal* signal)
-{
- jamEntry();
- StartInfoConf * conf = (StartInfoConf*)&signal->theData[0];
- if (getNodeStatus(conf->startingNodeId) != NodeRecord::STARTING) {
- jam();
- return;
- }//if
- ndbrequire(c_nodeStartMaster.startNode == conf->startingNodeId);
- startInfoReply(signal, conf->sendingNodeId);
-}//Dbdih::execSTART_INFOCONF()
-
-void Dbdih::startInfoReply(Signal* signal, Uint32 nodeId)
-{
- receiveLoopMacro(START_INFOREQ, nodeId);
- /**
- * We're finished with the START_INFOREQ's
- */
- if (c_nodeStartMaster.startInfoErrorCode == 0) {
- jam();
- /**
- * Everything has been a success so far
- */
- StartPermConf * conf = (StartPermConf*)&signal->theData[0];
- conf->startingNodeId = c_nodeStartMaster.startNode;
- conf->systemFailureNo = cfailurenr;
- sendSignal(calcDihBlockRef(c_nodeStartMaster.startNode),
- GSN_START_PERMCONF, signal, StartPermConf::SignalLength, JBB);
- c_nodeStartMaster.m_outstandingGsn = GSN_START_PERMCONF;
- } else {
- jam();
- StartPermRef * ref = (StartPermRef*)&signal->theData[0];
- ref->startingNodeId = c_nodeStartMaster.startNode;
- ref->errorCode = c_nodeStartMaster.startInfoErrorCode;
- sendSignal(calcDihBlockRef(c_nodeStartMaster.startNode),
- GSN_START_PERMREF, signal, StartPermRef::SignalLength, JBB);
- nodeResetStart();
- }//if
-}//Dbdih::startInfoReply()
-
-/*---------------------------------------------------------------------------*/
-/* NODE RESTART CONTINUE REQUEST */
-/*---------------------------------------------------------------------------*/
-// THIS SIGNAL AND THE CODE BELOW IS EXECUTED BY THE MASTER WHEN IT HAS BEEN
-// REQUESTED TO START UP A NEW NODE. The master instructs the starting node
-// how to set up its log for continued execution.
-/*---------------------------------------------------------------------------*/
-void Dbdih::execSTART_MEREQ(Signal* signal)
-{
- StartMeReq * req = (StartMeReq*)&signal->theData[0];
- jamEntry();
- const BlockReference Tblockref = req->startingRef;
- const Uint32 Tnodeid = refToNode(Tblockref);
-
- ndbrequire(isMaster());
- ndbrequire(c_nodeStartMaster.startNode == Tnodeid);
- ndbrequire(getNodeStatus(Tnodeid) == NodeRecord::STARTING);
-
- c_nodeStartMaster.blockLcp = true;
- if ((c_lcpState.lcpStatus != LCP_STATUS_IDLE) &&
- (c_lcpState.lcpStatus != LCP_TCGET)) {
- jam();
- /*-----------------------------------------------------------------------*/
- // WE WILL NOT ALLOW A NODE RESTART TO COME IN WHEN A LOCAL CHECKPOINT IS
- // ONGOING. IT WOULD COMPLICATE THE LCP PROTOCOL TOO MUCH. WE WILL ADD THIS
- // LATER.
- /*-----------------------------------------------------------------------*/
- return;
- }//if
- lcpBlockedLab(signal);
-}//Dbdih::nodeRestartStartRecConfLab()
-
-void Dbdih::lcpBlockedLab(Signal* signal)
-{
- ndbrequire(getNodeStatus(c_nodeStartMaster.startNode)==NodeRecord::STARTING);
- /*------------------------------------------------------------------------*/
- // NOW WE HAVE COPIED ALL INFORMATION IN DICT WE ARE NOW READY TO COPY ALL
- // INFORMATION IN DIH TO THE NEW NODE.
- /*------------------------------------------------------------------------*/
- c_nodeStartMaster.wait = 10;
- signal->theData[0] = DihContinueB::ZCOPY_NODE;
- signal->theData[1] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- c_nodeStartMaster.m_outstandingGsn = GSN_COPY_TABREQ;
-}//Dbdih::lcpBlockedLab()
-
-void Dbdih::nodeDictStartConfLab(Signal* signal)
-{
- /*-------------------------------------------------------------------------*/
- // NOW WE HAVE COPIED BOTH DIH AND DICT INFORMATION. WE ARE NOW READY TO
- // INTEGRATE THE NODE INTO THE LCP AND GCP PROTOCOLS AND TO ALLOW UPDATES OF
- // THE DICTIONARY AGAIN.
- /*-------------------------------------------------------------------------*/
- c_nodeStartMaster.wait = ZFALSE;
- c_nodeStartMaster.blockGcp = true;
- if (cgcpStatus != GCP_READY) {
- /*-----------------------------------------------------------------------*/
- // The global checkpoint is executing. Wait until it is completed before we
- // continue processing the node recovery.
- /*-----------------------------------------------------------------------*/
- jam();
- return;
- }//if
- gcpBlockedLab(signal);
-
- /*-----------------------------------------------------------------*/
- // Report that node restart has completed copy of dictionary.
- /*-----------------------------------------------------------------*/
- signal->theData[0] = NDB_LE_NR_CopyDict;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
-}//Dbdih::nodeDictStartConfLab()
-
-void Dbdih::dihCopyCompletedLab(Signal* signal)
-{
- BlockReference ref = calcDictBlockRef(c_nodeStartMaster.startNode);
- DictStartReq * req = (DictStartReq*)&signal->theData[0];
- req->restartGci = cnewgcp;
- req->senderRef = reference();
- sendSignal(ref, GSN_DICTSTARTREQ,
- signal, DictStartReq::SignalLength, JBB);
- c_nodeStartMaster.m_outstandingGsn = GSN_DICTSTARTREQ;
- c_nodeStartMaster.wait = 0;
-}//Dbdih::dihCopyCompletedLab()
-
-void Dbdih::gcpBlockedLab(Signal* signal)
-{
- /*-----------------------------------------------------------------*/
- // Report that node restart has completed copy of distribution info.
- /*-----------------------------------------------------------------*/
- signal->theData[0] = NDB_LE_NR_CopyDistr;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
-
- /**
- * The node DIH will be part of LCP
- */
- NodeRecordPtr nodePtr;
- nodePtr.i = c_nodeStartMaster.startNode;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- nodePtr.p->m_inclDihLcp = true;
-
- /*-------------------------------------------------------------------------*/
- // NOW IT IS TIME TO INFORM ALL OTHER NODES IN THE CLUSTER OF THE STARTED
- // NODE SUCH THAT THEY ALSO INCLUDE THE NODE IN THE NODE LISTS AND SO FORTH.
- /*------------------------------------------------------------------------*/
- sendLoopMacro(INCL_NODEREQ, sendINCL_NODEREQ);
- /*-------------------------------------------------------------------------*/
- // We also need to send to the starting node to ensure he is aware of the
- // global checkpoint id and the correct state. We do not wait for any reply
- // since the starting node will not send any.
- /*-------------------------------------------------------------------------*/
- Uint32 startVersion = getNodeInfo(c_nodeStartMaster.startNode).m_version;
-
- if ((getMajor(startVersion) == 4 &&
- startVersion >= NDBD_INCL_NODECONF_VERSION_4) ||
- (getMajor(startVersion) == 5 &&
- startVersion >= NDBD_INCL_NODECONF_VERSION_5) ||
- (getMajor(startVersion) > 5))
- {
- c_INCL_NODEREQ_Counter.setWaitingFor(c_nodeStartMaster.startNode);
- }
-
- sendINCL_NODEREQ(signal, c_nodeStartMaster.startNode);
-}//Dbdih::gcpBlockedLab()
-
-/*---------------------------------------------------------------------------*/
-// THIS SIGNAL IS EXECUTED IN BOTH SLAVES AND IN THE MASTER
-/*---------------------------------------------------------------------------*/
-void Dbdih::execINCL_NODECONF(Signal* signal)
-{
- jamEntry();
- Uint32 TstartNode = signal->theData[0];
- Uint32 TsendNodeId_or_blockref = signal->theData[1];
-
- Uint32 blocklist[6];
- blocklist[0] = clocallqhblockref;
- blocklist[1] = clocaltcblockref;
- blocklist[2] = cdictblockref;
- blocklist[3] = numberToRef(BACKUP, getOwnNodeId());
- blocklist[4] = numberToRef(SUMA, getOwnNodeId());
- blocklist[5] = 0;
-
- for (Uint32 i = 0; blocklist[i] != 0; i++)
- {
- if (TsendNodeId_or_blockref == blocklist[i])
- {
- jam();
-
- if (TstartNode != c_nodeStartSlave.nodeId)
- {
- jam();
- warningEvent("Recevied INCL_NODECONF for %u from %s"
- " while %u is starting",
- TstartNode,
- getBlockName(refToBlock(TsendNodeId_or_blockref)),
- c_nodeStartSlave.nodeId);
- return;
- }
-
- if (getNodeStatus(c_nodeStartSlave.nodeId) == NodeRecord::ALIVE &&
- blocklist[i+1] != 0)
- {
- /**
- * Send to next in block list
- */
- jam();
- signal->theData[0] = reference();
- signal->theData[1] = c_nodeStartSlave.nodeId;
- sendSignal(blocklist[i+1], GSN_INCL_NODEREQ, signal, 2, JBB);
- return;
- }
- else
- {
- /**
- * All done, reply to master
- */
- jam();
- signal->theData[0] = c_nodeStartSlave.nodeId;
- signal->theData[1] = cownNodeId;
- sendSignal(cmasterdihref, GSN_INCL_NODECONF, signal, 2, JBB);
-
- c_nodeStartSlave.nodeId = 0;
- return;
- }
- }
- }
-
- if (c_nodeStartMaster.startNode != TstartNode)
- {
- jam();
- warningEvent("Recevied INCL_NODECONF for %u from %u"
- " while %u is starting",
- TstartNode,
- TsendNodeId_or_blockref,
- c_nodeStartMaster.startNode);
- return;
- }
-
- ndbrequire(cmasterdihref = reference());
- receiveLoopMacro(INCL_NODEREQ, TsendNodeId_or_blockref);
-
- CRASH_INSERTION(7128);
- /*-------------------------------------------------------------------------*/
- // Now that we have included the starting node in the node lists in the
- // various blocks we are ready to start the global checkpoint protocol
- /*------------------------------------------------------------------------*/
- c_nodeStartMaster.wait = 11;
- c_nodeStartMaster.blockGcp = false;
-
- signal->theData[0] = reference();
- sendSignal(reference(), GSN_UNBLO_DICTCONF, signal, 1, JBB);
-}//Dbdih::execINCL_NODECONF()
-
-void Dbdih::execUNBLO_DICTCONF(Signal* signal)
-{
- jamEntry();
- c_nodeStartMaster.wait = ZFALSE;
- if (!c_nodeStartMaster.activeState) {
- jam();
- return;
- }//if
-
- CRASH_INSERTION(7129);
- /**-----------------------------------------------------------------------
- * WE HAVE NOW PREPARED IT FOR INCLUSION IN THE LCP PROTOCOL.
- * WE CAN NOW START THE LCP PROTOCOL AGAIN.
- * WE HAVE ALSO MADE THIS FOR THE GCP PROTOCOL.
- * WE ARE READY TO START THE PROTOCOLS AND RESPOND TO THE START REQUEST
- * FROM THE STARTING NODE.
- *------------------------------------------------------------------------*/
-
- StartMeConf * const startMe = (StartMeConf *)&signal->theData[0];
-
- const Uint32 wordPerSignal = StartMeConf::DATA_SIZE;
- const int noOfSignals = ((Sysfile::SYSFILE_SIZE32 + (wordPerSignal - 1)) /
- wordPerSignal);
-
- startMe->startingNodeId = c_nodeStartMaster.startNode;
- startMe->startWord = 0;
-
- const Uint32 ref = calcDihBlockRef(c_nodeStartMaster.startNode);
- for(int i = 0; i < noOfSignals; i++){
- jam();
- { // Do copy
- const int startWord = startMe->startWord;
- for(Uint32 j = 0; j < wordPerSignal; j++){
- startMe->data[j] = sysfileData[j+startWord];
- }
- }
- sendSignal(ref, GSN_START_MECONF, signal, StartMeConf::SignalLength, JBB);
- startMe->startWord += wordPerSignal;
- }//for
- c_nodeStartMaster.m_outstandingGsn = GSN_START_MECONF;
-}//Dbdih::execUNBLO_DICTCONF()
-
-/*---------------------------------------------------------------------------*/
-/* NODE RESTART COPY REQUEST */
-/*---------------------------------------------------------------------------*/
-// A NODE RESTART HAS REACHED ITS FINAL PHASE WHEN THE DATA IS TO BE COPIED
-// TO THE NODE. START_COPYREQ IS EXECUTED BY THE MASTER NODE.
-/*---------------------------------------------------------------------------*/
-void Dbdih::execSTART_COPYREQ(Signal* signal)
-{
- jamEntry();
- Uint32 startNodeId = signal->theData[0];
- //BlockReference startingRef = signal->theData[1];
- ndbrequire(c_nodeStartMaster.startNode == startNodeId);
- /*-------------------------------------------------------------------------*/
- // REPORT Copy process of node restart is now about to start up.
- /*-------------------------------------------------------------------------*/
- signal->theData[0] = NDB_LE_NR_CopyFragsStarted;
- signal->theData[1] = startNodeId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- CRASH_INSERTION(7131);
- nodeRestartTakeOver(signal, startNodeId);
- // BlockReference ref = calcQmgrBlockRef(startNodeId);
- // signal->theData[0] = cownNodeId;
- // Remove comments as soon as I open up the Qmgr block
- // TODO_RONM
- // sendSignal(ref, GSN_ALLOW_NODE_CRASHORD, signal, 1, JBB);
-}//Dbdih::execSTART_COPYREQ()
-
-/*---------------------------------------------------------------------------*/
-/* SLAVE LOGIC FOR NODE RESTART */
-/*---------------------------------------------------------------------------*/
-void Dbdih::execSTART_INFOREQ(Signal* signal)
-{
- jamEntry();
- StartInfoReq *const req =(StartInfoReq*)&signal->theData[0];
- Uint32 startNode = req->startingNodeId;
- if (cfailurenr != req->systemFailureNo) {
- jam();
- //---------------------------------------------------------------
- // A failure occurred since master sent this request. We will ignore
- // this request since the node is already dead that is starting.
- //---------------------------------------------------------------
- return;
- }//if
- CRASH_INSERTION(7123);
- if (isMaster()) {
- jam();
- ndbrequire(getNodeStatus(startNode) == NodeRecord::STARTING);
- } else {
- jam();
- ndbrequire(getNodeStatus(startNode) == NodeRecord::DEAD);
- }//if
- if ((!getAllowNodeStart(startNode)) ||
- (c_nodeStartSlave.nodeId != 0) ||
- (ERROR_INSERTED(7124))) {
- jam();
- StartInfoRef *const ref =(StartInfoRef*)&signal->theData[0];
- ref->startingNodeId = startNode;
- ref->sendingNodeId = cownNodeId;
- ref->errorCode = StartPermRef::ZNODE_START_DISALLOWED_ERROR;
- sendSignal(cmasterdihref, GSN_START_INFOREF, signal,
- StartInfoRef::SignalLength, JBB);
- return;
- }//if
- setNodeStatus(startNode, NodeRecord::STARTING);
- if (req->typeStart == NodeState::ST_INITIAL_NODE_RESTART) {
- jam();
- setAllowNodeStart(startNode, false);
- invalidateNodeLCP(signal, startNode, 0);
- } else {
- jam();
- StartInfoConf * c = (StartInfoConf*)&signal->theData[0];
- c->sendingNodeId = cownNodeId;
- c->startingNodeId = startNode;
- sendSignal(cmasterdihref, GSN_START_INFOCONF, signal,
- StartInfoConf::SignalLength, JBB);
- return;
- }//if
-}//Dbdih::execSTART_INFOREQ()
-
-void Dbdih::execINCL_NODEREQ(Signal* signal)
-{
- jamEntry();
- Uint32 retRef = signal->theData[0];
- Uint32 nodeId = signal->theData[1];
- if (nodeId == getOwnNodeId() && ERROR_INSERTED(7165))
- {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(reference(), GSN_INCL_NODEREQ, signal, 5000, signal->getLength());
- return;
- }
-
- Uint32 tnodeStartFailNr = signal->theData[2];
- currentgcp = signal->theData[4];
- CRASH_INSERTION(7127);
- cnewgcp = currentgcp;
- coldgcp = currentgcp - 1;
- if (!isMaster()) {
- jam();
- /*-----------------------------------------------------------------------*/
- // We don't want to change the state of the master since he can be in the
- // state LCP_TCGET at this time.
- /*-----------------------------------------------------------------------*/
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
- }//if
-
- /*-------------------------------------------------------------------------*/
- // When a node is restarted we must ensure that a lcp will be run
- // as soon as possible and the reset the delay according to the original
- // configuration.
- // Without an initial local checkpoint the new node will not be available.
- /*-------------------------------------------------------------------------*/
- if (getOwnNodeId() == nodeId) {
- jam();
- /*-----------------------------------------------------------------------*/
- // We are the starting node. We came here only to set the global checkpoint
- // id's and the lcp status.
- /*-----------------------------------------------------------------------*/
- CRASH_INSERTION(7171);
- Uint32 masterVersion = getNodeInfo(refToNode(cmasterdihref)).m_version;
-
- if ((NDB_VERSION_MAJOR == 4 &&
- masterVersion >= NDBD_INCL_NODECONF_VERSION_4) ||
- (NDB_VERSION_MAJOR == 5 &&
- masterVersion >= NDBD_INCL_NODECONF_VERSION_5) ||
- (NDB_VERSION_MAJOR > 5))
- {
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = getOwnNodeId();
- sendSignal(cmasterdihref, GSN_INCL_NODECONF, signal, 2, JBB);
- }
- return;
- }//if
- if (getNodeStatus(nodeId) != NodeRecord::STARTING) {
- jam();
- return;
- }//if
- ndbrequire(cfailurenr == tnodeStartFailNr);
- ndbrequire (c_nodeStartSlave.nodeId == 0);
- c_nodeStartSlave.nodeId = nodeId;
-
- ndbrequire (retRef == cmasterdihref);
-
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- Sysfile::ActiveStatus TsaveState = nodePtr.p->activeStatus;
- Uint32 TnodeGroup = nodePtr.p->nodeGroup;
-
- new (nodePtr.p) NodeRecord();
- nodePtr.p->nodeGroup = TnodeGroup;
- nodePtr.p->activeStatus = TsaveState;
- nodePtr.p->nodeStatus = NodeRecord::ALIVE;
- nodePtr.p->useInTransactions = true;
- nodePtr.p->m_inclDihLcp = true;
-
- removeDeadNode(nodePtr);
- insertAlive(nodePtr);
- con_lineNodes++;
-
- /*-------------------------------------------------------------------------*/
- // WE WILL ALSO SEND THE INCLUDE NODE REQUEST TO THE LOCAL LQH BLOCK.
- /*-------------------------------------------------------------------------*/
- signal->theData[0] = reference();
- signal->theData[1] = nodeId;
- signal->theData[2] = currentgcp;
- sendSignal(clocallqhblockref, GSN_INCL_NODEREQ, signal, 3, JBB);
-}//Dbdih::execINCL_NODEREQ()
-
-/* ------------------------------------------------------------------------- */
-// execINCL_NODECONF() is found in the master logic part since it is used by
-// both the master and the slaves.
-/* ------------------------------------------------------------------------- */
-
-/*****************************************************************************/
-/*********** TAKE OVER DECISION MODULE *************/
-/*****************************************************************************/
-// This module contains the subroutines that take the decision whether to take
-// over a node now or not.
-/* ------------------------------------------------------------------------- */
-/* MASTER LOGIC FOR SYSTEM RESTART */
-/* ------------------------------------------------------------------------- */
-// WE ONLY COME HERE IF WE ARE THE MASTER AND WE ARE PERFORMING A SYSTEM
-// RESTART. WE ALSO COME HERE DURING THIS SYSTEM RESTART ONE TIME PER NODE
-// THAT NEEDS TAKE OVER.
-/*---------------------------------------------------------------------------*/
-// WE CHECK IF ANY NODE NEEDS TO BE TAKEN OVER AND THE TAKE OVER HAS NOT YET
-// BEEN STARTED OR COMPLETED.
-/*---------------------------------------------------------------------------*/
-void
-Dbdih::systemRestartTakeOverLab(Signal* signal)
-{
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- jam();
- break;
- /*---------------------------------------------------------------------*/
- // WE HAVE NOT REACHED A STATE YET WHERE THIS NODE NEEDS TO BE TAKEN OVER
- /*---------------------------------------------------------------------*/
- case Sysfile::NS_ActiveMissed_2:
- case Sysfile::NS_NotActive_NotTakenOver:
- jam();
- /*---------------------------------------------------------------------*/
- // THIS NODE IS IN TROUBLE.
- // WE MUST SUCCEED WITH A LOCAL CHECKPOINT WITH THIS NODE TO REMOVE THE
- // DANGER. IF THE NODE IS NOT ALIVE THEN THIS WILL NOT BE
- // POSSIBLE AND WE CAN START THE TAKE OVER IMMEDIATELY IF WE HAVE ANY
- // NODES THAT CAN PERFORM A TAKE OVER.
- /*---------------------------------------------------------------------*/
- if (nodePtr.p->nodeStatus != NodeRecord::ALIVE) {
- jam();
- Uint32 ThotSpareNode = findHotSpare();
- if (ThotSpareNode != RNIL) {
- jam();
- startTakeOver(signal, RNIL, ThotSpareNode, nodePtr.i);
- }//if
- } else if(nodePtr.p->activeStatus == Sysfile::NS_NotActive_NotTakenOver){
- jam();
- /*-------------------------------------------------------------------*/
- // NOT ACTIVE NODES THAT HAVE NOT YET BEEN TAKEN OVER NEEDS TAKE OVER
- // IMMEDIATELY. IF WE ARE ALIVE WE TAKE OVER OUR OWN NODE.
- /*-------------------------------------------------------------------*/
- infoEvent("Take over of node %d started",
- nodePtr.i);
- startTakeOver(signal, RNIL, nodePtr.i, nodePtr.i);
- }//if
- break;
- case Sysfile::NS_TakeOver:
- /**-------------------------------------------------------------------
- * WE MUST HAVE FAILED IN THE MIDDLE OF THE TAKE OVER PROCESS.
- * WE WILL CONCLUDE THE TAKE OVER PROCESS NOW.
- *-------------------------------------------------------------------*/
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- Uint32 takeOverNode = Sysfile::getTakeOverNode(nodePtr.i,
- SYSFILE->takeOver);
- if(takeOverNode == 0){
- jam();
- warningEvent("Bug in take-over code restarting");
- takeOverNode = nodePtr.i;
- }
- startTakeOver(signal, RNIL, nodePtr.i, takeOverNode);
- } else {
- jam();
- /**-------------------------------------------------------------------
- * We are not currently taking over, change our active status.
- *-------------------------------------------------------------------*/
- nodePtr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
- setNodeRestartInfoBits();
- }//if
- break;
- case Sysfile::NS_HotSpare:
- jam();
- break;
- /*---------------------------------------------------------------------*/
- // WE NEED NOT TAKE OVER NODES THAT ARE HOT SPARE.
- /*---------------------------------------------------------------------*/
- case Sysfile::NS_NotDefined:
- jam();
- break;
- /*---------------------------------------------------------------------*/
- // WE NEED NOT TAKE OVER NODES THAT DO NOT EVEN EXIST IN THE CLUSTER.
- /*---------------------------------------------------------------------*/
- default:
- ndbrequire(false);
- break;
- }//switch
- }//for
- /*-------------------------------------------------------------------------*/
- /* NO TAKE OVER HAS BEEN INITIATED. */
- /*-------------------------------------------------------------------------*/
-}//Dbdih::systemRestartTakeOverLab()
-
-/*---------------------------------------------------------------------------*/
-// This subroutine is called as part of node restart in the master node.
-/*---------------------------------------------------------------------------*/
-void Dbdih::nodeRestartTakeOver(Signal* signal, Uint32 startNodeId)
-{
- switch (getNodeActiveStatus(startNodeId)) {
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- case Sysfile::NS_ActiveMissed_2:
- jam();
- /*-----------------------------------------------------------------------*/
- // AN ACTIVE NODE HAS BEEN STARTED. THE ACTIVE NODE MUST THEN GET ALL DATA
- // IT HAD BEFORE ITS CRASH. WE START THE TAKE OVER IMMEDIATELY.
- // SINCE WE ARE AN ACTIVE NODE WE WILL TAKE OVER OUR OWN NODE THAT
- // PREVIOUSLY CRASHED.
- /*-----------------------------------------------------------------------*/
- startTakeOver(signal, RNIL, startNodeId, startNodeId);
- break;
- case Sysfile::NS_HotSpare:{
- jam();
- /*-----------------------------------------------------------------------*/
- // WHEN STARTING UP A HOT SPARE WE WILL CHECK IF ANY NODE NEEDS TO TAKEN
- // OVER. IF SO THEN WE WILL START THE TAKE OVER.
- /*-----------------------------------------------------------------------*/
- bool takeOverStarted = false;
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (nodePtr.p->activeStatus == Sysfile::NS_NotActive_NotTakenOver) {
- jam();
- takeOverStarted = true;
- startTakeOver(signal, RNIL, startNodeId, nodePtr.i);
- }//if
- }//for
- if (!takeOverStarted) {
- jam();
- /*-------------------------------------------------------------------*/
- // NO TAKE OVER WAS NEEDED AT THE MOMENT WE START-UP AND WAIT UNTIL A
- // TAKE OVER IS NEEDED.
- /*-------------------------------------------------------------------*/
- BlockReference ref = calcDihBlockRef(startNodeId);
- signal->theData[0] = startNodeId;
- sendSignal(ref, GSN_START_COPYCONF, signal, 1, JBB);
- }//if
- break;
- }
- case Sysfile::NS_NotActive_NotTakenOver:
- jam();
- /*-----------------------------------------------------------------------*/
- // ALL DATA IN THE NODE IS LOST BUT WE HAVE NOT TAKEN OVER YET. WE WILL
- // TAKE OVER OUR OWN NODE
- /*-----------------------------------------------------------------------*/
- startTakeOver(signal, RNIL, startNodeId, startNodeId);
- break;
- case Sysfile::NS_TakeOver:{
- jam();
- /*--------------------------------------------------------------------
- * We were in the process of taking over but it was not completed.
- * We will complete it now instead.
- *--------------------------------------------------------------------*/
- Uint32 takeOverNode = Sysfile::getTakeOverNode(startNodeId,
- SYSFILE->takeOver);
- if(takeOverNode == 0){
- jam();
- warningEvent("Bug in take-over code restarting");
- takeOverNode = startNodeId;
- }
-
- startTakeOver(signal, RNIL, startNodeId, takeOverNode);
- break;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
- nodeResetStart();
-}//Dbdih::nodeRestartTakeOver()
-
-/*************************************************************************/
-// Ths routine is called when starting a local checkpoint.
-/*************************************************************************/
-void Dbdih::checkStartTakeOver(Signal* signal)
-{
- NodeRecordPtr csoNodeptr;
- Uint32 tcsoHotSpareNode;
- Uint32 tcsoTakeOverNode;
- if (isMaster()) {
- /*-----------------------------------------------------------------*/
- /* WE WILL ONLY START TAKE OVER IF WE ARE MASTER. */
- /*-----------------------------------------------------------------*/
- /* WE WILL ONLY START THE TAKE OVER IF THERE WERE A NEED OF */
- /* A TAKE OVER. */
- /*-----------------------------------------------------------------*/
- /* WE CAN ONLY PERFORM THE TAKE OVER IF WE HAVE A HOT SPARE */
- /* AVAILABLE. */
- /*-----------------------------------------------------------------*/
- tcsoTakeOverNode = 0;
- tcsoHotSpareNode = 0;
- for (csoNodeptr.i = 1; csoNodeptr.i < MAX_NDB_NODES; csoNodeptr.i++) {
- ptrAss(csoNodeptr, nodeRecord);
- if (csoNodeptr.p->activeStatus == Sysfile::NS_NotActive_NotTakenOver) {
- jam();
- tcsoTakeOverNode = csoNodeptr.i;
- } else {
- jam();
- if (csoNodeptr.p->activeStatus == Sysfile::NS_HotSpare) {
- jam();
- tcsoHotSpareNode = csoNodeptr.i;
- }//if
- }//if
- }//for
- if ((tcsoTakeOverNode != 0) &&
- (tcsoHotSpareNode != 0)) {
- jam();
- startTakeOver(signal, RNIL, tcsoHotSpareNode, tcsoTakeOverNode);
- }//if
- }//if
-}//Dbdih::checkStartTakeOver()
-
-/*****************************************************************************/
-/*********** NODE ADDING MODULE *************/
-/*********** CODE TO HANDLE TAKE OVER *************/
-/*****************************************************************************/
-// A take over can be initiated by a number of things:
-// 1) A node restart, usually the node takes over itself but can also take
-// over somebody else if its own data was already taken over
-// 2) At system restart it is necessary to use the take over code to recover
-// nodes which had too old checkpoints to be restorable by the usual
-// restoration from disk.
-// 3) When a node has missed too many local checkpoints and is decided by the
-// master to be taken over by a hot spare node that sits around waiting
-// for this to happen.
-//
-// To support multiple node failures efficiently the code is written such that
-// only one take over can handle transitions in state but during a copy
-// fragment other take over's can perform state transitions.
-/*****************************************************************************/
-void Dbdih::startTakeOver(Signal* signal,
- Uint32 takeOverPtrI,
- Uint32 startNode,
- Uint32 nodeTakenOver)
-{
- NodeRecordPtr toNodePtr;
- NodeGroupRecordPtr NGPtr;
- toNodePtr.i = nodeTakenOver;
- ptrCheckGuard(toNodePtr, MAX_NDB_NODES, nodeRecord);
- NGPtr.i = toNodePtr.p->nodeGroup;
- ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- TakeOverRecordPtr takeOverPtr;
- if (takeOverPtrI == RNIL) {
- jam();
- setAllowNodeStart(startNode, false);
- seizeTakeOver(takeOverPtr);
- if (startNode == c_nodeStartMaster.startNode) {
- jam();
- takeOverPtr.p->toNodeRestart = true;
- }//if
- takeOverPtr.p->toStartingNode = startNode;
- takeOverPtr.p->toFailedNode = nodeTakenOver;
- } else {
- jam();
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
- ndbrequire(takeOverPtr.p->toStartingNode == startNode);
- ndbrequire(takeOverPtr.p->toFailedNode == nodeTakenOver);
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::TO_WAIT_START_TAKE_OVER);
- }//if
- if ((NGPtr.p->activeTakeOver) || (ERROR_INSERTED(7157))) {
- jam();
- /**------------------------------------------------------------------------
- * A take over is already active in this node group. We only allow one
- * take over per node group. Otherwise we will overload the node group and
- * also we will require much more checks when starting up copying of
- * fragments. The parallelism for take over is mainly to ensure that we
- * can handle take over efficiently in large systems with 4 nodes and above
- * A typical case is a 8 node system executing on two 8-cpu boxes.
- * A box crash in one of the boxes will mean 4 nodes crashes.
- * We want to be able to restart those four nodes to some
- * extent in parallel.
- *
- * We will wait for a few seconds and then try again.
- */
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_WAIT_START_TAKE_OVER;
- signal->theData[0] = DihContinueB::ZSTART_TAKE_OVER;
- signal->theData[1] = takeOverPtr.i;
- signal->theData[2] = startNode;
- signal->theData[3] = nodeTakenOver;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 5000, 4);
- return;
- }//if
- NGPtr.p->activeTakeOver = true;
- if (startNode == nodeTakenOver) {
- jam();
- switch (getNodeActiveStatus(nodeTakenOver)) {
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- case Sysfile::NS_ActiveMissed_2:
- jam();
- break;
- case Sysfile::NS_NotActive_NotTakenOver:
- case Sysfile::NS_TakeOver:
- jam();
- setNodeActiveStatus(nodeTakenOver, Sysfile::NS_TakeOver);
- break;
- default:
- ndbrequire(false);
- }//switch
- } else {
- jam();
- setNodeActiveStatus(nodeTakenOver, Sysfile::NS_HotSpare);
- setNodeActiveStatus(startNode, Sysfile::NS_TakeOver);
- changeNodeGroups(startNode, nodeTakenOver);
- }//if
- setNodeRestartInfoBits();
- /* ---------------------------------------------------------------------- */
- /* WE SET THE RESTART INFORMATION TO INDICATE THAT WE ARE ABOUT TO TAKE */
- /* OVER THE FAILED NODE. WE SET THIS INFORMATION AND WAIT UNTIL THE */
- /* GLOBAL CHECKPOINT HAS WRITTEN THE RESTART INFORMATION. */
- /* ---------------------------------------------------------------------- */
- Sysfile::setTakeOverNode(takeOverPtr.p->toFailedNode, SYSFILE->takeOver,
- startNode);
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_START_COPY;
-
- if (getNodeState().getSystemRestartInProgress())
- {
- jam();
- checkToCopy();
- checkToCopyCompleted(signal);
- return;
- }
- cstartGcpNow = true;
-}//Dbdih::startTakeOver()
-
-void Dbdih::changeNodeGroups(Uint32 startNode, Uint32 nodeTakenOver)
-{
- NodeRecordPtr startNodePtr;
- NodeRecordPtr toNodePtr;
- startNodePtr.i = startNode;
- ptrCheckGuard(startNodePtr, MAX_NDB_NODES, nodeRecord);
- toNodePtr.i = nodeTakenOver;
- ptrCheckGuard(toNodePtr, MAX_NDB_NODES, nodeRecord);
- ndbrequire(startNodePtr.p->nodeGroup == ZNIL);
- NodeGroupRecordPtr NGPtr;
-
- NGPtr.i = toNodePtr.p->nodeGroup;
- ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- bool nodeFound = false;
- for (Uint32 i = 0; i < NGPtr.p->nodeCount; i++) {
- jam();
- if (NGPtr.p->nodesInGroup[i] == nodeTakenOver) {
- jam();
- NGPtr.p->nodesInGroup[i] = startNode;
- nodeFound = true;
- }//if
- }//for
- ndbrequire(nodeFound);
- Sysfile::setNodeGroup(startNodePtr.i, SYSFILE->nodeGroups, toNodePtr.p->nodeGroup);
- startNodePtr.p->nodeGroup = toNodePtr.p->nodeGroup;
- Sysfile::setNodeGroup(toNodePtr.i, SYSFILE->nodeGroups, NO_NODE_GROUP_ID);
- toNodePtr.p->nodeGroup = ZNIL;
-}//Dbdih::changeNodeGroups()
-
-void Dbdih::checkToCopy()
-{
- TakeOverRecordPtr takeOverPtr;
- for (takeOverPtr.i = 0;takeOverPtr.i < MAX_NDB_NODES; takeOverPtr.i++) {
- ptrAss(takeOverPtr, takeOverRecord);
- /*----------------------------------------------------------------------*/
- // TAKE OVER HANDLING WRITES RESTART INFORMATION THROUGH
- // THE GLOBAL CHECKPOINT
- // PROTOCOL. WE CHECK HERE BEFORE STARTING A WRITE OF THE RESTART
- // INFORMATION.
- /*-----------------------------------------------------------------------*/
- if (takeOverPtr.p->toMasterStatus == TakeOverRecord::TO_START_COPY) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_START_COPY_ONGOING;
- } else if (takeOverPtr.p->toMasterStatus == TakeOverRecord::TO_END_COPY) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_END_COPY_ONGOING;
- }//if
- }//for
-}//Dbdih::checkToCopy()
-
-void Dbdih::checkToCopyCompleted(Signal* signal)
-{
- /* ------------------------------------------------------------------------*/
- /* WE CHECK HERE IF THE WRITING OF TAKE OVER INFORMATION ALSO HAS BEEN */
- /* COMPLETED. */
- /* ------------------------------------------------------------------------*/
- TakeOverRecordPtr toPtr;
- for (toPtr.i = 0; toPtr.i < MAX_NDB_NODES; toPtr.i++) {
- ptrAss(toPtr, takeOverRecord);
- if (toPtr.p->toMasterStatus == TakeOverRecord::TO_START_COPY_ONGOING){
- jam();
- sendStartTo(signal, toPtr.i);
- } else if (toPtr.p->toMasterStatus == TakeOverRecord::TO_END_COPY_ONGOING){
- jam();
- sendEndTo(signal, toPtr.i);
- } else {
- jam();
- }//if
- }//for
-}//Dbdih::checkToCopyCompleted()
-
-bool Dbdih::checkToInterrupted(TakeOverRecordPtr& takeOverPtr)
-{
- if (checkNodeAlive(takeOverPtr.p->toStartingNode)) {
- jam();
- return false;
- } else {
- jam();
- endTakeOver(takeOverPtr.i);
- return true;
- }//if
-}//Dbdih::checkToInterrupted()
-
-void Dbdih::sendStartTo(Signal* signal, Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- CRASH_INSERTION(7155);
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
- if ((c_startToLock != RNIL) || (ERROR_INSERTED(7158))) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_WAIT_START;
- signal->theData[0] = DihContinueB::ZSEND_START_TO;
- signal->theData[1] = takeOverPtrI;
- signal->theData[2] = takeOverPtr.p->toStartingNode;
- signal->theData[3] = takeOverPtr.p->toFailedNode;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 30, 4);
- return;
- }//if
- c_startToLock = takeOverPtrI;
-
- takeOverPtr.p->toMasterStatus = TakeOverRecord::STARTING;
- StartToReq * const req = (StartToReq *)&signal->theData[0];
- req->userPtr = takeOverPtr.i;
- req->userRef = reference();
- req->startingNodeId = takeOverPtr.p->toStartingNode;
- req->nodeTakenOver = takeOverPtr.p->toFailedNode;
- req->nodeRestart = takeOverPtr.p->toNodeRestart;
- sendLoopMacro(START_TOREQ, sendSTART_TOREQ);
-}//Dbdih::sendStartTo()
-
-void Dbdih::execSTART_TOREQ(Signal* signal)
-{
- TakeOverRecordPtr takeOverPtr;
- jamEntry();
- const StartToReq * const req = (StartToReq *)&signal->theData[0];
- takeOverPtr.i = req->userPtr;
- BlockReference ref = req->userRef;
- Uint32 startingNode = req->startingNodeId;
-
- CRASH_INSERTION(7133);
- RETURN_IF_NODE_NOT_ALIVE(req->startingNodeId);
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- allocateTakeOver(takeOverPtr);
- initStartTakeOver(req, takeOverPtr);
-
- StartToConf * const conf = (StartToConf *)&signal->theData[0];
- conf->userPtr = takeOverPtr.i;
- conf->sendingNodeId = cownNodeId;
- conf->startingNodeId = startingNode;
- sendSignal(ref, GSN_START_TOCONF, signal, StartToConf::SignalLength, JBB);
-}//Dbdih::execSTART_TOREQ()
-
-void Dbdih::execSTART_TOCONF(Signal* signal)
-{
- TakeOverRecordPtr takeOverPtr;
- jamEntry();
- const StartToConf * const conf = (StartToConf *)&signal->theData[0];
-
- CRASH_INSERTION(7147);
-
- RETURN_IF_NODE_NOT_ALIVE(conf->startingNodeId);
-
- takeOverPtr.i = conf->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::STARTING);
- ndbrequire(takeOverPtr.p->toStartingNode == conf->startingNodeId);
- receiveLoopMacro(START_TOREQ, conf->sendingNodeId);
- CRASH_INSERTION(7134);
- c_startToLock = RNIL;
-
- if (takeOverPtr.p->toNodeRestart)
- {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::STARTING_LOCAL_FRAGMENTS;
- nr_start_fragments(signal, takeOverPtr);
- return;
- }
-
- startNextCopyFragment(signal, takeOverPtr.i);
-}//Dbdih::execSTART_TOCONF()
-
-void
-Dbdih::nr_start_fragments(Signal* signal,
- TakeOverRecordPtr takeOverPtr)
-{
- Uint32 loopCount = 0 ;
- TabRecordPtr tabPtr;
- while (loopCount++ < 100) {
- tabPtr.i = takeOverPtr.p->toCurrentTabref;
- if (tabPtr.i >= ctabFileSize) {
- jam();
- nr_run_redo(signal, takeOverPtr);
- return;
- }//if
- ptrAss(tabPtr, tabRecord);
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE ||
- tabPtr.p->tabStorage != TabRecord::ST_NORMAL)
- {
- jam();
- takeOverPtr.p->toCurrentFragid = 0;
- takeOverPtr.p->toCurrentTabref++;
- continue;
- }//if
- Uint32 fragId = takeOverPtr.p->toCurrentFragid;
- if (fragId >= tabPtr.p->totalfragments) {
- jam();
- takeOverPtr.p->toCurrentFragid = 0;
- takeOverPtr.p->toCurrentTabref++;
- continue;
- }//if
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- ReplicaRecordPtr loopReplicaPtr;
- loopReplicaPtr.i = fragPtr.p->oldStoredReplicas;
- while (loopReplicaPtr.i != RNIL) {
- ptrCheckGuard(loopReplicaPtr, creplicaFileSize, replicaRecord);
- if (loopReplicaPtr.p->procNode == takeOverPtr.p->toStartingNode) {
- jam();
- nr_start_fragment(signal, takeOverPtr, loopReplicaPtr);
- break;
- } else {
- jam();
- loopReplicaPtr.i = loopReplicaPtr.p->nextReplica;
- }//if
- }//while
- takeOverPtr.p->toCurrentFragid++;
- }//while
- signal->theData[0] = DihContinueB::ZTO_START_FRAGMENTS;
- signal->theData[1] = takeOverPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Dbdih::nr_start_fragment(Signal* signal,
- TakeOverRecordPtr takeOverPtr,
- ReplicaRecordPtr replicaPtr)
-{
- Uint32 i, j = 0;
- Uint32 maxLcpId = 0;
- Uint32 maxLcpIndex = ~0;
-
- Uint32 restorableGCI = 0;
-
- ndbout_c("tab: %d frag: %d replicaP->nextLcp: %d",
- takeOverPtr.p->toCurrentTabref,
- takeOverPtr.p->toCurrentFragid,
- replicaPtr.p->nextLcp);
-
- Uint32 idx = replicaPtr.p->nextLcp;
- for(i = 0; i<MAX_LCP_STORED; i++, idx = nextLcpNo(idx))
- {
- ndbout_c("scanning idx: %d lcpId: %d", idx, replicaPtr.p->lcpId[idx]);
- if (replicaPtr.p->lcpStatus[idx] == ZVALID)
- {
- ndbrequire(replicaPtr.p->lcpId[idx] > maxLcpId);
- Uint32 stopGci = replicaPtr.p->maxGciStarted[idx];
- for (;j < replicaPtr.p->noCrashedReplicas; j++)
- {
- ndbout_c("crashed replica: %d(%d) replicaLastGci: %d",
- j,
- replicaPtr.p->noCrashedReplicas,
- replicaPtr.p->replicaLastGci[j]);
- if (replicaPtr.p->replicaLastGci[j] > stopGci)
- {
- maxLcpId = replicaPtr.p->lcpId[idx];
- maxLcpIndex = idx;
- restorableGCI = replicaPtr.p->replicaLastGci[j];
- break;
- }
- }
- }
- }
-
- if (maxLcpIndex == ~ (Uint32) 0)
- {
- ndbout_c("Didnt find any LCP for node: %d tab: %d frag: %d",
- takeOverPtr.p->toStartingNode,
- takeOverPtr.p->toCurrentTabref,
- takeOverPtr.p->toCurrentFragid);
- replicaPtr.p->lcpIdStarted = 0;
- BlockReference ref = calcLqhBlockRef(takeOverPtr.p->toStartingNode);
- StartFragReq *req = (StartFragReq *)signal->getDataPtrSend();
- req->userPtr = 0;
- req->userRef = reference();
- req->lcpNo = ZNIL;
- req->lcpId = 0;
- req->tableId = takeOverPtr.p->toCurrentTabref;
- req->fragId = takeOverPtr.p->toCurrentFragid;
- req->noOfLogNodes = 0;
- sendSignal(ref, GSN_START_FRAGREQ, signal,
- StartFragReq::SignalLength, JBB);
- }
- else
- {
- ndbout_c("Found LCP: %d(%d) maxGciStarted: %d maxGciCompleted: %d restorable: %d(%d) newestRestorableGCI: %d",
- maxLcpId,
- maxLcpIndex,
- replicaPtr.p->maxGciStarted[maxLcpIndex],
- replicaPtr.p->maxGciCompleted[maxLcpIndex],
- restorableGCI,
- SYSFILE->lastCompletedGCI[takeOverPtr.p->toStartingNode],
- SYSFILE->newestRestorableGCI);
-
- replicaPtr.p->lcpIdStarted = restorableGCI;
- BlockReference ref = calcLqhBlockRef(takeOverPtr.p->toStartingNode);
- StartFragReq *req = (StartFragReq *)signal->getDataPtrSend();
- req->userPtr = 0;
- req->userRef = reference();
- req->lcpNo = maxLcpIndex;
- req->lcpId = maxLcpId;
- req->tableId = takeOverPtr.p->toCurrentTabref;
- req->fragId = takeOverPtr.p->toCurrentFragid;
- req->noOfLogNodes = 1;
- req->lqhLogNode[0] = takeOverPtr.p->toStartingNode;
- req->startGci[0] = replicaPtr.p->maxGciCompleted[maxLcpIndex];
- req->lastGci[0] = restorableGCI;
- sendSignal(ref, GSN_START_FRAGREQ, signal,
- StartFragReq::SignalLength, JBB);
- }
-}
-
-void
-Dbdih::nr_run_redo(Signal* signal, TakeOverRecordPtr takeOverPtr)
-{
- takeOverPtr.p->toCurrentTabref = 0;
- takeOverPtr.p->toCurrentFragid = 0;
- sendSTART_RECREQ(signal, takeOverPtr.p->toStartingNode);
-}
-
-void Dbdih::initStartTakeOver(const StartToReq * req,
- TakeOverRecordPtr takeOverPtr)
-{
- takeOverPtr.p->toCurrentTabref = 0;
- takeOverPtr.p->toCurrentFragid = 0;
- takeOverPtr.p->toStartingNode = req->startingNodeId;
- takeOverPtr.p->toFailedNode = req->nodeTakenOver;
- takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SLAVE_STARTED;
- takeOverPtr.p->toCopyNode = RNIL;
- takeOverPtr.p->toCurrentReplica = RNIL;
- takeOverPtr.p->toNodeRestart = req->nodeRestart;
-}//Dbdih::initStartTakeOver()
-
-void Dbdih::startNextCopyFragment(Signal* signal, Uint32 takeOverPtrI)
-{
- TabRecordPtr tabPtr;
- TakeOverRecordPtr takeOverPtr;
- Uint32 loopCount;
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
- takeOverPtr.p->toMasterStatus = TakeOverRecord::SELECTING_NEXT;
- loopCount = 0;
- if (ERROR_INSERTED(7159)) {
- loopCount = 100;
- }//if
- while (loopCount++ < 100) {
- tabPtr.i = takeOverPtr.p->toCurrentTabref;
- if (tabPtr.i >= ctabFileSize) {
- jam();
- CRASH_INSERTION(7136);
- sendUpdateTo(signal, takeOverPtr.i, UpdateToReq::TO_COPY_COMPLETED);
- return;
- }//if
- ptrAss(tabPtr, tabRecord);
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE){
- jam();
- takeOverPtr.p->toCurrentFragid = 0;
- takeOverPtr.p->toCurrentTabref++;
- continue;
- }//if
- Uint32 fragId = takeOverPtr.p->toCurrentFragid;
- if (fragId >= tabPtr.p->totalfragments) {
- jam();
- takeOverPtr.p->toCurrentFragid = 0;
- takeOverPtr.p->toCurrentTabref++;
- if (ERROR_INSERTED(7135)) {
- if (takeOverPtr.p->toCurrentTabref == 1) {
- ndbrequire(false);
- }//if
- }//if
- continue;
- }//if
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- ReplicaRecordPtr loopReplicaPtr;
- loopReplicaPtr.i = fragPtr.p->oldStoredReplicas;
- while (loopReplicaPtr.i != RNIL) {
- ptrCheckGuard(loopReplicaPtr, creplicaFileSize, replicaRecord);
- if (loopReplicaPtr.p->procNode == takeOverPtr.p->toFailedNode) {
- jam();
- /* ----------------------------------------------------------------- */
- /* WE HAVE FOUND A REPLICA THAT BELONGED THE FAILED NODE THAT NEEDS */
- /* TAKE OVER. WE TAKE OVER THIS REPLICA TO THE NEW NODE. */
- /* ----------------------------------------------------------------- */
- takeOverPtr.p->toCurrentReplica = loopReplicaPtr.i;
- toCopyFragLab(signal, takeOverPtr.i);
- return;
- } else if (loopReplicaPtr.p->procNode == takeOverPtr.p->toStartingNode) {
- jam();
- /* ----------------------------------------------------------------- */
- /* WE HAVE OBVIOUSLY STARTED TAKING OVER THIS WITHOUT COMPLETING IT. */
- /* WE */
- /* NEED TO COMPLETE THE TAKE OVER OF THIS REPLICA. */
- /* ----------------------------------------------------------------- */
- takeOverPtr.p->toCurrentReplica = loopReplicaPtr.i;
- toCopyFragLab(signal, takeOverPtr.i);
- return;
- } else {
- jam();
- loopReplicaPtr.i = loopReplicaPtr.p->nextReplica;
- }//if
- }//while
- takeOverPtr.p->toCurrentFragid++;
- }//while
- signal->theData[0] = DihContinueB::ZTO_START_COPY_FRAG;
- signal->theData[1] = takeOverPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}//Dbdih::startNextCopyFragment()
-
-void Dbdih::toCopyFragLab(Signal* signal,
- Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
-
- /**
- * Inform starting node that TakeOver is about to start
- */
- Uint32 nodeId = takeOverPtr.p->toStartingNode;
-
- Uint32 version = getNodeInfo(nodeId).m_version;
- if (ndb_check_prep_copy_frag_version(version))
- {
- jam();
- TabRecordPtr tabPtr;
- tabPtr.i = takeOverPtr.p->toCurrentTabref;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, takeOverPtr.p->toCurrentFragid, fragPtr);
- Uint32 nodes[MAX_REPLICAS];
- extractNodeInfo(fragPtr.p, nodes);
-
- PrepareCopyFragReq* req= (PrepareCopyFragReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = takeOverPtrI;
- req->tableId = takeOverPtr.p->toCurrentTabref;
- req->fragId = takeOverPtr.p->toCurrentFragid;
- req->copyNodeId = nodes[0]; // Src
- req->startingNodeId = takeOverPtr.p->toStartingNode; // Dst
- Uint32 ref = calcLqhBlockRef(takeOverPtr.p->toStartingNode);
-
- sendSignal(ref, GSN_PREPARE_COPY_FRAG_REQ, signal,
- PrepareCopyFragReq::SignalLength, JBB);
-
- takeOverPtr.p->toMasterStatus = TakeOverRecord::PREPARE_COPY;
- return;
- }
-
- takeOverPtr.p->maxPage = RNIL;
- toStartCopyFrag(signal, takeOverPtr);
-}
-
-void
-Dbdih::execPREPARE_COPY_FRAG_REF(Signal* signal)
-{
- jamEntry();
- PrepareCopyFragRef ref = *(PrepareCopyFragRef*)signal->getDataPtr();
-
- TakeOverRecordPtr takeOverPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(ref.senderData, takeOverPtr);
-
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::PREPARE_COPY);
-
- /**
- * Treat this as copy frag ref
- */
- CopyFragRef * cfref = (CopyFragRef*)signal->getDataPtrSend();
- cfref->userPtr = ref.senderData;
- cfref->startingNodeId = ref.startingNodeId;
- cfref->errorCode = ref.errorCode;
- cfref->tableId = ref.tableId;
- cfref->fragId = ref.fragId;
- cfref->sendingNodeId = ref.copyNodeId;
- takeOverPtr.p->toMasterStatus = TakeOverRecord::COPY_FRAG;
- execCOPY_FRAGREF(signal);
-}
-
-void
-Dbdih::execPREPARE_COPY_FRAG_CONF(Signal* signal)
-{
- PrepareCopyFragConf conf = *(PrepareCopyFragConf*)signal->getDataPtr();
-
- TakeOverRecordPtr takeOverPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(conf.senderData, takeOverPtr);
-
- Uint32 version = getNodeInfo(refToNode(conf.senderRef)).m_version;
- if (ndb_check_prep_copy_frag_version(version) >= 2)
- {
- jam();
- takeOverPtr.p->maxPage = conf.maxPageNo;
- }
- else
- {
- jam();
- takeOverPtr.p->maxPage = RNIL;
- }
- toStartCopyFrag(signal, takeOverPtr);
-}
-
-void
-Dbdih::toStartCopyFrag(Signal* signal, TakeOverRecordPtr takeOverPtr)
-{
- CreateReplicaRecordPtr createReplicaPtr;
- createReplicaPtr.i = 0;
- ptrAss(createReplicaPtr, createReplicaRecord);
-
- ReplicaRecordPtr replicaPtr;
- replicaPtr.i = takeOverPtr.p->toCurrentReplica;
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
-
- TabRecordPtr tabPtr;
- tabPtr.i = takeOverPtr.p->toCurrentTabref;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- /* ----------------------------------------------------------------------- */
- /* WE HAVE FOUND A REPLICA THAT NEEDS TAKE OVER. WE WILL START THIS TAKE */
- /* OVER BY ADDING THE FRAGMENT WHEREAFTER WE WILL ORDER THE PRIMARY */
- /* REPLICA TO COPY ITS CONTENT TO THE NEW STARTING REPLICA. */
- /* THIS OPERATION IS A SINGLE USER OPERATION UNTIL WE HAVE SENT */
- /* COPY_FRAGREQ. AFTER SENDING COPY_FRAGREQ WE ARE READY TO START A NEW */
- /* FRAGMENT REPLICA. WE WILL NOT IMPLEMENT THIS IN THE FIRST PHASE. */
- /* ----------------------------------------------------------------------- */
- cnoOfCreateReplicas = 1;
- createReplicaPtr.p->hotSpareUse = true;
- createReplicaPtr.p->dataNodeId = takeOverPtr.p->toStartingNode;
-
- prepareSendCreateFragReq(signal, takeOverPtr.i);
-}//Dbdih::toStartCopy()
-
-void Dbdih::prepareSendCreateFragReq(Signal* signal, Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
-
- TabRecordPtr tabPtr;
- tabPtr.i = takeOverPtr.p->toCurrentTabref;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- FragmentstorePtr fragPtr;
-
- getFragstore(tabPtr.p, takeOverPtr.p->toCurrentFragid, fragPtr);
- Uint32 nodes[MAX_REPLICAS];
- extractNodeInfo(fragPtr.p, nodes);
- takeOverPtr.p->toCopyNode = nodes[0];
- sendCreateFragReq(signal, 0, CreateFragReq::STORED, takeOverPtr.i);
-}//Dbdih::prepareSendCreateFragReq()
-
-void Dbdih::sendCreateFragReq(Signal* signal,
- Uint32 startGci,
- Uint32 replicaType,
- Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
- if ((c_createFragmentLock != RNIL) ||
- ((ERROR_INSERTED(7161))&&(replicaType == CreateFragReq::STORED)) ||
- ((ERROR_INSERTED(7162))&&(replicaType == CreateFragReq::COMMIT_STORED))){
- if (replicaType == CreateFragReq::STORED) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_WAIT_PREPARE_CREATE;
- } else {
- ndbrequire(replicaType == CreateFragReq::COMMIT_STORED);
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_WAIT_COMMIT_CREATE;
- }//if
- signal->theData[0] = DihContinueB::ZSEND_CREATE_FRAG;
- signal->theData[1] = takeOverPtr.i;
- signal->theData[2] = replicaType;
- signal->theData[3] = startGci;
- signal->theData[4] = takeOverPtr.p->toStartingNode;
- signal->theData[5] = takeOverPtr.p->toFailedNode;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 50, 6);
- return;
- }//if
- c_createFragmentLock = takeOverPtr.i;
- sendLoopMacro(CREATE_FRAGREQ, nullRoutine);
-
- CreateFragReq * const req = (CreateFragReq *)&signal->theData[0];
- req->userPtr = takeOverPtr.i;
- req->userRef = reference();
- req->tableId = takeOverPtr.p->toCurrentTabref;
- req->fragId = takeOverPtr.p->toCurrentFragid;
- req->startingNodeId = takeOverPtr.p->toStartingNode;
- req->copyNodeId = takeOverPtr.p->toCopyNode;
- req->startGci = startGci;
- req->replicaType = replicaType;
-
- NodeRecordPtr nodePtr;
- nodePtr.i = cfirstAliveNode;
- do {
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- BlockReference ref = calcDihBlockRef(nodePtr.i);
- sendSignal(ref, GSN_CREATE_FRAGREQ, signal,
- CreateFragReq::SignalLength, JBB);
- nodePtr.i = nodePtr.p->nextNode;
- } while (nodePtr.i != RNIL);
-
- if (replicaType == CreateFragReq::STORED) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::PREPARE_CREATE;
- } else {
- ndbrequire(replicaType == CreateFragReq::COMMIT_STORED);
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::COMMIT_CREATE;
- }
-}//Dbdih::sendCreateFragReq()
-
-/* --------------------------------------------------------------------------*/
-/* AN ORDER TO START OR COMMIT THE REPLICA CREATION ARRIVED FROM THE */
-/* MASTER. */
-/* --------------------------------------------------------------------------*/
-void Dbdih::execCREATE_FRAGREQ(Signal* signal)
-{
- jamEntry();
- CreateFragReq * const req = (CreateFragReq *)&signal->theData[0];
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = req->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- BlockReference retRef = req->userRef;
-
- TabRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- Uint32 fragId = req->fragId;
- Uint32 tdestNodeid = req->startingNodeId;
- Uint32 tsourceNodeid = req->copyNodeId;
- Uint32 startGci = req->startGci;
- Uint32 replicaType = req->replicaType;
-
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- RETURN_IF_NODE_NOT_ALIVE(tdestNodeid);
- ReplicaRecordPtr frReplicaPtr;
- findToReplica(takeOverPtr.p, replicaType, fragPtr, frReplicaPtr);
- ndbrequire(frReplicaPtr.i != RNIL);
-
- switch (replicaType) {
- case CreateFragReq::STORED:
- jam();
- CRASH_INSERTION(7138);
- /* ----------------------------------------------------------------------*/
- /* HERE WE ARE INSERTING THE NEW BACKUP NODE IN THE EXECUTION OF ALL */
- /* OPERATIONS. FROM HERE ON ALL OPERATIONS ON THIS FRAGMENT WILL INCLUDE*/
- /* USE OF THE NEW REPLICA. */
- /* --------------------------------------------------------------------- */
- insertBackup(fragPtr, tdestNodeid);
- takeOverPtr.p->toCopyNode = tsourceNodeid;
- takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SLAVE_CREATE_PREPARE;
-
- fragPtr.p->distributionKey++;
- fragPtr.p->distributionKey &= 255;
- break;
- case CreateFragReq::COMMIT_STORED:
- jam();
- CRASH_INSERTION(7139);
- /* ----------------------------------------------------------------------*/
- /* HERE WE ARE MOVING THE REPLICA TO THE STORED SECTION SINCE IT IS NOW */
- /* FULLY LOADED WITH ALL DATA NEEDED. */
- // We also update the order of the replicas here so that if the new
- // replica is the desired primary we insert it as primary.
- /* ----------------------------------------------------------------------*/
- takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SLAVE_CREATE_COMMIT;
- removeOldStoredReplica(fragPtr, frReplicaPtr);
- linkStoredReplica(fragPtr, frReplicaPtr);
- updateNodeInfo(fragPtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
-
- /* ------------------------------------------------------------------------*/
- /* THE NEW NODE OF THIS REPLICA IS THE STARTING NODE. */
- /* ------------------------------------------------------------------------*/
- if (frReplicaPtr.p->procNode != takeOverPtr.p->toStartingNode) {
- jam();
- /* ---------------------------------------------------------------------*/
- /* IF WE ARE STARTING A TAKE OVER NODE WE MUST INVALIDATE ALL LCP'S. */
- /* OTHERWISE WE WILL TRY TO START LCP'S THAT DO NOT EXIST. */
- /* ---------------------------------------------------------------------*/
- frReplicaPtr.p->procNode = takeOverPtr.p->toStartingNode;
- frReplicaPtr.p->noCrashedReplicas = 0;
- frReplicaPtr.p->createGci[0] = startGci;
- ndbrequire(startGci != 0xF1F1F1F1);
- frReplicaPtr.p->replicaLastGci[0] = (Uint32)-1;
- for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
- frReplicaPtr.p->lcpStatus[i] = ZINVALID;
- }//for
- } else {
- jam();
- const Uint32 noCrashed = frReplicaPtr.p->noCrashedReplicas;
- arrGuard(noCrashed, 8);
- frReplicaPtr.p->createGci[noCrashed] = startGci;
- ndbrequire(startGci != 0xF1F1F1F1);
- frReplicaPtr.p->replicaLastGci[noCrashed] = (Uint32)-1;
- }//if
- takeOverPtr.p->toCurrentTabref = tabPtr.i;
- takeOverPtr.p->toCurrentFragid = fragId;
- CreateFragConf * const conf = (CreateFragConf *)&signal->theData[0];
- conf->userPtr = takeOverPtr.i;
- conf->tableId = tabPtr.i;
- conf->fragId = fragId;
- conf->sendingNodeId = cownNodeId;
- conf->startingNodeId = tdestNodeid;
- sendSignal(retRef, GSN_CREATE_FRAGCONF, signal,
- CreateFragConf::SignalLength, JBB);
-}//Dbdih::execCREATE_FRAGREQ()
-
-void Dbdih::execCREATE_FRAGCONF(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(7148);
- const CreateFragConf * const conf = (CreateFragConf *)&signal->theData[0];
- Uint32 fragId = conf->fragId;
-
- RETURN_IF_NODE_NOT_ALIVE(conf->startingNodeId);
-
- TabRecordPtr tabPtr;
- tabPtr.i = conf->tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = conf->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- ndbrequire(tabPtr.i == takeOverPtr.p->toCurrentTabref);
- ndbrequire(fragId == takeOverPtr.p->toCurrentFragid);
- receiveLoopMacro(CREATE_FRAGREQ, conf->sendingNodeId);
- c_createFragmentLock = RNIL;
-
- if (takeOverPtr.p->toMasterStatus == TakeOverRecord::PREPARE_CREATE) {
- jam();
- CRASH_INSERTION(7140);
- /* --------------------------------------------------------------------- */
- /* ALL NODES HAVE PREPARED THE INTRODUCTION OF THIS NEW NODE AND IT IS */
- /* ALREADY IN USE. WE CAN NOW START COPYING THE FRAGMENT. */
- /*---------------------------------------------------------------------- */
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- Uint32 gci = 0;
- if (takeOverPtr.p->toNodeRestart)
- {
- ReplicaRecordPtr replicaPtr;
- findReplica(replicaPtr, fragPtr.p, takeOverPtr.p->toStartingNode, true);
- gci = replicaPtr.p->lcpIdStarted;
- replicaPtr.p->lcpIdStarted = 0;
- }
- takeOverPtr.p->toMasterStatus = TakeOverRecord::COPY_FRAG;
- BlockReference ref = calcLqhBlockRef(takeOverPtr.p->toCopyNode);
- CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
- copyFragReq->userPtr = takeOverPtr.i;
- copyFragReq->userRef = reference();
- copyFragReq->tableId = tabPtr.i;
- copyFragReq->fragId = fragId;
- copyFragReq->nodeId = takeOverPtr.p->toStartingNode;
- copyFragReq->schemaVersion = tabPtr.p->schemaVersion;
- copyFragReq->distributionKey = fragPtr.p->distributionKey;
- copyFragReq->gci = gci;
- Uint32 len = copyFragReq->nodeCount =
- extractNodeInfo(fragPtr.p,
- copyFragReq->nodeList);
- copyFragReq->nodeList[len] = takeOverPtr.p->maxPage;
- sendSignal(ref, GSN_COPY_FRAGREQ, signal,
- CopyFragReq::SignalLength + len, JBB);
- } else {
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COMMIT_CREATE);
- jam();
- CRASH_INSERTION(7141);
- /* --------------------------------------------------------------------- */
- // REPORT that copy of fragment has been completed.
- /* --------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_NR_CopyFragDone;
- signal->theData[1] = takeOverPtr.p->toStartingNode;
- signal->theData[2] = tabPtr.i;
- signal->theData[3] = takeOverPtr.p->toCurrentFragid;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
- /* --------------------------------------------------------------------- */
- /* WE HAVE NOW CREATED THIS NEW REPLICA AND WE ARE READY TO TAKE THE */
- /* THE NEXT REPLICA. */
- /* --------------------------------------------------------------------- */
-
- Mutex mutex(signal, c_mutexMgr, takeOverPtr.p->m_switchPrimaryMutexHandle);
- mutex.unlock(); // ignore result
-
- takeOverPtr.p->toCurrentFragid++;
- startNextCopyFragment(signal, takeOverPtr.i);
- }//if
-}//Dbdih::execCREATE_FRAGCONF()
-
-void Dbdih::execCOPY_FRAGREF(Signal* signal)
-{
- const CopyFragRef * const ref = (CopyFragRef *)&signal->theData[0];
- jamEntry();
- Uint32 takeOverPtrI = ref->userPtr;
- Uint32 startingNodeId = ref->startingNodeId;
- Uint32 errorCode = ref->errorCode;
-
- TakeOverRecordPtr takeOverPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
- ndbrequire(errorCode != ZNODE_FAILURE_ERROR);
- ndbrequire(ref->tableId == takeOverPtr.p->toCurrentTabref);
- ndbrequire(ref->fragId == takeOverPtr.p->toCurrentFragid);
- ndbrequire(ref->startingNodeId == takeOverPtr.p->toStartingNode);
- ndbrequire(ref->sendingNodeId == takeOverPtr.p->toCopyNode);
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COPY_FRAG);
- endTakeOver(takeOverPtrI);
- //--------------------------------------------------------------------------
- // For some reason we did not succeed in copying a fragment. We treat this
- // as a serious failure and crash the starting node.
- //--------------------------------------------------------------------------
- BlockReference cntrRef = calcNdbCntrBlockRef(startingNodeId);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::CopyFragRefError;
- sysErr->errorRef = reference();
- sysErr->data1 = errorCode;
- sysErr->data2 = 0;
- sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBB);
- return;
-}//Dbdih::execCOPY_FRAGREF()
-
-void Dbdih::execCOPY_FRAGCONF(Signal* signal)
-{
- const CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
- jamEntry();
- CRASH_INSERTION(7142);
-
- TakeOverRecordPtr takeOverPtr;
- Uint32 takeOverPtrI = conf->userPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
-
- ndbrequire(conf->tableId == takeOverPtr.p->toCurrentTabref);
- ndbrequire(conf->fragId == takeOverPtr.p->toCurrentFragid);
- ndbrequire(conf->startingNodeId == takeOverPtr.p->toStartingNode);
- ndbrequire(conf->sendingNodeId == takeOverPtr.p->toCopyNode);
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COPY_FRAG);
- sendUpdateTo(signal, takeOverPtr.i,
- (Uint32)UpdateToReq::TO_COPY_FRAG_COMPLETED);
-}//Dbdih::execCOPY_FRAGCONF()
-
-void Dbdih::sendUpdateTo(Signal* signal,
- Uint32 takeOverPtrI, Uint32 updateState)
-{
- TakeOverRecordPtr takeOverPtr;
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
- if ((c_updateToLock != RNIL) ||
- ((ERROR_INSERTED(7163)) &&
- (updateState == UpdateToReq::TO_COPY_FRAG_COMPLETED)) ||
- ((ERROR_INSERTED(7169)) &&
- (updateState == UpdateToReq::TO_COPY_COMPLETED))) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_WAIT_UPDATE_TO;
- signal->theData[0] = DihContinueB::ZSEND_UPDATE_TO;
- signal->theData[1] = takeOverPtrI;
- signal->theData[2] = takeOverPtr.p->toStartingNode;
- signal->theData[3] = takeOverPtr.p->toFailedNode;
- signal->theData[4] = updateState;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 30, 5);
- return;
- }//if
- c_updateToLock = takeOverPtrI;
- if (updateState == UpdateToReq::TO_COPY_FRAG_COMPLETED) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_UPDATE_TO;
- } else {
- jam();
- ndbrequire(updateState == UpdateToReq::TO_COPY_COMPLETED);
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_COPY_COMPLETED;
- }//if
-
- UpdateToReq * const req = (UpdateToReq *)&signal->theData[0];
- req->userPtr = takeOverPtr.i;
- req->userRef = reference();
- req->updateState = (UpdateToReq::UpdateState)updateState;
- req->startingNodeId = takeOverPtr.p->toStartingNode;
- req->tableId = takeOverPtr.p->toCurrentTabref;
- req->fragmentNo = takeOverPtr.p->toCurrentFragid;
- sendLoopMacro(UPDATE_TOREQ, sendUPDATE_TOREQ);
-}//Dbdih::sendUpdateTo()
-
-void Dbdih::execUPDATE_TOREQ(Signal* signal)
-{
- jamEntry();
- const UpdateToReq * const req = (UpdateToReq *)&signal->theData[0];
- BlockReference ref = req->userRef;
- ndbrequire(cmasterdihref == ref);
-
- CRASH_INSERTION(7154);
- RETURN_IF_NODE_NOT_ALIVE(req->startingNodeId);
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = req->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- ndbrequire(req->startingNodeId == takeOverPtr.p->toStartingNode);
- if (req->updateState == UpdateToReq::TO_COPY_FRAG_COMPLETED) {
- jam();
- ndbrequire(takeOverPtr.p->toSlaveStatus == TakeOverRecord::TO_SLAVE_CREATE_PREPARE);
- takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SLAVE_COPY_FRAG_COMPLETED;
- takeOverPtr.p->toCurrentTabref = req->tableId;
- takeOverPtr.p->toCurrentFragid = req->fragmentNo;
- } else {
- jam();
- ndbrequire(req->updateState == UpdateToReq::TO_COPY_COMPLETED);
- takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SLAVE_COPY_COMPLETED;
- setNodeCopyCompleted(takeOverPtr.p->toStartingNode, true);
- }//if
-
-
- UpdateToConf * const conf = (UpdateToConf *)&signal->theData[0];
- conf->userPtr = takeOverPtr.i;
- conf->sendingNodeId = cownNodeId;
- conf->startingNodeId = takeOverPtr.p->toStartingNode;
- sendSignal(ref, GSN_UPDATE_TOCONF, signal, UpdateToConf::SignalLength, JBB);
-}//Dbdih::execUPDATE_TOREQ()
-
-void Dbdih::execUPDATE_TOCONF(Signal* signal)
-{
- const UpdateToConf * const conf = (UpdateToConf *)&signal->theData[0];
- CRASH_INSERTION(7152);
-
- RETURN_IF_NODE_NOT_ALIVE(conf->startingNodeId);
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = conf->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- receiveLoopMacro(UPDATE_TOREQ, conf->sendingNodeId);
- CRASH_INSERTION(7153);
- c_updateToLock = RNIL;
-
- if (takeOverPtr.p->toMasterStatus == TakeOverRecord::TO_COPY_COMPLETED) {
- jam();
- toCopyCompletedLab(signal, takeOverPtr);
- return;
- } else {
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::TO_UPDATE_TO);
- }//if
- TabRecordPtr tabPtr;
- tabPtr.i = takeOverPtr.p->toCurrentTabref;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, takeOverPtr.p->toCurrentFragid, fragPtr);
- takeOverPtr.p->toMasterStatus = TakeOverRecord::COPY_ACTIVE;
- BlockReference lqhRef = calcLqhBlockRef(takeOverPtr.p->toStartingNode);
- CopyActiveReq * const req = (CopyActiveReq *)&signal->theData[0];
- req->userPtr = takeOverPtr.i;
- req->userRef = reference();
- req->tableId = takeOverPtr.p->toCurrentTabref;
- req->fragId = takeOverPtr.p->toCurrentFragid;
- req->distributionKey = fragPtr.p->distributionKey;
-
- sendSignal(lqhRef, GSN_COPY_ACTIVEREQ, signal,
- CopyActiveReq::SignalLength, JBB);
-}//Dbdih::execUPDATE_TOCONF()
-
-void Dbdih::execCOPY_ACTIVECONF(Signal* signal)
-{
- const CopyActiveConf * const conf = (CopyActiveConf *)&signal->theData[0];
- jamEntry();
- CRASH_INSERTION(7143);
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = conf->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- ndbrequire(conf->tableId == takeOverPtr.p->toCurrentTabref);
- ndbrequire(conf->fragId == takeOverPtr.p->toCurrentFragid);
- ndbrequire(checkNodeAlive(conf->startingNodeId));
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COPY_ACTIVE);
-
- takeOverPtr.p->startGci = conf->startGci;
- takeOverPtr.p->toMasterStatus = TakeOverRecord::LOCK_MUTEX;
-
- Mutex mutex(signal, c_mutexMgr, takeOverPtr.p->m_switchPrimaryMutexHandle);
- Callback c = { safe_cast(&Dbdih::switchPrimaryMutex_locked), takeOverPtr.i };
- ndbrequire(mutex.lock(c));
-}//Dbdih::execCOPY_ACTIVECONF()
-
-void
-Dbdih::switchPrimaryMutex_locked(Signal* signal, Uint32 toPtrI, Uint32 retVal){
- jamEntry();
- ndbrequire(retVal == 0);
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = toPtrI;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::LOCK_MUTEX);
-
- if (!checkNodeAlive((takeOverPtr.p->toStartingNode))) {
- // We have mutex
- Mutex mutex(signal, c_mutexMgr, takeOverPtr.p->m_switchPrimaryMutexHandle);
- mutex.unlock(); // Ignore result
-
- c_createFragmentLock = RNIL;
- c_CREATE_FRAGREQ_Counter.clearWaitingFor();
- endTakeOver(takeOverPtr.i);
- return;
- }
-
- takeOverPtr.p->toMasterStatus = TakeOverRecord::COMMIT_CREATE;
- sendCreateFragReq(signal, takeOverPtr.p->startGci,
- CreateFragReq::COMMIT_STORED, takeOverPtr.i);
-}
-
-void Dbdih::toCopyCompletedLab(Signal * signal, TakeOverRecordPtr takeOverPtr)
-{
- signal->theData[0] = NDB_LE_NR_CopyFragsCompleted;
- signal->theData[1] = takeOverPtr.p->toStartingNode;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- if (getNodeState().getSystemRestartInProgress())
- {
- jam();
- infoEvent("Take over of node %d complete", takeOverPtr.p->toStartingNode);
- setNodeActiveStatus(takeOverPtr.p->toStartingNode, Sysfile::NS_Active);
- takeOverPtr.p->toMasterStatus = TakeOverRecord::WAIT_LCP;
- takeOverCompleted(takeOverPtr.p->toStartingNode);
- checkToCopy();
- checkToCopyCompleted(signal);
- return;
- }
-
- c_lcpState.immediateLcpStart = true;
- takeOverPtr.p->toMasterStatus = TakeOverRecord::WAIT_LCP;
-
- /*-----------------------------------------------------------------------*/
- /* NOW WE CAN ALLOW THE NEW NODE TO PARTICIPATE IN LOCAL CHECKPOINTS. */
- /* WHEN THE FIRST LOCAL CHECKPOINT IS READY WE DECLARE THE TAKE OVER AS */
- /* COMPLETED. SINCE LOCAL CHECKPOINTS HAVE BEEN BLOCKED DURING THE COPY */
- /* PROCESS WE MUST ALSO START A NEW LOCAL CHECKPOINT PROCESS BY ENSURING */
- /* THAT IT LOOKS LIKE IT IS TIME FOR A NEW LOCAL CHECKPOINT AND BY */
- /* UNBLOCKING THE LOCAL CHECKPOINT AGAIN. */
- /* --------------------------------------------------------------------- */
-}//Dbdih::toCopyCompletedLab()
-
-void Dbdih::sendEndTo(Signal* signal, Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- CRASH_INSERTION(7156);
- RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr);
- if ((c_endToLock != RNIL) || (ERROR_INSERTED(7164))) {
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_WAIT_ENDING;
- signal->theData[0] = DihContinueB::ZSEND_END_TO;
- signal->theData[1] = takeOverPtrI;
- signal->theData[2] = takeOverPtr.p->toStartingNode;
- signal->theData[3] = takeOverPtr.p->toFailedNode;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 30, 4);
- return;
- }//if
- c_endToLock = takeOverPtr.i;
- takeOverPtr.p->toMasterStatus = TakeOverRecord::ENDING;
- EndToReq * const req = (EndToReq *)&signal->theData[0];
- req->userPtr = takeOverPtr.i;
- req->userRef = reference();
- req->startingNodeId = takeOverPtr.p->toStartingNode;
- sendLoopMacro(END_TOREQ, sendEND_TOREQ);
-}//Dbdih::sendStartTo()
-
-void Dbdih::execEND_TOREQ(Signal* signal)
-{
- jamEntry();
- const EndToReq * const req = (EndToReq *)&signal->theData[0];
- BlockReference ref = req->userRef;
- Uint32 startingNodeId = req->startingNodeId;
-
- CRASH_INSERTION(7144);
- RETURN_IF_NODE_NOT_ALIVE(startingNodeId);
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = req->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- ndbrequire(startingNodeId == takeOverPtr.p->toStartingNode);
- takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SLAVE_IDLE;
-
- if (!isMaster()) {
- jam();
- endTakeOver(takeOverPtr.i);
- }//if
-
- EndToConf * const conf = (EndToConf *)&signal->theData[0];
- conf->userPtr = takeOverPtr.i;
- conf->sendingNodeId = cownNodeId;
- conf->startingNodeId = startingNodeId;
- sendSignal(ref, GSN_END_TOCONF, signal, EndToConf::SignalLength, JBB);
-}//Dbdih::execEND_TOREQ()
-
-void Dbdih::execEND_TOCONF(Signal* signal)
-{
- const EndToConf * const conf = (EndToConf *)&signal->theData[0];
- jamEntry();
-
- const Uint32 nodeId = conf->startingNodeId;
- CRASH_INSERTION(7145);
-
- RETURN_IF_NODE_NOT_ALIVE(nodeId);
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = conf->userPtr;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::ENDING);
- ndbrequire(nodeId == takeOverPtr.p->toStartingNode);
-
- receiveLoopMacro(END_TOREQ, conf->sendingNodeId);
- CRASH_INSERTION(7146);
- c_endToLock = RNIL;
-
- /* -----------------------------------------------------------------------*/
- /* WE HAVE FINALLY COMPLETED THE TAKE OVER. WE RESET THE STATUS AND CHECK*/
- /* IF ANY MORE TAKE OVERS ARE NEEDED AT THE MOMENT. */
- /* FIRST WE CHECK IF A RESTART IS ONGOING. IN THAT CASE WE RESTART PHASE */
- /* 4 AND CHECK IF ANY MORE TAKE OVERS ARE NEEDED BEFORE WE START NDB */
- /* CLUSTER. THIS CAN ONLY HAPPEN IN A SYSTEM RESTART. */
- /* ---------------------------------------------------------------------- */
- if (takeOverPtr.p->toNodeRestart) {
- jam();
- /* ----------------------------------------------------------------------*/
- /* THE TAKE OVER NODE WAS A STARTING NODE. WE WILL SEND START_COPYCONF */
- /* TO THE STARTING NODE SUCH THAT THE NODE CAN COMPLETE THE START-UP. */
- /* --------------------------------------------------------------------- */
- BlockReference ref = calcDihBlockRef(takeOverPtr.p->toStartingNode);
- signal->theData[0] = takeOverPtr.p->toStartingNode;
- sendSignal(ref, GSN_START_COPYCONF, signal, 1,JBB);
- }//if
- endTakeOver(takeOverPtr.i);
-
- if (cstartPhase == ZNDB_SPH4) {
- jam();
- if (anyActiveTakeOver()) {
- jam();
- return;
- }//if
- ndbsttorry10Lab(signal, __LINE__);
- return;
- }//if
- checkStartTakeOver(signal);
-}//Dbdih::execEND_TOCONF()
-
-void Dbdih::allocateTakeOver(TakeOverRecordPtr& takeOverPtr)
-{
- if (isMaster()) {
- jam();
- //--------------------------------------------
- // Master already seized the take over record.
- //--------------------------------------------
- return;
- }//if
- if (takeOverPtr.i == cfirstfreeTakeOver) {
- jam();
- seizeTakeOver(takeOverPtr);
- } else {
- TakeOverRecordPtr nextTakeOverptr;
- TakeOverRecordPtr prevTakeOverptr;
- nextTakeOverptr.i = takeOverPtr.p->nextTakeOver;
- prevTakeOverptr.i = takeOverPtr.p->prevTakeOver;
- if (prevTakeOverptr.i != RNIL) {
- jam();
- ptrCheckGuard(prevTakeOverptr, MAX_NDB_NODES, takeOverRecord);
- prevTakeOverptr.p->nextTakeOver = nextTakeOverptr.i;
- }//if
- if (nextTakeOverptr.i != RNIL) {
- jam();
- ptrCheckGuard(nextTakeOverptr, MAX_NDB_NODES, takeOverRecord);
- nextTakeOverptr.p->prevTakeOver = prevTakeOverptr.i;
- }//if
- }//if
-}//Dbdih::allocateTakeOver()
-
-void Dbdih::seizeTakeOver(TakeOverRecordPtr& takeOverPtr)
-{
- TakeOverRecordPtr nextTakeOverptr;
- ndbrequire(cfirstfreeTakeOver != RNIL);
- takeOverPtr.i = cfirstfreeTakeOver;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- cfirstfreeTakeOver = takeOverPtr.p->nextTakeOver;
- nextTakeOverptr.i = takeOverPtr.p->nextTakeOver;
- if (nextTakeOverptr.i != RNIL) {
- jam();
- ptrCheckGuard(nextTakeOverptr, MAX_NDB_NODES, takeOverRecord);
- nextTakeOverptr.p->prevTakeOver = RNIL;
- }//if
- takeOverPtr.p->nextTakeOver = RNIL;
- takeOverPtr.p->prevTakeOver = RNIL;
-}//Dbdih::seizeTakeOver()
-
-void Dbdih::endTakeOver(Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = takeOverPtrI;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- if ((takeOverPtr.p->toMasterStatus != TakeOverRecord::IDLE) &&
- (takeOverPtr.p->toMasterStatus != TakeOverRecord::TO_WAIT_START_TAKE_OVER)) {
- jam();
- NodeGroupRecordPtr NGPtr;
- NodeRecordPtr nodePtr;
- nodePtr.i = takeOverPtr.p->toStartingNode;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- NGPtr.i = nodePtr.p->nodeGroup;
- ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- NGPtr.p->activeTakeOver = false;
- }//if
- setAllowNodeStart(takeOverPtr.p->toStartingNode, true);
- initTakeOver(takeOverPtr);
- releaseTakeOver(takeOverPtrI);
-}//Dbdih::endTakeOver()
-
-void Dbdih::releaseTakeOver(Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = takeOverPtrI;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- takeOverPtr.p->nextTakeOver = cfirstfreeTakeOver;
- cfirstfreeTakeOver = takeOverPtr.i;
-}//Dbdih::releaseTakeOver()
-
-void Dbdih::initTakeOver(TakeOverRecordPtr takeOverPtr)
-{
- takeOverPtr.p->toCopyNode = RNIL;
- takeOverPtr.p->toCurrentFragid = RNIL;
- takeOverPtr.p->toCurrentReplica = RNIL;
- takeOverPtr.p->toCurrentTabref = RNIL;
- takeOverPtr.p->toFailedNode = RNIL;
- takeOverPtr.p->toStartingNode = RNIL;
- takeOverPtr.p->prevTakeOver = RNIL;
- takeOverPtr.p->nextTakeOver = RNIL;
- takeOverPtr.p->toNodeRestart = false;
- takeOverPtr.p->toMasterStatus = TakeOverRecord::IDLE;
- takeOverPtr.p->toSlaveStatus = TakeOverRecord::TO_SLAVE_IDLE;
-}//Dbdih::initTakeOver()
-
-bool Dbdih::anyActiveTakeOver()
-{
- TakeOverRecordPtr takeOverPtr;
- for (takeOverPtr.i = 0; takeOverPtr.i < MAX_NDB_NODES; takeOverPtr.i++) {
- ptrAss(takeOverPtr, takeOverRecord);
- if (takeOverPtr.p->toMasterStatus != TakeOverRecord::IDLE) {
- jam();
- return true;
- }//if
- }//for
- return false;
-}//Dbdih::anyActiveTakeOver()
-
-/*****************************************************************************/
-/* ------------------------------------------------------------------------- */
-/* WE HAVE BEEN REQUESTED TO PERFORM A SYSTEM RESTART. WE START BY */
-/* READING THE GCI FILES. THIS REQUEST WILL ONLY BE SENT TO THE MASTER */
-/* DIH. THAT MEANS WE HAVE TO REPLICATE THE INFORMATION WE READ FROM */
-/* OUR FILES TO ENSURE THAT ALL NODES HAVE THE SAME DISTRIBUTION */
-/* INFORMATION. */
-/* ------------------------------------------------------------------------- */
-/*****************************************************************************/
-void Dbdih::readGciFileLab(Signal* signal)
-{
- FileRecordPtr filePtr;
- filePtr.i = crestartInfoFile[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- filePtr.p->reqStatus = FileRecord::OPENING_GCP;
-
- openFileRo(signal, filePtr);
-}//Dbdih::readGciFileLab()
-
-void Dbdih::openingGcpLab(Signal* signal, FileRecordPtr filePtr)
-{
- /* ----------------------------------------------------------------------- */
- /* WE HAVE SUCCESSFULLY OPENED A FILE CONTAINING INFORMATION ABOUT */
- /* THE GLOBAL CHECKPOINTS THAT ARE POSSIBLE TO RESTART. */
- /* ----------------------------------------------------------------------- */
- readRestorableGci(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::READING_GCP;
-}//Dbdih::openingGcpLab()
-
-void Dbdih::readingGcpLab(Signal* signal, FileRecordPtr filePtr)
-{
- /* ----------------------------------------------------------------------- */
- /* WE HAVE NOW SUCCESSFULLY MANAGED TO READ IN THE GLOBAL CHECKPOINT */
- /* INFORMATION FROM FILE. LATER WE WILL ADD SOME FUNCTIONALITY THAT */
- /* CHECKS THE RESTART TIMERS TO DEDUCE FROM WHERE TO RESTART. */
- /* NOW WE WILL SIMPLY RESTART FROM THE NEWEST GLOBAL CHECKPOINT */
- /* POSSIBLE TO RESTORE. */
- /* */
- /* BEFORE WE INVOKE DICT WE NEED TO COPY CRESTART_INFO TO ALL NODES. */
- /* WE ALSO COPY TO OUR OWN NODE. TO ENABLE US TO DO THIS PROPERLY WE */
- /* START BY CLOSING THIS FILE. */
- /* ----------------------------------------------------------------------- */
- globalData.m_restart_seq = ++SYSFILE->m_restart_seq;
- closeFile(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::CLOSING_GCP;
-}//Dbdih::readingGcpLab()
-
-void Dbdih::closingGcpLab(Signal* signal, FileRecordPtr filePtr)
-{
- if (Sysfile::getInitialStartOngoing(SYSFILE->systemRestartBits) == false){
- jam();
- selectMasterCandidateAndSend(signal);
- return;
- } else {
- jam();
- sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
- return;
- }//if
-}//Dbdih::closingGcpLab()
-
-/* ------------------------------------------------------------------------- */
-/* SELECT THE MASTER CANDIDATE TO BE USED IN SYSTEM RESTARTS. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::selectMasterCandidateAndSend(Signal* signal)
-{
- setNodeGroups();
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = SYSFILE->lastCompletedGCI[getOwnNodeId()];
- sendSignal(cntrlblockref, GSN_DIH_RESTARTCONF, signal, 2, JBB);
-
- NodeRecordPtr nodePtr;
- Uint32 node_groups[MAX_NDB_NODES];
- memset(node_groups, 0, sizeof(node_groups));
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- const Uint32 ng = Sysfile::getNodeGroup(nodePtr.i, SYSFILE->nodeGroups);
- if(ng != NO_NODE_GROUP_ID){
- ndbrequire(ng < MAX_NDB_NODES);
- node_groups[ng]++;
- }
- }
-
- for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- Uint32 count = node_groups[nodePtr.i];
- if(count != 0 && count != cnoReplicas){
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Illegal configuration change."
- " Initial start needs to be performed "
- " when changing no of replicas (%d != %d)",
- node_groups[nodePtr.i], cnoReplicas);
- progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf);
- }
- }
-}//Dbdih::selectMasterCandidate()
-
-/* ------------------------------------------------------------------------- */
-/* ERROR HANDLING DURING READING RESTORABLE GCI FROM FILE. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::openingGcpErrorLab(Signal* signal, FileRecordPtr filePtr)
-{
- filePtr.p->fileStatus = FileRecord::CRASHED;
- filePtr.p->reqStatus = FileRecord::IDLE;
- if (crestartInfoFile[0] == filePtr.i) {
- jam();
- /* --------------------------------------------------------------------- */
- /* THE FIRST FILE WAS NOT ABLE TO BE OPENED. SET STATUS TO CRASHED AND */
- /* TRY OPEN THE NEXT FILE. */
- /* --------------------------------------------------------------------- */
- filePtr.i = crestartInfoFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- openFileRo(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::OPENING_GCP;
- } else {
- jam();
- /* --------------------------------------------------------------------- */
- /* WE FAILED IN OPENING THE SECOND FILE. BOTH FILES WERE CORRUPTED. WE */
- /* CANNOT CONTINUE THE RESTART IN THIS CASE. TELL NDBCNTR OF OUR */
- /* FAILURE. */
- /*---------------------------------------------------------------------- */
- sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
- return;
- }//if
-}//Dbdih::openingGcpErrorLab()
-
-void Dbdih::readingGcpErrorLab(Signal* signal, FileRecordPtr filePtr)
-{
- filePtr.p->fileStatus = FileRecord::CRASHED;
- /* ----------------------------------------------------------------------- */
- /* WE FAILED IN READING THE FILE AS WELL. WE WILL CLOSE THIS FILE. */
- /* ----------------------------------------------------------------------- */
- closeFile(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::CLOSING_GCP_CRASH;
-}//Dbdih::readingGcpErrorLab()
-
-void Dbdih::closingGcpCrashLab(Signal* signal, FileRecordPtr filePtr)
-{
- if (crestartInfoFile[0] == filePtr.i) {
- jam();
- /* --------------------------------------------------------------------- */
- /* ERROR IN FIRST FILE, TRY THE SECOND FILE. */
- /* --------------------------------------------------------------------- */
- filePtr.i = crestartInfoFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- openFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::OPENING_GCP;
- return;
- }//if
- /* ----------------------------------------------------------------------- */
- /* WE DISCOVERED A FAILURE WITH THE SECOND FILE AS WELL. THIS IS A */
- /* SERIOUS PROBLEM. REPORT FAILURE TO NDBCNTR. */
- /* ----------------------------------------------------------------------- */
- sendSignal(cntrlblockref, GSN_DIH_RESTARTREF, signal, 1, JBB);
-}//Dbdih::closingGcpCrashLab()
-
-/*****************************************************************************/
-/* ------------------------------------------------------------------------- */
-/* THIS IS AN INITIAL RESTART. WE WILL CREATE THE TWO FILES DESCRIBING */
-/* THE GLOBAL CHECKPOINTS THAT ARE RESTORABLE. */
-/* ------------------------------------------------------------------------- */
-/*****************************************************************************/
-void Dbdih::initGciFilesLab(Signal* signal)
-{
- FileRecordPtr filePtr;
- filePtr.i = crestartInfoFile[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- createFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::CREATING_GCP;
-}//Dbdih::initGciFilesLab()
-
-/* ------------------------------------------------------------------------- */
-/* GLOBAL CHECKPOINT FILE HAVE BEEN SUCCESSFULLY CREATED. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::creatingGcpLab(Signal* signal, FileRecordPtr filePtr)
-{
- if (filePtr.i == crestartInfoFile[0]) {
- jam();
- /* --------------------------------------------------------------------- */
- /* IF CREATED FIRST THEN ALSO CREATE THE SECOND FILE. */
- /* --------------------------------------------------------------------- */
- filePtr.i = crestartInfoFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- createFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::CREATING_GCP;
- } else {
- jam();
- /* --------------------------------------------------------------------- */
- /* BOTH FILES HAVE BEEN CREATED. NOW WRITE THE INITIAL DATA TO BOTH */
- /* OF THE FILES. */
- /* --------------------------------------------------------------------- */
- filePtr.i = crestartInfoFile[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- writeRestorableGci(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::WRITE_INIT_GCP;
- }//if
-}//Dbdih::creatingGcpLab()
-
-/* ------------------------------------------------------------------------- */
-/* WE HAVE SUCCESSFULLY WRITTEN A GCI FILE. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::writeInitGcpLab(Signal* signal, FileRecordPtr filePtr)
-{
- filePtr.p->reqStatus = FileRecord::IDLE;
- if (filePtr.i == crestartInfoFile[0]) {
- jam();
- /* --------------------------------------------------------------------- */
- /* WE HAVE WRITTEN THE FIRST FILE NOW ALSO WRITE THE SECOND FILE. */
- /* --------------------------------------------------------------------- */
- filePtr.i = crestartInfoFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- writeRestorableGci(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::WRITE_INIT_GCP;
- } else {
- /* --------------------------------------------------------------------- */
- /* WE HAVE WRITTEN BOTH FILES. LEAVE BOTH FILES OPEN AND CONFIRM OUR */
- /* PART OF THE INITIAL START. */
- /* --------------------------------------------------------------------- */
- if (isMaster()) {
- jam();
- /*---------------------------------------------------------------------*/
- // IN MASTER NODES THE START REQUEST IS RECEIVED FROM NDBCNTR AND WE MUST
- // RESPOND WHEN COMPLETED.
- /*---------------------------------------------------------------------*/
- signal->theData[0] = reference();
- sendSignal(cndbStartReqBlockref, GSN_NDB_STARTCONF, signal, 1, JBB);
- } else {
- jam();
- ndbsttorry10Lab(signal, __LINE__);
- return;
- }//if
- }//if
-}//Dbdih::writeInitGcpLab()
-
-/*****************************************************************************/
-/* ********** NODES DELETION MODULE *************/
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/* LOGIC FOR NODE FAILURE */
-/*---------------------------------------------------------------------------*/
-void Dbdih::execNODE_FAILREP(Signal* signal)
-{
- Uint32 i;
- Uint32 failedNodes[MAX_NDB_NODES];
- jamEntry();
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
-
- cfailurenr = nodeFail->failNo;
- Uint32 newMasterId = nodeFail->masterNodeId;
- const Uint32 noOfFailedNodes = nodeFail->noOfNodes;
-
- if (ERROR_INSERTED(7179))
- {
- CLEAR_ERROR_INSERT_VALUE;
- }
-
- if (ERROR_INSERTED(7184))
- {
- SET_ERROR_INSERT_VALUE(7000);
- }
-
- /*-------------------------------------------------------------------------*/
- // The first step is to convert from a bit mask to an array of failed nodes.
- /*-------------------------------------------------------------------------*/
- Uint32 index = 0;
- for (i = 1; i < MAX_NDB_NODES; i++) {
- jam();
- if(NodeBitmask::get(nodeFail->theNodes, i)){
- jam();
- failedNodes[index] = i;
- index++;
- }//if
- }//for
- ndbrequire(noOfFailedNodes == index);
- ndbrequire(noOfFailedNodes - 1 < MAX_NDB_NODES);
-
- /*-------------------------------------------------------------------------*/
- // The second step is to update the node status of the failed nodes, remove
- // them from the alive node list and put them into the dead node list. Also
- // update the number of nodes on-line.
- // We also set certain state variables ensuring that the node no longer is
- // used in transactions and also mark that we received this signal.
- /*-------------------------------------------------------------------------*/
- for (i = 0; i < noOfFailedNodes; i++) {
- jam();
- NodeRecordPtr TNodePtr;
- TNodePtr.i = failedNodes[i];
- ptrCheckGuard(TNodePtr, MAX_NDB_NODES, nodeRecord);
- TNodePtr.p->useInTransactions = false;
- TNodePtr.p->m_inclDihLcp = false;
- TNodePtr.p->recNODE_FAILREP = ZTRUE;
- if (TNodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- con_lineNodes--;
- TNodePtr.p->nodeStatus = NodeRecord::DIED_NOW;
- removeAlive(TNodePtr);
- insertDeadNode(TNodePtr);
- }//if
- }//for
-
- /*-------------------------------------------------------------------------*/
- // Verify that we can continue to operate the cluster. If we cannot we will
- // not return from checkEscalation.
- /*-------------------------------------------------------------------------*/
- checkEscalation();
-
- /*------------------------------------------------------------------------*/
- // 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);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::StartInProgressError;
- sysErr->errorRef = reference();
- sysErr->data1= 0;
- sysErr->data2= __LINE__;
- sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal, SystemError::SignalLength, JBA);
- nodeResetStart();
- }//if
-#endif
-
- /*--------------------------------------------------*/
- /* */
- /* WE CHANGE THE REFERENCE TO MASTER DIH */
- /* BLOCK AND POINTER AT THIS PLACE IN THE CODE*/
- /*--------------------------------------------------*/
- Uint32 oldMasterId = cmasterNodeId;
- BlockReference oldMasterRef = cmasterdihref;
- cmasterdihref = calcDihBlockRef(newMasterId);
- cmasterNodeId = newMasterId;
-
- const bool masterTakeOver = (oldMasterId != newMasterId);
-
- for(i = 0; i < noOfFailedNodes; i++) {
- NodeRecordPtr failedNodePtr;
- failedNodePtr.i = failedNodes[i];
- ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
- Uint32 activeTakeOverPtr = findTakeOver(failedNodes[i]);
- if (oldMasterRef == reference()) {
- /*-------------------------------------------------------*/
- // Functions that need to be called only for master nodes.
- /*-------------------------------------------------------*/
- checkCopyTab(failedNodePtr);
- checkStopPermMaster(signal, failedNodePtr);
- checkWaitGCPMaster(signal, failedNodes[i]);
- checkTakeOverInMasterAllNodeFailure(signal, failedNodePtr);
- checkTakeOverInMasterCopyNodeFailure(signal, failedNodePtr.i);
- checkTakeOverInMasterStartNodeFailure(signal, activeTakeOverPtr);
- checkGcpOutstanding(signal, failedNodePtr.i);
- } else {
- jam();
- /*-----------------------------------------------------------*/
- // Functions that need to be called only for nodes that were
- // not master before these failures.
- /*-----------------------------------------------------------*/
- checkStopPermProxy(signal, failedNodes[i]);
- checkWaitGCPProxy(signal, failedNodes[i]);
- if (isMaster()) {
- /*-----------------------------------------------------------*/
- // We take over as master since old master has failed
- /*-----------------------------------------------------------*/
- handleTakeOverNewMaster(signal, activeTakeOverPtr);
- } else {
- /*-----------------------------------------------------------*/
- // We are not master and will not become master.
- /*-----------------------------------------------------------*/
- checkTakeOverInNonMasterStartNodeFailure(signal, activeTakeOverPtr);
- }//if
- }//if
- /*--------------------------------------------------*/
- // Functions that need to be called for all nodes.
- /*--------------------------------------------------*/
- checkStopMe(signal, failedNodePtr);
- failedNodeLcpHandling(signal, failedNodePtr);
- checkWaitDropTabFailedLqh(signal, failedNodePtr.i, 0); // 0 = start w/ tab 0
- startRemoveFailedNode(signal, failedNodePtr);
-
- /**
- * This is the last function called
- * It modifies failedNodePtr.p->nodeStatus
- */
- failedNodeSynchHandling(signal, failedNodePtr);
- }//for
-
- if(masterTakeOver){
- jam();
- startLcpMasterTakeOver(signal, oldMasterId);
- startGcpMasterTakeOver(signal, oldMasterId);
-
- if(getNodeState().getNodeRestartInProgress()){
- jam();
- progError(__LINE__, NDBD_EXIT_MASTER_FAILURE_DURING_NR);
- }
- }
-
-
- if (isMaster()) {
- jam();
- setNodeRestartInfoBits();
- }//if
-}//Dbdih::execNODE_FAILREP()
-
-void Dbdih::checkCopyTab(NodeRecordPtr failedNodePtr)
-{
- jam();
-
- if(c_nodeStartMaster.startNode != failedNodePtr.i){
- jam();
- return;
- }
-
- switch(c_nodeStartMaster.m_outstandingGsn){
- case GSN_COPY_TABREQ:
- jam();
- ndbrequire(c_COPY_TABREQ_Counter.isWaitingFor(failedNodePtr.i));
- releaseTabPages(failedNodePtr.p->activeTabptr);
- c_COPY_TABREQ_Counter.clearWaitingFor(failedNodePtr.i);
- c_nodeStartMaster.wait = ZFALSE;
- break;
- case GSN_START_INFOREQ:
- case GSN_START_PERMCONF:
- case GSN_DICTSTARTREQ:
- case GSN_START_MECONF:
- jam();
- break;
- default:
- g_eventLogger.error("outstanding gsn: %s(%d)",
- getSignalName(c_nodeStartMaster.m_outstandingGsn),
- c_nodeStartMaster.m_outstandingGsn);
- ndbrequire(false);
- }
-
- nodeResetStart();
-}//Dbdih::checkCopyTab()
-
-void Dbdih::checkStopMe(Signal* signal, NodeRecordPtr failedNodePtr)
-{
- jam();
- if (c_STOP_ME_REQ_Counter.isWaitingFor(failedNodePtr.i)){
- jam();
- ndbrequire(c_stopMe.clientRef != 0);
- StopMeConf * const stopMeConf = (StopMeConf *)&signal->theData[0];
- stopMeConf->senderRef = calcDihBlockRef(failedNodePtr.i);
- stopMeConf->senderData = c_stopMe.clientData;
- sendSignal(reference(), GSN_STOP_ME_CONF, signal,
- StopMeConf::SignalLength, JBB);
- }//if
-}//Dbdih::checkStopMe()
-
-void Dbdih::checkStopPermMaster(Signal* signal, NodeRecordPtr failedNodePtr)
-{
- DihSwitchReplicaRef* const ref = (DihSwitchReplicaRef*)&signal->theData[0];
- jam();
- if (c_DIH_SWITCH_REPLICA_REQ_Counter.isWaitingFor(failedNodePtr.i)){
- jam();
- ndbrequire(c_stopPermMaster.clientRef != 0);
- ref->senderNode = failedNodePtr.i;
- ref->errorCode = StopPermRef::NF_CausedAbortOfStopProcedure;
- sendSignal(reference(), GSN_DIH_SWITCH_REPLICA_REF, signal,
- DihSwitchReplicaRef::SignalLength, JBB);
- return;
- }//if
-}//Dbdih::checkStopPermMaster()
-
-void Dbdih::checkStopPermProxy(Signal* signal, NodeId failedNodeId)
-{
- jam();
- if(c_stopPermProxy.clientRef != 0 &&
- refToNode(c_stopPermProxy.masterRef) == failedNodeId){
-
- /**
- * The master has failed report to proxy-client
- */
- jam();
- StopPermRef* const ref = (StopPermRef*)&signal->theData[0];
-
- ref->senderData = c_stopPermProxy.clientData;
- ref->errorCode = StopPermRef::NF_CausedAbortOfStopProcedure;
- sendSignal(c_stopPermProxy.clientRef, GSN_STOP_PERM_REF, signal, 2, JBB);
- c_stopPermProxy.clientRef = 0;
- }//if
-}//Dbdih::checkStopPermProxy()
-
-void
-Dbdih::checkTakeOverInMasterAllNodeFailure(Signal* signal,
- NodeRecordPtr failedNodePtr)
-{
- //------------------------------------------------------------------------
- // This code is used to handle the failure of "all" nodes during the
- // take over when "all" nodes are informed about state changes in
- // the take over protocol.
- //--------------------------------------------------------------------------
- if (c_START_TOREQ_Counter.isWaitingFor(failedNodePtr.i)){
- jam();
- StartToConf * const conf = (StartToConf *)&signal->theData[0];
- conf->userPtr = c_startToLock;
- conf->sendingNodeId = failedNodePtr.i;
- conf->startingNodeId = getStartNode(c_startToLock);
- sendSignal(reference(), GSN_START_TOCONF, signal,
- StartToConf::SignalLength, JBB);
- }//if
- if (c_CREATE_FRAGREQ_Counter.isWaitingFor(failedNodePtr.i)){
- jam();
- CreateFragConf * const conf = (CreateFragConf *)&signal->theData[0];
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = c_createFragmentLock;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- conf->userPtr = takeOverPtr.i;
- conf->tableId = takeOverPtr.p->toCurrentTabref;
- conf->fragId = takeOverPtr.p->toCurrentFragid;
- conf->sendingNodeId = failedNodePtr.i;
- conf->startingNodeId = takeOverPtr.p->toStartingNode;
- sendSignal(reference(), GSN_CREATE_FRAGCONF, signal,
- CreateFragConf::SignalLength, JBB);
- }//if
- if (c_UPDATE_TOREQ_Counter.isWaitingFor(failedNodePtr.i)){
- jam();
- UpdateToConf * const conf = (UpdateToConf *)&signal->theData[0];
- conf->userPtr = c_updateToLock;
- conf->sendingNodeId = failedNodePtr.i;
- conf->startingNodeId = getStartNode(c_updateToLock);
- sendSignal(reference(), GSN_UPDATE_TOCONF, signal,
- UpdateToConf::SignalLength, JBB);
- }//if
-
- if (c_END_TOREQ_Counter.isWaitingFor(failedNodePtr.i)){
- jam();
- EndToConf * const conf = (EndToConf *)&signal->theData[0];
- conf->userPtr = c_endToLock;
- conf->sendingNodeId = failedNodePtr.i;
- conf->startingNodeId = getStartNode(c_endToLock);
- sendSignal(reference(), GSN_END_TOCONF, signal,
- EndToConf::SignalLength, JBB);
- }//if
-}//Dbdih::checkTakeOverInMasterAllNodeFailure()
-
-void Dbdih::checkTakeOverInMasterCopyNodeFailure(Signal* signal,
- Uint32 failedNodeId)
-{
- //---------------------------------------------------------------------------
- // This code is used to handle failure of the copying node during a take over
- //---------------------------------------------------------------------------
- TakeOverRecordPtr takeOverPtr;
- for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
- jam();
- takeOverPtr.i = i;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- if ((takeOverPtr.p->toMasterStatus == TakeOverRecord::COPY_FRAG) &&
- (takeOverPtr.p->toCopyNode == failedNodeId)) {
- jam();
- /**
- * The copying node failed but the system is still operational.
- * We restart the copy process by selecting a new copy node.
- * We do not need to add a fragment however since it is already added.
- * We start again from the prepare create fragment phase.
- */
- prepareSendCreateFragReq(signal, takeOverPtr.i);
- }//if
- }//for
-}//Dbdih::checkTakeOverInMasterCopyNodeFailure()
-
-void Dbdih::checkTakeOverInMasterStartNodeFailure(Signal* signal,
- Uint32 takeOverPtrI)
-{
- jam();
- ndbout_c("checkTakeOverInMasterStartNodeFailure %x",
- takeOverPtrI);
- if (takeOverPtrI == RNIL) {
- jam();
- return;
- }
- //-----------------------------------------------------------------------
- // We are the master and the starting node has failed during a take over.
- // We need to handle this failure in different ways depending on the state.
- //-----------------------------------------------------------------------
-
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = takeOverPtrI;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
-
- ndbout_c("takeOverPtr.p->toMasterStatus: %x",
- takeOverPtr.p->toMasterStatus);
-
- bool ok = false;
- switch (takeOverPtr.p->toMasterStatus) {
- case TakeOverRecord::IDLE:
- //-----------------------------------------------------------------------
- // The state cannot be idle when it has a starting node.
- //-----------------------------------------------------------------------
- ndbrequire(false);
- break;
- case TakeOverRecord::TO_WAIT_START_TAKE_OVER:
- jam();
- case TakeOverRecord::TO_START_COPY:
- jam();
- case TakeOverRecord::TO_START_COPY_ONGOING:
- jam();
- case TakeOverRecord::TO_WAIT_START:
- jam();
- case TakeOverRecord::TO_WAIT_PREPARE_CREATE:
- jam();
- case TakeOverRecord::TO_WAIT_UPDATE_TO:
- jam();
- case TakeOverRecord::TO_WAIT_COMMIT_CREATE:
- jam();
- case TakeOverRecord::TO_END_COPY:
- jam();
- case TakeOverRecord::TO_END_COPY_ONGOING:
- jam();
- case TakeOverRecord::TO_WAIT_ENDING:
- jam();
- //-----------------------------------------------------------------------
- // We will not do anything since an internal signal process is outstanding.
- // When the signal arrives the take over will be released.
- //-----------------------------------------------------------------------
- ok = true;
- break;
- case TakeOverRecord::STARTING:
- jam();
- ok = true;
- c_startToLock = RNIL;
- c_START_TOREQ_Counter.clearWaitingFor();
- endTakeOver(takeOverPtr.i);
- break;
- case TakeOverRecord::TO_UPDATE_TO:
- jam();
- ok = true;
- c_updateToLock = RNIL;
- c_UPDATE_TOREQ_Counter.clearWaitingFor();
- endTakeOver(takeOverPtr.i);
- break;
- case TakeOverRecord::ENDING:
- jam();
- ok = true;
- c_endToLock = RNIL;
- c_END_TOREQ_Counter.clearWaitingFor();
- endTakeOver(takeOverPtr.i);
- break;
- case TakeOverRecord::COMMIT_CREATE:
- ok = true;
- jam();
- {// We have mutex
- Mutex m(signal, c_mutexMgr, takeOverPtr.p->m_switchPrimaryMutexHandle);
- m.unlock(); // Ignore result
- }
- // Fall through
- case TakeOverRecord::PREPARE_CREATE:
- ok = true;
- jam();
- c_createFragmentLock = RNIL;
- c_CREATE_FRAGREQ_Counter.clearWaitingFor();
- endTakeOver(takeOverPtr.i);
- break;
- case TakeOverRecord::LOCK_MUTEX:
- ok = true;
- jam();
- // Lock mutex will return and do endTakeOver
- break;
-
- //-----------------------------------------------------------------------
- // Signals are outstanding to external nodes. These signals carry the node
- // id of the starting node and will not use the take over record if the
- // starting node has failed.
- //-----------------------------------------------------------------------
- case TakeOverRecord::COPY_FRAG:
- ok = true;
- jam();
- //-----------------------------------------------------------------------
- // The copying node will discover the problem. We will receive either
- // COPY_FRAGREQ or COPY_FRAGCONF and then we can release the take over
- // record and end the process. If the copying node should also die then
- // we will try to send prepare create fragment and will then discover
- // that the starting node has failed.
- //-----------------------------------------------------------------------
- break;
- case TakeOverRecord::PREPARE_COPY:
- ok = true;
- jam();
- /**
- * We're waiting for the starting node...which just died...
- * endTakeOver
- */
- endTakeOver(takeOverPtr.i);
- break;
- case TakeOverRecord::COPY_ACTIVE:
- ok = true;
- jam();
- //-----------------------------------------------------------------------
- // In this we are waiting for a signal from the starting node. Thus we
- // can release the take over record and end the process.
- //-----------------------------------------------------------------------
- endTakeOver(takeOverPtr.i);
- break;
- case TakeOverRecord::WAIT_LCP:
- ok = true;
- jam();
- //-----------------------------------------------------------------------
- //-----------------------------------------------------------------------
- endTakeOver(takeOverPtr.i);
- break;
-
- case TakeOverRecord::STARTING_LOCAL_FRAGMENTS:
- ok = true;
- jam();
- endTakeOver(takeOverPtr.i);
- break;
-
- /**
- * The following are states that it should not be possible to "be" in
- */
- case TakeOverRecord::SELECTING_NEXT:
- jam();
- case TakeOverRecord::TO_COPY_COMPLETED:
- jam();
- ndbrequire(false);
- }
- if(!ok){
- jamLine(takeOverPtr.p->toSlaveStatus);
- ndbrequire(ok);
- }
-}//Dbdih::checkTakeOverInMasterStartNodeFailure()
-
-void Dbdih::checkTakeOverInNonMasterStartNodeFailure(Signal* signal,
- Uint32 takeOverPtrI)
-{
- jam();
- if (takeOverPtrI == RNIL) {
- jam();
- return;
- }
- //-----------------------------------------------------------------------
- // We are not master and not taking over as master. A take over was ongoing
- // but the starting node has now failed. Handle it according to the state
- // of the take over.
- //-----------------------------------------------------------------------
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = takeOverPtrI;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- bool ok = false;
- switch (takeOverPtr.p->toSlaveStatus) {
- case TakeOverRecord::TO_SLAVE_IDLE:
- ndbrequire(false);
- break;
- case TakeOverRecord::TO_SLAVE_STARTED:
- jam();
- case TakeOverRecord::TO_SLAVE_CREATE_PREPARE:
- jam();
- case TakeOverRecord::TO_SLAVE_COPY_FRAG_COMPLETED:
- jam();
- case TakeOverRecord::TO_SLAVE_CREATE_COMMIT:
- jam();
- case TakeOverRecord::TO_SLAVE_COPY_COMPLETED:
- jam();
- ok = true;
- endTakeOver(takeOverPtr.i);
- break;
- }//switch
- if(!ok){
- jamLine(takeOverPtr.p->toSlaveStatus);
- ndbrequire(ok);
- }
-}//Dbdih::checkTakeOverInNonMasterStartNodeFailure()
-
-void Dbdih::failedNodeSynchHandling(Signal* signal,
- NodeRecordPtr failedNodePtr)
-{
- jam();
- /*----------------------------------------------------*/
- /* INITIALISE THE VARIABLES THAT KEEP TRACK OF */
- /* WHEN A NODE FAILURE IS COMPLETED. */
- /*----------------------------------------------------*/
- failedNodePtr.p->dbdictFailCompleted = ZFALSE;
- failedNodePtr.p->dbtcFailCompleted = ZFALSE;
- failedNodePtr.p->dbdihFailCompleted = ZFALSE;
- failedNodePtr.p->dblqhFailCompleted = ZFALSE;
-
- failedNodePtr.p->m_NF_COMPLETE_REP.clearWaitingFor();
-
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRecord);
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- /**
- * We'r waiting for nodePtr.i to complete
- * handling of failedNodePtr.i's death
- */
-
- failedNodePtr.p->m_NF_COMPLETE_REP.setWaitingFor(nodePtr.i);
- } else {
- jam();
- if ((nodePtr.p->nodeStatus == NodeRecord::DYING) &&
- (nodePtr.p->m_NF_COMPLETE_REP.isWaitingFor(failedNodePtr.i))){
- jam();
- /*----------------------------------------------------*/
- /* THE NODE FAILED BEFORE REPORTING THE FAILURE */
- /* HANDLING COMPLETED ON THIS FAILED NODE. */
- /* REPORT THAT NODE FAILURE HANDLING WAS */
- /* COMPLETED ON THE NEW FAILED NODE FOR THIS */
- /* PARTICULAR OLD FAILED NODE. */
- /*----------------------------------------------------*/
- NFCompleteRep * const nf = (NFCompleteRep *)&signal->theData[0];
- nf->blockNo = 0;
- nf->nodeId = failedNodePtr.i;
- nf->failedNodeId = nodePtr.i;
- nf->from = __LINE__;
- sendSignal(reference(), GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBB);
- }//if
- }//if
- }//for
- if (failedNodePtr.p->nodeStatus == NodeRecord::DIED_NOW) {
- jam();
- failedNodePtr.p->nodeStatus = NodeRecord::DYING;
- } else {
- jam();
- /*----------------------------------------------------*/
- // No more processing needed when node not even started
- // yet. We give the node status to DEAD since we do not
- // care whether all nodes complete the node failure
- // handling. The node have not been included in the
- // node failure protocols.
- /*----------------------------------------------------*/
- failedNodePtr.p->nodeStatus = NodeRecord::DEAD;
- /**-----------------------------------------------------------------------
- * WE HAVE COMPLETED HANDLING THE NODE FAILURE IN DIH. WE CAN REPORT THIS
- * TO DIH THAT WAIT FOR THE OTHER BLOCKS TO BE CONCLUDED AS WELL.
- *-----------------------------------------------------------------------*/
- NFCompleteRep * const nf = (NFCompleteRep *)&signal->theData[0];
- nf->blockNo = DBDIH;
- nf->nodeId = cownNodeId;
- nf->failedNodeId = failedNodePtr.i;
- nf->from = __LINE__;
- sendSignal(reference(), GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBB);
- }//if
-}//Dbdih::failedNodeSynchHandling()
-
-Uint32 Dbdih::findTakeOver(Uint32 failedNodeId)
-{
- for (Uint32 i = 0; i < MAX_NDB_NODES; i++) {
- jam();
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = i;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- if (takeOverPtr.p->toStartingNode == failedNodeId) {
- jam();
- return i;
- }//if
- }//for
- return RNIL;
-}//Dbdih::findTakeOver()
-
-Uint32 Dbdih::getStartNode(Uint32 takeOverPtrI)
-{
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = takeOverPtrI;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- return takeOverPtr.p->toStartingNode;
-}//Dbdih::getStartNode()
-
-void Dbdih::failedNodeLcpHandling(Signal* signal, NodeRecordPtr failedNodePtr)
-{
- jam();
- const Uint32 nodeId = failedNodePtr.i;
-
- if (isMaster() && c_lcpState.m_participatingLQH.get(failedNodePtr.i))
- {
- /*----------------------------------------------------*/
- /* THE NODE WAS INVOLVED IN A LOCAL CHECKPOINT. WE */
- /* MUST UPDATE THE ACTIVE STATUS TO INDICATE THAT */
- /* THE NODE HAVE MISSED A LOCAL CHECKPOINT. */
- /*----------------------------------------------------*/
-
- /**
- * Bug#28717, Only master should do this, as this status is copied
- * to other nodes
- */
- switch (failedNodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- jam();
- failedNodePtr.p->activeStatus = Sysfile::NS_ActiveMissed_1;
- break;
- case Sysfile::NS_ActiveMissed_1:
- jam();
- failedNodePtr.p->activeStatus = Sysfile::NS_ActiveMissed_2;
- break;
- case Sysfile::NS_ActiveMissed_2:
- jam();
- failedNodePtr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
- break;
- case Sysfile::NS_TakeOver:
- jam();
- failedNodePtr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
- break;
- default:
- g_eventLogger.error("activeStatus = %u "
- "at failure after NODE_FAILREP of node = %u",
- (Uint32) failedNodePtr.p->activeStatus,
- failedNodePtr.i);
- ndbrequire(false);
- break;
- }//switch
- }//if
-
- c_lcpState.m_participatingDIH.clear(failedNodePtr.i);
- c_lcpState.m_participatingLQH.clear(failedNodePtr.i);
-
- if(c_lcpState.m_LCP_COMPLETE_REP_Counter_DIH.isWaitingFor(failedNodePtr.i)){
- jam();
- LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtrSend();
- rep->nodeId = failedNodePtr.i;
- rep->lcpId = SYSFILE->latestLCP_ID;
- rep->blockNo = DBDIH;
- sendSignal(reference(), GSN_LCP_COMPLETE_REP, signal,
- LcpCompleteRep::SignalLength, JBB);
- }
-
- /**
- * Check if we'r waiting for the failed node's LQH to complete
- *
- * Note that this is ran "before" LCP master take over
- */
- if(c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH.isWaitingFor(nodeId)){
- jam();
-
- LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtrSend();
- rep->nodeId = nodeId;
- rep->lcpId = SYSFILE->latestLCP_ID;
- rep->blockNo = DBLQH;
- sendSignal(reference(), GSN_LCP_COMPLETE_REP, signal,
- LcpCompleteRep::SignalLength, JBB);
-
- if(c_lcpState.m_LAST_LCP_FRAG_ORD.isWaitingFor(nodeId)){
- jam();
- /**
- * Make sure we're ready to accept it
- */
- c_lcpState.m_LAST_LCP_FRAG_ORD.clearWaitingFor(nodeId);
- }
- }
-
- if (c_TCGETOPSIZEREQ_Counter.isWaitingFor(failedNodePtr.i)) {
- jam();
- signal->theData[0] = failedNodePtr.i;
- signal->theData[1] = 0;
- sendSignal(reference(), GSN_TCGETOPSIZECONF, signal, 2, JBB);
- }//if
-
- if (c_TC_CLOPSIZEREQ_Counter.isWaitingFor(failedNodePtr.i)) {
- jam();
- signal->theData[0] = failedNodePtr.i;
- sendSignal(reference(), GSN_TC_CLOPSIZECONF, signal, 1, JBB);
- }//if
-
- if (c_START_LCP_REQ_Counter.isWaitingFor(failedNodePtr.i)) {
- jam();
- StartLcpConf * conf = (StartLcpConf*)signal->getDataPtrSend();
- conf->senderRef = numberToRef(DBLQH, failedNodePtr.i);
- conf->lcpId = SYSFILE->latestLCP_ID;
- sendSignal(reference(), GSN_START_LCP_CONF, signal,
- StartLcpConf::SignalLength, JBB);
- }//if
-
- if (c_EMPTY_LCP_REQ_Counter.isWaitingFor(failedNodePtr.i)) {
- jam();
- EmptyLcpConf * const rep = (EmptyLcpConf *)&signal->theData[0];
- rep->senderNodeId = failedNodePtr.i;
- rep->tableId = ~0;
- rep->fragmentId = ~0;
- rep->lcpNo = 0;
- rep->lcpId = SYSFILE->latestLCP_ID;
- rep->idle = true;
- sendSignal(reference(), GSN_EMPTY_LCP_CONF, signal,
- EmptyLcpConf::SignalLength, JBB);
- }//if
-
- if (c_MASTER_LCPREQ_Counter.isWaitingFor(failedNodePtr.i)) {
- jam();
- MasterLCPRef * const ref = (MasterLCPRef *)&signal->theData[0];
- ref->senderNodeId = failedNodePtr.i;
- ref->failedNodeId = cmasterTakeOverNode;
- sendSignal(reference(), GSN_MASTER_LCPREF, signal,
- MasterLCPRef::SignalLength, JBB);
- }//if
-
-}//Dbdih::failedNodeLcpHandling()
-
-void Dbdih::checkGcpOutstanding(Signal* signal, Uint32 failedNodeId){
- if (c_GCP_PREPARE_Counter.isWaitingFor(failedNodeId)){
- jam();
- signal->theData[0] = failedNodeId;
- signal->theData[1] = cnewgcp;
- sendSignal(reference(), GSN_GCP_PREPARECONF, signal, 2, JBB);
- }//if
-
- if (c_GCP_COMMIT_Counter.isWaitingFor(failedNodeId)) {
- jam();
- signal->theData[0] = failedNodeId;
- signal->theData[1] = coldgcp;
- signal->theData[2] = cfailurenr;
- sendSignal(reference(), GSN_GCP_NODEFINISH, signal, 3, JBB);
- }//if
-
- if (c_GCP_SAVEREQ_Counter.isWaitingFor(failedNodeId)) {
- jam();
- GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
- saveRef->dihPtr = failedNodeId;
- saveRef->nodeId = failedNodeId;
- saveRef->gci = coldgcp;
- saveRef->errorCode = GCPSaveRef::FakedSignalDueToNodeFailure;
- sendSignal(reference(), GSN_GCP_SAVEREF, signal,
- GCPSaveRef::SignalLength, JBB);
- }//if
-
- if (c_COPY_GCIREQ_Counter.isWaitingFor(failedNodeId)) {
- jam();
- signal->theData[0] = failedNodeId;
- sendSignal(reference(), GSN_COPY_GCICONF, signal, 1, JBB);
- }//if
-
- if (c_MASTER_GCPREQ_Counter.isWaitingFor(failedNodeId)){
- jam();
- MasterGCPRef * const ref = (MasterGCPRef *)&signal->theData[0];
- ref->senderNodeId = failedNodeId;
- ref->failedNodeId = cmasterTakeOverNode;
- sendSignal(reference(), GSN_MASTER_GCPREF, signal,
- MasterGCPRef::SignalLength, JBB);
- }//if
-}//Dbdih::handleGcpStateInMaster()
-
-
-void
-Dbdih::startLcpMasterTakeOver(Signal* signal, Uint32 nodeId){
- jam();
-
- Uint32 oldNode = c_lcpMasterTakeOverState.failedNodeId;
-
- c_lcpMasterTakeOverState.minTableId = ~0;
- c_lcpMasterTakeOverState.minFragId = ~0;
- c_lcpMasterTakeOverState.failedNodeId = nodeId;
-
- c_lcpMasterTakeOverState.set(LMTOS_WAIT_EMPTY_LCP, __LINE__);
-
- if(c_EMPTY_LCP_REQ_Counter.done()){
- jam();
- c_lcpState.m_LAST_LCP_FRAG_ORD.clearWaitingFor();
-
- EmptyLcpReq* req = (EmptyLcpReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- sendLoopMacro(EMPTY_LCP_REQ, sendEMPTY_LCP_REQ);
- ndbrequire(!c_EMPTY_LCP_REQ_Counter.done());
- } else {
- /**
- * Node failure during master take over...
- */
- g_eventLogger.info("Nodefail during master take over (old: %d)", oldNode);
- }
-
- NodeRecordPtr nodePtr;
- nodePtr.i = oldNode;
- if (oldNode > 0 && oldNode < MAX_NDB_NODES)
- {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->m_nodefailSteps.get(NF_LCP_TAKE_OVER))
- {
- jam();
- checkLocalNodefailComplete(signal, oldNode, NF_LCP_TAKE_OVER);
- }
- }
-
- setLocalNodefailHandling(signal, nodeId, NF_LCP_TAKE_OVER);
-}
-
-void Dbdih::startGcpMasterTakeOver(Signal* signal, Uint32 oldMasterId){
- jam();
- /*--------------------------------------------------*/
- /* */
- /* THE MASTER HAVE FAILED AND WE WERE ELECTED */
- /* TO BE THE NEW MASTER NODE. WE NEED TO QUERY*/
- /* ALL THE OTHER NODES ABOUT THEIR STATUS IN */
- /* ORDER TO BE ABLE TO TAKE OVER CONTROL OF */
- /* THE GLOBAL CHECKPOINT PROTOCOL AND THE */
- /* LOCAL CHECKPOINT PROTOCOL. */
- /*--------------------------------------------------*/
- if(!isMaster()){
- jam();
- return;
- }
- cmasterState = MASTER_TAKE_OVER_GCP;
- cmasterTakeOverNode = oldMasterId;
- MasterGCPReq * const req = (MasterGCPReq *)&signal->theData[0];
- req->masterRef = reference();
- req->failedNodeId = oldMasterId;
- sendLoopMacro(MASTER_GCPREQ, sendMASTER_GCPREQ);
- cgcpMasterTakeOverState = GMTOS_INITIAL;
-
- signal->theData[0] = NDB_LE_GCP_TakeoverStarted;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
-
- setLocalNodefailHandling(signal, oldMasterId, NF_GCP_TAKE_OVER);
-}//Dbdih::handleNewMaster()
-
-void Dbdih::handleTakeOverNewMaster(Signal* signal, Uint32 takeOverPtrI)
-{
- jam();
- if (takeOverPtrI != RNIL) {
- jam();
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = takeOverPtrI;
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- bool ok = false;
- switch (takeOverPtr.p->toSlaveStatus) {
- case TakeOverRecord::TO_SLAVE_IDLE:
- ndbrequire(false);
- break;
- case TakeOverRecord::TO_SLAVE_STARTED:
- jam();
- case TakeOverRecord::TO_SLAVE_CREATE_PREPARE:
- jam();
- case TakeOverRecord::TO_SLAVE_COPY_FRAG_COMPLETED:
- jam();
- case TakeOverRecord::TO_SLAVE_CREATE_COMMIT:
- jam();
- ok = true;
- infoEvent("Unhandled MasterTO of TO slaveStatus=%d killing node %d",
- takeOverPtr.p->toSlaveStatus,
- takeOverPtr.p->toStartingNode);
- takeOverPtr.p->toMasterStatus = TakeOverRecord::COPY_ACTIVE;
-
- {
- BlockReference cntrRef = calcNdbCntrBlockRef(takeOverPtr.p->toStartingNode);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::CopyFragRefError;
- sysErr->errorRef = reference();
- sysErr->data1= 0;
- sysErr->data2= __LINE__;
- sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBB);
- }
- break;
- case TakeOverRecord::TO_SLAVE_COPY_COMPLETED:
- ok = true;
- jam();
- takeOverPtr.p->toMasterStatus = TakeOverRecord::WAIT_LCP;
- break;
- }
- ndbrequire(ok);
- endTakeOver(takeOverPtr.i);
- }//if
-}//Dbdih::handleTakeOverNewMaster()
-
-void Dbdih::startRemoveFailedNode(Signal* signal, NodeRecordPtr failedNodePtr)
-{
- Uint32 nodeId = failedNodePtr.i;
- if(failedNodePtr.p->nodeStatus != NodeRecord::DIED_NOW){
- jam();
- /**
- * Is node isn't alive. It can't be part of LCP
- */
- ndbrequire(!c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH.isWaitingFor(nodeId));
-
- /**
- * And there is no point in removing any replicas
- * It's dead...
- */
- return;
- }
-
- /**
- * If node has node complete LCP
- * we need to remove it as undo might not be complete
- * bug#31257
- */
- failedNodePtr.p->m_remove_node_from_table_lcp_id = RNIL;
- if (c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH.isWaitingFor(failedNodePtr.i))
- {
- jam();
- failedNodePtr.p->m_remove_node_from_table_lcp_id = SYSFILE->latestLCP_ID;
- }
-
- jam();
-
- if (!ERROR_INSERTED(7194))
- {
- signal->theData[0] = DihContinueB::ZREMOVE_NODE_FROM_TABLE;
- signal->theData[1] = failedNodePtr.i;
- signal->theData[2] = 0; // Tab id
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- }
- else
- {
- ndbout_c("7194 Not starting ZREMOVE_NODE_FROM_TABLE");
- }
-
- setLocalNodefailHandling(signal, failedNodePtr.i, NF_REMOVE_NODE_FROM_TABLE);
-}//Dbdih::startRemoveFailedNode()
-
-/*--------------------------------------------------*/
-/* THE MASTER HAS FAILED AND THE NEW MASTER IS*/
-/* QUERYING THIS NODE ABOUT THE STATE OF THE */
-/* GLOBAL CHECKPOINT PROTOCOL */
-/*--------------------------------------------------*/
-void Dbdih::execMASTER_GCPREQ(Signal* signal)
-{
- NodeRecordPtr failedNodePtr;
- MasterGCPReq * const masterGCPReq = (MasterGCPReq *)&signal->theData[0];
- jamEntry();
- const BlockReference newMasterBlockref = masterGCPReq->masterRef;
- const Uint32 failedNodeId = masterGCPReq->failedNodeId;
- if (c_copyGCISlave.m_copyReason != CopyGCIReq::IDLE) {
- jam();
- /*--------------------------------------------------*/
- /* WE ARE CURRENTLY WRITING THE RESTART INFO */
- /* IN THIS NODE. SINCE ONLY ONE PROCESS IS */
- /* ALLOWED TO DO THIS AT A TIME WE MUST ENSURE*/
- /* THAT THIS IS NOT ONGOING WHEN THE NEW */
- /* MASTER TAKES OVER CONTROL. IF NOT ALL NODES*/
- /* RECEIVE THE SAME RESTART INFO DUE TO THE */
- /* FAILURE OF THE MASTER IT IS TAKEN CARE OF */
- /* BY THE NEW MASTER. */
- /*--------------------------------------------------*/
- sendSignalWithDelay(reference(), GSN_MASTER_GCPREQ,
- signal, 10, MasterGCPReq::SignalLength);
- return;
- }//if
- failedNodePtr.i = failedNodeId;
- ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
- if (failedNodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- /*--------------------------------------------------*/
- /* ENSURE THAT WE HAVE PROCESSED THE SIGNAL */
- /* NODE_FAILURE BEFORE WE PROCESS THIS REQUEST*/
- /* FROM THE NEW MASTER. THIS ENSURES THAT WE */
- /* HAVE REMOVED THE FAILED NODE FROM THE LIST */
- /* OF ACTIVE NODES AND SO FORTH. */
- /*--------------------------------------------------*/
- sendSignalWithDelay(reference(), GSN_MASTER_GCPREQ,
- signal, 10, MasterGCPReq::SignalLength);
- return;
- } else {
- ndbrequire(failedNodePtr.p->nodeStatus == NodeRecord::DYING);
- }//if
-
- if (ERROR_INSERTED(7181))
- {
- ndbout_c("execGCP_TCFINISHED in MASTER_GCPREQ");
- CLEAR_ERROR_INSERT_VALUE;
- signal->theData[0] = c_error_7181_ref;
- signal->theData[1] = coldgcp;
- execGCP_TCFINISHED(signal);
- }
-
- MasterGCPConf::State gcpState;
- switch (cgcpParticipantState) {
- case GCP_PARTICIPANT_READY:
- jam();
- /*--------------------------------------------------*/
- /* THE GLOBAL CHECKPOINT IS NOT ACTIVE SINCE */
- /* THE PREVIOUS GLOBAL CHECKPOINT IS COMPLETED*/
- /* AND THE NEW HAVE NOT STARTED YET. */
- /*--------------------------------------------------*/
- gcpState = MasterGCPConf::GCP_READY;
- break;
- case GCP_PARTICIPANT_PREPARE_RECEIVED:
- jam();
- /*--------------------------------------------------*/
- /* GCP_PREPARE HAVE BEEN RECEIVED AND RESPONSE*/
- /* HAVE BEEN SENT. */
- /*--------------------------------------------------*/
- gcpState = MasterGCPConf::GCP_PREPARE_RECEIVED;
- break;
- case GCP_PARTICIPANT_COMMIT_RECEIVED:
- jam();
- /*------------------------------------------------*/
- /* GCP_COMMIT HAVE BEEN RECEIVED BUT NOT YET*/
- /* GCP_TCFINISHED FROM LOCAL TC. */
- /*------------------------------------------------*/
- gcpState = MasterGCPConf::GCP_COMMIT_RECEIVED;
- break;
- case GCP_PARTICIPANT_TC_FINISHED:
- jam();
- /*------------------------------------------------*/
- /* GCP_COMMIT HAS BEEN RECEIVED AND ALSO */
- /* GCP_TCFINISHED HAVE BEEN RECEIVED. */
- /*------------------------------------------------*/
- gcpState = MasterGCPConf::GCP_TC_FINISHED;
- break;
- case GCP_PARTICIPANT_COPY_GCI_RECEIVED:
- /*--------------------------------------------------*/
- /* COPY RESTART INFORMATION HAS BEEN RECEIVED */
- /* BUT NOT YET COMPLETED. */
- /*--------------------------------------------------*/
- ndbrequire(false);
- gcpState= MasterGCPConf::GCP_READY; // remove warning
- break;
- default:
- /*------------------------------------------------*/
- /* */
- /* THIS SHOULD NOT OCCUR SINCE THE ABOVE */
- /* STATES ARE THE ONLY POSSIBLE STATES AT A */
- /* NODE WHICH WAS NOT A MASTER NODE. */
- /*------------------------------------------------*/
- ndbrequire(false);
- gcpState= MasterGCPConf::GCP_READY; // remove warning
- break;
- }//switch
- MasterGCPConf * const masterGCPConf = (MasterGCPConf *)&signal->theData[0];
- masterGCPConf->gcpState = gcpState;
- masterGCPConf->senderNodeId = cownNodeId;
- masterGCPConf->failedNodeId = failedNodeId;
- masterGCPConf->newGCP = cnewgcp;
- masterGCPConf->latestLCP = SYSFILE->latestLCP_ID;
- masterGCPConf->oldestRestorableGCI = SYSFILE->oldestRestorableGCI;
- masterGCPConf->keepGCI = SYSFILE->keepGCI;
- for(Uint32 i = 0; i < NdbNodeBitmask::Size; i++)
- masterGCPConf->lcpActive[i] = SYSFILE->lcpActive[i];
- sendSignal(newMasterBlockref, GSN_MASTER_GCPCONF, signal,
- MasterGCPConf::SignalLength, JBB);
-
- if (ERROR_INSERTED(7182))
- {
- ndbout_c("execGCP_TCFINISHED in MASTER_GCPREQ");
- CLEAR_ERROR_INSERT_VALUE;
- signal->theData[0] = c_error_7181_ref;
- signal->theData[1] = coldgcp;
- execGCP_TCFINISHED(signal);
- }
-}//Dbdih::execMASTER_GCPREQ()
-
-void Dbdih::execMASTER_GCPCONF(Signal* signal)
-{
- NodeRecordPtr senderNodePtr;
- MasterGCPConf * const masterGCPConf = (MasterGCPConf *)&signal->theData[0];
- jamEntry();
- senderNodePtr.i = masterGCPConf->senderNodeId;
- ptrCheckGuard(senderNodePtr, MAX_NDB_NODES, nodeRecord);
-
- MasterGCPConf::State gcpState = (MasterGCPConf::State)masterGCPConf->gcpState;
- const Uint32 failedNodeId = masterGCPConf->failedNodeId;
- const Uint32 newGcp = masterGCPConf->newGCP;
- const Uint32 latestLcpId = masterGCPConf->latestLCP;
- const Uint32 oldestRestorableGci = masterGCPConf->oldestRestorableGCI;
- const Uint32 oldestKeepGci = masterGCPConf->keepGCI;
- if (latestLcpId > SYSFILE->latestLCP_ID) {
- jam();
-#if 0
- g_eventLogger.info("Dbdih: Setting SYSFILE->latestLCP_ID to %d",
- latestLcpId);
- SYSFILE->latestLCP_ID = latestLcpId;
-#endif
- SYSFILE->keepGCI = oldestKeepGci;
- SYSFILE->oldestRestorableGCI = oldestRestorableGci;
- for(Uint32 i = 0; i < NdbNodeBitmask::Size; i++)
- SYSFILE->lcpActive[i] = masterGCPConf->lcpActive[i];
- }//if
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- jam();
- senderNodePtr.p->gcpstate = NodeRecord::READY;
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- jam();
- senderNodePtr.p->gcpstate = NodeRecord::PREPARE_RECEIVED;
- cnewgcp = newGcp;
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- jam();
- senderNodePtr.p->gcpstate = NodeRecord::COMMIT_SENT;
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- jam();
- senderNodePtr.p->gcpstate = NodeRecord::NODE_FINISHED;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- switch (cgcpMasterTakeOverState) {
- case GMTOS_INITIAL:
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- jam();
- cgcpMasterTakeOverState = ALL_READY;
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- jam();
- cgcpMasterTakeOverState = ALL_PREPARED;
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- jam();
- cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- jam();
- cgcpMasterTakeOverState = COMMIT_COMPLETED;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- break;
- case ALL_READY:
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- jam();
- /*empty*/;
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- jam();
- cgcpMasterTakeOverState = PREPARE_STARTED_NOT_COMMITTED;
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- ndbrequire(false);
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- jam();
- cgcpMasterTakeOverState = SAVE_STARTED_NOT_COMPLETED;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- break;
- case PREPARE_STARTED_NOT_COMMITTED:
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- jam();
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- jam();
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- ndbrequire(false);
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- ndbrequire(false);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- break;
- case ALL_PREPARED:
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- jam();
- cgcpMasterTakeOverState = PREPARE_STARTED_NOT_COMMITTED;
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- jam();
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- jam();
- cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- jam();
- cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- break;
- case COMMIT_STARTED_NOT_COMPLETED:
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- ndbrequire(false);
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- jam();
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- jam();
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- jam();
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- break;
- case COMMIT_COMPLETED:
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- cgcpMasterTakeOverState = SAVE_STARTED_NOT_COMPLETED;
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- jam();
- cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- jam();
- cgcpMasterTakeOverState = COMMIT_STARTED_NOT_COMPLETED;
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- jam();
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- break;
- case SAVE_STARTED_NOT_COMPLETED:
- switch (gcpState) {
- case MasterGCPConf::GCP_READY:
- jam();
- break;
- case MasterGCPConf::GCP_PREPARE_RECEIVED:
- ndbrequire(false);
- break;
- case MasterGCPConf::GCP_COMMIT_RECEIVED:
- ndbrequire(false);
- break;
- case MasterGCPConf::GCP_TC_FINISHED:
- jam();
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- receiveLoopMacro(MASTER_GCPREQ, senderNodePtr.i);
- /*-------------------------------------------------------------------------*/
- // We have now received all responses and are ready to take over the GCP
- // protocol as master.
- /*-------------------------------------------------------------------------*/
- MASTER_GCPhandling(signal, failedNodeId);
- return;
-}//Dbdih::execMASTER_GCPCONF()
-
-void Dbdih::execMASTER_GCPREF(Signal* signal)
-{
- const MasterGCPRef * const ref = (MasterGCPRef *)&signal->theData[0];
- jamEntry();
- receiveLoopMacro(MASTER_GCPREQ, ref->senderNodeId);
- /*-------------------------------------------------------------------------*/
- // We have now received all responses and are ready to take over the GCP
- // protocol as master.
- /*-------------------------------------------------------------------------*/
- MASTER_GCPhandling(signal, ref->failedNodeId);
-}//Dbdih::execMASTER_GCPREF()
-
-void Dbdih::MASTER_GCPhandling(Signal* signal, Uint32 failedNodeId)
-{
- NodeRecordPtr failedNodePtr;
- cmasterState = MASTER_ACTIVE;
- /*----------------------------------------------------------*/
- /* REMOVE ALL ACTIVE STATUS ON ALREADY FAILED NODES */
- /* THIS IS PERFORMED HERE SINCE WE GET THE LCP ACTIVE */
- /* STATUS AS PART OF THE COPY RESTART INFO AND THIS IS*/
- /* HANDLED BY THE MASTER GCP TAKE OVER PROTOCOL. */
- /*----------------------------------------------------------*/
-
- failedNodePtr.i = failedNodeId;
- ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
- switch (cgcpMasterTakeOverState) {
- case ALL_READY:
- jam();
- startGcp(signal);
- break;
- case PREPARE_STARTED_NOT_COMMITTED:
- {
- NodeRecordPtr nodePtr;
- jam();
- c_GCP_PREPARE_Counter.clearWaitingFor();
- nodePtr.i = cfirstAliveNode;
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->gcpstate == NodeRecord::READY) {
- jam();
- c_GCP_PREPARE_Counter.setWaitingFor(nodePtr.i);
- sendGCP_PREPARE(signal, nodePtr.i);
- }//if
- nodePtr.i = nodePtr.p->nextNode;
- } while(nodePtr.i != RNIL);
- if (c_GCP_PREPARE_Counter.done()) {
- jam();
- gcpcommitreqLab(signal);
- }//if
- break;
- }
- case ALL_PREPARED:
- jam();
- gcpcommitreqLab(signal);
- break;
- case COMMIT_STARTED_NOT_COMPLETED:
- {
- NodeRecordPtr nodePtr;
- jam();
- c_GCP_COMMIT_Counter.clearWaitingFor();
- nodePtr.i = cfirstAliveNode;
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->gcpstate == NodeRecord::PREPARE_RECEIVED) {
- jam();
- sendGCP_COMMIT(signal, nodePtr.i);
- c_GCP_COMMIT_Counter.setWaitingFor(nodePtr.i);
- } else {
- ndbrequire((nodePtr.p->gcpstate == NodeRecord::NODE_FINISHED) ||
- (nodePtr.p->gcpstate == NodeRecord::COMMIT_SENT));
- }//if
- nodePtr.i = nodePtr.p->nextNode;
- } while(nodePtr.i != RNIL);
- if (c_GCP_COMMIT_Counter.done()){
- jam();
- gcpsavereqLab(signal);
- }//if
- break;
- }
- case COMMIT_COMPLETED:
- jam();
- gcpsavereqLab(signal);
- break;
- case SAVE_STARTED_NOT_COMPLETED:
- {
- NodeRecordPtr nodePtr;
- jam();
- SYSFILE->newestRestorableGCI = coldgcp;
- nodePtr.i = cfirstAliveNode;
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- SYSFILE->lastCompletedGCI[nodePtr.i] = coldgcp;
- nodePtr.i = nodePtr.p->nextNode;
- } while (nodePtr.i != RNIL);
- /**-------------------------------------------------------------------
- * THE FAILED NODE DID ALSO PARTICIPATE IN THIS GLOBAL CHECKPOINT
- * WHICH IS RECORDED.
- *-------------------------------------------------------------------*/
- SYSFILE->lastCompletedGCI[failedNodeId] = coldgcp;
- copyGciLab(signal, CopyGCIReq::GLOBAL_CHECKPOINT);
- break;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
-
- signal->theData[0] = NDB_LE_GCP_TakeoverCompleted;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
-
- /*--------------------------------------------------*/
- /* WE SEPARATE HANDLING OF GLOBAL CHECKPOINTS */
- /* AND LOCAL CHECKPOINTS HERE. LCP'S HAVE TO */
- /* REMOVE ALL FAILED FRAGMENTS BEFORE WE CAN */
- /* HANDLE THE LCP PROTOCOL. */
- /*--------------------------------------------------*/
- checkLocalNodefailComplete(signal, failedNodeId, NF_GCP_TAKE_OVER);
-
- return;
-}//Dbdih::masterGcpConfFromFailedLab()
-
-void
-Dbdih::invalidateNodeLCP(Signal* signal, Uint32 nodeId, Uint32 tableId)
-{
- jamEntry();
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- const Uint32 RT_BREAK = 64;
- if (ERROR_INSERTED(7125)) {
- return;
- }//if
- for (Uint32 i = 0; i<RT_BREAK; i++) {
- jam();
- if (tabPtr.i >= ctabFileSize){
- jam();
- /**
- * Ready with entire loop
- * Return to master
- */
- setAllowNodeStart(nodeId, true);
- if (getNodeStatus(nodeId) == NodeRecord::STARTING) {
- jam();
- StartInfoConf * conf = (StartInfoConf*)&signal->theData[0];
- conf->sendingNodeId = cownNodeId;
- conf->startingNodeId = nodeId;
- sendSignal(cmasterdihref, GSN_START_INFOCONF, signal,
- StartInfoConf::SignalLength, JBB);
- }//if
- return;
- }//if
- ptrAss(tabPtr, tabRecord);
- if (tabPtr.p->tabStatus == TabRecord::TS_ACTIVE) {
- jam();
- invalidateNodeLCP(signal, nodeId, tabPtr);
- return;
- }//if
- tabPtr.i++;
- }//for
- signal->theData[0] = DihContinueB::ZINVALIDATE_NODE_LCP;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-}//Dbdih::invalidateNodeLCP()
-
-void
-Dbdih::invalidateNodeLCP(Signal* signal, Uint32 nodeId, TabRecordPtr tabPtr)
-{
- /**
- * Check so that no one else is using the tab descriptior
- */
- if (tabPtr.p->tabCopyStatus != TabRecord::CS_IDLE) {
- jam();
- signal->theData[0] = DihContinueB::ZINVALIDATE_NODE_LCP;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 20, 3);
- return;
- }//if
-
- /**
- * For each fragment
- */
- bool modified = false;
- FragmentstorePtr fragPtr;
- for(Uint32 fragNo = 0; fragNo < tabPtr.p->totalfragments; fragNo++){
- jam();
- getFragstore(tabPtr.p, fragNo, fragPtr);
- /**
- * For each of replica record
- */
- ReplicaRecordPtr replicaPtr;
- for(replicaPtr.i = fragPtr.p->oldStoredReplicas; replicaPtr.i != RNIL;
- replicaPtr.i = replicaPtr.p->nextReplica) {
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if(replicaPtr.p->procNode == nodeId){
- jam();
- /**
- * Found one with correct node id
- */
- /**
- * Invalidate all LCP's
- */
- modified = true;
- for(int i = 0; i < MAX_LCP_STORED; i++) {
- replicaPtr.p->lcpStatus[i] = ZINVALID;
- }//if
- /**
- * And reset nextLcp
- */
- replicaPtr.p->nextLcp = 0;
- replicaPtr.p->noCrashedReplicas = 0;
- }//if
- }//for
- }//for
-
- if (modified) {
- jam();
- /**
- * Save table description to disk
- */
- tabPtr.p->tabCopyStatus = TabRecord::CS_INVALIDATE_NODE_LCP;
- tabPtr.p->tabUpdateState = TabRecord::US_INVALIDATE_NODE_LCP;
- tabPtr.p->tabRemoveNode = nodeId;
- signal->theData[0] = DihContinueB::ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- }
-
- jam();
- /**
- * Move to next table
- */
- tabPtr.i++;
- signal->theData[0] = DihContinueB::ZINVALIDATE_NODE_LCP;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
-}//Dbdih::invalidateNodeLCP()
-
-/*------------------------------------------------*/
-/* INPUT: TABPTR */
-/* TNODEID */
-/*------------------------------------------------*/
-void Dbdih::removeNodeFromTables(Signal* signal,
- Uint32 nodeId, Uint32 tableId)
-{
- jamEntry();
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- const Uint32 RT_BREAK = 64;
- for (Uint32 i = 0; i<RT_BREAK; i++) {
- jam();
- if (tabPtr.i >= ctabFileSize){
- jam();
- removeNodeFromTablesComplete(signal, nodeId);
- return;
- }//if
-
- ptrAss(tabPtr, tabRecord);
- if (tabPtr.p->tabStatus == TabRecord::TS_ACTIVE) {
- jam();
- removeNodeFromTable(signal, nodeId, tabPtr);
- return;
- }//if
- tabPtr.i++;
- }//for
- signal->theData[0] = DihContinueB::ZREMOVE_NODE_FROM_TABLE;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-}
-
-void Dbdih::removeNodeFromTable(Signal* signal,
- Uint32 nodeId, TabRecordPtr tabPtr){
-
- /**
- * Check so that no one else is using the tab descriptior
- */
- if (tabPtr.p->tabCopyStatus != TabRecord::CS_IDLE) {
- jam();
- signal->theData[0] = DihContinueB::ZREMOVE_NODE_FROM_TABLE;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 20, 3);
- return;
- }//if
-
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- const Uint32 lcpId = nodePtr.p->m_remove_node_from_table_lcp_id;
-
- /**
- * For each fragment
- */
- Uint32 noOfRemovedReplicas = 0; // No of replicas removed
- Uint32 noOfRemovedLcpReplicas = 0; // No of replicas in LCP removed
- Uint32 noOfRemainingLcpReplicas = 0;// No of replicas in LCP remaining
-
- const bool lcpOngoingFlag = (tabPtr.p->tabLcpStatus== TabRecord::TLS_ACTIVE);
- const bool unlogged = (tabPtr.p->tabStorage != TabRecord::ST_NORMAL);
-
- FragmentstorePtr fragPtr;
- for(Uint32 fragNo = 0; fragNo < tabPtr.p->totalfragments; fragNo++){
- jam();
- getFragstore(tabPtr.p, fragNo, fragPtr);
-
- /**
- * For each of replica record
- */
- bool found = false;
- ReplicaRecordPtr replicaPtr;
- for(replicaPtr.i = fragPtr.p->storedReplicas; replicaPtr.i != RNIL;
- replicaPtr.i = replicaPtr.p->nextReplica) {
- jam();
-
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if(replicaPtr.p->procNode == nodeId){
- jam();
- found = true;
- noOfRemovedReplicas++;
- removeNodeFromStored(nodeId, fragPtr, replicaPtr, unlogged);
- if(replicaPtr.p->lcpOngoingFlag){
- jam();
- /**
- * This replica is currently LCP:ed
- */
- ndbrequire(fragPtr.p->noLcpReplicas > 0);
- fragPtr.p->noLcpReplicas --;
-
- noOfRemovedLcpReplicas ++;
- replicaPtr.p->lcpOngoingFlag = false;
- }
-
- if (lcpId != RNIL)
- {
- jam();
- Uint32 lcpNo = prevLcpNo(replicaPtr.p->nextLcp);
- if (replicaPtr.p->lcpStatus[lcpNo] == ZVALID &&
- replicaPtr.p->lcpId[lcpNo] == SYSFILE->latestLCP_ID)
- {
- jam();
- replicaPtr.p->lcpStatus[lcpNo] = ZINVALID;
- replicaPtr.p->lcpId[lcpNo] = 0;
- replicaPtr.p->nextLcp = lcpNo;
- ndbout_c("REMOVING lcp: %u from table: %u frag: %u node: %u",
- SYSFILE->latestLCP_ID,
- tabPtr.i, fragNo, nodeId);
- }
- }
- }
- }
- if (!found)
- {
- jam();
- /**
- * Run updateNodeInfo to remove any dead nodes from list of activeNodes
- * see bug#15587
- */
- updateNodeInfo(fragPtr);
- }
- noOfRemainingLcpReplicas += fragPtr.p->noLcpReplicas;
- }
-
- if(noOfRemovedReplicas == 0){
- jam();
- /**
- * The table had no replica on the failed node
- * continue with next table
- */
- tabPtr.i++;
- signal->theData[0] = DihContinueB::ZREMOVE_NODE_FROM_TABLE;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
- }
-
- /**
- * We did remove at least one replica
- */
- bool ok = false;
- switch(tabPtr.p->tabLcpStatus){
- case TabRecord::TLS_COMPLETED:
- ok = true;
- jam();
- /**
- * WE WILL WRITE THE TABLE DESCRIPTION TO DISK AT THIS TIME
- * INDEPENDENT OF WHAT THE LOCAL CHECKPOINT NEEDED.
- * THIS IS TO ENSURE THAT THE FAILED NODES ARE ALSO UPDATED ON DISK
- * IN THE DIH DATA STRUCTURES BEFORE WE COMPLETE HANDLING OF THE
- * NODE FAILURE.
- */
- ndbrequire(noOfRemovedLcpReplicas == 0);
-
- tabPtr.p->tabCopyStatus = TabRecord::CS_REMOVE_NODE;
- tabPtr.p->tabUpdateState = TabRecord::US_REMOVE_NODE;
- tabPtr.p->tabRemoveNode = nodeId;
- signal->theData[0] = DihContinueB::ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- case TabRecord::TLS_ACTIVE:
- ok = true;
- jam();
- /**
- * The table is participating in an LCP currently
- */
- // Fall through
- break;
- case TabRecord::TLS_WRITING_TO_FILE:
- ok = true;
- jam();
- /**
- * This should never happen since we in the beginning of this function
- * checks the tabCopyStatus
- */
- ndbrequire(lcpOngoingFlag);
- ndbrequire(false);
- break;
- }
- ndbrequire(ok);
-
- /**
- * The table is participating in an LCP currently
- * and we removed some replicas that should have been checkpointed
- */
- ndbrequire(c_lcpState.lcpStatus != LCP_STATUS_IDLE);
- ndbrequire(tabPtr.p->tabLcpStatus == TabRecord::TLS_ACTIVE);
-
- /**
- * Save the table
- */
- tabPtr.p->tabCopyStatus = TabRecord::CS_REMOVE_NODE;
- tabPtr.p->tabUpdateState = TabRecord::US_REMOVE_NODE;
- tabPtr.p->tabRemoveNode = nodeId;
- signal->theData[0] = DihContinueB::ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-
- if(noOfRemainingLcpReplicas == 0){
- jam();
- /**
- * The removal on the failed node made the LCP complete
- */
- tabPtr.p->tabLcpStatus = TabRecord::TLS_WRITING_TO_FILE;
- checkLcpAllTablesDoneInLqh();
- }
-}
-
-void
-Dbdih::removeNodeFromTablesComplete(Signal* signal, Uint32 nodeId){
- jam();
-
- /**
- * Check if we "accidently" completed a LCP
- */
- checkLcpCompletedLab(signal);
-
- /**
- * Check if we (DIH) are finished with node fail handling
- */
- checkLocalNodefailComplete(signal, nodeId, NF_REMOVE_NODE_FROM_TABLE);
-}
-
-void
-Dbdih::checkLocalNodefailComplete(Signal* signal, Uint32 failedNodeId,
- NodefailHandlingStep step){
- jam();
-
- NodeRecordPtr nodePtr;
- nodePtr.i = failedNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- ndbrequire(nodePtr.p->m_nodefailSteps.get(step));
- nodePtr.p->m_nodefailSteps.clear(step);
-
- if(nodePtr.p->m_nodefailSteps.count() > 0){
- jam();
- return;
- }
-
- if (ERROR_INSERTED(7030))
- {
- g_eventLogger.info("Reenable GCP_PREPARE");
- CLEAR_ERROR_INSERT_VALUE;
- }
-
- NFCompleteRep * const nf = (NFCompleteRep *)&signal->theData[0];
- nf->blockNo = DBDIH;
- nf->nodeId = cownNodeId;
- nf->failedNodeId = failedNodeId;
- nf->from = __LINE__;
- sendSignal(reference(), GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBB);
-}
-
-
-void
-Dbdih::setLocalNodefailHandling(Signal* signal, Uint32 failedNodeId,
- NodefailHandlingStep step){
- jam();
-
- NodeRecordPtr nodePtr;
- nodePtr.i = failedNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- ndbrequire(!nodePtr.p->m_nodefailSteps.get(step));
- nodePtr.p->m_nodefailSteps.set(step);
-}
-
-void Dbdih::startLcpTakeOverLab(Signal* signal, Uint32 failedNodeId)
-{
- /*--------------------------------------------------------------------*/
- // Start LCP master take over process. Consists of the following steps.
- // 1) Ensure that all LQH's have reported all fragments they have been
- // told to checkpoint. Can be a fairly long step time-wise.
- // 2) Query all nodes about their LCP status.
- // During the query process we do not want our own state to change.
- // This can change due to delayed reception of LCP_REPORT, completed
- // save of table on disk or reception of DIH_LCPCOMPLETE from other
- // node.
- /*--------------------------------------------------------------------*/
-}//Dbdih::startLcpTakeOver()
-
-void Dbdih::execEMPTY_LCP_CONF(Signal* signal)
-{
- jamEntry();
-
- ndbrequire(c_lcpMasterTakeOverState.state == LMTOS_WAIT_EMPTY_LCP);
-
- const EmptyLcpConf * const conf = (EmptyLcpConf *)&signal->theData[0];
- Uint32 nodeId = conf->senderNodeId;
-
- if(!conf->idle){
- jam();
- if (conf->tableId < c_lcpMasterTakeOverState.minTableId) {
- jam();
- c_lcpMasterTakeOverState.minTableId = conf->tableId;
- c_lcpMasterTakeOverState.minFragId = conf->fragmentId;
- } else if (conf->tableId == c_lcpMasterTakeOverState.minTableId &&
- conf->fragmentId < c_lcpMasterTakeOverState.minFragId) {
- jam();
- c_lcpMasterTakeOverState.minFragId = conf->fragmentId;
- }//if
- if(isMaster()){
- jam();
- c_lcpState.m_LAST_LCP_FRAG_ORD.setWaitingFor(nodeId);
- }
- }
-
- receiveLoopMacro(EMPTY_LCP_REQ, nodeId);
- /*--------------------------------------------------------------------*/
- // Received all EMPTY_LCPCONF. We can continue with next phase of the
- // take over LCP master process.
- /*--------------------------------------------------------------------*/
- c_lcpMasterTakeOverState.set(LMTOS_WAIT_LCP_FRAG_REP, __LINE__);
- checkEmptyLcpComplete(signal);
- return;
-}//Dbdih::execEMPTY_LCPCONF()
-
-void
-Dbdih::checkEmptyLcpComplete(Signal *signal){
-
- ndbrequire(c_lcpMasterTakeOverState.state == LMTOS_WAIT_LCP_FRAG_REP);
-
- if(c_lcpState.noOfLcpFragRepOutstanding > 0){
- jam();
- return;
- }
-
- if(isMaster()){
- jam();
-
- signal->theData[0] = NDB_LE_LCP_TakeoverStarted;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
-
- signal->theData[0] = 7012;
- execDUMP_STATE_ORD(signal);
-
- if (ERROR_INSERTED(7194))
- {
- ndbout_c("7194 starting ZREMOVE_NODE_FROM_TABLE");
- signal->theData[0] = DihContinueB::ZREMOVE_NODE_FROM_TABLE;
- signal->theData[1] = c_lcpMasterTakeOverState.failedNodeId;
- signal->theData[2] = 0; // Tab id
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- }
-
- c_lcpMasterTakeOverState.set(LMTOS_INITIAL, __LINE__);
- MasterLCPReq * const req = (MasterLCPReq *)&signal->theData[0];
- req->masterRef = reference();
- req->failedNodeId = c_lcpMasterTakeOverState.failedNodeId;
- sendLoopMacro(MASTER_LCPREQ, sendMASTER_LCPREQ);
-
- } else {
- sendMASTER_LCPCONF(signal);
- }
-}
-
-/*--------------------------------------------------*/
-/* THE MASTER HAS FAILED AND THE NEW MASTER IS*/
-/* QUERYING THIS NODE ABOUT THE STATE OF THE */
-/* LOCAL CHECKPOINT PROTOCOL. */
-/*--------------------------------------------------*/
-void Dbdih::execMASTER_LCPREQ(Signal* signal)
-{
- const MasterLCPReq * const req = (MasterLCPReq *)&signal->theData[0];
- jamEntry();
- const BlockReference newMasterBlockref = req->masterRef;
-
- if (newMasterBlockref != cmasterdihref)
- {
- jam();
- ndbout_c("resending GSN_MASTER_LCPREQ");
- sendSignalWithDelay(reference(), GSN_MASTER_LCPREQ, signal,
- 50, signal->getLength());
- return;
- }
- Uint32 failedNodeId = req->failedNodeId;
-
- /**
- * There can be no take over with the same master
- */
- ndbrequire(c_lcpState.m_masterLcpDihRef != newMasterBlockref);
- c_lcpState.m_masterLcpDihRef = newMasterBlockref;
- c_lcpState.m_MASTER_LCPREQ_Received = true;
- c_lcpState.m_MASTER_LCPREQ_FailedNodeId = failedNodeId;
-
- if(newMasterBlockref != cmasterdihref){
- jam();
- ndbrequire(0);
- }
-
- sendMASTER_LCPCONF(signal);
-}//Dbdih::execMASTER_LCPREQ()
-
-void
-Dbdih::sendMASTER_LCPCONF(Signal * signal){
-
- if(!c_EMPTY_LCP_REQ_Counter.done()){
- /**
- * Have not received all EMPTY_LCP_REP
- * dare not answer MASTER_LCP_CONF yet
- */
- jam();
- return;
- }
-
- if(!c_lcpState.m_MASTER_LCPREQ_Received){
- jam();
- /**
- * Has not received MASTER_LCPREQ yet
- */
- return;
- }
-
- if(c_lcpState.lcpStatus == LCP_INIT_TABLES){
- jam();
- /**
- * Still aborting old initLcpLab
- */
- return;
- }
-
- if(c_lcpState.lcpStatus == LCP_COPY_GCI){
- jam();
- /**
- * Restart it
- */
- //Uint32 lcpId = SYSFILE->latestLCP_ID;
- SYSFILE->latestLCP_ID--;
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
-#if 0
- if(c_copyGCISlave.m_copyReason == CopyGCIReq::LOCAL_CHECKPOINT){
- g_eventLogger.info("Dbdih: Also resetting c_copyGCISlave");
- c_copyGCISlave.m_copyReason = CopyGCIReq::IDLE;
- c_copyGCISlave.m_expectedNextWord = 0;
- }
-#endif
- }
-
- MasterLCPConf::State lcpState;
- switch (c_lcpState.lcpStatus) {
- case LCP_STATUS_IDLE:
- jam();
- /*------------------------------------------------*/
- /* LOCAL CHECKPOINT IS CURRENTLY NOT ACTIVE */
- /* SINCE NO COPY OF RESTART INFORMATION HAVE*/
- /* BEEN RECEIVED YET. ALSO THE PREVIOUS */
- /* CHECKPOINT HAVE BEEN FULLY COMPLETED. */
- /*------------------------------------------------*/
- lcpState = MasterLCPConf::LCP_STATUS_IDLE;
- break;
- case LCP_STATUS_ACTIVE:
- jam();
- /*--------------------------------------------------*/
- /* COPY OF RESTART INFORMATION HAS BEEN */
- /* PERFORMED AND ALSO RESPONSE HAVE BEEN SENT.*/
- /*--------------------------------------------------*/
- lcpState = MasterLCPConf::LCP_STATUS_ACTIVE;
- break;
- case LCP_TAB_COMPLETED:
- jam();
- /*--------------------------------------------------------*/
- /* ALL LCP_REPORT'S HAVE BEEN COMPLETED FOR */
- /* ALL TABLES. SAVE OF AT LEAST ONE TABLE IS */
- /* ONGOING YET. */
- /*--------------------------------------------------------*/
- lcpState = MasterLCPConf::LCP_TAB_COMPLETED;
- break;
- case LCP_TAB_SAVED:
- jam();
- /*--------------------------------------------------------*/
- /* ALL LCP_REPORT'S HAVE BEEN COMPLETED FOR */
- /* ALL TABLES. ALL TABLES HAVE ALSO BEEN SAVED */
- /* ALL OTHER NODES ARE NOT YET FINISHED WITH */
- /* THE LOCAL CHECKPOINT. */
- /*--------------------------------------------------------*/
- lcpState = MasterLCPConf::LCP_TAB_SAVED;
- break;
- case LCP_TCGET:
- case LCP_CALCULATE_KEEP_GCI:
- case LCP_TC_CLOPSIZE:
- case LCP_START_LCP_ROUND:
- /**
- * These should only exists on the master
- * but since this is master take over
- * it not allowed
- */
- ndbrequire(false);
- lcpState= MasterLCPConf::LCP_STATUS_IDLE; // remove warning
- break;
- case LCP_COPY_GCI:
- case LCP_INIT_TABLES:
- /**
- * These two states are handled by if statements above
- */
- ndbrequire(false);
- lcpState= MasterLCPConf::LCP_STATUS_IDLE; // remove warning
- break;
- default:
- ndbrequire(false);
- lcpState= MasterLCPConf::LCP_STATUS_IDLE; // remove warning
- }//switch
-
- Uint32 failedNodeId = c_lcpState.m_MASTER_LCPREQ_FailedNodeId;
- MasterLCPConf * const conf = (MasterLCPConf *)&signal->theData[0];
- conf->senderNodeId = cownNodeId;
- conf->lcpState = lcpState;
- conf->failedNodeId = failedNodeId;
- sendSignal(c_lcpState.m_masterLcpDihRef, GSN_MASTER_LCPCONF,
- signal, MasterLCPConf::SignalLength, JBB);
-
- // Answer to MASTER_LCPREQ sent, reset flag so
- // that it's not sent again before another request comes in
- c_lcpState.m_MASTER_LCPREQ_Received = false;
-
- if(c_lcpState.lcpStatus == LCP_TAB_SAVED){
-#ifdef VM_TRACE
- g_eventLogger.info("Sending extra GSN_LCP_COMPLETE_REP to new master");
-#endif
- sendLCP_COMPLETE_REP(signal);
- }
-
- if(!isMaster()){
- c_lcpMasterTakeOverState.set(LMTOS_IDLE, __LINE__);
- checkLocalNodefailComplete(signal, failedNodeId, NF_LCP_TAKE_OVER);
- }
-
- return;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbdih::LcpMasterTakeOverState state){
- switch(state){
- case Dbdih::LMTOS_IDLE:
- out << "LMTOS_IDLE";
- break;
- case Dbdih::LMTOS_WAIT_EMPTY_LCP:
- out << "LMTOS_WAIT_EMPTY_LCP";
- break;
- case Dbdih::LMTOS_WAIT_LCP_FRAG_REP:
- out << "LMTOS_WAIT_EMPTY_LCP";
- break;
- case Dbdih::LMTOS_INITIAL:
- out << "LMTOS_INITIAL";
- break;
- case Dbdih::LMTOS_ALL_IDLE:
- out << "LMTOS_ALL_IDLE";
- break;
- case Dbdih::LMTOS_ALL_ACTIVE:
- out << "LMTOS_ALL_ACTIVE";
- break;
- case Dbdih::LMTOS_LCP_CONCLUDING:
- out << "LMTOS_LCP_CONCLUDING";
- break;
- case Dbdih::LMTOS_COPY_ONGOING:
- out << "LMTOS_COPY_ONGOING";
- break;
- }
- return out;
-}
-
-struct MASTERLCP_StateTransitions {
- Dbdih::LcpMasterTakeOverState CurrentState;
- MasterLCPConf::State ParticipantState;
- Dbdih::LcpMasterTakeOverState NewState;
-};
-
-static const
-MASTERLCP_StateTransitions g_masterLCPTakeoverStateTransitions[] = {
- /**
- * Current = LMTOS_INITIAL
- */
- { Dbdih::LMTOS_INITIAL,
- MasterLCPConf::LCP_STATUS_IDLE,
- Dbdih::LMTOS_ALL_IDLE },
-
- { Dbdih::LMTOS_INITIAL,
- MasterLCPConf::LCP_STATUS_ACTIVE,
- Dbdih::LMTOS_ALL_ACTIVE },
-
- { Dbdih::LMTOS_INITIAL,
- MasterLCPConf::LCP_TAB_COMPLETED,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- { Dbdih::LMTOS_INITIAL,
- MasterLCPConf::LCP_TAB_SAVED,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- /**
- * Current = LMTOS_ALL_IDLE
- */
- { Dbdih::LMTOS_ALL_IDLE,
- MasterLCPConf::LCP_STATUS_IDLE,
- Dbdih::LMTOS_ALL_IDLE },
-
- { Dbdih::LMTOS_ALL_IDLE,
- MasterLCPConf::LCP_STATUS_ACTIVE,
- Dbdih::LMTOS_COPY_ONGOING },
-
- { Dbdih::LMTOS_ALL_IDLE,
- MasterLCPConf::LCP_TAB_COMPLETED,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- { Dbdih::LMTOS_ALL_IDLE,
- MasterLCPConf::LCP_TAB_SAVED,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- /**
- * Current = LMTOS_COPY_ONGOING
- */
- { Dbdih::LMTOS_COPY_ONGOING,
- MasterLCPConf::LCP_STATUS_IDLE,
- Dbdih::LMTOS_COPY_ONGOING },
-
- { Dbdih::LMTOS_COPY_ONGOING,
- MasterLCPConf::LCP_STATUS_ACTIVE,
- Dbdih::LMTOS_COPY_ONGOING },
-
- /**
- * Current = LMTOS_ALL_ACTIVE
- */
- { Dbdih::LMTOS_ALL_ACTIVE,
- MasterLCPConf::LCP_STATUS_IDLE,
- Dbdih::LMTOS_COPY_ONGOING },
-
- { Dbdih::LMTOS_ALL_ACTIVE,
- MasterLCPConf::LCP_STATUS_ACTIVE,
- Dbdih::LMTOS_ALL_ACTIVE },
-
- { Dbdih::LMTOS_ALL_ACTIVE,
- MasterLCPConf::LCP_TAB_COMPLETED,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- { Dbdih::LMTOS_ALL_ACTIVE,
- MasterLCPConf::LCP_TAB_SAVED,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- /**
- * Current = LMTOS_LCP_CONCLUDING
- */
- { Dbdih::LMTOS_LCP_CONCLUDING,
- MasterLCPConf::LCP_STATUS_IDLE,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- { Dbdih::LMTOS_LCP_CONCLUDING,
- MasterLCPConf::LCP_STATUS_ACTIVE,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- { Dbdih::LMTOS_LCP_CONCLUDING,
- MasterLCPConf::LCP_TAB_COMPLETED,
- Dbdih::LMTOS_LCP_CONCLUDING },
-
- { Dbdih::LMTOS_LCP_CONCLUDING,
- MasterLCPConf::LCP_TAB_SAVED,
- Dbdih::LMTOS_LCP_CONCLUDING }
-};
-
-const Uint32 g_masterLCPTakeoverStateTransitionsRows =
-sizeof(g_masterLCPTakeoverStateTransitions) / sizeof(struct MASTERLCP_StateTransitions);
-
-void Dbdih::execMASTER_LCPCONF(Signal* signal)
-{
- const MasterLCPConf * const conf = (MasterLCPConf *)&signal->theData[0];
- jamEntry();
-
- if (ERROR_INSERTED(7194))
- {
- ndbout_c("delaying MASTER_LCPCONF due to error 7194");
- sendSignalWithDelay(reference(), GSN_MASTER_LCPCONF, signal,
- 300, signal->getLength());
- return;
- }
-
- Uint32 senderNodeId = conf->senderNodeId;
- MasterLCPConf::State lcpState = (MasterLCPConf::State)conf->lcpState;
- const Uint32 failedNodeId = conf->failedNodeId;
- NodeRecordPtr nodePtr;
- nodePtr.i = senderNodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- nodePtr.p->lcpStateAtTakeOver = lcpState;
-
- CRASH_INSERTION(7180);
-
-#ifdef VM_TRACE
- g_eventLogger.info("MASTER_LCPCONF");
- printMASTER_LCP_CONF(stdout, &signal->theData[0], 0, 0);
-#endif
-
- bool found = false;
- for(Uint32 i = 0; i<g_masterLCPTakeoverStateTransitionsRows; i++){
- const struct MASTERLCP_StateTransitions * valid =
- &g_masterLCPTakeoverStateTransitions[i];
-
- if(valid->CurrentState == c_lcpMasterTakeOverState.state &&
- valid->ParticipantState == lcpState){
- jam();
- found = true;
- c_lcpMasterTakeOverState.set(valid->NewState, __LINE__);
- break;
- }
- }
- ndbrequire(found);
-
- bool ok = false;
- switch(lcpState){
- case MasterLCPConf::LCP_STATUS_IDLE:
- ok = true;
- break;
- case MasterLCPConf::LCP_STATUS_ACTIVE:
- case MasterLCPConf::LCP_TAB_COMPLETED:
- case MasterLCPConf::LCP_TAB_SAVED:
- ok = true;
- c_lcpState.m_LCP_COMPLETE_REP_Counter_DIH.setWaitingFor(nodePtr.i);
- break;
- }
- ndbrequire(ok);
-
- receiveLoopMacro(MASTER_LCPREQ, senderNodeId);
- /*-------------------------------------------------------------------------*/
- // We have now received all responses and are ready to take over the LCP
- // protocol as master.
- /*-------------------------------------------------------------------------*/
- MASTER_LCPhandling(signal, failedNodeId);
-}//Dbdih::execMASTER_LCPCONF()
-
-void Dbdih::execMASTER_LCPREF(Signal* signal)
-{
- const MasterLCPRef * const ref = (MasterLCPRef *)&signal->theData[0];
- jamEntry();
- receiveLoopMacro(MASTER_LCPREQ, ref->senderNodeId);
- /*-------------------------------------------------------------------------*/
- // We have now received all responses and are ready to take over the LCP
- // protocol as master.
- /*-------------------------------------------------------------------------*/
- MASTER_LCPhandling(signal, ref->failedNodeId);
-}//Dbdih::execMASTER_LCPREF()
-
-void Dbdih::MASTER_LCPhandling(Signal* signal, Uint32 failedNodeId)
-{
- /*-------------------------------------------------------------------------
- *
- * WE ARE NOW READY TO CONCLUDE THE TAKE OVER AS MASTER.
- * WE HAVE ENOUGH INFO TO START UP ACTIVITIES IN THE PROPER PLACE.
- * ALSO SET THE PROPER STATE VARIABLES.
- *------------------------------------------------------------------------*/
- c_lcpState.currentFragment.tableId = c_lcpMasterTakeOverState.minTableId;
- c_lcpState.currentFragment.fragmentId = c_lcpMasterTakeOverState.minFragId;
- c_lcpState.m_LAST_LCP_FRAG_ORD = c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH;
-
- NodeRecordPtr failedNodePtr;
- failedNodePtr.i = failedNodeId;
- ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
-
- switch (c_lcpMasterTakeOverState.state) {
- case LMTOS_ALL_IDLE:
- jam();
- /* --------------------------------------------------------------------- */
- // All nodes were idle in the LCP protocol. Start checking for start of LCP
- // protocol.
- /* --------------------------------------------------------------------- */
-#ifdef VM_TRACE
- g_eventLogger.info("MASTER_LCPhandling:: LMTOS_ALL_IDLE -> checkLcpStart");
-#endif
- checkLcpStart(signal, __LINE__);
- break;
- case LMTOS_COPY_ONGOING:
- jam();
- /* --------------------------------------------------------------------- */
- // We were in the starting process of the LCP protocol. We will restart the
- // protocol by calculating the keep gci and storing the new lcp id.
- /* --------------------------------------------------------------------- */
-#ifdef VM_TRACE
- g_eventLogger.info("MASTER_LCPhandling:: LMTOS_COPY_ONGOING -> storeNewLcpId");
-#endif
- if (c_lcpState.lcpStatus == LCP_STATUS_ACTIVE) {
- jam();
- /*---------------------------------------------------------------------*/
- /* WE NEED TO DECREASE THE LATEST LCP ID SINCE WE HAVE ALREADY */
- /* STARTED THIS */
- /* LOCAL CHECKPOINT. */
- /*---------------------------------------------------------------------*/
- Uint32 lcpId = SYSFILE->latestLCP_ID;
-#ifdef VM_TRACE
- g_eventLogger.info("Decreasing latestLCP_ID from %d to %d", lcpId, lcpId - 1);
-#endif
- SYSFILE->latestLCP_ID--;
- }//if
- storeNewLcpIdLab(signal);
- break;
- case LMTOS_ALL_ACTIVE:
- {
- jam();
- /* -------------------------------------------------------------------
- * Everybody was in the active phase. We will restart sending
- * LCP_FRAGORD to the nodes from the new master.
- * We also need to set dihLcpStatus to ZACTIVE
- * in the master node since the master will wait for all nodes to
- * complete before finalising the LCP process.
- * ------------------------------------------------------------------ */
-#ifdef VM_TRACE
- g_eventLogger.info("MASTER_LCPhandling:: LMTOS_ALL_ACTIVE -> "
- "startLcpRoundLoopLab(table=%u, fragment=%u)",
- c_lcpMasterTakeOverState.minTableId,
- c_lcpMasterTakeOverState.minFragId);
-#endif
-
- c_lcpState.keepGci = SYSFILE->keepGCI;
- startLcpRoundLoopLab(signal, 0, 0);
- break;
- }
- case LMTOS_LCP_CONCLUDING:
- {
- jam();
- /* ------------------------------------------------------------------- */
- // The LCP process is in the finalisation phase. We simply wait for it to
- // complete with signals arriving in. We need to check also if we should
- // change state due to table write completion during state
- // collection phase.
- /* ------------------------------------------------------------------- */
- ndbrequire(c_lcpState.lcpStatus != LCP_STATUS_IDLE);
- startLcpRoundLoopLab(signal, 0, 0);
- break;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
- signal->theData[0] = NDB_LE_LCP_TakeoverCompleted;
- signal->theData[1] = c_lcpMasterTakeOverState.state;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- signal->theData[0] = 7012;
- execDUMP_STATE_ORD(signal);
-
- c_lcpMasterTakeOverState.set(LMTOS_IDLE, __LINE__);
-
- checkLocalNodefailComplete(signal, failedNodePtr.i, NF_LCP_TAKE_OVER);
-}
-
-/* ------------------------------------------------------------------------- */
-/* A BLOCK OR A NODE HAS COMPLETED THE HANDLING OF THE NODE FAILURE. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::execNF_COMPLETEREP(Signal* signal)
-{
- NodeRecordPtr failedNodePtr;
- NFCompleteRep * const nfCompleteRep = (NFCompleteRep *)&signal->theData[0];
- jamEntry();
- const Uint32 blockNo = nfCompleteRep->blockNo;
- Uint32 nodeId = nfCompleteRep->nodeId;
- failedNodePtr.i = nfCompleteRep->failedNodeId;
-
- ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRecord);
- switch (blockNo) {
- case DBTC:
- jam();
- ndbrequire(failedNodePtr.p->dbtcFailCompleted == ZFALSE);
- /* -------------------------------------------------------------------- */
- // Report the event that DBTC completed node failure handling.
- /* -------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_NodeFailCompleted;
- signal->theData[1] = DBTC;
- signal->theData[2] = failedNodePtr.i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
-
- failedNodePtr.p->dbtcFailCompleted = ZTRUE;
- break;
- case DBDICT:
- jam();
- ndbrequire(failedNodePtr.p->dbdictFailCompleted == ZFALSE);
- /* --------------------------------------------------------------------- */
- // Report the event that DBDICT completed node failure handling.
- /* --------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_NodeFailCompleted;
- signal->theData[1] = DBDICT;
- signal->theData[2] = failedNodePtr.i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
-
- failedNodePtr.p->dbdictFailCompleted = ZTRUE;
- break;
- case DBDIH:
- jam();
- ndbrequire(failedNodePtr.p->dbdihFailCompleted == ZFALSE);
- /* --------------------------------------------------------------------- */
- // Report the event that DBDIH completed node failure handling.
- /* --------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_NodeFailCompleted;
- signal->theData[1] = DBDIH;
- signal->theData[2] = failedNodePtr.i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
-
- failedNodePtr.p->dbdihFailCompleted = ZTRUE;
- break;
- case DBLQH:
- jam();
- ndbrequire(failedNodePtr.p->dblqhFailCompleted == ZFALSE);
- /* --------------------------------------------------------------------- */
- // Report the event that DBDIH completed node failure handling.
- /* --------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_NodeFailCompleted;
- signal->theData[1] = DBLQH;
- signal->theData[2] = failedNodePtr.i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
-
- failedNodePtr.p->dblqhFailCompleted = ZTRUE;
- break;
- case 0: /* Node has finished */
- jam();
- ndbrequire(nodeId < MAX_NDB_NODES);
-
- if (failedNodePtr.p->recNODE_FAILREP == ZFALSE) {
- jam();
- /* ------------------------------------------------------------------- */
- // We received a report about completion of node failure before we
- // received the message about the NODE failure ourselves.
- // We will send the signal to ourselves with a small delay
- // (10 milliseconds).
- /* ------------------------------------------------------------------- */
- //nf->from = __LINE__;
- sendSignalWithDelay(reference(), GSN_NF_COMPLETEREP, signal, 10,
- signal->length());
- return;
- }//if
-
- if (!failedNodePtr.p->m_NF_COMPLETE_REP.isWaitingFor(nodeId)){
- jam();
- return;
- }
-
- failedNodePtr.p->m_NF_COMPLETE_REP.clearWaitingFor(nodeId);;
-
- /* -------------------------------------------------------------------- */
- // Report the event that nodeId has completed node failure handling.
- /* -------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_NodeFailCompleted;
- signal->theData[1] = 0;
- signal->theData[2] = failedNodePtr.i;
- signal->theData[3] = nodeId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
-
- nodeFailCompletedCheckLab(signal, failedNodePtr);
- return;
- break;
- default:
- ndbrequire(false);
- return;
- break;
- }//switch
- if (failedNodePtr.p->dbtcFailCompleted == ZFALSE) {
- jam();
- return;
- }//if
- if (failedNodePtr.p->dbdictFailCompleted == ZFALSE) {
- jam();
- return;
- }//if
- if (failedNodePtr.p->dbdihFailCompleted == ZFALSE) {
- jam();
- return;
- }//if
- if (failedNodePtr.p->dblqhFailCompleted == ZFALSE) {
- jam();
- return;
- }//if
- /* ----------------------------------------------------------------------- */
- /* ALL BLOCKS IN THIS NODE HAVE COMPLETED THEIR PART OF HANDLING THE */
- /* NODE FAILURE. WE CAN NOW REPORT THIS COMPLETION TO ALL OTHER NODES. */
- /* ----------------------------------------------------------------------- */
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- BlockReference ref = calcDihBlockRef(nodePtr.i);
- NFCompleteRep * const nf = (NFCompleteRep *)&signal->theData[0];
- nf->blockNo = 0;
- nf->nodeId = cownNodeId;
- nf->failedNodeId = failedNodePtr.i;
- nf->from = __LINE__;
- sendSignal(ref, GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBB);
- }//if
- }//for
- return;
-}//Dbdih::execNF_COMPLETEREP()
-
-void Dbdih::nodeFailCompletedCheckLab(Signal* signal,
- NodeRecordPtr failedNodePtr)
-{
- jam();
- if (!failedNodePtr.p->m_NF_COMPLETE_REP.done()){
- jam();
- return;
- }//if
- /* ---------------------------------------------------------------------- */
- /* ALL BLOCKS IN ALL NODES HAVE NOW REPORTED COMPLETION OF THE NODE */
- /* FAILURE HANDLING. WE ARE NOW READY TO ACCEPT THAT THIS NODE STARTS */
- /* AGAIN. */
- /* ---------------------------------------------------------------------- */
- jam();
- failedNodePtr.p->nodeStatus = NodeRecord::DEAD;
- failedNodePtr.p->recNODE_FAILREP = ZFALSE;
-
- /* ---------------------------------------------------------------------- */
- // Report the event that all nodes completed node failure handling.
- /* ---------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_NodeFailCompleted;
- signal->theData[1] = 0;
- signal->theData[2] = failedNodePtr.i;
- signal->theData[3] = 0;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
-
- /* ---------------------------------------------------------------------- */
- // Report to QMGR that we have concluded recovery handling of this node.
- /* ---------------------------------------------------------------------- */
- signal->theData[0] = failedNodePtr.i;
- sendSignal(QMGR_REF, GSN_NDB_FAILCONF, signal, 1, JBB);
-
- if (isMaster()) {
- jam();
- /* --------------------------------------------------------------------- */
- /* IF WE ARE MASTER WE MUST CHECK IF COPY FRAGMENT WAS INTERRUPTED */
- /* BY THE FAILED NODES. */
- /* --------------------------------------------------------------------- */
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = 0;
- ptrAss(takeOverPtr, takeOverRecord);
- if ((takeOverPtr.p->toMasterStatus == TakeOverRecord::COPY_FRAG) &&
- (failedNodePtr.i == takeOverPtr.p->toCopyNode)) {
- jam();
-#ifdef VM_TRACE
- ndbrequire("Tell jonas" == 0);
-#endif
- /*------------------------------------------------------------------*/
- /* WE ARE CURRENTLY IN THE PROCESS OF COPYING A FRAGMENT. WE */
- /* WILL CHECK IF THE COPY NODE HAVE FAILED. */
- /*------------------------------------------------------------------*/
- takeOverPtr.p->toMasterStatus = TakeOverRecord::SELECTING_NEXT;
- startNextCopyFragment(signal, takeOverPtr.i);
- return;
- }//if
- checkStartTakeOver(signal);
- }//if
- return;
-}//Dbdih::nodeFailCompletedCheckLab()
-
-/*****************************************************************************/
-/* ********** SEIZING / RELEASING MODULE *************/
-/*****************************************************************************/
-/*
- 3.4 L O C A L N O D E S E I Z E
- ************************************
- */
-/*
- 3.4.1 L O C A L N O D E S E I Z E R E Q U E S T
- ******************************************************
- */
-void Dbdih::execDISEIZEREQ(Signal* signal)
-{
- ConnectRecordPtr connectPtr;
- jamEntry();
- Uint32 userPtr = signal->theData[0];
- BlockReference userRef = signal->theData[1];
- ndbrequire(cfirstconnect != RNIL);
- connectPtr.i = cfirstconnect;
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
- cfirstconnect = connectPtr.p->nfConnect;
- connectPtr.p->nfConnect = RNIL;
- connectPtr.p->userpointer = userPtr;
- connectPtr.p->userblockref = userRef;
- connectPtr.p->connectState = ConnectRecord::INUSE;
- signal->theData[0] = connectPtr.p->userpointer;
- signal->theData[1] = connectPtr.i;
- sendSignal(userRef, GSN_DISEIZECONF, signal, 2, JBB);
-}//Dbdih::execDISEIZEREQ()
-
-/*
- 3.5 L O C A L N O D E R E L E A S E
- ****************************************
- */
-/*
- 3.5.1 L O C A L N O D E R E L E A S E R E Q U E S T
- *******************************************************=
- */
-void Dbdih::execDIRELEASEREQ(Signal* signal)
-{
- ConnectRecordPtr connectPtr;
- jamEntry();
- connectPtr.i = signal->theData[0];
- Uint32 userRef = signal->theData[2];
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
- ndbrequire(connectPtr.p->connectState != ConnectRecord::FREE);
- ndbrequire(connectPtr.p->userblockref == userRef);
- signal->theData[0] = connectPtr.p->userpointer;
- sendSignal(connectPtr.p->userblockref, GSN_DIRELEASECONF, signal, 1, JBB);
- release_connect(connectPtr);
-}//Dbdih::execDIRELEASEREQ()
-
-/*
- 3.7 A D D T A B L E
- **********************=
- */
-/*****************************************************************************/
-/* ********** TABLE ADDING MODULE *************/
-/*****************************************************************************/
-/*
- 3.7.1 A D D T A B L E M A I N L Y
- ***************************************
- */
-
-static inline void inc_node_or_group(Uint32 &node, Uint32 max_node)
-{
- Uint32 next = node + 1;
- node = (next == max_node ? 0 : next);
-}
-
-/*
- Spread fragments in backwards compatible mode
-*/
-static void set_default_node_groups(Signal *signal, Uint32 noFrags)
-{
- Uint16 *node_group_array = (Uint16*)&signal->theData[25];
- Uint32 i;
- node_group_array[0] = 0;
- for (i = 1; i < noFrags; i++)
- node_group_array[i] = UNDEF_NODEGROUP;
-}
-void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal)
-{
- Uint16 node_group_id[MAX_NDB_PARTITIONS];
- jamEntry();
- CreateFragmentationReq * const req =
- (CreateFragmentationReq*)signal->getDataPtr();
-
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
- Uint32 noOfFragments = req->noOfFragments;
- const Uint32 fragType = req->fragmentationType;
- const Uint32 primaryTableId = req->primaryTableId;
-
- Uint32 err = 0;
-
- do {
- NodeGroupRecordPtr NGPtr;
- TabRecordPtr primTabPtr;
- Uint32 count = 2;
- Uint16 noOfReplicas = cnoReplicas;
- Uint16 *fragments = (Uint16*)(signal->theData+25);
- if (primaryTableId == RNIL) {
- jam();
- switch ((DictTabInfo::FragmentType)fragType)
- {
- /*
- Backward compatability and for all places in code not changed.
- */
- case DictTabInfo::AllNodesSmallTable:
- jam();
- noOfFragments = csystemnodes;
- set_default_node_groups(signal, noOfFragments);
- break;
- case DictTabInfo::AllNodesMediumTable:
- jam();
- noOfFragments = 2 * csystemnodes;
- set_default_node_groups(signal, noOfFragments);
- break;
- case DictTabInfo::AllNodesLargeTable:
- jam();
- noOfFragments = 4 * csystemnodes;
- set_default_node_groups(signal, noOfFragments);
- break;
- case DictTabInfo::SingleFragment:
- jam();
- noOfFragments = 1;
- set_default_node_groups(signal, noOfFragments);
- break;
- case DictTabInfo::DistrKeyHash:
- jam();
- case DictTabInfo::DistrKeyLin:
- jam();
- if (noOfFragments == 0)
- {
- jam();
- noOfFragments = csystemnodes;
- set_default_node_groups(signal, noOfFragments);
- }
- break;
- default:
- jam();
- if (noOfFragments == 0)
- {
- jam();
- err = CreateFragmentationRef::InvalidFragmentationType;
- }
- break;
- }
- if (err)
- break;
- /*
- When we come here the the exact partition is specified
- and there is an array of node groups sent along as well.
- */
- memcpy(&node_group_id[0], &signal->theData[25], 2 * noOfFragments);
- Uint16 next_replica_node[MAX_NDB_NODES];
- memset(next_replica_node,0,sizeof(next_replica_node));
- Uint32 default_node_group= c_nextNodeGroup;
- for(Uint32 fragNo = 0; fragNo < noOfFragments; fragNo++)
- {
- jam();
- NGPtr.i = node_group_id[fragNo];
- if (NGPtr.i == UNDEF_NODEGROUP)
- {
- jam();
- NGPtr.i = default_node_group;
- }
- if (NGPtr.i > cnoOfNodeGroups)
- {
- jam();
- err = CreateFragmentationRef::InvalidNodeGroup;
- break;
- }
- ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- const Uint32 max = NGPtr.p->nodeCount;
-
- fragments[count++] = c_nextLogPart++; // Store logpart first
- Uint32 tmp= next_replica_node[NGPtr.i];
- for(Uint32 replicaNo = 0; replicaNo < noOfReplicas; replicaNo++)
- {
- jam();
- const Uint16 nodeId = NGPtr.p->nodesInGroup[tmp];
- fragments[count++]= nodeId;
- inc_node_or_group(tmp, max);
- }
- inc_node_or_group(tmp, max);
- next_replica_node[NGPtr.i]= tmp;
-
- /**
- * Next node group for next fragment
- */
- inc_node_or_group(default_node_group, cnoOfNodeGroups);
- }
- if (err)
- {
- jam();
- break;
- }
- else
- {
- jam();
- c_nextNodeGroup = default_node_group;
- }
- } else {
- if (primaryTableId >= ctabFileSize) {
- jam();
- err = CreateFragmentationRef::InvalidPrimaryTable;
- break;
- }
- primTabPtr.i = primaryTableId;
- ptrAss(primTabPtr, tabRecord);
- if (primTabPtr.p->tabStatus != TabRecord::TS_ACTIVE) {
- jam();
- err = CreateFragmentationRef::InvalidPrimaryTable;
- break;
- }
- noOfFragments= primTabPtr.p->totalfragments;
- for (Uint32 fragNo = 0;
- fragNo < noOfFragments; fragNo++) {
- jam();
- FragmentstorePtr fragPtr;
- ReplicaRecordPtr replicaPtr;
- getFragstore(primTabPtr.p, fragNo, fragPtr);
- fragments[count++] = fragPtr.p->m_log_part_id;
- fragments[count++] = fragPtr.p->preferredPrimary;
- for (replicaPtr.i = fragPtr.p->storedReplicas;
- replicaPtr.i != RNIL;
- replicaPtr.i = replicaPtr.p->nextReplica) {
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if (replicaPtr.p->procNode != fragPtr.p->preferredPrimary) {
- jam();
- fragments[count++]= replicaPtr.p->procNode;
- }
- }
- for (replicaPtr.i = fragPtr.p->oldStoredReplicas;
- replicaPtr.i != RNIL;
- replicaPtr.i = replicaPtr.p->nextReplica) {
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if (replicaPtr.p->procNode != fragPtr.p->preferredPrimary) {
- jam();
- fragments[count++]= replicaPtr.p->procNode;
- }
- }
- }
- }
- if(count != (2U + (1 + noOfReplicas) * noOfFragments)){
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Illegal configuration change: NoOfReplicas."
- " Can't be applied online ");
- progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf);
- }
-
- CreateFragmentationConf * const conf =
- (CreateFragmentationConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->noOfReplicas = (Uint32)noOfReplicas;
- conf->noOfFragments = (Uint32)noOfFragments;
-
- fragments[0]= noOfReplicas;
- fragments[1]= noOfFragments;
-
- if(senderRef != 0)
- {
- jam();
- 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);
- }
- // Always ACK/NACK (here ACK)
- signal->theData[0] = 0;
- return;
- } while(false);
- // Always ACK/NACK (here NACK)
- signal->theData[0] = err;
-}
-
-void Dbdih::execDIADDTABREQ(Signal* signal)
-{
- Uint32 fragType;
- jamEntry();
-
- DiAddTabReq * const req = (DiAddTabReq*)signal->getDataPtr();
-
- // Seize connect record
- ndbrequire(cfirstconnect != RNIL);
- ConnectRecordPtr connectPtr;
- connectPtr.i = cfirstconnect;
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
- cfirstconnect = connectPtr.p->nfConnect;
-
- const Uint32 userPtr = req->connectPtr;
- const BlockReference userRef = signal->getSendersBlockRef();
- connectPtr.p->nfConnect = RNIL;
- connectPtr.p->userpointer = userPtr;
- connectPtr.p->userblockref = userRef;
- connectPtr.p->connectState = ConnectRecord::INUSE;
- connectPtr.p->table = req->tableId;
-
- TabRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- tabPtr.p->connectrec = connectPtr.i;
- tabPtr.p->tableType = req->tableType;
- fragType= req->fragType;
- tabPtr.p->schemaVersion = req->schemaVersion;
- tabPtr.p->primaryTableId = req->primaryTableId;
-
- if(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE){
- jam();
- tabPtr.p->tabStatus = TabRecord::TS_CREATING;
- sendAddFragreq(signal, connectPtr, tabPtr, 0);
- return;
- }
-
- if(getNodeState().getSystemRestartInProgress() &&
- tabPtr.p->tabStatus == TabRecord::TS_IDLE){
- jam();
-
- ndbrequire(cmasterNodeId == getOwnNodeId());
- tabPtr.p->tabStatus = TabRecord::TS_CREATING;
-
- initTableFile(tabPtr);
- FileRecordPtr filePtr;
- filePtr.i = tabPtr.p->tabFile[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- openFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::OPENING_TABLE;
- return;
- }
-
- /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
- /* AT THE TIME OF INITIATING THE FILE OF TABLE */
- /* DESCRIPTION IS CREATED FOR APPROPRIATE SIZE. EACH */
- /* EACH RECORD IN THIS FILE HAS THE INFORMATION ABOUT */
- /* ONE TABLE. THE POINTER TO THIS RECORD IS THE TABLE */
- /* REFERENCE. IN THE BEGINNING ALL RECORDS ARE CREATED */
- /* BUT THEY DO NOT HAVE ANY INFORMATION ABOUT ANY TABLE*/
- /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
- tabPtr.p->tabStatus = TabRecord::TS_CREATING;
- if(req->loggedTable)
- tabPtr.p->tabStorage= TabRecord::ST_NORMAL;
- else if(req->temporaryTable)
- tabPtr.p->tabStorage= TabRecord::ST_TEMPORARY;
- else
- tabPtr.p->tabStorage= TabRecord::ST_NOLOGGING;
- tabPtr.p->kvalue = req->kValue;
-
- switch ((DictTabInfo::FragmentType)fragType)
- {
- case DictTabInfo::AllNodesSmallTable:
- case DictTabInfo::AllNodesMediumTable:
- case DictTabInfo::AllNodesLargeTable:
- case DictTabInfo::SingleFragment:
- jam();
- case DictTabInfo::DistrKeyLin:
- jam();
- tabPtr.p->method= TabRecord::LINEAR_HASH;
- break;
- case DictTabInfo::DistrKeyHash:
- case DictTabInfo::DistrKeyUniqueHashIndex:
- case DictTabInfo::DistrKeyOrderedIndex:
- jam();
- tabPtr.p->method= TabRecord::NORMAL_HASH;
- break;
- case DictTabInfo::UserDefined:
- jam();
- tabPtr.p->method= TabRecord::USER_DEFINED;
- break;
- default:
- ndbrequire(false);
- }
-
- union {
- Uint16 fragments[2 + MAX_FRAG_PER_NODE*MAX_REPLICAS*MAX_NDB_NODES];
- Uint32 align;
- };
- SegmentedSectionPtr fragDataPtr;
- LINT_INIT(fragDataPtr.i);
- LINT_INIT(fragDataPtr.sz);
- signal->getSection(fragDataPtr, DiAddTabReq::FRAGMENTATION);
- copy((Uint32*)fragments, fragDataPtr);
- releaseSections(signal);
-
- const Uint32 noReplicas = fragments[0];
- const Uint32 noFragments = fragments[1];
-
- tabPtr.p->noOfBackups = noReplicas - 1;
- tabPtr.p->totalfragments = noFragments;
- ndbrequire(noReplicas == cnoReplicas); // Only allowed
-
- if (ERROR_INSERTED(7173)) {
- CLEAR_ERROR_INSERT_VALUE;
- addtabrefuseLab(signal, connectPtr, ZREPLERROR1);
- return;
- }
- if ((noReplicas * noFragments) > cnoFreeReplicaRec) {
- jam();
- addtabrefuseLab(signal, connectPtr, ZREPLERROR1);
- return;
- }//if
- if (noFragments > cremainingfrags) {
- jam();
- addtabrefuseLab(signal, connectPtr, ZREPLERROR1);
- return;
- }//if
-
- Uint32 logTotalFragments = 1;
- while (logTotalFragments <= tabPtr.p->totalfragments) {
- jam();
- logTotalFragments <<= 1;
- }
- logTotalFragments >>= 1;
- tabPtr.p->mask = logTotalFragments - 1;
- tabPtr.p->hashpointer = tabPtr.p->totalfragments - logTotalFragments;
- allocFragments(tabPtr.p->totalfragments, tabPtr);
-
- Uint32 index = 2;
- for (Uint32 fragId = 0; fragId < noFragments; fragId++) {
- jam();
- FragmentstorePtr fragPtr;
- Uint32 activeIndex = 0;
- getFragstore(tabPtr.p, fragId, fragPtr);
- fragPtr.p->m_log_part_id = fragments[index++];
- fragPtr.p->preferredPrimary = fragments[index];
-
- for (Uint32 i = 0; i<noReplicas; i++) {
- const Uint32 nodeId = fragments[index++];
- ReplicaRecordPtr replicaPtr;
- allocStoredReplica(fragPtr, replicaPtr, nodeId);
- if (getNodeStatus(nodeId) == NodeRecord::ALIVE) {
- jam();
- ndbrequire(activeIndex < MAX_REPLICAS);
- fragPtr.p->activeNodes[activeIndex] = nodeId;
- activeIndex++;
- } else {
- jam();
- removeStoredReplica(fragPtr, replicaPtr);
- linkOldStoredReplica(fragPtr, replicaPtr);
- }//if
- }//for
- fragPtr.p->fragReplicas = activeIndex;
- ndbrequire(activeIndex > 0 && fragPtr.p->storedReplicas != RNIL);
- }
- initTableFile(tabPtr);
- tabPtr.p->tabCopyStatus = TabRecord::CS_ADD_TABLE_MASTER;
- signal->theData[0] = DihContinueB::ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Dbdih::addTable_closeConf(Signal * signal, Uint32 tabPtrI){
- TabRecordPtr tabPtr;
- tabPtr.i = tabPtrI;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- ConnectRecordPtr connectPtr;
- connectPtr.i = tabPtr.p->connectrec;
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
-
- sendAddFragreq(signal, connectPtr, tabPtr, 0);
-}
-
-void
-Dbdih::sendAddFragreq(Signal* signal, ConnectRecordPtr connectPtr,
- TabRecordPtr tabPtr, Uint32 fragId){
- jam();
- const Uint32 fragCount = tabPtr.p->totalfragments;
- ReplicaRecordPtr replicaPtr;
- LINT_INIT(replicaPtr.p);
- replicaPtr.i = RNIL;
- FragmentstorePtr fragPtr;
- for(; fragId<fragCount; fragId++){
- jam();
- getFragstore(tabPtr.p, fragId, fragPtr);
-
- replicaPtr.i = fragPtr.p->storedReplicas;
- while(replicaPtr.i != RNIL){
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if(replicaPtr.p->procNode == getOwnNodeId()){
- break;
- }
- replicaPtr.i = replicaPtr.p->nextReplica;
- }
-
- if(replicaPtr.i != RNIL){
- jam();
- break;
- }
-
- replicaPtr.i = fragPtr.p->oldStoredReplicas;
- while(replicaPtr.i != RNIL){
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if(replicaPtr.p->procNode == getOwnNodeId()){
- break;
- }
- replicaPtr.i = replicaPtr.p->nextReplica;
- }
-
- if(replicaPtr.i != RNIL){
- jam();
- break;
- }
- }
-
- if(replicaPtr.i != RNIL){
- jam();
- ndbrequire(fragId < fragCount);
- ndbrequire(replicaPtr.p->procNode == getOwnNodeId());
-
- Uint32 requestInfo = 0;
- if(tabPtr.p->tabStorage != TabRecord::ST_NORMAL){
- requestInfo |= LqhFragReq::TemporaryTable;
- }
-
- if(getNodeState().getNodeRestartInProgress()){
- requestInfo |= LqhFragReq::CreateInRunning;
- }
-
- AddFragReq* const req = (AddFragReq*)signal->getDataPtr();
- req->dihPtr = connectPtr.i;
- req->senderData = connectPtr.p->userpointer;
- req->fragmentId = fragId;
- req->requestInfo = requestInfo;
- req->tableId = tabPtr.i;
- req->nextLCP = 0;
- req->nodeId = getOwnNodeId();
- req->totalFragments = fragCount;
- req->startGci = SYSFILE->newestRestorableGCI;
- req->logPartId = fragPtr.p->m_log_part_id;
- sendSignal(DBDICT_REF, GSN_ADD_FRAGREQ, signal,
- AddFragReq::SignalLength, JBB);
- return;
- }
-
- // Done
- DiAddTabConf * const conf = (DiAddTabConf*)signal->getDataPtr();
- conf->senderData = connectPtr.p->userpointer;
- sendSignal(connectPtr.p->userblockref, GSN_DIADDTABCONF, signal,
- DiAddTabConf::SignalLength, JBB);
-
- // Release
- release_connect(connectPtr);
-}
-void
-Dbdih::release_connect(ConnectRecordPtr ptr)
-{
- ptr.p->userblockref = ZNIL;
- ptr.p->userpointer = RNIL;
- ptr.p->connectState = ConnectRecord::FREE;
- ptr.p->nfConnect = cfirstconnect;
- cfirstconnect = ptr.i;
-}
-
-void
-Dbdih::execADD_FRAGCONF(Signal* signal){
- jamEntry();
- AddFragConf * const conf = (AddFragConf*)signal->getDataPtr();
-
- ConnectRecordPtr connectPtr;
- connectPtr.i = conf->dihPtr;
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
-
- TabRecordPtr tabPtr;
- tabPtr.i = connectPtr.p->table;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- sendAddFragreq(signal, connectPtr, tabPtr, conf->fragId + 1);
-}
-
-void
-Dbdih::execADD_FRAGREF(Signal* signal){
- jamEntry();
- AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
-
- ConnectRecordPtr connectPtr;
- connectPtr.i = ref->dihPtr;
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
-
- {
- DiAddTabRef * const ref = (DiAddTabRef*)signal->getDataPtr();
- ref->senderData = connectPtr.p->userpointer;
- ref->errorCode = ~0;
- sendSignal(connectPtr.p->userblockref, GSN_DIADDTABREF, signal,
- DiAddTabRef::SignalLength, JBB);
- }
-
- // Release
- release_connect(connectPtr);
-}
-
-/*
- 3.7.1.3 R E F U S E
- *********************
- */
-void Dbdih::addtabrefuseLab(Signal* signal, ConnectRecordPtr connectPtr, Uint32 errorCode)
-{
- signal->theData[0] = connectPtr.p->userpointer;
- signal->theData[1] = errorCode;
- sendSignal(connectPtr.p->userblockref, GSN_DIADDTABREF, signal, 2, JBB);
- release_connect(connectPtr);
- return;
-}//Dbdih::addtabrefuseLab()
-
-/*
- 3.7.2 A D D T A B L E D U P L I C A T I O N
- *************************************************
- */
-/*
- 3.7.2.1 A D D T A B L E D U P L I C A T I O N R E Q U E S T
- *******************************************************************=
- */
-
-/*
- D E L E T E T A B L E
- **********************=
- */
-/*****************************************************************************/
-/*********** DELETE TABLE MODULE *************/
-/*****************************************************************************/
-void
-Dbdih::execDROP_TAB_REQ(Signal* signal){
- jamEntry();
- DropTabReq* req = (DropTabReq*)signal->getDataPtr();
-
- TabRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- tabPtr.p->m_dropTab.tabUserRef = req->senderRef;
- tabPtr.p->m_dropTab.tabUserPtr = req->senderData;
-
- DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
-
- switch(rt){
- case DropTabReq::OnlineDropTab:
- jam();
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_DROPPING);
- releaseTable(tabPtr);
- break;
- case DropTabReq::CreateTabDrop:
- jam();
- releaseTable(tabPtr);
- break;
- case DropTabReq::RestartDropTab:
- break;
- }
-
- startDeleteFile(signal, tabPtr);
-}
-
-void Dbdih::startDeleteFile(Signal* signal, TabRecordPtr tabPtr)
-{
- if (tabPtr.p->tabFile[0] == RNIL) {
- jam();
- initTableFile(tabPtr);
- }//if
- openTableFileForDelete(signal, tabPtr.p->tabFile[0]);
-}//Dbdih::startDeleteFile()
-
-void Dbdih::openTableFileForDelete(Signal* signal, Uint32 fileIndex)
-{
- FileRecordPtr filePtr;
- filePtr.i = fileIndex;
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- openFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::TABLE_OPEN_FOR_DELETE;
-}//Dbdih::openTableFileForDelete()
-
-void Dbdih::tableOpenLab(Signal* signal, FileRecordPtr filePtr)
-{
- closeFileDelete(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::TABLE_CLOSE_DELETE;
- return;
-}//Dbdih::tableOpenLab()
-
-void Dbdih::tableDeleteLab(Signal* signal, FileRecordPtr filePtr)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if (filePtr.i == tabPtr.p->tabFile[0]) {
- jam();
- openTableFileForDelete(signal, tabPtr.p->tabFile[1]);
- return;
- }//if
- ndbrequire(filePtr.i == tabPtr.p->tabFile[1]);
-
- releaseFile(tabPtr.p->tabFile[0]);
- releaseFile(tabPtr.p->tabFile[1]);
- tabPtr.p->tabFile[0] = tabPtr.p->tabFile[1] = RNIL;
-
- tabPtr.p->tabStatus = TabRecord::TS_IDLE;
-
- DropTabConf * const dropConf = (DropTabConf *)signal->getDataPtrSend();
- dropConf->senderRef = reference();
- dropConf->senderData = tabPtr.p->m_dropTab.tabUserPtr;
- dropConf->tableId = tabPtr.i;
- sendSignal(tabPtr.p->m_dropTab.tabUserRef, GSN_DROP_TAB_CONF,
- signal, DropTabConf::SignalLength, JBB);
-
- tabPtr.p->m_dropTab.tabUserPtr = RNIL;
- tabPtr.p->m_dropTab.tabUserRef = 0;
-}//Dbdih::tableDeleteLab()
-
-
-void Dbdih::releaseTable(TabRecordPtr tabPtr)
-{
- FragmentstorePtr fragPtr;
- if (tabPtr.p->noOfFragChunks > 0) {
- for (Uint32 fragId = 0; fragId < tabPtr.p->totalfragments; fragId++) {
- jam();
- getFragstore(tabPtr.p, fragId, fragPtr);
- releaseReplicas(fragPtr.p->storedReplicas);
- releaseReplicas(fragPtr.p->oldStoredReplicas);
- }//for
- releaseFragments(tabPtr);
- }
- if (tabPtr.p->tabFile[0] != RNIL) {
- jam();
- releaseFile(tabPtr.p->tabFile[0]);
- releaseFile(tabPtr.p->tabFile[1]);
- tabPtr.p->tabFile[0] = tabPtr.p->tabFile[1] = RNIL;
- }//if
-}//Dbdih::releaseTable()
-
-void Dbdih::releaseReplicas(Uint32 replicaPtrI)
-{
- ReplicaRecordPtr replicaPtr;
- replicaPtr.i = replicaPtrI;
- jam();
- while (replicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- Uint32 tmp = replicaPtr.p->nextReplica;
- replicaPtr.p->nextReplica = cfirstfreeReplica;
- cfirstfreeReplica = replicaPtr.i;
- replicaPtr.i = tmp;
- cnoFreeReplicaRec++;
- }//while
-}//Dbdih::releaseReplicas()
-
-void Dbdih::seizeReplicaRec(ReplicaRecordPtr& replicaPtr)
-{
- replicaPtr.i = cfirstfreeReplica;
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- cfirstfreeReplica = replicaPtr.p->nextReplica;
- cnoFreeReplicaRec--;
- replicaPtr.p->nextReplica = RNIL;
-}//Dbdih::seizeReplicaRec()
-
-void Dbdih::releaseFile(Uint32 fileIndex)
-{
- FileRecordPtr filePtr;
- filePtr.i = fileIndex;
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- filePtr.p->nextFile = cfirstfreeFile;
- cfirstfreeFile = filePtr.i;
-}//Dbdih::releaseFile()
-
-
-void Dbdih::execALTER_TAB_REQ(Signal * signal)
-{
- AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
- const Uint32 changeMask = req->changeMask;
- const Uint32 tableId = req->tableId;
- const Uint32 tableVersion = req->tableVersion;
- const Uint32 gci = req->gci;
- AlterTabReq::RequestType requestType =
- (AlterTabReq::RequestType) req->requestType;
-
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- tabPtr.p->schemaVersion = tableVersion;
-
- // Request handled successfully
- AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->changeMask = changeMask;
- conf->tableId = tableId;
- conf->tableVersion = tableVersion;
- conf->gci = gci;
- conf->requestType = requestType;
- sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
- AlterTabConf::SignalLength, JBB);
-}
-
-/*
- G E T N O D E S
- **********************=
- */
-/*****************************************************************************/
-/* ********** TRANSACTION HANDLING MODULE *************/
-/*****************************************************************************/
-/*
- 3.8.1 G E T N O D E S R E Q U E S T
- ******************************************
- Asks what nodes should be part of a transaction.
-*/
-void Dbdih::execDIGETNODESREQ(Signal* signal)
-{
- const DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
- FragmentstorePtr fragPtr;
- TabRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- Uint32 hashValue = req->hashValue;
- Uint32 ttabFileSize = ctabFileSize;
- Uint32 fragId;
- DiGetNodesConf * const conf = (DiGetNodesConf *)&signal->theData[0];
- TabRecord* regTabDesc = tabRecord;
- jamEntry();
- ptrCheckGuard(tabPtr, ttabFileSize, regTabDesc);
- if (tabPtr.p->method == TabRecord::LINEAR_HASH)
- {
- jam();
- fragId = hashValue & tabPtr.p->mask;
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
- if (fragId < tabPtr.p->hashpointer) {
- jam();
- fragId = hashValue & ((tabPtr.p->mask << 1) + 1);
- }//if
- }
- else if (tabPtr.p->method == TabRecord::NORMAL_HASH)
- {
- jam();
- fragId= hashValue % tabPtr.p->totalfragments;
- }
- else
- {
- jam();
- ndbassert(tabPtr.p->method == TabRecord::USER_DEFINED);
- fragId= hashValue;
- if (fragId >= tabPtr.p->totalfragments)
- {
- jam();
- conf->zero= 1; //Indicate error;
- signal->theData[1]= ZUNDEFINED_FRAGMENT_ERROR;
- return;
- }
- }
- getFragstore(tabPtr.p, fragId, fragPtr);
- Uint32 nodeCount = extractNodeInfo(fragPtr.p, conf->nodes);
- Uint32 sig2 = (nodeCount - 1) +
- (fragPtr.p->distributionKey << 16);
- conf->zero = 0;
- conf->reqinfo = sig2;
- conf->fragId = fragId;
-}//Dbdih::execDIGETNODESREQ()
-
-Uint32 Dbdih::extractNodeInfo(const Fragmentstore * fragPtr, Uint32 nodes[])
-{
- Uint32 nodeCount = 0;
- for (Uint32 i = 0; i < fragPtr->fragReplicas; i++) {
- jam();
- NodeRecordPtr nodePtr;
- ndbrequire(i < MAX_REPLICAS);
- nodePtr.i = fragPtr->activeNodes[i];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->useInTransactions) {
- jam();
- nodes[nodeCount] = nodePtr.i;
- nodeCount++;
- }//if
- }//for
- ndbrequire(nodeCount > 0);
- return nodeCount;
-}//Dbdih::extractNodeInfo()
-
-void
-Dbdih::getFragstore(TabRecord * tab, //In parameter
- Uint32 fragNo, //In parameter
- FragmentstorePtr & fragptr) //Out parameter
-{
- FragmentstorePtr fragPtr;
- Uint32 chunkNo = fragNo >> LOG_NO_OF_FRAGS_PER_CHUNK;
- Uint32 chunkIndex = fragNo & (NO_OF_FRAGS_PER_CHUNK - 1);
- Uint32 TfragstoreFileSize = cfragstoreFileSize;
- Fragmentstore* TfragStore = fragmentstore;
- if (chunkNo < MAX_NDB_NODES) {
- fragPtr.i = tab->startFid[chunkNo] + chunkIndex;
- ptrCheckGuard(fragPtr, TfragstoreFileSize, TfragStore);
- fragptr = fragPtr;
- return;
- }//if
- ndbrequire(false);
-}//Dbdih::getFragstore()
-
-void Dbdih::allocFragments(Uint32 noOfFragments, TabRecordPtr tabPtr)
-{
- FragmentstorePtr fragPtr;
- Uint32 noOfChunks = (noOfFragments + (NO_OF_FRAGS_PER_CHUNK - 1)) >> LOG_NO_OF_FRAGS_PER_CHUNK;
- ndbrequire(cremainingfrags >= noOfFragments);
- for (Uint32 i = 0; i < noOfChunks; i++) {
- jam();
- Uint32 baseFrag = cfirstfragstore;
- tabPtr.p->startFid[i] = baseFrag;
- fragPtr.i = baseFrag;
- ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore);
- cfirstfragstore = fragPtr.p->nextFragmentChunk;
- cremainingfrags -= NO_OF_FRAGS_PER_CHUNK;
- for (Uint32 j = 0; j < NO_OF_FRAGS_PER_CHUNK; j++) {
- jam();
- fragPtr.i = baseFrag + j;
- ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore);
- initFragstore(fragPtr);
- }//if
- }//for
- tabPtr.p->noOfFragChunks = noOfChunks;
-}//Dbdih::allocFragments()
-
-void Dbdih::releaseFragments(TabRecordPtr tabPtr)
-{
- FragmentstorePtr fragPtr;
- for (Uint32 i = 0; i < tabPtr.p->noOfFragChunks; i++) {
- jam();
- Uint32 baseFrag = tabPtr.p->startFid[i];
- fragPtr.i = baseFrag;
- ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore);
- fragPtr.p->nextFragmentChunk = cfirstfragstore;
- cfirstfragstore = baseFrag;
- tabPtr.p->startFid[i] = RNIL;
- cremainingfrags += NO_OF_FRAGS_PER_CHUNK;
- }//for
- tabPtr.p->noOfFragChunks = 0;
-}//Dbdih::releaseFragments()
-
-void Dbdih::initialiseFragstore()
-{
- Uint32 i;
- FragmentstorePtr fragPtr;
- for (i = 0; i < cfragstoreFileSize; i++) {
- fragPtr.i = i;
- ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore);
- initFragstore(fragPtr);
- }//for
- Uint32 noOfChunks = cfragstoreFileSize >> LOG_NO_OF_FRAGS_PER_CHUNK;
- fragPtr.i = 0;
- cfirstfragstore = RNIL;
- cremainingfrags = 0;
- for (i = 0; i < noOfChunks; i++) {
- refresh_watch_dog();
- ptrCheckGuard(fragPtr, cfragstoreFileSize, fragmentstore);
- fragPtr.p->nextFragmentChunk = cfirstfragstore;
- cfirstfragstore = fragPtr.i;
- fragPtr.i += NO_OF_FRAGS_PER_CHUNK;
- cremainingfrags += NO_OF_FRAGS_PER_CHUNK;
- }//for
-}//Dbdih::initialiseFragstore()
-
-/*
- 3.9 V E R I F I C A T I O N
- ****************************=
- */
-/****************************************************************************/
-/* ********** VERIFICATION SUB-MODULE *************/
-/****************************************************************************/
-/*
- 3.9.1 R E C E I V I N G O F V E R I F I C A T I O N R E Q U E S T
- *************************************************************************
- */
-void Dbdih::execDIVERIFYREQ(Signal* signal)
-{
-
- jamEntry();
- if ((getBlockCommit() == false) &&
- (cfirstVerifyQueue == RNIL)) {
- jam();
- /*-----------------------------------------------------------------------*/
- // We are not blocked and the verify queue was empty currently so we can
- // simply reply back to TC immediately. The method was called with
- // EXECUTE_DIRECT so we reply back by setting signal data and returning.
- // theData[0] already contains the correct information so
- // we need not touch it.
- /*-----------------------------------------------------------------------*/
- signal->theData[1] = currentgcp;
- signal->theData[2] = 0;
- return;
- }//if
- /*-------------------------------------------------------------------------*/
- // Since we are blocked we need to put this operation last in the verify
- // queue to ensure that operation starts up in the correct order.
- /*-------------------------------------------------------------------------*/
- ApiConnectRecordPtr tmpApiConnectptr;
- ApiConnectRecordPtr localApiConnectptr;
-
- cverifyQueueCounter++;
- localApiConnectptr.i = signal->theData[0];
- tmpApiConnectptr.i = clastVerifyQueue;
- ptrCheckGuard(localApiConnectptr, capiConnectFileSize, apiConnectRecord);
- localApiConnectptr.p->apiGci = cnewgcp;
- localApiConnectptr.p->nextApi = RNIL;
- clastVerifyQueue = localApiConnectptr.i;
- if (tmpApiConnectptr.i == RNIL) {
- jam();
- cfirstVerifyQueue = localApiConnectptr.i;
- } else {
- jam();
- ptrCheckGuard(tmpApiConnectptr, capiConnectFileSize, apiConnectRecord);
- tmpApiConnectptr.p->nextApi = localApiConnectptr.i;
- }//if
- emptyverificbuffer(signal, false);
- signal->theData[2] = 1; // Indicate no immediate return
- return;
-}//Dbdih::execDIVERIFYREQ()
-
-void Dbdih::execDI_FCOUNTREQ(Signal* signal)
-{
- DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtr();
- ConnectRecordPtr connectPtr;
- TabRecordPtr tabPtr;
- const BlockReference senderRef = signal->senderBlockRef();
- const Uint32 senderData = req->m_senderData;
- jamEntry();
- connectPtr.i = req->m_connectionData;
- tabPtr.i = req->m_tableRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE)
- {
- DihFragCountRef* ref = (DihFragCountRef*)signal->getDataPtrSend();
- //connectPtr.i == RNIL -> question without connect record
- if(connectPtr.i == RNIL)
- ref->m_connectionData = RNIL;
- else
- {
- jam();
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
- ref->m_connectionData = connectPtr.p->userpointer;
- }
- ref->m_tableRef = tabPtr.i;
- ref->m_senderData = senderData;
- ref->m_error = DihFragCountRef::ErroneousTableState;
- ref->m_tableStatus = tabPtr.p->tabStatus;
- sendSignal(senderRef, GSN_DI_FCOUNTREF, signal,
- DihFragCountRef::SignalLength, JBB);
- return;
- }
-
- if(connectPtr.i != RNIL){
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
- if (connectPtr.p->connectState == ConnectRecord::INUSE) {
- jam();
- DihFragCountConf* conf = (DihFragCountConf*)signal->getDataPtrSend();
- conf->m_connectionData = connectPtr.p->userpointer;
- conf->m_tableRef = tabPtr.i;
- conf->m_senderData = senderData;
- conf->m_fragmentCount = tabPtr.p->totalfragments;
- conf->m_noOfBackups = tabPtr.p->noOfBackups;
- sendSignal(connectPtr.p->userblockref, GSN_DI_FCOUNTCONF, signal,
- DihFragCountConf::SignalLength, JBB);
- return;
- }//if
- DihFragCountRef* ref = (DihFragCountRef*)signal->getDataPtrSend();
- ref->m_connectionData = connectPtr.p->userpointer;
- ref->m_tableRef = tabPtr.i;
- ref->m_senderData = senderData;
- ref->m_error = DihFragCountRef::ErroneousTableState;
- ref->m_tableStatus = tabPtr.p->tabStatus;
- sendSignal(connectPtr.p->userblockref, GSN_DI_FCOUNTREF, signal,
- DihFragCountRef::SignalLength, JBB);
- return;
- }//if
- DihFragCountConf* conf = (DihFragCountConf*)signal->getDataPtrSend();
- //connectPtr.i == RNIL -> question without connect record
- conf->m_connectionData = RNIL;
- conf->m_tableRef = tabPtr.i;
- conf->m_senderData = senderData;
- conf->m_fragmentCount = tabPtr.p->totalfragments;
- conf->m_noOfBackups = tabPtr.p->noOfBackups;
- sendSignal(senderRef, GSN_DI_FCOUNTCONF, signal,
- DihFragCountConf::SignalLength, JBB);
-}//Dbdih::execDI_FCOUNTREQ()
-
-void Dbdih::execDIGETPRIMREQ(Signal* signal)
-{
- FragmentstorePtr fragPtr;
- ConnectRecordPtr connectPtr;
- TabRecordPtr tabPtr;
- jamEntry();
- Uint32 passThrough = signal->theData[1];
- tabPtr.i = signal->theData[2];
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType)) {
- jam();
- tabPtr.i = tabPtr.p->primaryTableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- }
- Uint32 fragId = signal->theData[3];
-
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
- connectPtr.i = signal->theData[0];
- if(connectPtr.i != RNIL)
- {
- jam();
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
- signal->theData[0] = connectPtr.p->userpointer;
- }
- else
- {
- jam();
- signal->theData[0] = RNIL;
- }
-
- Uint32 nodes[MAX_REPLICAS];
- getFragstore(tabPtr.p, fragId, fragPtr);
- Uint32 count = extractNodeInfo(fragPtr.p, nodes);
-
- signal->theData[1] = passThrough;
- signal->theData[2] = nodes[0];
- signal->theData[3] = nodes[1];
- signal->theData[4] = nodes[2];
- signal->theData[5] = nodes[3];
- signal->theData[6] = count;
- signal->theData[7] = tabPtr.i;
- signal->theData[8] = fragId;
-
- const BlockReference senderRef = signal->senderBlockRef();
- sendSignal(senderRef, GSN_DIGETPRIMCONF, signal, 9, JBB);
-}//Dbdih::execDIGETPRIMREQ()
-
-/****************************************************************************/
-/* ********** GLOBAL-CHECK-POINT HANDLING MODULE *************/
-/****************************************************************************/
-/*
- 3.10 G L O B A L C H E C K P O I N T ( IN M A S T E R R O L E)
- *******************************************************************
- */
-void Dbdih::checkGcpStopLab(Signal* signal)
-{
- Uint32 tgcpStatus;
-
- tgcpStatus = cgcpStatus;
- if (tgcpStatus == coldGcpStatus) {
- jam();
- if (coldGcpId == cnewgcp) {
- jam();
- if (cgcpStatus != GCP_READY) {
- jam();
- cgcpSameCounter++;
- if (cgcpSameCounter == 1200) {
- jam();
-#ifdef VM_TRACE
- g_eventLogger.error("System crash due to GCP Stop in state = %u",
- (Uint32) cgcpStatus);
-#endif
- crashSystemAtGcpStop(signal, false);
- return;
- }//if
- } else {
- jam();
- if (cgcpOrderBlocked == 0) {
- jam();
- cgcpSameCounter++;
- if (cgcpSameCounter == 1200) {
- jam();
-#ifdef VM_TRACE
- g_eventLogger.error("System crash due to GCP Stop in state = %u",
- (Uint32) cgcpStatus);
-#endif
- crashSystemAtGcpStop(signal, false);
- return;
- }//if
- } else {
- jam();
- cgcpSameCounter = 0;
- }//if
- }//if
- } else {
- jam();
- cgcpSameCounter = 0;
- }//if
- } else {
- jam();
- cgcpSameCounter = 0;
- }//if
- signal->theData[0] = DihContinueB::ZCHECK_GCP_STOP;
- signal->theData[1] = coldGcpStatus;
- signal->theData[2] = cgcpStatus;
- signal->theData[3] = coldGcpId;
- signal->theData[4] = cnewgcp;
- signal->theData[5] = cgcpSameCounter;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 6);
- coldGcpStatus = cgcpStatus;
- coldGcpId = cnewgcp;
- return;
-}//Dbdih::checkGcpStopLab()
-
-void Dbdih::startGcpLab(Signal* signal, Uint32 aWaitTime)
-{
- if ((cgcpOrderBlocked == 1) ||
- (c_nodeStartMaster.blockGcp == true) ||
- (cfirstVerifyQueue != RNIL)) {
- /*************************************************************************/
- // 1: Global Checkpoint has been stopped by management command
- // 2: Global Checkpoint is blocked by node recovery activity
- // 3: Previous global checkpoint is not yet completed.
- // All this means that global checkpoint cannot start now.
- /*************************************************************************/
- jam();
- cgcpStartCounter++;
- signal->theData[0] = DihContinueB::ZSTART_GCP;
- signal->theData[1] = aWaitTime > 100 ? (aWaitTime - 100) : 0;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
- return;
- }//if
- if (cstartGcpNow == false && aWaitTime > 100){
- /*************************************************************************/
- // We still have more than 100 milliseconds before we start the next and
- // nobody has ordered immediate start of a global checkpoint.
- // During initial start we will use continuos global checkpoints to
- // speed it up since we need to complete a global checkpoint after
- // inserting a lot of records.
- /*************************************************************************/
- jam();
- cgcpStartCounter++;
- signal->theData[0] = DihContinueB::ZSTART_GCP;
- signal->theData[1] = (aWaitTime - 100);
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
- return;
- }//if
- cgcpStartCounter = 0;
- cstartGcpNow = false;
- /***************************************************************************/
- // Report the event that a global checkpoint has started.
- /***************************************************************************/
- signal->theData[0] = NDB_LE_GlobalCheckpointStarted; //Event type
- signal->theData[1] = cnewgcp;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- CRASH_INSERTION(7000);
- cnewgcp++;
- signal->setTrace(TestOrd::TraceGlobalCheckpoint);
- sendLoopMacro(GCP_PREPARE, sendGCP_PREPARE);
- cgcpStatus = GCP_PREPARE_SENT;
-}//Dbdih::startGcpLab()
-
-void Dbdih::execGCP_PREPARECONF(Signal* signal)
-{
- jamEntry();
- Uint32 senderNodeId = signal->theData[0];
- Uint32 gci = signal->theData[1];
- ndbrequire(gci == cnewgcp);
- receiveLoopMacro(GCP_PREPARE, senderNodeId);
- //-------------------------------------------------------------
- // We have now received all replies. We are ready to continue
- // with committing the global checkpoint.
- //-------------------------------------------------------------
- gcpcommitreqLab(signal);
-}//Dbdih::execGCP_PREPARECONF()
-
-void Dbdih::gcpcommitreqLab(Signal* signal)
-{
- CRASH_INSERTION(7001);
- sendLoopMacro(GCP_COMMIT, sendGCP_COMMIT);
- cgcpStatus = GCP_COMMIT_SENT;
- return;
-}//Dbdih::gcpcommitreqLab()
-
-void Dbdih::execGCP_NODEFINISH(Signal* signal)
-{
- jamEntry();
- const Uint32 senderNodeId = signal->theData[0];
- const Uint32 gci = signal->theData[1];
- const Uint32 failureNr = signal->theData[2];
- if (!isMaster()) {
- jam();
- ndbrequire(failureNr > cfailurenr);
- //-------------------------------------------------------------
- // Another node thinks we are master. This could happen when he
- // has heard of a node failure which I have not heard of. Ignore
- // signal in this case since we will discover it by sending
- // MASTER_GCPREQ to the node.
- //-------------------------------------------------------------
- return;
- } else if (cmasterState == MASTER_TAKE_OVER_GCP) {
- jam();
- //-------------------------------------------------------------
- // We are currently taking over as master. Ignore
- // signal in this case since we will discover it in reception of
- // MASTER_GCPCONF.
- //-------------------------------------------------------------
- return;
- } else {
- ndbrequire(cmasterState == MASTER_ACTIVE);
- }//if
- ndbrequire(gci == coldgcp);
- receiveLoopMacro(GCP_COMMIT, senderNodeId);
- //-------------------------------------------------------------
- // We have now received all replies. We are ready to continue
- // with saving the global checkpoint to disk.
- //-------------------------------------------------------------
- CRASH_INSERTION(7002);
- gcpsavereqLab(signal);
- return;
-}//Dbdih::execGCP_NODEFINISH()
-
-void Dbdih::gcpsavereqLab(Signal* signal)
-{
- sendLoopMacro(GCP_SAVEREQ, sendGCP_SAVEREQ);
- cgcpStatus = GCP_NODE_FINISHED;
-}//Dbdih::gcpsavereqLab()
-
-void Dbdih::execGCP_SAVECONF(Signal* signal)
-{
- jamEntry();
- const GCPSaveConf * const saveConf = (GCPSaveConf*)&signal->theData[0];
- ndbrequire(saveConf->gci == coldgcp);
- ndbrequire(saveConf->nodeId == saveConf->dihPtr);
- SYSFILE->lastCompletedGCI[saveConf->nodeId] = saveConf->gci;
- GCP_SAVEhandling(signal, saveConf->nodeId);
-}//Dbdih::execGCP_SAVECONF()
-
-void Dbdih::execGCP_SAVEREF(Signal* signal)
-{
- jamEntry();
- const GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
- ndbrequire(saveRef->gci == coldgcp);
- ndbrequire(saveRef->nodeId == saveRef->dihPtr);
- /**
- * Only allow reason not to save
- */
- ndbrequire(saveRef->errorCode == GCPSaveRef::NodeShutdownInProgress ||
- saveRef->errorCode == GCPSaveRef::FakedSignalDueToNodeFailure ||
- saveRef->errorCode == GCPSaveRef::NodeRestartInProgress);
- GCP_SAVEhandling(signal, saveRef->nodeId);
-}//Dbdih::execGCP_SAVEREF()
-
-void Dbdih::GCP_SAVEhandling(Signal* signal, Uint32 nodeId)
-{
- receiveLoopMacro(GCP_SAVEREQ, nodeId);
- /*-------------------------------------------------------------------------*/
- // All nodes have replied. We are ready to update the system file.
- /*-------------------------------------------------------------------------*/
- cgcpStatus = GCP_SAVE_LQH_FINISHED;
- CRASH_INSERTION(7003);
- checkToCopy();
- /**------------------------------------------------------------------------
- * SET NEW RECOVERABLE GCI. ALSO RESET RESTART COUNTER TO ZERO.
- * THIS INDICATES THAT THE SYSTEM HAS BEEN RECOVERED AND SURVIVED AT
- * LEAST ONE GLOBAL CHECKPOINT PERIOD. WE WILL USE THIS PARAMETER TO
- * SET BACK THE RESTART GCI IF WE ENCOUNTER MORE THAN ONE UNSUCCESSFUL
- * RESTART.
- *------------------------------------------------------------------------*/
- SYSFILE->newestRestorableGCI = coldgcp;
- if(Sysfile::getInitialStartOngoing(SYSFILE->systemRestartBits) &&
- getNodeState().startLevel == NodeState::SL_STARTED){
- jam();
-#if 0
- g_eventLogger.info("Dbdih: Clearing initial start ongoing");
-#endif
- Sysfile::clearInitialStartOngoing(SYSFILE->systemRestartBits);
- }
- copyGciLab(signal, CopyGCIReq::GLOBAL_CHECKPOINT);
-}//Dbdih::GCP_SAVEhandling()
-
-/*
- 3.11 G L O B A L C H E C K P O I N T (N O T - M A S T E R)
- *************************************************************
- */
-void Dbdih::execGCP_PREPARE(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(7005);
-
- if (ERROR_INSERTED(7030))
- {
- cgckptflag = true;
- g_eventLogger.info("Delayed GCP_PREPARE 5s");
- sendSignalWithDelay(reference(), GSN_GCP_PREPARE, signal, 5000,
- signal->getLength());
- return;
- }
-
- Uint32 masterNodeId = signal->theData[0];
- Uint32 gci = signal->theData[1];
- BlockReference retRef = calcDihBlockRef(masterNodeId);
-
- ndbrequire (cmasterdihref == retRef);
- ndbrequire (cgcpParticipantState == GCP_PARTICIPANT_READY);
- ndbrequire (gci == (currentgcp + 1));
-
- cgckptflag = true;
- cgcpParticipantState = GCP_PARTICIPANT_PREPARE_RECEIVED;
- cnewgcp = gci;
-
- if (ERROR_INSERTED(7031))
- {
- g_eventLogger.info("Crashing delayed in GCP_PREPARE 3s");
- signal->theData[0] = 9999;
- sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 3000, 1);
- return;
- }
-
- signal->theData[0] = cownNodeId;
- signal->theData[1] = gci;
- sendSignal(retRef, GSN_GCP_PREPARECONF, signal, 2, JBA);
- return;
-}//Dbdih::execGCP_PREPARE()
-
-void Dbdih::execGCP_COMMIT(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(7006);
- Uint32 masterNodeId = signal->theData[0];
- Uint32 gci = signal->theData[1];
-
- ndbrequire(gci == (currentgcp + 1));
- ndbrequire(masterNodeId = cmasterNodeId);
- ndbrequire(cgcpParticipantState == GCP_PARTICIPANT_PREPARE_RECEIVED);
-
- coldgcp = currentgcp;
- currentgcp = cnewgcp;
- cgckptflag = false;
- emptyverificbuffer(signal, true);
- cgcpParticipantState = GCP_PARTICIPANT_COMMIT_RECEIVED;
- signal->theData[0] = calcDihBlockRef(masterNodeId);
- signal->theData[1] = coldgcp;
- sendSignal(clocaltcblockref, GSN_GCP_NOMORETRANS, signal, 2, JBB);
- return;
-}//Dbdih::execGCP_COMMIT()
-
-void Dbdih::execGCP_TCFINISHED(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(7007);
- Uint32 retRef = signal->theData[0];
- Uint32 gci = signal->theData[1];
- ndbrequire(gci == coldgcp);
-
- if (ERROR_INSERTED(7181) || ERROR_INSERTED(7182))
- {
- c_error_7181_ref = retRef; // Save ref
- ndbout_c("killing %d", refToNode(cmasterdihref));
- signal->theData[0] = 9999;
- sendSignal(numberToRef(CMVMI, refToNode(cmasterdihref)),
- GSN_NDB_TAMPER, signal, 1, JBB);
- return;
- }
-
- cgcpParticipantState = GCP_PARTICIPANT_TC_FINISHED;
- signal->theData[0] = cownNodeId;
- signal->theData[1] = coldgcp;
- signal->theData[2] = cfailurenr;
- sendSignal(retRef, GSN_GCP_NODEFINISH, signal, 3, JBB);
-}//Dbdih::execGCP_TCFINISHED()
-
-/*****************************************************************************/
-//****** RECEIVING TAMPER REQUEST FROM NDBAPI ******
-/*****************************************************************************/
-void Dbdih::execDIHNDBTAMPER(Signal* signal)
-{
- jamEntry();
- Uint32 tcgcpblocked = signal->theData[0];
- /* ACTION TO BE TAKEN BY DIH */
- Uint32 tuserpointer = signal->theData[1];
- BlockReference tuserblockref = signal->theData[2];
- switch (tcgcpblocked) {
- case 1:
- jam();
- if (isMaster()) {
- jam();
- cgcpOrderBlocked = 1;
- } else {
- jam();
- /* TRANSFER THE REQUEST */
- /* TO MASTER*/
- signal->theData[0] = tcgcpblocked;
- signal->theData[1] = tuserpointer;
- signal->theData[2] = tuserblockref;
- sendSignal(cmasterdihref, GSN_DIHNDBTAMPER, signal, 3, JBB);
- }//if
- break;
- case 2:
- jam();
- if (isMaster()) {
- jam();
- cgcpOrderBlocked = 0;
- } else {
- jam();
- /* TRANSFER THE REQUEST */
- /* TO MASTER*/
- signal->theData[0] = tcgcpblocked;
- signal->theData[1] = tuserpointer;
- signal->theData[2] = tuserblockref;
- sendSignal(cmasterdihref, GSN_DIHNDBTAMPER, signal, 3, JBB);
- }//if
- break;
- case 3:
- ndbrequire(false);
- return;
- break;
- case 4:
- jam();
- signal->theData[0] = tuserpointer;
- signal->theData[1] = crestartGci;
- sendSignal(tuserblockref, GSN_DIHNDBTAMPER, signal, 2, JBB);
- break;
-#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.
- /*----------------------------------------------------------------------*/
- if (tuserpointer < 1000) {
- /*--------------------------------------------------------------------*/
- // Insert errors into QMGR.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = QMGR_REF;
- } else if (tuserpointer < 2000) {
- /*--------------------------------------------------------------------*/
- // Insert errors into NDBCNTR.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = NDBCNTR_REF;
- } else if (tuserpointer < 3000) {
- /*--------------------------------------------------------------------*/
- // Insert errors into NDBFS.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = NDBFS_REF;
- } else if (tuserpointer < 4000) {
- /*--------------------------------------------------------------------*/
- // Insert errors into DBACC.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = DBACC_REF;
- } else if (tuserpointer < 5000) {
- /*--------------------------------------------------------------------*/
- // Insert errors into DBTUP.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = DBTUP_REF;
- } else if (tuserpointer < 6000) {
- /*---------------------------------------------------------------------*/
- // Insert errors into DBLQH.
- /*---------------------------------------------------------------------*/
- jam();
- tuserblockref = DBLQH_REF;
- } else if (tuserpointer < 7000) {
- /*---------------------------------------------------------------------*/
- // Insert errors into DBDICT.
- /*---------------------------------------------------------------------*/
- jam();
- tuserblockref = DBDICT_REF;
- } else if (tuserpointer < 8000) {
- /*---------------------------------------------------------------------*/
- // Insert errors into DBDIH.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = DBDIH_REF;
- } else if (tuserpointer < 9000) {
- /*--------------------------------------------------------------------*/
- // Insert errors into DBTC.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = DBTC_REF;
- } else if (tuserpointer < 10000) {
- /*--------------------------------------------------------------------*/
- // Insert errors into CMVMI.
- /*--------------------------------------------------------------------*/
- jam();
- tuserblockref = CMVMI_REF;
- } else if (tuserpointer < 11000) {
- jam();
- tuserblockref = BACKUP_REF;
- } else if (tuserpointer < 12000) {
- // DBUTIL_REF ?
- jam();
- } else if (tuserpointer < 13000) {
- jam();
- tuserblockref = DBTUX_REF;
- } else if (tuserpointer < 14000) {
- jam();
- tuserblockref = SUMA_REF;
- } else if (tuserpointer < 15000) {
- jam();
- tuserblockref = DBDICT_REF;
- } else if (tuserpointer < 16000) {
- jam();
- tuserblockref = LGMAN_REF;
- } else if (tuserpointer < 17000) {
- jam();
- tuserblockref = TSMAN_REF;
- } else if (tuserpointer < 30000) {
- /*--------------------------------------------------------------------*/
- // Ignore errors in the 20000-range.
- /*--------------------------------------------------------------------*/
- jam();
- return;
- } else if (tuserpointer < 40000) {
- jam();
- /*--------------------------------------------------------------------*/
- // Redirect errors to master DIH in the 30000-range.
- /*--------------------------------------------------------------------*/
- tuserblockref = cmasterdihref;
- tuserpointer -= 30000;
- signal->theData[0] = 5;
- signal->theData[1] = tuserpointer;
- signal->theData[2] = tuserblockref;
- sendSignal(tuserblockref, GSN_DIHNDBTAMPER, signal, 3, JBB);
- return;
- } else if (tuserpointer < 50000) {
- NodeRecordPtr localNodeptr;
- Uint32 Tfound = 0;
- jam();
- /*--------------------------------------------------------------------*/
- // Redirect errors to non-master DIH in the 40000-range.
- /*--------------------------------------------------------------------*/
- tuserpointer -= 40000;
- for (localNodeptr.i = 1;
- localNodeptr.i < MAX_NDB_NODES;
- localNodeptr.i++) {
- jam();
- ptrAss(localNodeptr, nodeRecord);
- if ((localNodeptr.p->nodeStatus == NodeRecord::ALIVE) &&
- (localNodeptr.i != cmasterNodeId)) {
- jam();
- tuserblockref = calcDihBlockRef(localNodeptr.i);
- Tfound = 1;
- break;
- }//if
- }//for
- if (Tfound == 0) {
- jam();
- /*-------------------------------------------------------------------*/
- // Ignore since no non-master node existed.
- /*-------------------------------------------------------------------*/
- return;
- }//if
- signal->theData[0] = 5;
- signal->theData[1] = tuserpointer;
- signal->theData[2] = tuserblockref;
- sendSignal(tuserblockref, GSN_DIHNDBTAMPER, signal, 3, JBB);
- return;
- } else {
- jam();
- return;
- }//if
- signal->theData[0] = tuserpointer;
- if (tuserpointer != 0) {
- sendSignal(tuserblockref, GSN_NDB_TAMPER, signal, 1, JBB);
- } else {
- 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);
- }//if
- break;
-#endif
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbdih::execDIHNDBTAMPER()
-
-/*****************************************************************************/
-/* ********** FILE HANDLING MODULE *************/
-/*****************************************************************************/
-void Dbdih::copyGciLab(Signal* signal, CopyGCIReq::CopyReason reason)
-{
- if(c_copyGCIMaster.m_copyReason != CopyGCIReq::IDLE){
- /**
- * There can currently only be one waiting
- */
- ndbrequire(c_copyGCIMaster.m_waiting == CopyGCIReq::IDLE);
- c_copyGCIMaster.m_waiting = reason;
- return;
- }
- c_copyGCIMaster.m_copyReason = reason;
- sendLoopMacro(COPY_GCIREQ, sendCOPY_GCIREQ);
-
-}//Dbdih::copyGciLab()
-
-/* ------------------------------------------------------------------------- */
-/* COPY_GCICONF RESPONSE TO COPY_GCIREQ */
-/* ------------------------------------------------------------------------- */
-void Dbdih::execCOPY_GCICONF(Signal* signal)
-{
- jamEntry();
- NodeRecordPtr senderNodePtr;
- senderNodePtr.i = signal->theData[0];
- receiveLoopMacro(COPY_GCIREQ, senderNodePtr.i);
-
- CopyGCIReq::CopyReason waiting = c_copyGCIMaster.m_waiting;
- CopyGCIReq::CopyReason current = c_copyGCIMaster.m_copyReason;
-
- c_copyGCIMaster.m_copyReason = CopyGCIReq::IDLE;
- c_copyGCIMaster.m_waiting = CopyGCIReq::IDLE;
-
- bool ok = false;
- switch(current){
- case CopyGCIReq::RESTART:{
- ok = true;
- jam();
- DictStartReq * req = (DictStartReq*)&signal->theData[0];
- req->restartGci = SYSFILE->newestRestorableGCI;
- req->senderRef = reference();
- sendSignal(cdictblockref, GSN_DICTSTARTREQ,
- signal, DictStartReq::SignalLength, JBB);
- break;
- }
- case CopyGCIReq::LOCAL_CHECKPOINT:{
- ok = true;
- jam();
- startLcpRoundLab(signal);
- break;
- }
- case CopyGCIReq::GLOBAL_CHECKPOINT:
- ok = true;
- jam();
- checkToCopyCompleted(signal);
-
- /************************************************************************/
- // Report the event that a global checkpoint has completed.
- /************************************************************************/
- signal->setTrace(0);
- signal->theData[0] = NDB_LE_GlobalCheckpointCompleted; //Event type
- signal->theData[1] = coldgcp;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- c_newest_restorable_gci = coldgcp;
-
- CRASH_INSERTION(7004);
- emptyWaitGCPMasterQueue(signal);
- cgcpStatus = GCP_READY;
- signal->theData[0] = DihContinueB::ZSTART_GCP;
- signal->theData[1] = cgcpDelay;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
- if (c_nodeStartMaster.blockGcp == true) {
- jam();
- /* ------------------------------------------------------------------ */
- /* A NEW NODE WANTS IN AND WE MUST ALLOW IT TO COME IN NOW SINCE THE */
- /* GCP IS COMPLETED. */
- /* ------------------------------------------------------------------ */
- gcpBlockedLab(signal);
- }//if
- break;
- case CopyGCIReq::INITIAL_START_COMPLETED:
- ok = true;
- jam();
- initialStartCompletedLab(signal);
- break;
- case CopyGCIReq::IDLE:
- ok = false;
- jam();
- }
- ndbrequire(ok);
-
- /**
- * Pop queue
- */
- if(waiting != CopyGCIReq::IDLE){
- c_copyGCIMaster.m_copyReason = waiting;
- signal->theData[0] = DihContinueB::ZCOPY_GCI;
- signal->theData[1] = waiting;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- }
-}//Dbdih::execCOPY_GCICONF()
-
-void Dbdih::invalidateLcpInfoAfterSr()
-{
- NodeRecordPtr nodePtr;
- SYSFILE->latestLCP_ID--;
- Sysfile::clearLCPOngoing(SYSFILE->systemRestartBits);
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (!NdbNodeBitmask::get(SYSFILE->lcpActive, nodePtr.i)){
- jam();
- /* ------------------------------------------------------------------- */
- // The node was not active in the local checkpoint.
- // To avoid that we step the active status too fast to not
- // active we step back one step from Sysfile::NS_ActiveMissed_x.
- /* ------------------------------------------------------------------- */
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- /* ----------------------------------------------------------------- */
- // When not active in ongoing LCP and still active is a contradiction.
- /* ----------------------------------------------------------------- */
- ndbrequire(false);
- case Sysfile::NS_ActiveMissed_1:
- jam();
- nodePtr.p->activeStatus = Sysfile::NS_Active;
- break;
- case Sysfile::NS_ActiveMissed_2:
- jam();
- nodePtr.p->activeStatus = Sysfile::NS_ActiveMissed_1;
- break;
- default:
- jam();
- break;
- }//switch
- }//if
- }//for
- setNodeRestartInfoBits();
-}//Dbdih::invalidateLcpInfoAfterSr()
-
-/* ------------------------------------------------------------------------- */
-/* THE NEXT STEP IS TO WRITE THE FILE. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::openingCopyGciSkipInitLab(Signal* signal, FileRecordPtr filePtr)
-{
- writeRestorableGci(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::WRITING_COPY_GCI;
- return;
-}//Dbdih::openingCopyGciSkipInitLab()
-
-void Dbdih::writingCopyGciLab(Signal* signal, FileRecordPtr filePtr)
-{
- /* ----------------------------------------------------------------------- */
- /* WE HAVE NOW WRITTEN THIS FILE. WRITE ALSO NEXT FILE IF THIS IS NOT */
- /* ALREADY THE LAST. */
- /* ----------------------------------------------------------------------- */
- filePtr.p->reqStatus = FileRecord::IDLE;
- if (filePtr.i == crestartInfoFile[0]) {
- jam();
- filePtr.i = crestartInfoFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- if (filePtr.p->fileStatus == FileRecord::OPEN) {
- jam();
- openingCopyGciSkipInitLab(signal, filePtr);
- return;
- }//if
- openFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::OPENING_COPY_GCI;
- return;
- }//if
- /* ----------------------------------------------------------------------- */
- /* WE HAVE COMPLETED WRITING BOTH FILES SUCCESSFULLY. NOW REPORT OUR */
- /* SUCCESS TO THE MASTER DIH. BUT FIRST WE NEED TO RESET A NUMBER OF */
- /* VARIABLES USED BY THE LOCAL CHECKPOINT PROCESS (ONLY IF TRIGGERED */
- /* BY LOCAL CHECKPOINT PROCESS. */
- /* ----------------------------------------------------------------------- */
- CopyGCIReq::CopyReason reason = c_copyGCISlave.m_copyReason;
-
- if (reason == CopyGCIReq::GLOBAL_CHECKPOINT) {
- jam();
- cgcpParticipantState = GCP_PARTICIPANT_READY;
-
- SubGcpCompleteRep * const rep = (SubGcpCompleteRep*)signal->getDataPtr();
- rep->gci = coldgcp;
- sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength, JBB);
-
- EXECUTE_DIRECT(LGMAN, GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength);
- jamEntry();
- }
-
- jam();
- c_copyGCISlave.m_copyReason = CopyGCIReq::IDLE;
-
- if(c_copyGCISlave.m_senderRef == cmasterdihref){
- jam();
- /**
- * Only if same master
- */
- signal->theData[0] = c_copyGCISlave.m_senderData;
- sendSignal(c_copyGCISlave.m_senderRef, GSN_COPY_GCICONF, signal, 1, JBB);
-
- }
- return;
-}//Dbdih::writingCopyGciLab()
-
-void Dbdih::execSTART_LCP_REQ(Signal* signal){
- StartLcpReq * req = (StartLcpReq*)signal->getDataPtr();
-
- CRASH_INSERTION2(7021, isMaster());
- CRASH_INSERTION2(7022, !isMaster());
-
- ndbrequire(c_lcpState.m_masterLcpDihRef = req->senderRef);
- c_lcpState.m_participatingDIH = req->participatingDIH;
- c_lcpState.m_participatingLQH = req->participatingLQH;
-
- c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH = req->participatingLQH;
- if(isMaster()){
- jam();
- ndbrequire(isActiveMaster());
- c_lcpState.m_LCP_COMPLETE_REP_Counter_DIH = req->participatingDIH;
-
- } else {
- c_lcpState.m_LCP_COMPLETE_REP_Counter_DIH.clearWaitingFor();
- }
-
- c_lcpState.m_LCP_COMPLETE_REP_From_Master_Received = false;
-
- c_lcpState.setLcpStatus(LCP_INIT_TABLES, __LINE__);
-
- signal->theData[0] = DihContinueB::ZINIT_LCP;
- signal->theData[1] = c_lcpState.m_masterLcpDihRef;
- signal->theData[2] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-}
-
-void Dbdih::initLcpLab(Signal* signal, Uint32 senderRef, Uint32 tableId)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
-
- if(c_lcpState.m_masterLcpDihRef != senderRef){
- jam();
- /**
- * This is LCP master takeover
- */
-#ifdef VM_TRACE
- g_eventLogger.info("initLcpLab aborted due to LCP master takeover - 1");
-#endif
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
- sendMASTER_LCPCONF(signal);
- return;
- }
-
- if(c_lcpState.m_masterLcpDihRef != cmasterdihref){
- jam();
- /**
- * Master take over but has not yet received MASTER_LCPREQ
- */
-#ifdef VM_TRACE
- g_eventLogger.info("initLcpLab aborted due to LCP master takeover - 2");
-#endif
- return;
- }
-
- //const Uint32 lcpId = SYSFILE->latestLCP_ID;
-
- for(; tabPtr.i < ctabFileSize; tabPtr.i++){
-
- ptrAss(tabPtr, tabRecord);
-
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE) {
- jam();
- tabPtr.p->tabLcpStatus = TabRecord::TLS_COMPLETED;
- continue;
- }
-
- if (tabPtr.p->tabStorage != TabRecord::ST_NORMAL) {
- /**
- * Table is not logged
- */
- jam();
- tabPtr.p->tabLcpStatus = TabRecord::TLS_COMPLETED;
- continue;
- }
-
- if (tabPtr.p->tabCopyStatus != TabRecord::CS_IDLE) {
- /* ----------------------------------------------------------------- */
- // We protect the updates of table data structures by this variable.
- /* ----------------------------------------------------------------- */
- jam();
- signal->theData[0] = DihContinueB::ZINIT_LCP;
- signal->theData[1] = senderRef;
- signal->theData[2] = tabPtr.i;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 20, 3);
- return;
- }//if
-
- /**
- * Found a table
- */
- tabPtr.p->tabLcpStatus = TabRecord::TLS_ACTIVE;
-
- /**
- * For each fragment
- */
- for (Uint32 fragId = 0; fragId < tabPtr.p->totalfragments; fragId++) {
- jam();
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
-
- /**
- * For each of replica record
- */
- Uint32 replicaCount = 0;
- ReplicaRecordPtr replicaPtr;
- for(replicaPtr.i = fragPtr.p->storedReplicas; replicaPtr.i != RNIL;
- replicaPtr.i = replicaPtr.p->nextReplica) {
- jam();
-
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- Uint32 nodeId = replicaPtr.p->procNode;
- if(c_lcpState.m_participatingLQH.get(nodeId)){
- jam();
- replicaCount++;
- replicaPtr.p->lcpOngoingFlag = true;
- }
- }
-
- fragPtr.p->noLcpReplicas = replicaCount;
- }//for
-
- signal->theData[0] = DihContinueB::ZINIT_LCP;
- signal->theData[1] = senderRef;
- signal->theData[2] = tabPtr.i + 1;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
- }
-
- /**
- * No more tables
- */
- jam();
-
- if (c_lcpState.m_masterLcpDihRef != reference()){
- jam();
- ndbrequire(!isMaster());
- c_lcpState.setLcpStatus(LCP_STATUS_ACTIVE, __LINE__);
- } else {
- jam();
- ndbrequire(isMaster());
- }
-
- CRASH_INSERTION2(7023, isMaster());
- CRASH_INSERTION2(7024, !isMaster());
-
- jam();
- StartLcpConf * conf = (StartLcpConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- sendSignal(c_lcpState.m_masterLcpDihRef, GSN_START_LCP_CONF, signal,
- StartLcpConf::SignalLength, JBB);
- return;
-}//Dbdih::initLcpLab()
-
-/* ------------------------------------------------------------------------- */
-/* ERROR HANDLING FOR COPY RESTORABLE GCI FILE. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::openingCopyGciErrorLab(Signal* signal, FileRecordPtr filePtr)
-{
- createFileRw(signal, filePtr);
- /* ------------------------------------------------------------------------- */
- /* ERROR IN OPENING FILE. WE WILL TRY BY CREATING FILE INSTEAD. */
- /* ------------------------------------------------------------------------- */
- filePtr.p->reqStatus = FileRecord::CREATING_COPY_GCI;
- return;
-}//Dbdih::openingCopyGciErrorLab()
-
-/* ------------------------------------------------------------------------- */
-/* ENTER DICTSTARTCONF WITH */
-/* TBLOCKREF */
-/* ------------------------------------------------------------------------- */
-void Dbdih::dictStartConfLab(Signal* signal)
-{
- /* ----------------------------------------------------------------------- */
- /* WE HAVE NOW RECEIVED ALL THE TABLES TO RESTART. */
- /* ----------------------------------------------------------------------- */
- signal->theData[0] = DihContinueB::ZSTART_FRAGMENT;
- signal->theData[1] = 0; /* START WITH TABLE 0 */
- signal->theData[2] = 0; /* AND FRAGMENT 0 */
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
-}//Dbdih::dictStartConfLab()
-
-
-void Dbdih::openingTableLab(Signal* signal, FileRecordPtr filePtr)
-{
- /* ---------------------------------------------------------------------- */
- /* SUCCESSFULLY OPENED A FILE. READ THE FIRST PAGE OF THIS FILE. */
- /* ---------------------------------------------------------------------- */
- TabRecordPtr tabPtr;
- PageRecordPtr pagePtr;
-
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- tabPtr.p->noPages = 1;
- allocpage(pagePtr);
- tabPtr.p->pageRef[0] = pagePtr.i;
- readTabfile(signal, tabPtr.p, filePtr);
- filePtr.p->reqStatus = FileRecord::READING_TABLE;
- return;
-}//Dbdih::openingTableLab()
-
-void Dbdih::openingTableErrorLab(Signal* signal, FileRecordPtr filePtr)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- /* ---------------------------------------------------------------------- */
- /* 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. */
- /* ---------------------------------------------------------------------- */
- 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)
-{
- TabRecordPtr tabPtr;
- PageRecordPtr pagePtr;
- /* ---------------------------------------------------------------------- */
- /* WE HAVE SUCCESSFULLY READ A NUMBER OF PAGES IN THE TABLE FILE. IF */
- /* MORE PAGES EXIST IN THE FILE THEN READ ALL PAGES IN THE FILE. */
- /* ---------------------------------------------------------------------- */
- filePtr.p->reqStatus = FileRecord::IDLE;
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- pagePtr.i = tabPtr.p->pageRef[0];
- ptrCheckGuard(pagePtr, cpageFileSize, pageRecord);
- Uint32 noOfStoredPages = pagePtr.p->word[33];
- if (tabPtr.p->noPages < noOfStoredPages) {
- jam();
- ndbrequire(noOfStoredPages <= 8);
- for (Uint32 i = tabPtr.p->noPages; i < noOfStoredPages; i++) {
- jam();
- allocpage(pagePtr);
- tabPtr.p->pageRef[i] = pagePtr.i;
- }//for
- tabPtr.p->noPages = noOfStoredPages;
- readTabfile(signal, tabPtr.p, filePtr);
- filePtr.p->reqStatus = FileRecord::READING_TABLE;
- } else {
- ndbrequire(tabPtr.p->noPages == pagePtr.p->word[33]);
- ndbrequire(tabPtr.p->tabCopyStatus == TabRecord::CS_IDLE);
- jam();
- /* --------------------------------------------------------------------- */
- /* WE HAVE READ ALL PAGES. NOW READ FROM PAGES INTO TABLE AND FRAGMENT */
- /* DATA STRUCTURES. */
- /* --------------------------------------------------------------------- */
- tabPtr.p->tabCopyStatus = TabRecord::CS_SR_PHASE1_READ_PAGES;
- signal->theData[0] = DihContinueB::ZREAD_PAGES_INTO_TABLE;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- }//if
- return;
-}//Dbdih::readingTableLab()
-
-void Dbdih::readTableFromPagesLab(Signal* signal, TabRecordPtr tabPtr)
-{
- FileRecordPtr filePtr;
- filePtr.i = tabPtr.p->tabFile[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- /* ---------------------------------------------------------------------- */
- /* WE HAVE NOW COPIED TO OUR NODE. WE HAVE NOW COMPLETED RESTORING */
- /* THIS TABLE. CONTINUE WITH THE NEXT TABLE. */
- /* WE ALSO NEED TO CLOSE THE TABLE FILE. */
- /* ---------------------------------------------------------------------- */
- if (filePtr.p->fileStatus != FileRecord::OPEN) {
- jam();
- filePtr.i = tabPtr.p->tabFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- }//if
- closeFile(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::CLOSING_TABLE_SR;
- return;
-}//Dbdih::readTableFromPagesLab()
-
-void Dbdih::closingTableSrLab(Signal* signal, FileRecordPtr filePtr)
-{
- /**
- * Update table/fragment info
- */
- TabRecordPtr tabPtr;
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- resetReplicaSr(tabPtr);
-
- signal->theData[0] = DihContinueB::ZCOPY_TABLE;
- signal->theData[1] = filePtr.p->tabRef;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-
- return;
-}//Dbdih::closingTableSrLab()
-
-void
-Dbdih::resetReplicaSr(TabRecordPtr tabPtr){
-
- const Uint32 newestRestorableGCI = SYSFILE->newestRestorableGCI;
-
- for(Uint32 i = 0; i<tabPtr.p->totalfragments; i++){
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, i, fragPtr);
-
- /**
- * 1) Start by moving all replicas into oldStoredReplicas
- */
- prepareReplicas(fragPtr);
-
- /**
- * 2) Move all "alive" replicas into storedReplicas
- * + update noCrashedReplicas...
- */
- ReplicaRecordPtr replicaPtr;
- replicaPtr.i = fragPtr.p->oldStoredReplicas;
- while (replicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- const Uint32 nextReplicaPtrI = replicaPtr.p->nextReplica;
-
- NodeRecordPtr nodePtr;
- nodePtr.i = replicaPtr.p->procNode;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- const Uint32 noCrashedReplicas = replicaPtr.p->noCrashedReplicas;
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- case Sysfile::NS_ActiveMissed_2:{
- jam();
- /* --------------------------------------------------------------- */
- /* THE NODE IS ALIVE AND KICKING AND ACTIVE, LET'S USE IT. */
- /* --------------------------------------------------------------- */
- arrGuardErr(noCrashedReplicas, 8, NDBD_EXIT_MAX_CRASHED_REPLICAS);
- Uint32 lastGci = replicaPtr.p->replicaLastGci[noCrashedReplicas];
- if(lastGci >= newestRestorableGCI){
- jam();
- /** -------------------------------------------------------------
- * THE REPLICA WAS ALIVE AT THE SYSTEM FAILURE. WE WILL SET THE
- * LAST REPLICA GCI TO MINUS ONE SINCE IT HASN'T FAILED YET IN THE
- * NEW SYSTEM.
- *-------------------------------------------------------------- */
- replicaPtr.p->replicaLastGci[noCrashedReplicas] = (Uint32)-1;
- } else {
- jam();
- /*--------------------------------------------------------------
- * SINCE IT WAS NOT ALIVE AT THE TIME OF THE SYSTEM CRASH THIS IS
- * A COMPLETELY NEW REPLICA. WE WILL SET THE CREATE GCI TO BE THE
- * NEXT GCI TO BE EXECUTED.
- *--------_----------------------------------------------------- */
- const Uint32 nextCrashed = noCrashedReplicas + 1;
- replicaPtr.p->noCrashedReplicas = nextCrashed;
- arrGuardErr(nextCrashed, 8, NDBD_EXIT_MAX_CRASHED_REPLICAS);
- replicaPtr.p->createGci[nextCrashed] = newestRestorableGCI + 1;
- ndbrequire(newestRestorableGCI + 1 != 0xF1F1F1F1);
- replicaPtr.p->replicaLastGci[nextCrashed] = (Uint32)-1;
- }//if
-
- resetReplicaLcp(replicaPtr.p, newestRestorableGCI);
-
- /**
- * Make sure we can also find REDO for restoring replica...
- */
- {
- CreateReplicaRecord createReplica;
- ConstPtr<ReplicaRecord> constReplicaPtr;
- constReplicaPtr.i = replicaPtr.i;
- constReplicaPtr.p = replicaPtr.p;
- if (tabPtr.p->tabStorage != TabRecord::ST_NORMAL ||
- setup_create_replica(fragPtr,
- &createReplica, constReplicaPtr))
- {
- jam();
- removeOldStoredReplica(fragPtr, replicaPtr);
- linkStoredReplica(fragPtr, replicaPtr);
- }
- else
- {
- jam();
- infoEvent("Forcing take-over of node %d due to unsufficient REDO"
- " for table %d fragment: %d",
- nodePtr.i, tabPtr.i, i);
-
- setNodeActiveStatus(nodePtr.i,
- Sysfile::NS_NotActive_NotTakenOver);
- }
- }
- }
- default:
- jam();
- /*empty*/;
- break;
- }
- }
- replicaPtr.i = nextReplicaPtrI;
- }//while
- updateNodeInfo(fragPtr);
- }
-}
-
-void
-Dbdih::resetReplicaLcp(ReplicaRecord * replicaP, Uint32 stopGci){
-
- Uint32 lcpNo = replicaP->nextLcp;
- const Uint32 startLcpNo = lcpNo;
- do {
- lcpNo = prevLcpNo(lcpNo);
- ndbrequire(lcpNo < MAX_LCP_STORED);
- if (replicaP->lcpStatus[lcpNo] == ZVALID) {
- if (replicaP->maxGciStarted[lcpNo] < stopGci) {
- jam();
- /* ----------------------------------------------------------------- */
- /* WE HAVE FOUND A USEFUL LOCAL CHECKPOINT THAT CAN BE USED FOR */
- /* RESTARTING THIS FRAGMENT REPLICA. */
- /* ----------------------------------------------------------------- */
- return ;
- }//if
- }//if
-
- /**
- * WE COULD NOT USE THIS LOCAL CHECKPOINT. IT WAS TOO
- * RECENT OR SIMPLY NOT A VALID CHECKPOINT.
- * WE SHOULD THUS REMOVE THIS LOCAL CHECKPOINT SINCE IT WILL NEVER
- * AGAIN BE USED. SET LCP_STATUS TO INVALID.
- */
- replicaP->nextLcp = lcpNo;
- replicaP->lcpId[lcpNo] = 0;
- replicaP->lcpStatus[lcpNo] = ZINVALID;
- } while (lcpNo != startLcpNo);
-
- replicaP->nextLcp = 0;
-}
-
-void Dbdih::readingTableErrorLab(Signal* signal, FileRecordPtr filePtr)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- /* ---------------------------------------------------------------------- */
- /* READING THIS FILE FAILED. CLOSE IT AFTER RELEASING ALL PAGES. */
- /* ---------------------------------------------------------------------- */
- ndbrequire(tabPtr.p->noPages <= 8);
- for (Uint32 i = 0; i < tabPtr.p->noPages; i++) {
- jam();
- releasePage(tabPtr.p->pageRef[i]);
- }//for
- closeFile(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::CLOSING_TABLE_CRASH;
- return;
-}//Dbdih::readingTableErrorLab()
-
-void Dbdih::closingTableCrashLab(Signal* signal, FileRecordPtr filePtr)
-{
- TabRecordPtr tabPtr;
- /* ---------------------------------------------------------------------- */
- /* WE HAVE NOW CLOSED A FILE WHICH WE HAD A READ ERROR WITH. PROCEED */
- /* WITH NEXT FILE IF NOT THE LAST OTHERWISE REPORT ERROR. */
- /* ---------------------------------------------------------------------- */
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- 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;
-}//Dbdih::closingTableCrashLab()
-
-/*****************************************************************************/
-/* ********** COPY TABLE MODULE *************/
-/*****************************************************************************/
-void Dbdih::execCOPY_TABREQ(Signal* signal)
-{
- CRASH_INSERTION(7172);
-
- TabRecordPtr tabPtr;
- PageRecordPtr pagePtr;
- jamEntry();
- BlockReference ref = signal->theData[0];
- Uint32 reqinfo = signal->theData[1];
- tabPtr.i = signal->theData[2];
- Uint32 schemaVersion = signal->theData[3];
- Uint32 noOfWords = signal->theData[4];
- ndbrequire(ref == cmasterdihref);
- ndbrequire(!isMaster());
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if (reqinfo == 1) {
- jam();
- tabPtr.p->schemaVersion = schemaVersion;
- initTableFile(tabPtr);
- }//if
- ndbrequire(tabPtr.p->noPages < 8);
- if (tabPtr.p->noOfWords == 0) {
- jam();
- allocpage(pagePtr);
- tabPtr.p->pageRef[tabPtr.p->noPages] = pagePtr.i;
- tabPtr.p->noPages++;
- } else {
- jam();
- pagePtr.i = tabPtr.p->pageRef[tabPtr.p->noPages - 1];
- ptrCheckGuard(pagePtr, cpageFileSize, pageRecord);
- }//if
- ndbrequire(tabPtr.p->noOfWords + 15 < 2048);
- ndbrequire(tabPtr.p->noOfWords < 2048);
- MEMCOPY_NO_WORDS(&pagePtr.p->word[tabPtr.p->noOfWords], &signal->theData[5], 16);
- tabPtr.p->noOfWords += 16;
- if (tabPtr.p->noOfWords == 2048) {
- jam();
- tabPtr.p->noOfWords = 0;
- }//if
- if (noOfWords > 16) {
- jam();
- return;
- }//if
- tabPtr.p->noOfWords = 0;
- ndbrequire(tabPtr.p->tabCopyStatus == TabRecord::CS_IDLE);
- tabPtr.p->tabCopyStatus = TabRecord::CS_COPY_TAB_REQ;
- signal->theData[0] = DihContinueB::ZREAD_PAGES_INTO_TABLE;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}//Dbdih::execCOPY_TABREQ()
-
-void
-Dbdih::copyTabReq_complete(Signal* signal, TabRecordPtr tabPtr){
- if (!isMaster()) {
- jam();
- //----------------------------------------------------------------------------
- // In this particular case we do not release table pages if we are master. The
- // reason is that the master could still be sending the table info to another
- // node.
- //----------------------------------------------------------------------------
- releaseTabPages(tabPtr.i);
- tabPtr.p->tabStatus = TabRecord::TS_ACTIVE;
- for (Uint32 fragId = 0; fragId < tabPtr.p->totalfragments; fragId++) {
- jam();
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- updateNodeInfo(fragPtr);
- }//for
- }//if
- signal->theData[0] = cownNodeId;
- signal->theData[1] = tabPtr.i;
- sendSignal(cmasterdihref, GSN_COPY_TABCONF, signal, 2, JBB);
-}
-
-/*****************************************************************************/
-/* ****** READ FROM A NUMBER OF PAGES INTO THE TABLE DATA STRUCTURES ********/
-/*****************************************************************************/
-void Dbdih::readPagesIntoTableLab(Signal* signal, Uint32 tableId)
-{
- RWFragment rf;
- rf.wordIndex = 35;
- rf.pageIndex = 0;
- rf.rwfTabPtr.i = tableId;
- ptrCheckGuard(rf.rwfTabPtr, ctabFileSize, tabRecord);
- rf.rwfPageptr.i = rf.rwfTabPtr.p->pageRef[0];
- ptrCheckGuard(rf.rwfPageptr, cpageFileSize, pageRecord);
- rf.rwfTabPtr.p->totalfragments = readPageWord(&rf);
- rf.rwfTabPtr.p->noOfBackups = readPageWord(&rf);
- rf.rwfTabPtr.p->hashpointer = readPageWord(&rf);
- rf.rwfTabPtr.p->kvalue = readPageWord(&rf);
- rf.rwfTabPtr.p->mask = readPageWord(&rf);
- rf.rwfTabPtr.p->method = (TabRecord::Method)readPageWord(&rf);
- /* ------------- */
- /* Type of table */
- /* ------------- */
- rf.rwfTabPtr.p->tabStorage = (TabRecord::Storage)(readPageWord(&rf));
-
- Uint32 noOfFrags = rf.rwfTabPtr.p->totalfragments;
- ndbrequire(noOfFrags > 0);
- ndbrequire((noOfFrags * (rf.rwfTabPtr.p->noOfBackups + 1)) <= cnoFreeReplicaRec);
- allocFragments(noOfFrags, rf.rwfTabPtr);
-
- signal->theData[0] = DihContinueB::ZREAD_PAGES_INTO_FRAG;
- signal->theData[1] = rf.rwfTabPtr.i;
- signal->theData[2] = 0;
- signal->theData[3] = rf.pageIndex;
- signal->theData[4] = rf.wordIndex;
- sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
- return;
-}//Dbdih::readPagesIntoTableLab()
-
-void Dbdih::readPagesIntoFragLab(Signal* signal, RWFragment* rf)
-{
- ndbrequire(rf->pageIndex < 8);
- rf->rwfPageptr.i = rf->rwfTabPtr.p->pageRef[rf->pageIndex];
- ptrCheckGuard(rf->rwfPageptr, cpageFileSize, pageRecord);
- FragmentstorePtr fragPtr;
- getFragstore(rf->rwfTabPtr.p, rf->fragId, fragPtr);
- readFragment(rf, fragPtr);
- readReplicas(rf, fragPtr);
- rf->fragId++;
- if (rf->fragId == rf->rwfTabPtr.p->totalfragments) {
- jam();
- switch (rf->rwfTabPtr.p->tabCopyStatus) {
- case TabRecord::CS_SR_PHASE1_READ_PAGES:
- jam();
- releaseTabPages(rf->rwfTabPtr.i);
- rf->rwfTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- signal->theData[0] = DihContinueB::ZREAD_TABLE_FROM_PAGES;
- signal->theData[1] = rf->rwfTabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- case TabRecord::CS_COPY_TAB_REQ:
- jam();
- rf->rwfTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- if(getNodeState().getSystemRestartInProgress()){
- jam();
- copyTabReq_complete(signal, rf->rwfTabPtr);
- return;
- }
- rf->rwfTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- rf->rwfTabPtr.p->tabUpdateState = TabRecord::US_COPY_TAB_REQ;
- signal->theData[0] = DihContinueB::ZTABLE_UPDATE;
- signal->theData[1] = rf->rwfTabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- default:
- ndbrequire(false);
- return;
- break;
- }//switch
- } else {
- jam();
- signal->theData[0] = DihContinueB::ZREAD_PAGES_INTO_FRAG;
- signal->theData[1] = rf->rwfTabPtr.i;
- signal->theData[2] = rf->fragId;
- signal->theData[3] = rf->pageIndex;
- signal->theData[4] = rf->wordIndex;
- sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
- }//if
- return;
-}//Dbdih::readPagesIntoFragLab()
-
-/*****************************************************************************/
-/***** WRITING FROM TABLE DATA STRUCTURES INTO A SET OF PAGES ******/
-// execCONTINUEB(ZPACK_TABLE_INTO_PAGES)
-/*****************************************************************************/
-void Dbdih::packTableIntoPagesLab(Signal* signal, Uint32 tableId)
-{
- RWFragment wf;
- TabRecordPtr tabPtr;
- allocpage(wf.rwfPageptr);
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- tabPtr.p->pageRef[0] = wf.rwfPageptr.i;
- tabPtr.p->noPages = 1;
- wf.wordIndex = 35;
- wf.pageIndex = 0;
- writePageWord(&wf, tabPtr.p->totalfragments);
- writePageWord(&wf, tabPtr.p->noOfBackups);
- writePageWord(&wf, tabPtr.p->hashpointer);
- writePageWord(&wf, tabPtr.p->kvalue);
- writePageWord(&wf, tabPtr.p->mask);
- writePageWord(&wf, tabPtr.p->method);
- writePageWord(&wf, tabPtr.p->tabStorage);
-
- signal->theData[0] = DihContinueB::ZPACK_FRAG_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = 0;
- signal->theData[3] = wf.pageIndex;
- signal->theData[4] = wf.wordIndex;
- sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
-}//Dbdih::packTableIntoPagesLab()
-
-/*****************************************************************************/
-// execCONTINUEB(ZPACK_FRAG_INTO_PAGES)
-/*****************************************************************************/
-void Dbdih::packFragIntoPagesLab(Signal* signal, RWFragment* wf)
-{
- ndbrequire(wf->pageIndex < 8);
- wf->rwfPageptr.i = wf->rwfTabPtr.p->pageRef[wf->pageIndex];
- ptrCheckGuard(wf->rwfPageptr, cpageFileSize, pageRecord);
- FragmentstorePtr fragPtr;
- getFragstore(wf->rwfTabPtr.p, wf->fragId, fragPtr);
- writeFragment(wf, fragPtr);
- writeReplicas(wf, fragPtr.p->storedReplicas);
- writeReplicas(wf, fragPtr.p->oldStoredReplicas);
- wf->fragId++;
- if (wf->fragId == wf->rwfTabPtr.p->totalfragments) {
- jam();
- PageRecordPtr pagePtr;
- pagePtr.i = wf->rwfTabPtr.p->pageRef[0];
- ptrCheckGuard(pagePtr, cpageFileSize, pageRecord);
- pagePtr.p->word[33] = wf->rwfTabPtr.p->noPages;
- pagePtr.p->word[34] = ((wf->rwfTabPtr.p->noPages - 1) * 2048) + wf->wordIndex;
- switch (wf->rwfTabPtr.p->tabCopyStatus) {
- case TabRecord::CS_SR_PHASE2_READ_TABLE:
- /* -------------------------------------------------------------------*/
- // We are performing a system restart and we are now ready to copy the
- // table from this node (the master) to all other nodes.
- /* -------------------------------------------------------------------*/
- jam();
- wf->rwfTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- signal->theData[0] = DihContinueB::ZSR_PHASE2_READ_TABLE;
- signal->theData[1] = wf->rwfTabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- case TabRecord::CS_COPY_NODE_STATE:
- jam();
- tableCopyNodeLab(signal, wf->rwfTabPtr);
- return;
- break;
- case TabRecord::CS_LCP_READ_TABLE:
- jam();
- signal->theData[0] = DihContinueB::ZTABLE_UPDATE;
- signal->theData[1] = wf->rwfTabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- case TabRecord::CS_REMOVE_NODE:
- case TabRecord::CS_INVALIDATE_NODE_LCP:
- jam();
- signal->theData[0] = DihContinueB::ZTABLE_UPDATE;
- signal->theData[1] = wf->rwfTabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- case TabRecord::CS_ADD_TABLE_MASTER:
- jam();
- wf->rwfTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- signal->theData[0] = DihContinueB::ZADD_TABLE_MASTER_PAGES;
- signal->theData[1] = wf->rwfTabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- case TabRecord::CS_ADD_TABLE_SLAVE:
- jam();
- wf->rwfTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- signal->theData[0] = DihContinueB::ZADD_TABLE_SLAVE_PAGES;
- signal->theData[1] = wf->rwfTabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- default:
- ndbrequire(false);
- return;
- break;
- }//switch
- } else {
- jam();
- signal->theData[0] = DihContinueB::ZPACK_FRAG_INTO_PAGES;
- signal->theData[1] = wf->rwfTabPtr.i;
- signal->theData[2] = wf->fragId;
- signal->theData[3] = wf->pageIndex;
- signal->theData[4] = wf->wordIndex;
- sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
- }//if
- return;
-}//Dbdih::packFragIntoPagesLab()
-
-/*****************************************************************************/
-/* ********** START FRAGMENT MODULE *************/
-/*****************************************************************************/
-void
-Dbdih::dump_replica_info()
-{
- TabRecordPtr tabPtr;
- FragmentstorePtr fragPtr;
-
- for(tabPtr.i = 0; tabPtr.i < ctabFileSize; tabPtr.i++)
- {
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE)
- continue;
-
- for(Uint32 fid = 0; fid<tabPtr.p->totalfragments; fid++)
- {
- getFragstore(tabPtr.p, fid, fragPtr);
- ndbout_c("tab: %d frag: %d gci: %d\n -- storedReplicas:",
- tabPtr.i, fid, SYSFILE->newestRestorableGCI);
-
- Uint32 i;
- ReplicaRecordPtr replicaPtr;
- replicaPtr.i = fragPtr.p->storedReplicas;
- for(; replicaPtr.i != RNIL; replicaPtr.i = replicaPtr.p->nextReplica)
- {
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- ndbout_c(" node: %d initialGci: %d nextLcp: %d noCrashedReplicas: %d",
- replicaPtr.p->procNode,
- replicaPtr.p->initialGci,
- replicaPtr.p->nextLcp,
- replicaPtr.p->noCrashedReplicas);
- for(i = 0; i<MAX_LCP_STORED; i++)
- {
- ndbout_c(" i: %d %s : lcpId: %d maxGci Completed: %d Started: %d",
- i,
- (replicaPtr.p->lcpStatus[i] == ZVALID ?"VALID":"INVALID"),
- replicaPtr.p->lcpId[i],
- replicaPtr.p->maxGciCompleted[i],
- replicaPtr.p->maxGciStarted[i]);
- }
-
- for (i = 0; i < 8; i++)
- {
- ndbout_c(" crashed replica: %d replicaLastGci: %d createGci: %d",
- i,
- replicaPtr.p->replicaLastGci[i],
- replicaPtr.p->createGci[i]);
- }
- }
- ndbout_c(" -- oldStoredReplicas");
- replicaPtr.i = fragPtr.p->oldStoredReplicas;
- for(; replicaPtr.i != RNIL; replicaPtr.i = replicaPtr.p->nextReplica)
- {
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- for(i = 0; i<MAX_LCP_STORED; i++)
- {
- ndbout_c(" i: %d %s : lcpId: %d maxGci Completed: %d Started: %d",
- i,
- (replicaPtr.p->lcpStatus[i] == ZVALID ?"VALID":"INVALID"),
- replicaPtr.p->lcpId[i],
- replicaPtr.p->maxGciCompleted[i],
- replicaPtr.p->maxGciStarted[i]);
- }
-
- for (i = 0; i < 8; i++)
- {
- ndbout_c(" crashed replica: %d replicaLastGci: %d createGci: %d",
- i,
- replicaPtr.p->replicaLastGci[i],
- replicaPtr.p->createGci[i]);
- }
- }
- }
- }
-}
-
-void Dbdih::startFragment(Signal* signal, Uint32 tableId, Uint32 fragId)
-{
- Uint32 TloopCount = 0;
- TabRecordPtr tabPtr;
- while (true) {
- if (TloopCount > 100) {
- jam();
- signal->theData[0] = DihContinueB::ZSTART_FRAGMENT;
- signal->theData[1] = tableId;
- signal->theData[2] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
- }
-
- if (tableId >= ctabFileSize) {
- jam();
- signal->theData[0] = DihContinueB::ZCOMPLETE_RESTART;
- sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
- return;
- }//if
-
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE){
- jam();
- TloopCount++;
- tableId++;
- fragId = 0;
- continue;
- }
-
- if(tabPtr.p->tabStorage != TabRecord::ST_NORMAL){
- jam();
- TloopCount++;
- tableId++;
- fragId = 0;
- continue;
- }
-
- jam();
- break;
- }//while
-
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- /* ----------------------------------------------------------------------- */
- /* WE NEED TO RESET THE REPLICA DATA STRUCTURES. THIS MEANS THAT WE */
- /* MUST REMOVE REPLICAS THAT WAS NOT STARTED AT THE GCI TO RESTORE. WE */
- /* NEED TO PUT ALL STORED REPLICAS ON THE LIST OF OLD STORED REPLICAS */
- /* RESET THE NUMBER OF REPLICAS TO CREATE. */
- /* ----------------------------------------------------------------------- */
- cnoOfCreateReplicas = 0;
- /* ----------------------------------------------------------------------- */
- /* WE WILL NEVER START MORE THAN FOUR FRAGMENT REPLICAS WHATEVER THE */
- /* DESIRED REPLICATION IS. */
- /* ----------------------------------------------------------------------- */
- ndbrequire(tabPtr.p->noOfBackups < 4);
- /* ----------------------------------------------------------------------- */
- /* SEARCH FOR STORED REPLICAS THAT CAN BE USED TO RESTART THE SYSTEM. */
- /* ----------------------------------------------------------------------- */
- searchStoredReplicas(fragPtr);
-
- if (cnoOfCreateReplicas == 0) {
- /* --------------------------------------------------------------------- */
- /* THERE WERE NO STORED REPLICAS AVAILABLE THAT CAN SERVE AS REPLICA TO*/
- /* RESTART THE SYSTEM FROM. IN A LATER RELEASE WE WILL ADD */
- /* FUNCTIONALITY TO CHECK IF THERE ARE ANY STANDBY NODES THAT COULD DO */
- /* THIS TASK INSTEAD IN THIS IMPLEMENTATION WE SIMPLY CRASH THE SYSTEM.*/
- /* THIS WILL DECREASE THE GCI TO RESTORE WHICH HOPEFULLY WILL MAKE IT */
- /* POSSIBLE TO RESTORE THE SYSTEM. */
- /* --------------------------------------------------------------------- */
- char buf[64];
- BaseString::snprintf(buf, sizeof(buf), "table: %d fragment: %d gci: %d",
- tableId, fragId, SYSFILE->newestRestorableGCI);
-
- ndbout_c(buf);
- dump_replica_info();
-
- progError(__LINE__, NDBD_EXIT_NO_RESTORABLE_REPLICA, buf);
- ndbrequire(false);
- return;
- }//if
-
- /* ----------------------------------------------------------------------- */
- /* WE HAVE CHANGED THE NODE TO BE PRIMARY REPLICA AND THE NODES TO BE */
- /* BACKUP NODES. WE MUST UPDATE THIS NODES DATA STRUCTURE SINCE WE */
- /* WILL NOT COPY THE TABLE DATA TO OURSELF. */
- /* ----------------------------------------------------------------------- */
- updateNodeInfo(fragPtr);
- /* ----------------------------------------------------------------------- */
- /* NOW WE HAVE COLLECTED ALL THE REPLICAS WE COULD GET. WE WILL NOW */
- /* RESTART THE FRAGMENT REPLICAS WE HAVE FOUND IRRESPECTIVE OF IF THERE*/
- /* ARE ENOUGH ACCORDING TO THE DESIRED REPLICATION. */
- /* ----------------------------------------------------------------------- */
- /* WE START BY SENDING ADD_FRAGREQ FOR THOSE REPLICAS THAT NEED IT. */
- /* ----------------------------------------------------------------------- */
- CreateReplicaRecordPtr createReplicaPtr;
- for (createReplicaPtr.i = 0;
- createReplicaPtr.i < cnoOfCreateReplicas;
- createReplicaPtr.i++) {
- jam();
- ptrCheckGuard(createReplicaPtr, 4, createReplicaRecord);
- createReplicaPtr.p->hotSpareUse = false;
- }//for
-
- sendStartFragreq(signal, tabPtr, fragId);
-
- /**
- * Don't wait for START_FRAGCONF
- */
- fragId++;
- if (fragId >= tabPtr.p->totalfragments) {
- jam();
- tabPtr.i++;
- fragId = 0;
- }//if
- signal->theData[0] = DihContinueB::ZSTART_FRAGMENT;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragId;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-
- return;
-}//Dbdih::startFragmentLab()
-
-
-/*****************************************************************************/
-/* ********** COMPLETE RESTART MODULE *************/
-/*****************************************************************************/
-void Dbdih::completeRestartLab(Signal* signal)
-{
- sendLoopMacro(START_RECREQ, sendSTART_RECREQ);
-}//completeRestartLab()
-
-/* ------------------------------------------------------------------------- */
-// SYSTEM RESTART:
-/* A NODE HAS COMPLETED RESTORING ALL DATABASE FRAGMENTS. */
-// NODE RESTART:
-// THE STARTING NODE HAS PREPARED ITS LOG FILES TO ENABLE EXECUTION
-// OF TRANSACTIONS.
-// Precondition:
-// This signal must be received by the master node.
-/* ------------------------------------------------------------------------- */
-void Dbdih::execSTART_RECCONF(Signal* signal)
-{
- jamEntry();
- Uint32 senderNodeId = signal->theData[0];
- ndbrequire(isMaster());
- if (getNodeState().startLevel >= NodeState::SL_STARTED){
- /* --------------------------------------------------------------------- */
- // Since our node is already up and running this must be a node restart.
- // This means that we should be the master node,
- // otherwise we have a problem.
- /* --------------------------------------------------------------------- */
- jam();
- ndbout_c("startNextCopyFragment");
- startNextCopyFragment(signal, findTakeOver(senderNodeId));
- return;
- } else {
- /* --------------------------------------------------------------------- */
- // This was the system restart case. We set the state indicating that the
- // node has completed restoration of all fragments.
- /* --------------------------------------------------------------------- */
- receiveLoopMacro(START_RECREQ, senderNodeId);
-
- signal->theData[0] = reference();
- sendSignal(cntrlblockref, GSN_NDB_STARTCONF, signal, 1, JBB);
- return;
- }//if
-}//Dbdih::execSTART_RECCONF()
-
-void Dbdih::copyNodeLab(Signal* signal, Uint32 tableId)
-{
- /* ----------------------------------------------------------------------- */
- // This code is executed by the master to assist a node restart in receiving
- // the data in the master.
- /* ----------------------------------------------------------------------- */
- Uint32 TloopCount = 0;
-
- if (!c_nodeStartMaster.activeState) {
- jam();
- /* --------------------------------------------------------------------- */
- // Obviously the node crashed in the middle of its node restart. We will
- // stop this process simply by returning after resetting the wait indicator.
- /* ---------------------------------------------------------------------- */
- c_nodeStartMaster.wait = ZFALSE;
- return;
- }//if
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- while (tabPtr.i < ctabFileSize) {
- ptrAss(tabPtr, tabRecord);
- if (tabPtr.p->tabStatus == TabRecord::TS_ACTIVE) {
- /* -------------------------------------------------------------------- */
- // The table is defined. We will start by packing the table into pages.
- // The tabCopyStatus indicates to the CONTINUEB(ZPACK_TABLE_INTO_PAGES)
- // who called it. After packing the table into page(s) it will be sent to
- // the starting node by COPY_TABREQ signals. After returning from the
- // starting node we will return to this subroutine and continue
- // with the next table.
- /* -------------------------------------------------------------------- */
- ndbrequire(tabPtr.p->tabCopyStatus == TabRecord::CS_IDLE);
- tabPtr.p->tabCopyStatus = TabRecord::CS_COPY_NODE_STATE;
- signal->theData[0] = DihContinueB::ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- } else {
- jam();
- if (TloopCount > 100) {
- /* ------------------------------------------------------------------ */
- // Introduce real-time break after looping through 100 not copied tables
- /* ----------------------------------------------------------------- */
- jam();
- signal->theData[0] = DihContinueB::ZCOPY_NODE;
- signal->theData[1] = tabPtr.i + 1;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- } else {
- jam();
- TloopCount++;
- tabPtr.i++;
- }//if
- }//if
- }//while
- dihCopyCompletedLab(signal);
- return;
-}//Dbdih::copyNodeLab()
-
-void Dbdih::tableCopyNodeLab(Signal* signal, TabRecordPtr tabPtr)
-{
- /* ----------------------------------------------------------------------- */
- /* COPY PAGES READ TO STARTING NODE. */
- /* ----------------------------------------------------------------------- */
- if (!c_nodeStartMaster.activeState) {
- jam();
- releaseTabPages(tabPtr.i);
- c_nodeStartMaster.wait = ZFALSE;
- return;
- }//if
- NodeRecordPtr copyNodePtr;
- PageRecordPtr pagePtr;
- copyNodePtr.i = c_nodeStartMaster.startNode;
- ptrCheckGuard(copyNodePtr, MAX_NDB_NODES, nodeRecord);
-
- copyNodePtr.p->activeTabptr = tabPtr.i;
- pagePtr.i = tabPtr.p->pageRef[0];
- ptrCheckGuard(pagePtr, cpageFileSize, pageRecord);
-
- signal->theData[0] = DihContinueB::ZCOPY_TABLE_NODE;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = copyNodePtr.i;
- signal->theData[3] = 0;
- signal->theData[4] = 0;
- signal->theData[5] = pagePtr.p->word[34];
- sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
-}//Dbdih::tableCopyNodeLab()
-
-/* ------------------------------------------------------------------------- */
-// execCONTINUEB(ZCOPY_TABLE)
-// This routine is used to copy the table descriptions from the master to
-// other nodes. It is used in the system restart to copy from master to all
-// starting nodes.
-/* ------------------------------------------------------------------------- */
-void Dbdih::copyTableLab(Signal* signal, Uint32 tableId)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrAss(tabPtr, tabRecord);
-
- ndbrequire(tabPtr.p->tabCopyStatus == TabRecord::CS_IDLE);
- tabPtr.p->tabCopyStatus = TabRecord::CS_SR_PHASE2_READ_TABLE;
- signal->theData[0] = DihContinueB::ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dbdih::copyTableLab()
-
-/* ------------------------------------------------------------------------- */
-// execCONTINUEB(ZSR_PHASE2_READ_TABLE)
-/* ------------------------------------------------------------------------- */
-void Dbdih::srPhase2ReadTableLab(Signal* signal, TabRecordPtr tabPtr)
-{
- /* ----------------------------------------------------------------------- */
- // We set the sendCOPY_TABREQState to ZACTIVE for all nodes since it is a long
- // process to send off all table descriptions. Thus we ensure that we do
- // not encounter race conditions where one node is completed before the
- // sending process is completed. This could lead to that we start off the
- // system before we actually finished all copying of table descriptions
- // and could lead to strange errors.
- /* ----------------------------------------------------------------------- */
-
- //sendLoopMacro(COPY_TABREQ, nullRoutine);
-
- breakCopyTableLab(signal, tabPtr, cfirstAliveNode);
- return;
-}//Dbdih::srPhase2ReadTableLab()
-
-/* ------------------------------------------------------------------------- */
-/* COPY PAGES READ TO ALL NODES. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::breakCopyTableLab(Signal* signal, TabRecordPtr tabPtr, Uint32 nodeId)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- while (nodePtr.i != RNIL) {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.i == getOwnNodeId()){
- jam();
- /* ------------------------------------------------------------------- */
- /* NOT NECESSARY TO COPY TO MY OWN NODE. I ALREADY HAVE THE PAGES. */
- /* I DO HOWEVER NEED TO STORE THE TABLE DESCRIPTION ONTO DISK. */
- /* ------------------------------------------------------------------- */
- /* IF WE ARE MASTER WE ONLY NEED TO SAVE THE TABLE ON DISK. WE ALREADY */
- /* HAVE THE TABLE DESCRIPTION IN THE DATA STRUCTURES. */
- // AFTER COMPLETING THE WRITE TO DISK THE MASTER WILL ALSO SEND
- // COPY_TABCONF AS ALL THE OTHER NODES.
- /* ------------------------------------------------------------------- */
- c_COPY_TABREQ_Counter.setWaitingFor(nodePtr.i);
- tabPtr.p->tabUpdateState = TabRecord::US_COPY_TAB_REQ;
- signal->theData[0] = DihContinueB::ZTABLE_UPDATE;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- nodePtr.i = nodePtr.p->nextNode;
- } else {
- PageRecordPtr pagePtr;
- /* -------------------------------------------------------------------- */
- // RATHER THAN SENDING ALL COPY_TABREQ IN PARALLEL WE WILL SERIALISE THIS
- // ACTIVITY AND WILL THUS CALL breakCopyTableLab AGAIN WHEN COMPLETED THE
- // SENDING OF COPY_TABREQ'S.
- /* -------------------------------------------------------------------- */
- jam();
- tabPtr.p->tabCopyStatus = TabRecord::CS_SR_PHASE3_COPY_TABLE;
- pagePtr.i = tabPtr.p->pageRef[0];
- ptrCheckGuard(pagePtr, cpageFileSize, pageRecord);
- signal->theData[0] = DihContinueB::ZCOPY_TABLE_NODE;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = nodePtr.i;
- signal->theData[3] = 0;
- signal->theData[4] = 0;
- signal->theData[5] = pagePtr.p->word[34];
- sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
- return;
- }//if
- }//while
- /* ----------------------------------------------------------------------- */
- /* WE HAVE NOW SENT THE TABLE PAGES TO ALL NODES. EXIT AND WAIT FOR ALL */
- /* REPLIES. */
- /* ----------------------------------------------------------------------- */
- return;
-}//Dbdih::breakCopyTableLab()
-
-/* ------------------------------------------------------------------------- */
-// execCONTINUEB(ZCOPY_TABLE_NODE)
-/* ------------------------------------------------------------------------- */
-void Dbdih::copyTableNode(Signal* signal,
- CopyTableNode* ctn, NodeRecordPtr nodePtr)
-{
- if (getNodeState().startLevel >= NodeState::SL_STARTED){
- /* --------------------------------------------------------------------- */
- // We are in the process of performing a node restart and are copying a
- // table description to a starting node. We will check that no nodes have
- // crashed in this process.
- /* --------------------------------------------------------------------- */
- if (!c_nodeStartMaster.activeState) {
- jam();
- /** ------------------------------------------------------------------
- * The starting node crashed. We will release table pages and stop this
- * copy process and allow new node restarts to start.
- * ------------------------------------------------------------------ */
- releaseTabPages(ctn->ctnTabPtr.i);
- c_nodeStartMaster.wait = ZFALSE;
- return;
- }//if
- }//if
- ndbrequire(ctn->pageIndex < 8);
- ctn->ctnPageptr.i = ctn->ctnTabPtr.p->pageRef[ctn->pageIndex];
- ptrCheckGuard(ctn->ctnPageptr, cpageFileSize, pageRecord);
- /**
- * If first page & firstWord reqinfo = 1 (first signal)
- */
- Uint32 reqinfo = (ctn->pageIndex == 0) && (ctn->wordIndex == 0);
- if(reqinfo == 1){
- c_COPY_TABREQ_Counter.setWaitingFor(nodePtr.i);
- }
-
- for (Uint32 i = 0; i < 16; i++) {
- jam();
- sendCopyTable(signal, ctn, calcDihBlockRef(nodePtr.i), reqinfo);
- reqinfo = 0;
- if (ctn->noOfWords <= 16) {
- jam();
- switch (ctn->ctnTabPtr.p->tabCopyStatus) {
- case TabRecord::CS_SR_PHASE3_COPY_TABLE:
- /* ------------------------------------------------------------------ */
- // We have copied the table description to this node.
- // We will now proceed
- // with sending the table description to the next node in the node list.
- /* ------------------------------------------------------------------ */
- jam();
- ctn->ctnTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- breakCopyTableLab(signal, ctn->ctnTabPtr, nodePtr.p->nextNode);
- return;
- break;
- case TabRecord::CS_COPY_NODE_STATE:
- jam();
- ctn->ctnTabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- } else {
- jam();
- ctn->wordIndex += 16;
- if (ctn->wordIndex == 2048) {
- jam();
- ctn->wordIndex = 0;
- ctn->pageIndex++;
- ndbrequire(ctn->pageIndex < 8);
- ctn->ctnPageptr.i = ctn->ctnTabPtr.p->pageRef[ctn->pageIndex];
- ptrCheckGuard(ctn->ctnPageptr, cpageFileSize, pageRecord);
- }//if
- ctn->noOfWords -= 16;
- }//if
- }//for
- signal->theData[0] = DihContinueB::ZCOPY_TABLE_NODE;
- signal->theData[1] = ctn->ctnTabPtr.i;
- signal->theData[2] = nodePtr.i;
- signal->theData[3] = ctn->pageIndex;
- signal->theData[4] = ctn->wordIndex;
- signal->theData[5] = ctn->noOfWords;
- sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
-}//Dbdih::copyTableNodeLab()
-
-void Dbdih::sendCopyTable(Signal* signal, CopyTableNode* ctn,
- BlockReference ref, Uint32 reqinfo)
-{
- signal->theData[0] = reference();
- signal->theData[1] = reqinfo;
- signal->theData[2] = ctn->ctnTabPtr.i;
- signal->theData[3] = ctn->ctnTabPtr.p->schemaVersion;
- signal->theData[4] = ctn->noOfWords;
- ndbrequire(ctn->wordIndex + 15 < 2048);
- MEMCOPY_NO_WORDS(&signal->theData[5], &ctn->ctnPageptr.p->word[ctn->wordIndex], 16);
- sendSignal(ref, GSN_COPY_TABREQ, signal, 21, JBB);
-}//Dbdih::sendCopyTable()
-
-void Dbdih::execCOPY_TABCONF(Signal* signal)
-{
- NodeRecordPtr nodePtr;
- jamEntry();
- nodePtr.i = signal->theData[0];
- Uint32 tableId = signal->theData[1];
- if (getNodeState().startLevel >= NodeState::SL_STARTED){
- /* --------------------------------------------------------------------- */
- // We are in the process of performing a node restart. Continue by copying
- // the next table to the starting node.
- /* --------------------------------------------------------------------- */
- jam();
- NodeRecordPtr nodePtr;
- nodePtr.i = signal->theData[0];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- c_COPY_TABREQ_Counter.clearWaitingFor(nodePtr.i);
-
- releaseTabPages(tableId);
- signal->theData[0] = DihContinueB::ZCOPY_NODE;
- signal->theData[1] = tableId + 1;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- } else {
- /* --------------------------------------------------------------------- */
- // We are in the process of performing a system restart. Check if all nodes
- // have saved the new table description to file and then continue with the
- // next table.
- /* --------------------------------------------------------------------- */
- receiveLoopMacro(COPY_TABREQ, nodePtr.i);
- /* --------------------------------------------------------------------- */
- /* WE HAVE NOW COPIED TO ALL NODES. WE HAVE NOW COMPLETED RESTORING */
- /* THIS TABLE. CONTINUE WITH THE NEXT TABLE. */
- /* WE NEED TO RELEASE THE PAGES IN THE TABLE IN THIS NODE HERE. */
- /* WE ALSO NEED TO CLOSE THE TABLE FILE. */
- /* --------------------------------------------------------------------- */
- releaseTabPages(tableId);
-
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- ConnectRecordPtr connectPtr;
- connectPtr.i = tabPtr.p->connectrec;
- ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
-
- sendAddFragreq(signal, connectPtr, tabPtr, 0);
- return;
- }//if
-}//Dbdih::execCOPY_TABCONF()
-
-/*
- 3.13 L O C A L C H E C K P O I N T (M A S T E R)
- ****************************************************
- */
-/*****************************************************************************/
-/* ********** LOCAL-CHECK-POINT-HANDLING MODULE *************/
-/*****************************************************************************/
-/* ------------------------------------------------------------------------- */
-/* IT IS TIME TO CHECK IF IT IS TIME TO START A LOCAL CHECKPOINT. */
-/* WE WILL EITHER START AFTER 1 MILLION WORDS HAVE ARRIVED OR WE WILL */
-/* EXECUTE AFTER ABOUT 16 MINUTES HAVE PASSED BY. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::checkTcCounterLab(Signal* signal)
-{
- CRASH_INSERTION(7009);
- if (c_lcpState.lcpStatus != LCP_STATUS_IDLE) {
- g_eventLogger.error("lcpStatus = %u"
- "lcpStatusUpdatedPlace = %d",
- (Uint32) c_lcpState.lcpStatus,
- c_lcpState.lcpStatusUpdatedPlace);
- ndbrequire(false);
- return;
- }//if
- c_lcpState.ctimer += 32;
- if ((c_nodeStartMaster.blockLcp == true) ||
- (c_lcpState.lcpStopGcp >= c_newest_restorable_gci)) {
- jam();
- /* --------------------------------------------------------------------- */
- // No reason to start juggling the states and checking for start of LCP if
- // we are blocked to start an LCP anyway.
- // We also block LCP start if we have not completed one global checkpoints
- // before starting another local checkpoint.
- /* --------------------------------------------------------------------- */
- signal->theData[0] = DihContinueB::ZCHECK_TC_COUNTER;
- signal->theData[1] = __LINE__;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1 * 100, 2);
- return;
- }//if
- c_lcpState.setLcpStatus(LCP_TCGET, __LINE__);
-
- c_lcpState.ctcCounter = c_lcpState.ctimer;
- sendLoopMacro(TCGETOPSIZEREQ, sendTCGETOPSIZEREQ);
-}//Dbdih::checkTcCounterLab()
-
-void Dbdih::checkLcpStart(Signal* signal, Uint32 lineNo)
-{
- /* ----------------------------------------------------------------------- */
- // Verify that we are not attempting to start another instance of the LCP
- // when it is not alright to do so.
- /* ----------------------------------------------------------------------- */
- ndbrequire(c_lcpState.lcpStart == ZIDLE);
- c_lcpState.lcpStart = ZACTIVE;
- signal->theData[0] = DihContinueB::ZCHECK_TC_COUNTER;
- signal->theData[1] = lineNo;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 2);
-}//Dbdih::checkLcpStart()
-
-/* ------------------------------------------------------------------------- */
-/*TCGETOPSIZECONF HOW MUCH OPERATION SIZE HAVE BEEN EXECUTED BY TC */
-/* ------------------------------------------------------------------------- */
-void Dbdih::execTCGETOPSIZECONF(Signal* signal)
-{
- jamEntry();
- Uint32 senderNodeId = signal->theData[0];
- c_lcpState.ctcCounter += signal->theData[1];
-
- receiveLoopMacro(TCGETOPSIZEREQ, senderNodeId);
-
- ndbrequire(c_lcpState.lcpStatus == LCP_TCGET);
- ndbrequire(c_lcpState.lcpStart == ZACTIVE);
- /* ----------------------------------------------------------------------- */
- // We are not actively starting another LCP, still we receive this signal.
- // This is not ok.
- /* ---------------------------------------------------------------------- */
- /* ALL TC'S HAVE RESPONDED NOW. NOW WE WILL CHECK IF ENOUGH OPERATIONS */
- /* HAVE EXECUTED TO ENABLE US TO START A NEW LOCAL CHECKPOINT. */
- /* WHILE COPYING DICTIONARY AND DISTRIBUTION INFO TO A STARTING NODE */
- /* WE WILL ALSO NOT ALLOW THE LOCAL CHECKPOINT TO PROCEED. */
- /*----------------------------------------------------------------------- */
- if (c_lcpState.immediateLcpStart == false) {
- if ((c_lcpState.ctcCounter <
- ((Uint32)1 << c_lcpState.clcpDelay)) ||
- (c_nodeStartMaster.blockLcp == true)) {
- jam();
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
-
- signal->theData[0] = DihContinueB::ZCHECK_TC_COUNTER;
- signal->theData[1] = __LINE__;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1 * 100, 2);
- return;
- }//if
- }//if
- c_lcpState.lcpStart = ZIDLE;
- c_lcpState.immediateLcpStart = false;
- /* -----------------------------------------------------------------------
- * Now the initial lcp is started,
- * we can reset the delay to its orginal value
- * --------------------------------------------------------------------- */
- CRASH_INSERTION(7010);
- /* ----------------------------------------------------------------------- */
- /* IF MORE THAN 1 MILLION WORDS PASSED THROUGH THE TC'S THEN WE WILL */
- /* START A NEW LOCAL CHECKPOINT. CLEAR CTIMER. START CHECKPOINT */
- /* ACTIVITY BY CALCULATING THE KEEP GLOBAL CHECKPOINT. */
- // Also remember the current global checkpoint to ensure that we run at least
- // one global checkpoints between each local checkpoint that we start up.
- /* ----------------------------------------------------------------------- */
- c_lcpState.ctimer = 0;
- c_lcpState.keepGci = coldgcp;
- /* ----------------------------------------------------------------------- */
- /* UPDATE THE NEW LATEST LOCAL CHECKPOINT ID. */
- /* ----------------------------------------------------------------------- */
- cnoOfActiveTables = 0;
- c_lcpState.setLcpStatus(LCP_CALCULATE_KEEP_GCI, __LINE__);
- c_lcpState.oldestRestorableGci = SYSFILE->oldestRestorableGCI;
- ndbrequire(((int)c_lcpState.oldestRestorableGci) > 0);
-
- if (ERROR_INSERTED(7011)) {
- signal->theData[0] = NDB_LE_LCPStoppedInCalcKeepGci;
- signal->theData[1] = 0;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- return;
- }//if
- signal->theData[0] = DihContinueB::ZCALCULATE_KEEP_GCI;
- signal->theData[1] = 0; /* TABLE ID = 0 */
- signal->theData[2] = 0; /* FRAGMENT ID = 0 */
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
-}//Dbdih::execTCGETOPSIZECONF()
-
-/* ------------------------------------------------------------------------- */
-/* WE NEED TO CALCULATE THE OLDEST GLOBAL CHECKPOINT THAT WILL BE */
-/* COMPLETELY RESTORABLE AFTER EXECUTING THIS LOCAL CHECKPOINT. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::calculateKeepGciLab(Signal* signal, Uint32 tableId, Uint32 fragId)
-{
- TabRecordPtr tabPtr;
- Uint32 TloopCount = 1;
- tabPtr.i = tableId;
- do {
- if (tabPtr.i >= ctabFileSize) {
- if (cnoOfActiveTables > 0) {
- jam();
- signal->theData[0] = DihContinueB::ZSTORE_NEW_LCP_ID;
- sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
- return;
- } else {
- jam();
- /* ------------------------------------------------------------------ */
- /* THERE ARE NO TABLES TO CHECKPOINT. WE STOP THE CHECKPOINT ALREADY */
- /* HERE TO AVOID STRANGE PROBLEMS LATER. */
- /* ------------------------------------------------------------------ */
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
- checkLcpStart(signal, __LINE__);
- return;
- }//if
- }//if
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE ||
- tabPtr.p->tabStorage != TabRecord::ST_NORMAL) {
- if (TloopCount > 100) {
- jam();
- signal->theData[0] = DihContinueB::ZCALCULATE_KEEP_GCI;
- signal->theData[1] = tabPtr.i + 1;
- signal->theData[2] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
- } else {
- jam();
- TloopCount++;
- tabPtr.i++;
- }//if
- } else {
- jam();
- TloopCount = 0;
- }//if
- } while (TloopCount != 0);
- cnoOfActiveTables++;
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- checkKeepGci(tabPtr, fragId, fragPtr.p, fragPtr.p->storedReplicas);
- checkKeepGci(tabPtr, fragId, fragPtr.p, fragPtr.p->oldStoredReplicas);
- fragId++;
- if (fragId >= tabPtr.p->totalfragments) {
- jam();
- tabPtr.i++;
- fragId = 0;
- }//if
- signal->theData[0] = DihContinueB::ZCALCULATE_KEEP_GCI;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragId;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
-}//Dbdih::calculateKeepGciLab()
-
-/* ------------------------------------------------------------------------- */
-/* WE NEED TO STORE ON DISK THE FACT THAT WE ARE STARTING THIS LOCAL */
-/* CHECKPOINT ROUND. THIS WILL INVALIDATE ALL THE LOCAL CHECKPOINTS */
-/* THAT WILL EVENTUALLY BE OVERWRITTEN AS PART OF THIS LOCAL CHECKPOINT*/
-/* ------------------------------------------------------------------------- */
-void Dbdih::storeNewLcpIdLab(Signal* signal)
-{
- /***************************************************************************/
- // Report the event that a local checkpoint has started.
- /***************************************************************************/
- 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;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
-
- signal->setTrace(TestOrd::TraceLocalCheckpoint);
-
- CRASH_INSERTION(7013);
- SYSFILE->keepGCI = c_lcpState.keepGci;
- //Uint32 lcpId = SYSFILE->latestLCP_ID;
- SYSFILE->latestLCP_ID++;
- SYSFILE->oldestRestorableGCI = c_lcpState.oldestRestorableGci;
-
- const Uint32 oldestRestorableGCI = SYSFILE->oldestRestorableGCI;
- //const Uint32 newestRestorableGCI = SYSFILE->newestRestorableGCI;
- //ndbrequire(newestRestorableGCI >= oldestRestorableGCI);
-
- Int32 val = oldestRestorableGCI;
- ndbrequire(val > 0);
-
- /* ----------------------------------------------------------------------- */
- /* SET BIT INDICATING THAT LOCAL CHECKPOINT IS ONGOING. THIS IS CLEARED */
- /* AT THE END OF A LOCAL CHECKPOINT. */
- /* ----------------------------------------------------------------------- */
- SYSFILE->setLCPOngoing(SYSFILE->systemRestartBits);
- /* ---------------------------------------------------------------------- */
- /* CHECK IF ANY NODE MUST BE TAKEN OUT OF SERVICE AND REFILLED WITH */
- /* NEW FRESH DATA FROM AN ACTIVE NODE. */
- /* ---------------------------------------------------------------------- */
- setLcpActiveStatusStart(signal);
- c_lcpState.setLcpStatus(LCP_COPY_GCI, __LINE__);
- //#ifdef VM_TRACE
- // infoEvent("LocalCheckpoint %d started", SYSFILE->latestLCP_ID);
- // signal->theData[0] = 7012;
- // execDUMP_STATE_ORD(signal);
- //#endif
-
- copyGciLab(signal, CopyGCIReq::LOCAL_CHECKPOINT);
-}//Dbdih::storeNewLcpIdLab()
-
-void Dbdih::startLcpRoundLab(Signal* signal) {
- jam();
-
- Mutex mutex(signal, c_mutexMgr, c_startLcpMutexHandle);
- Callback c = { safe_cast(&Dbdih::startLcpMutex_locked), 0 };
- ndbrequire(mutex.lock(c));
-}
-
-void
-Dbdih::startLcpMutex_locked(Signal* signal, Uint32 senderData, Uint32 retVal){
- jamEntry();
- ndbrequire(retVal == 0);
-
- StartLcpReq* req = (StartLcpReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->lcpId = SYSFILE->latestLCP_ID;
- req->participatingLQH = c_lcpState.m_participatingLQH;
- req->participatingDIH = c_lcpState.m_participatingDIH;
- sendLoopMacro(START_LCP_REQ, sendSTART_LCP_REQ);
-}
-void
-Dbdih::sendSTART_LCP_REQ(Signal* signal, Uint32 nodeId){
- BlockReference ref = calcDihBlockRef(nodeId);
- sendSignal(ref, GSN_START_LCP_REQ, signal, StartLcpReq::SignalLength, JBB);
-}
-
-void
-Dbdih::execSTART_LCP_CONF(Signal* signal){
- StartLcpConf * conf = (StartLcpConf*)signal->getDataPtr();
-
- Uint32 nodeId = refToNode(conf->senderRef);
- receiveLoopMacro(START_LCP_REQ, nodeId);
-
- Mutex mutex(signal, c_mutexMgr, c_startLcpMutexHandle);
- Callback c = { safe_cast(&Dbdih::startLcpMutex_unlocked), 0 };
- mutex.unlock(c);
-}
-
-void
-Dbdih::startLcpMutex_unlocked(Signal* signal, Uint32 data, Uint32 retVal){
- jamEntry();
- ndbrequire(retVal == 0);
-
- Mutex mutex(signal, c_mutexMgr, c_startLcpMutexHandle);
- mutex.release();
-
- CRASH_INSERTION(7014);
- c_lcpState.setLcpStatus(LCP_TC_CLOPSIZE, __LINE__);
- sendLoopMacro(TC_CLOPSIZEREQ, sendTC_CLOPSIZEREQ);
-}
-
-void Dbdih::execTC_CLOPSIZECONF(Signal* signal) {
- jamEntry();
- Uint32 senderNodeId = signal->theData[0];
- receiveLoopMacro(TC_CLOPSIZEREQ, senderNodeId);
-
- ndbrequire(c_lcpState.lcpStatus == LCP_TC_CLOPSIZE);
- /* ----------------------------------------------------------------------- */
- /* ALL TC'S HAVE CLEARED THEIR OPERATION SIZE COUNTERS. NOW PROCEED BY */
- /* STARTING THE LOCAL CHECKPOINT IN EACH LQH. */
- /* ----------------------------------------------------------------------- */
- c_lcpState.m_LAST_LCP_FRAG_ORD = c_lcpState.m_participatingLQH;
-
- CRASH_INSERTION(7015);
- c_lcpState.setLcpStatus(LCP_START_LCP_ROUND, __LINE__);
- startLcpRoundLoopLab(signal, 0, 0);
-}//Dbdih::execTC_CLOPSIZECONF()
-
-void Dbdih::startLcpRoundLoopLab(Signal* signal,
- Uint32 startTableId, Uint32 startFragId)
-{
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRecord);
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- ndbrequire(nodePtr.p->noOfStartedChkpt == 0);
- ndbrequire(nodePtr.p->noOfQueuedChkpt == 0);
- }//if
- }//if
- c_lcpState.currentFragment.tableId = startTableId;
- c_lcpState.currentFragment.fragmentId = startFragId;
- startNextChkpt(signal);
-}//Dbdih::startLcpRoundLoopLab()
-
-void Dbdih::startNextChkpt(Signal* signal)
-{
- Uint32 lcpId = SYSFILE->latestLCP_ID;
-
- NdbNodeBitmask busyNodes;
- busyNodes.clear();
- const Uint32 lcpNodes = c_lcpState.m_participatingLQH.count();
-
- bool save = true;
- LcpState::CurrentFragment curr = c_lcpState.currentFragment;
-
- while (curr.tableId < ctabFileSize) {
- TabRecordPtr tabPtr;
- tabPtr.i = curr.tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if ((tabPtr.p->tabStatus != TabRecord::TS_ACTIVE) ||
- (tabPtr.p->tabLcpStatus != TabRecord::TLS_ACTIVE)) {
- curr.tableId++;
- curr.fragmentId = 0;
- continue;
- }//if
-
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, curr.fragmentId, fragPtr);
-
- ReplicaRecordPtr replicaPtr;
- for(replicaPtr.i = fragPtr.p->storedReplicas;
- replicaPtr.i != RNIL ;
- replicaPtr.i = replicaPtr.p->nextReplica){
-
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
-
- NodeRecordPtr nodePtr;
- nodePtr.i = replicaPtr.p->procNode;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- if (c_lcpState.m_participatingLQH.get(nodePtr.i))
- {
- if (replicaPtr.p->lcpOngoingFlag &&
- replicaPtr.p->lcpIdStarted < lcpId)
- {
- jam();
- //-------------------------------------------------------------------
- // We have found a replica on a node that performs local checkpoint
- // that is alive and that have not yet been started.
- //-------------------------------------------------------------------
-
- if (nodePtr.p->noOfStartedChkpt < 2)
- {
- jam();
- /**
- * Send LCP_FRAG_ORD to LQH
- */
-
- /**
- * Mark the replica so with lcpIdStarted == true
- */
- replicaPtr.p->lcpIdStarted = lcpId;
-
- Uint32 i = nodePtr.p->noOfStartedChkpt;
- nodePtr.p->startedChkpt[i].tableId = tabPtr.i;
- nodePtr.p->startedChkpt[i].fragId = curr.fragmentId;
- nodePtr.p->startedChkpt[i].replicaPtr = replicaPtr.i;
- nodePtr.p->noOfStartedChkpt = i + 1;
-
- sendLCP_FRAG_ORD(signal, nodePtr.p->startedChkpt[i]);
- }
- else if (nodePtr.p->noOfQueuedChkpt < 2)
- {
- jam();
- /**
- * Put LCP_FRAG_ORD "in queue"
- */
-
- /**
- * Mark the replica so with lcpIdStarted == true
- */
- replicaPtr.p->lcpIdStarted = lcpId;
-
- Uint32 i = nodePtr.p->noOfQueuedChkpt;
- nodePtr.p->queuedChkpt[i].tableId = tabPtr.i;
- nodePtr.p->queuedChkpt[i].fragId = curr.fragmentId;
- nodePtr.p->queuedChkpt[i].replicaPtr = replicaPtr.i;
- nodePtr.p->noOfQueuedChkpt = i + 1;
- }
- else
- {
- jam();
-
- if(save)
- {
- /**
- * Stop increasing value on first that was "full"
- */
- c_lcpState.currentFragment = curr;
- save = false;
- }
-
- busyNodes.set(nodePtr.i);
- if(busyNodes.count() == lcpNodes)
- {
- /**
- * There were no possibility to start the local checkpoint
- * and it was not possible to queue it up. In this case we
- * stop the start of local checkpoints until the nodes with a
- * backlog have performed more checkpoints. We will return and
- * will not continue the process of starting any more checkpoints.
- */
- return;
- }//if
- }//if
- }
- }//while
- }
- curr.fragmentId++;
- if (curr.fragmentId >= tabPtr.p->totalfragments) {
- jam();
- curr.fragmentId = 0;
- curr.tableId++;
- }//if
- }//while
-
- sendLastLCP_FRAG_ORD(signal);
-}//Dbdih::startNextChkpt()
-
-void Dbdih::sendLastLCP_FRAG_ORD(Signal* signal)
-{
- LcpFragOrd * const lcpFragOrd = (LcpFragOrd *)&signal->theData[0];
- lcpFragOrd->tableId = RNIL;
- lcpFragOrd->fragmentId = 0;
- lcpFragOrd->lcpId = SYSFILE->latestLCP_ID;
- lcpFragOrd->lcpNo = 0;
- lcpFragOrd->keepGci = c_lcpState.keepGci;
- lcpFragOrd->lastFragmentFlag = true;
-
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
-
- if(nodePtr.p->noOfQueuedChkpt == 0 &&
- nodePtr.p->noOfStartedChkpt == 0 &&
- c_lcpState.m_LAST_LCP_FRAG_ORD.isWaitingFor(nodePtr.i)){
- jam();
-
- CRASH_INSERTION(7028);
-
- /**
- * Nothing queued or started <=> Complete on that node
- *
- */
- c_lcpState.m_LAST_LCP_FRAG_ORD.clearWaitingFor(nodePtr.i);
- if(ERROR_INSERTED(7075)){
- continue;
- }
-
- CRASH_INSERTION(7193);
- BlockReference ref = calcLqhBlockRef(nodePtr.i);
- sendSignal(ref, GSN_LCP_FRAG_ORD, signal,LcpFragOrd::SignalLength, JBB);
- }
- }
- if(ERROR_INSERTED(7075)){
- if(c_lcpState.m_LAST_LCP_FRAG_ORD.done())
- CRASH_INSERTION(7075);
- }
-}//Dbdih::sendLastLCP_FRAGORD()
-
-/* ------------------------------------------------------------------------- */
-/* A FRAGMENT REPLICA HAS COMPLETED EXECUTING ITS LOCAL CHECKPOINT. */
-/* CHECK IF ALL REPLICAS IN THE TABLE HAVE COMPLETED. IF SO STORE THE */
-/* THE TABLE DISTRIBUTION ON DISK. ALSO SEND LCP_REPORT TO ALL OTHER */
-/* NODES SO THAT THEY CAN STORE THE TABLE ONTO DISK AS WELL. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::execLCP_FRAG_REP(Signal* signal)
-{
- jamEntry();
- ndbrequire(c_lcpState.lcpStatus != LCP_STATUS_IDLE);
-
-#if 0
- printLCP_FRAG_REP(stdout,
- signal->getDataPtr(),
- signal->length(), number());
-#endif
-
- LcpFragRep * const lcpReport = (LcpFragRep *)&signal->theData[0];
- Uint32 nodeId = lcpReport->nodeId;
- Uint32 tableId = lcpReport->tableId;
- Uint32 fragId = lcpReport->fragId;
-
- jamEntry();
-
- if (ERROR_INSERTED(7178) && nodeId != getOwnNodeId())
- {
- jam();
- Uint32 owng =Sysfile::getNodeGroup(getOwnNodeId(), SYSFILE->nodeGroups);
- Uint32 nodeg = Sysfile::getNodeGroup(nodeId, SYSFILE->nodeGroups);
- if (owng == nodeg)
- {
- jam();
- ndbout_c("throwing away LCP_FRAG_REP from (and killing) %d", nodeId);
- SET_ERROR_INSERT_VALUE(7179);
- signal->theData[0] = 9999;
- sendSignal(numberToRef(CMVMI, nodeId),
- GSN_NDB_TAMPER, signal, 1, JBA);
- return;
- }
- }
-
- if (ERROR_INSERTED(7179) && nodeId != getOwnNodeId())
- {
- jam();
- Uint32 owng =Sysfile::getNodeGroup(getOwnNodeId(), SYSFILE->nodeGroups);
- Uint32 nodeg = Sysfile::getNodeGroup(nodeId, SYSFILE->nodeGroups);
- if (owng == nodeg)
- {
- jam();
- ndbout_c("throwing away LCP_FRAG_REP from %d", nodeId);
- return;
- }
- }
-
- CRASH_INSERTION2(7025, isMaster());
- CRASH_INSERTION2(7016, !isMaster());
-
- bool fromTimeQueue = (signal->senderBlockRef() == reference());
-
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if(tabPtr.p->tabCopyStatus != TabRecord::CS_IDLE) {
- jam();
- /*-----------------------------------------------------------------------*/
- // If the table is currently copied to disk we also
- // stop already here to avoid strange half-way updates
- // of the table data structures.
- /*-----------------------------------------------------------------------*/
- /*
- We need to send this signal without a delay since we have discovered
- that we have run out of space in the short time queue. This problem
- is very erunlikely to happen but it has and it results in a node crash.
- This should be considered a "quick fix" and not a permanent solution.
- A cleaner/better way would be to check the time queue if it is full or
- not before sending this signal.
- */
- sendSignal(reference(), GSN_LCP_FRAG_REP, signal, signal->length(), JBB);
- /* Kept here for reference
- sendSignalWithDelay(reference(), GSN_LCP_FRAG_REP,
- signal, 20, signal->length());
- */
-
- if(!fromTimeQueue){
- c_lcpState.noOfLcpFragRepOutstanding++;
- }
-
- return;
- }//if
-
- if(fromTimeQueue){
- jam();
-
- ndbrequire(c_lcpState.noOfLcpFragRepOutstanding > 0);
- c_lcpState.noOfLcpFragRepOutstanding--;
- }
-
- bool tableDone = reportLcpCompletion(lcpReport);
-
- Uint32 started = lcpReport->maxGciStarted;
- Uint32 completed = lcpReport->maxGciCompleted;
-
- if (started > c_lcpState.lcpStopGcp)
- {
- jam();
- c_lcpState.lcpStopGcp = started;
- }
-
- if(tableDone){
- jam();
-
- if(tabPtr.p->tabStatus == TabRecord::TS_DROPPING){
- jam();
- g_eventLogger.info("TS_DROPPING - Neglecting to save Table: %d Frag: %d - ",
- tableId, fragId);
- } else {
- jam();
- /**
- * Write table description to file
- */
- tabPtr.p->tabLcpStatus = TabRecord::TLS_WRITING_TO_FILE;
- tabPtr.p->tabCopyStatus = TabRecord::CS_LCP_READ_TABLE;
- tabPtr.p->tabUpdateState = TabRecord::US_LOCAL_CHECKPOINT;
- signal->theData[0] = DihContinueB::ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-
- checkLcpAllTablesDoneInLqh();
- }
- }
-
-#ifdef VM_TRACE
- /* --------------------------------------------------------------------- */
- // REPORT that local checkpoint have completed this fragment.
- /* --------------------------------------------------------------------- */
- signal->theData[0] = NDB_LE_LCPFragmentCompleted;
- signal->theData[1] = nodeId;
- signal->theData[2] = tableId;
- signal->theData[3] = fragId;
- signal->theData[4] = started;
- signal->theData[5] = completed;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB);
-#endif
-
- bool ok = false;
- switch(c_lcpMasterTakeOverState.state){
- case LMTOS_IDLE:
- ok = true;
- jam();
- /**
- * Fall through
- */
- break;
- case LMTOS_WAIT_EMPTY_LCP: // LCP Take over waiting for EMPTY_LCPCONF
- jam();
- return;
- case LMTOS_WAIT_LCP_FRAG_REP:
- jam();
- checkEmptyLcpComplete(signal);
- return;
- case LMTOS_INITIAL:
- case LMTOS_ALL_IDLE:
- case LMTOS_ALL_ACTIVE:
- case LMTOS_LCP_CONCLUDING:
- case LMTOS_COPY_ONGOING:
- ndbrequire(false);
- }
- ndbrequire(ok);
-
- /* ----------------------------------------------------------------------- */
- // Check if there are more LCP's to start up.
- /* ----------------------------------------------------------------------- */
- if(isMaster()){
- jam();
-
- /**
- * Remove from "running" array
- */
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- const Uint32 outstanding = nodePtr.p->noOfStartedChkpt;
- ndbrequire(outstanding > 0);
- if(nodePtr.p->startedChkpt[0].tableId != tableId ||
- nodePtr.p->startedChkpt[0].fragId != fragId){
- jam();
- ndbrequire(outstanding > 1);
- ndbrequire(nodePtr.p->startedChkpt[1].tableId == tableId);
- ndbrequire(nodePtr.p->startedChkpt[1].fragId == fragId);
- } else {
- jam();
- nodePtr.p->startedChkpt[0] = nodePtr.p->startedChkpt[1];
- }
- nodePtr.p->noOfStartedChkpt--;
- checkStartMoreLcp(signal, nodeId);
- }
-}
-
-bool
-Dbdih::checkLcpAllTablesDoneInLqh(){
- TabRecordPtr tabPtr;
-
- /**
- * Check if finished with all tables
- */
- for (tabPtr.i = 0; tabPtr.i < ctabFileSize; tabPtr.i++) {
- jam();
- ptrAss(tabPtr, tabRecord);
- if ((tabPtr.p->tabStatus == TabRecord::TS_ACTIVE) &&
- (tabPtr.p->tabLcpStatus == TabRecord::TLS_ACTIVE)) {
- jam();
- /**
- * Nope, not finished with all tables
- */
- return false;
- }//if
- }//for
-
- CRASH_INSERTION2(7026, isMaster());
- CRASH_INSERTION2(7017, !isMaster());
-
- c_lcpState.setLcpStatus(LCP_TAB_COMPLETED, __LINE__);
-
- if (ERROR_INSERTED(7194))
- {
- ndbout_c("CLEARING 7194");
- CLEAR_ERROR_INSERT_VALUE;
- }
-
- return true;
-}
-
-void Dbdih::findReplica(ReplicaRecordPtr& replicaPtr,
- Fragmentstore* fragPtrP,
- Uint32 nodeId,
- bool old)
-{
- replicaPtr.i = old ? fragPtrP->oldStoredReplicas : fragPtrP->storedReplicas;
- while(replicaPtr.i != RNIL){
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if (replicaPtr.p->procNode == nodeId) {
- jam();
- return;
- } else {
- jam();
- replicaPtr.i = replicaPtr.p->nextReplica;
- }//if
- };
-
-#ifdef VM_TRACE
- g_eventLogger.info("Fragment Replica(node=%d) not found", nodeId);
- replicaPtr.i = fragPtrP->oldStoredReplicas;
- while(replicaPtr.i != RNIL){
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- if (replicaPtr.p->procNode == nodeId) {
- jam();
- break;
- } else {
- jam();
- replicaPtr.i = replicaPtr.p->nextReplica;
- }//if
- };
- if(replicaPtr.i != RNIL){
- g_eventLogger.info("...But was found in oldStoredReplicas");
- } else {
- g_eventLogger.info("...And wasn't found in oldStoredReplicas");
- }
-#endif
- ndbrequire(false);
-}//Dbdih::findReplica()
-
-
-int
-Dbdih::handle_invalid_lcp_no(const LcpFragRep* rep,
- ReplicaRecordPtr replicaPtr)
-{
- ndbrequire(!isMaster());
- Uint32 lcpNo = rep->lcpNo;
- Uint32 lcpId = rep->lcpId;
-
- warningEvent("Detected previous node failure of %d during lcp",
- rep->nodeId);
- replicaPtr.p->nextLcp = lcpNo;
- replicaPtr.p->lcpId[lcpNo] = 0;
- replicaPtr.p->lcpStatus[lcpNo] = ZINVALID;
-
- for (Uint32 i = lcpNo; i != lcpNo; i = nextLcpNo(i))
- {
- jam();
- if (replicaPtr.p->lcpStatus[i] == ZVALID &&
- replicaPtr.p->lcpId[i] >= lcpId)
- {
- ndbout_c("i: %d lcpId: %d", i, replicaPtr.p->lcpId[i]);
- ndbrequire(false);
- }
- }
-
- return 0;
-}
-
-/**
- * Return true if table is all fragment replicas have been checkpointed
- * to disk (in all LQHs)
- * false otherwise
- */
-bool
-Dbdih::reportLcpCompletion(const LcpFragRep* lcpReport)
-{
- Uint32 lcpNo = lcpReport->lcpNo;
- Uint32 lcpId = lcpReport->lcpId;
- Uint32 maxGciStarted = lcpReport->maxGciStarted;
- Uint32 maxGciCompleted = lcpReport->maxGciCompleted;
- Uint32 tableId = lcpReport->tableId;
- Uint32 fragId = lcpReport->fragId;
- Uint32 nodeId = lcpReport->nodeId;
-
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
-
- ReplicaRecordPtr replicaPtr;
- findReplica(replicaPtr, fragPtr.p, nodeId);
-
- ndbrequire(replicaPtr.p->lcpOngoingFlag == true);
- if(lcpNo != replicaPtr.p->nextLcp){
- if (handle_invalid_lcp_no(lcpReport, replicaPtr))
- {
- g_eventLogger.error("lcpNo = %d replicaPtr.p->nextLcp = %d",
- lcpNo, replicaPtr.p->nextLcp);
- ndbrequire(false);
- }
- }
- ndbrequire(lcpNo == replicaPtr.p->nextLcp);
- ndbrequire(lcpNo < MAX_LCP_STORED);
- ndbrequire(replicaPtr.p->lcpId[lcpNo] != lcpId);
-
- replicaPtr.p->lcpIdStarted = lcpId;
- replicaPtr.p->lcpOngoingFlag = false;
-
- removeOldCrashedReplicas(replicaPtr);
- replicaPtr.p->lcpId[lcpNo] = lcpId;
- replicaPtr.p->lcpStatus[lcpNo] = ZVALID;
- replicaPtr.p->maxGciStarted[lcpNo] = maxGciStarted;
- gth(maxGciStarted + 1, 0);
- replicaPtr.p->maxGciCompleted[lcpNo] = maxGciCompleted;
- replicaPtr.p->nextLcp = nextLcpNo(replicaPtr.p->nextLcp);
-
- ndbrequire(fragPtr.p->noLcpReplicas > 0);
- fragPtr.p->noLcpReplicas --;
-
- if(fragPtr.p->noLcpReplicas > 0){
- jam();
- return false;
- }
-
- for (Uint32 fid = 0; fid < tabPtr.p->totalfragments; fid++) {
- jam();
- getFragstore(tabPtr.p, fid, fragPtr);
- if (fragPtr.p->noLcpReplicas > 0){
- jam();
- /* ----------------------------------------------------------------- */
- // Not all fragments in table have been checkpointed.
- /* ----------------------------------------------------------------- */
- if(0)
- g_eventLogger.info("reportLcpCompletion: fragment %d not ready", fid);
- return false;
- }//if
- }//for
- return true;
-}//Dbdih::reportLcpCompletion()
-
-void Dbdih::checkStartMoreLcp(Signal* signal, Uint32 nodeId)
-{
- ndbrequire(isMaster());
-
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- ndbrequire(nodePtr.p->noOfStartedChkpt < 2);
-
- if (nodePtr.p->noOfQueuedChkpt > 0) {
- jam();
- nodePtr.p->noOfQueuedChkpt--;
- Uint32 i = nodePtr.p->noOfStartedChkpt;
- nodePtr.p->startedChkpt[i] = nodePtr.p->queuedChkpt[0];
- nodePtr.p->queuedChkpt[0] = nodePtr.p->queuedChkpt[1];
- //-------------------------------------------------------------------
- // We can send a LCP_FRAGORD to the node ordering it to perform a
- // local checkpoint on this fragment replica.
- //-------------------------------------------------------------------
- nodePtr.p->noOfStartedChkpt = i + 1;
-
- sendLCP_FRAG_ORD(signal, nodePtr.p->startedChkpt[i]);
- }
-
- /* ----------------------------------------------------------------------- */
- // When there are no more outstanding LCP reports and there are no one queued
- // in at least one node, then we are ready to make sure all nodes have at
- // least two outstanding LCP requests per node and at least two queued for
- // sending.
- /* ----------------------------------------------------------------------- */
- startNextChkpt(signal);
-}//Dbdih::checkStartMoreLcp()
-
-void
-Dbdih::sendLCP_FRAG_ORD(Signal* signal,
- NodeRecord::FragmentCheckpointInfo info){
-
- ReplicaRecordPtr replicaPtr;
- replicaPtr.i = info.replicaPtr;
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
-
- BlockReference ref = calcLqhBlockRef(replicaPtr.p->procNode);
-
- if (ERROR_INSERTED(7193) && replicaPtr.p->procNode == getOwnNodeId())
- {
- return;
- }
-
- LcpFragOrd * const lcpFragOrd = (LcpFragOrd *)&signal->theData[0];
- lcpFragOrd->tableId = info.tableId;
- lcpFragOrd->fragmentId = info.fragId;
- lcpFragOrd->lcpId = SYSFILE->latestLCP_ID;
- lcpFragOrd->lcpNo = replicaPtr.p->nextLcp;
- lcpFragOrd->keepGci = c_lcpState.keepGci;
- lcpFragOrd->lastFragmentFlag = false;
- sendSignal(ref, GSN_LCP_FRAG_ORD, signal, LcpFragOrd::SignalLength, JBB);
-}
-
-void Dbdih::checkLcpCompletedLab(Signal* signal)
-{
- if(c_lcpState.lcpStatus < LCP_TAB_COMPLETED){
- jam();
- return;
- }
-
- TabRecordPtr tabPtr;
- for (tabPtr.i = 0; tabPtr.i < ctabFileSize; tabPtr.i++) {
- jam();
- ptrAss(tabPtr, tabRecord);
- if (tabPtr.p->tabStatus == TabRecord::TS_ACTIVE) {
- if (tabPtr.p->tabLcpStatus != TabRecord::TLS_COMPLETED) {
- jam();
- return;
- }//if
- }//if
- }//for
-
- CRASH_INSERTION2(7027, isMaster());
- CRASH_INSERTION2(7018, !isMaster());
-
- if(c_lcpState.lcpStatus == LCP_TAB_COMPLETED){
- /**
- * We'r done
- */
- c_lcpState.setLcpStatus(LCP_TAB_SAVED, __LINE__);
- sendLCP_COMPLETE_REP(signal);
- return;
- }
-
- ndbrequire(c_lcpState.lcpStatus == LCP_TAB_SAVED);
- allNodesLcpCompletedLab(signal);
- return;
-}//Dbdih::checkLcpCompletedLab()
-
-void
-Dbdih::sendLCP_COMPLETE_REP(Signal* signal){
- jam();
- LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtrSend();
- rep->nodeId = getOwnNodeId();
- rep->lcpId = SYSFILE->latestLCP_ID;
- rep->blockNo = DBDIH;
-
- sendSignal(c_lcpState.m_masterLcpDihRef, GSN_LCP_COMPLETE_REP, signal,
- LcpCompleteRep::SignalLength, JBB);
-
- /**
- * Say that an initial node restart does not need to be redone
- * once node has been part of first LCP
- */
- if (c_set_initial_start_flag &&
- c_lcpState.m_participatingLQH.get(getOwnNodeId()))
- {
- jam();
- c_set_initial_start_flag = FALSE;
- }
-}
-
-/*-------------------------------------------------------------------------- */
-/* COMP_LCP_ROUND A LQH HAS COMPLETED A LOCAL CHECKPOINT */
-/*------------------------------------------------------------------------- */
-void Dbdih::execLCP_COMPLETE_REP(Signal* signal)
-{
- jamEntry();
-
- CRASH_INSERTION(7191);
-
-#if 0
- g_eventLogger.info("LCP_COMPLETE_REP");
- printLCP_COMPLETE_REP(stdout,
- signal->getDataPtr(),
- signal->length(), number());
-#endif
-
- LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtr();
- Uint32 lcpId = rep->lcpId;
- Uint32 nodeId = rep->nodeId;
- Uint32 blockNo = rep->blockNo;
-
- if(c_lcpMasterTakeOverState.state > LMTOS_WAIT_LCP_FRAG_REP){
- jam();
- /**
- * Don't allow LCP_COMPLETE_REP to arrive during
- * LCP master take over
- */
- ndbrequire(isMaster());
- ndbrequire(blockNo == DBDIH);
- sendSignalWithDelay(reference(), GSN_LCP_COMPLETE_REP, signal, 100,
- signal->length());
- return;
- }
-
- ndbrequire(c_lcpState.lcpStatus != LCP_STATUS_IDLE);
-
- switch(blockNo){
- case DBLQH:
- jam();
- c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH.clearWaitingFor(nodeId);
- ndbrequire(!c_lcpState.m_LAST_LCP_FRAG_ORD.isWaitingFor(nodeId));
- break;
- case DBDIH:
- jam();
- ndbrequire(isMaster());
- c_lcpState.m_LCP_COMPLETE_REP_Counter_DIH.clearWaitingFor(nodeId);
- break;
- case 0:
- jam();
- ndbrequire(!isMaster());
- ndbrequire(c_lcpState.m_LCP_COMPLETE_REP_From_Master_Received == false);
- c_lcpState.m_LCP_COMPLETE_REP_From_Master_Received = true;
- break;
- default:
- ndbrequire(false);
- }
- ndbrequire(lcpId == SYSFILE->latestLCP_ID);
-
- allNodesLcpCompletedLab(signal);
- return;
-}
-
-void Dbdih::allNodesLcpCompletedLab(Signal* signal)
-{
- jam();
-
- if (c_lcpState.lcpStatus != LCP_TAB_SAVED) {
- jam();
- /**
- * We have not sent LCP_COMPLETE_REP to master DIH yet
- */
- return;
- }//if
-
- if (!c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH.done()){
- jam();
- return;
- }
-
- if (!c_lcpState.m_LCP_COMPLETE_REP_Counter_DIH.done()){
- jam();
- return;
- }
-
- if (!isMaster() &&
- c_lcpState.m_LCP_COMPLETE_REP_From_Master_Received == false){
- jam();
- /**
- * Wait until master DIH has signaled lcp is complete
- */
- return;
- }
-
- if(c_lcpMasterTakeOverState.state != LMTOS_IDLE){
- jam();
-#ifdef VM_TRACE
- g_eventLogger.info("Exiting from allNodesLcpCompletedLab");
-#endif
- return;
- }
-
-
- /*------------------------------------------------------------------------ */
- /* WE HAVE NOW COMPLETED A LOCAL CHECKPOINT. WE ARE NOW READY TO WAIT */
- /* FOR THE NEXT LOCAL CHECKPOINT. SEND WITHOUT TIME-OUT SINCE IT MIGHT */
- /* BE TIME TO START THE NEXT LOCAL CHECKPOINT IMMEDIATELY. */
- /* CLEAR BIT 3 OF SYSTEM RESTART BITS TO INDICATE THAT THERE IS NO */
- /* LOCAL CHECKPOINT ONGOING. THIS WILL BE WRITTEN AT SOME LATER TIME */
- /* DURING A GLOBAL CHECKPOINT. IT IS NOT NECESSARY TO WRITE IT */
- /* IMMEDIATELY. WE WILL ALSO CLEAR BIT 2 OF SYSTEM RESTART BITS IF ALL */
- /* CURRENTLY ACTIVE NODES COMPLETED THE LOCAL CHECKPOINT. */
- /*------------------------------------------------------------------------ */
- CRASH_INSERTION(7019);
- signal->setTrace(0);
-
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
- setLcpActiveStatusEnd();
- Sysfile::clearLCPOngoing(SYSFILE->systemRestartBits);
-
- if(!isMaster()){
- jam();
- /**
- * We're not master, be content
- */
- return;
- }
-
- // Send LCP_COMPLETE_REP to all other nodes
- // allowing them to set their lcpStatus to LCP_STATUS_IDLE
- LcpCompleteRep * rep = (LcpCompleteRep*)signal->getDataPtrSend();
- rep->nodeId = getOwnNodeId();
- rep->lcpId = SYSFILE->latestLCP_ID;
- rep->blockNo = 0; // 0 = Sent from master
-
- NodeRecordPtr nodePtr;
- nodePtr.i = cfirstAliveNode;
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.i != cownNodeId){
- BlockReference ref = calcDihBlockRef(nodePtr.i);
- sendSignal(ref, GSN_LCP_COMPLETE_REP, signal,
- LcpCompleteRep::SignalLength, JBB);
- }
- nodePtr.i = nodePtr.p->nextNode;
- } while (nodePtr.i != RNIL);
-
-
- jam();
- /***************************************************************************/
- // Report the event that a local checkpoint has completed.
- /***************************************************************************/
- signal->theData[0] = NDB_LE_LocalCheckpointCompleted; //Event type
- signal->theData[1] = SYSFILE->latestLCP_ID;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- if (c_newest_restorable_gci > c_lcpState.lcpStopGcp)
- {
- jam();
- c_lcpState.lcpStopGcp = c_newest_restorable_gci;
- }
-
- /**
- * Start checking for next LCP
- */
- checkLcpStart(signal, __LINE__);
-
- if (cwaitLcpSr == true) {
- jam();
- cwaitLcpSr = false;
- ndbsttorry10Lab(signal, __LINE__);
- return;
- }//if
-
- if (c_nodeStartMaster.blockLcp == true) {
- jam();
- lcpBlockedLab(signal);
- return;
- }//if
- return;
-}//Dbdih::allNodesLcpCompletedLab()
-
-/******************************************************************************/
-/* ********** TABLE UPDATE MODULE *************/
-/* ****************************************************************************/
-/* ------------------------------------------------------------------------- */
-/* THIS MODULE IS USED TO UPDATE THE TABLE DESCRIPTION. IT STARTS BY */
-/* CREATING THE FIRST TABLE FILE, THEN UPDATES THIS FILE AND CLOSES IT.*/
-/* AFTER THAT THE SAME HAPPENS WITH THE SECOND FILE. AFTER THAT THE */
-/* TABLE DISTRIBUTION HAS BEEN UPDATED. */
-/* */
-/* THE REASON FOR CREATING THE FILE AND NOT OPENING IT IS TO ENSURE */
-/* THAT WE DO NOT GET A MIX OF OLD AND NEW INFORMATION IN THE FILE IN */
-/* ERROR SITUATIONS. */
-/* ------------------------------------------------------------------------- */
-void Dbdih::tableUpdateLab(Signal* signal, TabRecordPtr tabPtr) {
- FileRecordPtr filePtr;
- if(tabPtr.p->tabStorage == TabRecord::ST_TEMPORARY) {
- // For temporary tables we do not write to disk. Mark both copies 0 and 1
- // as done, and go straight to the after-close code.
- filePtr.i = tabPtr.p->tabFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- tableCloseLab(signal, filePtr);
- return;
- }
- filePtr.i = tabPtr.p->tabFile[0];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- createFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::TABLE_CREATE;
- return;
-}//Dbdih::tableUpdateLab()
-
-void Dbdih::tableCreateLab(Signal* signal, FileRecordPtr filePtr)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- writeTabfile(signal, tabPtr.p, filePtr);
- filePtr.p->reqStatus = FileRecord::TABLE_WRITE;
- return;
-}//Dbdih::tableCreateLab()
-
-void Dbdih::tableWriteLab(Signal* signal, FileRecordPtr filePtr)
-{
- closeFile(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::TABLE_CLOSE;
- return;
-}//Dbdih::tableWriteLab()
-
-void Dbdih::tableCloseLab(Signal* signal, FileRecordPtr filePtr)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = filePtr.p->tabRef;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- if (filePtr.i == tabPtr.p->tabFile[0]) {
- jam();
- filePtr.i = tabPtr.p->tabFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- createFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::TABLE_CREATE;
- return;
- }//if
- switch (tabPtr.p->tabUpdateState) {
- case TabRecord::US_LOCAL_CHECKPOINT:
- jam();
- releaseTabPages(tabPtr.i);
- signal->theData[0] = DihContinueB::ZCHECK_LCP_COMPLETED;
- sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
-
- tabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- tabPtr.p->tabUpdateState = TabRecord::US_IDLE;
- tabPtr.p->tabLcpStatus = TabRecord::TLS_COMPLETED;
- return;
- break;
- case TabRecord::US_REMOVE_NODE:
- jam();
- releaseTabPages(tabPtr.i);
- for (Uint32 fragId = 0; fragId < tabPtr.p->totalfragments; fragId++) {
- jam();
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragId, fragPtr);
- updateNodeInfo(fragPtr);
- }//for
- tabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- tabPtr.p->tabUpdateState = TabRecord::US_IDLE;
- if (tabPtr.p->tabLcpStatus == TabRecord::TLS_WRITING_TO_FILE) {
- jam();
- tabPtr.p->tabLcpStatus = TabRecord::TLS_COMPLETED;
- signal->theData[0] = DihContinueB::ZCHECK_LCP_COMPLETED;
- sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
- }//if
- signal->theData[0] = DihContinueB::ZREMOVE_NODE_FROM_TABLE;
- signal->theData[1] = tabPtr.p->tabRemoveNode;
- signal->theData[2] = tabPtr.i + 1;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
- break;
- case TabRecord::US_INVALIDATE_NODE_LCP:
- jam();
- releaseTabPages(tabPtr.i);
- tabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- tabPtr.p->tabUpdateState = TabRecord::US_IDLE;
-
- signal->theData[0] = DihContinueB::ZINVALIDATE_NODE_LCP;
- signal->theData[1] = tabPtr.p->tabRemoveNode;
- signal->theData[2] = tabPtr.i + 1;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- return;
- case TabRecord::US_COPY_TAB_REQ:
- jam();
- tabPtr.p->tabUpdateState = TabRecord::US_IDLE;
- copyTabReq_complete(signal, tabPtr);
- return;
- break;
- case TabRecord::US_ADD_TABLE_MASTER:
- jam();
- releaseTabPages(tabPtr.i);
- tabPtr.p->tabUpdateState = TabRecord::US_IDLE;
- signal->theData[0] = DihContinueB::ZDIH_ADD_TABLE_MASTER;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- case TabRecord::US_ADD_TABLE_SLAVE:
- jam();
- releaseTabPages(tabPtr.i);
- tabPtr.p->tabUpdateState = TabRecord::US_IDLE;
- signal->theData[0] = DihContinueB::ZDIH_ADD_TABLE_SLAVE;
- signal->theData[1] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- break;
- default:
- ndbrequire(false);
- return;
- break;
- }//switch
-}//Dbdih::tableCloseLab()
-
-/**
- * GCP stop detected,
- * send SYSTEM_ERROR to all other alive nodes
- */
-void Dbdih::crashSystemAtGcpStop(Signal* signal, bool local)
-{
- if (local)
- goto dolocal;
-
- switch(cgcpStatus){
- case GCP_PREPARE_SENT:
- {
- jam();
- /**
- * We're waiting for a GCP PREPARE CONF
- */
- infoEvent("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_GCP_PREPARE_Counter.getText());
- ndbout_c("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_GCP_PREPARE_Counter.getText());
-
- {
- NodeReceiverGroup rg(DBDIH, c_GCP_PREPARE_Counter);
- signal->theData[0] = 7022;
- sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBA);
- }
-
- {
- NodeReceiverGroup rg(NDBCNTR, c_GCP_PREPARE_Counter);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::GCPStopDetected;
- sysErr->errorRef = reference();
- sysErr->data1 = cgcpStatus;
- sysErr->data2 = cgcpOrderBlocked;
- sendSignal(rg, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBA);
- }
- ndbrequire(!c_GCP_PREPARE_Counter.done());
- return;
- }
- case GCP_COMMIT_SENT:
- {
- jam();
- /**
- * We're waiting for a GCP_NODEFINISH
- */
- infoEvent("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_GCP_COMMIT_Counter.getText());
- ndbout_c("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_GCP_COMMIT_Counter.getText());
-
- {
- NodeReceiverGroup rg(DBDIH, c_GCP_COMMIT_Counter);
- signal->theData[0] = 7022;
- sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBA);
- }
-
- {
- NodeReceiverGroup rg(NDBCNTR, c_GCP_COMMIT_Counter);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::GCPStopDetected;
- sysErr->errorRef = reference();
- sysErr->data1 = cgcpStatus;
- sysErr->data2 = cgcpOrderBlocked;
- sendSignal(rg, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBA);
- }
- ndbrequire(!c_GCP_COMMIT_Counter.done());
- return;
- }
- case GCP_NODE_FINISHED:
- {
- jam();
- /**
- * We're waiting for a GCP save conf
- */
- NodeReceiverGroup rg(DBLQH, c_GCP_SAVEREQ_Counter);
- signal->theData[0] = 2305;
- sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
-
- infoEvent("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_GCP_SAVEREQ_Counter.getText());
- ndbout_c("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_GCP_SAVEREQ_Counter.getText());
- ndbrequire(!c_GCP_SAVEREQ_Counter.done());
- return;
- }
- case GCP_SAVE_LQH_FINISHED:
- {
- jam();
- /**
- * We're waiting for a COPY_GCICONF
- */
- infoEvent("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_COPY_GCIREQ_Counter.getText());
- ndbout_c("Detected GCP stop(%d)...sending kill to %s",
- cgcpStatus, c_COPY_GCIREQ_Counter.getText());
-
- {
- NodeReceiverGroup rg(DBDIH, c_COPY_GCIREQ_Counter);
- signal->theData[0] = 7022;
- sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBA);
- }
-
- {
- NodeReceiverGroup rg(NDBCNTR, c_COPY_GCIREQ_Counter);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::GCPStopDetected;
- sysErr->errorRef = reference();
- sysErr->data1 = cgcpStatus;
- sysErr->data2 = cgcpOrderBlocked;
- sendSignal(rg, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBA);
- }
- ndbrequire(!c_COPY_GCIREQ_Counter.done());
- return;
- }
- case GCP_READY: (void)1;
- }
-
-dolocal:
- ndbout_c("m_copyReason: %d m_waiting: %d",
- c_copyGCIMaster.m_copyReason,
- c_copyGCIMaster.m_waiting);
-
- 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());
-
- if (local == false)
- {
- jam();
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- const BlockReference ref =
- numberToRef(refToBlock(cntrlblockref), nodePtr.i);
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::GCPStopDetected;
- sysErr->errorRef = reference();
- sysErr->data1 = cgcpStatus;
- sysErr->data2 = cgcpOrderBlocked;
- sendSignal(ref, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBA);
- }//if
- }//for
- }
- else
- {
- jam();
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::GCPStopDetected;
- sysErr->errorRef = reference();
- sysErr->data1 = cgcpStatus;
- sysErr->data2 = cgcpOrderBlocked;
- EXECUTE_DIRECT(NDBCNTR, GSN_SYSTEM_ERROR,
- signal, SystemError::SignalLength);
- ndbrequire(false);
- }
- return;
-}//Dbdih::crashSystemAtGcpStop()
-
-/*************************************************************************/
-/* */
-/* MODULE: ALLOCPAGE */
-/* DESCRIPTION: THE SUBROUTINE IS CALLED WITH POINTER TO PAGE */
-/* RECORD. A PAGE RECORD IS TAKEN FROM */
-/* THE FREE PAGE LIST */
-/*************************************************************************/
-void Dbdih::allocpage(PageRecordPtr& pagePtr)
-{
- ndbrequire(cfirstfreepage != RNIL);
- pagePtr.i = cfirstfreepage;
- ptrCheckGuard(pagePtr, cpageFileSize, pageRecord);
- cfirstfreepage = pagePtr.p->nextfreepage;
- pagePtr.p->nextfreepage = RNIL;
-}//Dbdih::allocpage()
-
-/*************************************************************************/
-/* */
-/* MODULE: ALLOC_STORED_REPLICA */
-/* DESCRIPTION: THE SUBROUTINE IS CALLED TO GET A REPLICA RECORD, */
-/* TO INITIALISE IT AND TO LINK IT INTO THE FRAGMENT */
-/* STORE RECORD. USED FOR STORED REPLICAS. */
-/*************************************************************************/
-void Dbdih::allocStoredReplica(FragmentstorePtr fragPtr,
- ReplicaRecordPtr& newReplicaPtr,
- Uint32 nodeId)
-{
- Uint32 i;
- ReplicaRecordPtr arrReplicaPtr;
- ReplicaRecordPtr arrPrevReplicaPtr;
-
- seizeReplicaRec(newReplicaPtr);
- for (i = 0; i < MAX_LCP_STORED; i++) {
- newReplicaPtr.p->maxGciCompleted[i] = 0;
- newReplicaPtr.p->maxGciStarted[i] = 0;
- newReplicaPtr.p->lcpId[i] = 0;
- newReplicaPtr.p->lcpStatus[i] = ZINVALID;
- }//for
- newReplicaPtr.p->noCrashedReplicas = 0;
- newReplicaPtr.p->initialGci = currentgcp;
- for (i = 0; i < 8; i++) {
- newReplicaPtr.p->replicaLastGci[i] = (Uint32)-1;
- newReplicaPtr.p->createGci[i] = 0;
- }//for
- newReplicaPtr.p->createGci[0] = currentgcp;
- ndbrequire(currentgcp != 0xF1F1F1F1);
- newReplicaPtr.p->nextLcp = 0;
- newReplicaPtr.p->procNode = nodeId;
- newReplicaPtr.p->lcpOngoingFlag = false;
- newReplicaPtr.p->lcpIdStarted = 0;
-
- arrPrevReplicaPtr.i = RNIL;
- arrReplicaPtr.i = fragPtr.p->storedReplicas;
- while (arrReplicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(arrReplicaPtr, creplicaFileSize, replicaRecord);
- arrPrevReplicaPtr = arrReplicaPtr;
- arrReplicaPtr.i = arrReplicaPtr.p->nextReplica;
- }//while
- if (arrPrevReplicaPtr.i == RNIL) {
- jam();
- fragPtr.p->storedReplicas = newReplicaPtr.i;
- } else {
- jam();
- arrPrevReplicaPtr.p->nextReplica = newReplicaPtr.i;
- }//if
- fragPtr.p->noStoredReplicas++;
-}//Dbdih::allocStoredReplica()
-
-/*************************************************************************/
-/* CALCULATE HOW MANY HOT SPARES THAT ARE TO BE ASSIGNED IN THIS SYSTEM */
-/*************************************************************************/
-void Dbdih::calculateHotSpare()
-{
- Uint32 tchsTmp;
- Uint32 tchsNoNodes;
-
- switch (cnoReplicas) {
- case 1:
- jam();
- cnoHotSpare = 0;
- break;
- case 2:
- case 3:
- case 4:
- jam();
- if (csystemnodes > cnoReplicas) {
- jam();
- /* --------------------------------------------------------------------- */
- /* WITH MORE NODES THAN REPLICAS WE WILL ALWAYS USE AT LEAST ONE HOT */
- /* SPARE IF THAT HAVE BEEN REQUESTED BY THE CONFIGURATION FILE. THE */
- /* NUMBER OF NODES TO BE USED FOR NORMAL OPERATION IS ALWAYS */
- /* A MULTIPLE OF THE NUMBER OF REPLICAS SINCE WE WILL ORGANISE NODES */
- /* INTO NODE GROUPS. THE REMAINING NODES WILL BE HOT SPARE NODES. */
- /* --------------------------------------------------------------------- */
- if ((csystemnodes - cnoReplicas) >= cminHotSpareNodes) {
- jam();
- /* --------------------------------------------------------------------- */
- // We set the minimum number of hot spares according to users request
- // through the configuration file.
- /* --------------------------------------------------------------------- */
- tchsNoNodes = csystemnodes - cminHotSpareNodes;
- cnoHotSpare = cminHotSpareNodes;
- } else if (cminHotSpareNodes > 0) {
- jam();
- /* --------------------------------------------------------------------- */
- // The user requested at least one hot spare node and we will support him
- // in that.
- /* --------------------------------------------------------------------- */
- tchsNoNodes = csystemnodes - 1;
- cnoHotSpare = 1;
- } else {
- jam();
- /* --------------------------------------------------------------------- */
- // The user did not request any hot spare nodes so in this case we will
- // only use hot spare nodes if the number of nodes is such that we cannot
- // use all nodes as normal nodes.
- /* --------------------------------------------------------------------- */
- tchsNoNodes = csystemnodes;
- cnoHotSpare = 0;
- }//if
- } else {
- jam();
- /* --------------------------------------------------------------------- */
- // We only have enough to support the replicas. We will not have any hot
- // spares.
- /* --------------------------------------------------------------------- */
- tchsNoNodes = csystemnodes;
- cnoHotSpare = 0;
- }//if
- tchsTmp = tchsNoNodes - (cnoReplicas * (tchsNoNodes / cnoReplicas));
- cnoHotSpare = cnoHotSpare + tchsTmp;
- break;
- default:
- jam();
- ndbrequire(false);
- break;
- }//switch
-}//Dbdih::calculateHotSpare()
-
-/*************************************************************************/
-/* CHECK IF THE NODE CRASH IS TO ESCALATE INTO A SYSTEM CRASH. WE COULD */
-/* DO THIS BECAUSE ALL REPLICAS OF SOME FRAGMENT ARE LOST. WE COULD ALSO */
-/* DO IT AFTER MANY NODE FAILURES THAT MAKE IT VERY DIFFICULT TO RESTORE */
-/* DATABASE AFTER A SYSTEM CRASH. IT MIGHT EVEN BE IMPOSSIBLE AND THIS */
-/* MUST BE AVOIDED EVEN MORE THAN AVOIDING SYSTEM CRASHES. */
-/*************************************************************************/
-void Dbdih::checkEscalation()
-{
- Uint32 TnodeGroup[MAX_NDB_NODES];
- NodeRecordPtr nodePtr;
- Uint32 i;
- for (i = 0; i < MAX_NDB_NODES; i++) {
- TnodeGroup[i] = ZFALSE;
- }//for
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE &&
- nodePtr.p->activeStatus == Sysfile::NS_Active){
- ndbrequire(nodePtr.p->nodeGroup < MAX_NDB_NODES);
- TnodeGroup[nodePtr.p->nodeGroup] = ZTRUE;
- }
- }
- for (i = 0; i < cnoOfNodeGroups; i++) {
- jam();
- if (TnodeGroup[i] == ZFALSE) {
- jam();
- progError(__LINE__, NDBD_EXIT_LOST_NODE_GROUP, "Lost node group");
- }//if
- }//for
-}//Dbdih::checkEscalation()
-
-/*************************************************************************/
-/* */
-/* MODULE: CHECK_KEEP_GCI */
-/* DESCRIPTION: CHECK FOR MINIMUM GCI RESTORABLE WITH NEW LOCAL */
-/* CHECKPOINT. */
-/*************************************************************************/
-void Dbdih::checkKeepGci(TabRecordPtr tabPtr, Uint32 fragId, Fragmentstore*,
- Uint32 replicaStartIndex)
-{
- ReplicaRecordPtr ckgReplicaPtr;
- ckgReplicaPtr.i = replicaStartIndex;
- while (ckgReplicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(ckgReplicaPtr, creplicaFileSize, replicaRecord);
- Uint32 keepGci;
- Uint32 oldestRestorableGci;
- findMinGci(ckgReplicaPtr, keepGci, oldestRestorableGci);
- if (keepGci < c_lcpState.keepGci) {
- jam();
- /* ------------------------------------------------------------------- */
- /* WE MUST KEEP LOG RECORDS SO THAT WE CAN USE ALL LOCAL CHECKPOINTS */
- /* THAT ARE AVAILABLE. THUS WE NEED TO CALCULATE THE MINIMUM OVER ALL */
- /* FRAGMENTS. */
- /* ------------------------------------------------------------------- */
- c_lcpState.keepGci = keepGci;
- }//if
- if (oldestRestorableGci > c_lcpState.oldestRestorableGci) {
- jam();
- c_lcpState.oldestRestorableGci = oldestRestorableGci;
- }//if
- ckgReplicaPtr.i = ckgReplicaPtr.p->nextReplica;
- }//while
-}//Dbdih::checkKeepGci()
-
-void Dbdih::closeFile(Signal* signal, FileRecordPtr filePtr)
-{
- signal->theData[0] = filePtr.p->fileRef;
- signal->theData[1] = reference();
- signal->theData[2] = filePtr.i;
- signal->theData[3] = ZCLOSE_NO_DELETE;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
-}//Dbdih::closeFile()
-
-void Dbdih::closeFileDelete(Signal* signal, FileRecordPtr filePtr)
-{
- signal->theData[0] = filePtr.p->fileRef;
- signal->theData[1] = reference();
- signal->theData[2] = filePtr.i;
- signal->theData[3] = ZCLOSE_DELETE;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
-}//Dbdih::closeFileDelete()
-
-void Dbdih::createFileRw(Signal* signal, FileRecordPtr filePtr)
-{
- signal->theData[0] = reference();
- signal->theData[1] = filePtr.i;
- signal->theData[2] = filePtr.p->fileName[0];
- signal->theData[3] = filePtr.p->fileName[1];
- signal->theData[4] = filePtr.p->fileName[2];
- signal->theData[5] = filePtr.p->fileName[3];
- signal->theData[6] = ZCREATE_READ_WRITE;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
-}//Dbdih::createFileRw()
-
-void Dbdih::emptyverificbuffer(Signal* signal, bool aContinueB)
-{
- if(cfirstVerifyQueue == RNIL){
- jam();
- return;
- }//if
- ApiConnectRecordPtr localApiConnectptr;
- if(getBlockCommit() == false){
- jam();
- ndbrequire(cverifyQueueCounter > 0);
- cverifyQueueCounter--;
- localApiConnectptr.i = cfirstVerifyQueue;
- ptrCheckGuard(localApiConnectptr, capiConnectFileSize, apiConnectRecord);
- ndbrequire(localApiConnectptr.p->apiGci <= currentgcp);
- cfirstVerifyQueue = localApiConnectptr.p->nextApi;
- if (cfirstVerifyQueue == RNIL) {
- jam();
- ndbrequire(cverifyQueueCounter == 0);
- clastVerifyQueue = RNIL;
- }//if
- signal->theData[0] = localApiConnectptr.i;
- signal->theData[1] = currentgcp;
- sendSignal(clocaltcblockref, GSN_DIVERIFYCONF, signal, 2, JBB);
- if (aContinueB == true) {
- jam();
- //-----------------------------------------------------------------------
- // This emptying happened as part of a take-out process by continueb signals.
- // This ensures that we will empty the queue eventually. We will also empty
- // one item every time we insert one item to ensure that the list doesn't
- // grow when it is not blocked.
- //-----------------------------------------------------------------------
- signal->theData[0] = DihContinueB::ZEMPTY_VERIFY_QUEUE;
- sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
- }//if
- } else {
- jam();
- //-----------------------------------------------------------------------
- // We are blocked so it is no use in continuing the emptying of the
- // verify buffer. Whenever the block is removed the emptying will
- // restart.
- //-----------------------------------------------------------------------
- }
- return;
-}//Dbdih::emptyverificbuffer()
-
-/*----------------------------------------------------------------*/
-/* FIND A FREE HOT SPARE IF AVAILABLE AND ALIVE. */
-/*----------------------------------------------------------------*/
-Uint32 Dbdih::findHotSpare()
-{
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- if (nodePtr.p->activeStatus == Sysfile::NS_HotSpare) {
- jam();
- return nodePtr.i;
- }//if
- }//if
- }//for
- return RNIL;
-}//Dbdih::findHotSpare()
-
-/*************************************************************************/
-/* FIND THE NODES FROM WHICH WE CAN EXECUTE THE LOG TO RESTORE THE */
-/* DATA NODE IN A SYSTEM RESTART. */
-/*************************************************************************/
-bool Dbdih::findLogNodes(CreateReplicaRecord* createReplica,
- FragmentstorePtr fragPtr,
- Uint32 startGci,
- Uint32 stopGci)
-{
- ConstPtr<ReplicaRecord> flnReplicaPtr;
- flnReplicaPtr.i = createReplica->replicaRec;
- ptrCheckGuard(flnReplicaPtr, creplicaFileSize, replicaRecord);
- /* --------------------------------------------------------------------- */
- /* WE START BY CHECKING IF THE DATA NODE CAN HANDLE THE LOG ALL BY */
- /* ITSELF. THIS IS THE DESIRED BEHAVIOUR. IF THIS IS NOT POSSIBLE */
- /* THEN WE SEARCH FOR THE BEST POSSIBLE NODES AMONG THE NODES THAT */
- /* ARE PART OF THIS SYSTEM RESTART. */
- /* THIS CAN ONLY BE HANDLED BY THE LAST CRASHED REPLICA. */
- /* The condition is that the replica was created before or at the */
- /* time of the starting gci, in addition it must have been alive */
- /* at the time of the stopping gci. This is checked by two */
- /* conditions, the first checks replicaLastGci and the second */
- /* checks that it is also smaller than the last gci the node was */
- /* involved in. This is necessary to check since createGci is set */
- /* Last + 1 and sometimes startGci = stopGci + 1 and in that case */
- /* it could happen that replicaLastGci is set to -1 with CreateGci */
- /* set to LastGci + 1. */
- /* --------------------------------------------------------------------- */
- arrGuard(flnReplicaPtr.p->noCrashedReplicas, 8);
- const Uint32 noCrashed = flnReplicaPtr.p->noCrashedReplicas;
-
- if (!(ERROR_INSERTED(7073) || ERROR_INSERTED(7074))&&
- (startGci >= flnReplicaPtr.p->createGci[noCrashed]) &&
- (stopGci <= flnReplicaPtr.p->replicaLastGci[noCrashed]) &&
- (stopGci <= SYSFILE->lastCompletedGCI[flnReplicaPtr.p->procNode])) {
- jam();
- /* --------------------------------------------------------------------- */
- /* WE FOUND ALL THE LOG RECORDS NEEDED IN THE DATA NODE. WE WILL */
- /* USE THOSE. */
- /* --------------------------------------------------------------------- */
- createReplica->noLogNodes = 1;
- createReplica->logStartGci[0] = startGci;
- createReplica->logStopGci[0] = stopGci;
- createReplica->logNodeId[0] = flnReplicaPtr.p->procNode;
- return true;
- }//if
- Uint32 logNode = 0;
- do {
- Uint32 fblStopGci;
- jam();
- if(!findBestLogNode(createReplica,
- fragPtr,
- startGci,
- stopGci,
- logNode,
- fblStopGci)){
- jam();
- return false;
- }
-
- logNode++;
- if (fblStopGci >= stopGci) {
- jam();
- createReplica->noLogNodes = logNode;
- return true;
- }//if
- startGci = fblStopGci + 1;
- if (logNode >= 4) { // Why??
- jam();
- break;
- }//if
- } while (1);
- /* --------------------------------------------------------------------- */
- /* IT WAS NOT POSSIBLE TO RESTORE THE REPLICA. THIS CAN EITHER BE */
- /* BECAUSE OF LACKING NODES OR BECAUSE OF A REALLY SERIOUS PROBLEM.*/
- /* --------------------------------------------------------------------- */
- return false;
-}//Dbdih::findLogNodes()
-
-/*************************************************************************/
-/* FIND THE BEST POSSIBLE LOG NODE TO EXECUTE THE LOG AS SPECIFIED */
-/* BY THE INPUT PARAMETERS. WE SCAN THROUGH ALL ALIVE REPLICAS. */
-/* THIS MEANS STORED, OLD_STORED */
-/*************************************************************************/
-bool
-Dbdih::findBestLogNode(CreateReplicaRecord* createReplica,
- FragmentstorePtr fragPtr,
- Uint32 startGci,
- Uint32 stopGci,
- Uint32 logNode,
- Uint32& fblStopGci)
-{
- ConstPtr<ReplicaRecord> fblFoundReplicaPtr;
- ConstPtr<ReplicaRecord> fblReplicaPtr;
- LINT_INIT(fblFoundReplicaPtr.p);
-
- /* --------------------------------------------------------------------- */
- /* WE START WITH ZERO AS FOUND TO ENSURE THAT FIRST HIT WILL BE */
- /* BETTER. */
- /* --------------------------------------------------------------------- */
- fblStopGci = 0;
- fblReplicaPtr.i = fragPtr.p->storedReplicas;
- while (fblReplicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(fblReplicaPtr, creplicaFileSize, replicaRecord);
- if (checkNodeAlive(fblReplicaPtr.p->procNode)) {
- jam();
- Uint32 fliStopGci = findLogInterval(fblReplicaPtr, startGci);
- if (fliStopGci > fblStopGci) {
- jam();
- fblStopGci = fliStopGci;
- fblFoundReplicaPtr = fblReplicaPtr;
- }//if
- }//if
- fblReplicaPtr.i = fblReplicaPtr.p->nextReplica;
- }//while
- fblReplicaPtr.i = fragPtr.p->oldStoredReplicas;
- while (fblReplicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(fblReplicaPtr, creplicaFileSize, replicaRecord);
- if (checkNodeAlive(fblReplicaPtr.p->procNode)) {
- jam();
- Uint32 fliStopGci = findLogInterval(fblReplicaPtr, startGci);
- if (fliStopGci > fblStopGci) {
- jam();
- fblStopGci = fliStopGci;
- fblFoundReplicaPtr = fblReplicaPtr;
- }//if
- }//if
- fblReplicaPtr.i = fblReplicaPtr.p->nextReplica;
- }//while
- if (fblStopGci != 0) {
- jam();
- ndbrequire(logNode < MAX_LOG_EXEC);
- createReplica->logNodeId[logNode] = fblFoundReplicaPtr.p->procNode;
- createReplica->logStartGci[logNode] = startGci;
- if (fblStopGci >= stopGci) {
- jam();
- createReplica->logStopGci[logNode] = stopGci;
- } else {
- jam();
- createReplica->logStopGci[logNode] = fblStopGci;
- }//if
- }//if
-
- return fblStopGci != 0;
-}//Dbdih::findBestLogNode()
-
-Uint32 Dbdih::findLogInterval(ConstPtr<ReplicaRecord> replicaPtr,
- Uint32 startGci)
-{
- ndbrequire(replicaPtr.p->noCrashedReplicas <= 8);
- Uint32 loopLimit = replicaPtr.p->noCrashedReplicas + 1;
- for (Uint32 i = 0; i < loopLimit; i++) {
- jam();
- if (replicaPtr.p->createGci[i] <= startGci) {
- if (replicaPtr.p->replicaLastGci[i] >= startGci) {
- jam();
- return replicaPtr.p->replicaLastGci[i];
- }//if
- }//if
- }//for
- return 0;
-}//Dbdih::findLogInterval()
-
-/*************************************************************************/
-/* */
-/* MODULE: FIND THE MINIMUM GCI THAT THIS NODE HAS LOG RECORDS FOR.*/
-/*************************************************************************/
-void Dbdih::findMinGci(ReplicaRecordPtr fmgReplicaPtr,
- Uint32& keepGci,
- Uint32& oldestRestorableGci)
-{
- Uint32 nextLcpNo;
- Uint32 lcpNo;
- for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
- jam();
- if ((fmgReplicaPtr.p->lcpStatus[i] == ZVALID) &&
- ((fmgReplicaPtr.p->lcpId[i] + MAX_LCP_STORED) <= (SYSFILE->latestLCP_ID + 1))) {
- jam();
- /*--------------------------------------------------------------------*/
- // We invalidate the checkpoint we are preparing to overwrite.
- // The LCP id is still the old lcp id,
- // this is the reason of comparing with lcpId + 1.
- /*---------------------------------------------------------------------*/
- fmgReplicaPtr.p->lcpStatus[i] = ZINVALID;
- }//if
- }//for
- keepGci = (Uint32)-1;
- oldestRestorableGci = 0;
- nextLcpNo = fmgReplicaPtr.p->nextLcp;
- lcpNo = fmgReplicaPtr.p->nextLcp;
- do {
- ndbrequire(lcpNo < MAX_LCP_STORED);
- if (fmgReplicaPtr.p->lcpStatus[lcpNo] == ZVALID)
- {
- jam();
- keepGci = fmgReplicaPtr.p->maxGciCompleted[lcpNo];
- oldestRestorableGci = fmgReplicaPtr.p->maxGciStarted[lcpNo];
- ndbassert(fmgReplicaPtr.p->maxGciStarted[lcpNo] <c_newest_restorable_gci);
- return;
- } else {
- jam();
- if (fmgReplicaPtr.p->createGci[0] == fmgReplicaPtr.p->initialGci) {
- jam();
- /*-------------------------------------------------------------------
- * WE CAN STILL RESTORE THIS REPLICA WITHOUT ANY LOCAL CHECKPOINTS BY
- * ONLY USING THE LOG. IF THIS IS NOT POSSIBLE THEN WE REPORT THE LAST
- * VALID LOCAL CHECKPOINT AS THE MINIMUM GCI RECOVERABLE.
- *-----------------------------------------------------------------*/
- keepGci = fmgReplicaPtr.p->createGci[0];
- }//if
- }//if
- lcpNo = prevLcpNo(lcpNo);
- } while (lcpNo != nextLcpNo);
- return;
-}//Dbdih::findMinGci()
-
-bool Dbdih::findStartGci(ConstPtr<ReplicaRecord> replicaPtr,
- Uint32 stopGci,
- Uint32& startGci,
- Uint32& lcpNo)
-{
- lcpNo = replicaPtr.p->nextLcp;
- const Uint32 startLcpNo = lcpNo;
- do {
- lcpNo = prevLcpNo(lcpNo);
- ndbrequire(lcpNo < MAX_LCP_STORED);
- if (replicaPtr.p->lcpStatus[lcpNo] == ZVALID) {
- if (replicaPtr.p->maxGciStarted[lcpNo] < stopGci) {
- jam();
- /* ----------------------------------------------------------------- */
- /* WE HAVE FOUND A USEFUL LOCAL CHECKPOINT THAT CAN BE USED FOR */
- /* RESTARTING THIS FRAGMENT REPLICA. */
- /* ----------------------------------------------------------------- */
- startGci = replicaPtr.p->maxGciCompleted[lcpNo] + 1;
- return true;
- }
- }
- } while (lcpNo != startLcpNo);
- /* --------------------------------------------------------------------- */
- /* NO VALID LOCAL CHECKPOINT WAS AVAILABLE. WE WILL ADD THE */
- /* FRAGMENT. THUS THE NEXT LCP MUST BE SET TO ZERO. */
- /* WE MUST EXECUTE THE LOG FROM THE INITIAL GLOBAL CHECKPOINT WHEN */
- /* THE TABLE WAS CREATED. */
- /* --------------------------------------------------------------------- */
- startGci = replicaPtr.p->initialGci;
- ndbrequire(replicaPtr.p->nextLcp == 0);
- return false;
-}//Dbdih::findStartGci()
-
-/**************************************************************************/
-/* ---------------------------------------------------------------------- */
-/* FIND A TAKE OVER REPLICA WHICH IS TO BE STARTED OR COMMITTED WHEN*/
-/* TAKING OVER A FAILED NODE. */
-/* ---------------------------------------------------------------------- */
-/*************************************************************************/
-void Dbdih::findToReplica(TakeOverRecord* regTakeOver,
- Uint32 replicaType,
- FragmentstorePtr fragPtr,
- ReplicaRecordPtr& ftrReplicaPtr)
-{
- switch (replicaType) {
- case CreateFragReq::STORED:
- case CreateFragReq::COMMIT_STORED:
- /* ----------------------------------------------------------------------*/
- /* HERE WE SEARCH FOR STORED REPLICAS. THE REPLICA MUST BE STORED IN THE */
- /* SECTION FOR OLD STORED REPLICAS SINCE WE HAVE NOT TAKEN OVER YET. */
- /* ----------------------------------------------------------------------*/
- ftrReplicaPtr.i = fragPtr.p->oldStoredReplicas;
- while (ftrReplicaPtr.i != RNIL) {
- ptrCheckGuard(ftrReplicaPtr, creplicaFileSize, replicaRecord);
- if (ftrReplicaPtr.p->procNode == regTakeOver->toStartingNode) {
- jam();
- return;
- } else {
- if (ftrReplicaPtr.p->procNode == regTakeOver->toFailedNode) {
- jam();
- return;
- } else {
- jam();
- ftrReplicaPtr.i = ftrReplicaPtr.p->nextReplica;
- }//if
- }//if
- }//while
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
-}//Dbdih::findToReplica()
-
-void Dbdih::initCommonData()
-{
- c_blockCommit = false;
- c_blockCommitNo = 0;
- c_createFragmentLock = RNIL;
- c_endToLock = RNIL;
- cfailurenr = 1;
- cfirstAliveNode = RNIL;
- cfirstDeadNode = RNIL;
- cfirstVerifyQueue = RNIL;
- cgckptflag = false;
- cgcpDelay = 0;
- cgcpMasterTakeOverState = GMTOS_IDLE;
- cgcpOrderBlocked = 0;
- cgcpParticipantState = GCP_PARTICIPANT_READY;
- cgcpSameCounter = 0;
- cgcpStartCounter = 0;
- cgcpStatus = GCP_READY;
-
- clastVerifyQueue = RNIL;
- c_lcpMasterTakeOverState.set(LMTOS_IDLE, __LINE__);
-
- c_lcpState.clcpDelay = 0;
- c_lcpState.lcpStart = ZIDLE;
- c_lcpState.lcpStopGcp = 0;
- c_lcpState.setLcpStatus(LCP_STATUS_IDLE, __LINE__);
- c_lcpState.currentFragment.tableId = 0;
- c_lcpState.currentFragment.fragmentId = 0;
- c_lcpState.noOfLcpFragRepOutstanding = 0;
- c_lcpState.keepGci = 0;
- c_lcpState.oldestRestorableGci = 0;
- c_lcpState.ctcCounter = 0;
- c_lcpState.ctimer = 0;
- c_lcpState.immediateLcpStart = false;
- c_lcpState.m_MASTER_LCPREQ_Received = false;
-
- cmasterdihref = 0;
- cmasterNodeId = 0;
- cmasterState = MASTER_IDLE;
- cmasterTakeOverNode = 0;
- cnewgcp = 0;
- cnoHotSpare = 0;
- cnoOfActiveTables = 0;
- cnoOfNodeGroups = 0;
- c_nextNodeGroup = 0;
- cnoReplicas = 0;
- coldgcp = 0;
- coldGcpId = 0;
- coldGcpStatus = cgcpStatus;
- con_lineNodes = 0;
- creceivedfrag = 0;
- crestartGci = 0;
- crestartInfoFile[0] = RNIL;
- crestartInfoFile[1] = RNIL;
- cstartGcpNow = false;
- cstartPhase = 0;
- c_startToLock = RNIL;
- cstarttype = (Uint32)-1;
- csystemnodes = 0;
- c_updateToLock = RNIL;
- currentgcp = 0;
- c_newest_restorable_gci = 0;
- cverifyQueueCounter = 0;
- cwaitLcpSr = false;
- c_nextLogPart = 0;
-
- nodeResetStart();
- c_nodeStartMaster.wait = ZFALSE;
-
- memset(&sysfileData[0], 0, sizeof(sysfileData));
-
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- c_lcpState.clcpDelay = 20;
- ndb_mgm_get_int_parameter(p, CFG_DB_LCP_INTERVAL, &c_lcpState.clcpDelay);
- c_lcpState.clcpDelay = c_lcpState.clcpDelay > 31 ? 31 : c_lcpState.clcpDelay;
-
- cminHotSpareNodes = 0;
- //ndb_mgm_get_int_parameter(p, CFG_DB_MIN_HOT_SPARES, &cminHotSpareNodes);
- cminHotSpareNodes = cminHotSpareNodes > 2 ? 2 : cminHotSpareNodes;
-
- cnoReplicas = 1;
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_REPLICAS, &cnoReplicas);
- if (cnoReplicas > 4)
- {
- progError(__LINE__, NDBD_EXIT_INVALID_CONFIG,
- "Only up to four replicas are supported. Check NoOfReplicas.");
- }
-
- cgcpDelay = 2000;
- ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &cgcpDelay);
- cgcpDelay = cgcpDelay > 60000 ? 60000 : (cgcpDelay < 10 ? 10 : cgcpDelay);
-}//Dbdih::initCommonData()
-
-void Dbdih::initFragstore(FragmentstorePtr fragPtr)
-{
- fragPtr.p->storedReplicas = RNIL;
- fragPtr.p->oldStoredReplicas = RNIL;
-
- fragPtr.p->noStoredReplicas = 0;
- fragPtr.p->noOldStoredReplicas = 0;
- fragPtr.p->fragReplicas = 0;
- fragPtr.p->preferredPrimary = 0;
-
- for (Uint32 i = 0; i < MAX_REPLICAS; i++)
- fragPtr.p->activeNodes[i] = 0;
-
- fragPtr.p->noLcpReplicas = 0;
- fragPtr.p->distributionKey = 0;
-}//Dbdih::initFragstore()
-
-/*************************************************************************/
-/* */
-/* MODULE: INIT_RESTART_INFO */
-/* DESCRIPTION: INITIATE RESTART INFO VARIABLE AND VARIABLES FOR */
-/* GLOBAL CHECKPOINTS. */
-/*************************************************************************/
-void Dbdih::initRestartInfo()
-{
- Uint32 i;
- for (i = 0; i < MAX_NDB_NODES; i++) {
- SYSFILE->lastCompletedGCI[i] = 0;
- }//for
- NodeRecordPtr nodePtr;
- nodePtr.i = cfirstAliveNode;
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- SYSFILE->lastCompletedGCI[nodePtr.i] = 1;
- /* FIRST GCP = 1 ALREADY SET BY LQH */
- nodePtr.i = nodePtr.p->nextNode;
- } while (nodePtr.i != RNIL);
- coldgcp = 1;
- currentgcp = 2;
- cnewgcp = 2;
- crestartGci = 1;
- c_newest_restorable_gci = 1;
-
- SYSFILE->keepGCI = 1;
- SYSFILE->oldestRestorableGCI = 1;
- SYSFILE->newestRestorableGCI = 1;
- SYSFILE->systemRestartBits = 0;
- for (i = 0; i < NodeBitmask::Size; i++) {
- SYSFILE->lcpActive[0] = 0;
- }//for
- for (i = 0; i < Sysfile::TAKE_OVER_SIZE; i++) {
- SYSFILE->takeOver[i] = 0;
- }//for
- Sysfile::setInitialStartOngoing(SYSFILE->systemRestartBits);
- srand(time(0));
- globalData.m_restart_seq = SYSFILE->m_restart_seq = 0;
-}//Dbdih::initRestartInfo()
-
-/*--------------------------------------------------------------------*/
-/* NODE GROUP BITS ARE INITIALISED BEFORE THIS. */
-/* NODE ACTIVE BITS ARE INITIALISED BEFORE THIS. */
-/*--------------------------------------------------------------------*/
-/*************************************************************************/
-/* */
-/* MODULE: INIT_RESTORABLE_GCI_FILES */
-/* DESCRIPTION: THE SUBROUTINE SETS UP THE FILES THAT REFERS TO THE*/
-/* FILES THAT KEEP THE VARIABLE CRESTART_INFO */
-/*************************************************************************/
-void Dbdih::initRestorableGciFiles()
-{
- Uint32 tirgTmp;
- FileRecordPtr filePtr;
- seizeFile(filePtr);
- filePtr.p->tabRef = RNIL;
- filePtr.p->fileType = FileRecord::GCP_FILE;
- filePtr.p->reqStatus = FileRecord::IDLE;
- filePtr.p->fileStatus = FileRecord::CLOSED;
- crestartInfoFile[0] = filePtr.i;
- filePtr.p->fileName[0] = (Uint32)-1; /* T DIRECTORY NOT USED */
- filePtr.p->fileName[1] = (Uint32)-1; /* F DIRECTORY NOT USED */
- filePtr.p->fileName[2] = (Uint32)-1; /* S PART IGNORED */
- tirgTmp = 1; /* FILE NAME VERSION 1 */
- tirgTmp = (tirgTmp << 8) + 6; /* .SYSFILE */
- tirgTmp = (tirgTmp << 8) + 1; /* D1 DIRECTORY */
- tirgTmp = (tirgTmp << 8) + 0; /* P0 FILE NAME */
- filePtr.p->fileName[3] = tirgTmp;
- /* --------------------------------------------------------------------- */
- /* THE NAME BECOMES /D1/DBDICT/S0.SYSFILE */
- /* --------------------------------------------------------------------- */
- seizeFile(filePtr);
- filePtr.p->tabRef = RNIL;
- filePtr.p->fileType = FileRecord::GCP_FILE;
- filePtr.p->reqStatus = FileRecord::IDLE;
- filePtr.p->fileStatus = FileRecord::CLOSED;
- crestartInfoFile[1] = filePtr.i;
- filePtr.p->fileName[0] = (Uint32)-1; /* T DIRECTORY NOT USED */
- filePtr.p->fileName[1] = (Uint32)-1; /* F DIRECTORY NOT USED */
- filePtr.p->fileName[2] = (Uint32)-1; /* S PART IGNORED */
- tirgTmp = 1; /* FILE NAME VERSION 1 */
- tirgTmp = (tirgTmp << 8) + 6; /* .SYSFILE */
- tirgTmp = (tirgTmp << 8) + 2; /* D1 DIRECTORY */
- tirgTmp = (tirgTmp << 8) + 0; /* P0 FILE NAME */
- filePtr.p->fileName[3] = tirgTmp;
- /* --------------------------------------------------------------------- */
- /* THE NAME BECOMES /D2/DBDICT/P0.SYSFILE */
- /* --------------------------------------------------------------------- */
-}//Dbdih::initRestorableGciFiles()
-
-void Dbdih::initTable(TabRecordPtr tabPtr)
-{
- tabPtr.p->noOfFragChunks = 0;
- tabPtr.p->method = TabRecord::NOTDEFINED;
- tabPtr.p->tabStatus = TabRecord::TS_IDLE;
- tabPtr.p->noOfWords = 0;
- tabPtr.p->noPages = 0;
- tabPtr.p->tabLcpStatus = TabRecord::TLS_COMPLETED;
- tabPtr.p->tabCopyStatus = TabRecord::CS_IDLE;
- tabPtr.p->tabUpdateState = TabRecord::US_IDLE;
- tabPtr.p->noOfBackups = 0;
- tabPtr.p->kvalue = 0;
- tabPtr.p->hashpointer = (Uint32)-1;
- tabPtr.p->mask = 0;
- tabPtr.p->tabStorage = TabRecord::ST_NORMAL;
- tabPtr.p->tabErrorCode = 0;
- tabPtr.p->schemaVersion = (Uint32)-1;
- tabPtr.p->tabRemoveNode = RNIL;
- tabPtr.p->totalfragments = (Uint32)-1;
- tabPtr.p->connectrec = RNIL;
- tabPtr.p->tabFile[0] = RNIL;
- tabPtr.p->tabFile[1] = RNIL;
- tabPtr.p->m_dropTab.tabUserRef = 0;
- tabPtr.p->m_dropTab.tabUserPtr = RNIL;
- Uint32 i;
- for (i = 0; i < MAX_NDB_NODES; i++) {
- tabPtr.p->startFid[i] = RNIL;
- }//for
- for (i = 0; i < 8; i++) {
- tabPtr.p->pageRef[i] = RNIL;
- }//for
- tabPtr.p->tableType = DictTabInfo::UndefTableType;
-}//Dbdih::initTable()
-
-/*************************************************************************/
-/* */
-/* MODULE: INIT_TABLE_FILES */
-/* DESCRIPTION: THE SUBROUTINE SETS UP THE FILES THAT REFERS TO THE*/
-/* FILES THAT KEEP THE TABLE FRAGMENTATION DESCRIPTION. */
-/*************************************************************************/
-void Dbdih::initTableFile(TabRecordPtr tabPtr)
-{
- Uint32 titfTmp;
- FileRecordPtr filePtr;
- seizeFile(filePtr);
- filePtr.p->tabRef = tabPtr.i;
- filePtr.p->fileType = FileRecord::TABLE_FILE;
- filePtr.p->reqStatus = FileRecord::IDLE;
- filePtr.p->fileStatus = FileRecord::CLOSED;
- tabPtr.p->tabFile[0] = filePtr.i;
- filePtr.p->fileName[0] = (Uint32)-1; /* T DIRECTORY NOT USED */
- filePtr.p->fileName[1] = (Uint32)-1; /* F DIRECTORY NOT USED */
- filePtr.p->fileName[2] = tabPtr.i; /* Stid FILE NAME */
- titfTmp = 1; /* FILE NAME VERSION 1 */
- titfTmp = (titfTmp << 8) + 3; /* .FRAGLIST */
- titfTmp = (titfTmp << 8) + 1; /* D1 DIRECTORY */
- titfTmp = (titfTmp << 8) + 255; /* P PART IGNORED */
- filePtr.p->fileName[3] = titfTmp;
- /* --------------------------------------------------------------------- */
- /* THE NAME BECOMES /D1/DBDICT/Stid.FRAGLIST */
- /* --------------------------------------------------------------------- */
- seizeFile(filePtr);
- filePtr.p->tabRef = tabPtr.i;
- filePtr.p->fileType = FileRecord::TABLE_FILE;
- filePtr.p->reqStatus = FileRecord::IDLE;
- filePtr.p->fileStatus = FileRecord::CLOSED;
- tabPtr.p->tabFile[1] = filePtr.i;
- filePtr.p->fileName[0] = (Uint32)-1; /* T DIRECTORY NOT USED */
- filePtr.p->fileName[1] = (Uint32)-1; /* F DIRECTORY NOT USED */
- filePtr.p->fileName[2] = tabPtr.i; /* Stid FILE NAME */
- titfTmp = 1; /* FILE NAME VERSION 1 */
- titfTmp = (titfTmp << 8) + 3; /* .FRAGLIST */
- titfTmp = (titfTmp << 8) + 2; /* D2 DIRECTORY */
- titfTmp = (titfTmp << 8) + 255; /* P PART IGNORED */
- filePtr.p->fileName[3] = titfTmp;
- /* --------------------------------------------------------------------- */
- /* THE NAME BECOMES /D2/DBDICT/Stid.FRAGLIST */
- /* --------------------------------------------------------------------- */
-}//Dbdih::initTableFile()
-
-void Dbdih::initialiseRecordsLab(Signal* signal,
- Uint32 stepNo, Uint32 retRef, Uint32 retData)
-{
- switch (stepNo) {
- case 0:
- jam();
- initCommonData();
- break;
- case 1:{
- ApiConnectRecordPtr apiConnectptr;
- jam();
- /******** INTIALIZING API CONNECT RECORDS ********/
- for (apiConnectptr.i = 0; apiConnectptr.i < capiConnectFileSize; apiConnectptr.i++) {
- refresh_watch_dog();
- ptrAss(apiConnectptr, apiConnectRecord);
- apiConnectptr.p->nextApi = RNIL;
- }//for
- jam();
- break;
- }
- case 2:{
- ConnectRecordPtr connectPtr;
- jam();
- /****** CONNECT ******/
- for (connectPtr.i = 0; connectPtr.i < cconnectFileSize; connectPtr.i++) {
- refresh_watch_dog();
- ptrAss(connectPtr, connectRecord);
- connectPtr.p->userpointer = RNIL;
- connectPtr.p->userblockref = ZNIL;
- connectPtr.p->connectState = ConnectRecord::FREE;
- connectPtr.p->table = RNIL;
- connectPtr.p->nfConnect = connectPtr.i + 1;
- }//for
- connectPtr.i = cconnectFileSize - 1;
- ptrAss(connectPtr, connectRecord);
- connectPtr.p->nfConnect = RNIL;
- cfirstconnect = 0;
- break;
- }
- case 3:
- {
- FileRecordPtr filePtr;
- jam();
- /******** INTIALIZING FILE RECORDS ********/
- for (filePtr.i = 0; filePtr.i < cfileFileSize; filePtr.i++) {
- ptrAss(filePtr, fileRecord);
- filePtr.p->nextFile = filePtr.i + 1;
- filePtr.p->fileStatus = FileRecord::CLOSED;
- filePtr.p->reqStatus = FileRecord::IDLE;
- }//for
- filePtr.i = cfileFileSize - 1;
- ptrAss(filePtr, fileRecord);
- filePtr.p->nextFile = RNIL;
- cfirstfreeFile = 0;
- initRestorableGciFiles();
- break;
- }
- case 4:
- jam();
- initialiseFragstore();
- break;
- case 5:
- {
- jam();
- /******* NODE GROUP RECORD ******/
- /******* NODE RECORD ******/
- NodeGroupRecordPtr loopNGPtr;
- for (loopNGPtr.i = 0; loopNGPtr.i < MAX_NDB_NODES; loopNGPtr.i++) {
- ptrAss(loopNGPtr, nodeGroupRecord);
- loopNGPtr.p->nodesInGroup[0] = RNIL;
- loopNGPtr.p->nodesInGroup[1] = RNIL;
- loopNGPtr.p->nodesInGroup[2] = RNIL;
- loopNGPtr.p->nodesInGroup[3] = RNIL;
- loopNGPtr.p->nextReplicaNode = 0;
- loopNGPtr.p->nodeCount = 0;
- loopNGPtr.p->activeTakeOver = false;
- }//for
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 0; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRecord);
- new (nodePtr.p) NodeRecord();
- }//for
- break;
- }
- case 6:
- {
- PageRecordPtr pagePtr;
- jam();
- /******* PAGE RECORD ******/
- for (pagePtr.i = 0; pagePtr.i < cpageFileSize; pagePtr.i++) {
- refresh_watch_dog();
- ptrAss(pagePtr, pageRecord);
- pagePtr.p->nextfreepage = pagePtr.i + 1;
- }//for
- pagePtr.i = cpageFileSize - 1;
- ptrAss(pagePtr, pageRecord);
- pagePtr.p->nextfreepage = RNIL;
- cfirstfreepage = 0;
- break;
- }
- case 7:
- {
- ReplicaRecordPtr initReplicaPtr;
- jam();
- /******* REPLICA RECORD ******/
- for (initReplicaPtr.i = 0; initReplicaPtr.i < creplicaFileSize;
- initReplicaPtr.i++) {
- refresh_watch_dog();
- ptrAss(initReplicaPtr, replicaRecord);
- initReplicaPtr.p->lcpIdStarted = 0;
- initReplicaPtr.p->lcpOngoingFlag = false;
- initReplicaPtr.p->nextReplica = initReplicaPtr.i + 1;
- }//for
- initReplicaPtr.i = creplicaFileSize - 1;
- ptrAss(initReplicaPtr, replicaRecord);
- initReplicaPtr.p->nextReplica = RNIL;
- cnoFreeReplicaRec = creplicaFileSize;
- cfirstfreeReplica = 0;
- break;
- }
- case 8:
- {
- TabRecordPtr loopTabptr;
- jam();
- /********* TAB-DESCRIPTOR ********/
- for (loopTabptr.i = 0; loopTabptr.i < ctabFileSize; loopTabptr.i++) {
- ptrAss(loopTabptr, tabRecord);
- refresh_watch_dog();
- initTable(loopTabptr);
- }//for
- break;
- }
- case 9:
- {
- TakeOverRecordPtr takeOverPtr;
- jam();
- cfirstfreeTakeOver = RNIL;
- for (takeOverPtr.i = 0; takeOverPtr.i < MAX_NDB_NODES; takeOverPtr.i++) {
- ptrAss(takeOverPtr, takeOverRecord);
- initTakeOver(takeOverPtr);
- releaseTakeOver(takeOverPtr.i);
- }//for
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = retData;
- sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
- return;
- break;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
- jam();
- /* ---------------------------------------------------------------------- */
- /* SEND REAL-TIME BREAK DURING INIT OF VARIABLES DURING SYSTEM RESTART. */
- /* ---------------------------------------------------------------------- */
- signal->theData[0] = DihContinueB::ZINITIALISE_RECORDS;
- signal->theData[1] = stepNo + 1;
- signal->theData[2] = retRef;
- signal->theData[3] = retData;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
-}//Dbdih::initialiseRecordsLab()
-
-/*************************************************************************/
-/* INSERT THE NODE INTO THE LINKED LIST OF NODES INVOLVED ALL */
-/* DISTRIBUTED PROTOCOLS (EXCEPT GCP PROTOCOL THAT USES THE DIH */
-/* LINKED LIST INSTEAD). */
-/*************************************************************************/
-void Dbdih::insertAlive(NodeRecordPtr newNodePtr)
-{
- NodeRecordPtr nodePtr;
-
- nodePtr.i = cfirstAliveNode;
- if (nodePtr.i == RNIL) {
- jam();
- cfirstAliveNode = newNodePtr.i;
- } else {
- do {
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->nextNode == RNIL) {
- jam();
- nodePtr.p->nextNode = newNodePtr.i;
- break;
- } else {
- jam();
- nodePtr.i = nodePtr.p->nextNode;
- }//if
- } while (1);
- }//if
- newNodePtr.p->nextNode = RNIL;
-}//Dbdih::insertAlive()
-
-void Dbdih::insertBackup(FragmentstorePtr fragPtr, Uint32 nodeId)
-{
- for (Uint32 i = fragPtr.p->fragReplicas; i > 1; i--) {
- jam();
- ndbrequire(i < MAX_REPLICAS && i > 0);
- fragPtr.p->activeNodes[i] = fragPtr.p->activeNodes[i - 1];
- }//for
- fragPtr.p->activeNodes[1] = nodeId;
- fragPtr.p->fragReplicas++;
-}//Dbdih::insertBackup()
-
-void Dbdih::insertDeadNode(NodeRecordPtr newNodePtr)
-{
- NodeRecordPtr nodePtr;
-
- nodePtr.i = cfirstDeadNode;
- if (nodePtr.i == RNIL) {
- jam();
- cfirstDeadNode = newNodePtr.i;
- } else {
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->nextNode == RNIL) {
- jam();
- nodePtr.p->nextNode = newNodePtr.i;
- break;
- } else {
- jam();
- nodePtr.i = nodePtr.p->nextNode;
- }//if
- } while (1);
- }//if
- newNodePtr.p->nextNode = RNIL;
-}//Dbdih::insertDeadNode()
-
-void Dbdih::linkOldStoredReplica(FragmentstorePtr fragPtr,
- ReplicaRecordPtr replicatePtr)
-{
- ReplicaRecordPtr losReplicaPtr;
-
- replicatePtr.p->nextReplica = RNIL;
- fragPtr.p->noOldStoredReplicas++;
- losReplicaPtr.i = fragPtr.p->oldStoredReplicas;
- if (losReplicaPtr.i == RNIL) {
- jam();
- fragPtr.p->oldStoredReplicas = replicatePtr.i;
- return;
- }//if
- ptrCheckGuard(losReplicaPtr, creplicaFileSize, replicaRecord);
- while (losReplicaPtr.p->nextReplica != RNIL) {
- jam();
- losReplicaPtr.i = losReplicaPtr.p->nextReplica;
- ptrCheckGuard(losReplicaPtr, creplicaFileSize, replicaRecord);
- }//if
- losReplicaPtr.p->nextReplica = replicatePtr.i;
-}//Dbdih::linkOldStoredReplica()
-
-void Dbdih::linkStoredReplica(FragmentstorePtr fragPtr,
- ReplicaRecordPtr replicatePtr)
-{
- ReplicaRecordPtr lsrReplicaPtr;
-
- fragPtr.p->noStoredReplicas++;
- replicatePtr.p->nextReplica = RNIL;
- lsrReplicaPtr.i = fragPtr.p->storedReplicas;
- if (fragPtr.p->storedReplicas == RNIL) {
- jam();
- fragPtr.p->storedReplicas = replicatePtr.i;
- return;
- }//if
- ptrCheckGuard(lsrReplicaPtr, creplicaFileSize, replicaRecord);
- while (lsrReplicaPtr.p->nextReplica != RNIL) {
- jam();
- lsrReplicaPtr.i = lsrReplicaPtr.p->nextReplica;
- ptrCheckGuard(lsrReplicaPtr, creplicaFileSize, replicaRecord);
- }//if
- lsrReplicaPtr.p->nextReplica = replicatePtr.i;
-}//Dbdih::linkStoredReplica()
-
-/*************************************************************************/
-/* MAKE NODE GROUPS BASED ON THE LIST OF NODES RECEIVED FROM CNTR */
-/*************************************************************************/
-void Dbdih::makeNodeGroups(Uint32 nodeArray[])
-{
- NodeRecordPtr mngNodeptr;
- Uint32 tmngNode;
- Uint32 tmngNodeGroup;
- Uint32 tmngLimit;
- Uint32 i, j;
-
- /**-----------------------------------------------------------------------
- * ASSIGN ALL ACTIVE NODES INTO NODE GROUPS. HOT SPARE NODES ARE ASSIGNED
- * TO NODE GROUP ZNIL
- *-----------------------------------------------------------------------*/
- tmngNodeGroup = 0;
- tmngLimit = csystemnodes - cnoHotSpare;
- ndbrequire(tmngLimit < MAX_NDB_NODES);
- for (i = 0; i < tmngLimit; i++) {
- NodeGroupRecordPtr NGPtr;
- jam();
- tmngNode = nodeArray[i];
- mngNodeptr.i = tmngNode;
- ptrCheckGuard(mngNodeptr, MAX_NDB_NODES, nodeRecord);
- mngNodeptr.p->nodeGroup = tmngNodeGroup;
- NGPtr.i = tmngNodeGroup;
- ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- arrGuard(NGPtr.p->nodeCount, MAX_REPLICAS);
- NGPtr.p->nodesInGroup[NGPtr.p->nodeCount++] = mngNodeptr.i;
- if (NGPtr.p->nodeCount == cnoReplicas) {
- jam();
- tmngNodeGroup++;
- }//if
- }//for
- cnoOfNodeGroups = tmngNodeGroup;
- ndbrequire(csystemnodes < MAX_NDB_NODES);
- for (i = tmngLimit + 1; i < csystemnodes; i++) {
- jam();
- tmngNode = nodeArray[i];
- mngNodeptr.i = tmngNode;
- ptrCheckGuard(mngNodeptr, MAX_NDB_NODES, nodeRecord);
- mngNodeptr.p->nodeGroup = ZNIL;
- }//for
- for(i = 0; i < MAX_NDB_NODES; i++){
- jam();
- Sysfile::setNodeGroup(i, SYSFILE->nodeGroups, NO_NODE_GROUP_ID);
- }//for
- for (mngNodeptr.i = 1; mngNodeptr.i < MAX_NDB_NODES; mngNodeptr.i++) {
- jam();
- ptrAss(mngNodeptr, nodeRecord);
- if (mngNodeptr.p->nodeGroup != ZNIL) {
- jam();
- 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_INSUFFICENT_NODES,
- buf);
-
- }
- }
-}//Dbdih::makeNodeGroups()
-
-/**
- * On node failure QMGR asks DIH about node groups. This is
- * a direct signal (function call in same process). Input is
- * bitmask of surviving nodes. The routine is not concerned
- * about node count. Reply is one of:
- * 1) win - we can survive, and nobody else can
- * 2) lose - we cannot survive
- * 3) partition - we can survive but there could be others
- */
-void Dbdih::execCHECKNODEGROUPSREQ(Signal* signal)
-{
- jamEntry();
- CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
-
- bool direct = (sd->requestType & CheckNodeGroups::Direct);
- bool ok = false;
- switch(sd->requestType & ~CheckNodeGroups::Direct){
- case CheckNodeGroups::ArbitCheck:{
- ok = true;
- jam();
- unsigned missall = 0;
- unsigned haveall = 0;
- for (Uint32 i = 0; i < cnoOfNodeGroups; i++) {
- jam();
- NodeGroupRecordPtr ngPtr;
- ngPtr.i = i;
- ptrAss(ngPtr, nodeGroupRecord);
- Uint32 count = 0;
- for (Uint32 j = 0; j < ngPtr.p->nodeCount; j++) {
- jam();
- Uint32 nodeId = ngPtr.p->nodesInGroup[j];
- if (sd->mask.get(nodeId)) {
- jam();
- count++;
- }//if
- }//for
- if (count == 0) {
- jam();
- missall++;
- }//if
- if (count == ngPtr.p->nodeCount) {
- haveall++;
- }//if
- }//for
-
- if (missall) {
- jam();
- sd->output = CheckNodeGroups::Lose;
- } else if (haveall) {
- jam();
- sd->output = CheckNodeGroups::Win;
- } else {
- jam();
- sd->output = CheckNodeGroups::Partitioning;
- }//if
- }
- break;
- case CheckNodeGroups::GetNodeGroup:
- ok = true;
- sd->output = Sysfile::getNodeGroup(getOwnNodeId(), SYSFILE->nodeGroups);
- break;
- case CheckNodeGroups::GetNodeGroupMembers: {
- ok = true;
- Uint32 ownNodeGroup =
- Sysfile::getNodeGroup(sd->nodeId, SYSFILE->nodeGroups);
-
- sd->output = ownNodeGroup;
- sd->mask.clear();
-
- NodeGroupRecordPtr ngPtr;
- ngPtr.i = ownNodeGroup;
- ptrAss(ngPtr, nodeGroupRecord);
- for (Uint32 j = 0; j < ngPtr.p->nodeCount; j++) {
- jam();
- sd->mask.set(ngPtr.p->nodesInGroup[j]);
- }
-#if 0
- for (int i = 0; i < MAX_NDB_NODES; i++) {
- if (ownNodeGroup ==
- Sysfile::getNodeGroup(i, SYSFILE->nodeGroups)) {
- sd->mask.set(i);
- }
- }
-#endif
- }
- break;
- }
- ndbrequire(ok);
-
- if (!direct)
- sendSignal(sd->blockRef, GSN_CHECKNODEGROUPSCONF, signal,
- CheckNodeGroups::SignalLength, JBB);
-}//Dbdih::execCHECKNODEGROUPSREQ()
-
-void Dbdih::makePrnList(ReadNodesConf * readNodes, Uint32 nodeArray[])
-{
- cfirstAliveNode = RNIL;
- ndbrequire(con_lineNodes > 0);
- ndbrequire(csystemnodes < MAX_NDB_NODES);
- for (Uint32 i = 0; i < csystemnodes; i++) {
- NodeRecordPtr nodePtr;
- jam();
- nodePtr.i = nodeArray[i];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- new (nodePtr.p) NodeRecord();
- if (NodeBitmask::get(readNodes->inactiveNodes, nodePtr.i) == false){
- jam();
- nodePtr.p->nodeStatus = NodeRecord::ALIVE;
- nodePtr.p->useInTransactions = true;
- nodePtr.p->copyCompleted = true;
- nodePtr.p->m_inclDihLcp = true;
- insertAlive(nodePtr);
- } else {
- jam();
- nodePtr.p->nodeStatus = NodeRecord::DEAD;
- insertDeadNode(nodePtr);
- }//if
- }//for
-}//Dbdih::makePrnList()
-
-/*************************************************************************/
-/* A NEW CRASHED REPLICA IS ADDED BY A NODE FAILURE. */
-/*************************************************************************/
-void Dbdih::newCrashedReplica(Uint32 nodeId, ReplicaRecordPtr ncrReplicaPtr)
-{
- /*----------------------------------------------------------------------*/
- /* SET THE REPLICA_LAST_GCI OF THE CRASHED REPLICA TO LAST GCI */
- /* EXECUTED BY THE FAILED NODE. */
- /*----------------------------------------------------------------------*/
- /* WE HAVE A NEW CRASHED REPLICA. INITIATE CREATE GCI TO INDICATE */
- /* THAT THE NEW REPLICA IS NOT STARTED YET AND REPLICA_LAST_GCI IS*/
- /* SET TO -1 TO INDICATE THAT IT IS NOT DEAD YET. */
- /*----------------------------------------------------------------------*/
- Uint32 lastGCI = SYSFILE->lastCompletedGCI[nodeId];
- arrGuardErr(ncrReplicaPtr.p->noCrashedReplicas + 1, 8,
- NDBD_EXIT_MAX_CRASHED_REPLICAS);
- ncrReplicaPtr.p->replicaLastGci[ncrReplicaPtr.p->noCrashedReplicas] =
- lastGCI;
- ncrReplicaPtr.p->noCrashedReplicas = ncrReplicaPtr.p->noCrashedReplicas + 1;
- ncrReplicaPtr.p->createGci[ncrReplicaPtr.p->noCrashedReplicas] = 0;
- ncrReplicaPtr.p->replicaLastGci[ncrReplicaPtr.p->noCrashedReplicas] =
- (Uint32)-1;
-
- if (ncrReplicaPtr.p->noCrashedReplicas == 7 && lastGCI)
- {
- jam();
- SYSFILE->lastCompletedGCI[nodeId] = 0;
- warningEvent("Making filesystem for node %d unusable (need --initial)",
- nodeId);
- }
-}//Dbdih::newCrashedReplica()
-
-/*************************************************************************/
-/* AT NODE FAILURE DURING START OF A NEW NODE WE NEED TO RESET A */
-/* SET OF VARIABLES CONTROLLING THE START AND INDICATING ONGOING */
-/* START OF A NEW NODE. */
-/*************************************************************************/
-void Dbdih::nodeResetStart()
-{
- jam();
- c_nodeStartSlave.nodeId = 0;
- c_nodeStartMaster.startNode = RNIL;
- c_nodeStartMaster.failNr = cfailurenr;
- c_nodeStartMaster.activeState = false;
- c_nodeStartMaster.blockGcp = false;
- c_nodeStartMaster.blockLcp = false;
- c_nodeStartMaster.m_outstandingGsn = 0;
-}//Dbdih::nodeResetStart()
-
-void Dbdih::openFileRw(Signal* signal, FileRecordPtr filePtr)
-{
- signal->theData[0] = reference();
- signal->theData[1] = filePtr.i;
- signal->theData[2] = filePtr.p->fileName[0];
- signal->theData[3] = filePtr.p->fileName[1];
- signal->theData[4] = filePtr.p->fileName[2];
- signal->theData[5] = filePtr.p->fileName[3];
- signal->theData[6] = FsOpenReq::OM_READWRITE;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
-}//Dbdih::openFileRw()
-
-void Dbdih::openFileRo(Signal* signal, FileRecordPtr filePtr)
-{
- signal->theData[0] = reference();
- signal->theData[1] = filePtr.i;
- signal->theData[2] = filePtr.p->fileName[0];
- signal->theData[3] = filePtr.p->fileName[1];
- signal->theData[4] = filePtr.p->fileName[2];
- signal->theData[5] = filePtr.p->fileName[3];
- signal->theData[6] = FsOpenReq::OM_READONLY;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
-}//Dbdih::openFileRw()
-
-/*************************************************************************/
-/* REMOVE A CRASHED REPLICA BY PACKING THE ARRAY OF CREATED GCI AND*/
-/* THE LAST GCI OF THE CRASHED REPLICA. */
-/*************************************************************************/
-void Dbdih::packCrashedReplicas(ReplicaRecordPtr replicaPtr)
-{
- ndbrequire(replicaPtr.p->noCrashedReplicas > 0);
- ndbrequire(replicaPtr.p->noCrashedReplicas <= 8);
- for (Uint32 i = 0; i < replicaPtr.p->noCrashedReplicas; i++) {
- jam();
- replicaPtr.p->createGci[i] = replicaPtr.p->createGci[i + 1];
- replicaPtr.p->replicaLastGci[i] = replicaPtr.p->replicaLastGci[i + 1];
- }//for
- replicaPtr.p->noCrashedReplicas--;
-
-#ifdef VM_TRACE
- for (Uint32 i = 0; i < replicaPtr.p->noCrashedReplicas; i++) {
- jam();
- ndbrequire(replicaPtr.p->createGci[i] != 0xF1F1F1F1);
- ndbrequire(replicaPtr.p->replicaLastGci[i] != 0xF1F1F1F1);
- }//for
-#endif
-}//Dbdih::packCrashedReplicas()
-
-void Dbdih::prepareReplicas(FragmentstorePtr fragPtr)
-{
- ReplicaRecordPtr prReplicaPtr;
- Uint32 prevReplica = RNIL;
-
- /* --------------------------------------------------------------------- */
- /* BEGIN BY LINKING ALL REPLICA RECORDS ONTO THE OLD STORED REPLICA*/
- /* LIST. */
- /* AT A SYSTEM RESTART OBVIOUSLY ALL NODES ARE OLD. */
- /* --------------------------------------------------------------------- */
- prReplicaPtr.i = fragPtr.p->storedReplicas;
- while (prReplicaPtr.i != RNIL) {
- jam();
- prevReplica = prReplicaPtr.i;
- ptrCheckGuard(prReplicaPtr, creplicaFileSize, replicaRecord);
- prReplicaPtr.i = prReplicaPtr.p->nextReplica;
- }//while
- /* --------------------------------------------------------------------- */
- /* LIST OF STORED REPLICAS WILL BE EMPTY NOW. */
- /* --------------------------------------------------------------------- */
- if (prevReplica != RNIL) {
- prReplicaPtr.i = prevReplica;
- ptrCheckGuard(prReplicaPtr, creplicaFileSize, replicaRecord);
- prReplicaPtr.p->nextReplica = fragPtr.p->oldStoredReplicas;
- fragPtr.p->oldStoredReplicas = fragPtr.p->storedReplicas;
- fragPtr.p->storedReplicas = RNIL;
- fragPtr.p->noOldStoredReplicas += fragPtr.p->noStoredReplicas;
- fragPtr.p->noStoredReplicas = 0;
- }//if
-}//Dbdih::prepareReplicas()
-
-void Dbdih::readFragment(RWFragment* rf, FragmentstorePtr fragPtr)
-{
- Uint32 TreadFid = readPageWord(rf);
- fragPtr.p->preferredPrimary = readPageWord(rf);
- fragPtr.p->noStoredReplicas = readPageWord(rf);
- fragPtr.p->noOldStoredReplicas = readPageWord(rf);
- Uint32 TdistKey = readPageWord(rf);
-
- ndbrequire(fragPtr.p->noStoredReplicas > 0);
- ndbrequire(TreadFid == rf->fragId);
- ndbrequire(TdistKey < 256);
- if ((cstarttype == NodeState::ST_NODE_RESTART) ||
- (cstarttype == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- fragPtr.p->distributionKey = TdistKey;
- }//if
-
- fragPtr.p->m_log_part_id = readPageWord(rf);
-}//Dbdih::readFragment()
-
-Uint32 Dbdih::readPageWord(RWFragment* rf)
-{
- if (rf->wordIndex >= 2048) {
- jam();
- ndbrequire(rf->wordIndex == 2048);
- rf->pageIndex++;
- ndbrequire(rf->pageIndex < 8);
- rf->rwfPageptr.i = rf->rwfTabPtr.p->pageRef[rf->pageIndex];
- ptrCheckGuard(rf->rwfPageptr, cpageFileSize, pageRecord);
- rf->wordIndex = 32;
- }//if
- Uint32 dataWord = rf->rwfPageptr.p->word[rf->wordIndex];
- rf->wordIndex++;
- return dataWord;
-}//Dbdih::readPageWord()
-
-void Dbdih::readReplica(RWFragment* rf, ReplicaRecordPtr readReplicaPtr)
-{
- Uint32 i;
- readReplicaPtr.p->procNode = readPageWord(rf);
- readReplicaPtr.p->initialGci = readPageWord(rf);
- readReplicaPtr.p->noCrashedReplicas = readPageWord(rf);
- readReplicaPtr.p->nextLcp = readPageWord(rf);
-
- for (i = 0; i < MAX_LCP_STORED; i++) {
- readReplicaPtr.p->maxGciCompleted[i] = readPageWord(rf);
- readReplicaPtr.p->maxGciStarted[i] = readPageWord(rf);
- readReplicaPtr.p->lcpId[i] = readPageWord(rf);
- readReplicaPtr.p->lcpStatus[i] = readPageWord(rf);
- }//for
- const Uint32 noCrashedReplicas = readReplicaPtr.p->noCrashedReplicas;
- ndbrequire(noCrashedReplicas < 8);
- for (i = 0; i < noCrashedReplicas; i++) {
- readReplicaPtr.p->createGci[i] = readPageWord(rf);
- readReplicaPtr.p->replicaLastGci[i] = readPageWord(rf);
- ndbrequire(readReplicaPtr.p->createGci[i] != 0xF1F1F1F1);
- ndbrequire(readReplicaPtr.p->replicaLastGci[i] != 0xF1F1F1F1);
- }//for
- for(i = noCrashedReplicas; i<8; i++){
- readReplicaPtr.p->createGci[i] = readPageWord(rf);
- readReplicaPtr.p->replicaLastGci[i] = readPageWord(rf);
- // They are not initialized...
- readReplicaPtr.p->createGci[i] = 0;
- readReplicaPtr.p->replicaLastGci[i] = ~0;
- }
- /* ---------------------------------------------------------------------- */
- /* IF THE LAST COMPLETED LOCAL CHECKPOINT IS VALID AND LARGER THAN */
- /* THE LAST COMPLETED CHECKPOINT THEN WE WILL INVALIDATE THIS LOCAL */
- /* CHECKPOINT FOR THIS REPLICA. */
- /* ---------------------------------------------------------------------- */
- Uint32 trraLcp = prevLcpNo(readReplicaPtr.p->nextLcp);
- ndbrequire(trraLcp < MAX_LCP_STORED);
- if ((readReplicaPtr.p->lcpStatus[trraLcp] == ZVALID) &&
- (readReplicaPtr.p->lcpId[trraLcp] > SYSFILE->latestLCP_ID)) {
- jam();
- readReplicaPtr.p->lcpStatus[trraLcp] = ZINVALID;
- }//if
- /* ---------------------------------------------------------------------- */
- /* WE ALSO HAVE TO INVALIDATE ANY LOCAL CHECKPOINTS THAT HAVE BEEN */
- /* INVALIDATED BY MOVING BACK THE RESTART GCI. */
- /* ---------------------------------------------------------------------- */
- for (i = 0; i < MAX_LCP_STORED; i++) {
- jam();
- if ((readReplicaPtr.p->lcpStatus[i] == ZVALID) &&
- (readReplicaPtr.p->maxGciStarted[i] > SYSFILE->newestRestorableGCI)) {
- jam();
- readReplicaPtr.p->lcpStatus[i] = ZINVALID;
- }//if
- }//for
- /* ---------------------------------------------------------------------- */
- /* WE WILL REMOVE ANY OCCURRENCES OF REPLICAS THAT HAVE CRASHED */
- /* THAT ARE NO LONGER VALID DUE TO MOVING RESTART GCI BACKWARDS. */
- /* ---------------------------------------------------------------------- */
- removeTooNewCrashedReplicas(readReplicaPtr);
- /* ---------------------------------------------------------------------- */
- /* WE WILL REMOVE ANY OCCURRENCES OF REPLICAS THAT HAVE CRASHED */
- /* THAT ARE NO LONGER VALID SINCE THEY ARE NO LONGER RESTORABLE. */
- /* ---------------------------------------------------------------------- */
- removeOldCrashedReplicas(readReplicaPtr);
- /* --------------------------------------------------------------------- */
- // We set the last GCI of the replica that was alive before the node
- // crashed last time. We set it to the last GCI which the node participated in.
- /* --------------------------------------------------------------------- */
- ndbrequire(readReplicaPtr.p->noCrashedReplicas < 8);
- readReplicaPtr.p->replicaLastGci[readReplicaPtr.p->noCrashedReplicas] =
- SYSFILE->lastCompletedGCI[readReplicaPtr.p->procNode];
- /* ---------------------------------------------------------------------- */
- /* FIND PROCESSOR RECORD */
- /* ---------------------------------------------------------------------- */
-}//Dbdih::readReplica()
-
-void Dbdih::readReplicas(RWFragment* rf, FragmentstorePtr fragPtr)
-{
- Uint32 i;
- ReplicaRecordPtr newReplicaPtr;
- Uint32 noStoredReplicas = fragPtr.p->noStoredReplicas;
- Uint32 noOldStoredReplicas = fragPtr.p->noOldStoredReplicas;
- /* ----------------------------------------------------------------------- */
- /* WE CLEAR THE NUMBER OF STORED REPLICAS SINCE IT WILL BE CALCULATED */
- /* BY THE LINKING SUBROUTINES. */
- /* ----------------------------------------------------------------------- */
- fragPtr.p->noStoredReplicas = 0;
- fragPtr.p->noOldStoredReplicas = 0;
- Uint32 replicaIndex = 0;
- ndbrequire(noStoredReplicas + noOldStoredReplicas <= MAX_REPLICAS);
- for (i = 0; i < noStoredReplicas; i++) {
- seizeReplicaRec(newReplicaPtr);
- readReplica(rf, newReplicaPtr);
- if (checkNodeAlive(newReplicaPtr.p->procNode)) {
- jam();
- ndbrequire(replicaIndex < MAX_REPLICAS);
- fragPtr.p->activeNodes[replicaIndex] = newReplicaPtr.p->procNode;
- replicaIndex++;
- linkStoredReplica(fragPtr, newReplicaPtr);
- } else {
- jam();
- linkOldStoredReplica(fragPtr, newReplicaPtr);
- }//if
- }//for
- fragPtr.p->fragReplicas = noStoredReplicas;
- for (i = 0; i < noOldStoredReplicas; i++) {
- jam();
- seizeReplicaRec(newReplicaPtr);
- readReplica(rf, newReplicaPtr);
- linkOldStoredReplica(fragPtr, newReplicaPtr);
- }//for
-}//Dbdih::readReplicas()
-
-void Dbdih::readRestorableGci(Signal* signal, FileRecordPtr filePtr)
-{
- signal->theData[0] = filePtr.p->fileRef;
- signal->theData[1] = reference();
- signal->theData[2] = filePtr.i;
- signal->theData[3] = ZLIST_OF_PAIRS;
- signal->theData[4] = ZVAR_NO_CRESTART_INFO;
- signal->theData[5] = 1;
- signal->theData[6] = 0;
- signal->theData[7] = 0;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
-}//Dbdih::readRestorableGci()
-
-void Dbdih::readTabfile(Signal* signal, TabRecord* tab, FileRecordPtr filePtr)
-{
- signal->theData[0] = filePtr.p->fileRef;
- signal->theData[1] = reference();
- signal->theData[2] = filePtr.i;
- signal->theData[3] = ZLIST_OF_PAIRS;
- signal->theData[4] = ZVAR_NO_WORD;
- signal->theData[5] = tab->noPages;
- for (Uint32 i = 0; i < tab->noPages; i++) {
- signal->theData[6 + (2 * i)] = tab->pageRef[i];
- signal->theData[7 + (2 * i)] = i;
- }//for
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 22, JBA);
-}//Dbdih::readTabfile()
-
-void Dbdih::releasePage(Uint32 pageIndex)
-{
- PageRecordPtr pagePtr;
- pagePtr.i = pageIndex;
- ptrCheckGuard(pagePtr, cpageFileSize, pageRecord);
- pagePtr.p->nextfreepage = cfirstfreepage;
- cfirstfreepage = pagePtr.i;
-}//Dbdih::releasePage()
-
-void Dbdih::releaseTabPages(Uint32 tableId)
-{
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
- ndbrequire(tabPtr.p->noPages <= 8);
- for (Uint32 i = 0; i < tabPtr.p->noPages; i++) {
- jam();
- releasePage(tabPtr.p->pageRef[i]);
- }//for
- tabPtr.p->noPages = 0;
-}//Dbdih::releaseTabPages()
-
-/*************************************************************************/
-/* REMOVE NODE FROM SET OF ALIVE NODES. */
-/*************************************************************************/
-void Dbdih::removeAlive(NodeRecordPtr removeNodePtr)
-{
- NodeRecordPtr nodePtr;
-
- nodePtr.i = cfirstAliveNode;
- if (nodePtr.i == removeNodePtr.i) {
- jam();
- cfirstAliveNode = removeNodePtr.p->nextNode;
- return;
- }//if
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->nextNode == removeNodePtr.i) {
- jam();
- nodePtr.p->nextNode = removeNodePtr.p->nextNode;
- break;
- } else {
- jam();
- nodePtr.i = nodePtr.p->nextNode;
- }//if
- } while (1);
-}//Dbdih::removeAlive()
-
-/*************************************************************************/
-/* REMOVE NODE FROM SET OF DEAD NODES. */
-/*************************************************************************/
-void Dbdih::removeDeadNode(NodeRecordPtr removeNodePtr)
-{
- NodeRecordPtr nodePtr;
-
- nodePtr.i = cfirstDeadNode;
- if (nodePtr.i == removeNodePtr.i) {
- jam();
- cfirstDeadNode = removeNodePtr.p->nextNode;
- return;
- }//if
- do {
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->nextNode == removeNodePtr.i) {
- jam();
- nodePtr.p->nextNode = removeNodePtr.p->nextNode;
- break;
- } else {
- jam();
- nodePtr.i = nodePtr.p->nextNode;
- }//if
- } while (1);
-}//Dbdih::removeDeadNode()
-
-/*---------------------------------------------------------------*/
-/* REMOVE REPLICAS OF A FAILED NODE FROM LIST OF STORED */
-/* REPLICAS AND MOVE IT TO THE LIST OF OLD STORED REPLICAS.*/
-/* ALSO UPDATE THE CRASHED REPLICA INFORMATION. */
-/*---------------------------------------------------------------*/
-void Dbdih::removeNodeFromStored(Uint32 nodeId,
- FragmentstorePtr fragPtr,
- ReplicaRecordPtr replicatePtr,
- bool temporary)
-{
- if (!temporary)
- {
- jam();
- newCrashedReplica(nodeId, replicatePtr);
- }
- else
- {
- jam();
- }
- removeStoredReplica(fragPtr, replicatePtr);
- linkOldStoredReplica(fragPtr, replicatePtr);
- ndbrequire(fragPtr.p->storedReplicas != RNIL);
-}//Dbdih::removeNodeFromStored()
-
-/*************************************************************************/
-/* REMOVE ANY OLD CRASHED REPLICAS THAT ARE NOT RESTORABLE ANY MORE*/
-/*************************************************************************/
-void Dbdih::removeOldCrashedReplicas(ReplicaRecordPtr rocReplicaPtr)
-{
- while (rocReplicaPtr.p->noCrashedReplicas > 0) {
- jam();
- /* --------------------------------------------------------------------- */
- /* ONLY IF THERE IS AT LEAST ONE REPLICA THEN CAN WE REMOVE ANY. */
- /* --------------------------------------------------------------------- */
- if (rocReplicaPtr.p->replicaLastGci[0] < SYSFILE->oldestRestorableGCI){
- jam();
- /* ------------------------------------------------------------------- */
- /* THIS CRASHED REPLICA HAS BECOME EXTINCT AND MUST BE REMOVED TO */
- /* GIVE SPACE FOR NEW CRASHED REPLICAS. */
- /* ------------------------------------------------------------------- */
- packCrashedReplicas(rocReplicaPtr);
- } else {
- break;
- }//if
- }//while
- if (rocReplicaPtr.p->createGci[0] < SYSFILE->keepGCI){
- jam();
- /* --------------------------------------------------------------------- */
- /* MOVE FORWARD THE CREATE GCI TO A GCI THAT CAN BE USED. WE HAVE */
- /* NO CERTAINTY IN FINDING ANY LOG RECORDS FROM OLDER GCI'S. */
- /* --------------------------------------------------------------------- */
- rocReplicaPtr.p->createGci[0] = SYSFILE->keepGCI;
- ndbrequire(SYSFILE->keepGCI != 0xF1F1F1F1);
- }//if
-}//Dbdih::removeOldCrashedReplicas()
-
-void Dbdih::removeOldStoredReplica(FragmentstorePtr fragPtr,
- ReplicaRecordPtr replicatePtr)
-{
- ReplicaRecordPtr rosTmpReplicaPtr;
- ReplicaRecordPtr rosPrevReplicaPtr;
-
- fragPtr.p->noOldStoredReplicas--;
- if (fragPtr.p->oldStoredReplicas == replicatePtr.i) {
- jam();
- fragPtr.p->oldStoredReplicas = replicatePtr.p->nextReplica;
- } else {
- rosPrevReplicaPtr.i = fragPtr.p->oldStoredReplicas;
- ptrCheckGuard(rosPrevReplicaPtr, creplicaFileSize, replicaRecord);
- rosTmpReplicaPtr.i = rosPrevReplicaPtr.p->nextReplica;
- while (rosTmpReplicaPtr.i != replicatePtr.i) {
- jam();
- rosPrevReplicaPtr.i = rosTmpReplicaPtr.i;
- ptrCheckGuard(rosPrevReplicaPtr, creplicaFileSize, replicaRecord);
- ptrCheckGuard(rosTmpReplicaPtr, creplicaFileSize, replicaRecord);
- rosTmpReplicaPtr.i = rosTmpReplicaPtr.p->nextReplica;
- }//if
- rosPrevReplicaPtr.p->nextReplica = replicatePtr.p->nextReplica;
- }//if
-}//Dbdih::removeOldStoredReplica()
-
-void Dbdih::removeStoredReplica(FragmentstorePtr fragPtr,
- ReplicaRecordPtr replicatePtr)
-{
- ReplicaRecordPtr rsrTmpReplicaPtr;
- ReplicaRecordPtr rsrPrevReplicaPtr;
-
- fragPtr.p->noStoredReplicas--;
- if (fragPtr.p->storedReplicas == replicatePtr.i) {
- jam();
- fragPtr.p->storedReplicas = replicatePtr.p->nextReplica;
- } else {
- jam();
- rsrPrevReplicaPtr.i = fragPtr.p->storedReplicas;
- rsrTmpReplicaPtr.i = fragPtr.p->storedReplicas;
- ptrCheckGuard(rsrTmpReplicaPtr, creplicaFileSize, replicaRecord);
- rsrTmpReplicaPtr.i = rsrTmpReplicaPtr.p->nextReplica;
- while (rsrTmpReplicaPtr.i != replicatePtr.i) {
- jam();
- rsrPrevReplicaPtr.i = rsrTmpReplicaPtr.i;
- ptrCheckGuard(rsrTmpReplicaPtr, creplicaFileSize, replicaRecord);
- rsrTmpReplicaPtr.i = rsrTmpReplicaPtr.p->nextReplica;
- }//while
- ptrCheckGuard(rsrPrevReplicaPtr, creplicaFileSize, replicaRecord);
- rsrPrevReplicaPtr.p->nextReplica = replicatePtr.p->nextReplica;
- }//if
-}//Dbdih::removeStoredReplica()
-
-/*************************************************************************/
-/* REMOVE ALL TOO NEW CRASHED REPLICAS THAT IS IN THIS REPLICA. */
-/*************************************************************************/
-void Dbdih::removeTooNewCrashedReplicas(ReplicaRecordPtr rtnReplicaPtr)
-{
- while (rtnReplicaPtr.p->noCrashedReplicas > 0) {
- jam();
- /* --------------------------------------------------------------------- */
- /* REMOVE ALL REPLICAS THAT ONLY LIVED IN A PERIOD THAT HAVE BEEN */
- /* REMOVED FROM THE RESTART INFORMATION SINCE THE RESTART FAILED */
- /* TOO MANY TIMES. */
- /* --------------------------------------------------------------------- */
- arrGuard(rtnReplicaPtr.p->noCrashedReplicas - 1, 8);
- if (rtnReplicaPtr.p->createGci[rtnReplicaPtr.p->noCrashedReplicas - 1] >
- SYSFILE->newestRestorableGCI){
- jam();
- rtnReplicaPtr.p->createGci[rtnReplicaPtr.p->noCrashedReplicas - 1] =
- (Uint32)-1;
- rtnReplicaPtr.p->replicaLastGci[rtnReplicaPtr.p->noCrashedReplicas - 1] =
- (Uint32)-1;
- rtnReplicaPtr.p->noCrashedReplicas--;
- } else {
- break;
- }//if
- }//while
-}//Dbdih::removeTooNewCrashedReplicas()
-
-/*************************************************************************/
-/* */
-/* MODULE: SEARCH FOR POSSIBLE REPLICAS THAT CAN HANDLE THE GLOBAL */
-/* CHECKPOINT WITHOUT NEEDING ANY EXTRA LOGGING FACILITIES.*/
-/* A MAXIMUM OF FOUR NODES IS RETRIEVED. */
-/*************************************************************************/
-bool
-Dbdih::setup_create_replica(FragmentstorePtr fragPtr,
- CreateReplicaRecord* createReplicaPtrP,
- ConstPtr<ReplicaRecord> replicaPtr)
-{
- createReplicaPtrP->dataNodeId = replicaPtr.p->procNode;
- createReplicaPtrP->replicaRec = replicaPtr.i;
-
- /* ----------------------------------------------------------------- */
- /* WE NEED TO SEARCH FOR A PROPER LOCAL CHECKPOINT TO USE FOR THE */
- /* SYSTEM RESTART. */
- /* ----------------------------------------------------------------- */
- Uint32 startGci;
- Uint32 startLcpNo;
- Uint32 stopGci = SYSFILE->newestRestorableGCI;
- bool result = findStartGci(replicaPtr,
- stopGci,
- startGci,
- startLcpNo);
- if (!result)
- {
- jam();
- /* --------------------------------------------------------------- */
- /* WE COULD NOT FIND ANY LOCAL CHECKPOINT. THE FRAGMENT THUS DO NOT*/
- /* CONTAIN ANY VALID LOCAL CHECKPOINT. IT DOES HOWEVER CONTAIN A */
- /* VALID FRAGMENT LOG. THUS BY FIRST CREATING THE FRAGMENT AND THEN*/
- /* EXECUTING THE FRAGMENT LOG WE CAN CREATE THE FRAGMENT AS */
- /* DESIRED. THIS SHOULD ONLY OCCUR AFTER CREATING A FRAGMENT. */
- /* */
- /* TO INDICATE THAT NO LOCAL CHECKPOINT IS TO BE USED WE SET THE */
- /* LOCAL CHECKPOINT TO ZNIL. */
- /* --------------------------------------------------------------- */
- createReplicaPtrP->lcpNo = ZNIL;
- }
- else
- {
- jam();
- /* --------------------------------------------------------------- */
- /* WE FOUND A PROPER LOCAL CHECKPOINT TO RESTART FROM. */
- /* SET LOCAL CHECKPOINT ID AND LOCAL CHECKPOINT NUMBER. */
- /* --------------------------------------------------------------- */
- createReplicaPtrP->lcpNo = startLcpNo;
- arrGuard(startLcpNo, MAX_LCP_STORED);
- createReplicaPtrP->createLcpId = replicaPtr.p->lcpId[startLcpNo];
- }//if
-
-
- /* ----------------------------------------------------------------- */
- /* WE HAVE EITHER FOUND A LOCAL CHECKPOINT OR WE ARE PLANNING TO */
- /* EXECUTE THE LOG FROM THE INITIAL CREATION OF THE TABLE. IN BOTH */
- /* CASES WE NEED TO FIND A SET OF LOGS THAT CAN EXECUTE SUCH THAT */
- /* WE RECOVER TO THE SYSTEM RESTART GLOBAL CHECKPOINT. */
- /* -_--------------------------------------------------------------- */
- return findLogNodes(createReplicaPtrP, fragPtr, startGci, stopGci);
-}
-
-void Dbdih::searchStoredReplicas(FragmentstorePtr fragPtr)
-{
- Uint32 nextReplicaPtrI;
- Ptr<ReplicaRecord> replicaPtr;
-
- replicaPtr.i = fragPtr.p->storedReplicas;
- while (replicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- nextReplicaPtrI = replicaPtr.p->nextReplica;
- ConstPtr<ReplicaRecord> constReplicaPtr;
- constReplicaPtr.i = replicaPtr.i;
- constReplicaPtr.p = replicaPtr.p;
- NodeRecordPtr nodePtr;
- nodePtr.i = replicaPtr.p->procNode;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) {
- jam();
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- case Sysfile::NS_ActiveMissed_2:{
- /* ----------------------------------------------------------------- */
- /* INITIALISE THE CREATE REPLICA STRUCTURE THAT IS USED FOR SENDING*/
- /* TO LQH START_FRAGREQ. */
- /* SET THE DATA NODE WHERE THE LOCAL CHECKPOINT IS FOUND. ALSO */
- /* SET A REFERENCE TO THE REPLICA POINTER OF THAT. */
- /* ----------------------------------------------------------------- */
- CreateReplicaRecordPtr createReplicaPtr;
- createReplicaPtr.i = cnoOfCreateReplicas;
- ptrCheckGuard(createReplicaPtr, 4, createReplicaRecord);
- cnoOfCreateReplicas++;
-
- /**
- * Should have been checked in resetReplicaSr
- */
- ndbrequire(setup_create_replica(fragPtr,
- createReplicaPtr.p,
- constReplicaPtr));
- break;
- }
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- }
- replicaPtr.i = nextReplicaPtrI;
- }//while
-}//Dbdih::searchStoredReplicas()
-
-/*************************************************************************/
-/* */
-/* MODULE: SEIZE_FILE */
-/* DESCRIPTION: THE SUBROUTINE SEIZES A FILE RECORD FROM THE */
-/* FREE LIST. */
-/*************************************************************************/
-void Dbdih::seizeFile(FileRecordPtr& filePtr)
-{
- filePtr.i = cfirstfreeFile;
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- cfirstfreeFile = filePtr.p->nextFile;
- filePtr.p->nextFile = RNIL;
-}//Dbdih::seizeFile()
-
-/*************************************************************************/
-/* SEND CREATE_FRAGREQ TO ALL NODES IN THE NDB CLUSTER. */
-/*************************************************************************/
-/*************************************************************************/
-/* */
-/* MODULE: FIND THE START GCI AND LOCAL CHECKPOINT TO USE. */
-/*************************************************************************/
-void Dbdih::sendStartFragreq(Signal* signal,
- TabRecordPtr tabPtr, Uint32 fragId)
-{
- CreateReplicaRecordPtr replicaPtr;
- for (replicaPtr.i = 0; replicaPtr.i < cnoOfCreateReplicas; replicaPtr.i++) {
- jam();
- ptrAss(replicaPtr, createReplicaRecord);
- BlockReference ref = calcLqhBlockRef(replicaPtr.p->dataNodeId);
- StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
- startFragReq->userPtr = replicaPtr.p->replicaRec;
- startFragReq->userRef = reference();
- startFragReq->lcpNo = replicaPtr.p->lcpNo;
- startFragReq->lcpId = replicaPtr.p->createLcpId;
- startFragReq->tableId = tabPtr.i;
- startFragReq->fragId = fragId;
-
- if(ERROR_INSERTED(7072) || ERROR_INSERTED(7074)){
- jam();
- const Uint32 noNodes = replicaPtr.p->noLogNodes;
- Uint32 start = replicaPtr.p->logStartGci[noNodes - 1];
- const Uint32 stop = replicaPtr.p->logStopGci[noNodes - 1];
-
- for(Uint32 i = noNodes; i < 4 && (stop - start) > 0; i++){
- replicaPtr.p->noLogNodes++;
- replicaPtr.p->logStopGci[i - 1] = start;
-
- replicaPtr.p->logNodeId[i] = replicaPtr.p->logNodeId[i-1];
- replicaPtr.p->logStartGci[i] = start + 1;
- replicaPtr.p->logStopGci[i] = stop;
- start += 1;
- }
- }
-
- startFragReq->noOfLogNodes = replicaPtr.p->noLogNodes;
-
- for (Uint32 i = 0; i < 4 ; i++) {
- startFragReq->lqhLogNode[i] = replicaPtr.p->logNodeId[i];
- startFragReq->startGci[i] = replicaPtr.p->logStartGci[i];
- startFragReq->lastGci[i] = replicaPtr.p->logStopGci[i];
- }//for
-
- sendSignal(ref, GSN_START_FRAGREQ, signal,
- StartFragReq::SignalLength, JBB);
- }//for
-}//Dbdih::sendStartFragreq()
-
-/*************************************************************************/
-/* SET THE INITIAL ACTIVE STATUS ON ALL NODES AND PUT INTO LISTS. */
-/*************************************************************************/
-void Dbdih::setInitialActiveStatus()
-{
- NodeRecordPtr siaNodeptr;
- Uint32 tsiaNoActiveNodes;
-
- tsiaNoActiveNodes = csystemnodes - cnoHotSpare;
- for(Uint32 i = 0; i<Sysfile::NODE_STATUS_SIZE; i++)
- SYSFILE->nodeStatus[i] = 0;
- for (siaNodeptr.i = 1; siaNodeptr.i < MAX_NDB_NODES; siaNodeptr.i++) {
- ptrAss(siaNodeptr, nodeRecord);
- 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;
- if (siaNodeptr.p->nodeStatus == NodeRecord::ALIVE)
- {
- jam();
- siaNodeptr.p->activeStatus = Sysfile::NS_Active;
- }
- else
- {
- siaNodeptr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
- }
- }
- break;
- default:
- jam();
- siaNodeptr.p->activeStatus = Sysfile::NS_NotDefined;
- break;
- }//if
- Sysfile::setNodeStatus(siaNodeptr.i,
- SYSFILE->nodeStatus,
- siaNodeptr.p->activeStatus);
- }//for
-}//Dbdih::setInitialActiveStatus()
-
-/*************************************************************************/
-/* SET LCP ACTIVE STATUS AT THE END OF A LOCAL CHECKPOINT. */
-/*************************************************************************/
-void Dbdih::setLcpActiveStatusEnd()
-{
- NodeRecordPtr nodePtr;
-
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (c_lcpState.m_participatingLQH.get(nodePtr.i)){
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- case Sysfile::NS_ActiveMissed_2:
- jam();
- /*-------------------------------------------------------------------*/
- /* THE NODE PARTICIPATED IN THIS CHECKPOINT.
- * WE CAN SET ITS STATUS TO ACTIVE */
- /*-------------------------------------------------------------------*/
- nodePtr.p->activeStatus = Sysfile::NS_Active;
- takeOverCompleted(nodePtr.i);
- break;
- case Sysfile::NS_TakeOver:
- jam();
- /*-------------------------------------------------------------------*/
- /* THE NODE HAS COMPLETED A CHECKPOINT AFTER TAKE OVER. WE CAN NOW */
- /* SET ITS STATUS TO ACTIVE. WE CAN ALSO COMPLETE THE TAKE OVER */
- /* AND ALSO WE CLEAR THE TAKE OVER NODE IN THE RESTART INFO. */
- /*-------------------------------------------------------------------*/
- nodePtr.p->activeStatus = Sysfile::NS_Active;
- takeOverCompleted(nodePtr.i);
- break;
- default:
- ndbrequire(false);
- return;
- break;
- }//switch
- }//if
- }//for
-
- if(getNodeState().getNodeRestartInProgress()){
- jam();
- if(c_lcpState.m_participatingLQH.get(getOwnNodeId())){
- nodePtr.i = getOwnNodeId();
- ptrAss(nodePtr, nodeRecord);
- ndbrequire(nodePtr.p->activeStatus == Sysfile::NS_Active);
- g_eventLogger.info("NR: setLcpActiveStatusEnd - m_participatingLQH");
- } else {
- g_eventLogger.info("NR: setLcpActiveStatusEnd - !m_participatingLQH");
- }
- }
-
- c_lcpState.m_participatingDIH.clear();
- c_lcpState.m_participatingLQH.clear();
- if (isMaster()) {
- jam();
- setNodeRestartInfoBits();
- }//if
-}//Dbdih::setLcpActiveStatusEnd()
-
-void Dbdih::takeOverCompleted(Uint32 aNodeId)
-{
- TakeOverRecordPtr takeOverPtr;
- takeOverPtr.i = findTakeOver(aNodeId);
- if (takeOverPtr.i != RNIL) {
- jam();
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- if (takeOverPtr.p->toMasterStatus != TakeOverRecord::WAIT_LCP) {
- jam();
- ndbrequire(!isMaster());
- return;
- }//if
- ndbrequire(isMaster());
- Sysfile::setTakeOverNode(aNodeId, SYSFILE->takeOver, 0);
- takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_END_COPY;
- cstartGcpNow = true;
- }//if
-}//Dbdih::takeOverCompleted()
-
-/*************************************************************************/
-/* SET LCP ACTIVE STATUS BEFORE STARTING A LOCAL CHECKPOINT. */
-/*************************************************************************/
-void Dbdih::setLcpActiveStatusStart(Signal* signal)
-{
- NodeRecordPtr nodePtr;
-
- c_lcpState.m_participatingLQH.clear();
- c_lcpState.m_participatingDIH.clear();
-
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRecord);
-#if 0
- if(nodePtr.p->nodeStatus != NodeRecord::NOT_IN_CLUSTER){
- infoEvent("Node %d nodeStatus=%d activeStatus=%d copyCompleted=%d lcp=%d",
- nodePtr.i,
- nodePtr.p->nodeStatus,
- nodePtr.p->activeStatus,
- nodePtr.p->copyCompleted,
- nodePtr.p->m_inclDihLcp);
- }
-#endif
- if(nodePtr.p->nodeStatus == NodeRecord::ALIVE && nodePtr.p->m_inclDihLcp){
- jam();
- c_lcpState.m_participatingDIH.set(nodePtr.i);
- }
-
- if ((nodePtr.p->nodeStatus == NodeRecord::ALIVE) &&
- (nodePtr.p->copyCompleted)) {
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- jam();
- /*-------------------------------------------------------------------*/
- // The normal case. Starting a LCP for a started node which hasn't
- // missed the previous LCP.
- /*-------------------------------------------------------------------*/
- c_lcpState.m_participatingLQH.set(nodePtr.i);
- break;
- case Sysfile::NS_ActiveMissed_1:
- jam();
- /*-------------------------------------------------------------------*/
- // The node is starting up and is participating in a local checkpoint
- // as the final phase of the start-up. We can still use the checkpoints
- // on the node after a system restart.
- /*-------------------------------------------------------------------*/
- c_lcpState.m_participatingLQH.set(nodePtr.i);
- break;
- case Sysfile::NS_ActiveMissed_2:
- jam();
- /*-------------------------------------------------------------------*/
- // The node is starting up and is participating in a local checkpoint
- // as the final phase of the start-up. We have missed so
- // many checkpoints that we no longer can use this node to
- // recreate fragments from disk.
- // It must be taken over with the copy fragment process after a system
- // crash. We indicate this by setting the active status to TAKE_OVER.
- /*-------------------------------------------------------------------*/
- c_lcpState.m_participatingLQH.set(nodePtr.i);
- nodePtr.p->activeStatus = Sysfile::NS_TakeOver;
- //break; // Fall through
- case Sysfile::NS_TakeOver:{
- TakeOverRecordPtr takeOverPtr;
- jam();
- /*-------------------------------------------------------------------*/
- /* THIS NODE IS CURRENTLY TAKING OVER A FAILED NODE. */
- /*-------------------------------------------------------------------*/
- takeOverPtr.i = findTakeOver(nodePtr.i);
- if (takeOverPtr.i != RNIL) {
- jam();
- ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
- if (takeOverPtr.p->toMasterStatus == TakeOverRecord::WAIT_LCP) {
- jam();
- /*---------------------------------------------------------------
- * ALL THE INFORMATION HAVE BEEN REPLICATED TO THE NEW
- * NODE AND WE ARE ONLY WAITING FOR A LOCAL CHECKPOINT TO BE
- * PERFORMED ON THE NODE TO SET ITS STATUS TO ACTIVE.
- */
- infoEvent("Node %d is WAIT_LCP including in LCP", nodePtr.i);
- c_lcpState.m_participatingLQH.set(nodePtr.i);
- }//if
- }//if
- break;
- }
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- } else {
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- jam();
- nodePtr.p->activeStatus = Sysfile::NS_ActiveMissed_1;
- break;
- case Sysfile::NS_ActiveMissed_1:
- jam();
- nodePtr.p->activeStatus = Sysfile::NS_ActiveMissed_2;
- break;
- case Sysfile::NS_ActiveMissed_2:
- jam();
- CRASH_INSERTION(7192);
- if ((nodePtr.p->nodeStatus == NodeRecord::ALIVE) &&
- (!nodePtr.p->copyCompleted)) {
- jam();
- /*-----------------------------------------------------------------*/
- // The node is currently starting up and has not completed the
- // copy phase.
- // It will thus be in the TAKE_OVER state.
- /*-----------------------------------------------------------------*/
- ndbrequire(findTakeOver(nodePtr.i) != RNIL);
- nodePtr.p->activeStatus = Sysfile::NS_TakeOver;
- } else {
- jam();
- /*-----------------------------------------------------------------*/
- /* THE NODE IS ACTIVE AND HAS NOT COMPLETED ANY OF THE LAST 3
- * CHECKPOINTS */
- /* WE MUST TAKE IT OUT OF ACTION AND START A NEW NODE TO TAKE OVER.*/
- /*-----------------------------------------------------------------*/
- nodePtr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
- }//if
- break;
- case Sysfile::NS_TakeOver:
- jam();
- break;
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- }//if
- }//for
- if (isMaster()) {
- jam();
- checkStartTakeOver(signal);
- setNodeRestartInfoBits();
- }//if
-}//Dbdih::setLcpActiveStatusStart()
-
-/*************************************************************************/
-/* SET NODE ACTIVE STATUS AT SYSTEM RESTART AND WHEN UPDATED BY MASTER */
-/*************************************************************************/
-void Dbdih::setNodeActiveStatus()
-{
- NodeRecordPtr snaNodeptr;
-
- for (snaNodeptr.i = 1; snaNodeptr.i < MAX_NDB_NODES; snaNodeptr.i++) {
- ptrAss(snaNodeptr, nodeRecord);
- const Uint32 tsnaNodeBits = Sysfile::getNodeStatus(snaNodeptr.i,
- SYSFILE->nodeStatus);
- switch (tsnaNodeBits) {
- case Sysfile::NS_Active:
- jam();
- snaNodeptr.p->activeStatus = Sysfile::NS_Active;
- break;
- case Sysfile::NS_ActiveMissed_1:
- jam();
- snaNodeptr.p->activeStatus = Sysfile::NS_ActiveMissed_1;
- break;
- case Sysfile::NS_ActiveMissed_2:
- jam();
- snaNodeptr.p->activeStatus = Sysfile::NS_ActiveMissed_2;
- break;
- case Sysfile::NS_TakeOver:
- jam();
- snaNodeptr.p->activeStatus = Sysfile::NS_TakeOver;
- break;
- case Sysfile::NS_HotSpare:
- jam();
- snaNodeptr.p->activeStatus = Sysfile::NS_HotSpare;
- break;
- case Sysfile::NS_NotActive_NotTakenOver:
- jam();
- snaNodeptr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
- break;
- case Sysfile::NS_NotDefined:
- jam();
- snaNodeptr.p->activeStatus = Sysfile::NS_NotDefined;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- }//for
-}//Dbdih::setNodeActiveStatus()
-
-/***************************************************************************/
-/* SET THE NODE GROUP BASED ON THE RESTART INFORMATION OR AS SET BY MASTER */
-/***************************************************************************/
-void Dbdih::setNodeGroups()
-{
- NodeGroupRecordPtr NGPtr;
- NodeRecordPtr sngNodeptr;
- Uint32 Ti;
-
- for (Ti = 0; Ti < MAX_NDB_NODES; Ti++) {
- NGPtr.i = Ti;
- ptrAss(NGPtr, nodeGroupRecord);
- NGPtr.p->nodeCount = 0;
- }//for
- for (sngNodeptr.i = 1; sngNodeptr.i < MAX_NDB_NODES; sngNodeptr.i++) {
- ptrAss(sngNodeptr, nodeRecord);
- Sysfile::ActiveStatus s =
- (Sysfile::ActiveStatus)Sysfile::getNodeStatus(sngNodeptr.i,
- SYSFILE->nodeStatus);
- switch (s){
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- case Sysfile::NS_ActiveMissed_2:
- case Sysfile::NS_NotActive_NotTakenOver:
- case Sysfile::NS_TakeOver:
- jam();
- sngNodeptr.p->nodeGroup = Sysfile::getNodeGroup(sngNodeptr.i,
- SYSFILE->nodeGroups);
- NGPtr.i = sngNodeptr.p->nodeGroup;
- ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- NGPtr.p->nodesInGroup[NGPtr.p->nodeCount] = sngNodeptr.i;
- NGPtr.p->nodeCount++;
- break;
- case Sysfile::NS_HotSpare:
- case Sysfile::NS_NotDefined:
- jam();
- sngNodeptr.p->nodeGroup = ZNIL;
- break;
- default:
- ndbrequire(false);
- return;
- break;
- }//switch
- }//for
- cnoOfNodeGroups = 0;
- for (Ti = 0; Ti < MAX_NDB_NODES; Ti++) {
- jam();
- NGPtr.i = Ti;
- ptrAss(NGPtr, nodeGroupRecord);
- if (NGPtr.p->nodeCount != 0) {
- jam();
- cnoOfNodeGroups++;
- }//if
- }//for
- cnoHotSpare = csystemnodes - (cnoOfNodeGroups * cnoReplicas);
-}//Dbdih::setNodeGroups()
-
-/*************************************************************************/
-/* SET NODE INFORMATION AFTER RECEIVING RESTART INFORMATION FROM MASTER. */
-/* WE TAKE THE OPPORTUNITY TO SYNCHRONISE OUR DATA WITH THE MASTER. IT */
-/* IS ONLY THE MASTER THAT WILL ACT ON THIS DATA. WE WILL KEEP THEM */
-/* UPDATED FOR THE CASE WHEN WE HAVE TO BECOME MASTER. */
-/*************************************************************************/
-void Dbdih::setNodeInfo(Signal* signal)
-{
- setNodeActiveStatus();
- setNodeGroups();
- sendHOT_SPAREREP(signal);
-}//Dbdih::setNodeInfo()
-
-/*************************************************************************/
-// Keep also DBDICT informed about the Hot Spare situation in the cluster.
-/*************************************************************************/
-void Dbdih::sendHOT_SPAREREP(Signal* signal)
-{
- NodeRecordPtr locNodeptr;
- Uint32 Ti = 0;
- HotSpareRep * const hotSpare = (HotSpareRep*)&signal->theData[0];
- NodeBitmask::clear(hotSpare->theHotSpareNodes);
- for (locNodeptr.i = 1; locNodeptr.i < MAX_NDB_NODES; locNodeptr.i++) {
- ptrAss(locNodeptr, nodeRecord);
- switch (locNodeptr.p->activeStatus) {
- case Sysfile::NS_HotSpare:
- jam();
- NodeBitmask::set(hotSpare->theHotSpareNodes, locNodeptr.i);
- Ti++;
- break;
- default:
- jam();
- break;
- }//switch
- }//for
- hotSpare->noHotSpareNodes = Ti;
- sendSignal(DBDICT_REF, GSN_HOT_SPAREREP,
- signal, HotSpareRep::SignalLength, JBB);
-}//Dbdih::sendHOT_SPAREREP()
-
-/*************************************************************************/
-/* SET LCP ACTIVE STATUS FOR ALL NODES BASED ON THE INFORMATION IN */
-/* THE RESTART INFORMATION. */
-/*************************************************************************/
-#if 0
-void Dbdih::setNodeLcpActiveStatus()
-{
- c_lcpState.m_lcpActiveStatus.clear();
- for (Uint32 i = 1; i < MAX_NDB_NODES; i++) {
- if (NodeBitmask::get(SYSFILE->lcpActive, i)) {
- jam();
- c_lcpState.m_lcpActiveStatus.set(i);
- }//if
- }//for
-}//Dbdih::setNodeLcpActiveStatus()
-#endif
-
-/*************************************************************************/
-/* SET THE RESTART INFO BITS BASED ON THE NODES ACTIVE STATUS. */
-/*************************************************************************/
-void Dbdih::setNodeRestartInfoBits()
-{
- NodeRecordPtr nodePtr;
- Uint32 tsnrNodeGroup;
- Uint32 tsnrNodeActiveStatus;
- Uint32 i;
- for(i = 1; i < MAX_NDB_NODES; i++){
- Sysfile::setNodeStatus(i, SYSFILE->nodeStatus, Sysfile::NS_Active);
- }//for
- for(i = 1; i < Sysfile::NODE_GROUPS_SIZE; i++){
- SYSFILE->nodeGroups[i] = 0;
- }//for
- NdbNodeBitmask::clear(SYSFILE->lcpActive);
-
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRecord);
- switch (nodePtr.p->activeStatus) {
- case Sysfile::NS_Active:
- jam();
- tsnrNodeActiveStatus = Sysfile::NS_Active;
- break;
- case Sysfile::NS_ActiveMissed_1:
- jam();
- tsnrNodeActiveStatus = Sysfile::NS_ActiveMissed_1;
- break;
- case Sysfile::NS_ActiveMissed_2:
- jam();
- tsnrNodeActiveStatus = Sysfile::NS_ActiveMissed_2;
- break;
- case Sysfile::NS_HotSpare:
- jam();
- tsnrNodeActiveStatus = Sysfile::NS_HotSpare;
- break;
- case Sysfile::NS_TakeOver:
- jam();
- tsnrNodeActiveStatus = Sysfile::NS_TakeOver;
- break;
- case Sysfile::NS_NotActive_NotTakenOver:
- jam();
- tsnrNodeActiveStatus = Sysfile::NS_NotActive_NotTakenOver;
- break;
- case Sysfile::NS_NotDefined:
- jam();
- tsnrNodeActiveStatus = Sysfile::NS_NotDefined;
- break;
- default:
- ndbrequire(false);
- tsnrNodeActiveStatus = Sysfile::NS_NotDefined; // remove warning
- break;
- }//switch
- Sysfile::setNodeStatus(nodePtr.i, SYSFILE->nodeStatus,
- tsnrNodeActiveStatus);
- if (nodePtr.p->nodeGroup == ZNIL) {
- jam();
- tsnrNodeGroup = NO_NODE_GROUP_ID;
- } else {
- jam();
- tsnrNodeGroup = nodePtr.p->nodeGroup;
- }//if
- Sysfile::setNodeGroup(nodePtr.i, SYSFILE->nodeGroups, tsnrNodeGroup);
- if (c_lcpState.m_participatingLQH.get(nodePtr.i)){
- jam();
- NodeBitmask::set(SYSFILE->lcpActive, nodePtr.i);
- }//if
- }//for
-}//Dbdih::setNodeRestartInfoBits()
-
-/*************************************************************************/
-/* START THE GLOBAL CHECKPOINT PROTOCOL IN MASTER AT START-UP */
-/*************************************************************************/
-void Dbdih::startGcp(Signal* signal)
-{
- cgcpStatus = GCP_READY;
- coldGcpStatus = cgcpStatus;
- coldGcpId = cnewgcp;
- cgcpSameCounter = 0;
- signal->theData[0] = DihContinueB::ZSTART_GCP;
- signal->theData[1] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- signal->theData[0] = DihContinueB::ZCHECK_GCP_STOP;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
-}//Dbdih::startGcp()
-
-void Dbdih::updateNodeInfo(FragmentstorePtr fragPtr)
-{
- ReplicaRecordPtr replicatePtr;
- Uint32 index = 0;
- replicatePtr.i = fragPtr.p->storedReplicas;
- do {
- jam();
- ptrCheckGuard(replicatePtr, creplicaFileSize, replicaRecord);
- ndbrequire(index < MAX_REPLICAS);
- fragPtr.p->activeNodes[index] = replicatePtr.p->procNode;
- index++;
- replicatePtr.i = replicatePtr.p->nextReplica;
- } while (replicatePtr.i != RNIL);
- fragPtr.p->fragReplicas = index;
-
- /* ----------------------------------------------------------------------- */
- // We switch primary to the preferred primary if the preferred primary is
- // in the list.
- /* ----------------------------------------------------------------------- */
- const Uint32 prefPrim = fragPtr.p->preferredPrimary;
- for (Uint32 i = 1; i < index; i++) {
- jam();
- ndbrequire(i < MAX_REPLICAS);
- if (fragPtr.p->activeNodes[i] == prefPrim){
- jam();
- Uint32 switchNode = fragPtr.p->activeNodes[0];
- fragPtr.p->activeNodes[0] = prefPrim;
- fragPtr.p->activeNodes[i] = switchNode;
- break;
- }//if
- }//for
-}//Dbdih::updateNodeInfo()
-
-void Dbdih::writeFragment(RWFragment* wf, FragmentstorePtr fragPtr)
-{
- writePageWord(wf, wf->fragId);
- writePageWord(wf, fragPtr.p->preferredPrimary);
- writePageWord(wf, fragPtr.p->noStoredReplicas);
- writePageWord(wf, fragPtr.p->noOldStoredReplicas);
- writePageWord(wf, fragPtr.p->distributionKey);
- writePageWord(wf, fragPtr.p->m_log_part_id);
-}//Dbdih::writeFragment()
-
-void Dbdih::writePageWord(RWFragment* wf, Uint32 dataWord)
-{
- if (wf->wordIndex >= 2048) {
- jam();
- ndbrequire(wf->wordIndex == 2048);
- allocpage(wf->rwfPageptr);
- wf->wordIndex = 32;
- wf->pageIndex++;
- ndbrequire(wf->pageIndex < 8);
- wf->rwfTabPtr.p->pageRef[wf->pageIndex] = wf->rwfPageptr.i;
- wf->rwfTabPtr.p->noPages++;
- }//if
- wf->rwfPageptr.p->word[wf->wordIndex] = dataWord;
- wf->wordIndex++;
-}//Dbdih::writePageWord()
-
-void Dbdih::writeReplicas(RWFragment* wf, Uint32 replicaStartIndex)
-{
- ReplicaRecordPtr wfReplicaPtr;
- wfReplicaPtr.i = replicaStartIndex;
- while (wfReplicaPtr.i != RNIL) {
- jam();
- ptrCheckGuard(wfReplicaPtr, creplicaFileSize, replicaRecord);
- writePageWord(wf, wfReplicaPtr.p->procNode);
- writePageWord(wf, wfReplicaPtr.p->initialGci);
- writePageWord(wf, wfReplicaPtr.p->noCrashedReplicas);
- writePageWord(wf, wfReplicaPtr.p->nextLcp);
- Uint32 i;
- for (i = 0; i < MAX_LCP_STORED; i++) {
- writePageWord(wf, wfReplicaPtr.p->maxGciCompleted[i]);
- writePageWord(wf, wfReplicaPtr.p->maxGciStarted[i]);
- writePageWord(wf, wfReplicaPtr.p->lcpId[i]);
- writePageWord(wf, wfReplicaPtr.p->lcpStatus[i]);
- }//if
- for (i = 0; i < 8; i++) {
- writePageWord(wf, wfReplicaPtr.p->createGci[i]);
- writePageWord(wf, wfReplicaPtr.p->replicaLastGci[i]);
- }//if
-
- wfReplicaPtr.i = wfReplicaPtr.p->nextReplica;
- }//while
-}//Dbdih::writeReplicas()
-
-void Dbdih::writeRestorableGci(Signal* signal, FileRecordPtr filePtr)
-{
- for (Uint32 i = 0; i < Sysfile::SYSFILE_SIZE32; i++) {
- sysfileDataToFile[i] = sysfileData[i];
- }//for
- signal->theData[0] = filePtr.p->fileRef;
- signal->theData[1] = reference();
- signal->theData[2] = filePtr.i;
- signal->theData[3] = ZLIST_OF_PAIRS_SYNCH;
- signal->theData[4] = ZVAR_NO_CRESTART_INFO_TO_FILE;
- signal->theData[5] = 1; /* AMOUNT OF PAGES */
- signal->theData[6] = 0; /* MEMORY PAGE = 0 SINCE COMMON STORED VARIABLE */
- signal->theData[7] = 0;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
-}//Dbdih::writeRestorableGci()
-
-void Dbdih::writeTabfile(Signal* signal, TabRecord* tab, FileRecordPtr filePtr)
-{
- signal->theData[0] = filePtr.p->fileRef;
- signal->theData[1] = reference();
- signal->theData[2] = filePtr.i;
- signal->theData[3] = ZLIST_OF_PAIRS_SYNCH;
- signal->theData[4] = ZVAR_NO_WORD;
- signal->theData[5] = tab->noPages;
- for (Uint32 i = 0; i < tab->noPages; i++) {
- jam();
- signal->theData[6 + (2 * i)] = tab->pageRef[i];
- signal->theData[7 + (2 * i)] = i;
- }//for
- Uint32 length = 6 + (2 * tab->noPages);
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, length, JBA);
-}//Dbdih::writeTabfile()
-
-void Dbdih::execDEBUG_SIG(Signal* signal)
-{
- signal = signal; //Avoid compiler warnings
-}//Dbdih::execDEBUG_SIG()
-
-void
-Dbdih::execDUMP_STATE_ORD(Signal* signal)
-{
- DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
- Uint32 arg = dumpState->args[0];
- if (arg == DumpStateOrd::DihDumpNodeRestartInfo) {
- infoEvent("c_nodeStartMaster.blockLcp = %d, c_nodeStartMaster.blockGcp = %d, c_nodeStartMaster.wait = %d",
- c_nodeStartMaster.blockLcp, c_nodeStartMaster.blockGcp, c_nodeStartMaster.wait);
- infoEvent("cstartGcpNow = %d, cgcpStatus = %d",
- cstartGcpNow, cgcpStatus);
- infoEvent("cfirstVerifyQueue = %d, cverifyQueueCounter = %d",
- cfirstVerifyQueue, cverifyQueueCounter);
- infoEvent("cgcpOrderBlocked = %d, cgcpStartCounter = %d",
- cgcpOrderBlocked, cgcpStartCounter);
- }//if
- if (arg == DumpStateOrd::DihDumpNodeStatusInfo) {
- NodeRecordPtr localNodePtr;
- infoEvent("Printing nodeStatus of all nodes");
- for (localNodePtr.i = 1; localNodePtr.i < MAX_NDB_NODES; localNodePtr.i++) {
- ptrAss(localNodePtr, nodeRecord);
- if (localNodePtr.p->nodeStatus != NodeRecord::NOT_IN_CLUSTER) {
- infoEvent("Node = %d has status = %d",
- localNodePtr.i, localNodePtr.p->nodeStatus);
- }//if
- }//for
- }//if
-
- if (arg == DumpStateOrd::DihPrintFragmentation){
- infoEvent("Printing fragmentation of all tables --");
- for(Uint32 i = 0; i<ctabFileSize; i++){
- TabRecordPtr tabPtr;
- tabPtr.i = i;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- if(tabPtr.p->tabStatus != TabRecord::TS_ACTIVE)
- continue;
-
- for(Uint32 j = 0; j < tabPtr.p->totalfragments; j++){
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, j, fragPtr);
-
- Uint32 nodeOrder[MAX_REPLICAS];
- const Uint32 noOfReplicas = extractNodeInfo(fragPtr.p, nodeOrder);
- char buf[100];
- BaseString::snprintf(buf, sizeof(buf), " Table %d Fragment %d - ", tabPtr.i, j);
- for(Uint32 k = 0; k < noOfReplicas; k++){
- char tmp[100];
- BaseString::snprintf(tmp, sizeof(tmp), "%d ", nodeOrder[k]);
- strcat(buf, tmp);
- }
- infoEvent(buf);
- }
- }
- }
-
- if (signal->theData[0] == 7000) {
- infoEvent("ctimer = %d, cgcpParticipantState = %d, cgcpStatus = %d",
- c_lcpState.ctimer, cgcpParticipantState, cgcpStatus);
- infoEvent("coldGcpStatus = %d, coldGcpId = %d, cmasterState = %d",
- coldGcpStatus, coldGcpId, cmasterState);
- infoEvent("cmasterTakeOverNode = %d, ctcCounter = %d",
- cmasterTakeOverNode, c_lcpState.ctcCounter);
- }//if
- if (signal->theData[0] == 7001) {
- infoEvent("c_lcpState.keepGci = %d",
- c_lcpState.keepGci);
- infoEvent("c_lcpState.lcpStatus = %d, clcpStopGcp = %d",
- c_lcpState.lcpStatus,
- c_lcpState.lcpStopGcp);
- infoEvent("cgcpStartCounter = %d, cimmediateLcpStart = %d",
- cgcpStartCounter, c_lcpState.immediateLcpStart);
- }//if
- if (signal->theData[0] == 7002) {
- infoEvent("cnoOfActiveTables = %d, cgcpDelay = %d",
- cnoOfActiveTables, cgcpDelay);
- infoEvent("cdictblockref = %d, cfailurenr = %d",
- cdictblockref, cfailurenr);
- infoEvent("con_lineNodes = %d, reference() = %d, creceivedfrag = %d",
- con_lineNodes, reference(), creceivedfrag);
- }//if
- if (signal->theData[0] == 7003) {
- infoEvent("cfirstAliveNode = %d, cgckptflag = %d",
- cfirstAliveNode, cgckptflag);
- infoEvent("clocallqhblockref = %d, clocaltcblockref = %d, cgcpOrderBlocked = %d",
- clocallqhblockref, clocaltcblockref, cgcpOrderBlocked);
- infoEvent("cstarttype = %d, csystemnodes = %d, currentgcp = %d",
- cstarttype, csystemnodes, currentgcp);
- }//if
- if (signal->theData[0] == 7004) {
- infoEvent("cmasterdihref = %d, cownNodeId = %d, cnewgcp = %d",
- cmasterdihref, cownNodeId, cnewgcp);
- infoEvent("cndbStartReqBlockref = %d, cremainingfrags = %d",
- cndbStartReqBlockref, cremainingfrags);
- infoEvent("cntrlblockref = %d, cgcpSameCounter = %d, coldgcp = %d",
- cntrlblockref, cgcpSameCounter, coldgcp);
- }//if
- if (signal->theData[0] == 7005) {
- infoEvent("crestartGci = %d",
- crestartGci);
- }//if
- if (signal->theData[0] == 7006) {
- infoEvent("clcpDelay = %d, cgcpMasterTakeOverState = %d",
- c_lcpState.clcpDelay, cgcpMasterTakeOverState);
- infoEvent("cmasterNodeId = %d", cmasterNodeId);
- infoEvent("cnoHotSpare = %d, c_nodeStartMaster.startNode = %d, c_nodeStartMaster.wait = %d",
- cnoHotSpare, c_nodeStartMaster.startNode, c_nodeStartMaster.wait);
- }//if
- if (signal->theData[0] == 7007) {
- infoEvent("c_nodeStartMaster.failNr = %d", c_nodeStartMaster.failNr);
- infoEvent("c_nodeStartMaster.startInfoErrorCode = %d",
- c_nodeStartMaster.startInfoErrorCode);
- infoEvent("c_nodeStartMaster.blockLcp = %d, c_nodeStartMaster.blockGcp = %d",
- c_nodeStartMaster.blockLcp, c_nodeStartMaster.blockGcp);
- }//if
- if (signal->theData[0] == 7008) {
- infoEvent("cfirstDeadNode = %d, cstartPhase = %d, cnoReplicas = %d",
- cfirstDeadNode, cstartPhase, cnoReplicas);
- infoEvent("cwaitLcpSr = %d",cwaitLcpSr);
- }//if
- if (signal->theData[0] == 7009) {
- infoEvent("ccalcOldestRestorableGci = %d, cnoOfNodeGroups = %d",
- c_lcpState.oldestRestorableGci, cnoOfNodeGroups);
- infoEvent("cstartGcpNow = %d",
- cstartGcpNow);
- infoEvent("crestartGci = %d",
- crestartGci);
- }//if
- if (signal->theData[0] == 7010) {
- infoEvent("cminHotSpareNodes = %d, c_lcpState.lcpStatusUpdatedPlace = %d, cLcpStart = %d",
- cminHotSpareNodes, c_lcpState.lcpStatusUpdatedPlace, c_lcpState.lcpStart);
- infoEvent("c_blockCommit = %d, c_blockCommitNo = %d",
- c_blockCommit, c_blockCommitNo);
- }//if
- if (signal->theData[0] == 7011){
- infoEvent("c_COPY_GCIREQ_Counter = %s",
- c_COPY_GCIREQ_Counter.getText());
- infoEvent("c_COPY_TABREQ_Counter = %s",
- c_COPY_TABREQ_Counter.getText());
- infoEvent("c_CREATE_FRAGREQ_Counter = %s",
- c_CREATE_FRAGREQ_Counter.getText());
- infoEvent("c_DIH_SWITCH_REPLICA_REQ_Counter = %s",
- c_DIH_SWITCH_REPLICA_REQ_Counter.getText());
- infoEvent("c_EMPTY_LCP_REQ_Counter = %s",c_EMPTY_LCP_REQ_Counter.getText());
- infoEvent("c_END_TOREQ_Counter = %s", c_END_TOREQ_Counter.getText());
- infoEvent("c_GCP_COMMIT_Counter = %s", c_GCP_COMMIT_Counter.getText());
- infoEvent("c_GCP_PREPARE_Counter = %s", c_GCP_PREPARE_Counter.getText());
- infoEvent("c_GCP_SAVEREQ_Counter = %s", c_GCP_SAVEREQ_Counter.getText());
- infoEvent("c_INCL_NODEREQ_Counter = %s", c_INCL_NODEREQ_Counter.getText());
- infoEvent("c_MASTER_GCPREQ_Counter = %s",
- c_MASTER_GCPREQ_Counter.getText());
- infoEvent("c_MASTER_LCPREQ_Counter = %s",
- c_MASTER_LCPREQ_Counter.getText());
- infoEvent("c_START_INFOREQ_Counter = %s",
- c_START_INFOREQ_Counter.getText());
- infoEvent("c_START_RECREQ_Counter = %s", c_START_RECREQ_Counter.getText());
- infoEvent("c_START_TOREQ_Counter = %s", c_START_TOREQ_Counter.getText());
- infoEvent("c_STOP_ME_REQ_Counter = %s", c_STOP_ME_REQ_Counter.getText());
- infoEvent("c_TC_CLOPSIZEREQ_Counter = %s",
- c_TC_CLOPSIZEREQ_Counter.getText());
- infoEvent("c_TCGETOPSIZEREQ_Counter = %s",
- c_TCGETOPSIZEREQ_Counter.getText());
- infoEvent("c_UPDATE_TOREQ_Counter = %s", c_UPDATE_TOREQ_Counter.getText());
- }
-
- if(signal->theData[0] == 7012){
- char buf[8*_NDB_NODE_BITMASK_SIZE+1];
- infoEvent("ParticipatingDIH = %s", c_lcpState.m_participatingDIH.getText(buf));
- infoEvent("ParticipatingLQH = %s", c_lcpState.m_participatingLQH.getText(buf));
- infoEvent("m_LCP_COMPLETE_REP_Counter_DIH = %s",
- c_lcpState.m_LCP_COMPLETE_REP_Counter_DIH.getText());
- infoEvent("m_LCP_COMPLETE_REP_Counter_LQH = %s",
- c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH.getText());
- infoEvent("m_LAST_LCP_FRAG_ORD = %s",
- c_lcpState.m_LAST_LCP_FRAG_ORD.getText());
- infoEvent("m_LCP_COMPLETE_REP_From_Master_Received = %d",
- c_lcpState.m_LCP_COMPLETE_REP_From_Master_Received);
-
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if(nodePtr.p->nodeStatus == NodeRecord::ALIVE){
- Uint32 i;
- for(i = 0; i<nodePtr.p->noOfStartedChkpt; i++){
- infoEvent("Node %d: started: table=%d fragment=%d replica=%d",
- nodePtr.i,
- nodePtr.p->startedChkpt[i].tableId,
- nodePtr.p->startedChkpt[i].fragId,
- nodePtr.p->startedChkpt[i].replicaPtr);
- }
-
- for(i = 0; i<nodePtr.p->noOfQueuedChkpt; i++){
- infoEvent("Node %d: queued: table=%d fragment=%d replica=%d",
- nodePtr.i,
- nodePtr.p->queuedChkpt[i].tableId,
- nodePtr.p->queuedChkpt[i].fragId,
- nodePtr.p->queuedChkpt[i].replicaPtr);
- }
- }
- }
- }
-
- if(arg == 7019 && signal->getLength() == 2)
- {
- char buf2[8+1];
- NodeRecordPtr nodePtr;
- nodePtr.i = signal->theData[1];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- infoEvent("NF Node %d tc: %d lqh: %d dih: %d dict: %d recNODE_FAILREP: %d",
- nodePtr.i,
- nodePtr.p->dbtcFailCompleted,
- nodePtr.p->dblqhFailCompleted,
- nodePtr.p->dbdihFailCompleted,
- nodePtr.p->dbdictFailCompleted,
- nodePtr.p->recNODE_FAILREP);
- infoEvent(" m_NF_COMPLETE_REP: %s m_nodefailSteps: %s",
- nodePtr.p->m_NF_COMPLETE_REP.getText(),
- nodePtr.p->m_nodefailSteps.getText(buf2));
- }
-
- if(arg == 7020 && signal->getLength() > 3)
- {
- Uint32 gsn= signal->theData[1];
- Uint32 block= signal->theData[2];
- Uint32 length= signal->length() - 3;
- memmove(signal->theData, signal->theData+3, 4*length);
- sendSignal(numberToRef(block, getOwnNodeId()), gsn, signal, length, JBB);
-
- warningEvent("-- SENDING CUSTOM SIGNAL --");
- char buf[100], buf2[100];
- buf2[0]= 0;
- for(Uint32 i = 0; i<length; i++)
- {
- snprintf(buf, 100, "%s %.8x", buf2, signal->theData[i]);
- snprintf(buf2, 100, "%s", buf);
- }
- warningEvent("gsn: %d block: %s, length: %d theData: %s",
- gsn, getBlockName(block, "UNKNOWN"), length, buf);
-
- g_eventLogger.warning("-- SENDING CUSTOM SIGNAL --");
- g_eventLogger.warning("gsn: %d block: %s, length: %d theData: %s",
- gsn, getBlockName(block, "UNKNOWN"), length, buf);
- }
-
- if(arg == DumpStateOrd::DihDumpLCPState){
- infoEvent("-- Node %d LCP STATE --", getOwnNodeId());
- infoEvent("lcpStatus = %d (update place = %d) ",
- c_lcpState.lcpStatus, c_lcpState.lcpStatusUpdatedPlace);
- infoEvent
- ("lcpStart = %d lcpStopGcp = %d keepGci = %d oldestRestorable = %d",
- c_lcpState.lcpStart, c_lcpState.lcpStopGcp,
- c_lcpState.keepGci, c_lcpState.oldestRestorableGci);
-
- infoEvent
- ("immediateLcpStart = %d masterLcpNodeId = %d",
- c_lcpState.immediateLcpStart,
- refToNode(c_lcpState.m_masterLcpDihRef));
-
- for (Uint32 i = 0; i<10; i++)
- {
- infoEvent("%u : status: %u place: %u", i,
- c_lcpState.m_saveState[i].m_status,
- c_lcpState.m_saveState[i].m_place);
- }
-
- infoEvent("-- Node %d LCP STATE --", getOwnNodeId());
- }
-
- if(arg == DumpStateOrd::DihDumpLCPMasterTakeOver){
- infoEvent("-- Node %d LCP MASTER TAKE OVER STATE --", getOwnNodeId());
- infoEvent
- ("c_lcpMasterTakeOverState.state = %d updatePlace = %d failedNodeId = %d",
- c_lcpMasterTakeOverState.state,
- c_lcpMasterTakeOverState.updatePlace,
- c_lcpMasterTakeOverState.failedNodeId);
-
- infoEvent("c_lcpMasterTakeOverState.minTableId = %u minFragId = %u",
- c_lcpMasterTakeOverState.minTableId,
- c_lcpMasterTakeOverState.minFragId);
-
- infoEvent("-- Node %d LCP MASTER TAKE OVER STATE --", getOwnNodeId());
- }
-
- if (signal->theData[0] == 7015)
- {
- if (signal->getLength() == 1)
- {
- signal->theData[1] = 0;
- }
-
- Uint32 tableId = signal->theData[1];
- if (tableId < ctabFileSize)
- {
- signal->theData[0] = 7021;
- execDUMP_STATE_ORD(signal);
- signal->theData[0] = 7015;
- signal->theData[1] = tableId + 1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- }
-
- if(arg == DumpStateOrd::EnableUndoDelayDataWrite){
- g_eventLogger.info("Dbdih:: delay write of datapages for table = %d",
- dumpState->args[1]);
- // Send this dump to ACC and TUP
- EXECUTE_DIRECT(DBACC, GSN_DUMP_STATE_ORD, signal, 2);
- EXECUTE_DIRECT(DBTUP, GSN_DUMP_STATE_ORD, signal, 2);
-
- // Start immediate LCP
- c_lcpState.ctimer += (1 << c_lcpState.clcpDelay);
- return;
- }
-
- if (signal->theData[0] == DumpStateOrd::DihAllAllowNodeStart) {
- for (Uint32 i = 1; i < MAX_NDB_NODES; i++)
- setAllowNodeStart(i, true);
- return;
- }//if
- if (signal->theData[0] == DumpStateOrd::DihMinTimeBetweenLCP) {
- // Set time between LCP to min value
- g_eventLogger.info("Set time between LCP to min value");
- c_lcpState.clcpDelay = 0; // TimeBetweenLocalCheckpoints.min
- return;
- }
- if (signal->theData[0] == DumpStateOrd::DihMaxTimeBetweenLCP) {
- // Set time between LCP to max value
- g_eventLogger.info("Set time between LCP to max value");
- c_lcpState.clcpDelay = 31; // TimeBetweenLocalCheckpoints.max
- return;
- }
-
- if(arg == 7098){
- if(signal->length() == 3){
- jam();
- infoEvent("startLcpRoundLoopLab(tabel=%d, fragment=%d)",
- signal->theData[1], signal->theData[2]);
- startLcpRoundLoopLab(signal, signal->theData[1], signal->theData[2]);
- return;
- } else {
- infoEvent("Invalid no of arguments to 7098 - startLcpRoundLoopLab -"
- " expected 2 (tableId, fragmentId)");
- }
- }
-
- if(arg == DumpStateOrd::DihStartLcpImmediately){
- c_lcpState.ctimer += (1 << c_lcpState.clcpDelay);
- return;
- }
-
- if (arg == DumpStateOrd::DihSetTimeBetweenGcp)
- {
- if (signal->getLength() == 1)
- {
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
- ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &cgcpDelay);
- }
- else
- {
- cgcpDelay = signal->theData[1];
- }
- g_eventLogger.info("Setting time between gcp : %d", cgcpDelay);
- }
-
- if (arg == 7021 && signal->getLength() == 2)
- {
- TabRecordPtr tabPtr;
- tabPtr.i = signal->theData[1];
- if (tabPtr.i >= ctabFileSize)
- return;
-
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- if(tabPtr.p->tabStatus != TabRecord::TS_ACTIVE)
- return;
-
- infoEvent
- ("Table %d: TabCopyStatus: %d TabUpdateStatus: %d TabLcpStatus: %d",
- tabPtr.i,
- tabPtr.p->tabCopyStatus,
- tabPtr.p->tabUpdateState,
- tabPtr.p->tabLcpStatus);
-
- FragmentstorePtr fragPtr;
- for (Uint32 fid = 0; fid < tabPtr.p->totalfragments; fid++) {
- jam();
- getFragstore(tabPtr.p, fid, fragPtr);
-
- char buf[100], buf2[100];
- BaseString::snprintf(buf, sizeof(buf), " Fragment %d: noLcpReplicas==%d ",
- fid, fragPtr.p->noLcpReplicas);
-
- Uint32 num=0;
- ReplicaRecordPtr replicaPtr;
- replicaPtr.i = fragPtr.p->storedReplicas;
- do {
- ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
- BaseString::snprintf(buf2, sizeof(buf2), "%s %d(on %d)=%d(%s)",
- buf, num,
- replicaPtr.p->procNode,
- replicaPtr.p->lcpIdStarted,
- replicaPtr.p->lcpOngoingFlag ? "Ongoing" : "Idle");
- BaseString::snprintf(buf, sizeof(buf), "%s", buf2);
-
- num++;
- replicaPtr.i = replicaPtr.p->nextReplica;
- } while (replicaPtr.i != RNIL);
- infoEvent(buf);
- }
- }
-
- if (arg == 7022)
- {
- jam();
- crashSystemAtGcpStop(signal, true);
- }
-}//Dbdih::execDUMP_STATE_ORD()
-
-void
-Dbdih::execPREP_DROP_TAB_REQ(Signal* signal){
- jamEntry();
-
- PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
-
- TabRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
-
- PrepDropTabRef::ErrorCode err = PrepDropTabRef::OK;
- { /**
- * Check table state
- */
- bool ok = false;
- switch(tabPtr.p->tabStatus){
- case TabRecord::TS_IDLE:
- ok = true;
- jam();
- err = PrepDropTabRef::NoSuchTable;
- break;
- case TabRecord::TS_DROPPING:
- ok = true;
- jam();
- err = PrepDropTabRef::PrepDropInProgress;
- break;
- case TabRecord::TS_CREATING:
- jam();
- ok = true;
- break;
- case TabRecord::TS_ACTIVE:
- ok = true;
- jam();
- break;
- }
- ndbrequire(ok);
- }
-
- if(err != PrepDropTabRef::OK){
- jam();
- PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->tableId = tabPtr.i;
- ref->errorCode = err;
- sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
- PrepDropTabRef::SignalLength, JBB);
- return;
- }
-
- tabPtr.p->tabStatus = TabRecord::TS_DROPPING;
- tabPtr.p->m_prepDropTab.senderRef = senderRef;
- tabPtr.p->m_prepDropTab.senderData = senderData;
-
- if(isMaster()){
- /**
- * Remove from queue
- */
- NodeRecordPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRecord);
- if (c_lcpState.m_participatingLQH.get(nodePtr.i)){
-
- Uint32 index = 0;
- Uint32 count = nodePtr.p->noOfQueuedChkpt;
- while(index < count){
- if(nodePtr.p->queuedChkpt[index].tableId == tabPtr.i){
- jam();
- // g_eventLogger.info("Unqueuing %d", index);
-
- count--;
- for(Uint32 i = index; i<count; i++){
- jam();
- nodePtr.p->queuedChkpt[i] = nodePtr.p->queuedChkpt[i + 1];
- }
- } else {
- index++;
- }
- }
- nodePtr.p->noOfQueuedChkpt = count;
- }
- }
- }
-
- { /**
- * Check table lcp state
- */
-
- bool ok = false;
- switch(tabPtr.p->tabLcpStatus){
- case TabRecord::TLS_COMPLETED:
- case TabRecord::TLS_WRITING_TO_FILE:
- ok = true;
- jam();
- break;
- return;
- case TabRecord::TLS_ACTIVE:
- ok = true;
- jam();
-
- tabPtr.p->tabLcpStatus = TabRecord::TLS_COMPLETED;
-
- /**
- * First check if all fragments are done
- */
- if(checkLcpAllTablesDoneInLqh()){
- jam();
-
- g_eventLogger.info("This is the last table");
-
- /**
- * Then check if saving of tab info is done for all tables
- */
- LcpStatus a = c_lcpState.lcpStatus;
- checkLcpCompletedLab(signal);
-
- if(a != c_lcpState.lcpStatus){
- g_eventLogger.info("And all tables are written to already written disk");
- }
- }
- break;
- }
- ndbrequire(ok);
- }
-
- { /**
- * Send WaitDropTabReq to all LQH
- */
- WaitDropTabReq * req = (WaitDropTabReq*)signal->getDataPtrSend();
- req->tableId = tabPtr.i;
- req->senderRef = reference();
-
- NodeRecordPtr nodePtr;
- nodePtr.i = cfirstAliveNode;
- tabPtr.p->m_prepDropTab.waitDropTabCount.clearWaitingFor();
- while(nodePtr.i != RNIL){
- jam();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
-
- tabPtr.p->m_prepDropTab.waitDropTabCount.setWaitingFor(nodePtr.i);
- sendSignal(calcLqhBlockRef(nodePtr.i), GSN_WAIT_DROP_TAB_REQ,
- signal, WaitDropTabReq::SignalLength, JBB);
-
- nodePtr.i = nodePtr.p->nextNode;
- }
- }
-
- waitDropTabWritingToFile(signal, tabPtr);
-}
-
-void
-Dbdih::waitDropTabWritingToFile(Signal* signal, TabRecordPtr tabPtr){
-
- if(tabPtr.p->tabLcpStatus == TabRecord::TLS_WRITING_TO_FILE){
- jam();
- signal->theData[0] = DihContinueB::WAIT_DROP_TAB_WRITING_TO_FILE;
- signal->theData[1] = tabPtr.i;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
- return;
- }
-
- ndbrequire(tabPtr.p->tabLcpStatus == TabRecord::TLS_COMPLETED);
- checkPrepDropTabComplete(signal, tabPtr);
-}
-
-void
-Dbdih::checkPrepDropTabComplete(Signal* signal, TabRecordPtr tabPtr){
-
- if(tabPtr.p->tabLcpStatus != TabRecord::TLS_COMPLETED){
- jam();
- return;
- }
-
- if(!tabPtr.p->m_prepDropTab.waitDropTabCount.done()){
- jam();
- return;
- }
-
- const Uint32 ref = tabPtr.p->m_prepDropTab.senderRef;
- if(ref != 0){
- PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
- conf->tableId = tabPtr.i;
- conf->senderRef = reference();
- conf->senderData = tabPtr.p->m_prepDropTab.senderData;
- sendSignal(tabPtr.p->m_prepDropTab.senderRef, GSN_PREP_DROP_TAB_CONF,
- signal, PrepDropTabConf::SignalLength, JBB);
- tabPtr.p->m_prepDropTab.senderRef = 0;
- }
-}
-
-void
-Dbdih::execWAIT_DROP_TAB_REF(Signal* signal){
- jamEntry();
- WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr();
-
- TabRecordPtr tabPtr;
- tabPtr.i = ref->tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_DROPPING);
- Uint32 nodeId = refToNode(ref->senderRef);
-
- ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable ||
- ref->errorCode == WaitDropTabRef::NF_FakeErrorREF);
-
- tabPtr.p->m_prepDropTab.waitDropTabCount.clearWaitingFor(nodeId);
- checkPrepDropTabComplete(signal, tabPtr);
-}
-
-void
-Dbdih::execWAIT_DROP_TAB_CONF(Signal* signal){
- jamEntry();
- WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
-
- TabRecordPtr tabPtr;
- tabPtr.i = conf->tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_DROPPING);
- Uint32 nodeId = refToNode(conf->senderRef);
- tabPtr.p->m_prepDropTab.waitDropTabCount.clearWaitingFor(nodeId);
- checkPrepDropTabComplete(signal, tabPtr);
-}
-
-void
-Dbdih::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId){
-
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
-
- WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
- conf->tableId = tableId;
-
- const Uint32 RT_BREAK = 16;
- for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabFileSize; i++, tabPtr.i++){
- ptrAss(tabPtr, tabRecord);
- if(tabPtr.p->tabStatus == TabRecord::TS_DROPPING){
- if(tabPtr.p->m_prepDropTab.waitDropTabCount.isWaitingFor(nodeId)){
- conf->senderRef = calcLqhBlockRef(nodeId);
- execWAIT_DROP_TAB_CONF(signal);
- tabPtr.i++;
- break;
- }
- }
- }
-
- if(tabPtr.i == ctabFileSize){
- /**
- * Finished
- */
- jam();
- return;
- }
-
- signal->theData[0] = DihContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-}
-
-
-void
-Dbdih::execNDB_TAMPER(Signal* signal)
-{
- if ((ERROR_INSERTED(7011)) &&
- (signal->theData[0] == 7012)) {
- CLEAR_ERROR_INSERT_VALUE;
- calculateKeepGciLab(signal, 0, 0);
- return;
- }//if
- SET_ERROR_INSERT_VALUE(signal->theData[0]);
- return;
-}//Dbdih::execNDB_TAMPER()
-
-void Dbdih::execBLOCK_COMMIT_ORD(Signal* signal){
- BlockCommitOrd* const block = (BlockCommitOrd *)&signal->theData[0];
-
- jamEntry();
-#if 0
- ndbrequire(c_blockCommit == false ||
- c_blockCommitNo == block->failNo);
-#else
- if(!(c_blockCommit == false || c_blockCommitNo == block->failNo)){
- infoEvent("Possible bug in Dbdih::execBLOCK_COMMIT_ORD c_blockCommit = %d c_blockCommitNo = %d"
- " sig->failNo = %d", c_blockCommit, c_blockCommitNo, block->failNo);
- }
-#endif
- c_blockCommit = true;
- c_blockCommitNo = block->failNo;
-}
-
-void Dbdih::execUNBLOCK_COMMIT_ORD(Signal* signal){
- UnblockCommitOrd* const unblock = (UnblockCommitOrd *)&signal->theData[0];
- (void)unblock;
-
- jamEntry();
-
- if(c_blockCommit == true){
- jam();
- // ndbrequire(c_blockCommitNo == unblock->failNo);
-
- c_blockCommit = false;
- emptyverificbuffer(signal, true);
- }
-}
-
-void Dbdih::execSTOP_PERM_REQ(Signal* signal){
-
- jamEntry();
-
- StopPermReq* const req = (StopPermReq*)&signal->theData[0];
- StopPermRef* const ref = (StopPermRef*)&signal->theData[0];
-
- const Uint32 senderData = req->senderData;
- const BlockReference senderRef = req->senderRef;
- const NodeId nodeId = refToNode(senderRef);
-
- if (isMaster()) {
- /**
- * Master
- */
- jam();
- CRASH_INSERTION(7065);
- if (c_stopPermMaster.clientRef != 0) {
- jam();
-
- ref->senderData = senderData;
- ref->errorCode = StopPermRef::NodeShutdownInProgress;
- sendSignal(senderRef, GSN_STOP_PERM_REF, signal,
- StopPermRef::SignalLength, JBB);
- return;
- }//if
-
- if (c_nodeStartMaster.activeState) {
- jam();
- ref->senderData = senderData;
- ref->errorCode = StopPermRef::NodeStartInProgress;
- sendSignal(senderRef, GSN_STOP_PERM_REF, signal,
- StopPermRef::SignalLength, JBB);
- return;
- }//if
-
- /**
- * Lock
- */
- c_nodeStartMaster.activeState = true;
- c_stopPermMaster.clientRef = senderRef;
-
- c_stopPermMaster.clientData = senderData;
- c_stopPermMaster.returnValue = 0;
- c_switchReplicas.clear();
-
- Mutex mutex(signal, c_mutexMgr, c_switchPrimaryMutexHandle);
- Callback c = { safe_cast(&Dbdih::switch_primary_stop_node), nodeId };
- ndbrequire(mutex.lock(c));
- } else {
- /**
- * Proxy part
- */
- jam();
- CRASH_INSERTION(7066);
- if(c_stopPermProxy.clientRef != 0){
- jam();
- ref->senderData = senderData;
- ref->errorCode = StopPermRef::NodeShutdownInProgress;
- sendSignal(senderRef, GSN_STOP_PERM_REF, signal, 2, JBB);
- return;
- }//if
-
- c_stopPermProxy.clientRef = senderRef;
- c_stopPermProxy.masterRef = cmasterdihref;
- c_stopPermProxy.clientData = senderData;
-
- req->senderRef = reference();
- req->senderData = senderData;
- sendSignal(cmasterdihref, GSN_STOP_PERM_REQ, signal,
- StopPermReq::SignalLength, JBB);
- }//if
-}//Dbdih::execSTOP_PERM_REQ()
-
-void
-Dbdih::switch_primary_stop_node(Signal* signal, Uint32 node_id, Uint32 ret_val)
-{
- ndbrequire(ret_val == 0);
- signal->theData[0] = DihContinueB::SwitchReplica;
- signal->theData[1] = node_id;
- signal->theData[2] = 0; // table id
- signal->theData[3] = 0; // fragment id
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
-}
-
-void Dbdih::execSTOP_PERM_REF(Signal* signal)
-{
- jamEntry();
- ndbrequire(c_stopPermProxy.clientRef != 0);
- ndbrequire(c_stopPermProxy.masterRef == signal->senderBlockRef());
- sendSignal(c_stopPermProxy.clientRef, GSN_STOP_PERM_REF, signal, 2, JBB);
- c_stopPermProxy.clientRef = 0;
-}//Dbdih::execSTOP_PERM_REF()
-
-void Dbdih::execSTOP_PERM_CONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(c_stopPermProxy.clientRef != 0);
- ndbrequire(c_stopPermProxy.masterRef == signal->senderBlockRef());
- sendSignal(c_stopPermProxy.clientRef, GSN_STOP_PERM_CONF, signal, 1, JBB);
- c_stopPermProxy.clientRef = 0;
-}//Dbdih::execSTOP_PERM_CONF()
-
-void Dbdih::execDIH_SWITCH_REPLICA_REQ(Signal* signal)
-{
- jamEntry();
- DihSwitchReplicaReq* const req = (DihSwitchReplicaReq*)&signal->theData[0];
- const Uint32 tableId = req->tableId;
- const Uint32 fragNo = req->fragNo;
- const BlockReference senderRef = req->senderRef;
-
- CRASH_INSERTION(7067);
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
- if (tabPtr.p->tabCopyStatus != TabRecord::CS_IDLE) {
- jam();
- sendSignal(reference(), GSN_DIH_SWITCH_REPLICA_REQ, signal,
- DihSwitchReplicaReq::SignalLength, JBB);
- return;
- }//if
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragNo, fragPtr);
-
- /**
- * Do funky stuff
- */
- Uint32 oldOrder[MAX_REPLICAS];
- const Uint32 noOfReplicas = extractNodeInfo(fragPtr.p, oldOrder);
-
- if (noOfReplicas < req->noOfReplicas) {
- jam();
- //---------------------------------------------------------------------
- // A crash occurred in the middle of our switch handling.
- //---------------------------------------------------------------------
- DihSwitchReplicaRef* const ref = (DihSwitchReplicaRef*)&signal->theData[0];
- ref->senderNode = cownNodeId;
- ref->errorCode = StopPermRef::NF_CausedAbortOfStopProcedure;
- sendSignal(senderRef, GSN_DIH_SWITCH_REPLICA_REF, signal,
- DihSwitchReplicaRef::SignalLength, JBB);
- }//if
- for (Uint32 i = 0; i < noOfReplicas; i++) {
- jam();
- ndbrequire(i < MAX_REPLICAS);
- fragPtr.p->activeNodes[i] = req->newNodeOrder[i];
- }//for
- /**
- * Reply
- */
- DihSwitchReplicaConf* const conf = (DihSwitchReplicaConf*)&signal->theData[0];
- conf->senderNode = cownNodeId;
- sendSignal(senderRef, GSN_DIH_SWITCH_REPLICA_CONF, signal,
- DihSwitchReplicaConf::SignalLength, JBB);
-}//Dbdih::execDIH_SWITCH_REPLICA_REQ()
-
-void Dbdih::execDIH_SWITCH_REPLICA_CONF(Signal* signal)
-{
- jamEntry();
- /**
- * Response to master
- */
- CRASH_INSERTION(7068);
- DihSwitchReplicaConf* const conf = (DihSwitchReplicaConf*)&signal->theData[0];
- switchReplicaReply(signal, conf->senderNode);
-}//Dbdih::execDIH_SWITCH_REPLICA_CONF()
-
-void Dbdih::execDIH_SWITCH_REPLICA_REF(Signal* signal)
-{
- jamEntry();
- DihSwitchReplicaRef* const ref = (DihSwitchReplicaRef*)&signal->theData[0];
- if(c_stopPermMaster.returnValue == 0){
- jam();
- c_stopPermMaster.returnValue = ref->errorCode;
- }//if
- switchReplicaReply(signal, ref->senderNode);
-}//Dbdih::execDIH_SWITCH_REPLICA_REF()
-
-void Dbdih::switchReplicaReply(Signal* signal,
- NodeId nodeId){
- jam();
- receiveLoopMacro(DIH_SWITCH_REPLICA_REQ, nodeId);
- //------------------------------------------------------
- // We have received all responses from the nodes. Thus
- // we have completed switching replica roles. Continue
- // with the next fragment.
- //------------------------------------------------------
- if(c_stopPermMaster.returnValue != 0){
- jam();
- c_switchReplicas.tableId = ctabFileSize + 1;
- }//if
- c_switchReplicas.fragNo++;
-
- signal->theData[0] = DihContinueB::SwitchReplica;
- signal->theData[1] = c_switchReplicas.nodeId;
- signal->theData[2] = c_switchReplicas.tableId;
- signal->theData[3] = c_switchReplicas.fragNo;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
-}//Dbdih::switchReplicaReply()
-
-void
-Dbdih::switchReplica(Signal* signal,
- Uint32 nodeId,
- Uint32 tableId,
- Uint32 fragNo){
- jam();
- DihSwitchReplicaReq* const req = (DihSwitchReplicaReq*)&signal->theData[0];
-
- const Uint32 RT_BREAK = 64;
-
- for (Uint32 i = 0; i < RT_BREAK; i++) {
- jam();
- if (tableId >= ctabFileSize) {
- jam();
- StopPermConf* const conf = (StopPermConf*)&signal->theData[0];
- StopPermRef* const ref = (StopPermRef*)&signal->theData[0];
- /**
- * Finished with all tables
- */
- if(c_stopPermMaster.returnValue == 0) {
- jam();
- conf->senderData = c_stopPermMaster.clientData;
- sendSignal(c_stopPermMaster.clientRef, GSN_STOP_PERM_CONF,
- signal, 1, JBB);
- } else {
- jam();
- ref->senderData = c_stopPermMaster.clientData;
- ref->errorCode = c_stopPermMaster.returnValue;
- sendSignal(c_stopPermMaster.clientRef, GSN_STOP_PERM_REF, signal, 2,JBB);
- }//if
-
- /**
- * UnLock
- */
- c_nodeStartMaster.activeState = false;
- c_stopPermMaster.clientRef = 0;
- c_stopPermMaster.clientData = 0;
- c_stopPermMaster.returnValue = 0;
- Mutex mutex(signal, c_mutexMgr, c_switchPrimaryMutexHandle);
- mutex.unlock(); // ignore result
- return;
- }//if
-
- TabRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
-
- if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE) {
- jam();
- tableId++;
- fragNo = 0;
- continue;
- }//if
- if (fragNo >= tabPtr.p->totalfragments) {
- jam();
- tableId++;
- fragNo = 0;
- continue;
- }//if
- FragmentstorePtr fragPtr;
- getFragstore(tabPtr.p, fragNo, fragPtr);
-
- Uint32 oldOrder[MAX_REPLICAS];
- const Uint32 noOfReplicas = extractNodeInfo(fragPtr.p, oldOrder);
-
- if(oldOrder[0] != nodeId) {
- jam();
- fragNo++;
- continue;
- }//if
- req->tableId = tableId;
- req->fragNo = fragNo;
- req->noOfReplicas = noOfReplicas;
- for (Uint32 i = 0; i < (noOfReplicas - 1); i++) {
- req->newNodeOrder[i] = oldOrder[i+1];
- }//for
- req->newNodeOrder[noOfReplicas-1] = nodeId;
- req->senderRef = reference();
-
- /**
- * Initialize struct
- */
- c_switchReplicas.tableId = tableId;
- c_switchReplicas.fragNo = fragNo;
- c_switchReplicas.nodeId = nodeId;
-
- sendLoopMacro(DIH_SWITCH_REPLICA_REQ, sendDIH_SWITCH_REPLICA_REQ);
- return;
- }//for
-
- signal->theData[0] = DihContinueB::SwitchReplica;
- signal->theData[1] = nodeId;
- signal->theData[2] = tableId;
- signal->theData[3] = fragNo;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
-}//Dbdih::switchReplica()
-
-void Dbdih::execSTOP_ME_REQ(Signal* signal)
-{
- jamEntry();
- StopMeReq* const req = (StopMeReq*)&signal->theData[0];
- const BlockReference senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
- const Uint32 nodeId = refToNode(senderRef);
- {
- /**
- * Set node dead (remove from operations)
- */
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- nodePtr.p->useInTransactions = false;
- }
- if (nodeId != getOwnNodeId()) {
- jam();
- StopMeConf * const stopMeConf = (StopMeConf *)&signal->theData[0];
- stopMeConf->senderData = senderData;
- stopMeConf->senderRef = reference();
- sendSignal(senderRef, GSN_STOP_ME_CONF, signal,
- StopMeConf::SignalLength, JBB);
- return;
- }//if
-
- /**
- * Local signal
- */
- jam();
- ndbrequire(c_stopMe.clientRef == 0);
-
- c_stopMe.clientData = senderData;
- c_stopMe.clientRef = senderRef;
-
- req->senderData = senderData;
- req->senderRef = reference();
-
- sendLoopMacro(STOP_ME_REQ, sendSTOP_ME_REQ);
-
- /**
- * Send conf to self
- */
- StopMeConf * const stopMeConf = (StopMeConf *)&signal->theData[0];
- stopMeConf->senderData = senderData;
- stopMeConf->senderRef = reference();
- sendSignal(reference(), GSN_STOP_ME_CONF, signal,
- StopMeConf::SignalLength, JBB);
-}//Dbdih::execSTOP_ME_REQ()
-
-void Dbdih::execSTOP_ME_REF(Signal* signal)
-{
- ndbrequire(false);
-}
-
-void Dbdih::execSTOP_ME_CONF(Signal* signal)
-{
- jamEntry();
- StopMeConf * const stopMeConf = (StopMeConf *)&signal->theData[0];
-
- const Uint32 senderRef = stopMeConf->senderRef;
- const Uint32 senderData = stopMeConf->senderData;
- const Uint32 nodeId = refToNode(senderRef);
-
- ndbrequire(c_stopMe.clientRef != 0);
- ndbrequire(c_stopMe.clientData == senderData);
-
- receiveLoopMacro(STOP_ME_REQ, nodeId);
- //---------------------------------------------------------
- // All STOP_ME_REQ have been received. We will send the
- // confirmation back to the requesting block.
- //---------------------------------------------------------
-
- stopMeConf->senderRef = reference();
- stopMeConf->senderData = c_stopMe.clientData;
- sendSignal(c_stopMe.clientRef, GSN_STOP_ME_CONF, signal,
- StopMeConf::SignalLength, JBB);
- c_stopMe.clientRef = 0;
-}//Dbdih::execSTOP_ME_CONF()
-
-void Dbdih::execWAIT_GCP_REQ(Signal* signal)
-{
- jamEntry();
- WaitGCPReq* const req = (WaitGCPReq*)&signal->theData[0];
- WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0];
- WaitGCPConf* const conf = (WaitGCPConf*)&signal->theData[0];
- const Uint32 senderData = req->senderData;
- const BlockReference senderRef = req->senderRef;
- const Uint32 requestType = req->requestType;
-
- if(requestType == WaitGCPReq::CurrentGCI) {
- jam();
- conf->senderData = senderData;
- conf->gcp = cnewgcp;
- conf->blockStatus = cgcpOrderBlocked;
- sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
- WaitGCPConf::SignalLength, JBB);
- return;
- }//if
-
- if (requestType == WaitGCPReq::BlockStartGcp)
- {
- jam();
- conf->senderData = senderData;
- conf->gcp = cnewgcp;
- conf->blockStatus = cgcpOrderBlocked;
- sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
- WaitGCPConf::SignalLength, JBB);
- cgcpOrderBlocked = 1;
- return;
- }
-
- if (requestType == WaitGCPReq::UnblockStartGcp)
- {
- jam();
- conf->senderData = senderData;
- conf->gcp = cnewgcp;
- conf->blockStatus = cgcpOrderBlocked;
- sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
- WaitGCPConf::SignalLength, JBB);
- cgcpOrderBlocked = 0;
- return;
- }
-
- if(isMaster()) {
- /**
- * Master
- */
- jam();
-
- if((requestType == WaitGCPReq::CompleteIfRunning) &&
- (cgcpStatus == GCP_READY)) {
- jam();
- conf->senderData = senderData;
- conf->gcp = coldgcp;
- conf->blockStatus = cgcpOrderBlocked;
- sendSignal(senderRef, GSN_WAIT_GCP_CONF, signal,
- WaitGCPConf::SignalLength, JBB);
- return;
- }//if
-
- WaitGCPMasterPtr ptr;
- if(c_waitGCPMasterList.seize(ptr) == false){
- jam();
- ref->senderData = senderData;
- ref->errorCode = WaitGCPRef::NoWaitGCPRecords;
- sendSignal(senderRef, GSN_WAIT_GCP_REF, signal,
- WaitGCPRef::SignalLength, JBB);
- return;
- }//if
- ptr.p->clientRef = senderRef;
- ptr.p->clientData = senderData;
-
- if((requestType == WaitGCPReq::CompleteForceStart) &&
- (cgcpStatus == GCP_READY)) {
- jam();
- cstartGcpNow = true;
- }//if
- return;
- } else {
- /**
- * Proxy part
- */
- jam();
- WaitGCPProxyPtr ptr;
- if (c_waitGCPProxyList.seize(ptr) == false) {
- jam();
- ref->senderData = senderData;
- ref->errorCode = WaitGCPRef::NoWaitGCPRecords;
- sendSignal(senderRef, GSN_WAIT_GCP_REF, signal,
- WaitGCPRef::SignalLength, JBB);
- return;
- }//if
- ptr.p->clientRef = senderRef;
- ptr.p->clientData = senderData;
- ptr.p->masterRef = cmasterdihref;
-
- req->senderData = ptr.i;
- req->senderRef = reference();
- req->requestType = requestType;
-
- sendSignal(cmasterdihref, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBB);
- return;
- }//if
-}//Dbdih::execWAIT_GCP_REQ()
-
-void Dbdih::execWAIT_GCP_REF(Signal* signal)
-{
- jamEntry();
- ndbrequire(!isMaster());
- WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0];
-
- const Uint32 proxyPtr = ref->senderData;
- const Uint32 errorCode = ref->errorCode;
-
- WaitGCPProxyPtr ptr;
- ptr.i = proxyPtr;
- c_waitGCPProxyList.getPtr(ptr);
-
- ref->senderData = ptr.p->clientData;
- ref->errorCode = errorCode;
- sendSignal(ptr.p->clientRef, GSN_WAIT_GCP_REF, signal,
- WaitGCPRef::SignalLength, JBB);
-
- c_waitGCPProxyList.release(ptr);
-}//Dbdih::execWAIT_GCP_REF()
-
-void Dbdih::execWAIT_GCP_CONF(Signal* signal)
-{
- jamEntry();
- ndbrequire(!isMaster());
- WaitGCPConf* const conf = (WaitGCPConf*)&signal->theData[0];
- const Uint32 proxyPtr = conf->senderData;
- const Uint32 gcp = conf->gcp;
- WaitGCPProxyPtr ptr;
-
- ptr.i = proxyPtr;
- c_waitGCPProxyList.getPtr(ptr);
-
- conf->senderData = ptr.p->clientData;
- conf->gcp = gcp;
- conf->blockStatus = cgcpOrderBlocked;
- sendSignal(ptr.p->clientRef, GSN_WAIT_GCP_CONF, signal,
- WaitGCPConf::SignalLength, JBB);
-
- c_waitGCPProxyList.release(ptr);
-}//Dbdih::execWAIT_GCP_CONF()
-
-void Dbdih::checkWaitGCPProxy(Signal* signal, NodeId failedNodeId)
-{
- jam();
- WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0];
- ref->errorCode = WaitGCPRef::NF_CausedAbortOfProcedure;
-
- WaitGCPProxyPtr ptr;
- c_waitGCPProxyList.first(ptr);
- while(ptr.i != RNIL) {
- jam();
- const Uint32 i = ptr.i;
- const Uint32 clientData = ptr.p->clientData;
- const BlockReference clientRef = ptr.p->clientRef;
- const BlockReference masterRef = ptr.p->masterRef;
-
- c_waitGCPProxyList.next(ptr);
- if(refToNode(masterRef) == failedNodeId) {
- jam();
- c_waitGCPProxyList.release(i);
- ref->senderData = clientData;
- sendSignal(clientRef, GSN_WAIT_GCP_REF, signal,
- WaitGCPRef::SignalLength, JBB);
- }//if
- }//while
-}//Dbdih::checkWaitGCPProxy()
-
-void Dbdih::checkWaitGCPMaster(Signal* signal, NodeId failedNodeId)
-{
- jam();
- WaitGCPMasterPtr ptr;
- c_waitGCPMasterList.first(ptr);
-
- while (ptr.i != RNIL) {
- jam();
- const Uint32 i = ptr.i;
- const NodeId nodeId = refToNode(ptr.p->clientRef);
-
- c_waitGCPMasterList.next(ptr);
- if (nodeId == failedNodeId) {
- jam()
- c_waitGCPMasterList.release(i);
- }//if
- }//while
-}//Dbdih::checkWaitGCPMaster()
-
-void Dbdih::emptyWaitGCPMasterQueue(Signal* signal)
-{
- jam();
- WaitGCPConf* const conf = (WaitGCPConf*)&signal->theData[0];
- conf->gcp = coldgcp;
-
- WaitGCPMasterPtr ptr;
- c_waitGCPMasterList.first(ptr);
- while(ptr.i != RNIL) {
- jam();
- const Uint32 i = ptr.i;
- const Uint32 clientData = ptr.p->clientData;
- const BlockReference clientRef = ptr.p->clientRef;
-
- c_waitGCPMasterList.next(ptr);
- conf->senderData = clientData;
- conf->blockStatus = cgcpOrderBlocked;
- sendSignal(clientRef, GSN_WAIT_GCP_CONF, signal,
- WaitGCPConf::SignalLength, JBB);
-
- c_waitGCPMasterList.release(i);
- }//while
-}//Dbdih::emptyWaitGCPMasterQueue()
-
-void Dbdih::setNodeStatus(Uint32 nodeId, NodeRecord::NodeStatus newStatus)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- nodePtr.p->nodeStatus = newStatus;
-}//Dbdih::setNodeStatus()
-
-Dbdih::NodeRecord::NodeStatus Dbdih::getNodeStatus(Uint32 nodeId)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- return nodePtr.p->nodeStatus;
-}//Dbdih::getNodeStatus()
-
-Sysfile::ActiveStatus
-Dbdih::getNodeActiveStatus(Uint32 nodeId)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- return nodePtr.p->activeStatus;
-}//Dbdih::getNodeActiveStatus()
-
-
-void
-Dbdih::setNodeActiveStatus(Uint32 nodeId, Sysfile::ActiveStatus newStatus)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- nodePtr.p->activeStatus = newStatus;
-}//Dbdih::setNodeActiveStatus()
-
-void Dbdih::setAllowNodeStart(Uint32 nodeId, bool newState)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- nodePtr.p->allowNodeStart = newState;
-}//Dbdih::setAllowNodeStart()
-
-void Dbdih::setNodeCopyCompleted(Uint32 nodeId, bool newState)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- nodePtr.p->copyCompleted = newState;
-}//Dbdih::setNodeCopyCompleted()
-
-bool Dbdih::getAllowNodeStart(Uint32 nodeId)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- return nodePtr.p->allowNodeStart;
-}//Dbdih::getAllowNodeStart()
-
-bool Dbdih::getNodeCopyCompleted(Uint32 nodeId)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- return nodePtr.p->copyCompleted;
-}//Dbdih::getNodeCopyCompleted()
-
-bool Dbdih::checkNodeAlive(Uint32 nodeId)
-{
- NodeRecordPtr nodePtr;
- nodePtr.i = nodeId;
- ndbrequire(nodeId > 0);
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (nodePtr.p->nodeStatus != NodeRecord::ALIVE) {
- return false;
- } else {
- return true;
- }//if
-}//Dbdih::checkNodeAlive()
-
-bool Dbdih::isMaster()
-{
- return (reference() == cmasterdihref);
-}//Dbdih::isMaster()
-
-bool Dbdih::isActiveMaster()
-{
- return ((reference() == cmasterdihref) && (cmasterState == MASTER_ACTIVE));
-}//Dbdih::isActiveMaster()
-
-Dbdih::NodeRecord::NodeRecord(){
- m_nodefailSteps.clear();
- gcpstate = NodeRecord::READY;
-
- activeStatus = Sysfile::NS_NotDefined;
- recNODE_FAILREP = ZFALSE;
- nodeGroup = ZNIL;
- dbtcFailCompleted = ZTRUE;
- dbdictFailCompleted = ZTRUE;
- dbdihFailCompleted = ZTRUE;
- dblqhFailCompleted = ZTRUE;
- noOfStartedChkpt = 0;
- noOfQueuedChkpt = 0;
- lcpStateAtTakeOver = (MasterLCPConf::State)255;
-
- activeTabptr = RNIL;
- nodeStatus = NodeRecord::NOT_IN_CLUSTER;
- useInTransactions = false;
- copyCompleted = false;
- allowNodeStart = true;
-}
-
-// 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;
-
- const unsigned int get_major = getMajor(masterVersion);
- const unsigned int get_minor = getMinor(masterVersion);
- const unsigned int get_build = getBuild(masterVersion);
- ndbrequire(get_major >= 4);
-
- if (masterVersion < NDBD_DICT_LOCK_VERSION_5 ||
- masterVersion < NDBD_DICT_LOCK_VERSION_5_1 &&
- get_major == 5 && get_minor == 1 ||
- 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;
-
- const unsigned int get_major = getMajor(masterVersion);
- const unsigned int get_minor = getMinor(masterVersion);
- ndbrequire(get_major >= 4);
-
- if (masterVersion < NDBD_DICT_LOCK_VERSION_5 ||
- masterVersion < NDBD_DICT_LOCK_VERSION_5_1 &&
- get_major == 5 && get_minor == 1 ||
- ERROR_INSERTED(7176)) {
- return;
- }
- }
-
- BlockReference dictMasterRef = calcDictBlockRef(cmasterNodeId);
- sendSignal(dictMasterRef, GSN_DICT_UNLOCK_ORD, signal,
- DictUnlockOrd::SignalLength, JBB);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbdih/LCP.txt b/storage/ndb/src/kernel/blocks/dbdih/LCP.txt
deleted file mode 100644
index 500c82f6baf..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/LCP.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-Master DIH LQH
-========== ==========
-
-1) TCGETOPSIZEREQ -> all TC
-
-2) If sum(operation size) < Threshold
- Goto 1
-
-3) For each table
- Calc Keep GCI (local using CONTINUEB)
-
-4) COPY_GCIREQ -> all DIH
-
-5) TC_CLOPSIZEREQ -> all TC
-
-6) For each fragment
- LCP_FRAG_ORD -> LQH
-
- Do LCP...
- 1) LCP_FRAG_REP -> all DIH
- 2) If last fragment
- LCP_COMPLETE_REP -> all DIH
-
-7) When receiving LCP_COMPLETE_REP from DIH
- 1) If all DIHs have completed
- Goto 1
-
-All DIHs
-==========
-1) When receiving LCP_FRAG_REP
- If all fragments & replicas done in table
- 1) Save Table descriptor
- 2) If all tables done + LCP_COMPLETE_REP(from lqh) has arrived
- LCP_COMPLETE_REP -> master DIH
diff --git a/storage/ndb/src/kernel/blocks/dbdih/Makefile.am b/storage/ndb/src/kernel/blocks/dbdih/Makefile.am
deleted file mode 100644
index 7e667878d83..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2004-2005 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-ndbtools_PROGRAMS = ndb_print_sys_file
-ndb_print_sys_file_SOURCES = printSysfile.cpp
-ndb_print_sys_file_LDFLAGS = @ndb_bin_am_ldflags@ \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a
-
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
diff --git a/storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp b/storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp
deleted file mode 100644
index ae489bafa90..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SYSFILE_HPP
-#define SYSFILE_HPP
-
-#include <ndb_types.h>
-#include <ndb_limits.h>
-#include <NodeBitmask.hpp>
-
-/**
- * No bits in Sysfile to represent nodeid
- */
-#define NODEID_BITS 8
-
-/**
- * Constant representing that node do not belong to
- * any node group
- */
-#define NO_NODE_GROUP_ID ((1 << NODEID_BITS) - 1)
-
-/**
- * No of 32 bits word in sysfile
- *
- * 6 + // was 5 in < version 5.1
- * MAX_NDB_NODES + // lastCompletedGCI
- * NODE_ARRAY_SIZE(MAX_NDB_NODES, 4) + // nodeStatus
- * NODE_ARRAY_SIZE(MAX_NDB_NODES, NODEID_BITS) + // nodeGroups
- * NODE_ARRAY_SIZE(MAX_NDB_NODES, NODEID_BITS) + // takeOver
- * NodeBitmask::NDB_NODE_BITMASK_SIZE // Lcp Active
- */
-#define _SYSFILE_SIZE32 (6 + \
- MAX_NDB_NODES + \
- NODE_ARRAY_SIZE(MAX_NDB_NODES, 4) + \
- NODE_ARRAY_SIZE(MAX_NDB_NODES, NODEID_BITS) + \
- NODE_ARRAY_SIZE(MAX_NDB_NODES, NODEID_BITS) + \
- _NDB_NODE_BITMASK_SIZE)
-
-/**
- * This struct defines the format of P<X>.sysfile
- */
-struct Sysfile {
-public:
-
- /**
- * No of 32 bits words in the sysfile
- */
- STATIC_CONST( SYSFILE_SIZE32 = _SYSFILE_SIZE32 );
-
- Uint32 systemRestartBits;
-
- /**
- * Restart seq for _this_ node...
- */
- Uint32 m_restart_seq;
-
- static bool getInitialStartOngoing(const Uint32 & systemRestartBits);
- static void setInitialStartOngoing(Uint32 & systemRestartBits);
- static void clearInitialStartOngoing(Uint32 & systemRestartBits);
-
- static bool getRestartOngoing(const Uint32 & systemRestartBits);
- static void setRestartOngoing(Uint32 & systemRestartBits);
- static void clearRestartOngoing(Uint32 & systemRestartBits);
-
- static bool getLCPOngoing(const Uint32 & systemRestartBits);
- static void setLCPOngoing(Uint32 & systemRestartBits);
- static void clearLCPOngoing(Uint32 & systemRestartBits);
-
- Uint32 keepGCI;
- Uint32 oldestRestorableGCI;
- Uint32 newestRestorableGCI;
- Uint32 latestLCP_ID;
-
- /**
- * Last completed GCI for each node
- */
- Uint32 lastCompletedGCI[MAX_NDB_NODES];
-
- /**
- * Active status bits
- *
- * It takes 4 bits to represent it
- */
- enum ActiveStatus {
- NS_Active = 0
- ,NS_ActiveMissed_1 = 1
- ,NS_ActiveMissed_2 = 2
- ,NS_ActiveMissed_3 = 3
- ,NS_HotSpare = 4
- ,NS_NotActive_NotTakenOver = 5
- ,NS_TakeOver = 6
- ,NS_NotActive_TakenOver = 7
- ,NS_NotDefined = 8
- ,NS_Standby = 9
- };
- STATIC_CONST( NODE_STATUS_SIZE = NODE_ARRAY_SIZE(MAX_NDB_NODES, 4) );
- Uint32 nodeStatus[NODE_STATUS_SIZE];
-
- static Uint32 getNodeStatus(NodeId, const Uint32 nodeStatus[]);
- static void setNodeStatus(NodeId, Uint32 nodeStatus[], Uint32 status);
-
- /**
- * The node group of each node
- * Sizeof(NodeGroup) = 8 Bit
- */
- STATIC_CONST( NODE_GROUPS_SIZE = NODE_ARRAY_SIZE(MAX_NDB_NODES,
- NODEID_BITS) );
- Uint32 nodeGroups[NODE_GROUPS_SIZE];
-
- static Uint16 getNodeGroup(NodeId, const Uint32 nodeGroups[]);
- static void setNodeGroup(NodeId, Uint32 nodeGroups[], Uint16 group);
-
- /**
- * Any node can take over for any node
- */
- STATIC_CONST( TAKE_OVER_SIZE = NODE_ARRAY_SIZE(MAX_NDB_NODES,
- NODEID_BITS) );
- Uint32 takeOver[TAKE_OVER_SIZE];
-
- static NodeId getTakeOverNode(NodeId, const Uint32 takeOver[]);
- static void setTakeOverNode(NodeId, Uint32 takeOver[], NodeId toNode);
-
- /**
- * Is a node running a LCP
- */
- Uint32 lcpActive[NdbNodeBitmask::Size];
-};
-
-#if (MAX_NDB_NODES > (1<<NODEID_BITS))
-#error "Sysfile node id is too small"
-#endif
-
-/**
- * Restart Info
- *
- * i = Initial start completed
- * r = Crash during system restart
- * l = Crash during local checkpoint
-
- * 1111111111222222222233
- * 01234567890123456789012345678901
- * irl
- */
-inline
-bool
-Sysfile::getInitialStartOngoing(const Uint32 & systemRestartBits){
- return systemRestartBits & 1;
-}
-
-inline
-void
-Sysfile::setInitialStartOngoing(Uint32 & systemRestartBits){
- systemRestartBits |= 1;
-}
-
-inline
-void
-Sysfile::clearInitialStartOngoing(Uint32 & systemRestartBits){
- systemRestartBits &= ~1;
-}
-
-inline
-bool
-Sysfile::getRestartOngoing(const Uint32 & systemRestartBits){
- return (systemRestartBits & 2) != 0;
-}
-
-inline
-void
-Sysfile::setRestartOngoing(Uint32 & systemRestartBits){
- systemRestartBits |= 2;
-}
-
-inline
-void
-Sysfile::clearRestartOngoing(Uint32 & systemRestartBits){
- systemRestartBits &= ~2;
-}
-
-inline
-bool
-Sysfile::getLCPOngoing(const Uint32 & systemRestartBits){
- return systemRestartBits & 4;
-}
-
-inline
-void
-Sysfile::setLCPOngoing(Uint32 & systemRestartBits){
- systemRestartBits |= 4;
-}
-
-inline
-void
-Sysfile::clearLCPOngoing(Uint32 & systemRestartBits){
- systemRestartBits &= ~4;
-}
-
-inline
-Uint32
-Sysfile::getNodeStatus(NodeId nodeId, const Uint32 nodeStatus[]){
- const int word = nodeId >> 3;
- const int shift = (nodeId & 7) << 2;
-
- return (nodeStatus[word] >> shift) & 15;
-}
-
-inline
-void
-Sysfile::setNodeStatus(NodeId nodeId, Uint32 nodeStatus[], Uint32 status){
- const int word = nodeId >> 3;
- const int shift = (nodeId & 7) << 2;
-
- const Uint32 mask = ~(((Uint32)15) << shift);
- const Uint32 tmp = nodeStatus[word];
-
- nodeStatus[word] = (tmp & mask) | ((status & 15) << shift);
-}
-
-inline
-Uint16
-Sysfile::getNodeGroup(NodeId nodeId, const Uint32 nodeGroups[]){
- const int word = nodeId >> 2;
- const int shift = (nodeId & 3) << 3;
-
- return (nodeGroups[word] >> shift) & 255;
-}
-
-inline
-void
-Sysfile::setNodeGroup(NodeId nodeId, Uint32 nodeGroups[], Uint16 group){
- const int word = nodeId >> 2;
- const int shift = (nodeId & 3) << 3;
-
- const Uint32 mask = ~(((Uint32)255) << shift);
- const Uint32 tmp = nodeGroups[word];
-
- nodeGroups[word] = (tmp & mask) | ((group & 255) << shift);
-}
-
-inline
-NodeId
-Sysfile::getTakeOverNode(NodeId nodeId, const Uint32 takeOver[]){
- const int word = nodeId >> 2;
- const int shift = (nodeId & 3) << 3;
-
- return (takeOver[word] >> shift) & 255;
-}
-
-inline
-void
-Sysfile::setTakeOverNode(NodeId nodeId, Uint32 takeOver[], NodeId toNode){
- const int word = nodeId >> 2;
- const int shift = (nodeId & 3) << 3;
-
- const Uint32 mask = ~(((Uint32)255) << shift);
- const Uint32 tmp = takeOver[word];
-
- takeOver[word] = (tmp & mask) | ((toNode & 255) << shift);
-}
-
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp b/storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp
deleted file mode 100644
index 13aeac81f81..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <Sysfile.hpp>
-
-void
-usage(const char * prg){
- ndbout << "Usage " << prg
- << " P[0-1].sysfile" << endl;
-}
-
-struct NSString {
- Sysfile::ActiveStatus NodeStatus;
- const char * desc;
-};
-
-static const
-NSString NodeStatusStrings[] = {
- { Sysfile::NS_Active, "Active " },
- { Sysfile::NS_ActiveMissed_1, "Active missed 1" },
- { Sysfile::NS_ActiveMissed_2, "Active missed 2" },
- { Sysfile::NS_ActiveMissed_3, "Active missed 3" },
- { Sysfile::NS_HotSpare, "Hot spare " },
- { Sysfile::NS_NotActive_NotTakenOver, "Not active " },
- { Sysfile::NS_TakeOver, "Take over " },
- { Sysfile::NS_NotActive_TakenOver, "Taken over " },
- { Sysfile::NS_NotDefined, "Not defined " },
- { Sysfile::NS_Standby, "Stand by " }
-};
-
-const
-char * getNSString(Uint32 ns){
- for(Uint32 i = 0; i<(sizeof(NodeStatusStrings)/sizeof(NSString)); i++)
- if((Uint32)NodeStatusStrings[i].NodeStatus == ns)
- return NodeStatusStrings[i].desc;
- return "<Unknown state>";
-}
-
-void
-fill(const char * buf, int mod){
- int len = strlen(buf)+1;
- ndbout << buf << " ";
- while((len % mod) != 0){
- ndbout << " ";
- len++;
- }
-}
-
-void
-print(const char * filename, const Sysfile * sysfile){
- char buf[255];
- ndbout << "----- Sysfile: " << filename
- << " seq: " << hex << sysfile->m_restart_seq
- << " -----" << endl;
- ndbout << "Initial start ongoing: "
- << Sysfile::getInitialStartOngoing(sysfile->systemRestartBits)
- << ", ";
-
- ndbout << "Restart Ongoing: "
- << Sysfile::getRestartOngoing(sysfile->systemRestartBits)
- << ", ";
-
- ndbout << "LCP Ongoing: "
- << Sysfile::getLCPOngoing(sysfile->systemRestartBits)
- << endl;
-
-
- ndbout << "-- Global Checkpoint Identities: --" << endl;
- sprintf(buf, "keepGCI = %u", sysfile->keepGCI);
- fill(buf, 40);
- ndbout << " -- Tail of REDO log" << endl;
-
- sprintf(buf, "oldestRestorableGCI = %u", sysfile->oldestRestorableGCI);
- fill(buf, 40);
- ndbout << " -- " << endl;
-
- sprintf(buf, "newestRestorableGCI = %u", sysfile->newestRestorableGCI);
- fill(buf, 40);
- ndbout << " -- " << endl;
-
- sprintf(buf, "latestLCP = %u", sysfile->latestLCP_ID);
- fill(buf, 40);
- ndbout << " -- " << endl;
-
- ndbout << "-- Node status: --" << endl;
- for(int i = 1; i < MAX_NDB_NODES; i++){
- if(Sysfile::getNodeStatus(i, sysfile->nodeStatus) !=Sysfile::NS_NotDefined){
- sprintf(buf,
- "Node %.2d -- %s GCP: %d, NodeGroup: %d, TakeOverNode: %d, "
- "LCP Ongoing: %s",
- i,
- getNSString(Sysfile::getNodeStatus(i,sysfile->nodeStatus)),
- sysfile->lastCompletedGCI[i],
- Sysfile::getNodeGroup(i, sysfile->nodeGroups),
- Sysfile::getTakeOverNode(i, sysfile->takeOver),
- BitmaskImpl::get(NdbNodeBitmask::Size,
- sysfile->lcpActive, i) != 0 ? "yes" : "no");
- ndbout << buf << endl;
- }
- }
-}
-
-NDB_COMMAND(printSysfile,
- "printSysfile", "printSysfile", "Prints a sysfile", 16384){
- if(argc < 2){
- usage(argv[0]);
- return 0;
- }
-
- for(int i = 1; i<argc; i++){
- const char * filename = argv[i];
-
- struct stat sbuf;
- const int res = stat(filename, &sbuf);
- if(res != 0){
- ndbout << "Could not find file: \"" << filename << "\"" << endl;
- continue;
- }
- 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;
- continue;
- }
- Uint32 sz = fread(buf, 1, bytes, f);
- fclose(f);
- if(sz != bytes){
- ndbout << "Failure while reading file" << endl;
- delete [] buf;
- continue;
- }
-
- print(filename, (Sysfile *)&buf[0]);
- delete [] buf;
- continue;
- }
- return 0;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbdih/printSysfile/Makefile b/storage/ndb/src/kernel/blocks/dbdih/printSysfile/Makefile
deleted file mode 100644
index 4c4b1026aff..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/printSysfile/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-BIN_TARGET := printSysfile
-BIN_TARGET_ARCHIVES := portlib general
-
-CCFLAGS_LOC += -I..
-
-SOURCES := printSysfile.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/storage/ndb/src/kernel/blocks/dbdih/printSysfile/printSysfile.cpp b/storage/ndb/src/kernel/blocks/dbdih/printSysfile/printSysfile.cpp
deleted file mode 100644
index 49322252349..00000000000
--- a/storage/ndb/src/kernel/blocks/dbdih/printSysfile/printSysfile.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <Sysfile.hpp>
-
-void
-usage(const char * prg){
- ndbout << "Usage " << prg
- << " P[0-1].sysfile" << endl;
-}
-
-struct NSString {
- Sysfile::ActiveStatus NodeStatus;
- const char * desc;
-};
-
-static const
-NSString NodeStatusStrings[] = {
- { Sysfile::NS_Active, "Active " },
- { Sysfile::NS_ActiveMissed_1, "Active missed 1" },
- { Sysfile::NS_ActiveMissed_2, "Active missed 2" },
- { Sysfile::NS_ActiveMissed_3, "Active missed 3" },
- { Sysfile::NS_HotSpare, "Hot spare " },
- { Sysfile::NS_NotActive_NotTakenOver, "Not active " },
- { Sysfile::NS_TakeOver, "Take over " },
- { Sysfile::NS_NotActive_TakenOver, "Taken over " },
- { Sysfile::NS_NotDefined, "Not defined " },
- { Sysfile::NS_Standby, "Stand by " }
-};
-
-const
-char * getNSString(Uint32 ns){
- for(Uint32 i = 0; i<(sizeof(NodeStatusStrings)/sizeof(NSString)); i++)
- if((Uint32)NodeStatusStrings[i].NodeStatus == ns)
- return NodeStatusStrings[i].desc;
- return "<Unknown state>";
-}
-
-void
-fill(const char * buf, int mod){
- int len = strlen(buf)+1;
- ndbout << buf << " ";
- while((len % mod) != 0){
- ndbout << " ";
- len++;
- }
-}
-
-void
-print(const char * filename, const Sysfile * sysfile){
- char buf[255];
- ndbout << "----- Sysfile: " << filename << " -----" << endl;
- ndbout << "Initial start ongoing: "
- << Sysfile::getInitialStartOngoing(sysfile->systemRestartBits)
- << ", ";
-
- ndbout << "Restart Ongoing: "
- << Sysfile::getRestartOngoing(sysfile->systemRestartBits)
- << ", ";
-
- ndbout << "LCP Ongoing: "
- << Sysfile::getLCPOngoing(sysfile->systemRestartBits)
- << endl;
-
-
- ndbout << "-- Global Checkpoint Identities: --" << endl;
- sprintf(buf, "keepGCI = %u", sysfile->keepGCI);
- fill(buf, 40);
- ndbout << " -- Tail of REDO log" << endl;
-
- sprintf(buf, "oldestRestorableGCI = %u", sysfile->oldestRestorableGCI);
- fill(buf, 40);
- ndbout << " -- " << endl;
-
- sprintf(buf, "newestRestorableGCI = %u", sysfile->newestRestorableGCI);
- fill(buf, 40);
- ndbout << " -- " << endl;
-
- sprintf(buf, "latestLCP = %u", sysfile->latestLCP_ID);
- fill(buf, 40);
- ndbout << " -- " << endl;
-
- ndbout << "-- Node status: --" << endl;
- for(int i = 1; i < MAX_NDB_NODES; i++){
- if(Sysfile::getNodeStatus(i, sysfile->nodeStatus) !=Sysfile::NS_NotDefined){
- sprintf(buf,
- "Node %.2d -- %s GCP: %d, NodeGroup: %d, TakeOverNode: %d, "
- "LCP Ongoing: %s",
- i,
- getNSString(Sysfile::getNodeStatus(i,sysfile->nodeStatus)),
- sysfile->lastCompletedGCI[i],
- Sysfile::getNodeGroup(i, sysfile->nodeGroups),
- Sysfile::getTakeOverNode(i, sysfile->takeOver),
- BitmaskImpl::get(NdbNodeBitmask::Size,
- sysfile->lcpActive, i) != 0 ? "yes" : "no");
- ndbout << buf << endl;
- }
- }
-}
-
-NDB_COMMAND(printSysfile,
- "printSysfile", "printSysfile", "Prints a sysfile", 16384){
- if(argc < 2){
- usage(argv[0]);
- return 0;
- }
-
- for(int i = 1; i<argc; i++){
- const char * filename = argv[i];
-
- struct stat sbuf;
- const int res = stat(filename, &sbuf);
- if(res != 0){
- ndbout << "Could not find file: \"" << filename << "\"" << endl;
- continue;
- }
- 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;
- continue;
- }
- Uint32 sz = fread(buf, 1, bytes, f);
- fclose(f);
- if(sz != bytes){
- ndbout << "Failure while reading file" << endl;
- delete [] buf;
- continue;
- }
-
- print(filename, (Sysfile *)&buf[0]);
- delete [] buf;
- continue;
- }
- return 0;
-}
diff --git a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
deleted file mode 100644
index 399460078c2..00000000000
--- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ /dev/null
@@ -1,3029 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBLQH_H
-#define DBLQH_H
-
-#include <pc.hpp>
-#include <ndb_limits.h>
-#include <SimulatedBlock.hpp>
-#include <SLList.hpp>
-#include <DLList.hpp>
-#include <DLFifoList.hpp>
-#include <DLHashTable.hpp>
-
-#include <NodeBitmask.hpp>
-#include <signaldata/LCP.hpp>
-#include <signaldata/LqhTransConf.hpp>
-#include <signaldata/LqhFrag.hpp>
-#include <signaldata/FsOpenReq.hpp>
-
-// primary key is stored in TUP
-#include "../dbtup/Dbtup.hpp"
-
-class Dbacc;
-class Dbtup;
-
-#ifdef DBLQH_C
-// Constants
-/* ------------------------------------------------------------------------- */
-/* CONSTANTS USED WHEN MASTER REQUESTS STATE OF COPY FRAGMENTS. */
-/* ------------------------------------------------------------------------- */
-#define ZCOPY_CLOSING 0
-#define ZCOPY_ONGOING 1
-#define ZCOPY_ACTIVATION 2
-/* ------------------------------------------------------------------------- */
-/* STATES FOR THE VARIABLE GCP_LOG_PART_STATE */
-/* ------------------------------------------------------------------------- */
-#define ZIDLE 0
-#define ZWAIT_DISK 1
-#define ZON_DISK 2
-#define ZACTIVE 1
-/* ------------------------------------------------------------------------- */
-/* STATES FOR THE VARIABLE CSR_PHASES_STARTED */
-/* ------------------------------------------------------------------------- */
-#define ZSR_NO_PHASE_STARTED 0
-#define ZSR_PHASE1_COMPLETED 1
-#define ZSR_PHASE2_COMPLETED 2
-#define ZSR_BOTH_PHASES_STARTED 3
-/* ------------------------------------------------------------------------- */
-/* THE NUMBER OF PAGES IN A MBYTE, THE TWO LOGARITHM OF THIS. */
-/* THE NUMBER OF MBYTES IN A LOG FILE. */
-/* THE MAX NUMBER OF PAGES READ/WRITTEN FROM/TO DISK DURING */
-/* A WRITE OR READ. */
-/* ------------------------------------------------------------------------- */
-#define ZNOT_DIRTY 0
-#define ZDIRTY 1
-#define ZREAD_AHEAD_SIZE 8
-/* ------------------------------------------------------------------------- */
-/* CONSTANTS OF THE LOG PAGES */
-/* ------------------------------------------------------------------------- */
-#define ZPAGE_HEADER_SIZE 32
-#define ZPAGE_SIZE 8192
-#define ZPAGES_IN_MBYTE 32
-#define ZTWOLOG_NO_PAGES_IN_MBYTE 5
-#define ZTWOLOG_PAGE_SIZE 13
-#define ZMAX_MM_BUFFER_SIZE 32 // Main memory window during log execution
-
-#define ZMAX_PAGES_WRITTEN 8 // Max pages before writing to disk (=> config)
-#define ZMIN_READ_BUFFER_SIZE 2 // Minimum number of pages to execute log
-#define ZMIN_LOG_PAGES_OPERATION 10 // Minimum no of pages before stopping
-
-#define ZPOS_CHECKSUM 0
-#define ZPOS_LOG_LAP 1
-#define ZPOS_MAX_GCI_COMPLETED 2
-#define ZPOS_MAX_GCI_STARTED 3
-#define ZNEXT_PAGE 4
-#define ZPREV_PAGE 5
-#define ZPOS_VERSION 6
-#define ZPOS_NO_LOG_FILES 7
-#define ZCURR_PAGE_INDEX 8
-#define ZLAST_LOG_PREP_REF 10
-#define ZPOS_DIRTY 11
-/* A number of debug items written in the page header of all log files */
-#define ZPOS_LOG_TIMER 12
-#define ZPOS_PAGE_I 13
-#define ZPOS_PLACE_WRITTEN_FROM 14
-#define ZPOS_PAGE_NO 15
-#define ZPOS_PAGE_FILE_NO 16
-#define ZPOS_WORD_WRITTEN 17
-#define ZPOS_IN_WRITING 18
-#define ZPOS_PREV_PAGE_NO 19
-#define ZPOS_IN_FREE_LIST 20
-
-/* ------------------------------------------------------------------------- */
-/* CONSTANTS FOR THE VARIOUS REPLICA AND NODE TYPES. */
-/* ------------------------------------------------------------------------- */
-#define ZPRIMARY_NODE 0
-#define ZBACKUP_NODE 1
-#define ZSTANDBY_NODE 2
-#define ZTC_NODE 3
-#define ZLOG_NODE 3
-/* ------------------------------------------------------------------------- */
-/* VARIOUS CONSTANTS USED AS FLAGS TO THE FILE MANAGER. */
-/* ------------------------------------------------------------------------- */
-#define ZVAR_NO_LOG_PAGE_WORD 1
-#define ZLIST_OF_PAIRS 0
-#define ZLIST_OF_PAIRS_SYNCH 16
-#define ZARRAY_OF_PAGES 1
-#define ZLIST_OF_MEM_PAGES 2
-#define ZLIST_OF_MEM_PAGES_SYNCH 18
-#define ZCLOSE_NO_DELETE 0
-#define ZCLOSE_DELETE 1
-#define ZPAGE_ZERO 0
-/* ------------------------------------------------------------------------- */
-/* THE FOLLOWING CONSTANTS ARE USED TO DESCRIBE THE TYPES OF */
-/* LOG RECORDS, THE SIZE OF THE VARIOUS LOG RECORD TYPES AND */
-/* THE POSITIONS WITHIN THOSE LOG RECORDS. */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* THESE CONSTANTS DESCRIBE THE SIZES OF VARIOUS TYPES OF LOG REORDS. */
-/* NEXT_LOG_SIZE IS ACTUALLY ONE. THE REASON WE SET IT TO 2 IS TO */
-/* SIMPLIFY THE CODE SINCE OTHERWISE HAVE TO USE A SPECIAL VERSION */
-/* OF READ_LOGWORD WHEN READING LOG RECORD TYPE */
-/* SINCE NEXT MBYTE TYPE COULD BE THE VERY LAST WORD IN THE MBYTE. */
-/* BY SETTING IT TO 2 WE ENSURE IT IS NEVER THE VERY LAST WORD */
-/* IN THE MBYTE. */
-/* ------------------------------------------------------------------------- */
-#define ZFD_HEADER_SIZE 3
-#define ZFD_MBYTE_SIZE 3
-#define ZLOG_HEAD_SIZE 8
-#define ZNEXT_LOG_SIZE 2
-#define ZABORT_LOG_SIZE 3
-#define ZCOMMIT_LOG_SIZE 9
-#define ZCOMPLETED_GCI_LOG_SIZE 2
-/* ------------------------------------------------------------------------- */
-/* THESE CONSTANTS DESCRIBE THE TYPE OF A LOG RECORD. */
-/* THIS IS THE FIRST WORD OF A LOG RECORD. */
-/* ------------------------------------------------------------------------- */
-#define ZNEW_PREP_OP_TYPE 0
-#define ZPREP_OP_TYPE 1
-#define ZCOMMIT_TYPE 2
-#define ZABORT_TYPE 3
-#define ZFD_TYPE 4
-#define ZFRAG_SPLIT_TYPE 5
-#define ZNEXT_LOG_RECORD_TYPE 6
-#define ZNEXT_MBYTE_TYPE 7
-#define ZCOMPLETED_GCI_TYPE 8
-#define ZINVALID_COMMIT_TYPE 9
-/* ------------------------------------------------------------------------- */
-/* THE POSITIONS OF LOGGED DATA IN A FILE DESCRIPTOR LOG RECORD HEADER.*/
-/* ALSO THE MAXIMUM NUMBER OF FILE DESCRIPTORS IN A LOG RECORD. */
-/* ------------------------------------------------------------------------- */
-#define ZPOS_LOG_TYPE 0
-#define ZPOS_NO_FD 1
-#define ZPOS_FILE_NO 2
-/* ------------------------------------------------------------------------- */
-/* THE POSITIONS WITHIN A PREPARE LOG RECORD AND A NEW PREPARE */
-/* LOG RECORD. */
-/* ------------------------------------------------------------------------- */
-#define ZPOS_HASH_VALUE 2
-#define ZPOS_SCHEMA_VERSION 3
-#define ZPOS_TRANS_TICKET 4
-#define ZPOS_OP_TYPE 5
-#define ZPOS_NO_ATTRINFO 6
-#define ZPOS_NO_KEYINFO 7
-/* ------------------------------------------------------------------------- */
-/* THE POSITIONS WITHIN A COMMIT LOG RECORD. */
-/* ------------------------------------------------------------------------- */
-#define ZPOS_COMMIT_TRANSID1 1
-#define ZPOS_COMMIT_TRANSID2 2
-#define ZPOS_COMMIT_GCI 3
-#define ZPOS_COMMIT_TABLE_REF 4
-#define ZPOS_COMMIT_FRAGID 5
-#define ZPOS_COMMIT_FILE_NO 6
-#define ZPOS_COMMIT_START_PAGE_NO 7
-#define ZPOS_COMMIT_START_PAGE_INDEX 8
-#define ZPOS_COMMIT_STOP_PAGE_NO 9
-/* ------------------------------------------------------------------------- */
-/* THE POSITIONS WITHIN A ABORT LOG RECORD. */
-/* ------------------------------------------------------------------------- */
-#define ZPOS_ABORT_TRANSID1 1
-#define ZPOS_ABORT_TRANSID2 2
-/* ------------------------------------------------------------------------- */
-/* THE POSITION WITHIN A COMPLETED GCI LOG RECORD. */
-/* ------------------------------------------------------------------------- */
-#define ZPOS_COMPLETED_GCI 1
-/* ------------------------------------------------------------------------- */
-/* THE POSITIONS WITHIN A NEW PREPARE LOG RECORD. */
-/* ------------------------------------------------------------------------- */
-#define ZPOS_NEW_PREP_FILE_NO 8
-#define ZPOS_NEW_PREP_PAGE_REF 9
-
-#define ZLAST_WRITE_IN_FILE 1
-#define ZENFORCE_WRITE 2
-/* ------------------------------------------------------------------------- */
-/* CONSTANTS USED AS INPUT TO SUBROUTINE WRITE_LOG_PAGES AMONG OTHERS. */
-/* ------------------------------------------------------------------------- */
-#define ZNORMAL 0
-#define ZINIT 1
-/* ------------------------------------------------------------------------- */
-/* CONSTANTS USED BY CONTINUEB TO DEDUCE WHICH CONTINUE SIGNAL IS TO */
-/* BE EXECUTED AS A RESULT OF THIS CONTINUEB SIGNAL. */
-/* ------------------------------------------------------------------------- */
-#define ZLOG_LQHKEYREQ 0
-#define ZPACK_LQHKEYREQ 1
-#define ZSEND_ATTRINFO 2
-#define ZSR_GCI_LIMITS 3
-#define ZSR_LOG_LIMITS 4
-#define ZSEND_EXEC_CONF 5
-#define ZEXEC_SR 6
-#define ZSR_FOURTH_COMP 7
-#define ZINIT_FOURTH 8
-#define ZTIME_SUPERVISION 9
-#define ZSR_PHASE3_START 10
-#define ZLQH_TRANS_NEXT 11
-#define ZLQH_RELEASE_AT_NODE_FAILURE 12
-#define ZSCAN_TC_CONNECT 13
-#define ZINITIALISE_RECORDS 14
-#define ZINIT_GCP_REC 15
-#define ZCHECK_LCP_STOP_BLOCKED 17
-#define ZSCAN_MARKERS 18
-#define ZOPERATION_EVENT_REP 19
-#define ZPREP_DROP_TABLE 20
-#define ZENABLE_EXPAND_CHECK 21
-#define ZRETRY_TCKEYREF 22
-
-/* ------------------------------------------------------------------------- */
-/* NODE STATE DURING SYSTEM RESTART, VARIABLES CNODES_SR_STATE */
-/* AND CNODES_EXEC_SR_STATE. */
-/* ------------------------------------------------------------------------- */
-#define ZSTART_SR 1
-#define ZEXEC_SR_COMPLETED 2
-/* ------------------------------------------------------------------------- */
-/* CONSTANTS USED BY NODE STATUS TO DEDUCE THE STATUS OF A NODE. */
-/* ------------------------------------------------------------------------- */
-#define ZNODE_UP 0
-#define ZNODE_DOWN 1
-/* ------------------------------------------------------------------------- */
-/* START PHASES */
-/* ------------------------------------------------------------------------- */
-#define ZLAST_START_PHASE 255
-#define ZSTART_PHASE1 1
-#define ZSTART_PHASE2 2
-#define ZSTART_PHASE3 3
-#define ZSTART_PHASE4 4
-#define ZSTART_PHASE6 6
-/* ------------------------------------------------------------------------- */
-/* CONSTANTS USED BY SCAN AND COPY FRAGMENT PROCEDURES */
-/* ------------------------------------------------------------------------- */
-#define ZSTORED_PROC_SCAN 0
-#define ZSTORED_PROC_COPY 2
-#define ZDELETE_STORED_PROC_ID 3
-#define ZWRITE_LOCK 1
-#define ZSCAN_FRAG_CLOSED 2
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES ADDED IN VERSION 0.1 AND 0.2 */
-/* ------------------------------------------------------------------------- */
-#define ZNOT_FOUND 1 // Not an error code, a return value
-#define ZNO_FREE_LQH_CONNECTION 414
-#define ZGET_DATAREC_ERROR 418
-#define ZGET_ATTRINBUF_ERROR 419
-#define ZNO_FREE_FRAGMENTREC 460 // Insert new fragment error code
-#define ZTAB_FILE_SIZE 464 // Insert new fragment error code + Start kernel
-#define ZNO_ADD_FRAGREC 465 // Insert new fragment error code
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES ADDED IN VERSION 0.3 */
-/* ------------------------------------------------------------------------- */
-#define ZTAIL_PROBLEM_IN_LOG_ERROR 410
-#define ZGCI_TOO_LOW_ERROR 429 // GCP_SAVEREF error code
-#define ZTAB_STATE_ERROR 474 // Insert new fragment error code
-#define ZTOO_NEW_GCI_ERROR 479 // LCP Start error
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES ADDED IN VERSION 0.4 */
-/* ------------------------------------------------------------------------- */
-
-#define ZNO_FREE_FRAG_SCAN_REC_ERROR 490 // SCAN_FRAGREF error code
-#define ZCOPY_NO_FRAGMENT_ERROR 491 // COPY_FRAGREF error code
-#define ZTAKE_OVER_ERROR 499
-#define ZCOPY_NODE_ERROR 1204
-#define ZTOO_MANY_COPY_ACTIVE_ERROR 1208 // COPY_FRAG and COPY_ACTIVEREF code
-#define ZCOPY_ACTIVE_ERROR 1210 // COPY_ACTIVEREF error code
-#define ZNO_TC_CONNECT_ERROR 1217 // Simple Read + SCAN
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES ADDED IN VERSION 1.X */
-/* ------------------------------------------------------------------------- */
-//#define ZSCAN_BOOK_ACC_OP_ERROR 1219 // SCAN_FRAGREF error code
-#define ZFILE_CHANGE_PROBLEM_IN_LOG_ERROR 1220
-#define ZTEMPORARY_REDO_LOG_FAILURE 1221
-#define ZNO_FREE_MARKER_RECORDS_ERROR 1222
-#define ZNODE_SHUTDOWN_IN_PROGESS 1223
-#define ZTOO_MANY_FRAGMENTS 1224
-#define ZTABLE_NOT_DEFINED 1225
-#define ZDROP_TABLE_IN_PROGRESS 1226
-#define ZINVALID_SCHEMA_VERSION 1227
-
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES ADDED IN VERSION 2.X */
-/* ------------------------------------------------------------------------- */
-#define ZNODE_FAILURE_ERROR 400
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES FROM ACC */
-/* ------------------------------------------------------------------------- */
-#define ZNO_TUPLE_FOUND 626
-#define ZTUPLE_ALREADY_EXIST 630
-/* ------------------------------------------------------------------------- */
-/* ERROR CODES FROM TUP */
-/* ------------------------------------------------------------------------- */
-#define ZSEARCH_CONDITION_FALSE 899
-#define ZUSER_ERROR_CODE_LIMIT 6000
-#endif
-
-/**
- * @class dblqh
- *
- * @section secIntro Introduction
- *
- * Dblqh is the coordinator of the LDM. Dblqh is responsible for
- * performing operations on tuples. It does this job with help of
- * Dbacc block (that manages the index structures) and Dbtup
- * (that manages the tuples).
- *
- * Dblqh also keeps track of the participants and acts as a coordinator of
- * 2-phase commits. Logical redo logging is also handled by the Dblqh
- * block.
- *
- * @section secModules Modules
- *
- * The code is partitioned into the following modules:
- * - START / RESTART
- * - Start phase 1: Load our block reference and our processor id
- * - Start phase 2: Initiate all records within the block
- * Connect LQH with ACC and TUP.
- * - Start phase 4: Connect LQH with LQH. Connect every LQH with
- * every LQH in the database system.
- * If initial start, then create the fragment log files.
- * If system restart or node restart,
- * then open the fragment log files and
- * find the end of the log files.
- * - ADD / DELETE FRAGMENT<br>
- * Used by dictionary to create new fragments and delete old fragments.
- * - EXECUTION<br>
- * handles the reception of lqhkeyreq and all processing
- * of operations on behalf of this request.
- * This does also involve reception of various types of attrinfo
- * and keyinfo.
- * It also involves communication with ACC and TUP.
- * - LOG<br>
- * The log module handles the reading and writing of the log.
- * It is also responsible for handling system restart.
- * It controls the system restart in TUP and ACC as well.
- * - TRANSACTION<br>
- * This module handles the commit and the complete phases.
- * - MODULE TO HANDLE TC FAILURE<br>
- * - SCAN<br>
- * This module contains the code that handles a scan of a particular
- * fragment.
- * It operates under the control of TC and orders ACC to
- * perform a scan of all tuples in the fragment.
- * TUP performs the necessary search conditions
- * to ensure that only valid tuples are returned to the application.
- * - NODE RECOVERY<br>
- * Used when a node has failed.
- * It performs a copy of a fragment to a new replica of the fragment.
- * It does also shut down all connections to the failed node.
- * - LOCAL CHECKPOINT<br>
- * Handles execution and control of LCPs
- * It controls the LCPs in TUP and ACC.
- * It also interacts with DIH to control which GCPs are recoverable.
- * - GLOBAL CHECKPOINT<br>
- * Helps DIH in discovering when GCPs are recoverable.
- * It handles the request gcp_savereq that requests LQH to
- * save a particular GCP to disk and respond when completed.
- * - FILE HANDLING<br>
- * With submodules:
- * - SIGNAL RECEPTION
- * - NORMAL OPERATION
- * - FILE CHANGE
- * - INITIAL START
- * - SYSTEM RESTART PHASE ONE
- * - SYSTEM RESTART PHASE TWO,
- * - SYSTEM RESTART PHASE THREE
- * - SYSTEM RESTART PHASE FOUR
- * - ERROR
- * - TEST
- * - LOG
- */
-class Dblqh: public SimulatedBlock {
-public:
- enum LcpCloseState {
- LCP_IDLE = 0,
- LCP_RUNNING = 1, // LCP is running
- LCP_CLOSE_STARTED = 2, // Completion(closing of files) has started
- ACC_LCP_CLOSE_COMPLETED = 3,
- TUP_LCP_CLOSE_COMPLETED = 4
- };
-
- enum ExecUndoLogState {
- EULS_IDLE = 0,
- EULS_STARTED = 1,
- EULS_COMPLETED = 2
- };
-
- struct AddFragRecord {
- enum AddFragStatus {
- FREE = 0,
- ACC_ADDFRAG = 1,
- WAIT_TUP = 3,
- WAIT_TUX = 5,
- WAIT_ADD_ATTR = 6,
- TUP_ATTR_WAIT = 7,
- TUX_ATTR_WAIT = 9
- };
- LqhAddAttrReq::Entry attributes[LqhAddAttrReq::MAX_ATTRIBUTES];
- UintR accConnectptr;
- AddFragStatus addfragStatus;
- UintR dictConnectptr;
- UintR fragmentPtr;
- UintR nextAddfragrec;
- UintR schemaVer;
- UintR tupConnectptr;
- UintR tuxConnectptr;
- UintR checksumIndicator;
- UintR GCPIndicator;
- BlockReference dictBlockref;
- Uint32 m_senderAttrPtr;
- Uint16 addfragErrorCode;
- Uint16 attrSentToTup;
- Uint16 attrReceived;
- Uint16 addFragid;
- Uint16 noOfAttr;
- Uint16 noOfNull;
- Uint16 tabId;
- Uint16 totalAttrReceived;
- Uint16 fragCopyCreation;
- Uint16 noOfKeyAttr;
- Uint16 noOfCharsets;
- Uint16 lh3DistrBits;
- Uint16 tableType;
- Uint16 primaryTableId;
- Uint32 tablespace_id;
- Uint32 maxRowsLow;
- Uint32 maxRowsHigh;
- Uint32 minRowsLow;
- Uint32 minRowsHigh;
- Uint32 forceVarPartFlag;
- };
- typedef Ptr<AddFragRecord> AddFragRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ ATTRIBUTE INFORMATION RECORD $$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * Can contain one (1) attrinfo signal.
- * One signal contains 24 attr. info words.
- * But 32 elements are used to make plex happy.
- * Some of the elements are used to the following things:
- * - Data length in this record is stored in the
- * element indexed by ZINBUF_DATA_LEN.
- * - Next attrinbuf is pointed out by the element
- * indexed by ZINBUF_NEXT.
- */
- struct Attrbuf {
- UintR attrbuf[32];
- }; // Size 128 bytes
- typedef Ptr<Attrbuf> AttrbufPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ DATA BUFFER $$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * This buffer is used as a general data storage.
- */
- struct Databuf {
- UintR data[4];
- UintR nextDatabuf;
- }; // size 20 bytes
- typedef Ptr<Databuf> DatabufPtr;
-
- struct ScanRecord {
- ScanRecord() {}
- enum ScanState {
- SCAN_FREE = 0,
- WAIT_STORED_PROC_COPY = 1,
- WAIT_STORED_PROC_SCAN = 2,
- WAIT_NEXT_SCAN_COPY = 3,
- WAIT_NEXT_SCAN = 4,
- WAIT_DELETE_STORED_PROC_ID_SCAN = 5,
- WAIT_DELETE_STORED_PROC_ID_COPY = 6,
- WAIT_ACC_COPY = 7,
- WAIT_ACC_SCAN = 8,
- WAIT_SCAN_NEXTREQ = 10,
- WAIT_CLOSE_SCAN = 12,
- WAIT_CLOSE_COPY = 13,
- WAIT_RELEASE_LOCK = 14,
- WAIT_TUPKEY_COPY = 15,
- WAIT_LQHKEY_COPY = 16,
- IN_QUEUE = 17
- };
- enum ScanType {
- ST_IDLE = 0,
- SCAN = 1,
- COPY = 2
- };
-
- UintR scan_acc_op_ptr[32];
- Uint32 scan_acc_index;
- Uint32 scan_acc_attr_recs;
- UintR scanApiOpPtr;
- Local_key m_row_id;
-
- Uint32 m_max_batch_size_rows;
- Uint32 m_max_batch_size_bytes;
-
- Uint32 m_curr_batch_size_rows;
- Uint32 m_curr_batch_size_bytes;
-
- bool check_scan_batch_completed() const;
-
- UintR copyPtr;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- Uint32 nextHash;
- Uint32 prevHash;
- bool equal(const ScanRecord & key) const {
- return scanNumber == key.scanNumber && fragPtrI == key.fragPtrI;
- }
- Uint32 hashValue() const {
- return fragPtrI ^ scanNumber;
- }
-
- UintR scanAccPtr;
- UintR scanAiLength;
- UintR scanErrorCounter;
- UintR scanSchemaVersion;
-
- /**
- * This is _always_ main table, even in range scan
- * in which case scanTcrec->fragmentptr is different
- */
- Uint32 fragPtrI;
- UintR scanStoredProcId;
- ScanState scanState;
- UintR scanTcrec;
- ScanType scanType;
- BlockReference scanApiBlockref;
- NodeId scanNodeId;
- Uint16 scanReleaseCounter;
- Uint16 scanNumber;
-
- // scan source block ACC TUX TUP
- BlockReference scanBlockref;
-
- Uint8 scanCompletedStatus;
- Uint8 scanFlag;
- Uint8 scanLockHold;
- Uint8 scanLockMode;
- Uint8 readCommitted;
- Uint8 rangeScan;
- Uint8 descending;
- Uint8 tupScan;
- Uint8 lcpScan;
- Uint8 scanTcWaiting;
- Uint8 scanKeyinfoFlag;
- Uint8 m_last_row;
- }; // Size 272 bytes
- typedef Ptr<ScanRecord> ScanRecordPtr;
-
- struct Fragrecord {
- Fragrecord() {}
-
- enum ExecSrStatus {
- IDLE = 0,
- ACTIVE = 2
- };
- /**
- * Possible state transitions are:
- * - FREE -> DEFINED Fragment record is allocated
- * - DEFINED -> ACTIVE Add fragment is completed and
- * fragment is ready to
- * receive operations.
- * - DEFINED -> ACTIVE_CREATION Add fragment is completed and
- * fragment is ready to
- * receive operations in parallel
- * with a copy fragment
- * which is performed from the
- * primary replica
- * - DEFINED -> CRASH_RECOVERING A fragment is ready to be
- * recovered from a local
- * checkpoint on disk
- * - ACTIVE -> BLOCKED A local checkpoint is to be
- * started. No more operations
- * are allowed to be started until
- * the local checkpoint
- * has been started.
- * - ACTIVE -> REMOVING A fragment is removed from the node
- * - BLOCKED -> ACTIVE Operations are allowed again in
- * the fragment.
- * - CRASH_RECOVERING -> ACTIVE A fragment has been recovered and
- * are now ready for
- * operations again.
- * - CRASH_RECOVERING -> REMOVING Fragment recovery failed or
- * was cancelled.
- * - ACTIVE_CREATION -> ACTIVE A fragment is now copied and now
- * is a normal fragment
- * - ACTIVE_CREATION -> REMOVING Copying of the fragment failed
- * - REMOVING -> FREE Removing of the fragment is
- * completed and the fragment
- * is now free again.
- */
- enum FragStatus {
- FREE = 0, ///< Fragment record is currently not in use
- FSACTIVE = 1, ///< Fragment is defined and usable for operations
- DEFINED = 2, ///< Fragment is defined but not yet usable by
- ///< operations
- BLOCKED = 3, ///< LQH is waiting for all active operations to
- ///< complete the current phase so that the
- ///< local checkpoint can be started.
- ACTIVE_CREATION = 4, ///< Fragment is defined and active but is under
- ///< creation by the primary LQH.
- CRASH_RECOVERING = 5, ///< Fragment is recovering after a crash by
- ///< executing the fragment log and so forth.
- ///< Will need further breakdown.
- REMOVING = 6 ///< The fragment is currently removed.
- ///< Operations are not allowed.
- };
- enum LogFlag {
- STATE_TRUE = 0,
- STATE_FALSE = 1
- };
- enum SrStatus {
- SS_IDLE = 0,
- SS_STARTED = 1,
- SS_COMPLETED = 2
- };
- enum LcpFlag {
- LCP_STATE_TRUE = 0,
- LCP_STATE_FALSE = 1
- };
- /**
- * Last GCI for executing the fragment log in this phase.
- */
- UintR execSrLastGci[4];
- /**
- * Start GCI for executing the fragment log in this phase.
- */
- UintR execSrStartGci[4];
- /**
- * Requesting user pointer for executing the fragment log in
- * this phase
- */
- UintR execSrUserptr[4];
- /**
- * The LCP identifier of the LCP's.
- * =0 means that the LCP number has not been stored.
- * The LCP identifier is supplied by DIH when starting the LCP.
- */
- UintR lcpId[MAX_LCP_STORED];
- UintR maxGciInLcp;
- /**
- * This variable contains the maximum global checkpoint
- * identifier that exists in a certain local checkpoint.
- * Maximum 4 local checkpoints is possible in this release.
- */
- UintR maxGciCompletedInLcp;
- UintR srLastGci[4];
- UintR srStartGci[4];
- /**
- * The fragment pointers in ACC
- */
- UintR accFragptr;
- /**
- * The EXEC_SR variables are used to keep track of which fragments
- * that are interested in being executed as part of executing the
- * fragment loop.
- * It is initialised for every phase of executing the
- * fragment log (the fragment log can be executed upto four times).
- *
- * Each execution is capable of executing the log records on four
- * fragment replicas.
- */
- /**
- * Requesting block reference for executing the fragment log
- * in this phase.
- */
- BlockReference execSrBlockref[4];
- /**
- * This variable contains references to active scan and copy
- * fragment operations on the fragment.
- * A maximum of four concurrently active is allowed.
- */
- typedef Bitmask<4> ScanNumberMask;
- ScanNumberMask m_scanNumberMask;
- DLList<ScanRecord>::Head m_activeScans;
- DLFifoList<ScanRecord>::Head m_queuedScans;
-
- Uint16 srLqhLognode[4];
- /**
- * The fragment pointers in TUP and TUX
- */
- UintR tupFragptr;
- UintR tuxFragptr;
-
- /**
- * This variable keeps track of how many operations that are
- * active that have skipped writing the log but not yet committed
- * or aborted. This is used during start of fragment.
- */
- UintR activeTcCounter;
-
- /**
- * This status specifies whether this fragment is actively
- * engaged in executing the fragment log.
- */
- ExecSrStatus execSrStatus;
-
- /**
- * The fragment id of this fragment.
- */
- UintR fragId;
-
- /**
- * Status of fragment
- */
- FragStatus fragStatus;
-
- /**
- * 0 = undefined i.e fragStatus != ACTIVE_CREATION
- * 1 = yes
- * 2 = no
- */
- enum ActiveCreat {
- AC_NORMAL = 0, // fragStatus != ACTIVE_CREATION
- AC_IGNORED = 1, // Operation that got ignored during NR
- AC_NR_COPY = 2 // Operation that got performed during NR
- };
- Uint8 m_copy_started_state;
-
- /**
- * This flag indicates whether logging is currently activated at
- * the fragment.
- * During a system restart it is temporarily shut off.
- * Some fragments have it permanently shut off.
- */
- LogFlag logFlag;
- UintR masterPtr;
- /**
- * This variable contains the maximum global checkpoint identifier
- * which was completed when the local checkpoint was started.
- */
- /**
- * Reference to the next fragment record in a free list of fragment
- * records.
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
-
- /**
- * The newest GCI that has been committed on fragment
- */
- UintR newestGci;
- SrStatus srStatus;
- UintR srUserptr;
- /**
- * The starting global checkpoint of this fragment.
- */
- UintR startGci;
- /**
- * A reference to the table owning this fragment.
- */
- UintR tabRef;
-
- /**
- * This is the queue to put operations that have been blocked
- * during start of a local chkp.
- */
- UintR firstWaitQueue;
- UintR lastWaitQueue;
-
- /**
- * The block reference to ACC on the fragment makes it
- * possible to have different ACC blocks for different
- * fragments in the future.
- */
- BlockReference accBlockref;
-
- /**
- * Ordered index block.
- */
- BlockReference tuxBlockref;
- /**
- * The master block reference as sent in COPY_ACTIVEREQ.
- */
- BlockReference masterBlockref;
- /**
- * These variables are used during system restart to recall
- * from which node to execute the fragment log and which GCI's
- * this node should start and stop from. Also to remember who
- * to send the response to when system restart is completed.
- */
- BlockReference srBlockref;
- /**
- * The block reference to TUP on the fragment makes it
- * possible to have different TUP blocks for different
- * fragments in the future.
- */
- BlockReference tupBlockref;
- /**
- * This state indicates if the fragment will participate in a
- * checkpoint.
- * Temporary tables with Fragrecord::logFlag permanently off
- * will also have Fragrecord::lcpFlag off.
- */
- LcpFlag lcpFlag;
- /**
- * Used to ensure that updates started with old
- * configuration do not arrive here after the copy fragment
- * has started.
- * If they are allowed to arrive after they
- * could update a record that has already been replicated to
- * the new node. This type of arrival should be extremely
- * rare but we must anyway ensure that no harm is done.
- */
- Uint16 copyNode;
- /**
- * This variable ensures that only one copy fragment is
- * active at a time on the fragment.
- */
- Uint8 copyFragState;
- /**
- * The number of fragment replicas that will execute the log
- * records in this round of executing the fragment
- * log. Maximum four is possible.
- */
- Uint8 execSrNoReplicas;
- /**
- * This variable contains what type of replica this fragment
- * is. Two types are possible:
- * - Primary/Backup replica = 0
- * - Stand-by replica = 1
- *
- * It is not possible to distinguish between primary and
- * backup on a fragment.
- * This can only be done per transaction.
- * DIH can change from primary to backup without informing
- * the various replicas about this change.
- */
- Uint8 fragCopy;
- /**
- * This is the last fragment distribution key that we have
- * heard of.
- */
- Uint8 fragDistributionKey;
- /**
- * How many local checkpoints does the fragment contain
- */
- Uint8 srChkpnr;
- Uint8 srNoLognodes;
- /**
- * Table type.
- */
- Uint8 tableType;
- /**
- * For ordered index fragment, i-value of corresponding
- * fragment in primary table.
- */
- UintR tableFragptr;
-
- /**
- * Log part
- */
- Uint32 m_log_part_ptr_i;
- };
- typedef Ptr<Fragrecord> FragrecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ GLOBAL CHECKPOINT RECORD $$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * This record describes a global checkpoint that is
- * completed. It waits for all log records belonging to this
- * global checkpoint to be saved on disk.
- */
- struct GcpRecord {
- /**
- * The file number within each log part where the log was
- * located when gcp_savereq was received. The last record
- * belonging to this global checkpoint is certainly before
- * this place in the log. We could come even closer but it
- * would cost performance and doesn't seem like a good
- * idea. This is simple and it works.
- */
- Uint16 gcpFilePtr[4];
- /**
- * The page number within the file for each log part.
- */
- Uint16 gcpPageNo[4];
- /**
- * The word number within the last page that was written for
- * each log part.
- */
- Uint16 gcpWordNo[4];
- /**
- * The identity of this global checkpoint.
- */
- UintR gcpId;
- /**
- * The state of this global checkpoint, one for each log part.
- */
- Uint8 gcpLogPartState[4];
- /**
- * The sync state of this global checkpoint, one for each
- * log part.
- */
- Uint8 gcpSyncReady[4];
- /**
- * User pointer of the sender of gcp_savereq (= master DIH).
- */
- UintR gcpUserptr;
- /**
- * Block reference of the sender of gcp_savereq
- * (= master DIH).
- */
- BlockReference gcpBlockref;
- }; // Size 44 bytes
- typedef Ptr<GcpRecord> GcpRecordPtr;
-
- struct HostRecord {
- bool inPackedList;
- UintR noOfPackedWordsLqh;
- UintR packedWordsLqh[30];
- UintR noOfPackedWordsTc;
- UintR packedWordsTc[29];
- BlockReference hostLqhBlockRef;
- BlockReference hostTcBlockRef;
- };// Size 128 bytes
- typedef Ptr<HostRecord> HostRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$ LOCAL CHECKPOINT SUPPORT RECORD $$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * This record contains the information about an outstanding
- * request to TUP or ACC. Used for both local checkpoints and
- * system restart.
- */
- struct LcpLocRecord {
- enum LcpLocstate {
- IDLE = 0,
- WAIT_TUP_PREPLCP = 1,
- WAIT_LCPHOLDOP = 2,
- HOLDOP_READY = 3,
- ACC_WAIT_STARTED = 4,
- ACC_STARTED = 5,
- ACC_COMPLETED = 6,
- TUP_WAIT_STARTED = 7,
- TUP_STARTED = 8,
- TUP_COMPLETED = 9,
- SR_ACC_STARTED = 10,
- SR_TUP_STARTED = 11,
- SR_ACC_COMPLETED = 12,
- SR_TUP_COMPLETED = 13
- };
- LcpLocstate lcpLocstate;
- Uint32 lcpRef;
- }; // 28 bytes
- typedef Ptr<LcpLocRecord> LcpLocRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ LOCAL CHECKPOINT RECORD $$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * This record contains the information about a local
- * checkpoint that is ongoing. This record is also used as a
- * system restart record.
- */
- struct LcpRecord {
- LcpRecord() { m_EMPTY_LCP_REQ.clear(); }
-
- enum LcpState {
- LCP_IDLE = 0,
- LCP_COMPLETED = 2,
- LCP_WAIT_FRAGID = 3,
- LCP_WAIT_TUP_PREPLCP = 4,
- LCP_WAIT_HOLDOPS = 5,
- LCP_START_CHKP = 7,
- LCP_BLOCKED_COMP = 8,
- LCP_SR_WAIT_FRAGID = 9,
- LCP_SR_STARTED = 10,
- LCP_SR_COMPLETED = 11
- };
-
- LcpState lcpState;
- bool firstFragmentFlag;
- bool lastFragmentFlag;
-
- struct FragOrd {
- Uint32 fragPtrI;
- LcpFragOrd lcpFragOrd;
- };
- FragOrd currentFragment;
-
- bool lcpQueued;
- FragOrd queuedFragment;
-
- bool reportEmpty;
- NdbNodeBitmask m_EMPTY_LCP_REQ;
-
- Uint32 m_error;
- Uint32 m_outstanding;
- }; // Size 76 bytes
- typedef Ptr<LcpRecord> LcpRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* */
- /* THE RECORDS THAT START BY LOG_ ARE A PART OF THE LOG MANAGER. */
- /* THESE RECORDS ARE USED TO HANDLE THE FRAGMENT LOG. */
- /* */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ LOG RECORD $$$$$$$ */
- /* */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* THIS RECORD IS ALIGNED TO BE 256 BYTES. */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * This record describes the current state of a log.
- * A log consists of a number of log files.
- * These log files are described by the log file record.
- *
- * There will be 4 sets of log files.
- * Different tables will use different log files dependent
- * on the table id.
- * This ensures that more than one outstanding request can
- * be sent to the file system.
- * The log file to use is found by performing a very simple hash
- * function.
- */
- struct LogPartRecord {
- enum LogPartState {
- IDLE = 0, ///< Nothing happens at the moment
- ACTIVE = 1, ///< An operation is active logging
- SR_FIRST_PHASE = 2, ///< Finding the end of the log and
- ///< the information about global
- ///< checkpoints in the log is ongoing.
- SR_FIRST_PHASE_COMPLETED = 3, ///< First phase completed
- SR_THIRD_PHASE_STARTED = 4, ///< Executing fragment log is in 3rd ph
- SR_THIRD_PHASE_COMPLETED = 5,
- SR_FOURTH_PHASE_STARTED = 6, ///< Finding the log tail and head
- ///< is the fourth phase.
- SR_FOURTH_PHASE_COMPLETED = 7,
- FILE_CHANGE_PROBLEM = 8, ///< For some reason the write to
- ///< page zero in file zero have not
- ///< finished after 15 mbyte of
- ///< log data have been written
- TAIL_PROBLEM = 9 ///< Only 1 mbyte of log left.
- ///< No operations allowed to enter the
- ///< log. Only special log records
- ///< are allowed
- };
- enum WaitWriteGciLog {
- WWGL_TRUE = 0,
- WWGL_FALSE = 1
- };
- enum LogExecState {
- LES_IDLE = 0,
- LES_SEARCH_STOP = 1,
- LES_SEARCH_START = 2,
- LES_EXEC_LOG = 3,
- LES_EXEC_LOG_NEW_MBYTE = 4,
- LES_EXEC_LOG_NEW_FILE = 5,
- LES_EXEC_LOGREC_FROM_FILE = 6,
- LES_EXEC_LOG_COMPLETED = 7,
- LES_WAIT_READ_EXEC_SR_NEW_MBYTE = 8,
- LES_WAIT_READ_EXEC_SR = 9,
- LES_EXEC_LOG_INVALIDATE = 10
- };
-
- /**
- * Is a CONTINUEB(ZLOG_LQHKEYREQ) signal sent and
- * outstanding. We do not want several instances of this
- * signal out in the air since that would create multiple
- * writers of the list.
- */
- UintR LogLqhKeyReqSent;
- /**
- * Contains the current log file where log records are
- * written. During system restart it is used to indicate the
- * last log file.
- */
- UintR currentLogfile;
- /**
- * The log file used to execute log records from far behind.
- */
- UintR execSrExecLogFile;
- /**
- * The currently executing prepare record starts in this log
- * page. This variable is used to enable that a log record is
- * executed multiple times in execution of the log.
- */
- UintR execSrLogPage;
- /**
- * This variable keeps track of the lfo record where the
- * pages that were read from disk when an operations log
- * record were not found in the main memory buffer for log
- * pages.
- */
- UintR execSrLfoRec;
- /**
- * The starting page number when reading log from far behind.
- */
- UintR execSrStartPageNo;
- /**
- * The last page number when reading log from far behind.
- */
- UintR execSrStopPageNo;
- /**
- * Contains a reference to the first log file, file number 0.
- */
- UintR firstLogfile;
- /**
- * The head of the operations queued for logging.
- */
- UintR firstLogQueue;
- /**
- * This variable contains the oldest operation in this log
- * part which have not been committed yet.
- */
- UintR firstLogTcrec;
- /**
- * The first reference to a set of 8 pages. These are used
- * during execution of the log to keep track of which pages
- * are in memory and which are not.
- */
- UintR firstPageRef;
- /**
- * This variable contains the global checkpoint record
- * waiting for disk writes to complete.
- */
- UintR gcprec;
- /**
- * The last reference to a set of 8 pages. These are used
- * during execution of the log to keep track of which pages
- * are in memory and which are not.
- */
- UintR lastPageRef;
- /**
- * The tail of the operations queued for logging.
- */
- UintR lastLogQueue;
- /**
- * This variable contains the newest operation in this log
- * part which have not been committed yet.
- */
- UintR lastLogTcrec;
- /**
- * This variable indicates which was the last mbyte that was
- * written before the system crashed. Discovered during
- * system restart.
- */
- UintR lastLogfile;
- /**
- * This variable is used to keep track of the state during
- * the third phase of the system restart, i.e. when
- * LogPartRecord::logPartState ==
- * LogPartRecord::SR_THIRD_PHASE_STARTED.
- */
- LogExecState logExecState;
- /**
- * This variable contains the lap number of this log part.
- */
- UintR logLap;
- /**
- * This variable contains the place to stop executing the log
- * in this phase.
- */
- UintR logLastGci;
- /**
- * This variable contains the place to start executing the
- * log in this phase.
- */
- UintR logStartGci;
- /**
- * The latest GCI completed in this log part.
- */
- UintR logPartNewestCompletedGCI;
- /**
- * The current state of this log part.
- */
- LogPartState logPartState;
- /**
- * A timer that is set every time a log page is sent to disk.
- * Ensures that log pages are not kept in main memory for
- * more than a certain time.
- */
- UintR logPartTimer;
- /**
- * The current timer which is set by the periodic signal
- * received by LQH
- */
- UintR logTimer;
- /**
- * Contains the number of the log tail file and the mbyte
- * reference within that file. This information ensures that
- * the tail is not overwritten when writing new log records.
- */
- UintR logTailFileNo;
- /**
- * The TcConnectionrec used during execution of this log part.
- */
- UintR logTcConrec;
- /**
- * The number of pages that currently resides in the main
- * memory buffer. It does not refer pages that are currently
- * read from the log files. Only to pages already read
- * from the log file.
- */
- UintR mmBufferSize;
- /**
- * Contains the current number of log files in this log part.
- */
- UintR noLogFiles;
- /**
- * This variable is used only during execution of a log
- * record. It keeps track of in which page record a log
- * record was started. It is used then to deduce which
- * pages that are dirty after that the log records on the
- * page have been executed.
- *
- * It is also used to find out where to write the invalidate
- * command when that is needed.
- */
- UintR prevLogpage;
- /**
- * The number of files remaining to gather GCI information
- * for during system restart. Only used if number of files
- * is larger than 60.
- */
- UintR srRemainingFiles;
- /**
- * The log file where to start executing the log during
- * system restart.
- */
- UintR startLogfile;
- /**
- * The last log file in which to execute the log during system
- * restart.
- */
- UintR stopLogfile;
- /**
- * This variable keeps track of when we want to write a complete
- * gci log record but have been blocked by an ongoing log operation.
- */
- WaitWriteGciLog waitWriteGciLog;
- /**
- * The currently executing prepare record starts in this index
- * in the log page.
- */
- Uint16 execSrLogPageIndex;
- /**
- * Which of the four exec_sr's in the fragment is currently executing
- */
- Uint16 execSrExecuteIndex;
- /**
- * The number of pages executed in the current mbyte.
- */
- Uint16 execSrPagesExecuted;
- /**
- * The number of pages read from disk that have arrived and are
- * currently awaiting execution of the log.
- */
- Uint16 execSrPagesRead;
- /**
- * The number of pages read from disk and currently not arrived
- * to the block.
- */
- Uint16 execSrPagesReading;
- /**
- * This variable refers to the new header file where we will
- * start writing the log after a system restart have been completed.
- */
- Uint16 headFileNo;
- /**
- * This variable refers to the page number within the header file.
- */
- Uint16 headPageNo;
- /**
- * This variable refers to the index within the new header
- * page.
- */
- Uint16 headPageIndex;
- /**
- * This variables indicates which was the last mbyte in the last
- * logfile before a system crash. Discovered during system restart.
- */
- Uint16 lastMbyte;
- /**
- * This variable is used only during execution of a log
- * record. It keeps track of in which file page a log
- * record was started. It is used if it is needed to write a
- * dirty page to disk during log execution (this happens when
- * commit records are invalidated).
- */
- Uint16 prevFilepage;
- /**
- * This is used to save where we were in the execution of log
- * records when we find a commit record that needs to be
- * executed.
- *
- * This variable is also used to remember the index where the
- * log type was in the log record. It is only used in this
- * role when finding a commit record that needs to be
- * invalidated.
- */
- Uint16 savePageIndex;
- Uint8 logTailMbyte;
- /**
- * The mbyte within the starting log file where to start
- * executing the log.
- */
- Uint8 startMbyte;
- /**
- * The last mbyte in which to execute the log during system
- * restart.
- */
- Uint8 stopMbyte;
- /**
- * This variable refers to the file where invalidation is
- * occuring during system/node restart.
- */
- Uint16 invalidateFileNo;
- /**
- * This variable refers to the page where invalidation is
- * occuring during system/node restart.
- */
- Uint16 invalidatePageNo;
- }; // Size 164 Bytes
- typedef Ptr<LogPartRecord> LogPartRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ LOG FILE RECORD $$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* THIS RECORD IS ALIGNED TO BE 288 (256 + 32) BYTES. */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * This record contains information about a log file.
- * A log file contains log records from several tables and
- * fragments of a table. LQH can contain more than
- * one log file to ensure faster log processing.
- *
- * The number of pages to write to disk at a time is
- * configurable.
- */
- struct LogFileRecord {
- enum FileChangeState {
- NOT_ONGOING = 0,
- BOTH_WRITES_ONGOING = 1,
- LAST_WRITE_ONGOING = 2,
- FIRST_WRITE_ONGOING = 3,
- WRITE_PAGE_ZERO_ONGOING = 4
- };
- enum LogFileStatus {
- LFS_IDLE = 0, ///< Log file record not in use
- CLOSED = 1, ///< Log file closed
- OPENING_INIT = 2,
- OPEN_SR_FRONTPAGE = 3, ///< Log file opened as part of system
- ///< restart. Open file 0 to find
- ///< the front page of the log part.
- OPEN_SR_LAST_FILE = 4, ///< Open last log file that was written
- ///< before the system restart.
- OPEN_SR_NEXT_FILE = 5, ///< Open a log file which is 16 files
- ///< backwards to find the next
- ///< information about GCPs.
- OPEN_EXEC_SR_START = 6, ///< Log file opened as part of
- ///< executing
- ///< log during system restart.
- OPEN_EXEC_SR_NEW_MBYTE = 7,
- OPEN_SR_FOURTH_PHASE = 8,
- OPEN_SR_FOURTH_NEXT = 9,
- OPEN_SR_FOURTH_ZERO = 10,
- OPENING_WRITE_LOG = 11, ///< Log file opened as part of writing
- ///< log during normal operation.
- OPEN_EXEC_LOG = 12,
- CLOSING_INIT = 13,
- CLOSING_SR = 14, ///< Log file closed as part of system
- ///< restart. Currently trying to
- ///< find where to start executing the
- ///< log
- CLOSING_EXEC_SR = 15, ///< Log file closed as part of
- ///< executing log during system restart
- CLOSING_EXEC_SR_COMPLETED = 16,
- CLOSING_WRITE_LOG = 17, ///< Log file closed as part of writing
- ///< log during normal operation.
- CLOSING_EXEC_LOG = 18,
- OPEN_INIT = 19,
- OPEN = 20, ///< Log file open
- OPEN_SR_INVALIDATE_PAGES = 21,
- CLOSE_SR_INVALIDATE_PAGES = 22
- };
-
- /**
- * When a new mbyte is started in the log we have to find out
- * how far back in the log we still have prepared operations
- * which have been neither committed or aborted. This variable
- * keeps track of this value for each of the mbytes in this
- * log file. This is used in writing down these values in the
- * header of each log file. That information is used during
- * system restart to find the tail of the log.
- */
- UintR *logLastPrepRef;
- /**
- * The max global checkpoint completed before the mbyte in the
- * log file was started. One variable per mbyte.
- */
- UintR *logMaxGciCompleted;
- /**
- * The max global checkpoint started before the mbyte in the log
- * file was started. One variable per mbyte.
- */
- UintR *logMaxGciStarted;
- /**
- * This variable contains the file name as needed by the file
- * system when opening the file.
- */
- UintR fileName[4];
- /**
- * This variable has a reference to the log page which is
- * currently in use by the log.
- */
- UintR currentLogpage;
- /**
- * The number of the current mbyte in the log file.
- */
- UintR currentMbyte;
- /**
- * This variable is used when changing files. It is to find
- * out when both the last write in the previous file and the
- * first write in this file has been completed. After these
- * writes have completed the variable keeps track of when the
- * write to page zero in file zero is completed.
- */
- FileChangeState fileChangeState;
- /**
- * The number of the file within this log part.
- */
- UintR fileNo;
- /**
- * This variable shows where to read/write the next pages into
- * the log. Used when writing the log during normal operation
- * and when reading the log during system restart. It
- * specifies the page position where each page is 8 kbyte.
- */
- UintR filePosition;
- /**
- * This contains the file pointer needed by the file system
- * when reading/writing/closing and synching.
- */
- UintR fileRef;
- /**
- * The head of the pages waiting for shipment to disk.
- * They are filled with log info.
- */
- UintR firstFilledPage;
- /**
- * A list of active read/write operations on the log file.
- * Operations are always put in last and the first should
- * always complete first.
- */
- UintR firstLfo;
- UintR lastLfo;
- /**
- * The tail of the pages waiting for shipment to disk.
- * They are filled with log info.
- */
- UintR lastFilledPage;
- /**
- * This variable keeps track of the last written page in the
- * file while writing page zero in file zero when changing log
- * file.
- */
- UintR lastPageWritten;
- /**
- * This variable keeps track of the last written word in the
- * last page written in the file while writing page zero in
- * file zero when changing log file.
- */
- UintR lastWordWritten;
- /**
- * This variable contains the last word written in the last page.
- */
- LogFileStatus logFileStatus;
- /**
- * A reference to page zero in this file.
- * This page is written before the file is closed.
- */
- UintR logPageZero;
- /**
- * This variable contains a reference to the record describing
- * this log part. One of four records (0,1,2 or 3).
- */
- UintR logPartRec;
- /**
- * Next free log file record or next log file in this log.
- */
- UintR nextLogFile;
- /**
- * The previous log file.
- */
- UintR prevLogFile;
- /**
- * The number of remaining words in this mbyte of the log file.
- */
- UintR remainingWordsInMbyte;
- /**
- * The current file page within the current log file. This is
- * a reference within the file and not a reference to a log
- * page record. It is used to deduce where log records are
- * written. Particularly completed gcp records and prepare log
- * records.
- */
- Uint16 currentFilepage;
- /**
- * The number of pages in the list referenced by
- * LOG_PAGE_BUFFER.
- */
- Uint16 noLogpagesInBuffer;
- }; // Size 288 bytes
- typedef Ptr<LogFileRecord> LogFileRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ LOG OPERATION RECORD $$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * This record contains a currently active file operation
- * that has started by the log module.
- */
- struct LogFileOperationRecord {
- enum LfoState {
- IDLE = 0, ///< Operation is not used at the moment
- INIT_WRITE_AT_END = 1, ///< Write in file so that it grows to
- ///< 16 Mbyte
- INIT_FIRST_PAGE = 2, ///< Initialise the first page in a file
- WRITE_GCI_ZERO = 3,
- WRITE_INIT_MBYTE = 4,
- WRITE_DIRTY = 5,
- READ_SR_FRONTPAGE = 6, ///< Read page zero in file zero during
- ///< system restart
- READ_SR_LAST_FILE = 7, ///< Read page zero in last file open
- ///< before system crash
- READ_SR_NEXT_FILE = 8, ///< Read 60 files backwards to find
- ///< further information GCPs in page
- ///< zero
- READ_SR_LAST_MBYTE = 9,
- READ_EXEC_SR = 10,
- READ_EXEC_LOG = 11,
- READ_SR_FOURTH_PHASE = 12,
- READ_SR_FOURTH_ZERO = 13,
- FIRST_PAGE_WRITE_IN_LOGFILE = 14,
- LAST_WRITE_IN_FILE = 15,
- WRITE_PAGE_ZERO = 16,
- ACTIVE_WRITE_LOG = 17, ///< A write operation during
- ///< writing of log
- READ_SR_INVALIDATE_PAGES = 18,
- WRITE_SR_INVALIDATE_PAGES = 19,
- WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0 = 20
- };
- /**
- * We have to remember the log pages read.
- * Otherwise we cannot build the linked list after the pages have
- * arrived to main memory.
- */
- UintR logPageArray[16];
- /**
- * A list of the pages that are part of this active operation.
- */
- UintR firstLfoPage;
- /**
- * A timer to ensure that records are not lost.
- */
- UintR lfoTimer;
- /**
- * The word number of the last written word in the last during
- * a file write.
- */
- UintR lfoWordWritten;
- /**
- * This variable contains the state of the log file operation.
- */
- LfoState lfoState;
- /**
- * The log file that the file operation affects.
- */
- UintR logFileRec;
- /**
- * The log file operations on a file are kept in a linked list.
- */
- UintR nextLfo;
- /**
- * The page number of the first read/written page during a file
- * read/write.
- */
- Uint16 lfoPageNo;
- /**
- * The number of pages written or read during an operation to
- * the log file.
- */
- Uint16 noPagesRw;
- }; // 92 bytes
- typedef Ptr<LogFileOperationRecord> LogFileOperationRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$$ LOG PAGE RECORD $$$$$$$ */
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /**
- * These are the 8 k pages used to store log records before storing
- * them in the file system.
- * Since 64 kbyte is sent to disk at a time it is necessary to have
- * at least 4*64 kbytes of log pages.
- * To handle multiple outstanding requests we need some additional pages.
- * Thus we allocate 1 mbyte to ensure that we do not get problems with
- * insufficient number of pages.
- */
- struct LogPageRecord {
- /**
- * This variable contains the pages that are sent to disk.
- *
- * All pages contain a header of 12 words:
- * - WORD 0: CHECKSUM Calculated before storing on disk and
- * checked when read from disk.
- * - WORD 1: LAP How many wraparounds have the log
- * experienced since initial start of the
- * system.
- * - WORD 2: MAX_GCI_COMPLETED Which is the maximum gci which have
- * completed before this page. This
- * gci will not be found in this
- * page and hereafter in the log.
- * - WORD 3: MAX_GCI_STARTED The maximum gci which have started
- * before this page.
- * - WORD 4: NEXT_PAGE Pointer to the next page.
- * Only used in main memory
- * - WORD 5: PREVIOUS_PAGE Pointer to the previous page.
- * Currently not used.
- * - WORD 6: VERSION NDB version that wrote the page.
- * - WORD 7: NO_LOG_FILES Number of log files in this log part.
- * - WORD 8: CURRENT PAGE INDEX This keeps track of where we are in the
- * page.
- * This is only used when pages is in
- * memory.
- * - WORD 9: OLD PREPARE FILE NO This keeps track of the oldest prepare
- * operation still alive (not committed
- * or aborted) when this mbyte started.
- * - WORD 10: OLD PREPARE PAGE REF File page reference within this file
- * number.
- * Page no + Page index.
- * If no prepare was alive then these
- * values points this mbyte.
- * - WORD 11: DIRTY FLAG = 0 means not dirty and
- * = 1 means the page is dirty.
- * Is used when executing log when
- * a need to write invalid commit
- * records arise.
- *
- * The remaining 2036 words are used for log information, i.e.
- * log records.
- *
- * A log record on this page has the following layout:
- * - WORD 0: LOG RECORD TYPE
- * The following types are supported:
- * - PREPARE OPERATION An operation not yet committed.
- * - NEW PREPARE OPERATION A prepared operation already
- * logged is inserted
- * into the log again so that the
- * log tail can be advanced.
- * This can happen when a transaction is
- * committed for a long time.
- * - ABORT TRANSACTION A previously prepared transaction
- * was aborted.
- * - COMMIT TRANSACTION A previously prepared transaction
- * was committed.
- * - INVALID COMMIT A previous commit record was
- * invalidated by a
- * subsequent system restart.
- * A log record must be invalidated
- * in a system restart if it belongs
- * to a global checkpoint id which
- * is not included in the system
- * restart.
- * Otherwise it will be included in
- * a subsequent system restart since
- * it will then most likely belong
- * to a global checkpoint id which
- * is part of that system
- * restart.
- * This is not a correct behaviour
- * since this operation is lost in a
- * system restart and should not
- * reappear at a later system
- * restart.
- * - COMPLETED GCI A GCI has now been completed.
- * - FRAGMENT SPLIT A fragment has been split
- * (not implemented yet)
- * - FILE DESCRIPTOR This is always the first log record
- * in a file.
- * It is always placed on page 0 after
- * the header.
- * It is written when the file is
- * opened and when the file is closed.
- * - NEXT LOG RECORD This log record only records where
- * the next log record starts.
- * - NEXT MBYTE RECORD This log record specifies that there
- * are no more log records in this mbyte.
- *
- *
- * A FILE DESCRIPTOR log record continues as follows:
- * - WORD 1: NO_LOG_DESCRIPTORS This defines the number of
- * descriptors of log files that
- * will follow hereafter (max 32).
- * the log descriptor will describe
- * information about
- * max_gci_completed,
- * max_gci_started and log_lap at
- * every 1 mbyte of the log file
- * since a log file is 16 mbyte
- * always, i need 16 entries in the
- * array with max_gci_completed,
- * max_gci_started and log_lap. thus
- * 32 entries per log file
- * descriptor (max 32*48 = 1536,
- * always fits in page 0).
- * - WORD 2: LAST LOG FILE The number of the log file currently
- * open. This is only valid in file 0.
- * - WORD 3 - WORD 18: MAX_GCI_COMPLETED for every 1 mbyte
- * in this log file.
- * - WORD 19 - WORD 34: MAX_GCI_STARTED for every 1 mbyte
- * in this log file.
- *
- * Then it continues for NO_LOG_DESCRIPTORS until all subsequent
- * log files (max 32) have been properly described.
- *
- *
- * A PREPARE OPERATION log record continues as follows:
- * - WORD 1: LOG RECORD SIZE
- * - WORD 2: HASH VALUE
- * - WORD 3: SCHEMA VERSION
- * - WORD 4: OPERATION TYPE
- * = 0 READ,
- * = 1 UPDATE,
- * = 2 INSERT,
- * = 3 DELETE
- * - WORD 5: NUMBER OF WORDS IN ATTRINFO PART
- * - WORD 6: KEY LENGTH IN WORDS
- * - WORD 7 - (WORD 7 + KEY_LENGTH - 1) The tuple key
- * - (WORD 7 + KEY_LENGTH) -
- * (WORD 7 + KEY_LENGTH + ATTRINFO_LENGTH - 1) The attrinfo
- *
- * A log record can be spread in several pages in some cases.
- * The next log record always starts immediately after this log record.
- * A log record does however never traverse a 1 mbyte boundary.
- * This is used to ensure that we can always come back if something
- * strange occurs in the log file.
- * To ensure this we also have log records which only records
- * the next log record.
- *
- *
- * A COMMIT TRANSACTION log record continues as follows:
- * - WORD 1: TRANSACTION ID PART 1
- * - WORD 2: TRANSACTION ID PART 2
- * - WORD 3: FRAGMENT ID OF THE OPERATION
- * - WORD 4: TABLE ID OF THE OPERATION
- * - WORD 5: THE FILE NUMBER OF THE PREPARE RECORD
- * - WORD 6: THE STARTING PAGE NUMBER OF THE PREPARE RECORD
- * - WORD 7: THE STARTING PAGE INDEX OF THE PREPARE RECORD
- * - WORD 8: THE STOP PAGE NUMBER OF THE PREPARE RECORD
- * - WORD 9: GLOBAL CHECKPOINT OF THE TRANSACTION
- *
- *
- * An ABORT TRANSACTION log record continues as follows:
- * - WORD 1: TRANSACTION ID PART 1
- * - WORD 2: TRANSACTION ID PART 2
- *
- *
- * A COMPLETED CGI log record continues as follows:
- * - WORD 1: THE COMPLETED GCI
- *
- *
- * A NEXT LOG RECORD log record continues as follows:
- * - There is no more information needed.
- * The next log record will always refer to the start of the next page.
- *
- * A NEXT MBYTE RECORD log record continues as follows:
- * - There is no more information needed.
- * The next mbyte will always refer to the start of the next mbyte.
- */
- UintR logPageWord[8192]; // Size 32 kbytes
- };
- typedef Ptr<LogPageRecord> LogPageRecordPtr;
-
- struct PageRefRecord {
- UintR pageRef[8];
- UintR prNext;
- UintR prPrev;
- Uint16 prFileNo;
- Uint16 prPageNo;
- }; // size 44 bytes
- typedef Ptr<PageRefRecord> PageRefRecordPtr;
-
- struct Tablerec {
- enum TableStatus {
- TABLE_DEFINED = 0,
- NOT_DEFINED = 1,
- ADD_TABLE_ONGOING = 2,
- PREP_DROP_TABLE_ONGOING = 3,
- PREP_DROP_TABLE_DONE = 4
- };
-
- UintR fragrec[MAX_FRAG_PER_NODE];
- Uint16 fragid[MAX_FRAG_PER_NODE];
- /**
- * Status of the table
- */
- TableStatus tableStatus;
- /**
- * Table type and target table of index.
- */
- Uint16 tableType;
- Uint16 primaryTableId;
- Uint32 schemaVersion;
- Uint8 m_disk_table;
-
- Uint32 usageCount;
- NdbNodeBitmask waitingTC;
- NdbNodeBitmask waitingDIH;
- }; // Size 100 bytes
- typedef Ptr<Tablerec> TablerecPtr;
-
- struct TcConnectionrec {
- enum ListState {
- NOT_IN_LIST = 0,
- WAIT_QUEUE_LIST = 3
- };
- enum LogWriteState {
- NOT_STARTED = 0,
- NOT_WRITTEN = 1,
- NOT_WRITTEN_WAIT = 2,
- WRITTEN = 3
- };
- enum AbortState {
- ABORT_IDLE = 0,
- ABORT_ACTIVE = 1,
- NEW_FROM_TC = 2,
- REQ_FROM_TC = 3,
- ABORT_FROM_TC = 4,
- ABORT_FROM_LQH = 5
- };
- enum TransactionState {
- IDLE = 0,
-
- /* -------------------------------------------------------------------- */
- // Transaction in progress states
- /* -------------------------------------------------------------------- */
- WAIT_ACC = 1,
- WAIT_TUPKEYINFO = 2,
- WAIT_ATTR = 3,
- WAIT_TUP = 4,
- STOPPED = 5,
- LOG_QUEUED = 6,
- PREPARED = 7,
- LOG_COMMIT_WRITTEN_WAIT_SIGNAL = 8,
- LOG_COMMIT_QUEUED_WAIT_SIGNAL = 9,
-
- /* -------------------------------------------------------------------- */
- // Commit in progress states
- /* -------------------------------------------------------------------- */
- COMMIT_STOPPED = 10,
- LOG_COMMIT_QUEUED = 11,
- COMMIT_QUEUED = 12,
- COMMITTED = 13,
- WAIT_TUP_COMMIT= 35,
-
- /* -------------------------------------------------------------------- */
- // Abort in progress states
- /* -------------------------------------------------------------------- */
- WAIT_ACC_ABORT = 14,
- ABORT_QUEUED = 15,
- ABORT_STOPPED = 16,
- WAIT_AI_AFTER_ABORT = 17,
- LOG_ABORT_QUEUED = 18,
- WAIT_TUP_TO_ABORT = 19,
-
- /* -------------------------------------------------------------------- */
- // Scan in progress states
- /* -------------------------------------------------------------------- */
- WAIT_SCAN_AI = 20,
- SCAN_STATE_USED = 21,
- SCAN_FIRST_STOPPED = 22,
- SCAN_CHECK_STOPPED = 23,
- SCAN_STOPPED = 24,
- SCAN_RELEASE_STOPPED = 25,
- SCAN_CLOSE_STOPPED = 26,
- COPY_CLOSE_STOPPED = 27,
- COPY_FIRST_STOPPED = 28,
- COPY_STOPPED = 29,
- SCAN_TUPKEY = 30,
- COPY_TUPKEY = 31,
-
- TC_NOT_CONNECTED = 32,
- PREPARED_RECEIVED_COMMIT = 33, // Temporary state in write commit log
- LOG_COMMIT_WRITTEN = 34 // Temporary state in write commit log
- };
- enum ConnectState {
- DISCONNECTED = 0,
- CONNECTED = 1,
- COPY_CONNECTED = 2,
- LOG_CONNECTED = 3
- };
- ConnectState connectState;
- UintR copyCountWords;
- UintR firstAttrinfo[5];
- UintR tupkeyData[4];
- UintR transid[2];
- AbortState abortState;
- UintR accConnectrec;
- UintR applOprec;
- UintR clientConnectrec;
- UintR tcTimer;
- UintR currReclenAi;
- UintR currTupAiLen;
- UintR firstAttrinbuf;
- UintR firstTupkeybuf;
- UintR fragmentid;
- UintR fragmentptr;
- UintR gci;
- UintR hashValue;
- UintR lastTupkeybuf;
- UintR lastAttrinbuf;
- /**
- * Each operation (TcConnectrec) can be stored in max one out of many
- * lists.
- * This variable keeps track of which list it is in.
- */
- ListState listState;
-
- UintR logStartFileNo;
- LogWriteState logWriteState;
- UintR nextHashRec;
- UintR nextLogTcrec;
- UintR nextTcLogQueue;
- UintR nextTc;
- UintR nextTcConnectrec;
- UintR prevHashRec;
- UintR prevLogTcrec;
- UintR prevTc;
- UintR readlenAi;
- UintR reqRef;
- UintR reqinfo;
- UintR schemaVersion;
- UintR storedProcId;
- UintR simpleTcConnect;
- UintR tableref;
- UintR tcOprec;
- UintR tcScanInfo;
- UintR tcScanRec;
- UintR totReclenAi;
- UintR totSendlenAi;
- UintR tupConnectrec;
- UintR savePointId;
- TransactionState transactionState;
- BlockReference applRef;
- BlockReference clientBlockref;
-
- BlockReference reqBlockref;
- BlockReference tcBlockref;
- BlockReference tcAccBlockref;
- BlockReference tcTuxBlockref;
- BlockReference tcTupBlockref;
- Uint32 commitAckMarker;
- union {
- Uint32 m_scan_curr_range_no;
- UintR noFiredTriggers;
- };
- Uint16 errorCode;
- Uint16 logStartPageIndex;
- Uint16 logStartPageNo;
- Uint16 logStopPageNo;
- Uint16 nextReplica;
- Uint16 primKeyLen;
- Uint16 save1;
- Uint16 nodeAfterNext[3];
-
- Uint8 activeCreat;
- Uint8 apiVersionNo;
- Uint8 dirtyOp;
- Uint8 indTakeOver;
- Uint8 lastReplicaNo;
- Uint8 lockType;
- Uint8 nextSeqNoReplica;
- Uint8 opSimple;
- Uint8 opExec;
- Uint8 operation;
- Uint8 reclenAiLqhkey;
- Uint8 m_offset_current_keybuf;
- Uint8 replicaType;
- Uint8 seqNoReplica;
- Uint8 tcNodeFailrec;
- Uint8 m_disk_table;
- Uint8 m_use_rowid;
- Uint8 m_dealloc;
- Uint32 m_log_part_ptr_i;
- Local_key m_row_id;
-
- struct {
- Uint32 m_cnt;
- Uint32 m_page_id[2];
- Local_key m_disk_ref[2];
- } m_nr_delete;
- }; /* p2c: size = 280 bytes */
-
- typedef Ptr<TcConnectionrec> TcConnectionrecPtr;
-
- struct TcNodeFailRecord {
- enum TcFailStatus {
- TC_STATE_TRUE = 0,
- TC_STATE_FALSE = 1,
- TC_STATE_BREAK = 2
- };
- UintR lastNewTcRef;
- UintR newTcRef;
- TcFailStatus tcFailStatus;
- UintR tcRecNow;
- BlockReference lastNewTcBlockref;
- BlockReference newTcBlockref;
- Uint16 oldNodeId;
- }; // Size 28 bytes
- typedef Ptr<TcNodeFailRecord> TcNodeFailRecordPtr;
-
- struct CommitLogRecord {
- Uint32 startPageNo;
- Uint32 startPageIndex;
- Uint32 stopPageNo;
- Uint32 fileNo;
- };
-
-public:
- Dblqh(Block_context& ctx);
- virtual ~Dblqh();
-
- void receive_keyinfo(Signal*, Uint32 * data, Uint32 len);
- void receive_attrinfo(Signal*, Uint32 * data, Uint32 len);
-
-private:
- BLOCK_DEFINES(Dblqh);
-
- void execPACKED_SIGNAL(Signal* signal);
- void execDEBUG_SIG(Signal* signal);
- void execATTRINFO(Signal* signal);
- void execKEYINFO(Signal* signal);
- void execLQHKEYREQ(Signal* signal);
- void execLQHKEYREF(Signal* signal);
- void execCOMMIT(Signal* signal);
- void execCOMPLETE(Signal* signal);
- void execLQHKEYCONF(Signal* signal);
- void execTESTSIG(Signal* signal);
- void execLQH_RESTART_OP(Signal* signal);
- void execCONTINUEB(Signal* signal);
- void execSTART_RECREQ(Signal* signal);
- void execSTART_RECCONF(Signal* signal);
- void execEXEC_FRAGREQ(Signal* signal);
- void execEXEC_FRAGCONF(Signal* signal);
- void execEXEC_FRAGREF(Signal* signal);
- void execSTART_EXEC_SR(Signal* signal);
- void execEXEC_SRREQ(Signal* signal);
- void execEXEC_SRCONF(Signal* signal);
- void execREAD_PSEUDO_REQ(Signal* signal);
-
- void execDUMP_STATE_ORD(Signal* signal);
- void execACC_ABORTCONF(Signal* signal);
- void execNODE_FAILREP(Signal* signal);
- void execCHECK_LCP_STOP(Signal* signal);
- void execSEND_PACKED(Signal* signal);
- void execTUP_ATTRINFO(Signal* signal);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execLQHFRAGREQ(Signal* signal);
- void execLQHADDATTREQ(Signal* signal);
- void execTUP_ADD_ATTCONF(Signal* signal);
- void execTUP_ADD_ATTRREF(Signal* signal);
- void execACCFRAGCONF(Signal* signal);
- void execACCFRAGREF(Signal* signal);
- void execTUPFRAGCONF(Signal* signal);
- void execTUPFRAGREF(Signal* signal);
- void execTAB_COMMITREQ(Signal* signal);
- void execACCSEIZECONF(Signal* signal);
- void execACCSEIZEREF(Signal* signal);
- void execREAD_NODESCONF(Signal* signal);
- void execREAD_NODESREF(Signal* signal);
- void execSTTOR(Signal* signal);
- void execNDB_STTOR(Signal* signal);
- void execTUPSEIZECONF(Signal* signal);
- void execTUPSEIZEREF(Signal* signal);
- void execACCKEYCONF(Signal* signal);
- void execACCKEYREF(Signal* signal);
- void execTUPKEYCONF(Signal* signal);
- void execTUPKEYREF(Signal* signal);
- void execABORT(Signal* signal);
- void execABORTREQ(Signal* signal);
- void execCOMMITREQ(Signal* signal);
- void execCOMPLETEREQ(Signal* signal);
- void execMEMCHECKREQ(Signal* signal);
- void execSCAN_FRAGREQ(Signal* signal);
- void execSCAN_NEXTREQ(Signal* signal);
- void execACC_SCANCONF(Signal* signal);
- void execACC_SCANREF(Signal* signal);
- void execNEXT_SCANCONF(Signal* signal);
- void execNEXT_SCANREF(Signal* signal);
- void execACC_TO_REF(Signal* signal);
- void execSTORED_PROCCONF(Signal* signal);
- void execSTORED_PROCREF(Signal* signal);
- void execCOPY_FRAGREQ(Signal* signal);
- void execPREPARE_COPY_FRAG_REQ(Signal* signal);
- void execUPDATE_FRAG_DIST_KEY_ORD(Signal*);
- void execCOPY_ACTIVEREQ(Signal* signal);
- void execCOPY_STATEREQ(Signal* signal);
- void execLQH_TRANSREQ(Signal* signal);
- void execTRANSID_AI(Signal* signal);
- void execINCL_NODEREQ(Signal* signal);
-
- void execLCP_FRAG_ORD(Signal* signal);
- void execEMPTY_LCP_REQ(Signal* signal);
-
- void execSTART_FRAGREQ(Signal* signal);
- void execSTART_RECREF(Signal* signal);
-
- void execGCP_SAVEREQ(Signal* signal);
- void execFSOPENREF(Signal* signal);
- void execFSOPENCONF(Signal* signal);
- void execFSCLOSECONF(Signal* signal);
- void execFSWRITECONF(Signal* signal);
- void execFSWRITEREF(Signal* signal);
- void execFSREADCONF(Signal* signal);
- void execFSREADREF(Signal* signal);
- void execSCAN_HBREP(Signal* signal);
- void execTIME_SIGNAL(Signal* signal);
- void execFSSYNCCONF(Signal* signal);
-
- void execALTER_TAB_REQ(Signal* signal);
- void execALTER_TAB_CONF(Signal* signal);
-
- void execCREATE_TRIG_CONF(Signal* signal);
- void execCREATE_TRIG_REF(Signal* signal);
- void execCREATE_TRIG_REQ(Signal* signal);
-
- void execDROP_TRIG_CONF(Signal* signal);
- void execDROP_TRIG_REF(Signal* signal);
- void execDROP_TRIG_REQ(Signal* signal);
-
- void execPREP_DROP_TAB_REQ(Signal* signal);
- void execWAIT_DROP_TAB_REQ(Signal* signal);
- void execDROP_TAB_REQ(Signal* signal);
-
- void execLQH_ALLOCREQ(Signal* signal);
- void execTUP_DEALLOCREQ(Signal* signal);
- void execLQH_WRITELOG_REQ(Signal* signal);
-
- void execTUXFRAGCONF(Signal* signal);
- void execTUXFRAGREF(Signal* signal);
- void execTUX_ADD_ATTRCONF(Signal* signal);
- void execTUX_ADD_ATTRREF(Signal* signal);
-
- // Statement blocks
-
- void init_acc_ptr_list(ScanRecord*);
- bool seize_acc_ptr_list(ScanRecord*, Uint32);
- void release_acc_ptr_list(ScanRecord*);
- Uint32 get_acc_ptr_from_scan_record(ScanRecord*, Uint32, bool);
- void set_acc_ptr_in_scan_record(ScanRecord*, Uint32, Uint32);
- void i_get_acc_ptr(ScanRecord*, Uint32*&, Uint32);
-
- void removeTable(Uint32 tableId);
- void sendLCP_COMPLETE_REP(Signal* signal, Uint32 lcpId);
- void sendEMPTY_LCP_CONF(Signal* signal, bool idle);
- void sendLCP_FRAGIDREQ(Signal* signal);
- void sendLCP_FRAG_REP(Signal * signal, const LcpRecord::FragOrd &) const;
-
- void updatePackedList(Signal* signal, HostRecord * ahostptr, Uint16 hostId);
- void LQHKEY_abort(Signal* signal, int errortype);
- void LQHKEY_error(Signal* signal, int errortype);
- void nextRecordCopy(Signal* signal);
- Uint32 calculateHash(Uint32 tableId, const Uint32* src);
- void continueAfterCheckLcpStopBlocked(Signal* signal);
- void checkLcpStopBlockedLab(Signal* signal);
- void sendCommittedTc(Signal* signal, BlockReference atcBlockref);
- void sendCompletedTc(Signal* signal, BlockReference atcBlockref);
- void sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref);
- void sendCommitLqh(Signal* signal, BlockReference alqhBlockref);
- void sendCompleteLqh(Signal* signal, BlockReference alqhBlockref);
- void sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr);
- void sendPackedSignalTc(Signal* signal, HostRecord * ahostptr);
- void cleanUp(Signal* signal);
- void sendAttrinfoLoop(Signal* signal);
- void sendAttrinfoSignal(Signal* signal);
- void sendLqhAttrinfoSignal(Signal* signal);
- void sendKeyinfoAcc(Signal* signal, Uint32 pos);
- Uint32 initScanrec(const class ScanFragReq *);
- void initScanTc(const class ScanFragReq *,
- Uint32 transid1,
- Uint32 transid2,
- Uint32 fragId,
- Uint32 nodeId);
- void finishScanrec(Signal* signal);
- void releaseScanrec(Signal* signal);
- void seizeScanrec(Signal* signal);
- Uint32 sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
- void sendTCKEYREF(Signal*, Uint32 dst, Uint32 route, Uint32 cnt);
- void sendScanFragConf(Signal* signal, Uint32 scanCompleted);
- void initCopyrec(Signal* signal);
- void initCopyTc(Signal* signal, Operation_t);
- void sendCopyActiveConf(Signal* signal,Uint32 tableId);
- void checkLcpCompleted(Signal* signal);
- void checkLcpHoldop(Signal* signal);
- bool checkLcpStarted(Signal* signal);
- void checkLcpTupprep(Signal* signal);
- void getNextFragForLcp(Signal* signal);
- void sendAccContOp(Signal* signal);
- void sendStartLcp(Signal* signal);
- void setLogTail(Signal* signal, Uint32 keepGci);
- Uint32 remainingLogSize(const LogFileRecordPtr &sltCurrLogFilePtr,
- const LogPartRecordPtr &sltLogPartPtr);
- void checkGcpCompleted(Signal* signal, Uint32 pageWritten, Uint32 wordWritten);
- void initFsopenconf(Signal* signal);
- void initFsrwconf(Signal* signal, bool write);
- void initLfo(Signal* signal);
- void initLogfile(Signal* signal, Uint32 fileNo);
- void initLogpage(Signal* signal);
- void openFileRw(Signal* signal, LogFileRecordPtr olfLogFilePtr);
- void openLogfileInit(Signal* signal);
- void openNextLogfile(Signal* signal);
- void releaseLfo(Signal* signal);
- void releaseLfoPages(Signal* signal);
- void releaseLogpage(Signal* signal);
- void seizeLfo(Signal* signal);
- void seizeLogfile(Signal* signal);
- void seizeLogpage(Signal* signal);
- void writeFileDescriptor(Signal* signal);
- void writeFileHeaderOpen(Signal* signal, Uint32 type);
- void writeInitMbyte(Signal* signal);
- void writeSinglePage(Signal* signal, Uint32 pageNo,
- Uint32 wordWritten, Uint32 place);
- void buildLinkedLogPageList(Signal* signal);
- void changeMbyte(Signal* signal);
- Uint32 checkIfExecLog(Signal* signal);
- void checkNewMbyte(Signal* signal);
- void checkReadExecSr(Signal* signal);
- void checkScanTcCompleted(Signal* signal);
- void closeFile(Signal* signal, LogFileRecordPtr logFilePtr, Uint32 place);
- void completedLogPage(Signal* signal, Uint32 clpType, Uint32 place);
- void deleteFragrec(Uint32 fragId);
- void deleteTransidHash(Signal* signal);
- void findLogfile(Signal* signal,
- Uint32 fileNo,
- LogPartRecordPtr flfLogPartPtr,
- LogFileRecordPtr* parLogFilePtr);
- void findPageRef(Signal* signal, CommitLogRecord* commitLogRecord);
- int findTransaction(UintR Transid1, UintR Transid2, UintR TcOprec);
- void getFirstInLogQueue(Signal* signal);
- bool getFragmentrec(Signal* signal, Uint32 fragId);
- void initialiseAddfragrec(Signal* signal);
- void initialiseAttrbuf(Signal* signal);
- void initialiseDatabuf(Signal* signal);
- void initialiseFragrec(Signal* signal);
- void initialiseGcprec(Signal* signal);
- void initialiseLcpRec(Signal* signal);
- void initialiseLfo(Signal* signal);
- void initialiseLogFile(Signal* signal);
- void initialiseLogPage(Signal* signal);
- void initialiseLogPart(Signal* signal);
- void initialisePageRef(Signal* signal);
- void initialiseScanrec(Signal* signal);
- void initialiseTabrec(Signal* signal);
- void initialiseTcrec(Signal* signal);
- void initialiseTcNodeFailRec(Signal* signal);
- void initFragrec(Signal* signal,
- Uint32 tableId,
- Uint32 fragId,
- Uint32 copyType);
- void initFragrecSr(Signal* signal);
- void initGciInLogFileRec(Signal* signal, Uint32 noFdDesc);
- void initLcpSr(Signal* signal,
- Uint32 lcpNo,
- Uint32 lcpId,
- Uint32 tableId,
- Uint32 fragId,
- Uint32 fragPtr);
- void initLogpart(Signal* signal);
- void initLogPointers(Signal* signal);
- void initReqinfoExecSr(Signal* signal);
- bool insertFragrec(Signal* signal, Uint32 fragId);
- void linkFragQueue(Signal* signal);
- void linkWaitLog(Signal* signal, LogPartRecordPtr regLogPartPtr);
- void logNextStart(Signal* signal);
- void moveToPageRef(Signal* signal);
- void readAttrinfo(Signal* signal);
- void readCommitLog(Signal* signal, CommitLogRecord* commitLogRecord);
- void readExecLog(Signal* signal);
- void readExecSrNewMbyte(Signal* signal);
- void readExecSr(Signal* signal);
- void readKey(Signal* signal);
- void readLogData(Signal* signal, Uint32 noOfWords, Uint32* dataPtr);
- void readLogHeader(Signal* signal);
- Uint32 readLogword(Signal* signal);
- Uint32 readLogwordExec(Signal* signal);
- void readSinglePage(Signal* signal, Uint32 pageNo);
- void releaseActiveCopy(Signal* signal);
- void releaseAddfragrec(Signal* signal);
- void releaseFragrec();
- void releaseOprec(Signal* signal);
- void releasePageRef(Signal* signal);
- void releaseMmPages(Signal* signal);
- void releasePrPages(Signal* signal);
- void releaseTcrec(Signal* signal, TcConnectionrecPtr tcConnectptr);
- void releaseTcrecLog(Signal* signal, TcConnectionrecPtr tcConnectptr);
- void releaseWaitQueue(Signal* signal);
- void removeLogTcrec(Signal* signal);
- void removePageRef(Signal* signal);
- Uint32 returnExecLog(Signal* signal);
- int saveTupattrbuf(Signal* signal, Uint32* dataPtr, Uint32 length);
- void seizeAddfragrec(Signal* signal);
- 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();
- void seizeTupkeybuf(Signal* signal);
- void sendAborted(Signal* signal);
- void sendLqhTransconf(Signal* signal, LqhTransConf::OperationStatus);
- void sendTupkey(Signal* signal);
- void startExecSr(Signal* signal);
- void startNextExecSr(Signal* signal);
- void startTimeSupervision(Signal* signal);
- void stepAhead(Signal* signal, Uint32 stepAheadWords);
- void systemError(Signal* signal, int line);
- void writeAbortLog(Signal* signal);
- void writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr);
- void writeCompletedGciLog(Signal* signal);
- void writeDbgInfoPageHeader(LogPageRecordPtr logPagePtr, Uint32 place,
- Uint32 pageNo, Uint32 wordWritten);
- void writeDirty(Signal* signal, Uint32 place);
- void writeKey(Signal* signal);
- void writeLogHeader(Signal* signal);
- void writeLogWord(Signal* signal, Uint32 data);
- void writeNextLog(Signal* signal);
- void errorReport(Signal* signal, int place);
- void warningReport(Signal* signal, int place);
- void invalidateLogAfterLastGCI(Signal *signal);
- void readFileInInvalidate(Signal *signal, bool stepNext);
- void exitFromInvalidate(Signal* signal);
- Uint32 calcPageCheckSum(LogPageRecordPtr logP);
- Uint32 handleLongTupKey(Signal* signal, Uint32* dataPtr, Uint32 len);
-
- // Generated statement blocks
- void systemErrorLab(Signal* signal, int line);
- void initFourth(Signal* signal);
- void packLqhkeyreqLab(Signal* signal);
- void sendNdbSttorryLab(Signal* signal);
- void execSrCompletedLab(Signal* signal);
- void execLogRecord(Signal* signal);
- void srPhase3Comp(Signal* signal);
- void srLogLimits(Signal* signal);
- void srGciLimits(Signal* signal);
- void srPhase3Start(Signal* signal);
- void checkStartCompletedLab(Signal* signal);
- void continueAbortLab(Signal* signal);
- void abortContinueAfterBlockedLab(Signal* signal, bool canBlock);
- void abortCommonLab(Signal* signal);
- void localCommitLab(Signal* signal);
- void abortErrorLab(Signal* signal);
- void continueAfterReceivingAllAiLab(Signal* signal);
- void abortStateHandlerLab(Signal* signal);
- void writeAttrinfoLab(Signal* signal);
- void scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
- void abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode);
- void localAbortStateHandlerLab(Signal* signal);
- void logLqhkeyreqLab(Signal* signal);
- void lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
- void rwConcludedAiLab(Signal* signal);
- void aiStateErrorCheckLab(Signal* signal, Uint32* dataPtr, Uint32 length);
- void takeOverErrorLab(Signal* signal);
- void endgettupkeyLab(Signal* signal);
- void noFreeRecordLab(Signal* signal,
- const class LqhKeyReq * lqhKeyReq,
- Uint32 errorCode);
- void logLqhkeyrefLab(Signal* signal);
- void closeCopyLab(Signal* signal);
- void commitReplyLab(Signal* signal);
- void completeUnusualLab(Signal* signal);
- void completeTransNotLastLab(Signal* signal);
- void completedLab(Signal* signal);
- void copyCompletedLab(Signal* signal);
- void completeLcpRoundLab(Signal* signal, Uint32 lcpId);
- void continueAfterLogAbortWriteLab(Signal* signal);
- void sendAttrinfoLab(Signal* signal);
- void sendExecConf(Signal* signal);
- void execSr(Signal* signal);
- void srFourthComp(Signal* signal);
- void timeSup(Signal* signal);
- void closeCopyRequestLab(Signal* signal);
- void closeScanRequestLab(Signal* signal);
- void scanTcConnectLab(Signal* signal, Uint32 startTcCon, Uint32 fragId);
- void initGcpRecLab(Signal* signal);
- void prepareContinueAfterBlockedLab(Signal* signal);
- void commitContinueAfterBlockedLab(Signal* signal);
- void continueCopyAfterBlockedLab(Signal* signal);
- void continueFirstCopyAfterBlockedLab(Signal* signal);
- void continueFirstScanAfterBlockedLab(Signal* signal);
- void continueScanAfterBlockedLab(Signal* signal);
- void continueScanReleaseAfterBlockedLab(Signal* signal);
- void continueCloseScanAfterBlockedLab(Signal* signal);
- void continueCloseCopyAfterBlockedLab(Signal* signal);
- void sendExecFragRefLab(Signal* signal);
- void fragrefLab(Signal* signal, BlockReference retRef,
- Uint32 retPtr, Uint32 errorCode);
- void abortAddFragOps(Signal* signal);
- void rwConcludedLab(Signal* signal);
- void sendsttorryLab(Signal* signal);
- void initialiseRecordsLab(Signal* signal, Uint32 data, Uint32, Uint32);
- void startphase2Lab(Signal* signal, Uint32 config);
- void startphase3Lab(Signal* signal);
- void startphase4Lab(Signal* signal);
- void startphase6Lab(Signal* signal);
- void moreconnectionsLab(Signal* signal);
- void scanReleaseLocksLab(Signal* signal);
- void closeScanLab(Signal* signal);
- void nextScanConfLoopLab(Signal* signal);
- void scanNextLoopLab(Signal* signal);
- void commitReqLab(Signal* signal, Uint32 gci);
- void completeTransLastLab(Signal* signal);
- void tupScanCloseConfLab(Signal* signal);
- void tupCopyCloseConfLab(Signal* signal);
- void accScanCloseConfLab(Signal* signal);
- void accCopyCloseConfLab(Signal* signal);
- void nextScanConfScanLab(Signal* signal);
- void nextScanConfCopyLab(Signal* signal);
- void continueScanNextReqLab(Signal* signal);
- void keyinfoLab(const Uint32 * src, const Uint32 * end);
- void copySendTupkeyReqLab(Signal* signal);
- void storedProcConfScanLab(Signal* signal);
- void storedProcConfCopyLab(Signal* signal);
- void copyStateFinishedLab(Signal* signal);
- void lcpCompletedLab(Signal* signal);
- void lcpStartedLab(Signal* signal);
- void contChkpNextFragLab(Signal* signal);
- void startLcpRoundLab(Signal* signal);
- void startFragRefLab(Signal* signal);
- void srCompletedLab(Signal* signal);
- void openFileInitLab(Signal* signal);
- void openSrFrontpageLab(Signal* signal);
- void openSrLastFileLab(Signal* signal);
- void openSrNextFileLab(Signal* signal);
- void openExecSrStartLab(Signal* signal);
- void openExecSrNewMbyteLab(Signal* signal);
- void openSrFourthPhaseLab(Signal* signal);
- void openSrFourthZeroSkipInitLab(Signal* signal);
- void openSrFourthZeroLab(Signal* signal);
- void openExecLogLab(Signal* signal);
- void checkInitCompletedLab(Signal* signal);
- void closingSrLab(Signal* signal);
- void closeExecSrLab(Signal* signal);
- void execLogComp(Signal* signal);
- void closeWriteLogLab(Signal* signal);
- void closeExecLogLab(Signal* signal);
- void writePageZeroLab(Signal* signal);
- void lastWriteInFileLab(Signal* signal);
- void initWriteEndLab(Signal* signal);
- void initFirstPageLab(Signal* signal);
- void writeGciZeroLab(Signal* signal);
- void writeDirtyLab(Signal* signal);
- void writeInitMbyteLab(Signal* signal);
- void writeLogfileLab(Signal* signal);
- void firstPageWriteLab(Signal* signal);
- void readSrLastMbyteLab(Signal* signal);
- void readSrLastFileLab(Signal* signal);
- void readSrNextFileLab(Signal* signal);
- void readExecSrLab(Signal* signal);
- void readExecLogLab(Signal* signal);
- void readSrFourthPhaseLab(Signal* signal);
- void readSrFourthZeroLab(Signal* signal);
- void copyLqhKeyRefLab(Signal* signal);
- void restartOperationsLab(Signal* signal);
- void lqhTransNextLab(Signal* signal);
- void restartOperationsAfterStopLab(Signal* signal);
- void startphase1Lab(Signal* signal, Uint32 config, Uint32 nodeId);
- void tupkeyConfLab(Signal* signal);
- void copyTupkeyConfLab(Signal* signal);
- void scanTupkeyConfLab(Signal* signal);
- void scanTupkeyRefLab(Signal* signal);
- void accScanConfScanLab(Signal* signal);
- void accScanConfCopyLab(Signal* signal);
- void scanLockReleasedLab(Signal* signal);
- void openSrFourthNextLab(Signal* signal);
- void closingInitLab(Signal* signal);
- void closeExecSrCompletedLab(Signal* signal);
- void readSrFrontpageLab(Signal* signal);
-
- void sendAddFragReq(Signal* signal);
- void sendAddAttrReq(Signal* signal);
- void checkDropTab(Signal*);
- Uint32 checkDropTabState(Tablerec::TableStatus, Uint32) const;
-
- // Initialisation
- void initData();
- void initRecords();
-
- void define_backup(Signal*);
- void execDEFINE_BACKUP_REF(Signal*);
- void execDEFINE_BACKUP_CONF(Signal*);
- void execBACKUP_FRAGMENT_REF(Signal* signal);
- void execBACKUP_FRAGMENT_CONF(Signal* signal);
- void execLCP_PREPARE_REF(Signal* signal);
- void execLCP_PREPARE_CONF(Signal* signal);
- void execEND_LCPREF(Signal* signal);
- void execEND_LCPCONF(Signal* signal);
- Uint32 m_backup_ptr;
-
- void send_restore_lcp(Signal * signal);
- void execRESTORE_LCP_REF(Signal* signal);
- void execRESTORE_LCP_CONF(Signal* signal);
-
- Dbtup* c_tup;
- Dbacc* c_acc;
-
- /**
- * Read primary key from tup
- */
- Uint32 readPrimaryKeys(ScanRecord*, TcConnectionrec*, Uint32 * dst);
-
- /**
- * Read primary key from operation
- */
-public:
- Uint32 readPrimaryKeys(Uint32 opPtrI, Uint32 * dst, bool xfrm);
-private:
-
- void acckeyconf_tupkeyreq(Signal*, TcConnectionrec*, Fragrecord*, Uint32, Uint32);
- void acckeyconf_load_diskpage(Signal*,TcConnectionrecPtr,Fragrecord*,Uint32);
-
- void handle_nr_copy(Signal*, Ptr<TcConnectionrec>);
- void exec_acckeyreq(Signal*, Ptr<TcConnectionrec>);
- int compare_key(const TcConnectionrec*, const Uint32 * ptr, Uint32 len);
- void nr_copy_delete_row(Signal*, Ptr<TcConnectionrec>, Local_key*, Uint32);
-public:
- struct Nr_op_info
- {
- Uint32 m_ptr_i;
- Uint32 m_tup_frag_ptr_i;
- Uint32 m_gci;
- Uint32 m_page_id;
- Local_key m_disk_ref;
- };
- void get_nr_op_info(Nr_op_info*, Uint32 page_id = RNIL);
- void nr_delete_complete(Signal*, Nr_op_info*);
-
-public:
- void acckeyconf_load_diskpage_callback(Signal*, Uint32, Uint32);
-
-private:
- void next_scanconf_load_diskpage(Signal* signal,
- ScanRecordPtr scanPtr,
- Ptr<TcConnectionrec> regTcPtr,
- Fragrecord* fragPtrP);
-
- void next_scanconf_tupkeyreq(Signal* signal, ScanRecordPtr,
- TcConnectionrec * regTcPtr,
- Fragrecord* fragPtrP,
- Uint32 disk_page);
-
-public:
- void next_scanconf_load_diskpage_callback(Signal* signal, Uint32, Uint32);
-
- void tupcommit_conf_callback(Signal* signal, Uint32 tcPtrI);
-private:
- void tupcommit_conf(Signal* signal, TcConnectionrec *,Fragrecord *);
-
-// ----------------------------------------------------------------
-// These are variables handling the records. For most records one
-// pointer to the array of structs, one pointer-struct, a file size
-// and a first free record variable. The pointer struct are temporary
-// variables that are kept on the class object since there are often a
-// great deal of those variables that exist simultaneously and
-// thus no perfect solution of handling them is currently available.
-// ----------------------------------------------------------------
-/* ------------------------------------------------------------------------- */
-/* POSITIONS WITHIN THE ATTRINBUF AND THE MAX SIZE OF DATA WITHIN AN */
-/* ATTRINBUF. */
-/* ------------------------------------------------------------------------- */
-
-
-#define ZADDFRAGREC_FILE_SIZE 1
- AddFragRecord *addFragRecord;
- AddFragRecordPtr addfragptr;
- UintR cfirstfreeAddfragrec;
- UintR caddfragrecFileSize;
-
-#define ZATTRINBUF_FILE_SIZE 12288 // 1.5 MByte
-#define ZINBUF_DATA_LEN 24 /* POSITION OF 'DATA LENGHT'-VARIABLE. */
-#define ZINBUF_NEXT 25 /* POSITION OF 'NEXT'-VARIABLE. */
- Attrbuf *attrbuf;
- AttrbufPtr attrinbufptr;
- UintR cfirstfreeAttrinbuf;
- UintR cattrinbufFileSize;
- Uint32 c_no_attrinbuf_recs;
-
-#define ZDATABUF_FILE_SIZE 10000 // 200 kByte
- Databuf *databuf;
- DatabufPtr databufptr;
- UintR cfirstfreeDatabuf;
- UintR cdatabufFileSize;
-
-// Configurable
- FragrecordPtr fragptr;
- ArrayPool<Fragrecord> c_fragment_pool;
-
-#define ZGCPREC_FILE_SIZE 1
- GcpRecord *gcpRecord;
- GcpRecordPtr gcpPtr;
- UintR cgcprecFileSize;
-
-// MAX_NDB_NODES is the size of this array
- HostRecord *hostRecord;
- UintR chostFileSize;
-
-#define ZNO_CONCURRENT_LCP 1
- LcpRecord *lcpRecord;
- LcpRecordPtr lcpPtr;
- UintR cfirstfreeLcpLoc;
- UintR clcpFileSize;
-
-#define ZLOG_PART_FILE_SIZE 4
- LogPartRecord *logPartRecord;
- LogPartRecordPtr logPartPtr;
- UintR clogPartFileSize;
- Uint32 clogFileSize; // In MBYTE
- Uint32 cmaxLogFilesInPageZero; //
-
-// Configurable
- LogFileRecord *logFileRecord;
- LogFileRecordPtr logFilePtr;
- UintR cfirstfreeLogFile;
- UintR clogFileFileSize;
-
-#define ZLFO_MIN_FILE_SIZE 256
-// RedoBuffer/32K minimum ZLFO_MIN_FILE_SIZE
- LogFileOperationRecord *logFileOperationRecord;
- LogFileOperationRecordPtr lfoPtr;
- UintR cfirstfreeLfo;
- UintR clfoFileSize;
-
- LogPageRecord *logPageRecord;
- void *logPageRecordUnaligned;
- LogPageRecordPtr logPagePtr;
- UintR cfirstfreeLogPage;
- UintR clogPageFileSize;
-
-#define ZPAGE_REF_FILE_SIZE 20
- PageRefRecord *pageRefRecord;
- PageRefRecordPtr pageRefPtr;
- UintR cfirstfreePageRef;
- UintR cpageRefFileSize;
-
-// Configurable
- ArrayPool<ScanRecord> c_scanRecordPool;
- ScanRecordPtr scanptr;
- UintR cscanNoFreeRec;
- Uint32 cscanrecFileSize;
-
-// Configurable
- Tablerec *tablerec;
- TablerecPtr tabptr;
- UintR ctabrecFileSize;
-
-// Configurable
- TcConnectionrec *tcConnectionrec;
- TcConnectionrecPtr tcConnectptr;
- UintR cfirstfreeTcConrec;
- UintR ctcConnectrecFileSize;
-
-// MAX_NDB_NODES is the size of this array
- TcNodeFailRecord *tcNodeFailRecord;
- TcNodeFailRecordPtr tcNodeFailptr;
- UintR ctcNodeFailrecFileSize;
-
- Uint16 terrorCode;
-
- Uint32 c_firstInNodeGroup;
-
-// ------------------------------------------------------------------------
-// These variables are used to store block state which do not need arrays
-// of struct's.
-// ------------------------------------------------------------------------
- Uint32 c_lcpId;
- Uint32 cnoOfFragsCheckpointed;
-
-/* ------------------------------------------------------------------------- */
-// cmaxWordsAtNodeRec keeps track of how many words that currently are
-// outstanding in a node recovery situation.
-// cbookedAccOps keeps track of how many operation records that have been
-// booked in ACC for the scan processes.
-// cmaxAccOps contains the maximum number of operation records which can be
-// allocated for scan purposes in ACC.
-/* ------------------------------------------------------------------------- */
- UintR cmaxWordsAtNodeRec;
- UintR cbookedAccOps;
- UintR cmaxAccOps;
-/* ------------------------------------------------------------------------- */
-/*THIS STATE VARIABLE IS ZTRUE IF AN ADD NODE IS ONGOING. ADD NODE MEANS */
-/*THAT CONNECTIONS ARE SET-UP TO THE NEW NODE. */
-/* ------------------------------------------------------------------------- */
- Uint8 caddNodeState;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE SPECIFIES WHICH TYPE OF RESTART THAT IS ONGOING */
-/* ------------------------------------------------------------------------- */
- Uint16 cstartType;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE INDICATES WHETHER AN INITIAL RESTART IS ONGOING OR NOT. */
-/* ------------------------------------------------------------------------- */
- Uint8 cinitialStartOngoing;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE KEEPS TRACK OF WHEN TUP AND ACC HAVE COMPLETED EXECUTING */
-/*THEIR UNDO LOG. */
-/* ------------------------------------------------------------------------- */
- ExecUndoLogState csrExecUndoLogState;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE KEEPS TRACK OF WHEN TUP AND ACC HAVE CONFIRMED COMPLETION */
-/*OF A LOCAL CHECKPOINT ROUND. */
-/* ------------------------------------------------------------------------- */
- LcpCloseState clcpCompletedState;
-/* ------------------------------------------------------------------------- */
-/*DURING CONNECTION PROCESSES IN SYSTEM RESTART THESE VARIABLES KEEP TRACK */
-/*OF HOW MANY CONNECTIONS AND RELEASES THAT ARE TO BE PERFORMED. */
-/* ------------------------------------------------------------------------- */
-/***************************************************************************>*/
-/*THESE VARIABLES CONTAIN INFORMATION USED DURING SYSTEM RESTART. */
-/***************************************************************************>*/
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE IS ZTRUE IF THE SIGNAL START_REC_REQ HAVE BEEN RECEIVED. */
-/*RECEPTION OF THIS SIGNAL INDICATES THAT ALL FRAGMENTS THAT THIS NODE */
-/*SHOULD START HAVE BEEN RECEIVED. */
-/* ------------------------------------------------------------------------- */
- Uint8 cstartRecReq;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE KEEPS TRACK OF HOW MANY FRAGMENTS THAT PARTICIPATE IN */
-/*EXECUTING THE LOG. IF ZERO WE DON'T NEED TO EXECUTE THE LOG AT ALL. */
-/* ------------------------------------------------------------------------- */
- Uint32 cnoFragmentsExecSr;
-
- /**
- * This is no of sent GSN_EXEC_FRAGREQ during this log phase
- */
- Uint32 cnoOutstandingExecFragReq;
-
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE KEEPS TRACK OF WHICH OF THE FIRST TWO RESTART PHASES THAT */
-/*HAVE COMPLETED. */
-/* ------------------------------------------------------------------------- */
- Uint8 csrPhaseStarted;
-/* ------------------------------------------------------------------------- */
-/*NUMBER OF PHASES COMPLETED OF EXECUTING THE FRAGMENT LOG. */
-/* ------------------------------------------------------------------------- */
- Uint8 csrPhasesCompleted;
-/* ------------------------------------------------------------------------- */
-/*THE BLOCK REFERENCE OF THE MASTER DIH DURING SYSTEM RESTART. */
-/* ------------------------------------------------------------------------- */
- BlockReference cmasterDihBlockref;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE IS THE HEAD OF A LINKED LIST OF FRAGMENTS WAITING TO BE */
-/*RESTORED FROM DISK. */
-/* ------------------------------------------------------------------------- */
- DLFifoList<Fragrecord> c_lcp_waiting_fragments; // StartFragReq'ed
- DLFifoList<Fragrecord> c_lcp_restoring_fragments; // Restoring as we speek
- DLFifoList<Fragrecord> c_lcp_complete_fragments; // Restored
-
-/* ------------------------------------------------------------------------- */
-/*USED DURING SYSTEM RESTART, INDICATES THE OLDEST GCI THAT CAN BE RESTARTED */
-/*FROM AFTER THIS SYSTEM RESTART. USED TO FIND THE LOG TAIL. */
-/* ------------------------------------------------------------------------- */
- UintR crestartOldestGci;
-/* ------------------------------------------------------------------------- */
-/*USED DURING SYSTEM RESTART, INDICATES THE NEWEST GCI THAT CAN BE RESTARTED */
-/*AFTER THIS SYSTEM RESTART. USED TO FIND THE LOG HEAD. */
-/* ------------------------------------------------------------------------- */
- UintR crestartNewestGci;
-/* ------------------------------------------------------------------------- */
-/*THE NUMBER OF LOG FILES. SET AS A PARAMETER WHEN NDB IS STARTED. */
-/* ------------------------------------------------------------------------- */
- UintR cnoLogFiles;
-/* ------------------------------------------------------------------------- */
-/*THESE TWO VARIABLES CONTAIN THE NEWEST GCI RECEIVED IN THE BLOCK AND THE */
-/*NEWEST COMPLETED GCI IN THE BLOCK. */
-/* ------------------------------------------------------------------------- */
- UintR cnewestGci;
- UintR cnewestCompletedGci;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE ONLY PASSES INFORMATION FROM STTOR TO STTORRY = TEMPORARY */
-/* ------------------------------------------------------------------------- */
- Uint16 csignalKey;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE CONTAINS THE CURRENT START PHASE IN THE BLOCK. IS ZNIL IF */
-/*NO SYSTEM RESTART IS ONGOING. */
-/* ------------------------------------------------------------------------- */
- Uint16 cstartPhase;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE CONTAIN THE CURRENT GLOBAL CHECKPOINT RECORD. IT'S RNIL IF */
-/*NOT A GCP SAVE IS ONGOING. */
-/* ------------------------------------------------------------------------- */
- UintR ccurrentGcprec;
-/* ------------------------------------------------------------------------- */
-/*THESE VARIABLES ARE USED TO KEEP TRACK OF ALL ACTIVE COPY FRAGMENTS IN LQH.*/
-/* ------------------------------------------------------------------------- */
- Uint8 cnoActiveCopy;
- UintR cactiveCopy[4];
-
-/* ------------------------------------------------------------------------- */
-/*THESE VARIABLES CONTAIN THE BLOCK REFERENCES OF THE OTHER NDB BLOCKS. */
-/*ALSO THE BLOCK REFERENCE OF MY OWN BLOCK = LQH */
-/* ------------------------------------------------------------------------- */
- BlockReference caccBlockref;
- BlockReference ctupBlockref;
- BlockReference ctuxBlockref;
- BlockReference cownref;
- UintR cLqhTimeOutCount;
- UintR cLqhTimeOutCheckCount;
- UintR cnoOfLogPages;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE CONTAINS MY OWN PROCESSOR ID. */
-/* ------------------------------------------------------------------------- */
- NodeId cownNodeid;
-
-/* ------------------------------------------------------------------------- */
-/*THESE VARIABLES CONTAIN INFORMATION ABOUT THE OTHER NODES IN THE SYSTEM */
-/*THESE VARIABLES ARE MOSTLY USED AT SYSTEM RESTART AND ADD NODE TO SET-UP */
-/*AND RELEASE CONNECTIONS TO OTHER NODES IN THE CLUSTER. */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/*THIS ARRAY CONTAINS THE PROCESSOR ID'S OF THE NODES THAT ARE ALIVE. */
-/*CNO_OF_NODES SPECIFIES HOW MANY NODES THAT ARE CURRENTLY ALIVE. */
-/*CNODE_VERSION SPECIFIES THE NDB VERSION EXECUTING ON THE NODE. */
-/* ------------------------------------------------------------------------- */
- UintR cpackedListIndex;
- Uint16 cpackedList[MAX_NDB_NODES];
- UintR cnodeData[MAX_NDB_NODES];
- UintR cnodeStatus[MAX_NDB_NODES];
- UintR cnoOfNodes;
-
- NdbNodeBitmask m_sr_nodes;
- NdbNodeBitmask m_sr_exec_sr_req;
- NdbNodeBitmask m_sr_exec_sr_conf;
-
-/* ------------------------------------------------------------------------- */
-/* THIS VARIABLE CONTAINS THE DIRECTORY OF A HASH TABLE OF ALL ACTIVE */
-/* OPERATION IN THE BLOCK. IT IS USED TO BE ABLE TO QUICKLY ABORT AN */
-/* OPERATION WHERE THE CONNECTION WAS LOST DUE TO NODE FAILURES. IT IS */
-/* ACTUALLY USED FOR ALL ABORTS COMMANDED BY TC. */
-/* ------------------------------------------------------------------------- */
- UintR preComputedRequestInfoMask;
- UintR ctransidHash[1024];
-
- Uint32 c_diskless;
- Uint32 c_o_direct;
- Uint32 c_error_insert_table_id;
-
-public:
- bool is_same_trans(Uint32 opId, Uint32 trid1, Uint32 trid2);
- void get_op_info(Uint32 opId, Uint32 *hash, Uint32* gci);
- void accminupdate(Signal*, Uint32 opPtrI, const Local_key*);
-
- /**
- *
- */
- struct CommitAckMarker {
- CommitAckMarker() {}
- Uint32 transid1;
- Uint32 transid2;
-
- Uint32 apiRef; // Api block ref
- Uint32 apiOprec; // Connection Object in NDB API
- Uint32 tcNodeId;
- union { Uint32 nextPool; Uint32 nextHash; };
- Uint32 prevHash;
-
- inline bool equal(const CommitAckMarker & p) const {
- return ((p.transid1 == transid1) && (p.transid2 == transid2));
- }
-
- inline Uint32 hashValue() const {
- return transid1;
- }
- };
-
- typedef Ptr<CommitAckMarker> CommitAckMarkerPtr;
- ArrayPool<CommitAckMarker> m_commitAckMarkerPool;
- DLHashTable<CommitAckMarker> m_commitAckMarkerHash;
- typedef DLHashTable<CommitAckMarker>::Iterator CommitAckMarkerIterator;
- void execREMOVE_MARKER_ORD(Signal* signal);
- void scanMarkers(Signal* signal, Uint32 tcNodeFail, Uint32 bucket, Uint32 i);
-
- struct Counters {
- Counters() {}
- Uint32 operations;
-
- inline void clear(){
- operations = 0;
- }
- };
-
- Counters c_Counters;
-
- inline bool getAllowRead() const {
- return getNodeState().startLevel < NodeState::SL_STOPPING_3;
- }
-
- DLHashTable<ScanRecord> c_scanTakeOverHash;
-
- inline bool TRACE_OP_CHECK(const TcConnectionrec* regTcPtr);
-#ifdef ERROR_INSERT
- void TRACE_OP_DUMP(const TcConnectionrec* regTcPtr, const char * pos);
-#endif
-};
-
-inline
-bool
-Dblqh::ScanRecord::check_scan_batch_completed() const
-{
- Uint32 max_rows = m_max_batch_size_rows;
- Uint32 max_bytes = m_max_batch_size_bytes;
-
- return (max_rows > 0 && (m_curr_batch_size_rows >= max_rows)) ||
- (max_bytes > 0 && (m_curr_batch_size_bytes >= max_bytes));
-}
-
-inline
-void
-Dblqh::i_get_acc_ptr(ScanRecord* scanP, Uint32* &acc_ptr, Uint32 index)
-{
- if (index == 0) {
- acc_ptr= (Uint32*)&scanP->scan_acc_op_ptr[0];
- } else {
- Uint32 attr_buf_index, attr_buf_rec;
-
- AttrbufPtr regAttrPtr;
- jam();
- attr_buf_rec= (index + 31) / 32;
- attr_buf_index= (index - 1) & 31;
- regAttrPtr.i= scanP->scan_acc_op_ptr[attr_buf_rec];
- ptrCheckGuard(regAttrPtr, cattrinbufFileSize, attrbuf);
- acc_ptr= (Uint32*)&regAttrPtr.p->attrbuf[attr_buf_index];
- }
-}
-
-inline
-bool
-Dblqh::is_same_trans(Uint32 opId, Uint32 trid1, Uint32 trid2)
-{
- TcConnectionrecPtr regTcPtr;
- regTcPtr.i= opId;
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
- return ((regTcPtr.p->transid[0] == trid1) &&
- (regTcPtr.p->transid[1] == trid2));
-}
-
-inline
-void
-Dblqh::get_op_info(Uint32 opId, Uint32 *hash, Uint32* gci)
-{
- TcConnectionrecPtr regTcPtr;
- regTcPtr.i= opId;
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
- *hash= regTcPtr.p->hashValue;
- *gci= regTcPtr.p->gci;
-}
-
-#include "../dbacc/Dbacc.hpp"
-
-inline
-void
-Dblqh::accminupdate(Signal* signal, Uint32 opId, const Local_key* key)
-{
- TcConnectionrecPtr regTcPtr;
- regTcPtr.i= opId;
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
- signal->theData[0] = regTcPtr.p->accConnectrec;
- signal->theData[1] = key->m_page_no << MAX_TUPLES_BITS | key->m_page_idx;
- c_acc->execACCMINUPDATE(signal);
-
- if (ERROR_INSERTED(5712) || ERROR_INSERTED(5713))
- ndbout << " LK: " << *key;
- regTcPtr.p->m_row_id = *key;
-}
-
-inline
-bool
-Dblqh::TRACE_OP_CHECK(const TcConnectionrec* regTcPtr)
-{
- return (ERROR_INSERTED(5712) &&
- (regTcPtr->operation == ZINSERT ||
- regTcPtr->operation == ZDELETE)) ||
- ERROR_INSERTED(5713);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
deleted file mode 100644
index 79b3c6ce8d8..00000000000
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <pc.hpp>
-#define DBLQH_C
-#include "Dblqh.hpp"
-#include <ndb_limits.h>
-
-#define DEBUG(x) { ndbout << "LQH::" << x << endl; }
-
-void Dblqh::initData()
-{
- caddfragrecFileSize = ZADDFRAGREC_FILE_SIZE;
- cattrinbufFileSize = ZATTRINBUF_FILE_SIZE;
- c_no_attrinbuf_recs= ZATTRINBUF_FILE_SIZE;
- cdatabufFileSize = ZDATABUF_FILE_SIZE;
- cgcprecFileSize = ZGCPREC_FILE_SIZE;
- chostFileSize = MAX_NDB_NODES;
- clcpFileSize = ZNO_CONCURRENT_LCP;
- clfoFileSize = 0;
- clogFileFileSize = 0;
- clogPartFileSize = ZLOG_PART_FILE_SIZE;
- cpageRefFileSize = ZPAGE_REF_FILE_SIZE;
- cscanrecFileSize = 0;
- ctabrecFileSize = 0;
- ctcConnectrecFileSize = 0;
- ctcNodeFailrecFileSize = MAX_NDB_NODES;
-
- addFragRecord = 0;
- attrbuf = 0;
- databuf = 0;
- gcpRecord = 0;
- hostRecord = 0;
- lcpRecord = 0;
- logPartRecord = 0;
- logFileRecord = 0;
- logFileOperationRecord = 0;
- logPageRecord = 0;
- logPageRecordUnaligned= 0;
- pageRefRecord = 0;
- tablerec = 0;
- tcConnectionrec = 0;
- tcNodeFailRecord = 0;
-
- // Records with constant sizes
-
- cLqhTimeOutCount = 0;
- cLqhTimeOutCheckCount = 0;
- cbookedAccOps = 0;
- m_backup_ptr = RNIL;
- clogFileSize = 16;
- cmaxLogFilesInPageZero = 40;
-}//Dblqh::initData()
-
-void Dblqh::initRecords()
-{
- // Records with dynamic sizes
- addFragRecord = (AddFragRecord*)allocRecord("AddFragRecord",
- sizeof(AddFragRecord),
- caddfragrecFileSize);
- attrbuf = (Attrbuf*)allocRecord("Attrbuf",
- sizeof(Attrbuf),
- cattrinbufFileSize);
-
- databuf = (Databuf*)allocRecord("Databuf",
- sizeof(Databuf),
- cdatabufFileSize);
-
- gcpRecord = (GcpRecord*)allocRecord("GcpRecord",
- sizeof(GcpRecord),
- cgcprecFileSize);
-
- hostRecord = (HostRecord*)allocRecord("HostRecord",
- sizeof(HostRecord),
- chostFileSize);
-
- lcpRecord = (LcpRecord*)allocRecord("LcpRecord",
- sizeof(LcpRecord),
- clcpFileSize);
-
- for(Uint32 i = 0; i<clcpFileSize; i++){
- new (&lcpRecord[i])LcpRecord();
- }
-
- logPartRecord = (LogPartRecord*)allocRecord("LogPartRecord",
- sizeof(LogPartRecord),
- clogPartFileSize);
-
- logFileRecord = (LogFileRecord*)allocRecord("LogFileRecord",
- sizeof(LogFileRecord),
- clogFileFileSize);
-
- logFileOperationRecord = (LogFileOperationRecord*)
- allocRecord("LogFileOperationRecord",
- sizeof(LogFileOperationRecord),
- clfoFileSize);
-
- logPageRecord =
- (LogPageRecord*)allocRecordAligned("LogPageRecord",
- sizeof(LogPageRecord),
- clogPageFileSize,
- &logPageRecordUnaligned,
- NDB_O_DIRECT_WRITE_ALIGNMENT,
- false);
-
- pageRefRecord = (PageRefRecord*)allocRecord("PageRefRecord",
- sizeof(PageRefRecord),
- cpageRefFileSize);
-
- cscanNoFreeRec = cscanrecFileSize;
- c_scanRecordPool.setSize(cscanrecFileSize);
- c_scanTakeOverHash.setSize(64);
-
- tablerec = (Tablerec*)allocRecord("Tablerec",
- sizeof(Tablerec),
- ctabrecFileSize);
-
- tcConnectionrec = (TcConnectionrec*)allocRecord("TcConnectionrec",
- sizeof(TcConnectionrec),
- ctcConnectrecFileSize);
-
- m_commitAckMarkerPool.setSize(ctcConnectrecFileSize);
- m_commitAckMarkerHash.setSize(1024);
-
- tcNodeFailRecord = (TcNodeFailRecord*)allocRecord("TcNodeFailRecord",
- sizeof(TcNodeFailRecord),
- ctcNodeFailrecFileSize);
-
- /*
- ndbout << "FRAGREC SIZE = " << sizeof(Fragrecord) << endl;
- ndbout << "TAB SIZE = " << sizeof(Tablerec) << endl;
- ndbout << "GCP SIZE = " << sizeof(GcpRecord) << endl;
- ndbout << "LCP SIZE = " << sizeof(LcpRecord) << endl;
- ndbout << "LCPLOC SIZE = " << sizeof(LcpLocRecord) << endl;
- ndbout << "LOGPART SIZE = " << sizeof(LogPartRecord) << endl;
- ndbout << "LOGFILE SIZE = " << sizeof(LogFileRecord) << endl;
- ndbout << "TC SIZE = " << sizeof(TcConnectionrec) << endl;
- ndbout << "HOST SIZE = " << sizeof(HostRecord) << endl;
- ndbout << "LFO SIZE = " << sizeof(LogFileOperationRecord) << endl;
- ndbout << "PR SIZE = " << sizeof(PageRefRecord) << endl;
- ndbout << "SCAN SIZE = " << sizeof(ScanRecord) << endl;
-*/
-
- // Initialize BAT for interface to file system
- NewVARIABLE* bat = allocateBat(2);
- bat[1].WA = &logPageRecord->logPageWord[0];
- bat[1].nrr = clogPageFileSize;
- bat[1].ClusterSize = sizeof(LogPageRecord);
- bat[1].bits.q = ZTWOLOG_PAGE_SIZE;
- bat[1].bits.v = 5;
-}//Dblqh::initRecords()
-
-Dblqh::Dblqh(Block_context& ctx):
- SimulatedBlock(DBLQH, ctx),
- c_lcp_waiting_fragments(c_fragment_pool),
- c_lcp_restoring_fragments(c_fragment_pool),
- c_lcp_complete_fragments(c_fragment_pool),
- m_commitAckMarkerHash(m_commitAckMarkerPool),
- c_scanTakeOverHash(c_scanRecordPool)
-{
- BLOCK_CONSTRUCTOR(Dblqh);
-
- addRecSignal(GSN_PACKED_SIGNAL, &Dblqh::execPACKED_SIGNAL);
- addRecSignal(GSN_DEBUG_SIG, &Dblqh::execDEBUG_SIG);
- addRecSignal(GSN_ATTRINFO, &Dblqh::execATTRINFO);
- addRecSignal(GSN_KEYINFO, &Dblqh::execKEYINFO);
- addRecSignal(GSN_LQHKEYREQ, &Dblqh::execLQHKEYREQ);
- addRecSignal(GSN_LQHKEYREF, &Dblqh::execLQHKEYREF);
- addRecSignal(GSN_COMMIT, &Dblqh::execCOMMIT);
- addRecSignal(GSN_COMPLETE, &Dblqh::execCOMPLETE);
- addRecSignal(GSN_LQHKEYCONF, &Dblqh::execLQHKEYCONF);
-#ifdef VM_TRACE
- addRecSignal(GSN_TESTSIG, &Dblqh::execTESTSIG);
-#endif
- addRecSignal(GSN_CONTINUEB, &Dblqh::execCONTINUEB);
- addRecSignal(GSN_START_RECREQ, &Dblqh::execSTART_RECREQ);
- addRecSignal(GSN_START_RECCONF, &Dblqh::execSTART_RECCONF);
- addRecSignal(GSN_EXEC_FRAGREQ, &Dblqh::execEXEC_FRAGREQ);
- addRecSignal(GSN_EXEC_FRAGCONF, &Dblqh::execEXEC_FRAGCONF);
- addRecSignal(GSN_EXEC_FRAGREF, &Dblqh::execEXEC_FRAGREF);
- addRecSignal(GSN_START_EXEC_SR, &Dblqh::execSTART_EXEC_SR);
- addRecSignal(GSN_EXEC_SRREQ, &Dblqh::execEXEC_SRREQ);
- addRecSignal(GSN_EXEC_SRCONF, &Dblqh::execEXEC_SRCONF);
- addRecSignal(GSN_SCAN_HBREP, &Dblqh::execSCAN_HBREP);
-
- addRecSignal(GSN_ALTER_TAB_REQ, &Dblqh::execALTER_TAB_REQ);
-
- // Trigger signals, transit to from TUP
- addRecSignal(GSN_CREATE_TRIG_REQ, &Dblqh::execCREATE_TRIG_REQ);
- addRecSignal(GSN_CREATE_TRIG_CONF, &Dblqh::execCREATE_TRIG_CONF);
- addRecSignal(GSN_CREATE_TRIG_REF, &Dblqh::execCREATE_TRIG_REF);
-
- addRecSignal(GSN_DROP_TRIG_REQ, &Dblqh::execDROP_TRIG_REQ);
- addRecSignal(GSN_DROP_TRIG_CONF, &Dblqh::execDROP_TRIG_CONF);
- addRecSignal(GSN_DROP_TRIG_REF, &Dblqh::execDROP_TRIG_REF);
-
- addRecSignal(GSN_DUMP_STATE_ORD, &Dblqh::execDUMP_STATE_ORD);
- addRecSignal(GSN_NODE_FAILREP, &Dblqh::execNODE_FAILREP);
- addRecSignal(GSN_CHECK_LCP_STOP, &Dblqh::execCHECK_LCP_STOP);
- addRecSignal(GSN_SEND_PACKED, &Dblqh::execSEND_PACKED);
- addRecSignal(GSN_TUP_ATTRINFO, &Dblqh::execTUP_ATTRINFO);
- addRecSignal(GSN_READ_CONFIG_REQ, &Dblqh::execREAD_CONFIG_REQ, true);
- addRecSignal(GSN_LQHFRAGREQ, &Dblqh::execLQHFRAGREQ);
- addRecSignal(GSN_LQHADDATTREQ, &Dblqh::execLQHADDATTREQ);
- addRecSignal(GSN_TUP_ADD_ATTCONF, &Dblqh::execTUP_ADD_ATTCONF);
- addRecSignal(GSN_TUP_ADD_ATTRREF, &Dblqh::execTUP_ADD_ATTRREF);
- addRecSignal(GSN_ACCFRAGCONF, &Dblqh::execACCFRAGCONF);
- addRecSignal(GSN_ACCFRAGREF, &Dblqh::execACCFRAGREF);
- addRecSignal(GSN_TUPFRAGCONF, &Dblqh::execTUPFRAGCONF);
- addRecSignal(GSN_TUPFRAGREF, &Dblqh::execTUPFRAGREF);
- addRecSignal(GSN_TAB_COMMITREQ, &Dblqh::execTAB_COMMITREQ);
- addRecSignal(GSN_ACCSEIZECONF, &Dblqh::execACCSEIZECONF);
- addRecSignal(GSN_ACCSEIZEREF, &Dblqh::execACCSEIZEREF);
- addRecSignal(GSN_READ_NODESCONF, &Dblqh::execREAD_NODESCONF);
- addRecSignal(GSN_READ_NODESREF, &Dblqh::execREAD_NODESREF);
- addRecSignal(GSN_STTOR, &Dblqh::execSTTOR);
- addRecSignal(GSN_NDB_STTOR, &Dblqh::execNDB_STTOR);
- addRecSignal(GSN_TUPSEIZECONF, &Dblqh::execTUPSEIZECONF);
- addRecSignal(GSN_TUPSEIZEREF, &Dblqh::execTUPSEIZEREF);
- addRecSignal(GSN_ACCKEYCONF, &Dblqh::execACCKEYCONF);
- addRecSignal(GSN_ACCKEYREF, &Dblqh::execACCKEYREF);
- addRecSignal(GSN_TUPKEYCONF, &Dblqh::execTUPKEYCONF);
- addRecSignal(GSN_TUPKEYREF, &Dblqh::execTUPKEYREF);
- addRecSignal(GSN_ABORT, &Dblqh::execABORT);
- addRecSignal(GSN_ABORTREQ, &Dblqh::execABORTREQ);
- addRecSignal(GSN_COMMITREQ, &Dblqh::execCOMMITREQ);
- addRecSignal(GSN_COMPLETEREQ, &Dblqh::execCOMPLETEREQ);
-#ifdef VM_TRACE
- addRecSignal(GSN_MEMCHECKREQ, &Dblqh::execMEMCHECKREQ);
-#endif
- addRecSignal(GSN_SCAN_FRAGREQ, &Dblqh::execSCAN_FRAGREQ);
- addRecSignal(GSN_SCAN_NEXTREQ, &Dblqh::execSCAN_NEXTREQ);
- addRecSignal(GSN_ACC_SCANCONF, &Dblqh::execACC_SCANCONF);
- addRecSignal(GSN_ACC_SCANREF, &Dblqh::execACC_SCANREF);
- addRecSignal(GSN_NEXT_SCANCONF, &Dblqh::execNEXT_SCANCONF);
- addRecSignal(GSN_NEXT_SCANREF, &Dblqh::execNEXT_SCANREF);
- addRecSignal(GSN_STORED_PROCCONF, &Dblqh::execSTORED_PROCCONF);
- addRecSignal(GSN_STORED_PROCREF, &Dblqh::execSTORED_PROCREF);
- addRecSignal(GSN_COPY_FRAGREQ, &Dblqh::execCOPY_FRAGREQ);
- addRecSignal(GSN_COPY_ACTIVEREQ, &Dblqh::execCOPY_ACTIVEREQ);
- addRecSignal(GSN_COPY_STATEREQ, &Dblqh::execCOPY_STATEREQ);
- addRecSignal(GSN_LQH_TRANSREQ, &Dblqh::execLQH_TRANSREQ);
- addRecSignal(GSN_TRANSID_AI, &Dblqh::execTRANSID_AI);
- addRecSignal(GSN_INCL_NODEREQ, &Dblqh::execINCL_NODEREQ);
- addRecSignal(GSN_LCP_PREPARE_REF, &Dblqh::execLCP_PREPARE_REF);
- addRecSignal(GSN_LCP_PREPARE_CONF, &Dblqh::execLCP_PREPARE_CONF);
- addRecSignal(GSN_END_LCPCONF, &Dblqh::execEND_LCPCONF);
-
- addRecSignal(GSN_EMPTY_LCP_REQ, &Dblqh::execEMPTY_LCP_REQ);
- addRecSignal(GSN_LCP_FRAG_ORD, &Dblqh::execLCP_FRAG_ORD);
-
- addRecSignal(GSN_START_FRAGREQ, &Dblqh::execSTART_FRAGREQ);
- addRecSignal(GSN_START_RECREF, &Dblqh::execSTART_RECREF);
- addRecSignal(GSN_GCP_SAVEREQ, &Dblqh::execGCP_SAVEREQ);
- addRecSignal(GSN_FSOPENREF, &Dblqh::execFSOPENREF, true);
- addRecSignal(GSN_FSOPENCONF, &Dblqh::execFSOPENCONF);
- addRecSignal(GSN_FSCLOSECONF, &Dblqh::execFSCLOSECONF);
- addRecSignal(GSN_FSWRITECONF, &Dblqh::execFSWRITECONF);
- addRecSignal(GSN_FSWRITEREF, &Dblqh::execFSWRITEREF, true);
- addRecSignal(GSN_FSREADCONF, &Dblqh::execFSREADCONF);
- addRecSignal(GSN_FSREADREF, &Dblqh::execFSREADREF, true);
- addRecSignal(GSN_ACC_ABORTCONF, &Dblqh::execACC_ABORTCONF);
- addRecSignal(GSN_TIME_SIGNAL, &Dblqh::execTIME_SIGNAL);
- addRecSignal(GSN_FSSYNCCONF, &Dblqh::execFSSYNCCONF);
- addRecSignal(GSN_REMOVE_MARKER_ORD, &Dblqh::execREMOVE_MARKER_ORD);
-
- //addRecSignal(GSN_DROP_TAB_REQ, &Dblqh::execDROP_TAB_REQ);
- addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dblqh::execPREP_DROP_TAB_REQ);
- addRecSignal(GSN_WAIT_DROP_TAB_REQ, &Dblqh::execWAIT_DROP_TAB_REQ);
- addRecSignal(GSN_DROP_TAB_REQ, &Dblqh::execDROP_TAB_REQ);
-
- addRecSignal(GSN_LQH_ALLOCREQ, &Dblqh::execLQH_ALLOCREQ);
- addRecSignal(GSN_LQH_WRITELOG_REQ, &Dblqh::execLQH_WRITELOG_REQ);
- addRecSignal(GSN_TUP_DEALLOCREQ, &Dblqh::execTUP_DEALLOCREQ);
-
- // TUX
- addRecSignal(GSN_TUXFRAGCONF, &Dblqh::execTUXFRAGCONF);
- addRecSignal(GSN_TUXFRAGREF, &Dblqh::execTUXFRAGREF);
- addRecSignal(GSN_TUX_ADD_ATTRCONF, &Dblqh::execTUX_ADD_ATTRCONF);
- addRecSignal(GSN_TUX_ADD_ATTRREF, &Dblqh::execTUX_ADD_ATTRREF);
-
- addRecSignal(GSN_READ_PSEUDO_REQ, &Dblqh::execREAD_PSEUDO_REQ);
-
- addRecSignal(GSN_DEFINE_BACKUP_REF, &Dblqh::execDEFINE_BACKUP_REF);
- addRecSignal(GSN_DEFINE_BACKUP_CONF, &Dblqh::execDEFINE_BACKUP_CONF);
-
- addRecSignal(GSN_BACKUP_FRAGMENT_REF, &Dblqh::execBACKUP_FRAGMENT_REF);
- addRecSignal(GSN_BACKUP_FRAGMENT_CONF, &Dblqh::execBACKUP_FRAGMENT_CONF);
-
- addRecSignal(GSN_RESTORE_LCP_REF, &Dblqh::execRESTORE_LCP_REF);
- addRecSignal(GSN_RESTORE_LCP_CONF, &Dblqh::execRESTORE_LCP_CONF);
-
- addRecSignal(GSN_UPDATE_FRAG_DIST_KEY_ORD,
- &Dblqh::execUPDATE_FRAG_DIST_KEY_ORD);
-
- addRecSignal(GSN_PREPARE_COPY_FRAG_REQ,
- &Dblqh::execPREPARE_COPY_FRAG_REQ);
-
- initData();
-
-#ifdef VM_TRACE
- {
- void* tmp[] = {
- &addfragptr,
- &attrinbufptr,
- &databufptr,
- &fragptr,
- &gcpPtr,
- &lcpPtr,
- &logPartPtr,
- &logFilePtr,
- &lfoPtr,
- &logPagePtr,
- &pageRefPtr,
- &scanptr,
- &tabptr,
- &tcConnectptr,
- &tcNodeFailptr,
- };
- init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
- }
-#endif
-
-}//Dblqh::Dblqh()
-
-Dblqh::~Dblqh()
-{
- // Records with dynamic sizes
- deallocRecord((void **)&addFragRecord, "AddFragRecord",
- sizeof(AddFragRecord),
- caddfragrecFileSize);
-
- deallocRecord((void**)&attrbuf,
- "Attrbuf",
- sizeof(Attrbuf),
- cattrinbufFileSize);
-
- deallocRecord((void**)&databuf,
- "Databuf",
- sizeof(Databuf),
- cdatabufFileSize);
-
- deallocRecord((void**)&gcpRecord,
- "GcpRecord",
- sizeof(GcpRecord),
- cgcprecFileSize);
-
- deallocRecord((void**)&hostRecord,
- "HostRecord",
- sizeof(HostRecord),
- chostFileSize);
-
- deallocRecord((void**)&lcpRecord,
- "LcpRecord",
- sizeof(LcpRecord),
- clcpFileSize);
-
- deallocRecord((void**)&logPartRecord,
- "LogPartRecord",
- sizeof(LogPartRecord),
- clogPartFileSize);
-
- deallocRecord((void**)&logFileRecord,
- "LogFileRecord",
- sizeof(LogFileRecord),
- clogFileFileSize);
-
- deallocRecord((void**)&logFileOperationRecord,
- "LogFileOperationRecord",
- sizeof(LogFileOperationRecord),
- clfoFileSize);
-
- deallocRecord((void**)&logPageRecordUnaligned,
- "LogPageRecord",
- sizeof(LogPageRecord),
- clogPageFileSize);
-
- deallocRecord((void**)&pageRefRecord,
- "PageRefRecord",
- sizeof(PageRefRecord),
- cpageRefFileSize);
-
-
- deallocRecord((void**)&tablerec,
- "Tablerec",
- sizeof(Tablerec),
- ctabrecFileSize);
-
- deallocRecord((void**)&tcConnectionrec,
- "TcConnectionrec",
- sizeof(TcConnectionrec),
- ctcConnectrecFileSize);
-
- deallocRecord((void**)&tcNodeFailRecord,
- "TcNodeFailRecord",
- sizeof(TcNodeFailRecord),
- ctcNodeFailrecFileSize);
-}//Dblqh::~Dblqh()
-
-BLOCK_FUNCTIONS(Dblqh)
-
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
deleted file mode 100644
index e76ad2530aa..00000000000
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ /dev/null
@@ -1,19357 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBLQH_C
-#include "Dblqh.hpp"
-#include <ndb_limits.h>
-#include <md5_hash.hpp>
-
-#include <ndb_version.h>
-#include <signaldata/TuxBound.hpp>
-#include <signaldata/AccScan.hpp>
-#include <signaldata/CopyActive.hpp>
-#include <signaldata/CopyFrag.hpp>
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/DropTrig.hpp>
-#include <signaldata/EmptyLcp.hpp>
-#include <signaldata/EventReport.hpp>
-#include <signaldata/ExecFragReq.hpp>
-#include <signaldata/GCPSave.hpp>
-#include <signaldata/TcKeyRef.hpp>
-#include <signaldata/LqhKey.hpp>
-#include <signaldata/NextScan.hpp>
-#include <signaldata/NFCompleteRep.hpp>
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/RelTabMem.hpp>
-#include <signaldata/ScanFrag.hpp>
-#include <signaldata/SrFragidConf.hpp>
-#include <signaldata/StartFragReq.hpp>
-#include <signaldata/StartRec.hpp>
-#include <signaldata/TupKey.hpp>
-#include <signaldata/TupCommit.hpp>
-#include <signaldata/LqhFrag.hpp>
-#include <signaldata/AccFrag.hpp>
-#include <signaldata/TupFrag.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/PackedSignal.hpp>
-
-#include <signaldata/PrepDropTab.hpp>
-#include <signaldata/DropTab.hpp>
-
-#include <signaldata/AlterTab.hpp>
-#include <signaldata/DictTabInfo.hpp>
-
-#include <signaldata/LCP.hpp>
-#include <DebuggerNames.hpp>
-#include <signaldata/BackupImpl.hpp>
-#include <signaldata/RestoreImpl.hpp>
-#include <signaldata/KeyInfo.hpp>
-#include <signaldata/AttrInfo.hpp>
-#include <KeyDescriptor.hpp>
-#include <signaldata/RouteOrd.hpp>
-#include <signaldata/FsRef.hpp>
-
-// Use DEBUG to print messages that should be
-// seen only when we debug the product
-#ifdef VM_TRACE
-#define DEBUG(x) ndbout << "DBLQH: "<< x << endl;
-static
-NdbOut &
-operator<<(NdbOut& out, Dblqh::TcConnectionrec::TransactionState state){
- out << (int)state;
- return out;
-}
-
-static
-NdbOut &
-operator<<(NdbOut& out, Dblqh::TcConnectionrec::LogWriteState state){
- out << (int)state;
- return out;
-}
-
-static
-NdbOut &
-operator<<(NdbOut& out, Dblqh::TcConnectionrec::ListState state){
- out << (int)state;
- return out;
-}
-
-static
-NdbOut &
-operator<<(NdbOut& out, Dblqh::TcConnectionrec::AbortState state){
- out << (int)state;
- return out;
-}
-
-static
-NdbOut &
-operator<<(NdbOut& out, Dblqh::ScanRecord::ScanState state){
- out << (int)state;
- return out;
-}
-
-static
-NdbOut &
-operator<<(NdbOut& out, Dblqh::LogFileOperationRecord::LfoState state){
- out << (int)state;
- return out;
-}
-
-static
-NdbOut &
-operator<<(NdbOut& out, Dblqh::ScanRecord::ScanType state){
- out << (int)state;
- return out;
-}
-
-static
-NdbOut &
-operator<<(NdbOut& out, Operation_t op)
-{
- switch(op){
- case ZREAD: out << "READ"; break;
- case ZREAD_EX: out << "READ-EX"; break;
- case ZINSERT: out << "INSERT"; break;
- case ZUPDATE: out << "UPDATE"; break;
- case ZDELETE: out << "DELETE"; break;
- case ZWRITE: out << "WRITE"; break;
- }
- return out;
-}
-
-#else
-#define DEBUG(x)
-#endif
-
-//#define MARKER_TRACE 1
-//#define TRACE_SCAN_TAKEOVER 1
-
-#ifndef DEBUG_REDO
-#define DEBUG_REDO 0
-#endif
-
-const Uint32 NR_ScanNo = 0;
-
-#if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR
-#include <NdbConfig.h>
-static NdbOut * tracenrout = 0;
-static int TRACENR_FLAG = 0;
-#define TRACENR(x) (* tracenrout) << x
-#define SET_TRACENR_FLAG TRACENR_FLAG = 1
-#define CLEAR_TRACENR_FLAG TRACENR_FLAG = 0
-#else
-#define TRACENR_FLAG 0
-#define TRACENR(x)
-#define SET_TRACENR_FLAG
-#define CLEAR_TRACENR_FLAG
-#endif
-
-#ifdef ERROR_INSERT
-static NdbOut * traceopout = 0;
-#define TRACE_OP(regTcPtr, place) do { if (TRACE_OP_CHECK(regTcPtr)) TRACE_OP_DUMP(regTcPtr, place); } while(0)
-#else
-#define TRACE_OP(x, y) {}
-#endif
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEND SYSTEM ERROR ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::systemError(Signal* signal, int line)
-{
- signal->theData[0] = 2304;
- execDUMP_STATE_ORD(signal);
- progError(line, NDBD_EXIT_NDBREQUIRE);
-}//Dblqh::systemError()
-
-/* *************** */
-/* ACCSEIZEREF > */
-/* *************** */
-void Dblqh::execACCSEIZEREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execACCSEIZEREF()
-
-/* ******************************************************>> */
-/* THIS SIGNAL IS USED TO HANDLE REAL-TIME */
-/* BREAKS THAT ARE NECESSARY TO ENSURE REAL-TIME */
-/* OPERATION OF LQH. */
-/* This signal is also used for signal loops, for example */
-/* the timeout handling for writing logs every second. */
-/* ******************************************************>> */
-void Dblqh::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- Uint32 tcase = signal->theData[0];
- Uint32 data0 = signal->theData[1];
- Uint32 data1 = signal->theData[2];
- Uint32 data2 = signal->theData[3];
-#if 0
- if (tcase == RNIL) {
- tcConnectptr.i = data0;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- ndbout << "State = " << tcConnectptr.p->transactionState;
- ndbout << " seqNoReplica = " << tcConnectptr.p->seqNoReplica;
- ndbout << " tcNodeFailrec = " << tcConnectptr.p->tcNodeFailrec;
- ndbout << " activeCreat = " << tcConnectptr.p->activeCreat;
- ndbout << endl;
- ndbout << "tupkeyData0 = " << tcConnectptr.p->tupkeyData[0];
- ndbout << "tupkeyData1 = " << tcConnectptr.p->tupkeyData[1];
- ndbout << "tupkeyData2 = " << tcConnectptr.p->tupkeyData[2];
- ndbout << "tupkeyData3 = " << tcConnectptr.p->tupkeyData[3];
- ndbout << endl;
- ndbout << "abortState = " << tcConnectptr.p->abortState;
- ndbout << "listState = " << tcConnectptr.p->listState;
- ndbout << endl;
- return;
- }//if
-#endif
- switch (tcase) {
- case ZLOG_LQHKEYREQ:
- if (cnoOfLogPages == 0) {
- jam();
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
- return;
- }//if
- logPartPtr.i = data0;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
-
- tcConnectptr.i = logPartPtr.p->firstLogQueue;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- logPartPtr.p->LogLqhKeyReqSent = ZFALSE;
- getFirstInLogQueue(signal);
-
- switch (tcConnectptr.p->transactionState) {
- case TcConnectionrec::LOG_QUEUED:
- if (tcConnectptr.p->abortState != TcConnectionrec::ABORT_IDLE) {
- jam();
- logNextStart(signal);
- abortCommonLab(signal);
- return;
- } else {
- jam();
-/*------------------------------------------------------------*/
-/* WE MUST SET THE STATE OF THE LOG PART TO IDLE TO */
-/* ENSURE THAT WE ARE NOT QUEUED AGAIN ON THE LOG PART */
-/* WE WILL SET THE LOG PART STATE TO ACTIVE IMMEDIATELY */
-/* SO NO OTHER PROCESS WILL SEE THIS STATE. IT IS MERELY*/
-/* USED TO ENABLE REUSE OF CODE. */
-/*------------------------------------------------------------*/
- if (logPartPtr.p->logPartState == LogPartRecord::ACTIVE) {
- jam();
- logPartPtr.p->logPartState = LogPartRecord::IDLE;
- }//if
- logLqhkeyreqLab(signal);
- return;
- }//if
- break;
- case TcConnectionrec::LOG_ABORT_QUEUED:
- jam();
- writeAbortLog(signal);
- removeLogTcrec(signal);
- logNextStart(signal);
- continueAfterLogAbortWriteLab(signal);
- return;
- break;
- case TcConnectionrec::LOG_COMMIT_QUEUED:
- case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
- jam();
- writeCommitLog(signal, logPartPtr);
- logNextStart(signal);
- if (tcConnectptr.p->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
- if (tcConnectptr.p->seqNoReplica == 0 ||
- tcConnectptr.p->activeCreat == Fragrecord::AC_NR_COPY) {
- jam();
- localCommitLab(signal);
- } else {
- jam();
- commitReplyLab(signal);
- }//if
- return;
- } else {
- jam();
- tcConnectptr.p->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
- return;
- }//if
- break;
- case TcConnectionrec::COMMIT_QUEUED:
- jam();
- logNextStart(signal);
- localCommitLab(signal);
- break;
- case TcConnectionrec::ABORT_QUEUED:
- jam();
- logNextStart(signal);
- abortCommonLab(signal);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
- break;
- case ZSR_GCI_LIMITS:
- jam();
- signal->theData[0] = data0;
- srGciLimits(signal);
- return;
- break;
- case ZSR_LOG_LIMITS:
- jam();
- signal->theData[0] = data0;
- signal->theData[1] = data1;
- signal->theData[2] = data2;
- srLogLimits(signal);
- return;
- break;
- case ZSEND_EXEC_CONF:
- jam();
- signal->theData[0] = data0;
- sendExecConf(signal);
- return;
- break;
- case ZEXEC_SR:
- jam();
- signal->theData[0] = data0;
- execSr(signal);
- return;
- break;
- case ZSR_FOURTH_COMP:
- jam();
- signal->theData[0] = data0;
- srFourthComp(signal);
- return;
- break;
- case ZINIT_FOURTH:
- jam();
- signal->theData[0] = data0;
- initFourth(signal);
- return;
- break;
- case ZTIME_SUPERVISION:
- jam();
- signal->theData[0] = data0;
- timeSup(signal);
- return;
- break;
- case ZSR_PHASE3_START:
- jam();
- srPhase3Start(signal);
- return;
- break;
- case ZLQH_TRANS_NEXT:
- jam();
- tcNodeFailptr.i = data0;
- ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
- lqhTransNextLab(signal);
- return;
- break;
- case ZSCAN_TC_CONNECT:
- jam();
- tabptr.i = data1;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- scanTcConnectLab(signal, data0, data2);
- return;
- break;
- case ZINITIALISE_RECORDS:
- jam();
- initialiseRecordsLab(signal, data0, data2, signal->theData[4]);
- return;
- break;
- case ZINIT_GCP_REC:
- jam();
- gcpPtr.i = 0;
- ptrAss(gcpPtr, gcpRecord);
- initGcpRecLab(signal);
- return;
- break;
- case ZCHECK_LCP_STOP_BLOCKED:
- jam();
- c_scanRecordPool.getPtr(scanptr, data0);
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- checkLcpStopBlockedLab(signal);
- return;
- case ZSCAN_MARKERS:
- jam();
- scanMarkers(signal, data0, data1, data2);
- return;
- break;
-
- case ZOPERATION_EVENT_REP:
- jam();
- /* --------------------------------------------------------------------- */
- // Report information about transaction activity once per second.
- /* --------------------------------------------------------------------- */
- if (signal->theData[1] == 0) {
- signal->theData[0] = NDB_LE_OperationReportCounters;
- signal->theData[1] = c_Counters.operations;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- }//if
- c_Counters.clear();
- signal->theData[0] = ZOPERATION_EVENT_REP;
- signal->theData[1] = 0;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 2);
- break;
- case ZPREP_DROP_TABLE:
- jam();
- checkDropTab(signal);
- return;
- break;
- case ZENABLE_EXPAND_CHECK:
- {
- jam();
- fragptr.i = signal->theData[1];
- if (fragptr.i != RNIL)
- {
- jam();
- c_lcp_complete_fragments.getPtr(fragptr);
- signal->theData[0] = fragptr.p->tabRef;
- signal->theData[1] = fragptr.p->fragId;
- sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB);
- Ptr<Fragrecord> save = fragptr;
-
- c_lcp_complete_fragments.next(fragptr);
- signal->theData[0] = ZENABLE_EXPAND_CHECK;
- signal->theData[1] = fragptr.i;
- sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 2, JBB);
-
- c_lcp_complete_fragments.remove(save);
- return;
- }
- else
- {
- jam();
- cstartRecReq = 2;
- ndbrequire(c_lcp_complete_fragments.isEmpty());
- StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend();
- conf->startingNodeId = getOwnNodeId();
- sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal,
- StartRecConf::SignalLength, JBB);
- return;
- }
- }
- case ZRETRY_TCKEYREF:
- {
- jam();
- Uint32 cnt = signal->theData[1];
- Uint32 ref = signal->theData[2];
- if (cnt < (10 * 60 * 5))
- {
- jam();
- /**
- * Only retry for 5 minutes...then hope that API has handled it..somehow
- */
- memmove(signal->theData, signal->theData+3, 4*TcKeyRef::SignalLength);
- sendTCKEYREF(signal, ref, 0, cnt);
- }
- return;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
-}//Dblqh::execCONTINUEB()
-
-/* *********************************************************> */
-/* Request from DBDIH to include a new node in the node list */
-/* and so forth. */
-/* *********************************************************> */
-void Dblqh::execINCL_NODEREQ(Signal* signal)
-{
- jamEntry();
- BlockReference retRef = signal->theData[0];
- Uint32 nodeId = signal->theData[1];
- cnewestGci = signal->theData[2];
- cnewestCompletedGci = signal->theData[2] - 1;
- ndbrequire(cnoOfNodes < MAX_NDB_NODES);
- for (Uint32 i = 0; i < cnoOfNodes; i++) {
- jam();
- if (cnodeData[i] == nodeId) {
- jam();
- cnodeStatus[i] = ZNODE_UP;
- }//if
- }//for
- signal->theData[0] = nodeId;
- signal->theData[1] = cownref;
- sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
- return;
-}//Dblqh::execINCL_NODEREQ()
-
-void Dblqh::execTUPSEIZEREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execTUPSEIZEREF()
-
-/* ########################################################################## */
-/* ####### START / RESTART MODULE ####### */
-/* ########################################################################## */
-/* ************************************************************************>> */
-/* This is first signal that arrives in a start / restart. Sender is NDBCNTR_REF. */
-/* ************************************************************************>> */
-void Dblqh::execSTTOR(Signal* signal)
-{
- UintR tstartPhase;
-
- jamEntry();
- /* START CASE */
- tstartPhase = signal->theData[1];
- /* SYSTEM RESTART RANK */
- csignalKey = signal->theData[6];
-#if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR
- char *name;
- FILE *out = 0;
-#endif
- switch (tstartPhase) {
- case ZSTART_PHASE1:
- jam();
- cstartPhase = tstartPhase;
- c_tup = (Dbtup*)globalData.getBlock(DBTUP);
- c_acc = (Dbacc*)globalData.getBlock(DBACC);
- ndbrequire(c_tup != 0 && c_acc != 0);
- sendsttorryLab(signal);
-
-#if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR
-#ifdef VM_TRACE
- out = globalSignalLoggers.getOutputStream();
-#endif
- if (out == 0) {
- name = NdbConfig_SignalLogFileName(getOwnNodeId());
- out = fopen(name, "a");
- }
- tracenrout = new NdbOut(* new FileOutputStream(out));
-#endif
-
-#ifdef ERROR_INSERT
- traceopout = &ndbout;
-#endif
-
- return;
- break;
- case 4:
- jam();
- define_backup(signal);
- break;
- default:
- jam();
- /*empty*/;
- sendsttorryLab(signal);
- return;
- break;
- }//switch
-}//Dblqh::execSTTOR()
-
-void
-Dblqh::define_backup(Signal* signal)
-{
- DefineBackupReq * req = (DefineBackupReq*)signal->getDataPtrSend();
- req->backupId = 0;
- req->clientRef = 0;
- req->clientData = 0;
- req->senderRef = reference();
- req->backupPtr = 0;
- req->backupKey[0] = 0;
- req->backupKey[1] = 0;
- req->nodes.clear();
- req->nodes.set(getOwnNodeId());
- req->backupDataLen = ~0;
-
- sendSignal(BACKUP_REF, GSN_DEFINE_BACKUP_REQ, signal,
- DefineBackupReq::SignalLength, JBB);
-}
-
-void
-Dblqh::execDEFINE_BACKUP_REF(Signal* signal)
-{
- jamEntry();
- m_backup_ptr = RNIL;
- DefineBackupRef* ref = (DefineBackupRef*)signal->getDataPtrSend();
- int err_code = 0;
- char * extra_msg = NULL;
-
- switch(ref->errorCode){
- case DefineBackupRef::Undefined:
- case DefineBackupRef::FailedToSetupFsBuffers:
- case DefineBackupRef::FailedToAllocateBuffers:
- case DefineBackupRef::FailedToAllocateTables:
- case DefineBackupRef::FailedAllocateTableMem:
- case DefineBackupRef::FailedToAllocateFileRecord:
- case DefineBackupRef::FailedToAllocateAttributeRecord:
- case DefineBackupRef::FailedInsertFileHeader:
- case DefineBackupRef::FailedInsertTableList:
- jam();
- err_code = NDBD_EXIT_INVALID_CONFIG;
- extra_msg = (char*) "Probably Backup parameters configuration error, Please consult the manual";
- progError(__LINE__, err_code, extra_msg);
- }
-
- sendsttorryLab(signal);
-}
-
-void
-Dblqh::execDEFINE_BACKUP_CONF(Signal* signal)
-{
- jamEntry();
- DefineBackupConf * conf = (DefineBackupConf*)signal->getDataPtrSend();
- m_backup_ptr = conf->backupPtr;
- sendsttorryLab(signal);
-}
-
-/* ***************************************> */
-/* Restart phases 1 - 6, sender is Ndbcntr */
-/* ***************************************> */
-void Dblqh::execNDB_STTOR(Signal* signal)
-{
- jamEntry();
- Uint32 ownNodeId = signal->theData[1]; /* START PHASE*/
- cstartPhase = signal->theData[2]; /* MY NODE ID */
- cstartType = signal->theData[3]; /* START TYPE */
-
- switch (cstartPhase) {
- case ZSTART_PHASE1:
- jam();
- preComputedRequestInfoMask = 0;
- LqhKeyReq::setKeyLen(preComputedRequestInfoMask, RI_KEYLEN_MASK);
- LqhKeyReq::setLastReplicaNo(preComputedRequestInfoMask, RI_LAST_REPL_MASK);
- // Dont LqhKeyReq::setApplicationAddressFlag
- LqhKeyReq::setDirtyFlag(preComputedRequestInfoMask, 1);
- // Dont LqhKeyReq::setInterpretedFlag
- LqhKeyReq::setSimpleFlag(preComputedRequestInfoMask, 1);
- LqhKeyReq::setOperation(preComputedRequestInfoMask, RI_OPERATION_MASK);
- LqhKeyReq::setGCIFlag(preComputedRequestInfoMask, 1);
- LqhKeyReq::setNrCopyFlag(preComputedRequestInfoMask, 1);
- // Dont setAIInLqhKeyReq
- // Dont setSeqNoReplica
- // Dont setSameClientAndTcFlag
- // Dont setReturnedReadLenAIFlag
- // Dont setAPIVersion
- LqhKeyReq::setMarkerFlag(preComputedRequestInfoMask, 1);
- //preComputedRequestInfoMask = 0x003d7fff;
- startphase1Lab(signal, /* dummy */ ~0, ownNodeId);
-
- signal->theData[0] = ZOPERATION_EVENT_REP;
- signal->theData[1] = 1;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
- return;
- break;
- case ZSTART_PHASE2:
- jam();
- startphase2Lab(signal, /* dummy */ ~0);
- return;
- break;
- case ZSTART_PHASE3:
- jam();
- startphase3Lab(signal);
- return;
- break;
- case ZSTART_PHASE4:
- jam();
- startphase4Lab(signal);
- return;
- break;
- case ZSTART_PHASE6:
- jam();
- startphase6Lab(signal);
- return;
- break;
- default:
- jam();
- /*empty*/;
- sendNdbSttorryLab(signal);
- return;
- break;
- }//switch
-}//Dblqh::execNDB_STTOR()
-
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* +++++++ START PHASE 2 +++++++ */
-/* */
-/* INITIATE ALL RECORDS WITHIN THE BLOCK */
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-void Dblqh::startphase1Lab(Signal* signal, Uint32 _dummy, Uint32 ownNodeId)
-{
- UintR Ti;
- HostRecordPtr ThostPtr;
-
-/* ------- INITIATE ALL RECORDS ------- */
- cownNodeid = ownNodeId;
- caccBlockref = calcAccBlockRef (cownNodeid);
- ctupBlockref = calcTupBlockRef (cownNodeid);
- ctuxBlockref = calcTuxBlockRef (cownNodeid);
- cownref = calcLqhBlockRef (cownNodeid);
- for (Ti = 0; Ti < chostFileSize; Ti++) {
- ThostPtr.i = Ti;
- ptrCheckGuard(ThostPtr, chostFileSize, hostRecord);
- ThostPtr.p->hostLqhBlockRef = calcLqhBlockRef(ThostPtr.i);
- ThostPtr.p->hostTcBlockRef = calcTcBlockRef(ThostPtr.i);
- ThostPtr.p->inPackedList = false;
- ThostPtr.p->noOfPackedWordsLqh = 0;
- ThostPtr.p->noOfPackedWordsTc = 0;
- }//for
- cpackedListIndex = 0;
- sendNdbSttorryLab(signal);
- return;
-}//Dblqh::startphase1Lab()
-
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* +++++++ START PHASE 2 +++++++ */
-/* */
-/* CONNECT LQH WITH ACC AND TUP. */
-/* EVERY CONNECTION RECORD IN LQH IS ASSIGNED TO ONE ACC CONNECTION RECORD */
-/* AND ONE TUP CONNECTION RECORD. */
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-void Dblqh::startphase2Lab(Signal* signal, Uint32 _dummy)
-{
- cmaxWordsAtNodeRec = MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT;
-/* -- ACC AND TUP CONNECTION PROCESS -- */
- tcConnectptr.i = 0;
- ptrAss(tcConnectptr, tcConnectionrec);
- moreconnectionsLab(signal);
- return;
-}//Dblqh::startphase2Lab()
-
-void Dblqh::moreconnectionsLab(Signal* signal)
-{
- tcConnectptr.p->tcAccBlockref = caccBlockref;
- // set TUX block here (no operation is seized in TUX)
- tcConnectptr.p->tcTuxBlockref = ctuxBlockref;
-/* NO STATE CHECKING IS PERFORMED, ASSUMED TO WORK */
-/* *************** */
-/* ACCSEIZEREQ < */
-/* *************** */
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- sendSignal(caccBlockref, GSN_ACCSEIZEREQ, signal, 2, JBB);
- return;
-}//Dblqh::moreconnectionsLab()
-
-/* ***************> */
-/* ACCSEIZECONF > */
-/* ***************> */
-void Dblqh::execACCSEIZECONF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- tcConnectptr.p->accConnectrec = signal->theData[1];
-/* *************** */
-/* TUPSEIZEREQ < */
-/* *************** */
- tcConnectptr.p->tcTupBlockref = ctupBlockref;
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- sendSignal(ctupBlockref, GSN_TUPSEIZEREQ, signal, 2, JBB);
- return;
-}//Dblqh::execACCSEIZECONF()
-
-/* ***************> */
-/* TUPSEIZECONF > */
-/* ***************> */
-void Dblqh::execTUPSEIZECONF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- tcConnectptr.p->tupConnectrec = signal->theData[1];
-/* ------- CHECK IF THERE ARE MORE CONNECTIONS TO BE CONNECTED ------- */
- tcConnectptr.i = tcConnectptr.p->nextTcConnectrec;
- if (tcConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- moreconnectionsLab(signal);
- return;
- }//if
-/* ALL LQH_CONNECT RECORDS ARE CONNECTED TO ACC AND TUP ---- */
- sendNdbSttorryLab(signal);
- return;
-}//Dblqh::execTUPSEIZECONF()
-
-/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* +++++++ START PHASE 4 +++++++ */
-/* */
-/* CONNECT LQH WITH LQH. */
-/* CONNECT EACH LQH WITH EVERY LQH IN THE DATABASE SYSTEM. */
-/* IF INITIAL START THEN CREATE THE FRAGMENT LOG FILES */
-/*IF SYSTEM RESTART OR NODE RESTART THEN OPEN THE FRAGMENT LOG FILES AND */
-/*FIND THE END OF THE LOG FILES. */
-/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* WAIT UNTIL ADD NODE PROCESSES ARE COMPLETED */
-/* IF INITIAL START ALSO WAIT FOR LOG FILES TO INITIALISED */
-/*START TIME SUPERVISION OF LOG FILES. WE HAVE TO WRITE LOG PAGES TO DISK */
-/*EVEN IF THE PAGES ARE NOT FULL TO ENSURE THAT THEY COME TO DISK ASAP. */
-/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-void Dblqh::startphase3Lab(Signal* signal)
-{
- LogFileRecordPtr prevLogFilePtr;
- LogFileRecordPtr zeroLogFilePtr;
-
- caddNodeState = ZTRUE;
-/* ***************<< */
-/* READ_NODESREQ < */
-/* ***************<< */
- cinitialStartOngoing = ZTRUE;
- ndbrequire(cnoLogFiles != 0);
-
- for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
- initLogpart(signal);
- for (Uint32 fileNo = 0; fileNo < cnoLogFiles; fileNo++) {
- seizeLogfile(signal);
- if (fileNo != 0) {
- jam();
- prevLogFilePtr.p->nextLogFile = logFilePtr.i;
- logFilePtr.p->prevLogFile = prevLogFilePtr.i;
- } else {
- jam();
- logPartPtr.p->firstLogfile = logFilePtr.i;
- logPartPtr.p->currentLogfile = logFilePtr.i;
- zeroLogFilePtr.i = logFilePtr.i;
- zeroLogFilePtr.p = logFilePtr.p;
- }//if
- prevLogFilePtr.i = logFilePtr.i;
- prevLogFilePtr.p = logFilePtr.p;
- initLogfile(signal, fileNo);
- if ((cstartType == NodeState::ST_INITIAL_START) ||
- (cstartType == NodeState::ST_INITIAL_NODE_RESTART)) {
- if (logFilePtr.i == zeroLogFilePtr.i) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*IN AN INITIAL START WE START BY CREATING ALL LOG FILES AND SETTING THEIR */
-/*PROPER SIZE AND INITIALISING PAGE ZERO IN ALL FILES. */
-/*WE START BY CREATING FILE ZERO IN EACH LOG PART AND THEN PROCEED */
-/*SEQUENTIALLY THROUGH ALL LOG FILES IN THE LOG PART. */
-/* ------------------------------------------------------------------------- */
- openLogfileInit(signal);
- }//if
- }//if
- }//for
- zeroLogFilePtr.p->prevLogFile = logFilePtr.i;
- logFilePtr.p->nextLogFile = zeroLogFilePtr.i;
- }//for
- if (cstartType != NodeState::ST_INITIAL_START &&
- cstartType != NodeState::ST_INITIAL_NODE_RESTART) {
- jam();
- ndbrequire(cstartType == NodeState::ST_NODE_RESTART ||
- cstartType == NodeState::ST_SYSTEM_RESTART);
- /** --------------------------------------------------------------------
- * THIS CODE KICKS OFF THE SYSTEM RESTART AND NODE RESTART. IT STARTS UP
- * THE RESTART BY FINDING THE END OF THE LOG AND FROM THERE FINDING THE
- * INFO ABOUT THE GLOBAL CHECKPOINTS IN THE FRAGMENT LOG.
- --------------------------------------------------------------------- */
- for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) {
- jam();
- LogFileRecordPtr locLogFilePtr;
- ptrAss(logPartPtr, logPartRecord);
- locLogFilePtr.i = logPartPtr.p->firstLogfile;
- ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FRONTPAGE;
- openFileRw(signal, locLogFilePtr);
- }//for
- }//if
-
- signal->theData[0] = cownref;
- sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
- return;
-}//Dblqh::startphase3Lab()
-
-/* ****************** */
-/* READ_NODESCONF > */
-/* ****************** */
-void Dblqh::execREAD_NODESCONF(Signal* signal)
-{
- jamEntry();
-
- ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
- cnoOfNodes = readNodes->noOfNodes;
-
- unsigned ind = 0;
- unsigned i = 0;
- for (i = 1; i < MAX_NDB_NODES; i++) {
- jam();
- if (NodeBitmask::get(readNodes->allNodes, i)) {
- jam();
- cnodeData[ind] = i;
- cnodeStatus[ind] = NodeBitmask::get(readNodes->inactiveNodes, i);
- //readNodes->getVersionId(i, readNodes->theVersionIds) not used
- if (!NodeBitmask::get(readNodes->inactiveNodes, i))
- {
- jam();
- m_sr_nodes.set(i);
- }
- ind++;
- }//if
- }//for
- ndbrequire(ind == cnoOfNodes);
- ndbrequire(cnoOfNodes >= 1 && cnoOfNodes < MAX_NDB_NODES);
- ndbrequire(!(cnoOfNodes == 1 && cstartType == NodeState::ST_NODE_RESTART));
-
- caddNodeState = ZFALSE;
- if (cstartType == NodeState::ST_SYSTEM_RESTART)
- {
- jam();
- sendNdbSttorryLab(signal);
- return;
- }
- else if (cstartType == NodeState::ST_NODE_RESTART)
- {
- jam();
- SET_TRACENR_FLAG;
- m_sr_nodes.clear();
- m_sr_nodes.set(getOwnNodeId());
- sendNdbSttorryLab(signal);
- return;
- }
- SET_TRACENR_FLAG;
-
- checkStartCompletedLab(signal);
- return;
-}//Dblqh::execREAD_NODESCONF()
-
-void Dblqh::checkStartCompletedLab(Signal* signal)
-{
- if (caddNodeState == ZFALSE) {
- if (cinitialStartOngoing == ZFALSE) {
- jam();
- sendNdbSttorryLab(signal);
- return;
- }//if
- }//if
- return;
-}//Dblqh::checkStartCompletedLab()
-
-void Dblqh::startphase4Lab(Signal* signal)
-{
- sendNdbSttorryLab(signal);
- return;
-}//Dblqh::startphase4Lab()
-
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* SET CONCURRENCY OF LOCAL CHECKPOINTS TO BE USED AFTER SYSTEM RESTART. */
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-void Dblqh::startphase6Lab(Signal* signal)
-{
- cstartPhase = ZNIL;
- cstartType = ZNIL;
- CLEAR_TRACENR_FLAG;
- sendNdbSttorryLab(signal);
- return;
-}//Dblqh::startphase6Lab()
-
-void Dblqh::sendNdbSttorryLab(Signal* signal)
-{
- signal->theData[0] = cownref;
- sendSignal(NDBCNTR_REF, GSN_NDB_STTORRY, signal, 1, JBB);
- return;
-}//Dblqh::sendNdbSttorryLab()
-
-void Dblqh::sendsttorryLab(Signal* signal)
-{
-/* *********<< */
-/* STTORRY < */
-/* *********<< */
- signal->theData[0] = csignalKey; /* SIGNAL KEY */
- signal->theData[1] = 3; /* BLOCK CATEGORY */
- signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
- signal->theData[3] = ZSTART_PHASE1;
- signal->theData[4] = 4;
- signal->theData[5] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
- return;
-}//Dblqh::sendsttorryLab()
-
-/* ***************>> */
-/* READ_NODESREF > */
-/* ***************>> */
-void Dblqh::execREAD_NODESREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execREAD_NODESREF()
-
-/* *************** */
-/* SIZEALT_REP > */
-/* *************** */
-void Dblqh::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- cnoLogFiles = 8;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_REDOLOG_FILES,
- &cnoLogFiles));
- ndbrequire(cnoLogFiles > 0);
-
- Uint32 log_page_size= 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_REDO_BUFFER,
- &log_page_size);
-
- /**
- * Always set page size in half MBytes
- */
- clogPageFileSize= (log_page_size / sizeof(LogPageRecord));
- Uint32 mega_byte_part= clogPageFileSize & 15;
- if (mega_byte_part != 0) {
- jam();
- clogPageFileSize+= (16 - mega_byte_part);
- }
-
- /* maximum number of log file operations */
- clfoFileSize = clogPageFileSize;
- if (clfoFileSize < ZLFO_MIN_FILE_SIZE)
- clfoFileSize = ZLFO_MIN_FILE_SIZE;
-
- 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_OP_PER_SCAN;
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &c_diskless));
- c_o_direct = true;
- ndb_mgm_get_int_parameter(p, CFG_DB_O_DIRECT, &c_o_direct);
-
- Uint32 tmp= 0;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &tmp));
- c_fragment_pool.setSize(tmp);
-
- if (!ndb_mgm_get_int_parameter(p, CFG_DB_REDOLOG_FILE_SIZE,
- &clogFileSize))
- {
- // convert to mbyte
- clogFileSize = (clogFileSize + 1024*1024 - 1) / (1024 * 1024);
- ndbrequire(clogFileSize >= 4 && clogFileSize <= 1024);
- }
-
- cmaxLogFilesInPageZero = (ZPAGE_SIZE - ZPAGE_HEADER_SIZE - 128) /
- (ZFD_MBYTE_SIZE * clogFileSize);
-
- /**
- * "Old" cmaxLogFilesInPageZero was 40
- * Each FD need 3 words per mb, require that they can fit into 1 page
- * (atleast 1 FD)
- * Is also checked in ConfigInfo.cpp (max FragmentLogFileSize = 1Gb)
- * 1Gb = 1024Mb => 3(ZFD_MBYTE_SIZE) * 1024 < 8192 (ZPAGE_SIZE)
- */
- if (cmaxLogFilesInPageZero > 40)
- {
- jam();
- cmaxLogFilesInPageZero = 40;
- }
- else
- {
- ndbrequire(cmaxLogFilesInPageZero);
- }
-
- initRecords();
- initialiseRecordsLab(signal, 0, ref, senderData);
-
- return;
-}//Dblqh::execSIZEALT_REP()
-
-/* ########################################################################## */
-/* ####### ADD/DELETE FRAGMENT MODULE ####### */
-/* THIS MODULE IS USED BY DICTIONARY TO CREATE NEW FRAGMENTS AND DELETE */
-/* OLD FRAGMENTS. */
-/* */
-/* ########################################################################## */
-/* -------------------------------------------------------------- */
-/* FRAG REQ */
-/* -------------------------------------------------------------- */
-/* *********************************************************> */
-/* LQHFRAGREQ: Create new fragments for a table. Sender DICT */
-/* *********************************************************> */
-
-// this unbelievable mess could be replaced by one signal to LQH
-// and execute direct to local DICT to get everything at once
-
-void Dblqh::execLQHFRAGREQ(Signal* signal)
-{
- jamEntry();
- LqhFragReq * req = (LqhFragReq*)signal->getDataPtr();
-
- Uint32 retPtr = req->senderData;
- BlockReference retRef = req->senderRef;
- Uint32 fragId = req->fragmentId;
- Uint32 reqinfo = req->requestInfo;
- tabptr.i = req->tableId;
- Uint16 tlocalKeylen = req->localKeyLength;
- Uint32 tmaxLoadFactor = req->maxLoadFactor;
- Uint32 tminLoadFactor = req->minLoadFactor;
- Uint8 tk = req->kValue;
- Uint8 tlhstar = req->lh3DistrBits;
- Uint8 tlh = req->lh3PageBits;
- Uint32 tnoOfAttr = req->noOfAttributes;
- Uint32 tnoOfNull = req->noOfNullAttributes;
- 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 noOfKeyAttr = req->noOfKeyAttr;
- Uint32 noOfCharsets = req->noOfCharsets;
- Uint32 checksumIndicator = req->checksumIndicator;
- Uint32 gcpIndicator = req->GCPIndicator;
- Uint32 startGci = req->startGci;
- Uint32 tableType = req->tableType;
- Uint32 primaryTableId = req->primaryTableId;
- Uint32 tablespace= req->tablespace_id;
- Uint32 logPart = req->logPartId;
- Uint32 forceVarPartFlag = req->forceVarPartFlag;
-
- if (signal->getLength() < 20)
- {
- logPart = (fragId & 1) + 2 * (tabptr.i & 1);
- }
- logPart &= 3;
-
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- bool tempTable = ((reqinfo & LqhFragReq::TemporaryTable) != 0);
-
- /* Temporary tables set to defined in system restart */
- if (tabptr.p->tableStatus == Tablerec::NOT_DEFINED){
- tabptr.p->tableStatus = Tablerec::ADD_TABLE_ONGOING;
- tabptr.p->tableType = tableType;
- tabptr.p->primaryTableId =
- (primaryTableId == RNIL ? tabptr.i : primaryTableId);
- tabptr.p->schemaVersion = tschemaVersion;
- tabptr.p->m_disk_table= 0;
- }//if
-
- if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING){
- jam();
- fragrefLab(signal, retRef, retPtr, ZTAB_STATE_ERROR);
- return;
- }//if
- //--------------------------------------------------------------------
- // We could arrive here if we create the fragment as part of a take
- // over by a hot spare node. The table is then is already created
- // and bit 31 is set, thus indicating that we are creating a fragment
- // by copy creation. Also since the node has already been started we
- // know that it is not a node restart ongoing.
- //--------------------------------------------------------------------
-
- if (getFragmentrec(signal, fragId)) {
- jam();
- fragrefLab(signal, retRef, retPtr, terrorCode);
- return;
- }//if
- if (!insertFragrec(signal, fragId)) {
- jam();
- fragrefLab(signal, retRef, retPtr, terrorCode);
- return;
- }//if
- Uint32 copyType = reqinfo & 3;
- initFragrec(signal, tabptr.i, fragId, copyType);
- fragptr.p->startGci = startGci;
- fragptr.p->newestGci = startGci;
- fragptr.p->tableType = tableType;
- fragptr.p->m_log_part_ptr_i = logPart; // assumes array
-
- if (DictTabInfo::isOrderedIndex(tableType)) {
- jam();
- // find corresponding primary table fragment
- TablerecPtr tTablePtr;
- tTablePtr.i = primaryTableId;
- ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
- FragrecordPtr tFragPtr;
- tFragPtr.i = RNIL;
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- if (tTablePtr.p->fragid[i] == fragptr.p->fragId) {
- jam();
- tFragPtr.i = tTablePtr.p->fragrec[i];
- break;
- }
- }
- ndbrequire(tFragPtr.i != RNIL);
- // store it
- fragptr.p->tableFragptr = tFragPtr.i;
- } else {
- fragptr.p->tableFragptr = fragptr.i;
- }
-
- if (tempTable) {
-//--------------------------------------------
-// reqinfo bit 3-4 = 2 means temporary table
-// without logging or checkpointing.
-//--------------------------------------------
- jam();
- fragptr.p->logFlag = Fragrecord::STATE_FALSE;
- fragptr.p->lcpFlag = Fragrecord::LCP_STATE_FALSE;
- }//if
-
-//----------------------------------------------
-// For node restarts it is not necessarily zero
-//----------------------------------------------
- if (cfirstfreeAddfragrec == RNIL) {
- jam();
- deleteFragrec(fragId);
- fragrefLab(signal, retRef, retPtr, ZNO_ADD_FRAGREC);
- return;
- }//if
- seizeAddfragrec(signal);
- addfragptr.p->addFragid = fragId;
- addfragptr.p->fragmentPtr = fragptr.i;
- addfragptr.p->dictBlockref = retRef;
- addfragptr.p->dictConnectptr = retPtr;
- addfragptr.p->m_senderAttrPtr = RNIL;
- addfragptr.p->noOfAttr = tnoOfAttr;
- addfragptr.p->noOfNull = tnoOfNull;
- 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 */
- addfragptr.p->schemaVer = tschemaVersion;
- Uint32 tmp = (reqinfo & LqhFragReq::CreateInRunning);
- addfragptr.p->fragCopyCreation = (tmp == 0 ? 0 : 1);
- addfragptr.p->addfragErrorCode = 0;
- addfragptr.p->noOfKeyAttr = noOfKeyAttr;
- addfragptr.p->noOfCharsets = noOfCharsets;
- addfragptr.p->checksumIndicator = checksumIndicator;
- addfragptr.p->GCPIndicator = gcpIndicator;
- addfragptr.p->lh3DistrBits = tlhstar;
- addfragptr.p->tableType = tableType;
- addfragptr.p->primaryTableId = primaryTableId;
- addfragptr.p->tablespace_id= tablespace;
- addfragptr.p->forceVarPartFlag = forceVarPartFlag;
- //
- addfragptr.p->tupConnectptr = RNIL;
- addfragptr.p->tuxConnectptr = RNIL;
-
- if (DictTabInfo::isTable(tableType) ||
- DictTabInfo::isHashIndex(tableType)) {
- jam();
- AccFragReq* const accreq = (AccFragReq*)signal->getDataPtrSend();
- accreq->userPtr = addfragptr.i;
- accreq->userRef = cownref;
- accreq->tableId = tabptr.i;
- accreq->reqInfo = copyType << 4;
- accreq->fragId = fragId;
- accreq->localKeyLen = tlocalKeylen;
- accreq->maxLoadFactor = tmaxLoadFactor;
- accreq->minLoadFactor = tminLoadFactor;
- accreq->kValue = tk;
- accreq->lhFragBits = tlhstar;
- accreq->lhDirBits = tlh;
- accreq->keyLength = ttupKeyLength;
- /* --------------------------------------------------------------------- */
- /* Send ACCFRAGREQ, when confirmation is received send 2 * TUPFRAGREQ to */
- /* create 2 tuple fragments on this node. */
- /* --------------------------------------------------------------------- */
- addfragptr.p->addfragStatus = AddFragRecord::ACC_ADDFRAG;
- sendSignal(fragptr.p->accBlockref, GSN_ACCFRAGREQ,
- signal, AccFragReq::SignalLength, JBB);
- return;
- }
- if (DictTabInfo::isOrderedIndex(tableType)) {
- jam();
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
- sendAddFragReq(signal);
- return;
- }
- ndbrequire(false);
-}//Dblqh::execLQHFRAGREQ()
-
-/* *************** */
-/* ACCFRAGCONF > */
-/* *************** */
-void Dblqh::execACCFRAGCONF(Signal* signal)
-{
- jamEntry();
- addfragptr.i = signal->theData[0];
- Uint32 taccConnectptr = signal->theData[1];
- //Uint32 fragId1 = signal->theData[2];
- Uint32 accFragPtr1 = signal->theData[4];
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
-
- addfragptr.p->accConnectptr = taccConnectptr;
- fragptr.i = addfragptr.p->fragmentPtr;
- c_fragment_pool.getPtr(fragptr);
- fragptr.p->accFragptr = accFragPtr1;
-
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
- sendAddFragReq(signal);
-}//Dblqh::execACCFRAGCONF()
-
-/* *************** */
-/* TUPFRAGCONF > */
-/* *************** */
-void Dblqh::execTUPFRAGCONF(Signal* signal)
-{
- jamEntry();
- addfragptr.i = signal->theData[0];
- Uint32 tupConnectptr = signal->theData[1];
- Uint32 tupFragPtr = signal->theData[2]; /* TUP FRAGMENT POINTER */
- //Uint32 localFragId = signal->theData[3]; /* LOCAL FRAGMENT ID */
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- fragptr.i = addfragptr.p->fragmentPtr;
- c_fragment_pool.getPtr(fragptr);
- fragptr.p->tupFragptr = tupFragPtr;
- switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::WAIT_TUP:
- jam();
- fragptr.p->tupFragptr = tupFragPtr;
- addfragptr.p->tupConnectptr = tupConnectptr;
- if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
- sendAddFragReq(signal);
- break;
- }
- goto done_with_frag;
- break;
- case AddFragRecord::WAIT_TUX:
- jam();
- fragptr.p->tuxFragptr = tupFragPtr;
- addfragptr.p->tuxConnectptr = tupConnectptr;
- goto done_with_frag;
- break;
- done_with_frag:
- /* ---------------------------------------------------------------- */
- /* Finished create of fragments. Now ready for creating attributes. */
- /* ---------------------------------------------------------------- */
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
- {
- LqhFragConf* conf = (LqhFragConf*)signal->getDataPtrSend();
- conf->senderData = addfragptr.p->dictConnectptr;
- conf->lqhFragPtr = addfragptr.i;
- sendSignal(addfragptr.p->dictBlockref, GSN_LQHFRAGCONF,
- signal, LqhFragConf::SignalLength, JBB);
- }
- break;
- default:
- ndbrequire(false);
- break;
- }
-}//Dblqh::execTUPFRAGCONF()
-
-/* *************** */
-/* TUXFRAGCONF > */
-/* *************** */
-void Dblqh::execTUXFRAGCONF(Signal* signal)
-{
- jamEntry();
- execTUPFRAGCONF(signal);
-}//Dblqh::execTUXFRAGCONF
-
-/*
- * Add fragment in TUP or TUX. Called up to 4 times.
- */
-void
-Dblqh::sendAddFragReq(Signal* signal)
-{
- fragptr.i = addfragptr.p->fragmentPtr;
- c_fragment_pool.getPtr(fragptr);
- if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUP){
- TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
- if (DictTabInfo::isTable(addfragptr.p->tableType) ||
- DictTabInfo::isHashIndex(addfragptr.p->tableType)) {
- jam();
- 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->addFragid;
- 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->noOfCharsets = addfragptr.p->noOfCharsets;
- tupFragReq->checksumIndicator = addfragptr.p->checksumIndicator;
- tupFragReq->globalCheckpointIdIndicator = addfragptr.p->GCPIndicator;
- tupFragReq->tablespaceid = addfragptr.p->tablespace_id;
- tupFragReq->forceVarPartFlag = addfragptr.p->forceVarPartFlag;
- sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
- signal, TupFragReq::SignalLength, JBB);
- return;
- }
- if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
- jam();
- 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->addFragid;
- 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->noOfCharsets = addfragptr.p->noOfCharsets;
- tupFragReq->checksumIndicator = addfragptr.p->checksumIndicator;
- tupFragReq->globalCheckpointIdIndicator = addfragptr.p->GCPIndicator;
- tupFragReq->forceVarPartFlag = addfragptr.p->forceVarPartFlag;
- sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
- signal, TupFragReq::SignalLength, JBB);
- return;
- }
- }
- if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUX) {
- if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
- jam();
- TuxFragReq* const tuxreq = (TuxFragReq*)signal->getDataPtrSend();
- tuxreq->userPtr = addfragptr.i;
- tuxreq->userRef = cownref;
- tuxreq->reqInfo = 0; /* ADD TABLE */
- tuxreq->tableId = addfragptr.p->tabId;
- ndbrequire(addfragptr.p->noOfAttr >= 2);
- tuxreq->noOfAttr = addfragptr.p->noOfAttr - 1; /* skip NDB$TNODE */
- tuxreq->fragId = addfragptr.p->addFragid;
- tuxreq->fragOff = addfragptr.p->lh3DistrBits;
- tuxreq->tableType = addfragptr.p->tableType;
- tuxreq->primaryTableId = addfragptr.p->primaryTableId;
- // pointer to index fragment in TUP
- tuxreq->tupIndexFragPtrI = fragptr.p->tupFragptr;
- // pointers to table fragments in TUP and ACC
- FragrecordPtr tFragPtr;
- tFragPtr.i = fragptr.p->tableFragptr;
- c_fragment_pool.getPtr(tFragPtr);
- tuxreq->tupTableFragPtrI[0] = tFragPtr.p->tupFragptr;
- tuxreq->tupTableFragPtrI[1] = RNIL;
- tuxreq->accTableFragPtrI[0] = tFragPtr.p->accFragptr;
- tuxreq->accTableFragPtrI[1] = RNIL;
- sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ,
- signal, TuxFragReq::SignalLength, JBB);
- return;
- }
- }
- ndbrequire(false);
-}//Dblqh::sendAddFragReq
-
-/* ************************************************************************> */
-/* LQHADDATTRREQ: Request from DICT to create attributes for the new table. */
-/* ************************************************************************> */
-void Dblqh::execLQHADDATTREQ(Signal* signal)
-{
- jamEntry();
- LqhAddAttrReq * const req = (LqhAddAttrReq*)signal->getDataPtr();
-
- addfragptr.i = req->lqhFragPtr;
- const Uint32 tnoOfAttr = req->noOfAttributes;
- const Uint32 senderData = req->senderData;
- const Uint32 senderAttrPtr = req->senderAttrPtr;
-
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::WAIT_ADD_ATTR);
- ndbrequire((tnoOfAttr != 0) && (tnoOfAttr <= LqhAddAttrReq::MAX_ATTRIBUTES));
- addfragptr.p->totalAttrReceived += tnoOfAttr;
- ndbrequire(addfragptr.p->totalAttrReceived <= addfragptr.p->noOfAttr);
-
- addfragptr.p->attrReceived = tnoOfAttr;
- for (Uint32 i = 0; i < tnoOfAttr; i++) {
- addfragptr.p->attributes[i] = req->attributes[i];
- if(AttributeDescriptor::getDiskBased(req->attributes[i].attrDescriptor))
- {
- TablerecPtr tabPtr;
- tabPtr.i = addfragptr.p->tabId;
- ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
- tabPtr.p->m_disk_table = 1;
- }
- }//for
- addfragptr.p->attrSentToTup = 0;
- ndbrequire(addfragptr.p->dictConnectptr == senderData);
- addfragptr.p->m_senderAttrPtr = senderAttrPtr;
- addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
- sendAddAttrReq(signal);
-}//Dblqh::execLQHADDATTREQ()
-
-/* *********************>> */
-/* TUP_ADD_ATTCONF > */
-/* *********************>> */
-void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
-{
- jamEntry();
- addfragptr.i = signal->theData[0];
- // implies that operation was released on the other side
- const bool lastAttr = signal->theData[1];
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::TUP_ATTR_WAIT:
- if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
- addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT;
- sendAddAttrReq(signal);
- break;
- }
- goto done_with_attr;
- break;
- case AddFragRecord::TUX_ATTR_WAIT:
- jam();
- if (lastAttr)
- addfragptr.p->tuxConnectptr = RNIL;
- goto done_with_attr;
- break;
- done_with_attr:
- addfragptr.p->attrSentToTup = addfragptr.p->attrSentToTup + 1;
- ndbrequire(addfragptr.p->attrSentToTup <= addfragptr.p->attrReceived);
- ndbrequire(addfragptr.p->totalAttrReceived <= addfragptr.p->noOfAttr);
- if (addfragptr.p->attrSentToTup < addfragptr.p->attrReceived) {
- // more in this batch
- jam();
- addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
- sendAddAttrReq(signal);
- } else if (addfragptr.p->totalAttrReceived < addfragptr.p->noOfAttr) {
- // more batches to receive
- jam();
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_ADD_ATTR;
- LqhAddAttrConf *const conf = (LqhAddAttrConf*)signal->getDataPtrSend();
- conf->senderData = addfragptr.p->dictConnectptr;
- conf->senderAttrPtr = addfragptr.p->m_senderAttrPtr;
- conf->fragId = addfragptr.p->addFragid;
- sendSignal(addfragptr.p->dictBlockref, GSN_LQHADDATTCONF,
- signal, LqhAddAttrConf::SignalLength, JBB);
- } else {
- fragptr.i = addfragptr.p->fragmentPtr;
- c_fragment_pool.getPtr(fragptr);
- /* ------------------------------------------------------------------
- * WE HAVE NOW COMPLETED ADDING THIS FRAGMENT. WE NOW NEED TO SET THE
- * PROPER STATE IN FRAG_STATUS DEPENDENT ON IF WE ARE CREATING A NEW
- * REPLICA OR IF WE ARE CREATING A TABLE. FOR FRAGMENTS IN COPY
- * PROCESS WE DO NOT WANT LOGGING ACTIVATED.
- * ----------------------------------------------------------------- */
- if (addfragptr.p->fragCopyCreation == 1) {
- jam();
- if (! DictTabInfo::isOrderedIndex(addfragptr.p->tableType))
- {
- fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED;
- //fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
- fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
- }
- else
- {
- fragptr.p->fragStatus = Fragrecord::FSACTIVE;
- }
- fragptr.p->logFlag = Fragrecord::STATE_FALSE;
- } else {
- jam();
- fragptr.p->fragStatus = Fragrecord::FSACTIVE;
- }//if
- LqhAddAttrConf *const conf = (LqhAddAttrConf*)signal->getDataPtrSend();
- conf->senderData = addfragptr.p->dictConnectptr;
- conf->senderAttrPtr = addfragptr.p->m_senderAttrPtr;
- conf->fragId = addfragptr.p->addFragid;
- sendSignal(addfragptr.p->dictBlockref, GSN_LQHADDATTCONF, signal,
- LqhAddAttrConf::SignalLength, JBB);
- releaseAddfragrec(signal);
- }//if
- break;
- default:
- ndbrequire(false);
- break;
- }
-}
-
-/* **********************>> */
-/* TUX_ADD_ATTRCONF > */
-/* **********************>> */
-void Dblqh::execTUX_ADD_ATTRCONF(Signal* signal)
-{
- jamEntry();
- execTUP_ADD_ATTCONF(signal);
-}//Dblqh::execTUX_ADD_ATTRCONF
-
-/*
- * Add attribute in TUP or TUX. Called up to 4 times.
- */
-void
-Dblqh::sendAddAttrReq(Signal* signal)
-{
- arrGuard(addfragptr.p->attrSentToTup, LqhAddAttrReq::MAX_ATTRIBUTES);
- LqhAddAttrReq::Entry& entry =
- addfragptr.p->attributes[addfragptr.p->attrSentToTup];
- const Uint32 attrId = entry.attrId & 0xffff;
- const Uint32 primaryAttrId = entry.attrId >> 16;
- fragptr.i = addfragptr.p->fragmentPtr;
- c_fragment_pool.getPtr(fragptr);
- if (addfragptr.p->addfragStatus == AddFragRecord::TUP_ATTR_WAIT) {
- if (DictTabInfo::isTable(addfragptr.p->tableType) ||
- DictTabInfo::isHashIndex(addfragptr.p->tableType) ||
- (DictTabInfo::isOrderedIndex(addfragptr.p->tableType) &&
- primaryAttrId == ZNIL)) {
- jam();
- TupAddAttrReq* const tupreq = (TupAddAttrReq*)signal->getDataPtrSend();
- tupreq->tupConnectPtr = addfragptr.p->tupConnectptr;
- tupreq->notused1 = 0;
- tupreq->attrId = attrId;
- tupreq->attrDescriptor = entry.attrDescriptor;
- tupreq->extTypeInfo = entry.extTypeInfo;
- sendSignal(fragptr.p->tupBlockref, GSN_TUP_ADD_ATTRREQ,
- signal, TupAddAttrReq::SignalLength, JBB);
- return;
- }
- if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType) &&
- primaryAttrId != ZNIL) {
- // this attribute is not for TUP
- jam();
- TupAddAttrConf* tupconf = (TupAddAttrConf*)signal->getDataPtrSend();
- tupconf->userPtr = addfragptr.i;
- tupconf->lastAttr = false;
- sendSignal(reference(), GSN_TUP_ADD_ATTCONF,
- signal, TupAddAttrConf::SignalLength, JBB);
- return;
- }
- }
- if (addfragptr.p->addfragStatus == AddFragRecord::TUX_ATTR_WAIT) {
- jam();
- if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType) &&
- primaryAttrId != ZNIL) {
- jam();
- TuxAddAttrReq* const tuxreq = (TuxAddAttrReq*)signal->getDataPtrSend();
- tuxreq->tuxConnectPtr = addfragptr.p->tuxConnectptr;
- tuxreq->notused1 = 0;
- tuxreq->attrId = attrId;
- tuxreq->attrDescriptor = entry.attrDescriptor;
- tuxreq->extTypeInfo = entry.extTypeInfo;
- tuxreq->primaryAttrId = primaryAttrId;
- sendSignal(fragptr.p->tuxBlockref, GSN_TUX_ADD_ATTRREQ,
- signal, TuxAddAttrReq::SignalLength, JBB);
- return;
- }
- if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType) &&
- primaryAttrId == ZNIL) {
- // this attribute is not for TUX
- jam();
- TuxAddAttrConf* tuxconf = (TuxAddAttrConf*)signal->getDataPtrSend();
- tuxconf->userPtr = addfragptr.i;
- tuxconf->lastAttr = false;
- sendSignal(reference(), GSN_TUX_ADD_ATTRCONF,
- signal, TuxAddAttrConf::SignalLength, JBB);
- return;
- }
- }
- ndbrequire(false);
-}//Dblqh::sendAddAttrReq
-
-/* ************************************************************************>> */
-/* TAB_COMMITREQ: Commit the new table for use in transactions. Sender DICT. */
-/* ************************************************************************>> */
-void Dblqh::execTAB_COMMITREQ(Signal* signal)
-{
- jamEntry();
- Uint32 dihPtr = signal->theData[0];
- BlockReference dihBlockref = signal->theData[1];
- tabptr.i = signal->theData[2];
-
- if (tabptr.i >= ctabrecFileSize) {
- jam();
- terrorCode = ZTAB_FILE_SIZE;
- signal->theData[0] = dihPtr;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = tabptr.i;
- signal->theData[3] = terrorCode;
- sendSignal(dihBlockref, GSN_TAB_COMMITREF, signal, 4, JBB);
- return;
- }//if
- ptrAss(tabptr, tablerec);
- if (tabptr.p->tableStatus != Tablerec::ADD_TABLE_ONGOING) {
- jam();
- terrorCode = ZTAB_STATE_ERROR;
- signal->theData[0] = dihPtr;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = tabptr.i;
- signal->theData[3] = terrorCode;
- signal->theData[4] = tabptr.p->tableStatus;
- sendSignal(dihBlockref, GSN_TAB_COMMITREF, signal, 5, JBB);
- ndbrequire(false);
- return;
- }//if
- tabptr.p->usageCount = 0;
- tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
- signal->theData[0] = dihPtr;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = tabptr.i;
- sendSignal(dihBlockref, GSN_TAB_COMMITCONF, signal, 3, JBB);
- return;
-}//Dblqh::execTAB_COMMITREQ()
-
-
-void Dblqh::fragrefLab(Signal* signal,
- BlockReference fragBlockRef,
- Uint32 fragConPtr,
- Uint32 errorCode)
-{
- LqhFragRef * ref = (LqhFragRef*)signal->getDataPtrSend();
- ref->senderData = fragConPtr;
- ref->errorCode = errorCode;
- sendSignal(fragBlockRef, GSN_LQHFRAGREF, signal,
- LqhFragRef::SignalLength, JBB);
- return;
-}//Dblqh::fragrefLab()
-
-/*
- * Abort on-going ops.
- */
-void Dblqh::abortAddFragOps(Signal* signal)
-{
- fragptr.i = addfragptr.p->fragmentPtr;
- c_fragment_pool.getPtr(fragptr);
- if (addfragptr.p->tupConnectptr != RNIL) {
- jam();
- TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
- tupFragReq->userPtr = (Uint32)-1;
- tupFragReq->userRef = addfragptr.p->tupConnectptr;
- sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
- addfragptr.p->tupConnectptr = RNIL;
- }
- if (addfragptr.p->tuxConnectptr != RNIL) {
- jam();
- TuxFragReq* const tuxFragReq = (TuxFragReq*)signal->getDataPtrSend();
- tuxFragReq->userPtr = (Uint32)-1;
- tuxFragReq->userRef = addfragptr.p->tuxConnectptr;
- sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
- addfragptr.p->tuxConnectptr = RNIL;
- }
-}
-
-/* ************>> */
-/* ACCFRAGREF > */
-/* ************>> */
-void Dblqh::execACCFRAGREF(Signal* signal)
-{
- jamEntry();
- addfragptr.i = signal->theData[0];
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- terrorCode = signal->theData[1];
- ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
- addfragptr.p->addfragErrorCode = terrorCode;
-
- const Uint32 ref = addfragptr.p->dictBlockref;
- const Uint32 senderData = addfragptr.p->dictConnectptr;
- const Uint32 errorCode = addfragptr.p->addfragErrorCode;
- releaseAddfragrec(signal);
- fragrefLab(signal, ref, senderData, errorCode);
-
- return;
-}//Dblqh::execACCFRAGREF()
-
-/* ************>> */
-/* TUPFRAGREF > */
-/* ************>> */
-void Dblqh::execTUPFRAGREF(Signal* signal)
-{
- jamEntry();
- addfragptr.i = signal->theData[0];
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- terrorCode = signal->theData[1];
- fragptr.i = addfragptr.p->fragmentPtr;
- c_fragment_pool.getPtr(fragptr);
- addfragptr.p->addfragErrorCode = terrorCode;
-
- // no operation to release, just add some jams
- switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::WAIT_TUP:
- jam();
- break;
- case AddFragRecord::WAIT_TUX:
- jam();
- break;
- default:
- ndbrequire(false);
- break;
- }
- abortAddFragOps(signal);
-
- const Uint32 ref = addfragptr.p->dictBlockref;
- const Uint32 senderData = addfragptr.p->dictConnectptr;
- const Uint32 errorCode = addfragptr.p->addfragErrorCode;
- releaseAddfragrec(signal);
- fragrefLab(signal, ref, senderData, errorCode);
-
-}//Dblqh::execTUPFRAGREF()
-
-/* ************>> */
-/* TUXFRAGREF > */
-/* ************>> */
-void Dblqh::execTUXFRAGREF(Signal* signal)
-{
- jamEntry();
- execTUPFRAGREF(signal);
-}//Dblqh::execTUXFRAGREF
-
-/* *********************> */
-/* TUP_ADD_ATTREF > */
-/* *********************> */
-void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
-{
- jamEntry();
- addfragptr.i = signal->theData[0];
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- terrorCode = signal->theData[1];
- addfragptr.p->addfragErrorCode = terrorCode;
-
- // operation was released on the other side
- switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::TUP_ATTR_WAIT:
- jam();
- ndbrequire(addfragptr.p->tupConnectptr != RNIL);
- addfragptr.p->tupConnectptr = RNIL;
- break;
- case AddFragRecord::TUX_ATTR_WAIT:
- jam();
- ndbrequire(addfragptr.p->tuxConnectptr != RNIL);
- addfragptr.p->tuxConnectptr = RNIL;
- break;
- default:
- ndbrequire(false);
- break;
- }
- abortAddFragOps(signal);
-
- const Uint32 Ref = addfragptr.p->dictBlockref;
- const Uint32 senderData = addfragptr.p->dictConnectptr;
- const Uint32 errorCode = addfragptr.p->addfragErrorCode;
- releaseAddfragrec(signal);
-
- LqhAddAttrRef *const ref = (LqhAddAttrRef*)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->errorCode = errorCode;
- sendSignal(Ref, GSN_LQHADDATTREF, signal,
- LqhAddAttrRef::SignalLength, JBB);
-
-}//Dblqh::execTUP_ADD_ATTRREF()
-
-/* **********************> */
-/* TUX_ADD_ATTRREF > */
-/* **********************> */
-void Dblqh::execTUX_ADD_ATTRREF(Signal* signal)
-{
- jamEntry();
- execTUP_ADD_ATTRREF(signal);
-}//Dblqh::execTUX_ADD_ATTRREF
-
-void
-Dblqh::execPREP_DROP_TAB_REQ(Signal* signal){
- jamEntry();
-
- PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
-
- TablerecPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
-
- Uint32 errCode = 0;
- errCode = checkDropTabState(tabPtr.p->tableStatus, GSN_PREP_DROP_TAB_REQ);
- if(errCode != 0){
- jam();
-
- PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->tableId = tabPtr.i;
- ref->errorCode = errCode;
- sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
- PrepDropTabRef::SignalLength, JBB);
- return;
- }
-
- tabPtr.p->tableStatus = Tablerec::PREP_DROP_TABLE_ONGOING;
- tabPtr.p->waitingTC.clear();
- tabPtr.p->waitingDIH.clear();
-
- PrepDropTabConf * conf = (PrepDropTabConf*)signal->getDataPtrSend();
- conf->tableId = tabPtr.i;
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
- PrepDropTabConf::SignalLength, JBB);
-
- signal->theData[0] = ZPREP_DROP_TABLE;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = senderRef;
- signal->theData[3] = senderData;
- checkDropTab(signal);
-}
-
-void
-Dblqh::checkDropTab(Signal* signal){
-
- TablerecPtr tabPtr;
- tabPtr.i = signal->theData[1];
- ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
-
- ndbrequire(tabPtr.p->tableStatus == Tablerec::PREP_DROP_TABLE_ONGOING);
-
- if(tabPtr.p->usageCount > 0){
- jam();
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
- return;
- }
-
- bool lcpDone = true;
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- if(lcpPtr.p->lcpState != LcpRecord::LCP_IDLE){
- jam();
-
- if(lcpPtr.p->currentFragment.lcpFragOrd.tableId == tabPtr.i){
- jam();
- lcpDone = false;
- }
-
- if(lcpPtr.p->lcpQueued &&
- lcpPtr.p->queuedFragment.lcpFragOrd.tableId == tabPtr.i){
- jam();
- lcpDone = false;
- }
- }
-
- if(!lcpDone){
- jam();
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 4);
- return;
- }
-
- tabPtr.p->tableStatus = Tablerec::PREP_DROP_TABLE_DONE;
-
- WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtrSend();
- conf->tableId = tabPtr.i;
- conf->senderRef = reference();
- for(Uint32 i = 1; i<MAX_NDB_NODES; i++){
- if(tabPtr.p->waitingTC.get(i)){
- tabPtr.p->waitingTC.clear(i);
- sendSignal(calcTcBlockRef(i), GSN_WAIT_DROP_TAB_CONF, signal,
- WaitDropTabConf::SignalLength, JBB);
- }
- if(tabPtr.p->waitingDIH.get(i)){
- tabPtr.p->waitingDIH.clear(i);
- sendSignal(calcDihBlockRef(i), GSN_WAIT_DROP_TAB_CONF, signal,
- WaitDropTabConf::SignalLength, JBB);
- }
- }
-}
-
-void
-Dblqh::execWAIT_DROP_TAB_REQ(Signal* signal){
- jamEntry();
- WaitDropTabReq * req = (WaitDropTabReq*)signal->getDataPtr();
-
- TablerecPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
-
- Uint32 senderRef = req->senderRef;
- Uint32 nodeId = refToNode(senderRef);
- Uint32 blockNo = refToBlock(senderRef);
-
- if(tabPtr.p->tableStatus == Tablerec::PREP_DROP_TABLE_ONGOING){
- jam();
- switch(blockNo){
- case DBTC:
- tabPtr.p->waitingTC.set(nodeId);
- break;
- case DBDIH:
- tabPtr.p->waitingDIH.set(nodeId);
- break;
- default:
- ndbrequire(false);
- }
- return;
- }
-
- if(tabPtr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE){
- jam();
- WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtrSend();
- conf->tableId = tabPtr.i;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_WAIT_DROP_TAB_CONF, signal,
- WaitDropTabConf::SignalLength, JBB);
- return;
- }
-
- WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtrSend();
- ref->tableId = tabPtr.i;
- ref->senderRef = reference();
-
- bool ok = false;
- switch(tabPtr.p->tableStatus){
- case Tablerec::TABLE_DEFINED:
- ok = true;
- ref->errorCode = WaitDropTabRef::IllegalTableState;
- break;
- case Tablerec::NOT_DEFINED:
- ok = true;
- ref->errorCode = WaitDropTabRef::NoSuchTable;
- break;
- case Tablerec::ADD_TABLE_ONGOING:
- ok = true;
- ref->errorCode = WaitDropTabRef::IllegalTableState;
- break;
- case Tablerec::PREP_DROP_TABLE_ONGOING:
- case Tablerec::PREP_DROP_TABLE_DONE:
- // Should have been take care of above
- ndbrequire(false);
- }
- ndbrequire(ok);
- ref->tableStatus = tabPtr.p->tableStatus;
- sendSignal(senderRef, GSN_WAIT_DROP_TAB_REF, signal,
- WaitDropTabRef::SignalLength, JBB);
- return;
-}
-
-void
-Dblqh::execDROP_TAB_REQ(Signal* signal){
- jamEntry();
-
- DropTabReq* req = (DropTabReq*)signal->getDataPtr();
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
-
- TablerecPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
-
- do {
- if(req->requestType == DropTabReq::RestartDropTab){
- jam();
- break;
- }
-
- if(req->requestType == DropTabReq::OnlineDropTab){
- jam();
- Uint32 errCode = 0;
- errCode = checkDropTabState(tabPtr.p->tableStatus, GSN_DROP_TAB_REQ);
- if(errCode != 0){
- jam();
-
- DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->tableId = tabPtr.i;
- ref->errorCode = errCode;
- sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
- DropTabRef::SignalLength, JBB);
- return;
- }
- }
-
- removeTable(tabPtr.i);
-
- } while(false);
-
- ndbrequire(tabPtr.p->usageCount == 0);
- tabPtr.p->tableStatus = Tablerec::NOT_DEFINED;
-
- DropTabConf * const dropConf = (DropTabConf *)signal->getDataPtrSend();
- dropConf->senderRef = reference();
- dropConf->senderData = senderData;
- dropConf->tableId = tabPtr.i;
- sendSignal(senderRef, GSN_DROP_TAB_CONF,
- signal, DropTabConf::SignalLength, JBB);
-}
-
-Uint32
-Dblqh::checkDropTabState(Tablerec::TableStatus status, Uint32 gsn) const{
-
- if(gsn == GSN_PREP_DROP_TAB_REQ){
- switch(status){
- case Tablerec::NOT_DEFINED:
- jam();
- // Fall through
- case Tablerec::ADD_TABLE_ONGOING:
- jam();
- return PrepDropTabRef::NoSuchTable;
- break;
- case Tablerec::PREP_DROP_TABLE_ONGOING:
- jam();
- return PrepDropTabRef::PrepDropInProgress;
- break;
- case Tablerec::PREP_DROP_TABLE_DONE:
- jam();
- return PrepDropTabRef::DropInProgress;
- break;
- case Tablerec::TABLE_DEFINED:
- jam();
- return 0;
- break;
- }
- ndbrequire(0);
- }
-
- if(gsn == GSN_DROP_TAB_REQ){
- switch(status){
- case Tablerec::NOT_DEFINED:
- jam();
- // Fall through
- case Tablerec::ADD_TABLE_ONGOING:
- jam();
- return DropTabRef::NoSuchTable;
- break;
- case Tablerec::PREP_DROP_TABLE_ONGOING:
- jam();
- return DropTabRef::PrepDropInProgress;
- break;
- case Tablerec::PREP_DROP_TABLE_DONE:
- jam();
- return 0;
- break;
- case Tablerec::TABLE_DEFINED:
- jam();
- return DropTabRef::DropWoPrep;
- }
- ndbrequire(0);
- }
- ndbrequire(0);
- return RNIL;
-}
-
-void Dblqh::removeTable(Uint32 tableId)
-{
- tabptr.i = tableId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
-
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabptr.p->fragid[i] != ZNIL) {
- jam();
- deleteFragrec(tabptr.p->fragid[i]);
- }//if
- }//for
-}//Dblqh::removeTable()
-
-void
-Dblqh::execALTER_TAB_REQ(Signal* signal)
-{
- jamEntry();
- AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
- const Uint32 changeMask = req->changeMask;
- const Uint32 tableId = req->tableId;
- const Uint32 tableVersion = req->tableVersion;
- const Uint32 gci = req->gci;
- AlterTabReq::RequestType requestType =
- (AlterTabReq::RequestType) req->requestType;
-
- TablerecPtr tablePtr;
- tablePtr.i = tableId;
- ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
- tablePtr.p->schemaVersion = tableVersion;
-
- // Request handled successfully
- AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->changeMask = changeMask;
- conf->tableId = tableId;
- conf->tableVersion = tableVersion;
- conf->gci = gci;
- conf->requestType = requestType;
- sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
- AlterTabConf::SignalLength, JBB);
-}
-
-/* ************************************************************************>>
- * TIME_SIGNAL: Handles time-out of local operations. This is a clean-up
- * handler. If no other measure has succeeded in cleaning up after time-outs
- * or else then this routine will remove the transaction after 120 seconds of
- * inactivity. The check is performed once per 10 second. Sender is QMGR.
- * ************************************************************************>> */
-void Dblqh::execTIME_SIGNAL(Signal* signal)
-{
- jamEntry();
- cLqhTimeOutCount++;
- cLqhTimeOutCheckCount++;
- if (cLqhTimeOutCheckCount < 10) {
- jam();
- return;
- }//if
- cLqhTimeOutCheckCount = 0;
-#ifdef VM_TRACE
- TcConnectionrecPtr tTcConptr;
-
- for (tTcConptr.i = 0; tTcConptr.i < ctcConnectrecFileSize;
- tTcConptr.i++) {
- jam();
- ptrAss(tTcConptr, tcConnectionrec);
- if ((tTcConptr.p->tcTimer != 0) &&
- ((tTcConptr.p->tcTimer + 120) < cLqhTimeOutCount)) {
- ndbout << "Dblqh::execTIME_SIGNAL"<<endl
- << "Timeout found in tcConnectRecord " <<tTcConptr.i<<endl
- << " cLqhTimeOutCount = " << cLqhTimeOutCount << endl
- << " tcTimer="<<tTcConptr.p->tcTimer<<endl
- << " tcTimer+120="<<tTcConptr.p->tcTimer + 120<<endl;
-
- signal->theData[0] = 2307;
- signal->theData[1] = tTcConptr.i;
- execDUMP_STATE_ORD(signal);
-
- // Reset the timer
- tTcConptr.p->tcTimer = 0;
- }//if
- }//for
-#endif
-#ifdef VM_TRACE
- for (lfoPtr.i = 0; lfoPtr.i < clfoFileSize; lfoPtr.i++) {
- ptrAss(lfoPtr, logFileOperationRecord);
- if ((lfoPtr.p->lfoTimer != 0) &&
- ((lfoPtr.p->lfoTimer + 120) < cLqhTimeOutCount)) {
- ndbout << "We have lost LFO record" << endl;
- ndbout << "index = " << lfoPtr.i;
- ndbout << "State = " << lfoPtr.p->lfoState;
- ndbout << " Page No = " << lfoPtr.p->lfoPageNo;
- ndbout << " noPagesRw = " << lfoPtr.p->noPagesRw;
- ndbout << "lfoWordWritten = " << lfoPtr.p->lfoWordWritten << endl;
- lfoPtr.p->lfoTimer = cLqhTimeOutCount;
- }//if
- }//for
-
-#endif
-
-#if 0
- LcpRecordPtr TlcpPtr;
- // Print information about the current local checkpoint
- TlcpPtr.i = 0;
- ptrAss(TlcpPtr, lcpRecord);
- ndbout << "Information about LCP in this LQH" << endl
- << " lcpState="<<TlcpPtr.p->lcpState<<endl
- << " firstLcpLocAcc="<<TlcpPtr.p->firstLcpLocAcc<<endl
- << " firstLcpLocTup="<<TlcpPtr.p->firstLcpLocTup<<endl
- << " lcpAccptr="<<TlcpPtr.p->lcpAccptr<<endl
- << " lastFragmentFlag="<<TlcpPtr.p->lastFragmentFlag<<endl
- << " lcpQueued="<<TlcpPtr.p->lcpQueued<<endl
- << " reportEmptyref="<< TlcpPtr.p->reportEmptyRef<<endl
- << " reportEmpty="<<TlcpPtr.p->reportEmpty<<endl;
-#endif
-}//Dblqh::execTIME_SIGNAL()
-
-/* ######################################################################### */
-/* ####### EXECUTION MODULE ####### */
-/* THIS MODULE HANDLES THE RECEPTION OF LQHKEYREQ AND ALL PROCESSING */
-/* OF OPERATIONS ON BEHALF OF THIS REQUEST. THIS DOES ALSO INVOLVE */
-/* RECEPTION OF VARIOUS TYPES OF ATTRINFO AND KEYINFO. IT DOES ALSO */
-/* INVOLVE COMMUNICATION WITH ACC AND TUP. */
-/* ######################################################################### */
-
-void Dblqh::noFreeRecordLab(Signal* signal,
- const LqhKeyReq * lqhKeyReq,
- Uint32 errCode)
-{
- jamEntry();
- const Uint32 transid1 = lqhKeyReq->transId1;
- const Uint32 transid2 = lqhKeyReq->transId2;
- const Uint32 reqInfo = lqhKeyReq->requestInfo;
-
- if(errCode == ZNO_FREE_MARKER_RECORDS_ERROR ||
- errCode == ZNODE_SHUTDOWN_IN_PROGESS){
- releaseTcrec(signal, tcConnectptr);
- }
-
- if (LqhKeyReq::getSimpleFlag(reqInfo) &&
- LqhKeyReq::getOperation(reqInfo) == ZREAD){
- jam();
- ndbrequire(LqhKeyReq::getApplicationAddressFlag(reqInfo));
- const Uint32 apiRef = lqhKeyReq->variableData[0];
- const Uint32 apiOpRec = lqhKeyReq->variableData[1];
-
- TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
-
- tcKeyRef->connectPtr = apiOpRec;
- tcKeyRef->transId[0] = transid1;
- tcKeyRef->transId[1] = transid2;
- tcKeyRef->errorCode = errCode;
- sendTCKEYREF(signal, apiRef, signal->getSendersBlockRef(), 0);
- } else {
- jam();
-
- const Uint32 clientPtr = lqhKeyReq->clientConnectPtr;
- Uint32 TcOprec = clientPtr;
- if(LqhKeyReq::getSameClientAndTcFlag(reqInfo) == 1){
- if(LqhKeyReq::getApplicationAddressFlag(reqInfo))
- TcOprec = lqhKeyReq->variableData[2];
- else
- TcOprec = lqhKeyReq->variableData[0];
- }
-
- LqhKeyRef * const ref = (LqhKeyRef*)signal->getDataPtrSend();
- ref->userRef = clientPtr;
- ref->connectPtr = TcOprec;
- ref->errorCode = errCode;
- ref->transId1 = transid1;
- ref->transId2 = transid2;
- sendSignal(signal->senderBlockRef(), GSN_LQHKEYREF, signal,
- LqhKeyRef::SignalLength, JBB);
- }//if
- return;
-}//Dblqh::noFreeRecordLab()
-
-void Dblqh::LQHKEY_abort(Signal* signal, int errortype)
-{
- switch (errortype) {
- case 0:
- jam();
- terrorCode = ZCOPY_NODE_ERROR;
- break;
- case 1:
- jam();
- terrorCode = ZNO_FREE_LQH_CONNECTION;
- break;
- case 2:
- jam();
- terrorCode = signal->theData[1];
- break;
- case 3:
- jam();
- ndbrequire((tcConnectptr.p->transactionState == TcConnectionrec::WAIT_ACC_ABORT) ||
- (tcConnectptr.p->transactionState == TcConnectionrec::ABORT_STOPPED) ||
- (tcConnectptr.p->transactionState == TcConnectionrec::ABORT_QUEUED));
- return;
- break;
- case 4:
- jam();
- if(tabptr.p->tableStatus == Tablerec::NOT_DEFINED){
- jam();
- terrorCode = ZTABLE_NOT_DEFINED;
- } else if (tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_ONGOING ||
- tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE){
- jam();
- terrorCode = ZDROP_TABLE_IN_PROGRESS;
- } else {
- ndbrequire(0);
- }
- break;
- case 5:
- jam();
- terrorCode = ZINVALID_SCHEMA_VERSION;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- abortErrorLab(signal);
-}//Dblqh::LQHKEY_abort()
-
-void Dblqh::LQHKEY_error(Signal* signal, int errortype)
-{
- switch (errortype) {
- case 0:
- jam();
- break;
- case 1:
- jam();
- break;
- case 2:
- jam();
- break;
- case 3:
- jam();
- break;
- case 4:
- jam();
- break;
- case 5:
- jam();
- break;
- case 6:
- jam();
- break;
- default:
- jam();
- break;
- }//switch
- ndbrequire(false);
-}//Dblqh::LQHKEY_error()
-
-void Dblqh::execLQHKEYREF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- terrorCode = signal->theData[2];
- Uint32 transid1 = signal->theData[3];
- Uint32 transid2 = signal->theData[4];
- if (tcConnectptr.i >= ctcConnectrecFileSize) {
- errorReport(signal, 3);
- return;
- }//if
-/*------------------------------------------------------------------*/
-/* WE HAVE TO CHECK THAT THE SIGNAL DO NOT BELONG TO SOMETHING*/
-/* REMOVED DUE TO A TIME-OUT. */
-/*------------------------------------------------------------------*/
- ptrAss(tcConnectptr, tcConnectionrec);
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- switch (regTcPtr->connectState) {
- case TcConnectionrec::CONNECTED:
- jam();
- if ((regTcPtr->transid[0] != transid1) ||
- (regTcPtr->transid[1] != transid2)) {
- warningReport(signal, 14);
- return;
- }//if
- if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
- warningReport(signal, 15);
- return;
- }//if
- abortErrorLab(signal);
- return;
- break;
- case TcConnectionrec::LOG_CONNECTED:
- jam();
- logLqhkeyrefLab(signal);
- return;
- break;
- case TcConnectionrec::COPY_CONNECTED:
- jam();
- copyLqhKeyRefLab(signal);
- return;
- break;
- default:
- warningReport(signal, 16);
- return;
- break;
- }//switch
-}//Dblqh::execLQHKEYREF()
-
-/* -------------------------------------------------------------------------- */
-/* ------- ENTER PACKED_SIGNAL ------- */
-/* Execution of packed signal. The packed signal can contain COMMIT, COMPLETE */
-/* or LQHKEYCONF signals. These signals will be executed by their resp. exec */
-/* functions. */
-/* -------------------------------------------------------------------------- */
-void Dblqh::execPACKED_SIGNAL(Signal* signal)
-{
- Uint32 Tstep = 0;
- Uint32 Tlength;
- Uint32 TpackedData[28];
- Uint32 sig0, sig1, sig2, sig3 ,sig4, sig5, sig6;
-
- jamEntry();
- Tlength = signal->length();
- ndbrequire(Tlength <= 25);
- MEMCOPY_NO_WORDS(&TpackedData[0], &signal->theData[0], Tlength);
- while (Tlength > Tstep) {
- switch (TpackedData[Tstep] >> 28) {
- case ZCOMMIT:
- jam();
- sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
- sig1 = TpackedData[Tstep + 1];
- sig2 = TpackedData[Tstep + 2];
- sig3 = TpackedData[Tstep + 3];
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->theData[2] = sig2;
- signal->theData[3] = sig3;
- signal->header.theLength = 4;
- execCOMMIT(signal);
- Tstep += 4;
- break;
- case ZCOMPLETE:
- jam();
- sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
- sig1 = TpackedData[Tstep + 1];
- sig2 = TpackedData[Tstep + 2];
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->theData[2] = sig2;
- signal->header.theLength = 3;
- execCOMPLETE(signal);
- Tstep += 3;
- break;
- case ZLQHKEYCONF: {
- jam();
- LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
-
- sig0 = TpackedData[Tstep + 0] & 0x0FFFFFFF;
- sig1 = TpackedData[Tstep + 1];
- sig2 = TpackedData[Tstep + 2];
- sig3 = TpackedData[Tstep + 3];
- sig4 = TpackedData[Tstep + 4];
- sig5 = TpackedData[Tstep + 5];
- sig6 = TpackedData[Tstep + 6];
- lqhKeyConf->connectPtr = sig0;
- lqhKeyConf->opPtr = sig1;
- lqhKeyConf->userRef = sig2;
- lqhKeyConf->readLen = sig3;
- lqhKeyConf->transId1 = sig4;
- lqhKeyConf->transId2 = sig5;
- lqhKeyConf->noFiredTriggers = sig6;
- execLQHKEYCONF(signal);
- Tstep += LqhKeyConf::SignalLength;
- break;
- }
- case ZREMOVE_MARKER:
- jam();
- sig0 = TpackedData[Tstep + 1];
- sig1 = TpackedData[Tstep + 2];
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->header.theLength = 2;
- execREMOVE_MARKER_ORD(signal);
- Tstep += 3;
- break;
- default:
- ndbrequire(false);
- return;
- }//switch
- }//while
- ndbrequire(Tlength == Tstep);
- return;
-}//Dblqh::execPACKED_SIGNAL()
-
-void
-Dblqh::execREMOVE_MARKER_ORD(Signal* signal)
-{
- CommitAckMarker key;
- key.transid1 = signal->theData[0];
- key.transid2 = signal->theData[1];
- jamEntry();
-
- CommitAckMarkerPtr removedPtr;
- m_commitAckMarkerHash.remove(removedPtr, key);
-#if defined VM_TRACE || defined ERROR_INSERT
- ndbrequire(removedPtr.i != RNIL);
- m_commitAckMarkerPool.release(removedPtr);
-#else
- if (removedPtr.i != RNIL)
- {
- jam();
- m_commitAckMarkerPool.release(removedPtr);
- }
-#endif
-#ifdef MARKER_TRACE
- ndbout_c("Rem marker[%.8x %.8x]", key.transid1, key.transid2);
-#endif
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* ------- ENTER SEND_PACKED ------- */
-/* Used to force a packed signal to be sent if local signal buffer is not */
-/* empty. */
-/* -------------------------------------------------------------------------- */
-void Dblqh::execSEND_PACKED(Signal* signal)
-{
- HostRecordPtr Thostptr;
- UintR i;
- UintR TpackedListIndex = cpackedListIndex;
- jamEntry();
- for (i = 0; i < TpackedListIndex; i++) {
- Thostptr.i = cpackedList[i];
- ptrAss(Thostptr, hostRecord);
- jam();
- ndbrequire(Thostptr.i - 1 < MAX_NDB_NODES - 1);
- if (Thostptr.p->noOfPackedWordsLqh > 0) {
- jam();
- sendPackedSignalLqh(signal, Thostptr.p);
- }//if
- if (Thostptr.p->noOfPackedWordsTc > 0) {
- jam();
- sendPackedSignalTc(signal, Thostptr.p);
- }//if
- Thostptr.p->inPackedList = false;
- }//for
- cpackedListIndex = 0;
- return;
-}//Dblqh::execSEND_PACKED()
-
-void
-Dblqh::updatePackedList(Signal* signal, HostRecord * ahostptr, Uint16 hostId)
-{
- Uint32 TpackedListIndex = cpackedListIndex;
- if (ahostptr->inPackedList == false) {
- jam();
- ahostptr->inPackedList = true;
- cpackedList[TpackedListIndex] = hostId;
- cpackedListIndex = TpackedListIndex + 1;
- }//if
-}//Dblqh::updatePackedList()
-
-void
-Dblqh::execREAD_PSEUDO_REQ(Signal* signal){
- jamEntry();
- TcConnectionrecPtr regTcPtr;
- regTcPtr.i = signal->theData[0];
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
-
- if (signal->theData[1] == AttributeHeader::RANGE_NO) {
- signal->theData[0] = regTcPtr.p->m_scan_curr_range_no;
- }
- else if (signal->theData[1] != AttributeHeader::RECORDS_IN_RANGE)
- {
- jam();
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr.p->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
-
- signal->theData[0] = regFragptr.p->accFragptr;
- EXECUTE_DIRECT(DBACC, GSN_READ_PSEUDO_REQ, signal, 2);
- }
- else
- {
- jam();
- // scanptr gets reset somewhere within the timeslice
- ScanRecordPtr tmp;
- tmp.i = regTcPtr.p->tcScanRec;
- c_scanRecordPool.getPtr(tmp);
- signal->theData[0] = tmp.p->scanAccPtr;
- EXECUTE_DIRECT(DBTUX, GSN_READ_PSEUDO_REQ, signal, 2);
- }
-}
-
-/* ************>> */
-/* TUPKEYCONF > */
-/* ************>> */
-void Dblqh::execTUPKEYCONF(Signal* signal)
-{
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
- Uint32 tcIndex = tupKeyConf->userPtr;
- jamEntry();
- tcConnectptr.i = tcIndex;
- ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
- TcConnectionrec * regTcPtr = tcConnectptr.p;
- Uint32 activeCreat = regTcPtr->activeCreat;
-
- FragrecordPtr regFragptr;
- regFragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
- fragptr = regFragptr;
-
- 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:
- jam();
- copyTupkeyConfLab(signal);
- break;
- case TcConnectionrec::SCAN_TUPKEY:
- jam();
- scanTupkeyConfLab(signal);
- break;
- case TcConnectionrec::WAIT_TUP_TO_ABORT:
- jam();
-/* ------------------------------------------------------------------------- */
-// Abort was not ready to start until this signal came back. Now we are ready
-// to start the abort.
-/* ------------------------------------------------------------------------- */
- if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
- {
- jam();
- ndbrequire(regTcPtr->m_nr_delete.m_cnt);
- regTcPtr->m_nr_delete.m_cnt--;
- if (regTcPtr->m_nr_delete.m_cnt)
- {
- jam();
- /**
- * Let operation wait for pending NR operations
- * even for before writing log...(as it's simpler)
- */
-
-#ifdef VM_TRACE
- /**
- * Only disk table can have pending ops...
- */
- TablerecPtr tablePtr;
- tablePtr.i = regTcPtr->tableref;
- ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
- ndbrequire(tablePtr.p->m_disk_table);
-#endif
- return;
- }
- }
-
- abortCommonLab(signal);
- break;
- case TcConnectionrec::WAIT_ACC_ABORT:
- case TcConnectionrec::ABORT_QUEUED:
- jam();
-/* ------------------------------------------------------------------------- */
-/* IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
-/* ------------------------------------------------------------------------- */
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
-
-}//Dblqh::execTUPKEYCONF()
-
-/* ************> */
-/* TUPKEYREF > */
-/* ************> */
-void Dblqh::execTUPKEYREF(Signal* signal)
-{
- const TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtr();
-
- jamEntry();
- tcConnectptr.i = tupKeyRef->userRef;
- terrorCode = tupKeyRef->errorCode;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- TcConnectionrec* regTcPtr = tcConnectptr.p;
- Uint32 activeCreat = regTcPtr->activeCreat;
-
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
- fragptr = regFragptr;
-
- TRACE_OP(regTcPtr, "TUPKEYREF");
-
- if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
- {
- jam();
- ndbrequire(regTcPtr->m_nr_delete.m_cnt);
- regTcPtr->m_nr_delete.m_cnt--;
- ndbassert(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP ||
- regTcPtr->transactionState ==TcConnectionrec::WAIT_TUP_TO_ABORT);
- }
-
- switch (tcConnectptr.p->transactionState) {
- case TcConnectionrec::WAIT_TUP:
- jam();
- abortErrorLab(signal);
- break;
- case TcConnectionrec::COPY_TUPKEY:
- ndbrequire(false);
- break;
- case TcConnectionrec::SCAN_TUPKEY:
- jam();
- scanTupkeyRefLab(signal);
- break;
- case TcConnectionrec::WAIT_TUP_TO_ABORT:
- jam();
-/* ------------------------------------------------------------------------- */
-// Abort was not ready to start until this signal came back. Now we are ready
-// to start the abort.
-/* ------------------------------------------------------------------------- */
- abortCommonLab(signal);
- break;
- case TcConnectionrec::WAIT_ACC_ABORT:
- case TcConnectionrec::ABORT_QUEUED:
- jam();
-/* ------------------------------------------------------------------------- */
-/* IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
-/* ------------------------------------------------------------------------- */
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
-}//Dblqh::execTUPKEYREF()
-
-void Dblqh::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
-{
- Uint32 noOfWords = ahostptr->noOfPackedWordsLqh;
- BlockReference hostRef = ahostptr->hostLqhBlockRef;
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &ahostptr->packedWordsLqh[0],
- noOfWords);
- sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
- ahostptr->noOfPackedWordsLqh = 0;
-}//Dblqh::sendPackedSignalLqh()
-
-void Dblqh::sendPackedSignalTc(Signal* signal, HostRecord * ahostptr)
-{
- Uint32 noOfWords = ahostptr->noOfPackedWordsTc;
- BlockReference hostRef = ahostptr->hostTcBlockRef;
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &ahostptr->packedWordsTc[0],
- noOfWords);
- sendSignal(hostRef, GSN_PACKED_SIGNAL, signal, noOfWords, JBB);
- ahostptr->noOfPackedWordsTc = 0;
-}//Dblqh::sendPackedSignalTc()
-
-void Dblqh::sendCommitLqh(Signal* signal, BlockReference alqhBlockref)
-{
- HostRecordPtr Thostptr;
- Thostptr.i = refToNode(alqhBlockref);
- ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
- if (Thostptr.p->noOfPackedWordsLqh > 21) {
- jam();
- sendPackedSignalLqh(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
- Uint32 pos = Thostptr.p->noOfPackedWordsLqh;
- Uint32 ptrAndType = tcConnectptr.p->clientConnectrec | (ZCOMMIT << 28);
- Uint32 gci = tcConnectptr.p->gci;
- Uint32 transid1 = tcConnectptr.p->transid[0];
- Uint32 transid2 = tcConnectptr.p->transid[1];
- Thostptr.p->packedWordsLqh[pos] = ptrAndType;
- Thostptr.p->packedWordsLqh[pos + 1] = gci;
- Thostptr.p->packedWordsLqh[pos + 2] = transid1;
- Thostptr.p->packedWordsLqh[pos + 3] = transid2;
- Thostptr.p->noOfPackedWordsLqh = pos + 4;
-}//Dblqh::sendCommitLqh()
-
-void Dblqh::sendCompleteLqh(Signal* signal, BlockReference alqhBlockref)
-{
- HostRecordPtr Thostptr;
- Thostptr.i = refToNode(alqhBlockref);
- ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
- if (Thostptr.p->noOfPackedWordsLqh > 22) {
- jam();
- sendPackedSignalLqh(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
- Uint32 pos = Thostptr.p->noOfPackedWordsLqh;
- Uint32 ptrAndType = tcConnectptr.p->clientConnectrec | (ZCOMPLETE << 28);
- Uint32 transid1 = tcConnectptr.p->transid[0];
- Uint32 transid2 = tcConnectptr.p->transid[1];
- Thostptr.p->packedWordsLqh[pos] = ptrAndType;
- Thostptr.p->packedWordsLqh[pos + 1] = transid1;
- Thostptr.p->packedWordsLqh[pos + 2] = transid2;
- Thostptr.p->noOfPackedWordsLqh = pos + 3;
-}//Dblqh::sendCompleteLqh()
-
-void Dblqh::sendCommittedTc(Signal* signal, BlockReference atcBlockref)
-{
- HostRecordPtr Thostptr;
- Thostptr.i = refToNode(atcBlockref);
- ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
- if (Thostptr.p->noOfPackedWordsTc > 22) {
- jam();
- sendPackedSignalTc(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
- Uint32 pos = Thostptr.p->noOfPackedWordsTc;
- Uint32 ptrAndType = tcConnectptr.p->clientConnectrec | (ZCOMMITTED << 28);
- Uint32 transid1 = tcConnectptr.p->transid[0];
- Uint32 transid2 = tcConnectptr.p->transid[1];
- Thostptr.p->packedWordsTc[pos] = ptrAndType;
- Thostptr.p->packedWordsTc[pos + 1] = transid1;
- Thostptr.p->packedWordsTc[pos + 2] = transid2;
- Thostptr.p->noOfPackedWordsTc = pos + 3;
-}//Dblqh::sendCommittedTc()
-
-void Dblqh::sendCompletedTc(Signal* signal, BlockReference atcBlockref)
-{
- HostRecordPtr Thostptr;
- Thostptr.i = refToNode(atcBlockref);
- ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
- if (Thostptr.p->noOfPackedWordsTc > 22) {
- jam();
- sendPackedSignalTc(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
- Uint32 pos = Thostptr.p->noOfPackedWordsTc;
- Uint32 ptrAndType = tcConnectptr.p->clientConnectrec | (ZCOMPLETED << 28);
- Uint32 transid1 = tcConnectptr.p->transid[0];
- Uint32 transid2 = tcConnectptr.p->transid[1];
- Thostptr.p->packedWordsTc[pos] = ptrAndType;
- Thostptr.p->packedWordsTc[pos + 1] = transid1;
- Thostptr.p->packedWordsTc[pos + 2] = transid2;
- Thostptr.p->noOfPackedWordsTc = pos + 3;
-}//Dblqh::sendCompletedTc()
-
-void Dblqh::sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref)
-{
- LqhKeyConf* lqhKeyConf;
- HostRecordPtr Thostptr;
-
- bool packed= true;
- Thostptr.i = refToNode(atcBlockref);
- ptrCheckGuard(Thostptr, chostFileSize, hostRecord);
- if (refToBlock(atcBlockref) == DBTC) {
- jam();
-/*******************************************************************
-// This signal was intended for DBTC as part of the normal transaction
-// execution.
-********************************************************************/
- if (Thostptr.p->noOfPackedWordsTc > (25 - LqhKeyConf::SignalLength)) {
- jam();
- sendPackedSignalTc(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
- lqhKeyConf = (LqhKeyConf *)
- &Thostptr.p->packedWordsTc[Thostptr.p->noOfPackedWordsTc];
- Thostptr.p->noOfPackedWordsTc += LqhKeyConf::SignalLength;
- } else if(refToBlock(atcBlockref) == DBLQH){
- jam();
-/*******************************************************************
-// This signal was intended for DBLQH as part of log execution or
-// node recovery.
-********************************************************************/
- if (Thostptr.p->noOfPackedWordsLqh > (25 - LqhKeyConf::SignalLength)) {
- jam();
- sendPackedSignalLqh(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
- lqhKeyConf = (LqhKeyConf *)
- &Thostptr.p->packedWordsLqh[Thostptr.p->noOfPackedWordsLqh];
- Thostptr.p->noOfPackedWordsLqh += LqhKeyConf::SignalLength;
- } else {
- packed= false;
- lqhKeyConf = (LqhKeyConf *)signal->getDataPtrSend();
- }
- Uint32 ptrAndType = tcConnectptr.i | (ZLQHKEYCONF << 28);
- Uint32 tcOprec = tcConnectptr.p->tcOprec;
- Uint32 ownRef = cownref;
- Uint32 readlenAi = tcConnectptr.p->readlenAi;
- Uint32 transid1 = tcConnectptr.p->transid[0];
- Uint32 transid2 = tcConnectptr.p->transid[1];
- Uint32 noFiredTriggers = tcConnectptr.p->noFiredTriggers;
- lqhKeyConf->connectPtr = ptrAndType;
- lqhKeyConf->opPtr = tcOprec;
- lqhKeyConf->userRef = ownRef;
- lqhKeyConf->readLen = readlenAi;
- lqhKeyConf->transId1 = transid1;
- lqhKeyConf->transId2 = transid2;
- lqhKeyConf->noFiredTriggers = noFiredTriggers;
-
- if(!packed)
- {
- lqhKeyConf->connectPtr = tcConnectptr.i;
- if(Thostptr.i == 0 || Thostptr.i == getOwnNodeId())
- {
- EXECUTE_DIRECT(refToBlock(atcBlockref), GSN_LQHKEYCONF,
- signal, LqhKeyConf::SignalLength);
- }
- else
- {
- sendSignal(atcBlockref, GSN_LQHKEYCONF,
- signal, LqhKeyConf::SignalLength, JBB);
- }
- }
-}//Dblqh::sendLqhkeyconfTc()
-
-/* ************************************************************************>>
- * KEYINFO: Get tuple request from DBTC. Next step is to contact DBACC to get
- * key to tuple if all key/attrinfo has been received, else for more attrinfo
- * signals.
- * ************************************************************************>> */
-void Dblqh::execKEYINFO(Signal* signal)
-{
- Uint32 tcOprec = signal->theData[0];
- Uint32 transid1 = signal->theData[1];
- Uint32 transid2 = signal->theData[2];
- jamEntry();
- if (findTransaction(transid1, transid2, tcOprec) != ZOK) {
- jam();
- return;
- }//if
-
- receive_keyinfo(signal,
- signal->theData+KeyInfo::HeaderLength,
- signal->getLength()-KeyInfo::HeaderLength);
-}
-
-void
-Dblqh::receive_keyinfo(Signal* signal,
- Uint32 * data, Uint32 len)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- TcConnectionrec::TransactionState state = regTcPtr->transactionState;
- if (state != TcConnectionrec::WAIT_TUPKEYINFO &&
- state != TcConnectionrec::WAIT_SCAN_AI)
- {
- jam();
-/*****************************************************************************/
-/* TRANSACTION WAS ABORTED, THIS IS MOST LIKELY A SIGNAL BELONGING TO THE */
-/* ABORTED TRANSACTION. THUS IGNORE THE SIGNAL. */
-/*****************************************************************************/
- return;
- }//if
-
- Uint32 errorCode =
- handleLongTupKey(signal, data, len);
-
- if (errorCode != 0) {
- if (errorCode == 1) {
- jam();
- return;
- }//if
- jam();
- terrorCode = errorCode;
- if(state == TcConnectionrec::WAIT_TUPKEYINFO)
- abortErrorLab(signal);
- else
- abort_scan(signal, regTcPtr->tcScanRec, errorCode);
- return;
- }//if
- if(state == TcConnectionrec::WAIT_TUPKEYINFO)
- {
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
- fragptr = regFragptr;
- endgettupkeyLab(signal);
- }
- return;
-}//Dblqh::execKEYINFO()
-
-/* ------------------------------------------------------------------------- */
-/* FILL IN KEY DATA INTO DATA BUFFERS. */
-/* ------------------------------------------------------------------------- */
-Uint32 Dblqh::handleLongTupKey(Signal* signal,
- Uint32* dataPtr,
- Uint32 len)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 dataPos = 0;
- Uint32 total = regTcPtr->save1 + len;
- Uint32 primKeyLen = regTcPtr->primKeyLen;
- while (dataPos < len) {
- if (cfirstfreeDatabuf == RNIL) {
- jam();
- return ZGET_DATAREC_ERROR;
- }//if
- seizeTupkeybuf(signal);
- Databuf * const regDataPtr = databufptr.p;
- Uint32 data0 = dataPtr[dataPos];
- Uint32 data1 = dataPtr[dataPos + 1];
- Uint32 data2 = dataPtr[dataPos + 2];
- Uint32 data3 = dataPtr[dataPos + 3];
- regDataPtr->data[0] = data0;
- regDataPtr->data[1] = data1;
- regDataPtr->data[2] = data2;
- regDataPtr->data[3] = data3;
- dataPos += 4;
- }
-
- regTcPtr->save1 = total;
- return (total >= primKeyLen ? 0 : 1);
-}//Dblqh::handleLongTupKey()
-
-/* ------------------------------------------------------------------------- */
-/* ------- HANDLE ATTRINFO SIGNALS ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ************************************************************************>> */
-/* ATTRINFO: Continuation of KEYINFO signal (except for scans that do not use*/
-/* any KEYINFO). When all key and attribute info is received we contact DBACC*/
-/* for index handling. */
-/* ************************************************************************>> */
-void Dblqh::execATTRINFO(Signal* signal)
-{
- Uint32 tcOprec = signal->theData[0];
- Uint32 transid1 = signal->theData[1];
- Uint32 transid2 = signal->theData[2];
- jamEntry();
- if (findTransaction(transid1,
- transid2,
- tcOprec) != ZOK) {
- jam();
- return;
- }//if
-
- receive_attrinfo(signal,
- signal->getDataPtrSend()+AttrInfo::HeaderLength,
- signal->getLength()-AttrInfo::HeaderLength);
-}//Dblqh::execATTRINFO()
-
-void
-Dblqh::receive_attrinfo(Signal* signal, Uint32 * dataPtr, Uint32 length)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 totReclenAi = regTcPtr->totReclenAi;
- Uint32 currReclenAi = regTcPtr->currReclenAi + length;
- regTcPtr->currReclenAi = currReclenAi;
- if (totReclenAi == currReclenAi) {
- switch (regTcPtr->transactionState) {
- case TcConnectionrec::WAIT_ATTR:
- {
- jam();
- fragptr.i = regTcPtr->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- lqhAttrinfoLab(signal, dataPtr, length);
- endgettupkeyLab(signal);
- return;
- break;
- }
- case TcConnectionrec::WAIT_SCAN_AI:
- jam();
- scanAttrinfoLab(signal, dataPtr, length);
- return;
- break;
- case TcConnectionrec::WAIT_TUP_TO_ABORT:
- case TcConnectionrec::LOG_ABORT_QUEUED:
- case TcConnectionrec::ABORT_QUEUED:
- case TcConnectionrec::ABORT_STOPPED:
- case TcConnectionrec::WAIT_ACC_ABORT:
- case TcConnectionrec::WAIT_AI_AFTER_ABORT:
- jam();
- aiStateErrorCheckLab(signal, dataPtr,length);
- return;
- break;
- default:
- jam();
- ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
- break;
- }//switch
- } else if (currReclenAi < totReclenAi) {
- jam();
- switch (regTcPtr->transactionState) {
- case TcConnectionrec::WAIT_ATTR:
- jam();
- lqhAttrinfoLab(signal, dataPtr, length);
- return;
- break;
- case TcConnectionrec::WAIT_SCAN_AI:
- jam();
- scanAttrinfoLab(signal, dataPtr, length);
- return;
- break;
- case TcConnectionrec::WAIT_TUP_TO_ABORT:
- case TcConnectionrec::LOG_ABORT_QUEUED:
- case TcConnectionrec::ABORT_QUEUED:
- case TcConnectionrec::ABORT_STOPPED:
- case TcConnectionrec::WAIT_ACC_ABORT:
- case TcConnectionrec::WAIT_AI_AFTER_ABORT:
- jam();
- aiStateErrorCheckLab(signal, dataPtr, length);
- return;
- break;
- default:
- jam();
- ndbrequire(regTcPtr->abortState != TcConnectionrec::ABORT_IDLE);
- break;
- }//switch
- } else {
- switch (regTcPtr->transactionState) {
- case TcConnectionrec::WAIT_SCAN_AI:
- jam();
- scanAttrinfoLab(signal, dataPtr, length);
- return;
- break;
- default:
- ndbout_c("%d", regTcPtr->transactionState);
- ndbrequire(false);
- break;
- }//switch
- }//if
- return;
-}
-
-/* ************************************************************************>> */
-/* TUP_ATTRINFO: Interpreted execution in DBTUP generates redo-log info */
-/* which is sent back to DBLQH for logging. This is because the decision */
-/* to execute or not is made in DBTUP and thus we cannot start logging until */
-/* DBTUP part has been run. */
-/* ************************************************************************>> */
-void Dblqh::execTUP_ATTRINFO(Signal* signal)
-{
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- Uint32 length = signal->length() - 3;
- Uint32 tcIndex = signal->theData[0];
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- jamEntry();
- tcConnectptr.i = tcIndex;
- ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
- ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_TUP);
- if (saveTupattrbuf(signal, &signal->theData[3], length) == ZOK) {
- return;
- } else {
- jam();
-/* ------------------------------------------------------------------------- */
-/* WE ARE WAITING FOR RESPONSE FROM TUP HERE. THUS WE NEED TO */
-/* GO THROUGH THE STATE MACHINE FOR THE OPERATION. */
-/* ------------------------------------------------------------------------- */
- localAbortStateHandlerLab(signal);
- }//if
-}//Dblqh::execTUP_ATTRINFO()
-
-/* ------------------------------------------------------------------------- */
-/* ------- HANDLE ATTRINFO FROM LQH ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->operation != ZREAD) {
- if (regTcPtr->operation != ZDELETE)
- {
- if (regTcPtr->opExec != 1) {
- if (saveTupattrbuf(signal, dataPtr, length) == ZOK) {
- ;
- } else {
- jam();
-/* ------------------------------------------------------------------------- */
-/* WE MIGHT BE WAITING FOR RESPONSE FROM SOME BLOCK HERE. THUS WE NEED TO */
-/* GO THROUGH THE STATE MACHINE FOR THE OPERATION. */
-/* ------------------------------------------------------------------------- */
- localAbortStateHandlerLab(signal);
- return;
- }//if
- }//if
- }//if
- }
- c_tup->receive_attrinfo(signal, regTcPtr->tupConnectrec, dataPtr, length);
-}//Dblqh::lqhAttrinfoLab()
-
-/* ------------------------------------------------------------------------- */
-/* ------ FIND TRANSACTION BY USING HASH TABLE ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-int Dblqh::findTransaction(UintR Transid1, UintR Transid2, UintR TcOprec)
-{
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- TcConnectionrecPtr locTcConnectptr;
-
- Uint32 ThashIndex = (Transid1 ^ TcOprec) & 1023;
- locTcConnectptr.i = ctransidHash[ThashIndex];
- while (locTcConnectptr.i != RNIL) {
- ptrCheckGuard(locTcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
- if ((locTcConnectptr.p->transid[0] == Transid1) &&
- (locTcConnectptr.p->transid[1] == Transid2) &&
- (locTcConnectptr.p->tcOprec == TcOprec)) {
-/* FIRST PART OF TRANSACTION CORRECT */
-/* SECOND PART ALSO CORRECT */
-/* THE OPERATION RECORD POINTER IN TC WAS ALSO CORRECT */
- jam();
- tcConnectptr.i = locTcConnectptr.i;
- tcConnectptr.p = locTcConnectptr.p;
- return (int)ZOK;
- }//if
- jam();
-/* THIS WAS NOT THE TRANSACTION WHICH WAS SOUGHT */
- locTcConnectptr.i = locTcConnectptr.p->nextHashRec;
- }//while
-/* WE DID NOT FIND THE TRANSACTION, REPORT NOT FOUND */
- return (int)ZNOT_FOUND;
-}//Dblqh::findTransaction()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SAVE ATTRINFO FROM TUP IN ATTRINBUF ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-int Dblqh::saveTupattrbuf(Signal* signal, Uint32* dataPtr, Uint32 len)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- while(len)
- {
- Uint32 length = len > AttrInfo::DataLength ? AttrInfo::DataLength : len;
- Uint32 tfirstfreeAttrinbuf = cfirstfreeAttrinbuf;
- Uint32 currTupAiLen = regTcPtr->currTupAiLen;
- if (tfirstfreeAttrinbuf == RNIL) {
- jam();
- terrorCode = ZGET_ATTRINBUF_ERROR;
- return ZGET_ATTRINBUF_ERROR;
- }//if
- seizeAttrinbuf(signal);
- Attrbuf * const regAttrPtr = attrinbufptr.p;
- MEMCOPY_NO_WORDS(&regAttrPtr->attrbuf[0], dataPtr, length);
- regTcPtr->currTupAiLen = currTupAiLen + length;
- regAttrPtr->attrbuf[ZINBUF_DATA_LEN] = length;
-
- len -= length;
- dataPtr += length;
- }
- return ZOK;
-}//Dblqh::saveTupattrbuf()
-
-/* ==========================================================================
- * ======= SEIZE ATTRIBUTE IN BUFFER =======
- *
- * GET A NEW ATTRINBUF AND SETS ATTRINBUFPTR.
- * ========================================================================= */
-void Dblqh::seizeAttrinbuf(Signal* signal)
-{
- AttrbufPtr tmpAttrinbufptr;
- AttrbufPtr regAttrinbufptr;
- Attrbuf *regAttrbuf = attrbuf;
- Uint32 tattrinbufFileSize = cattrinbufFileSize;
-
- regAttrinbufptr.i = seize_attrinbuf();
- tmpAttrinbufptr.i = tcConnectptr.p->lastAttrinbuf;
- ptrCheckGuard(regAttrinbufptr, tattrinbufFileSize, regAttrbuf);
- tcConnectptr.p->lastAttrinbuf = regAttrinbufptr.i;
- regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN] = 0;
- if (tmpAttrinbufptr.i == RNIL) {
- jam();
- tcConnectptr.p->firstAttrinbuf = regAttrinbufptr.i;
- } else {
- jam();
- ptrCheckGuard(tmpAttrinbufptr, tattrinbufFileSize, regAttrbuf);
- tmpAttrinbufptr.p->attrbuf[ZINBUF_NEXT] = regAttrinbufptr.i;
- }//if
- regAttrinbufptr.p->attrbuf[ZINBUF_NEXT] = RNIL;
- attrinbufptr = regAttrinbufptr;
-}//Dblqh::seizeAttrinbuf()
-
-/* ==========================================================================
- * ======= SEIZE TC CONNECT RECORD =======
- *
- * GETS A NEW TC CONNECT RECORD FROM FREELIST.
- * ========================================================================= */
-void Dblqh::seizeTcrec()
-{
- TcConnectionrecPtr locTcConnectptr;
-
- locTcConnectptr.i = cfirstfreeTcConrec;
- ptrCheckGuard(locTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- Uint32 nextTc = locTcConnectptr.p->nextTcConnectrec;
- locTcConnectptr.p->nextTcConnectrec = RNIL;
- locTcConnectptr.p->clientConnectrec = RNIL;
- locTcConnectptr.p->clientBlockref = RNIL;
- locTcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
- locTcConnectptr.p->tcTimer = cLqhTimeOutCount;
- locTcConnectptr.p->tableref = RNIL;
- locTcConnectptr.p->savePointId = 0;
- locTcConnectptr.p->gci = 0;
- cfirstfreeTcConrec = nextTc;
- tcConnectptr = locTcConnectptr;
- locTcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
-}//Dblqh::seizeTcrec()
-
-/* ==========================================================================
- * ======= SEIZE DATA BUFFER =======
- * ========================================================================= */
-void Dblqh::seizeTupkeybuf(Signal* signal)
-{
- Databuf *regDatabuf = databuf;
- DatabufPtr tmpDatabufptr;
- DatabufPtr regDatabufptr;
- Uint32 tdatabufFileSize = cdatabufFileSize;
-
-/* ------- GET A DATABUF. ------- */
- regDatabufptr.i = cfirstfreeDatabuf;
- tmpDatabufptr.i = tcConnectptr.p->lastTupkeybuf;
- ptrCheckGuard(regDatabufptr, tdatabufFileSize, regDatabuf);
- Uint32 nextFirst = regDatabufptr.p->nextDatabuf;
- tcConnectptr.p->lastTupkeybuf = regDatabufptr.i;
- if (tmpDatabufptr.i == RNIL) {
- jam();
- tcConnectptr.p->firstTupkeybuf = regDatabufptr.i;
- } else {
- jam();
- ptrCheckGuard(tmpDatabufptr, tdatabufFileSize, regDatabuf);
- tmpDatabufptr.p->nextDatabuf = regDatabufptr.i;
- }//if
- cfirstfreeDatabuf = nextFirst;
- regDatabufptr.p->nextDatabuf = RNIL;
- databufptr = regDatabufptr;
-}//Dblqh::seizeTupkeybuf()
-
-/* ------------------------------------------------------------------------- */
-/* ------- TAKE CARE OF LQHKEYREQ ------- */
-/* LQHKEYREQ IS THE SIGNAL THAT STARTS ALL OPERATIONS IN THE LQH BLOCK */
-/* THIS SIGNAL CONTAINS A LOT OF INFORMATION ABOUT WHAT TYPE OF OPERATION, */
-/* KEY INFORMATION, ATTRIBUTE INFORMATION, NODE INFORMATION AND A LOT MORE */
-/* ------------------------------------------------------------------------- */
-void Dblqh::execLQHKEYREQ(Signal* signal)
-{
- UintR sig0, sig1, sig2, sig3, sig4, sig5;
- Uint8 tfragDistKey;
-
- const LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtr();
-
- sig0 = lqhKeyReq->clientConnectPtr;
- if (cfirstfreeTcConrec != RNIL && !ERROR_INSERTED(5031)) {
- jamEntry();
- seizeTcrec();
- } else {
-/* ------------------------------------------------------------------------- */
-/* NO FREE TC RECORD AVAILABLE, THUS WE CANNOT HANDLE THE REQUEST. */
-/* ------------------------------------------------------------------------- */
- if (ERROR_INSERTED(5031)) {
- CLEAR_ERROR_INSERT_VALUE;
- }
- noFreeRecordLab(signal, lqhKeyReq, ZNO_TC_CONNECT_ERROR);
- return;
- }//if
-
- if(ERROR_INSERTED(5038) &&
- refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
- jam();
- SET_ERROR_INSERT_VALUE(5039);
- return;
- }
-
- c_Counters.operations++;
-
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 senderRef = regTcPtr->clientBlockref = signal->senderBlockRef();
- regTcPtr->clientConnectrec = sig0;
- regTcPtr->tcOprec = sig0;
- regTcPtr->storedProcId = ZNIL;
-
- UintR TtotReclenAi = lqhKeyReq->attrLen;
- sig1 = lqhKeyReq->savePointId;
- sig2 = lqhKeyReq->hashValue;
- UintR Treqinfo = lqhKeyReq->requestInfo;
- sig4 = lqhKeyReq->tableSchemaVersion;
- sig5 = lqhKeyReq->tcBlockref;
-
- regTcPtr->savePointId = sig1;
- regTcPtr->hashValue = sig2;
- const Uint32 schemaVersion = regTcPtr->schemaVersion = LqhKeyReq::getSchemaVersion(sig4);
- tabptr.i = LqhKeyReq::getTableId(sig4);
- regTcPtr->tcBlockref = sig5;
-
- const Uint8 op = LqhKeyReq::getOperation(Treqinfo);
- if ((op == ZREAD || op == ZREAD_EX) && !getAllowRead()){
- noFreeRecordLab(signal, lqhKeyReq, ZNODE_SHUTDOWN_IN_PROGESS);
- return;
- }
-
- Uint32 senderVersion = getNodeInfo(refToNode(senderRef)).m_version;
-
- regTcPtr->totReclenAi = LqhKeyReq::getAttrLen(TtotReclenAi);
- regTcPtr->tcScanInfo = lqhKeyReq->scanInfo;
- regTcPtr->indTakeOver = LqhKeyReq::getScanTakeOverFlag(TtotReclenAi);
-
- regTcPtr->readlenAi = 0;
- regTcPtr->currTupAiLen = 0;
- regTcPtr->listState = TcConnectionrec::NOT_IN_LIST;
- regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
- regTcPtr->fragmentptr = RNIL;
-
- sig0 = lqhKeyReq->fragmentData;
- sig1 = lqhKeyReq->transId1;
- sig2 = lqhKeyReq->transId2;
- sig3 = lqhKeyReq->variableData[0];
- sig4 = lqhKeyReq->variableData[1];
-
- regTcPtr->fragmentid = LqhKeyReq::getFragmentId(sig0);
- regTcPtr->nextReplica = LqhKeyReq::getNextReplicaNodeId(sig0);
- regTcPtr->transid[0] = sig1;
- regTcPtr->transid[1] = sig2;
- regTcPtr->applRef = sig3;
- regTcPtr->applOprec = sig4;
-
- regTcPtr->commitAckMarker = RNIL;
- if(LqhKeyReq::getMarkerFlag(Treqinfo)){
- jam();
-
- CommitAckMarkerPtr markerPtr;
- m_commitAckMarkerHash.seize(markerPtr);
- if(markerPtr.i == RNIL){
- noFreeRecordLab(signal, lqhKeyReq, ZNO_FREE_MARKER_RECORDS_ERROR);
- return;
- }
- markerPtr.p->transid1 = sig1;
- markerPtr.p->transid2 = sig2;
- markerPtr.p->apiRef = sig3;
- markerPtr.p->apiOprec = sig4;
- const NodeId tcNodeId = refToNode(sig5);
- markerPtr.p->tcNodeId = tcNodeId;
-
- CommitAckMarkerPtr tmp;
-#if defined VM_TRACE || defined ERROR_INSERT
-#ifdef MARKER_TRACE
- ndbout_c("Add marker[%.8x %.8x]", markerPtr.p->transid1, markerPtr.p->transid2);
-#endif
- ndbrequire(!m_commitAckMarkerHash.find(tmp, * markerPtr.p));
-#endif
- m_commitAckMarkerHash.add(markerPtr);
- regTcPtr->commitAckMarker = markerPtr.i;
- }
-
- regTcPtr->reqinfo = Treqinfo;
- regTcPtr->lastReplicaNo = LqhKeyReq::getLastReplicaNo(Treqinfo);
- regTcPtr->dirtyOp = LqhKeyReq::getDirtyFlag(Treqinfo);
- regTcPtr->opExec = LqhKeyReq::getInterpretedFlag(Treqinfo);
- regTcPtr->opSimple = LqhKeyReq::getSimpleFlag(Treqinfo);
- regTcPtr->seqNoReplica = LqhKeyReq::getSeqNoReplica(Treqinfo);
- UintR TreclenAiLqhkey = LqhKeyReq::getAIInLqhKeyReq(Treqinfo);
- regTcPtr->apiVersionNo = 0;
- regTcPtr->m_use_rowid = LqhKeyReq::getRowidFlag(Treqinfo);
- regTcPtr->m_dealloc = 0;
- if (unlikely(senderVersion < NDBD_ROWID_VERSION))
- {
- regTcPtr->operation = op;
- regTcPtr->lockType = LqhKeyReq::getLockType(Treqinfo);
- }
- else
- {
- regTcPtr->operation = (Operation_t) op == ZREAD_EX ? ZREAD : (Operation_t) op;
- regTcPtr->lockType =
- op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
- }
-
- if (regTcPtr->dirtyOp)
- {
- ndbrequire(regTcPtr->opSimple);
- }
-
- CRASH_INSERTION2(5041, (op == ZREAD &&
- (regTcPtr->opSimple || regTcPtr->dirtyOp) &&
- refToNode(signal->senderBlockRef()) != cownNodeid));
-
- regTcPtr->reclenAiLqhkey = TreclenAiLqhkey;
- regTcPtr->currReclenAi = TreclenAiLqhkey;
- UintR TitcKeyLen = LqhKeyReq::getKeyLen(Treqinfo);
- regTcPtr->primKeyLen = TitcKeyLen;
- regTcPtr->noFiredTriggers = lqhKeyReq->noFiredTriggers;
-
- UintR TapplAddressInd = LqhKeyReq::getApplicationAddressFlag(Treqinfo);
- UintR nextPos = (TapplAddressInd << 1);
- UintR TsameClientAndTcOprec = LqhKeyReq::getSameClientAndTcFlag(Treqinfo);
- if (TsameClientAndTcOprec == 1) {
- regTcPtr->tcOprec = lqhKeyReq->variableData[nextPos];
- nextPos++;
- }//if
- UintR TnextReplicasIndicator = regTcPtr->lastReplicaNo -
- regTcPtr->seqNoReplica;
- if (TnextReplicasIndicator > 1) {
- regTcPtr->nodeAfterNext[0] = lqhKeyReq->variableData[nextPos] & 0xFFFF;
- regTcPtr->nodeAfterNext[1] = lqhKeyReq->variableData[nextPos] >> 16;
- nextPos++;
- }//if
- UintR TstoredProcIndicator = LqhKeyReq::getStoredProcFlag(TtotReclenAi);
- if (TstoredProcIndicator == 1) {
- regTcPtr->storedProcId = lqhKeyReq->variableData[nextPos] & ZNIL;
- nextPos++;
- }//if
- UintR TreadLenAiIndicator = LqhKeyReq::getReturnedReadLenAIFlag(Treqinfo);
- if (TreadLenAiIndicator == 1) {
- regTcPtr->readlenAi = lqhKeyReq->variableData[nextPos] & ZNIL;
- nextPos++;
- }//if
- sig0 = lqhKeyReq->variableData[nextPos + 0];
- sig1 = lqhKeyReq->variableData[nextPos + 1];
- sig2 = lqhKeyReq->variableData[nextPos + 2];
- sig3 = lqhKeyReq->variableData[nextPos + 3];
-
- regTcPtr->tupkeyData[0] = sig0;
- regTcPtr->tupkeyData[1] = sig1;
- regTcPtr->tupkeyData[2] = sig2;
- regTcPtr->tupkeyData[3] = sig3;
-
- if (TitcKeyLen > 0) {
- if (TitcKeyLen < 4) {
- nextPos += TitcKeyLen;
- } else {
- nextPos += 4;
- }//if
- }
- else if (! (LqhKeyReq::getNrCopyFlag(Treqinfo)))
- {
- LQHKEY_error(signal, 3);
- return;
- }//if
-
- sig0 = lqhKeyReq->variableData[nextPos + 0];
- sig1 = lqhKeyReq->variableData[nextPos + 1];
- regTcPtr->m_row_id.m_page_no = sig0;
- regTcPtr->m_row_id.m_page_idx = sig1;
- nextPos += 2 * LqhKeyReq::getRowidFlag(Treqinfo);
-
- sig2 = lqhKeyReq->variableData[nextPos + 0];
- sig3 = cnewestGci;
- regTcPtr->gci = LqhKeyReq::getGCIFlag(Treqinfo) ? sig2 : sig3;
- nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
-
- if (LqhKeyReq::getRowidFlag(Treqinfo))
- {
- ndbassert(refToBlock(senderRef) != DBTC);
- }
- else if(op == ZINSERT)
- {
- ndbassert(refToBlock(senderRef) == DBTC);
- }
-
- if ((LqhKeyReq::FixedSignalLength + nextPos + TreclenAiLqhkey) !=
- signal->length()) {
- LQHKEY_error(signal, 2);
- return;
- }//if
- UintR TseqNoReplica = regTcPtr->seqNoReplica;
- UintR TlastReplicaNo = regTcPtr->lastReplicaNo;
- if (TseqNoReplica == TlastReplicaNo) {
- jam();
- regTcPtr->nextReplica = ZNIL;
- } else {
- if (TseqNoReplica < TlastReplicaNo) {
- jam();
- regTcPtr->nextSeqNoReplica = TseqNoReplica + 1;
- if ((regTcPtr->nextReplica == 0) ||
- (regTcPtr->nextReplica == cownNodeid)) {
- LQHKEY_error(signal, 0);
- }//if
- } else {
- LQHKEY_error(signal, 4);
- return;
- }//if
- }//if
- TcConnectionrecPtr localNextTcConnectptr;
- Uint32 hashIndex = (regTcPtr->transid[0] ^ regTcPtr->tcOprec) & 1023;
- localNextTcConnectptr.i = ctransidHash[hashIndex];
- ctransidHash[hashIndex] = tcConnectptr.i;
- regTcPtr->prevHashRec = RNIL;
- regTcPtr->nextHashRec = localNextTcConnectptr.i;
- if (localNextTcConnectptr.i != RNIL) {
-/* -------------------------------------------------------------------------- */
-/* ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD IF IT EXISTS */
-/* -------------------------------------------------------------------------- */
- ptrCheckGuard(localNextTcConnectptr,
- ctcConnectrecFileSize, tcConnectionrec);
- jam();
- localNextTcConnectptr.p->prevHashRec = tcConnectptr.i;
- }//if
- if (tabptr.i >= ctabrecFileSize) {
- LQHKEY_error(signal, 5);
- return;
- }//if
- ptrAss(tabptr, tablerec);
- if(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED){
- LQHKEY_abort(signal, 4);
- return;
- }
- if(table_version_major(tabptr.p->schemaVersion) !=
- table_version_major(schemaVersion)){
- LQHKEY_abort(signal, 5);
- return;
- }
-
- regTcPtr->tableref = tabptr.i;
- regTcPtr->m_disk_table = tabptr.p->m_disk_table;
- if(refToBlock(signal->senderBlockRef()) == RESTORE)
- regTcPtr->m_disk_table &= !LqhKeyReq::getNoDiskFlag(Treqinfo);
- else if(op == ZREAD || op == ZREAD_EX || op == ZUPDATE)
- regTcPtr->m_disk_table &= !LqhKeyReq::getNoDiskFlag(Treqinfo);
-
- tabptr.p->usageCount++;
-
- if (!getFragmentrec(signal, regTcPtr->fragmentid)) {
- LQHKEY_error(signal, 6);
- return;
- }//if
-
- if (LqhKeyReq::getNrCopyFlag(Treqinfo))
- {
- ndbassert(refToBlock(senderRef) == DBLQH);
- ndbassert(LqhKeyReq::getRowidFlag(Treqinfo));
- if (! (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION))
- {
- ndbout_c("fragptr.p->fragStatus: %d",
- fragptr.p->fragStatus);
- CRASH_INSERTION(5046);
- }
- ndbassert(fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION);
- fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
- }
-
- Uint8 TcopyType = fragptr.p->fragCopy;
- Uint32 logPart = fragptr.p->m_log_part_ptr_i;
- tfragDistKey = fragptr.p->fragDistributionKey;
- if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
- jam();
- regTcPtr->activeCreat = fragptr.p->m_copy_started_state;
- CRASH_INSERTION(5002);
- CRASH_INSERTION2(5042, tabptr.i == c_error_insert_table_id);
- } else {
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
- }//if
- regTcPtr->replicaType = TcopyType;
- regTcPtr->fragmentptr = fragptr.i;
- regTcPtr->m_log_part_ptr_i = logPart;
- Uint8 TdistKey = LqhKeyReq::getDistributionKey(TtotReclenAi);
- if ((tfragDistKey != TdistKey) &&
- (regTcPtr->seqNoReplica == 0) &&
- (regTcPtr->dirtyOp == ZFALSE))
- {
- /* ----------------------------------------------------------------------
- * WE HAVE DIFFERENT OPINION THAN THE DIH THAT STARTED THE TRANSACTION.
- * THE REASON COULD BE THAT THIS IS AN OLD DISTRIBUTION WHICH IS NO LONGER
- * VALID TO USE. THIS MUST BE CHECKED.
- * ONE IS ADDED TO THE DISTRIBUTION KEY EVERY TIME WE ADD A NEW REPLICA.
- * FAILED REPLICAS DO NOT AFFECT THE DISTRIBUTION KEY. THIS MEANS THAT THE
- * MAXIMUM DEVIATION CAN BE ONE BETWEEN THOSE TWO VALUES.
- * --------------------------------------------------------------------- */
- Int32 tmp = TdistKey - tfragDistKey;
- tmp = (tmp < 0 ? - tmp : tmp);
- if ((tmp <= 1) || (tfragDistKey == 0)) {
- LQHKEY_abort(signal, 0);
- return;
- }//if
- LQHKEY_error(signal, 1);
- }//if
- if (TreclenAiLqhkey != 0) {
- if (regTcPtr->operation != ZREAD) {
- if (regTcPtr->operation != ZDELETE) {
- if (regTcPtr->opExec != 1) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* */
-/* UPDATES, WRITES AND INSERTS THAT ARE NOT INTERPRETED WILL USE THE */
-/* SAME ATTRINFO IN ALL REPLICAS. THUS WE SAVE THE ATTRINFO ALREADY */
-/* TO SAVE A SIGNAL FROM TUP TO LQH. INTERPRETED EXECUTION IN TUP */
-/* WILL CREATE NEW ATTRINFO FOR THE OTHER REPLICAS AND IT IS THUS NOT */
-/* A GOOD IDEA TO SAVE THE INFORMATION HERE. READS WILL ALSO BE */
-/* UNNECESSARY TO SAVE SINCE THAT ATTRINFO WILL NEVER BE SENT TO ANY */
-/* MORE REPLICAS. */
-/*---------------------------------------------------------------------------*/
-/* READS AND DELETES CAN ONLY HAVE INFORMATION ABOUT WHAT IS TO BE READ. */
-/* NO INFORMATION THAT NEEDS LOGGING. */
-/*---------------------------------------------------------------------------*/
- sig0 = lqhKeyReq->variableData[nextPos + 0];
- sig1 = lqhKeyReq->variableData[nextPos + 1];
- sig2 = lqhKeyReq->variableData[nextPos + 2];
- sig3 = lqhKeyReq->variableData[nextPos + 3];
- sig4 = lqhKeyReq->variableData[nextPos + 4];
-
- regTcPtr->firstAttrinfo[0] = sig0;
- regTcPtr->firstAttrinfo[1] = sig1;
- regTcPtr->firstAttrinfo[2] = sig2;
- regTcPtr->firstAttrinfo[3] = sig3;
- regTcPtr->firstAttrinfo[4] = sig4;
- regTcPtr->currTupAiLen = TreclenAiLqhkey;
- } else {
- jam();
- regTcPtr->reclenAiLqhkey = 0;
- }//if
- } else {
- jam();
- regTcPtr->reclenAiLqhkey = 0;
- }//if
- }//if
- sig0 = lqhKeyReq->variableData[nextPos + 0];
- sig1 = lqhKeyReq->variableData[nextPos + 1];
- sig2 = lqhKeyReq->variableData[nextPos + 2];
- sig3 = lqhKeyReq->variableData[nextPos + 3];
- sig4 = lqhKeyReq->variableData[nextPos + 4];
-
- c_tup->receive_attrinfo(signal, regTcPtr->tupConnectrec,
- lqhKeyReq->variableData+nextPos, TreclenAiLqhkey);
-
- if (signal->theData[0] == (UintR)-1) {
- LQHKEY_abort(signal, 2);
- return;
- }//if
- }//if
-/* ------- TAKE CARE OF PRIM KEY DATA ------- */
- if (regTcPtr->primKeyLen <= 4) {
- endgettupkeyLab(signal);
- return;
- } else {
- jam();
-/*--------------------------------------------------------------------*/
-/* KEY LENGTH WAS MORE THAN 4 WORDS (WORD = 4 BYTE). THUS WE */
-/* HAVE TO ALLOCATE A DATA BUFFER TO STORE THE KEY DATA AND */
-/* WAIT FOR THE KEYINFO SIGNAL. */
-/*--------------------------------------------------------------------*/
- regTcPtr->save1 = 4;
- regTcPtr->transactionState = TcConnectionrec::WAIT_TUPKEYINFO;
- return;
- }//if
- return;
-}//Dblqh::execLQHKEYREQ()
-
-void Dblqh::endgettupkeyLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->totReclenAi == regTcPtr->currReclenAi) {
- ;
- } else {
- jam();
- ndbrequire(regTcPtr->currReclenAi < regTcPtr->totReclenAi);
- regTcPtr->transactionState = TcConnectionrec::WAIT_ATTR;
- return;
- }//if
-
-/* ---------------------------------------------------------------------- */
-/* NOW RECEPTION OF LQHKEYREQ IS COMPLETED THE NEXT STEP IS TO START*/
-/* PROCESSING THE MESSAGE. IF THE MESSAGE IS TO A STAND-BY NODE */
-/* WITHOUT NETWORK REDUNDANCY OR PREPARE-TO-COMMIT ACTIVATED THE */
-/* PREPARATION TO SEND TO THE NEXT NODE WILL START IMMEDIATELY. */
-/* */
-/* OTHERWISE THE PROCESSING WILL START AFTER SETTING THE PROPER */
-/* STATE. HOWEVER BEFORE PROCESSING THE MESSAGE */
-/* IT IS NECESSARY TO CHECK THAT THE FRAGMENT IS NOT PERFORMING */
-/* A CHECKPOINT. THE OPERATION SHALL ALSO BE LINKED INTO THE */
-/* FRAGMENT QUEUE OR LIST OF ACTIVE OPERATIONS. */
-/* */
-/* THE FIRST STEP IN PROCESSING THE MESSAGE IS TO CONTACT DBACC. */
-/*------------------------------------------------------------------------*/
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- case Fragrecord::CRASH_RECOVERING:
- case Fragrecord::ACTIVE_CREATION:
- prepareContinueAfterBlockedLab(signal);
- return;
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- regTcPtr->transactionState = TcConnectionrec::STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dblqh::endgettupkeyLab()
-
-void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
-{
- UintR ttcScanOp;
-
-/* -------------------------------------------------------------------------- */
-/* INPUT: TC_CONNECTPTR ACTIVE CONNECTION RECORD */
-/* FRAGPTR FRAGMENT RECORD */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* CONTINUE HERE AFTER BEING BLOCKED FOR A WHILE DURING LOCAL CHECKPOINT. */
-/* -------------------------------------------------------------------------- */
-/* ALSO AFTER NORMAL PROCEDURE WE CONTINUE HERE */
-/* -------------------------------------------------------------------------- */
- Uint32 tc_ptr_i = tcConnectptr.i;
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 activeCreat = regTcPtr->activeCreat;
- if (regTcPtr->indTakeOver == ZTRUE) {
- jam();
- ttcScanOp = KeyInfo20::getScanOp(regTcPtr->tcScanInfo);
- scanptr.i = RNIL;
- {
- ScanRecord key;
- key.scanNumber = KeyInfo20::getScanNo(regTcPtr->tcScanInfo);
- key.fragPtrI = fragptr.i;
- c_scanTakeOverHash.find(scanptr, key);
-#ifdef TRACE_SCAN_TAKEOVER
- if(scanptr.i == RNIL)
- ndbout_c("not finding (%d %d)", key.scanNumber, key.fragPtrI);
-#endif
- }
- if (scanptr.i == RNIL) {
- jam();
- takeOverErrorLab(signal);
- return;
- }//if
- Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
- ttcScanOp,
- true);
- if (accOpPtr == RNIL) {
- jam();
- takeOverErrorLab(signal);
- return;
- }//if
- signal->theData[1] = accOpPtr;
- signal->theData[2] = regTcPtr->transid[0];
- signal->theData[3] = regTcPtr->transid[1];
- EXECUTE_DIRECT(refToBlock(regTcPtr->tcAccBlockref), GSN_ACC_TO_REQ,
- signal, 4);
- if (signal->theData[0] == (UintR)-1) {
- execACC_TO_REF(signal);
- return;
- }//if
- jamEntry();
- }//if
-/*-------------------------------------------------------------------*/
-/* IT IS NOW TIME TO CONTACT ACC. THE TUPLE KEY WILL BE SENT */
-/* AND THIS WILL BE TRANSLATED INTO A LOCAL KEY BY USING THE */
-/* LOCAL PART OF THE LH3-ALGORITHM. ALSO PROPER LOCKS ON THE */
-/* TUPLE WILL BE SET. FOR INSERTS AND DELETES THE MESSAGE WILL */
-/* START AN INSERT/DELETE INTO THE HASH TABLE. */
-/* */
-/* BEFORE SENDING THE MESSAGE THE REQUEST INFORMATION IS SET */
-/* PROPERLY. */
-/* ----------------------------------------------------------------- */
- if (TRACENR_FLAG)
- {
- TRACE_OP(regTcPtr, "RECEIVED");
- switch (regTcPtr->operation) {
- case ZREAD: TRACENR("READ"); break;
- case ZUPDATE: TRACENR("UPDATE"); break;
- case ZWRITE: TRACENR("WRITE"); break;
- case ZINSERT: TRACENR("INSERT"); break;
- case ZDELETE: TRACENR("DELETE"); break;
- default: TRACENR("<Unknown: " << regTcPtr->operation << ">"); break;
- }
-
- TRACENR(" tab: " << regTcPtr->tableref
- << " frag: " << regTcPtr->fragmentid
- << " activeCreat: " << (Uint32)activeCreat);
- if (LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo))
- TRACENR(" NrCopy");
- if (LqhKeyReq::getRowidFlag(regTcPtr->reqinfo))
- TRACENR(" rowid: " << regTcPtr->m_row_id);
- TRACENR(" key: " << regTcPtr->tupkeyData[0]);
- }
-
- if (likely(activeCreat == Fragrecord::AC_NORMAL))
- {
- if (TRACENR_FLAG)
- TRACENR(endl);
- ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr->reqinfo));
- exec_acckeyreq(signal, tcConnectptr);
- }
- else if (activeCreat == Fragrecord::AC_NR_COPY)
- {
- regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
- handle_nr_copy(signal, tcConnectptr);
- }
- else
- {
- ndbassert(activeCreat == Fragrecord::AC_IGNORED);
- if (TRACENR_FLAG)
- TRACENR(" IGNORING (activeCreat == 2)" << endl);
-
- signal->theData[0] = tc_ptr_i;
- regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
-
- signal->theData[0] = regTcPtr->tupConnectrec;
- EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
- jamEntry();
-
- regTcPtr->totSendlenAi = regTcPtr->totReclenAi;
- packLqhkeyreqLab(signal);
- }
-}
-
-void
-Dblqh::exec_acckeyreq(Signal* signal, TcConnectionrecPtr regTcPtr)
-{
- Uint32 taccreq;
- regTcPtr.p->transactionState = TcConnectionrec::WAIT_ACC;
- taccreq = regTcPtr.p->operation;
- taccreq = taccreq + (regTcPtr.p->opSimple << 3);
- taccreq = taccreq + (regTcPtr.p->lockType << 4);
- taccreq = taccreq + (regTcPtr.p->dirtyOp << 6);
- taccreq = taccreq + (regTcPtr.p->replicaType << 7);
- taccreq = taccreq + (regTcPtr.p->apiVersionNo << 9);
-/* ************ */
-/* ACCKEYREQ < */
-/* ************ */
- Uint32 sig0, sig1, sig2, sig3, sig4;
- sig0 = regTcPtr.p->accConnectrec;
- sig1 = fragptr.p->accFragptr;
- sig2 = regTcPtr.p->hashValue;
- sig3 = regTcPtr.p->primKeyLen;
- sig4 = regTcPtr.p->transid[0];
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->theData[2] = taccreq;
- signal->theData[3] = sig2;
- signal->theData[4] = sig3;
- signal->theData[5] = sig4;
-
- sig0 = regTcPtr.p->transid[1];
- sig1 = regTcPtr.p->tupkeyData[0];
- sig2 = regTcPtr.p->tupkeyData[1];
- sig3 = regTcPtr.p->tupkeyData[2];
- sig4 = regTcPtr.p->tupkeyData[3];
- signal->theData[6] = sig0;
- signal->theData[7] = sig1;
- signal->theData[8] = sig2;
- signal->theData[9] = sig3;
- signal->theData[10] = sig4;
-
- TRACE_OP(regTcPtr.p, "ACC");
-
- if (regTcPtr.p->primKeyLen > 4) {
- sendKeyinfoAcc(signal, 11);
- }//if
- EXECUTE_DIRECT(refToBlock(regTcPtr.p->tcAccBlockref), GSN_ACCKEYREQ,
- signal, 7 + regTcPtr.p->primKeyLen);
- if (signal->theData[0] < RNIL) {
- signal->theData[0] = regTcPtr.i;
- execACCKEYCONF(signal);
- return;
- } else if (signal->theData[0] == RNIL) {
- ;
- } else {
- ndbrequire(signal->theData[0] == (UintR)-1);
- signal->theData[0] = regTcPtr.i;
- execACCKEYREF(signal);
- }//if
- return;
-}//Dblqh::prepareContinueAfterBlockedLab()
-
-void
-Dblqh::handle_nr_copy(Signal* signal, Ptr<TcConnectionrec> regTcPtr)
-{
- jam();
- Uint32 fragPtr = fragptr.p->tupFragptr;
- Uint32 op = regTcPtr.p->operation;
-
- const bool copy = LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo);
-
- if (!LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
- {
- /**
- * Rowid not set, that mean that primary has finished copying...
- */
- jam();
- if (TRACENR_FLAG)
- TRACENR(" Waiting for COPY_ACTIVEREQ" << endl);
- ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo));
- regTcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
- exec_acckeyreq(signal, regTcPtr);
- return;
- }
-
- regTcPtr.p->m_nr_delete.m_cnt = 1; // Wait for real op aswell
- Uint32* dst = signal->theData+24;
- bool uncommitted;
- const int len = c_tup->nr_read_pk(fragPtr, &regTcPtr.p->m_row_id, dst,
- uncommitted);
- const bool match = (len>0) ? compare_key(regTcPtr.p, dst, len) == 0 : false;
-
- if (TRACENR_FLAG)
- TRACENR(" len: " << len << " match: " << match
- << " uncommitted: " << uncommitted);
-
- if (copy)
- {
- ndbassert(LqhKeyReq::getGCIFlag(regTcPtr.p->reqinfo));
- if (match)
- {
- /**
- * Case 1
- */
- jam();
- ndbassert(op == ZINSERT);
- if (TRACENR_FLAG)
- TRACENR(" Changing from INSERT to ZUPDATE" << endl);
- regTcPtr.p->operation = ZUPDATE;
- goto run;
- }
- else if (len > 0 && op == ZDELETE)
- {
- /**
- * Case 4
- * Perform delete using rowid
- * primKeyLen == 0
- * tupkeyData[0] == rowid
- */
- jam();
- ndbassert(regTcPtr.p->primKeyLen == 0);
- if (TRACENR_FLAG)
- TRACENR(" performing DELETE key: "
- << dst[0] << endl);
-
- nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
- ndbassert(regTcPtr.p->m_nr_delete.m_cnt);
- regTcPtr.p->m_nr_delete.m_cnt--; // No real op is run
- if (regTcPtr.p->m_nr_delete.m_cnt)
- {
- jam();
- return;
- }
- packLqhkeyreqLab(signal);
- return;
- }
- else if (len == 0 && op == ZDELETE)
- {
- /**
- * Case 7
- */
- jam();
- if (TRACENR_FLAG)
- TRACENR(" UPDATE_GCI" << endl);
- c_tup->nr_update_gci(fragPtr, &regTcPtr.p->m_row_id, regTcPtr.p->gci);
- goto update_gci_ignore;
- }
-
- /**
- * 1) Delete row at specified rowid (if len > 0)
- * 2) Delete specified row at different rowid (if exists)
- * 3) Run insert
- */
- if (len > 0)
- {
- /**
- * 1) Delete row at specified rowid (if len > 0)
- */
- jam();
- nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
- }
- /**
- * 2) Delete specified row at different rowid (if exists)
- */
- jam();
- nr_copy_delete_row(signal, regTcPtr, 0, 0);
- if (TRACENR_FLAG)
- TRACENR(" RUN INSERT" << endl);
- goto run;
- }
- else
- {
- if (!match && op != ZINSERT)
- {
- jam();
- if (TRACENR_FLAG)
- TRACENR(" IGNORE " << endl);
- goto ignore;
- }
- if (match)
- {
- jam();
- if (op != ZDELETE)
- {
- if (TRACENR_FLAG)
- TRACENR(" Changing from to ZWRITE" << endl);
- regTcPtr.p->operation = ZWRITE;
- }
- goto run;
- }
-
- /**
- * 1) Delete row at specified rowid (if len > 0)
- * 2) Delete specified row at different rowid (if exists)
- * 3) Run insert
- */
- if (len > 0)
- {
- /**
- * 1) Delete row at specified rowid (if len > 0)
- */
- jam();
- nr_copy_delete_row(signal, regTcPtr, &regTcPtr.p->m_row_id, len);
- }
-
- /**
- * 2) Delete specified row at different rowid (if exists)
- */
- jam();
- nr_copy_delete_row(signal, regTcPtr, 0, 0);
- if (TRACENR_FLAG)
- TRACENR(" RUN op: " << op << endl);
- goto run;
- }
-
-run:
- jam();
- exec_acckeyreq(signal, regTcPtr);
- return;
-
-ignore:
- jam();
- ndbassert(!LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo));
-update_gci_ignore:
- regTcPtr.p->activeCreat = Fragrecord::AC_IGNORED;
- signal->theData[0] = regTcPtr.p->tupConnectrec;
- EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
-
- packLqhkeyreqLab(signal);
-}
-
-int
-Dblqh::compare_key(const TcConnectionrec* regTcPtr,
- const Uint32 * ptr, Uint32 len)
-{
- if (regTcPtr->primKeyLen != len)
- return 1;
-
- if (len <= 4)
- return memcmp(ptr, regTcPtr->tupkeyData, 4*len);
-
- if (memcmp(ptr, regTcPtr->tupkeyData, sizeof(regTcPtr->tupkeyData)))
- return 1;
-
- len -= (sizeof(regTcPtr->tupkeyData) >> 2);
- ptr += (sizeof(regTcPtr->tupkeyData) >> 2);
-
- DatabufPtr regDatabufptr;
- regDatabufptr.i = tcConnectptr.p->firstTupkeybuf;
- ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
- while(len > 4)
- {
- if (memcmp(ptr, regDatabufptr.p, 4*4))
- return 1;
-
- ptr += 4;
- len -= 4;
- regDatabufptr.i = regDatabufptr.p->nextDatabuf;
- ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
- }
-
- if (memcmp(ptr, regDatabufptr.p, 4*len))
- return 1;
-
- return 0;
-}
-
-void
-Dblqh::nr_copy_delete_row(Signal* signal,
- Ptr<TcConnectionrec> regTcPtr,
- Local_key* rowid, Uint32 len)
-{
- Ptr<Fragrecord> fragPtr = fragptr;
-
- Uint32 keylen;
- Uint32 tableId = regTcPtr.p->tableref;
- Uint32 accPtr = regTcPtr.p->accConnectrec;
-
- signal->theData[0] = accPtr;
- signal->theData[1] = fragptr.p->accFragptr;
- signal->theData[2] = ZDELETE + (ZDELETE << 4);
- signal->theData[5] = regTcPtr.p->transid[0];
- signal->theData[6] = regTcPtr.p->transid[1];
-
- if (rowid)
- {
- jam();
- keylen = 1;
- if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
- {
- signal->theData[3] = calculateHash(tableId, signal->theData+24);
- }
- else
- {
- signal->theData[3] = md5_hash((Uint64*)(signal->theData+24), len);
- }
- signal->theData[4] = 0; // seach by local key
- signal->theData[7] = rowid->ref();
- }
- else
- {
- jam();
- keylen = regTcPtr.p->primKeyLen;
- signal->theData[3] = regTcPtr.p->hashValue;
- signal->theData[4] = keylen;
- signal->theData[7] = regTcPtr.p->tupkeyData[0];
- signal->theData[8] = regTcPtr.p->tupkeyData[1];
- signal->theData[9] = regTcPtr.p->tupkeyData[2];
- signal->theData[10] = regTcPtr.p->tupkeyData[3];
- if (keylen > 4)
- sendKeyinfoAcc(signal, 11);
- }
- const Uint32 ref = refToBlock(regTcPtr.p->tcAccBlockref);
- EXECUTE_DIRECT(ref, GSN_ACCKEYREQ, signal, 7 + keylen);
- jamEntry();
-
- Uint32 retValue = signal->theData[0];
- ndbrequire(retValue != RNIL); // This should never block...
- ndbrequire(retValue != (Uint32)-1 || rowid == 0); // rowid should never fail
-
- if (retValue == (Uint32)-1)
- {
- /**
- * Only delete by pk, may fail
- */
- jam();
- ndbrequire(rowid == 0);
- signal->theData[0] = accPtr;
- signal->theData[1] = 0;
- EXECUTE_DIRECT(ref, GSN_ACC_ABORTREQ, signal, 2);
- jamEntry();
- return;
- }
-
- /**
- * We found row (and have it locked in ACC)
- */
- ndbrequire(regTcPtr.p->m_dealloc == 0);
- Local_key save = regTcPtr.p->m_row_id;
-
- c_acc->execACCKEY_ORD(signal, accPtr);
- signal->theData[0] = accPtr;
- EXECUTE_DIRECT(ref, GSN_ACC_COMMITREQ, signal, 1);
- jamEntry();
-
- ndbrequire(regTcPtr.p->m_dealloc == 1);
- int ret = c_tup->nr_delete(signal, regTcPtr.i,
- fragPtr.p->tupFragptr, &regTcPtr.p->m_row_id,
- regTcPtr.p->gci);
- jamEntry();
-
- if (ret)
- {
- ndbassert(ret == 1);
- Uint32 pos = regTcPtr.p->m_nr_delete.m_cnt - 1;
- memcpy(regTcPtr.p->m_nr_delete.m_disk_ref + pos,
- signal->theData, sizeof(Local_key));
- regTcPtr.p->m_nr_delete.m_page_id[pos] = RNIL;
- regTcPtr.p->m_nr_delete.m_cnt = pos + 2;
- if (0) ndbout << "PENDING DISK DELETE: " <<
- regTcPtr.p->m_nr_delete.m_disk_ref[pos] << endl;
- }
-
- TRACENR("DELETED: " << regTcPtr.p->m_row_id << endl);
-
- regTcPtr.p->m_dealloc = 0;
- regTcPtr.p->m_row_id = save;
- fragptr = fragPtr;
- tcConnectptr = regTcPtr;
-}
-
-void
-Dblqh::get_nr_op_info(Nr_op_info* op, Uint32 page_id)
-{
- Ptr<TcConnectionrec> tcPtr;
- tcPtr.i = op->m_ptr_i;
- ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
-
- Ptr<Fragrecord> fragPtr;
- c_fragment_pool.getPtr(fragPtr, tcPtr.p->fragmentptr);
-
- op->m_gci = tcPtr.p->gci;
- op->m_tup_frag_ptr_i = fragPtr.p->tupFragptr;
-
- ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
- ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
-
-
- if (page_id == RNIL)
- {
- // get log buffer callback
- for (Uint32 i = 0; i<2; i++)
- {
- if (tcPtr.p->m_nr_delete.m_page_id[i] != RNIL)
- {
- op->m_page_id = tcPtr.p->m_nr_delete.m_page_id[i];
- op->m_disk_ref = tcPtr.p->m_nr_delete.m_disk_ref[i];
- return;
- }
- }
- }
- else
- {
- // get page callback
- for (Uint32 i = 0; i<2; i++)
- {
- Local_key key = tcPtr.p->m_nr_delete.m_disk_ref[i];
- if (op->m_disk_ref.m_page_no == key.m_page_no &&
- op->m_disk_ref.m_file_no == key.m_file_no &&
- tcPtr.p->m_nr_delete.m_page_id[i] == RNIL)
- {
- op->m_disk_ref = key;
- tcPtr.p->m_nr_delete.m_page_id[i] = page_id;
- return;
- }
- }
- }
- ndbrequire(false);
-}
-
-void
-Dblqh::nr_delete_complete(Signal* signal, Nr_op_info* op)
-{
- jamEntry();
- Ptr<TcConnectionrec> tcPtr;
- tcPtr.i = op->m_ptr_i;
- ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
-
- ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
- ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
-
- tcPtr.p->m_nr_delete.m_cnt--;
- if (tcPtr.p->m_nr_delete.m_cnt == 0)
- {
- jam();
- tcConnectptr = tcPtr;
- c_fragment_pool.getPtr(fragptr, tcPtr.p->fragmentptr);
-
- if (tcPtr.p->abortState != TcConnectionrec::ABORT_IDLE)
- {
- jam();
- tcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
- abortCommonLab(signal);
- }
- else if (tcPtr.p->operation == ZDELETE &&
- LqhKeyReq::getNrCopyFlag(tcPtr.p->reqinfo))
- {
- /**
- * This is run directly in handle_nr_copy
- */
- jam();
- packLqhkeyreqLab(signal);
- }
- else
- {
- jam();
- rwConcludedLab(signal);
- }
- return;
- }
-
- if (memcmp(&tcPtr.p->m_nr_delete.m_disk_ref[0],
- &op->m_disk_ref, sizeof(Local_key)) == 0)
- {
- jam();
- ndbassert(tcPtr.p->m_nr_delete.m_page_id[0] != RNIL);
- tcPtr.p->m_nr_delete.m_page_id[0] = tcPtr.p->m_nr_delete.m_page_id[1];
- tcPtr.p->m_nr_delete.m_disk_ref[0] = tcPtr.p->m_nr_delete.m_disk_ref[1];
- }
-}
-
-Uint32
-Dblqh::readPrimaryKeys(Uint32 opPtrI, Uint32 * dst, bool xfrm)
-{
- TcConnectionrecPtr regTcPtr;
- DatabufPtr regDatabufptr;
- Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS >> 1];
-
- jamEntry();
- regTcPtr.i = opPtrI;
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
-
- Uint32 tableId = regTcPtr.p->tableref;
- Uint32 keyLen = regTcPtr.p->primKeyLen;
- regDatabufptr.i = regTcPtr.p->firstTupkeybuf;
- Uint32 * tmp = xfrm ? (Uint32*)Tmp : dst;
-
- memcpy(tmp, regTcPtr.p->tupkeyData, sizeof(regTcPtr.p->tupkeyData));
- if (keyLen > 4)
- {
- tmp += 4;
- Uint32 pos = 4;
- do {
- ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
- memcpy(tmp, regDatabufptr.p->data, sizeof(regDatabufptr.p->data));
- regDatabufptr.i = regDatabufptr.p->nextDatabuf;
- tmp += sizeof(regDatabufptr.p->data) >> 2;
- pos += sizeof(regDatabufptr.p->data) >> 2;
- } while(pos < keyLen);
- }
-
- if (xfrm)
- {
- jam();
- Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
- return xfrm_key(tableId, (Uint32*)Tmp, dst, ~0, keyPartLen);
- }
-
- return keyLen;
-}
-
-/* =*======================================================================= */
-/* ======= SEND KEYINFO TO ACC ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::sendKeyinfoAcc(Signal* signal, Uint32 Ti)
-{
- DatabufPtr regDatabufptr;
- regDatabufptr.i = tcConnectptr.p->firstTupkeybuf;
-
- do {
- jam();
- 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];
- signal->theData[Ti] = sig0;
- signal->theData[Ti + 1] = sig1;
- signal->theData[Ti + 2] = sig2;
- signal->theData[Ti + 3] = sig3;
- regDatabufptr.i = regDatabufptr.p->nextDatabuf;
- Ti += 4;
- } while (regDatabufptr.i != RNIL);
-}//Dblqh::sendKeyinfoAcc()
-
-void Dblqh::execLQH_ALLOCREQ(Signal* signal)
-{
- TcConnectionrecPtr regTcPtr;
- FragrecordPtr regFragptr;
-
- jamEntry();
- regTcPtr.i = signal->theData[0];
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
-
- regFragptr.i = regTcPtr.p->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
-
- signal->theData[0] = regTcPtr.p->tupConnectrec;
- signal->theData[1] = regFragptr.p->tupFragptr;
- signal->theData[2] = regTcPtr.p->tableref;
- Uint32 tup = refToBlock(regTcPtr.p->tcTupBlockref);
- EXECUTE_DIRECT(tup, GSN_TUP_ALLOCREQ, signal, 3);
-}//Dblqh::execTUP_ALLOCREQ()
-
-void Dblqh::execTUP_DEALLOCREQ(Signal* signal)
-{
- TcConnectionrecPtr regTcPtr;
-
- jamEntry();
- regTcPtr.i = signal->theData[4];
-
- if (TRACENR_FLAG)
- {
- Local_key tmp;
- tmp.m_page_no = signal->theData[2];
- tmp.m_page_idx = signal->theData[3];
- TRACENR("TUP_DEALLOC: " << tmp <<
- (signal->theData[5] ? " DIRECT " : " DELAYED") << endl);
- }
-
- if (signal->theData[5])
- {
- jam();
- Local_key tmp;
- tmp.m_page_no = signal->theData[2];
- tmp.m_page_idx = signal->theData[3];
- EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, signal->getLength());
- return;
- }
- else
- {
- jam();
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
- regTcPtr.p->m_row_id.m_page_no = signal->theData[2];
- regTcPtr.p->m_row_id.m_page_idx = signal->theData[3];
-
- ndbrequire(regTcPtr.p->m_dealloc == 0);
- regTcPtr.p->m_dealloc = 1;
- }
-}//Dblqh::execTUP_ALLOCREQ()
-
-/* ************>> */
-/* ACCKEYCONF > */
-/* ************>> */
-void Dblqh::execACCKEYCONF(Signal* signal)
-{
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- Uint32 tcIndex = signal->theData[0];
- Uint32 localKey1 = signal->theData[3];
- //Uint32 localKey2 = signal->theData[4];
- Uint32 localKeyFlag = signal->theData[5];
- jamEntry();
- tcConnectptr.i = tcIndex;
- ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->transactionState != TcConnectionrec::WAIT_ACC) {
- LQHKEY_abort(signal, 3);
- return;
- }//if
-
- /* ------------------------------------------------------------------------
- * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
- * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
- * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
- * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
- * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
- * TABLE.
- * ----------------------------------------------------------------------- */
- if (regTcPtr->operation == ZWRITE)
- {
- ndbassert(regTcPtr->seqNoReplica == 0 ||
- regTcPtr->activeCreat == Fragrecord::AC_NR_COPY);
- Uint32 op= signal->theData[1];
- Uint32 requestInfo = regTcPtr->reqinfo;
- if(likely(op == ZINSERT || op == ZUPDATE))
- {
- jam();
- regTcPtr->operation = op;
- }
- else
- {
- jam();
- warningEvent("Convering %d to ZUPDATE", op);
- op = regTcPtr->operation = ZUPDATE;
- }
- if (regTcPtr->seqNoReplica == 0)
- {
- jam();
- requestInfo &= ~(RI_OPERATION_MASK << RI_OPERATION_SHIFT);
- LqhKeyReq::setOperation(requestInfo, op);
- regTcPtr->reqinfo = requestInfo;
- }
- }//if
-
- /* ------------------------------------------------------------------------
- * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
- * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
- * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
- * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
- * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
- * TABLE.
- * ----------------------------------------------------------------------- */
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
-
- ndbrequire(localKeyFlag == 1);
- if(!regTcPtr->m_disk_table)
- acckeyconf_tupkeyreq(signal, regTcPtr, regFragptr.p, localKey1, RNIL);
- else
- acckeyconf_load_diskpage(signal, tcConnectptr, regFragptr.p, localKey1);
-}
-
-void
-Dblqh::acckeyconf_tupkeyreq(Signal* signal, TcConnectionrec* regTcPtr,
- Fragrecord* regFragptrP,
- Uint32 local_key,
- Uint32 disk_page)
-{
- Uint32 op = regTcPtr->operation;
- regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
- /* ------------------------------------------------------------------------
- * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
- * INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
- * KNOW THE TYPE OF OPERATION TO PERFORM. TUP CAN SEND THE ATTRINFO DATA
- * EITHER TO THE TC BLOCK OR DIRECTLY TO THE APPLICATION. THE SCHEMA VERSION
- * IS NEEDED SINCE TWO SCHEMA VERSIONS CAN BE ACTIVE SIMULTANEOUSLY ON A
- * TABLE.
- * ----------------------------------------------------------------------- */
- Uint32 page_idx = local_key & MAX_TUPLES_PER_PAGE;
- Uint32 page_no = local_key >> MAX_TUPLES_BITS;
- Uint32 Ttupreq = regTcPtr->dirtyOp;
- Ttupreq = Ttupreq + (regTcPtr->opSimple << 1);
- Ttupreq = Ttupreq + (op << 6);
- Ttupreq = Ttupreq + (regTcPtr->opExec << 10);
- Ttupreq = Ttupreq + (regTcPtr->apiVersionNo << 11);
- Ttupreq = Ttupreq + (regTcPtr->m_use_rowid << 11);
-
- /* ---------------------------------------------------------------------
- * Clear interpreted mode bit since we do not want the next replica to
- * use interpreted mode. The next replica will receive a normal write.
- * --------------------------------------------------------------------- */
- regTcPtr->opExec = 0;
- /* ************< */
- /* TUPKEYREQ < */
- /* ************< */
- Uint32 sig0, sig1, sig2, sig3;
- sig0 = regTcPtr->tupConnectrec;
-
- TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
- tupKeyReq->connectPtr = sig0;
- tupKeyReq->request = Ttupreq;
- tupKeyReq->keyRef1 = page_no;
- tupKeyReq->keyRef2 = page_idx;
-
- sig0 = regTcPtr->totReclenAi;
- sig1 = regTcPtr->applOprec;
- sig2 = regTcPtr->applRef;
-
- tupKeyReq->attrBufLen = sig0;
- tupKeyReq->opRef = sig1;
- tupKeyReq->applRef = sig2;
-
- sig0 = regTcPtr->storedProcId;
- sig1 = regTcPtr->transid[0];
- sig2 = regTcPtr->transid[1];
- sig3 = regFragptrP->tupFragptr;
- Uint32 tup = refToBlock(regTcPtr->tcTupBlockref);
-
- tupKeyReq->storedProcedure = sig0;
- tupKeyReq->transId1 = sig1;
- tupKeyReq->transId2 = sig2;
- tupKeyReq->fragPtr = sig3;
-
- sig0 = regTcPtr->m_row_id.m_page_no;
- sig1 = regTcPtr->m_row_id.m_page_idx;
-
- tupKeyReq->primaryReplica = (tcConnectptr.p->seqNoReplica == 0)?true:false;
- tupKeyReq->coordinatorTC = tcConnectptr.p->tcBlockref;
- tupKeyReq->tcOpIndex = tcConnectptr.p->tcOprec;
- tupKeyReq->savePointId = tcConnectptr.p->savePointId;
- tupKeyReq->disk_page= disk_page;
-
- tupKeyReq->m_row_id_page_no = sig0;
- tupKeyReq->m_row_id_page_idx = sig1;
-
- TRACE_OP(regTcPtr, "TUPKEYREQ");
-
- regTcPtr->m_use_rowid |= (op == ZINSERT);
- regTcPtr->m_row_id.m_page_no = page_no;
- regTcPtr->m_row_id.m_page_idx = page_idx;
-
- EXECUTE_DIRECT(tup, GSN_TUPKEYREQ, signal, TupKeyReq::SignalLength);
-}//Dblqh::execACCKEYCONF()
-
-void
-Dblqh::acckeyconf_load_diskpage(Signal* signal, TcConnectionrecPtr regTcPtr,
- Fragrecord* regFragptrP, Uint32 local_key)
-{
- int res;
- if((res= c_tup->load_diskpage(signal,
- regTcPtr.p->tupConnectrec,
- regFragptrP->tupFragptr,
- local_key,
- regTcPtr.p->operation)) > 0)
- {
- acckeyconf_tupkeyreq(signal, regTcPtr.p, regFragptrP, local_key, res);
- }
- else if(res == 0)
- {
- regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
- regTcPtr.p->m_row_id.assref(local_key);
- }
- else
- {
- regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
- TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
- ref->userRef= regTcPtr.i;
- ref->errorCode= ~0;
- execTUPKEYREF(signal);
- }
-}
-
-void
-Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
- Uint32 callbackData,
- Uint32 disk_page)
-{
- jamEntry();
- tcConnectptr.i = callbackData;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
-
- TcConnectionrec::TransactionState state = regTcPtr->transactionState;
- if (likely(disk_page > 0 && state == TcConnectionrec::WAIT_TUP))
- {
- FragrecordPtr fragPtr;
- c_fragment_pool.getPtr(fragPtr, regTcPtr->fragmentptr);
-
- acckeyconf_tupkeyreq(signal, regTcPtr, fragPtr.p,
- regTcPtr->m_row_id.ref(),
- disk_page);
- }
- else if (state != TcConnectionrec::WAIT_TUP)
- {
- ndbrequire(state == TcConnectionrec::WAIT_TUP_TO_ABORT);
- abortCommonLab(signal);
- return;
- }
- else
- {
- regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
- TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
- ref->userRef= callbackData;
- ref->errorCode= disk_page;
- execTUPKEYREF(signal);
- }
-}
-
-/* --------------------------------------------------------------------------
- * ------- ENTER TUP... -------
- * ENTER TUPKEYCONF WITH
- * TC_CONNECTPTR,
- * TDATA2, LOCAL KEY REFERENCE 1, ONLY INTERESTING AFTER INSERT
- * TDATA3, LOCAL KEY REFERENCE 1, ONLY INTERESTING AFTER INSERT
- * TDATA4, TOTAL LENGTH OF READ DATA SENT TO TC/APPLICATION
- * TDATA5 TOTAL LENGTH OF UPDATE DATA SENT TO/FROM TUP
- * GOTO TUPKEY_CONF
- *
- * TAKE CARE OF RESPONSES FROM TUPLE MANAGER.
- * -------------------------------------------------------------------------- */
-void Dblqh::tupkeyConfLab(Signal* signal)
-{
-/* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED --- */
- const TupKeyConf * const tupKeyConf = (TupKeyConf *)&signal->theData[0];
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 activeCreat = regTcPtr->activeCreat;
- Uint32 readLen = tupKeyConf->readLength;
- Uint32 writeLen = tupKeyConf->writeLength;
-
- Uint32 accOp = regTcPtr->accConnectrec;
- c_acc->execACCKEY_ORD(signal, accOp);
-
- TRACE_OP(regTcPtr, "TUPKEYCONF");
-
- if (readLen != 0)
- {
- jam();
-
- /* SET BIT 15 IN REQINFO */
- LqhKeyReq::setApplicationAddressFlag(regTcPtr->reqinfo, 1);
- regTcPtr->readlenAi = readLen;
- }//if
-
- if (regTcPtr->operation == ZREAD &&
- (regTcPtr->opSimple || regTcPtr->dirtyOp))
- {
- jam();
- /* ----------------------------------------------------------------------
- * THE OPERATION IS A SIMPLE READ.
- * WE WILL IMMEDIATELY COMMIT THE OPERATION.
- * SINCE WE HAVE NOT RELEASED THE FRAGMENT LOCK
- * (FOR LOCAL CHECKPOINTS) YET
- * WE CAN GO IMMEDIATELY TO COMMIT_CONTINUE_AFTER_BLOCKED.
- * WE HAVE ALREADY SENT THE RESPONSE SO WE ARE NOT INTERESTED IN
- * READ LENGTH
- * --------------------------------------------------------------------- */
- commitContinueAfterBlockedLab(signal);
- return;
- }//if
- regTcPtr->totSendlenAi = writeLen;
- ndbrequire(regTcPtr->totSendlenAi == regTcPtr->currTupAiLen);
-
- if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
- {
- jam();
- ndbrequire(regTcPtr->m_nr_delete.m_cnt);
- regTcPtr->m_nr_delete.m_cnt--;
- if (regTcPtr->m_nr_delete.m_cnt)
- {
- jam();
- /**
- * Let operation wait for pending NR operations
- * even for before writing log...(as it's simpler)
- */
-
-#ifdef VM_TRACE
- /**
- * Only disk table can have pending ops...
- */
- TablerecPtr tablePtr;
- tablePtr.i = regTcPtr->tableref;
- ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
- ndbrequire(tablePtr.p->m_disk_table);
-#endif
-
- return;
- }
- }
-
- rwConcludedLab(signal);
- return;
-}//Dblqh::tupkeyConfLab()
-
-/* --------------------------------------------------------------------------
- * THE CODE IS FOUND IN THE SIGNAL RECEPTION PART OF LQH
- * -------------------------------------------------------------------------- */
-void Dblqh::rwConcludedLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- /* ------------------------------------------------------------------------
- * WE HAVE NOW CONCLUDED READING/WRITING IN ACC AND TUP FOR THIS OPERATION.
- * IT IS NOW TIME TO LOG THE OPERATION, SEND REQUEST TO NEXT NODE OR TC AND
- * FOR SOME TYPES OF OPERATIONS IT IS EVEN TIME TO COMMIT THE OPERATION.
- * ------------------------------------------------------------------------ */
- if (regTcPtr->operation == ZREAD) {
- jam();
- /* ----------------------------------------------------------------------
- * A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL THE
- * COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
- * ---------------------------------------------------------------------- */
- packLqhkeyreqLab(signal);
- return;
- } else {
- FragrecordPtr regFragptr = fragptr;
- if (regFragptr.p->logFlag == Fragrecord::STATE_FALSE){
- if (regTcPtr->dirtyOp == ZTRUE) {
- jam();
- /* ------------------------------------------------------------------
- * THIS OPERATION WAS A WRITE OPERATION THAT DO NOT NEED LOGGING AND
- * THAT CAN CAN BE COMMITTED IMMEDIATELY.
- * ----------------------------------------------------------------- */
- commitContinueAfterBlockedLab(signal);
- return;
- } else {
- jam();
- /* ------------------------------------------------------------------
- * A NORMAL WRITE OPERATION ON A FRAGMENT WHICH DO NOT NEED LOGGING.
- * WE WILL PACK THE REQUEST/RESPONSE TO THE NEXT NODE/TO TC.
- * ------------------------------------------------------------------ */
- regTcPtr->logWriteState = TcConnectionrec::NOT_WRITTEN;
- packLqhkeyreqLab(signal);
- return;
- }//if
- } else {
- jam();
- /* --------------------------------------------------------------------
- * A DIRTY OPERATION WHICH NEEDS LOGGING. WE START BY LOGGING THE
- * REQUEST. IN THIS CASE WE WILL RELEASE THE FRAGMENT LOCK FIRST.
- * --------------------------------------------------------------------
- * A NORMAL WRITE OPERATION THAT NEEDS LOGGING AND WILL NOT BE
- * PREMATURELY COMMITTED.
- * -------------------------------------------------------------------- */
- logLqhkeyreqLab(signal);
- return;
- }//if
- }//if
-}//Dblqh::rwConcludedLab()
-
-void Dblqh::rwConcludedAiLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- fragptr.i = regTcPtr->fragmentptr;
- /* ------------------------------------------------------------------------
- * WE HAVE NOW CONCLUDED READING/WRITING IN ACC AND TUP FOR THIS OPERATION.
- * IT IS NOW TIME TO LOG THE OPERATION, SEND REQUEST TO NEXT NODE OR TC AND
- * FOR SOME TYPES OF OPERATIONS IT IS EVEN TIME TO COMMIT THE OPERATION.
- * IN THIS CASE WE HAVE ALREADY RELEASED THE FRAGMENT LOCK.
- * ERROR CASES AT FRAGMENT CREATION AND STAND-BY NODES ARE THE REASONS FOR
- * COMING HERE.
- * ------------------------------------------------------------------------ */
- if (regTcPtr->operation == ZREAD) {
- if (regTcPtr->opSimple == 1) {
- jam();
- /* --------------------------------------------------------------------
- * THE OPERATION IS A SIMPLE READ. WE WILL IMMEDIATELY COMMIT THE
- * OPERATION.
- * -------------------------------------------------------------------- */
- localCommitLab(signal);
- return;
- } else {
- jam();
- /* --------------------------------------------------------------------
- * A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL
- * THE COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
- * -------------------------------------------------------------------- */
- c_fragment_pool.getPtr(fragptr);
- packLqhkeyreqLab(signal);
- return;
- }//if
- } else {
- jam();
- c_fragment_pool.getPtr(fragptr);
- if (fragptr.p->logFlag == Fragrecord::STATE_FALSE) {
- if (regTcPtr->dirtyOp == ZTRUE) {
- /* ------------------------------------------------------------------
- * THIS OPERATION WAS A WRITE OPERATION THAT DO NOT NEED LOGGING AND
- * THAT CAN CAN BE COMMITTED IMMEDIATELY.
- * ----------------------------------------------------------------- */
- jam();
- /* ----------------------------------------------------------------
- * IT MUST BE ACTIVE CREATION OF A FRAGMENT.
- * ---------------------------------------------------------------- */
- localCommitLab(signal);
- return;
- } else {
- /* ------------------------------------------------------------------
- * A NORMAL WRITE OPERATION ON A FRAGMENT WHICH DO NOT NEED LOGGING.
- * WE WILL PACK THE REQUEST/RESPONSE TO THE NEXT NODE/TO TC.
- * ------------------------------------------------------------------ */
- jam();
- /* ---------------------------------------------------------------
- * IT MUST BE ACTIVE CREATION OF A FRAGMENT.
- * NOT A DIRTY OPERATION THUS PACK REQUEST/RESPONSE.
- * ---------------------------------------------------------------- */
- regTcPtr->logWriteState = TcConnectionrec::NOT_WRITTEN;
- packLqhkeyreqLab(signal);
- return;
- }//if
- } else {
- jam();
- /* --------------------------------------------------------------------
- * A DIRTY OPERATION WHICH NEEDS LOGGING. WE START BY LOGGING THE
- * REQUEST. IN THIS CASE WE WILL RELEASE THE FRAGMENT LOCK FIRST.
- * -------------------------------------------------------------------- */
- /* A NORMAL WRITE OPERATION THAT NEEDS LOGGING AND WILL NOT BE
- * PREMATURELY COMMITTED.
- * -------------------------------------------------------------------- */
- logLqhkeyreqLab(signal);
- return;
- }//if
- }//if
-}//Dblqh::rwConcludedAiLab()
-
-/* ##########################################################################
- * ####### LOG MODULE #######
- *
- * ##########################################################################
- * --------------------------------------------------------------------------
- * THE LOG MODULE HANDLES THE READING AND WRITING OF THE LOG
- * IT IS ALSO RESPONSIBLE FOR HANDLING THE SYSTEM RESTART.
- * IT CONTROLS THE SYSTEM RESTART IN TUP AND ACC AS WELL.
- * -------------------------------------------------------------------------- */
-void Dblqh::logLqhkeyreqLab(Signal* signal)
-{
- UintR tcurrentFilepage;
- TcConnectionrecPtr tmpTcConnectptr;
-
- if (cnoOfLogPages < ZMIN_LOG_PAGES_OPERATION || ERROR_INSERTED(5032)) {
- jam();
- if(ERROR_INSERTED(5032)){
- CLEAR_ERROR_INSERT_VALUE;
- }
-/*---------------------------------------------------------------------------*/
-// The log disk is having problems in catching up with the speed of execution.
-// We must wait with writing the log of this operation to ensure we do not
-// overload the log.
-/*---------------------------------------------------------------------------*/
- terrorCode = ZTEMPORARY_REDO_LOG_FAILURE;
- abortErrorLab(signal);
- return;
- }//if
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- logPartPtr.i = regTcPtr->m_log_part_ptr_i;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
-/* -------------------------------------------------- */
-/* THIS PART IS USED TO WRITE THE LOG */
-/* -------------------------------------------------- */
-/* -------------------------------------------------- */
-/* CHECK IF A LOG OPERATION IS ONGOING ALREADY. */
-/* IF SO THEN QUEUE THE OPERATION FOR LATER */
-/* RESTART WHEN THE LOG PART IS FREE AGAIN. */
-/* -------------------------------------------------- */
- LogPartRecord * const regLogPartPtr = logPartPtr.p;
-
- if(ERROR_INSERTED(5033)){
- jam();
- CLEAR_ERROR_INSERT_VALUE;
-
- if ((regLogPartPtr->firstLogQueue != RNIL) &&
- (regLogPartPtr->LogLqhKeyReqSent == ZFALSE)) {
- /* -------------------------------------------------- */
- /* WE HAVE A PROBLEM IN THAT THE LOG HAS NO */
- /* ROOM FOR ADDITIONAL OPERATIONS AT THE MOMENT.*/
- /* -------------------------------------------------- */
- /* -------------------------------------------------- */
- /* WE MUST STILL RESTART QUEUED OPERATIONS SO */
- /* THEY ALSO CAN BE ABORTED. */
- /* -------------------------------------------------- */
- regLogPartPtr->LogLqhKeyReqSent = ZTRUE;
- signal->theData[0] = ZLOG_LQHKEYREQ;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
-
- terrorCode = ZTAIL_PROBLEM_IN_LOG_ERROR;
- abortErrorLab(signal);
- return;
- }
-
- if (regLogPartPtr->logPartState == LogPartRecord::IDLE) {
- ;
- } else if (regLogPartPtr->logPartState == LogPartRecord::ACTIVE) {
- jam();
- linkWaitLog(signal, logPartPtr);
- regTcPtr->transactionState = TcConnectionrec::LOG_QUEUED;
- return;
- } else {
- if ((regLogPartPtr->firstLogQueue != RNIL) &&
- (regLogPartPtr->LogLqhKeyReqSent == ZFALSE)) {
-/* -------------------------------------------------- */
-/* WE HAVE A PROBLEM IN THAT THE LOG HAS NO */
-/* ROOM FOR ADDITIONAL OPERATIONS AT THE MOMENT.*/
-/* -------------------------------------------------- */
-/* -------------------------------------------------- */
-/* WE MUST STILL RESTART QUEUED OPERATIONS SO */
-/* THEY ALSO CAN BE ABORTED. */
-/* -------------------------------------------------- */
- regLogPartPtr->LogLqhKeyReqSent = ZTRUE;
- signal->theData[0] = ZLOG_LQHKEYREQ;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
- if (regLogPartPtr->logPartState == LogPartRecord::TAIL_PROBLEM) {
- jam();
- terrorCode = ZTAIL_PROBLEM_IN_LOG_ERROR;
- } else {
- ndbrequire(regLogPartPtr->logPartState == LogPartRecord::FILE_CHANGE_PROBLEM);
- jam();
- terrorCode = ZFILE_CHANGE_PROBLEM_IN_LOG_ERROR;
- }//if
- abortErrorLab(signal);
- return;
- }//if
- regLogPartPtr->logPartState = LogPartRecord::ACTIVE;
- logFilePtr.i = regLogPartPtr->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
-/* -------------------------------------------------- */
-/* CHECK IF A NEW MBYTE IS TO BE STARTED. IF */
-/* SO INSERT A NEXT LOG RECORD, WRITE THE LOG */
-/* AND PLACE THE LOG POINTER ON THE NEW POSITION*/
-/* IF A NEW FILE IS TO BE USED, CHANGE FILE AND */
-/* ALSO START OPENING THE NEXT LOG FILE. IF A */
-/* LAP HAS BEEN COMPLETED THEN ADD ONE TO LAP */
-/* COUNTER. */
-/* -------------------------------------------------- */
- checkNewMbyte(signal);
-/* -------------------------------------------------- */
-/* INSERT THE OPERATION RECORD LAST IN THE LIST */
-/* OF NOT COMPLETED OPERATIONS. ALSO RECORD THE */
-/* FILE NO, PAGE NO AND PAGE INDEX OF THE START */
-/* OF THIS LOG RECORD. */
-/* IT IS NOT ALLOWED TO INSERT IT INTO THE LIST */
-/* BEFORE CHECKING THE NEW MBYTE SINCE THAT WILL*/
-/* CAUSE THE OLD VALUES OF TC_CONNECTPTR TO BE */
-/* USED IN WRITE_FILE_DESCRIPTOR. */
-/* -------------------------------------------------- */
- Uint32 tcIndex = tcConnectptr.i;
- tmpTcConnectptr.i = regLogPartPtr->lastLogTcrec;
- regLogPartPtr->lastLogTcrec = tcIndex;
- if (tmpTcConnectptr.i == RNIL) {
- jam();
- regLogPartPtr->firstLogTcrec = tcIndex;
- } else {
- ptrCheckGuard(tmpTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- tmpTcConnectptr.p->nextLogTcrec = tcIndex;
- }//if
- Uint32 fileNo = logFilePtr.p->fileNo;
- tcurrentFilepage = logFilePtr.p->currentFilepage;
- logPagePtr.i = logFilePtr.p->currentLogpage;
- regTcPtr->nextLogTcrec = RNIL;
- regTcPtr->prevLogTcrec = tmpTcConnectptr.i;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- Uint32 pageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- regTcPtr->logStartFileNo = fileNo;
- regTcPtr->logStartPageNo = tcurrentFilepage;
- regTcPtr->logStartPageIndex = pageIndex;
-/* -------------------------------------------------- */
-/* WRITE THE LOG HEADER OF THIS OPERATION. */
-/* -------------------------------------------------- */
- writeLogHeader(signal);
-/* -------------------------------------------------- */
-/* WRITE THE TUPLE KEY OF THIS OPERATION. */
-/* -------------------------------------------------- */
- writeKey(signal);
-/* -------------------------------------------------- */
-/* WRITE THE ATTRIBUTE INFO OF THIS OPERATION. */
-/* -------------------------------------------------- */
- writeAttrinfoLab(signal);
-
- logNextStart(signal);
-/* -------------------------------------------------- */
-/* RESET THE STATE OF THE LOG PART. IF ANY */
-/* OPERATIONS HAVE QUEUED THEN START THE FIRST */
-/* OF THESE. */
-/* -------------------------------------------------- */
-/* -------------------------------------------------- */
-/* CONTINUE WITH PACKING OF LQHKEYREQ */
-/* -------------------------------------------------- */
- tcurrentFilepage = logFilePtr.p->currentFilepage;
- if (logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] == ZPAGE_HEADER_SIZE) {
- jam();
- tcurrentFilepage--;
- }//if
- regTcPtr->logStopPageNo = tcurrentFilepage;
- regTcPtr->logWriteState = TcConnectionrec::WRITTEN;
- if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
-/* -------------------------------------------------- */
-/* AN ABORT HAVE BEEN ORDERED. THE ABORT WAITED */
-/* FOR THE LOG WRITE TO BE COMPLETED. NOW WE */
-/* CAN PROCEED WITH THE NORMAL ABORT HANDLING. */
-/* -------------------------------------------------- */
- abortCommonLab(signal);
- return;
- }//if
- if (regTcPtr->dirtyOp != ZTRUE) {
- packLqhkeyreqLab(signal);
- } else {
- /* ----------------------------------------------------------------------
- * I NEED TO INSERT A COMMIT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
- * TRANSACTION. SINCE WE RELEASED THE LOG LOCK JUST NOW NO ONE ELSE CAN BE
- * ACTIVE IN WRITING THE LOG. WE THUS WRITE THE LOG WITHOUT GETTING A LOCK
- * SINCE WE ARE ONLY WRITING A COMMIT LOG RECORD.
- * ---------------------------------------------------------------------- */
- writeCommitLog(signal, logPartPtr);
- /* ----------------------------------------------------------------------
- * DIRTY OPERATIONS SHOULD COMMIT BEFORE THEY PACK THE REQUEST/RESPONSE.
- * ---------------------------------------------------------------------- */
- localCommitLab(signal);
- }//if
-}//Dblqh::logLqhkeyreqLab()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEND LQHKEYREQ */
-/* */
-/* NO STATE CHECKING SINCE THE SIGNAL IS A LOCAL SIGNAL. THE EXECUTION OF */
-/* THE OPERATION IS COMPLETED. IT IS NOW TIME TO SEND THE OPERATION TO THE */
-/* NEXT REPLICA OR TO TC. */
-/* ------------------------------------------------------------------------- */
-void Dblqh::packLqhkeyreqLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->nextReplica == ZNIL) {
-/* ------------------------------------------------------------------------- */
-/* ------- SEND LQHKEYCONF ------- */
-/* */
-/* ------------------------------------------------------------------------- */
- sendLqhkeyconfTc(signal, regTcPtr->tcBlockref);
- if (! (regTcPtr->dirtyOp ||
- (regTcPtr->operation == ZREAD && regTcPtr->opSimple)))
- {
- jam();
- regTcPtr->transactionState = TcConnectionrec::PREPARED;
- releaseOprec(signal);
- } else {
- jam();
-
-/*************************************************************>*/
-/* DIRTY WRITES ARE USED IN TWO SITUATIONS. THE FIRST */
-/* SITUATION IS WHEN THEY ARE USED TO UPDATE COUNTERS AND*/
-/* OTHER ATTRIBUTES WHICH ARE NOT SENSITIVE TO CONSISTE- */
-/* NCY. THE SECOND SITUATION IS BY OPERATIONS THAT ARE */
-/* SENT AS PART OF A COPY FRAGMENT PROCESS. */
-/* */
-/* DURING A COPY FRAGMENT PROCESS THERE IS NO LOGGING */
-/* ONGOING SINCE THE FRAGMENT IS NOT COMPLETE YET. THE */
-/* LOGGING STARTS AFTER COMPLETING THE LAST COPY TUPLE */
-/* OPERATION. THE EXECUTION OF THE LAST COPY TUPLE DOES */
-/* ALSO START A LOCAL CHECKPOINT SO THAT THE FRAGMENT */
-/* REPLICA IS RECOVERABLE. THUS GLOBAL CHECKPOINT ID FOR */
-/* THOSE OPERATIONS ARE NOT INTERESTING. */
-/* */
-/* A DIRTY WRITE IS BY DEFINITION NOT CONSISTENT. THUS */
-/* IT CAN USE ANY GLOBAL CHECKPOINT. THE IDEA HERE IS TO */
-/* ALWAYS USE THE LATEST DEFINED GLOBAL CHECKPOINT ID IN */
-/* THIS NODE. */
-/*************************************************************>*/
- cleanUp(signal);
- }//if
- return;
- }//if
-/* ------------------------------------------------------------------------- */
-/* ------- SEND LQHKEYREQ ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* THERE ARE MORE REPLICAS TO SEND THE OPERATION TO. A NEW LQHKEYREQ WILL BE */
-/* PREPARED FOR THE NEXT REPLICA. */
-/* ------------------------------------------------------------------------- */
-/* CLEAR REPLICA TYPE, ATTRINFO INDICATOR (IN LQHKEYREQ), */
-/* INTERPRETED EXECUTION, SEQUENTIAL NUMBER OF REPLICA. */
-// Set bit indicating Client and TC record not the same.
-// Set readlenAi indicator if readlenAi != 0
-// Stored Procedure Indicator not set.
-/* ------------------------------------------------------------------------- */
- LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)&signal->theData[0];
-
- UintR Treqinfo;
- UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
- Treqinfo = preComputedRequestInfoMask & regTcPtr->reqinfo;
-
- Uint32 nextNodeId = regTcPtr->nextReplica;
- Uint32 nextVersion = getNodeInfo(nextNodeId).m_version;
- UintR TAiLen = regTcPtr->reclenAiLqhkey;
-
- UintR TapplAddressIndicator = (regTcPtr->nextSeqNoReplica == 0 ? 0 : 1);
- LqhKeyReq::setApplicationAddressFlag(Treqinfo, TapplAddressIndicator);
- LqhKeyReq::setInterpretedFlag(Treqinfo, regTcPtr->opExec);
- LqhKeyReq::setSeqNoReplica(Treqinfo, regTcPtr->nextSeqNoReplica);
- LqhKeyReq::setAIInLqhKeyReq(Treqinfo, TAiLen);
-
- if (unlikely(nextVersion < NDBD_ROWID_VERSION))
- {
- LqhKeyReq::setLockType(Treqinfo, regTcPtr->lockType);
- }
- else
- {
- regTcPtr->m_use_rowid |=
- fragptr.p->m_copy_started_state == Fragrecord::AC_NR_COPY;
- LqhKeyReq::setRowidFlag(Treqinfo, regTcPtr->m_use_rowid);
- }
-
- if (LqhKeyReq::getRowidFlag(Treqinfo))
- {
- //ndbassert(LqhKeyReq::getOperation(Treqinfo) == ZINSERT);
- }
- else
- {
- ndbassert(LqhKeyReq::getOperation(Treqinfo) != ZINSERT);
- }
-
- UintR TreadLenAiInd = (regTcPtr->readlenAi == 0 ? 0 : 1);
- UintR TsameLqhAndClient = (tcConnectptr.i ==
- regTcPtr->tcOprec ? 0 : 1);
- LqhKeyReq::setSameClientAndTcFlag(Treqinfo, TsameLqhAndClient);
- LqhKeyReq::setReturnedReadLenAIFlag(Treqinfo, TreadLenAiInd);
-
- UintR TotReclenAi = regTcPtr->totSendlenAi;
-/* ------------------------------------------------------------------------- */
-/* WE ARE NOW PREPARED TO SEND THE LQHKEYREQ. WE HAVE TO DECIDE IF ATTRINFO */
-/* IS INCLUDED IN THE LQHKEYREQ SIGNAL AND THEN SEND IT. */
-/* TAKE OVER SCAN OPERATION IS NEVER USED ON BACKUPS, LOG RECORDS AND START-UP*/
-/* OF NEW REPLICA AND THUS ONLY TOT_SENDLEN_AI IS USED THE UPPER 16 BITS ARE */
-/* ZERO. */
-/* ------------------------------------------------------------------------- */
- sig0 = tcConnectptr.i;
- sig1 = regTcPtr->savePointId;
- sig2 = regTcPtr->hashValue;
- sig4 = regTcPtr->tcBlockref;
-
- lqhKeyReq->clientConnectPtr = sig0;
- lqhKeyReq->attrLen = TotReclenAi;
- lqhKeyReq->savePointId = sig1;
- lqhKeyReq->hashValue = sig2;
- lqhKeyReq->requestInfo = Treqinfo;
- lqhKeyReq->tcBlockref = sig4;
-
- sig0 = regTcPtr->tableref + ((regTcPtr->schemaVersion << 16) & 0xFFFF0000);
- sig1 = regTcPtr->fragmentid + (regTcPtr->nodeAfterNext[0] << 16);
- sig2 = regTcPtr->transid[0];
- sig3 = regTcPtr->transid[1];
- sig4 = regTcPtr->applRef;
- sig5 = regTcPtr->applOprec;
- sig6 = regTcPtr->tcOprec;
- UintR nextPos = (TapplAddressIndicator << 1);
-
- lqhKeyReq->tableSchemaVersion = sig0;
- lqhKeyReq->fragmentData = sig1;
- lqhKeyReq->transId1 = sig2;
- lqhKeyReq->transId2 = sig3;
- lqhKeyReq->noFiredTriggers = regTcPtr->noFiredTriggers;
- lqhKeyReq->variableData[0] = sig4;
- lqhKeyReq->variableData[1] = sig5;
- lqhKeyReq->variableData[2] = sig6;
-
- nextPos += TsameLqhAndClient;
-
- if ((regTcPtr->lastReplicaNo - regTcPtr->nextSeqNoReplica) > 1) {
- sig0 = (UintR)regTcPtr->nodeAfterNext[1] +
- (UintR)(regTcPtr->nodeAfterNext[2] << 16);
- lqhKeyReq->variableData[nextPos] = sig0;
- nextPos++;
- }//if
- sig0 = regTcPtr->readlenAi;
- sig1 = regTcPtr->tupkeyData[0];
- sig2 = regTcPtr->tupkeyData[1];
- sig3 = regTcPtr->tupkeyData[2];
- sig4 = regTcPtr->tupkeyData[3];
-
- lqhKeyReq->variableData[nextPos] = sig0;
- nextPos += TreadLenAiInd;
- lqhKeyReq->variableData[nextPos] = sig1;
- lqhKeyReq->variableData[nextPos + 1] = sig2;
- lqhKeyReq->variableData[nextPos + 2] = sig3;
- lqhKeyReq->variableData[nextPos + 3] = sig4;
- UintR TkeyLen = LqhKeyReq::getKeyLen(Treqinfo);
- if (TkeyLen < 4) {
- nextPos += TkeyLen;
- } else {
- nextPos += 4;
- }//if
-
- sig0 = regTcPtr->gci;
- Local_key tmp = regTcPtr->m_row_id;
-
- lqhKeyReq->variableData[nextPos + 0] = tmp.m_page_no;
- lqhKeyReq->variableData[nextPos + 1] = tmp.m_page_idx;
- nextPos += 2*LqhKeyReq::getRowidFlag(Treqinfo);
-
- lqhKeyReq->variableData[nextPos + 0] = sig0;
- nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
-
- BlockReference lqhRef = calcLqhBlockRef(regTcPtr->nextReplica);
-
- if (likely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength <= 25))
- {
- jam();
- sig0 = regTcPtr->firstAttrinfo[0];
- sig1 = regTcPtr->firstAttrinfo[1];
- sig2 = regTcPtr->firstAttrinfo[2];
- sig3 = regTcPtr->firstAttrinfo[3];
- sig4 = regTcPtr->firstAttrinfo[4];
-
- lqhKeyReq->variableData[nextPos] = sig0;
- lqhKeyReq->variableData[nextPos + 1] = sig1;
- lqhKeyReq->variableData[nextPos + 2] = sig2;
- lqhKeyReq->variableData[nextPos + 3] = sig3;
- lqhKeyReq->variableData[nextPos + 4] = sig4;
-
- nextPos += TAiLen;
- TAiLen = 0;
- }
- else
- {
- Treqinfo &= ~(Uint32)(RI_AI_IN_THIS_MASK << RI_AI_IN_THIS_SHIFT);
- lqhKeyReq->requestInfo = Treqinfo;
- }
-
- sendSignal(lqhRef, GSN_LQHKEYREQ, signal,
- nextPos + LqhKeyReq::FixedSignalLength, JBB);
- if (regTcPtr->primKeyLen > 4) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* MORE THAN 4 WORDS OF KEY DATA IS IN THE OPERATION. THEREFORE WE NEED TO */
-/* PREPARE A KEYINFO SIGNAL. MORE THAN ONE KEYINFO SIGNAL CAN BE SENT. */
-/* ------------------------------------------------------------------------- */
- sendTupkey(signal);
- }//if
-/* ------------------------------------------------------------------------- */
-/* NOW I AM PREPARED TO SEND ALL THE ATTRINFO SIGNALS. AT THE MOMENT A LOOP */
-/* SENDS ALL AT ONCE. LATER WE HAVE TO ADDRESS THE PROBLEM THAT THESE COULD */
-/* LEAD TO BUFFER EXPLOSION => NODE CRASH. */
-/* ------------------------------------------------------------------------- */
-/* NEW CODE TO SEND ATTRINFO IN PACK_LQHKEYREQ */
-/* THIS CODE USES A REAL-TIME BREAK AFTER */
-/* SENDING 16 SIGNALS. */
-/* -------------------------------------------------- */
- sig0 = regTcPtr->tcOprec;
- sig1 = regTcPtr->transid[0];
- sig2 = regTcPtr->transid[1];
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->theData[2] = sig2;
-
- if (unlikely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength > 25))
- {
- jam();
- /**
- * 4 replicas...
- */
- memcpy(signal->theData+3, regTcPtr->firstAttrinfo, TAiLen << 2);
- sendSignal(lqhRef, GSN_ATTRINFO, signal, 3 + TAiLen, JBB);
- }
-
- AttrbufPtr regAttrinbufptr;
- regAttrinbufptr.i = regTcPtr->firstAttrinbuf;
- while (regAttrinbufptr.i != RNIL) {
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
- jam();
- Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
- ndbrequire(dataLen != 0);
- MEMCOPY_NO_WORDS(&signal->theData[3], &regAttrinbufptr.p->attrbuf[0], dataLen);
- regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
- sendSignal(lqhRef, GSN_ATTRINFO, signal, dataLen + 3, JBB);
- }//while
- regTcPtr->transactionState = TcConnectionrec::PREPARED;
- if (regTcPtr->dirtyOp == ZTRUE) {
- jam();
-/*************************************************************>*/
-/* DIRTY WRITES ARE USED IN TWO SITUATIONS. THE FIRST */
-/* SITUATION IS WHEN THEY ARE USED TO UPDATE COUNTERS AND*/
-/* OTHER ATTRIBUTES WHICH ARE NOT SENSITIVE TO CONSISTE- */
-/* NCY. THE SECOND SITUATION IS BY OPERATIONS THAT ARE */
-/* SENT AS PART OF A COPY FRAGMENT PROCESS. */
-/* */
-/* DURING A COPY FRAGMENT PROCESS THERE IS NO LOGGING */
-/* ONGOING SINCE THE FRAGMENT IS NOT COMPLETE YET. THE */
-/* LOGGING STARTS AFTER COMPLETING THE LAST COPY TUPLE */
-/* OPERATION. THE EXECUTION OF THE LAST COPY TUPLE DOES */
-/* ALSO START A LOCAL CHECKPOINT SO THAT THE FRAGMENT */
-/* REPLICA IS RECOVERABLE. THUS GLOBAL CHECKPOINT ID FOR */
-/* THOSE OPERATIONS ARE NOT INTERESTING. */
-/* */
-/* A DIRTY WRITE IS BY DEFINITION NOT CONSISTENT. THUS */
-/* IT CAN USE ANY GLOBAL CHECKPOINT. THE IDEA HERE IS TO */
-/* ALWAYS USE THE LATEST DEFINED GLOBAL CHECKPOINT ID IN */
-/* THIS NODE. */
-/*************************************************************>*/
- cleanUp(signal);
- return;
- }//if
- /* ------------------------------------------------------------------------
- * ALL INFORMATION NEEDED BY THE COMMIT PHASE AND COMPLETE PHASE IS
- * KEPT IN THE TC_CONNECT RECORD. TO ENSURE PROPER USE OF MEMORY
- * RESOURCES WE DEALLOCATE THE ATTRINFO RECORD AND KEY RECORDS
- * AS SOON AS POSSIBLE.
- * ------------------------------------------------------------------------ */
- releaseOprec(signal);
-}//Dblqh::packLqhkeyreqLab()
-
-/* ========================================================================= */
-/* ==== CHECK IF THE LOG RECORD FITS INTO THE CURRENT MBYTE, ======= */
-/* OTHERWISE SWITCH TO NEXT MBYTE. */
-/* */
-/* ========================================================================= */
-void Dblqh::checkNewMbyte(Signal* signal)
-{
- UintR tcnmTmp;
- UintR ttotalLogSize;
-
-/* -------------------------------------------------- */
-/* CHECK IF A NEW MBYTE OF LOG RECORD IS TO BE */
-/* OPENED BEFORE WRITING THE LOG RECORD. NO LOG */
-/* RECORDS ARE ALLOWED TO SPAN A MBYTE BOUNDARY */
-/* */
-/* INPUT: TC_CONNECTPTR THE OPERATION */
-/* LOG_FILE_PTR THE LOG FILE */
-/* OUTPUT: LOG_FILE_PTR THE NEW LOG FILE */
-/* -------------------------------------------------- */
- ttotalLogSize = ZLOG_HEAD_SIZE + tcConnectptr.p->currTupAiLen;
- ttotalLogSize = ttotalLogSize + tcConnectptr.p->primKeyLen;
- tcnmTmp = logFilePtr.p->remainingWordsInMbyte;
- if ((ttotalLogSize + ZNEXT_LOG_SIZE) <= tcnmTmp) {
- ndbrequire(tcnmTmp >= ttotalLogSize);
- logFilePtr.p->remainingWordsInMbyte = tcnmTmp - ttotalLogSize;
- return;
- } else {
- jam();
-/* -------------------------------------------------- */
-/* IT WAS NOT ENOUGH SPACE IN THIS MBYTE FOR */
-/* THIS LOG RECORD. MOVE TO NEXT MBYTE */
-/* THIS MIGHT INCLUDE CHANGING LOG FILE */
-/* -------------------------------------------------- */
-/* WE HAVE TO INSERT A NEXT LOG RECORD FIRST */
-/* -------------------------------------------------- */
-/* THEN CONTINUE BY WRITING THE FILE DESCRIPTORS*/
-/* -------------------------------------------------- */
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- changeMbyte(signal);
- tcnmTmp = logFilePtr.p->remainingWordsInMbyte;
- }//if
- ndbrequire(tcnmTmp >= ttotalLogSize);
- logFilePtr.p->remainingWordsInMbyte = tcnmTmp - ttotalLogSize;
-}//Dblqh::checkNewMbyte()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE OPERATION HEADER TO LOG -------
- *
- * SUBROUTINE SHORT NAME: WLH
- * ------------------------------------------------------------------------- */
-void Dblqh::writeLogHeader(Signal* signal)
-{
- Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- Uint32 hashValue = tcConnectptr.p->hashValue;
- Uint32 operation = tcConnectptr.p->operation;
- Uint32 keyLen = tcConnectptr.p->primKeyLen;
- Uint32 aiLen = tcConnectptr.p->currTupAiLen;
- Local_key rowid = tcConnectptr.p->m_row_id;
- Uint32 totLogLen = ZLOG_HEAD_SIZE + aiLen + keyLen;
-
- if ((logPos + ZLOG_HEAD_SIZE) < ZPAGE_SIZE) {
- Uint32* dataPtr = &logPagePtr.p->logPageWord[logPos];
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + ZLOG_HEAD_SIZE;
- dataPtr[0] = ZPREP_OP_TYPE;
- dataPtr[1] = totLogLen;
- dataPtr[2] = hashValue;
- dataPtr[3] = operation;
- dataPtr[4] = aiLen;
- dataPtr[5] = keyLen;
- dataPtr[6] = rowid.m_page_no;
- dataPtr[7] = rowid.m_page_idx;
- } else {
- writeLogWord(signal, ZPREP_OP_TYPE);
- writeLogWord(signal, totLogLen);
- writeLogWord(signal, hashValue);
- writeLogWord(signal, operation);
- writeLogWord(signal, aiLen);
- writeLogWord(signal, keyLen);
- writeLogWord(signal, rowid.m_page_no);
- writeLogWord(signal, rowid.m_page_idx);
- }//if
-}//Dblqh::writeLogHeader()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE TUPLE KEY TO LOG -------
- *
- * SUBROUTINE SHORT NAME: WK
- * ------------------------------------------------------------------------- */
-void Dblqh::writeKey(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 logPos, endPos, dataLen;
- Int32 remainingLen;
- logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- remainingLen = regTcPtr->primKeyLen;
- dataLen = remainingLen;
- if (remainingLen > 4)
- dataLen = 4;
- remainingLen -= dataLen;
- endPos = logPos + dataLen;
- if (endPos < ZPAGE_SIZE) {
- MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
- &regTcPtr->tupkeyData[0],
- dataLen);
- } else {
- jam();
- for (Uint32 i = 0; i < dataLen; i++)
- writeLogWord(signal, regTcPtr->tupkeyData[i]);
- endPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- }//if
- DatabufPtr regDatabufptr;
- regDatabufptr.i = regTcPtr->firstTupkeybuf;
- while (remainingLen > 0) {
- logPos = endPos;
- ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
- dataLen = remainingLen;
- if (remainingLen > 4)
- dataLen = 4;
- remainingLen -= dataLen;
- endPos += dataLen;
- if (endPos < ZPAGE_SIZE) {
- MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
- &regDatabufptr.p->data[0],
- dataLen);
- } else {
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
- for (Uint32 i = 0; i < dataLen; i++)
- writeLogWord(signal, regDatabufptr.p->data[i]);
- endPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- }//if
- regDatabufptr.i = regDatabufptr.p->nextDatabuf;
- }//while
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = endPos;
- ndbrequire(regDatabufptr.i == RNIL);
-}//Dblqh::writeKey()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE ATTRINFO TO LOG -------
- *
- * SUBROUTINE SHORT NAME: WA
- * ------------------------------------------------------------------------- */
-void Dblqh::writeAttrinfoLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 totLen = regTcPtr->currTupAiLen;
- if (totLen == 0)
- return;
- Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- Uint32 lqhLen = regTcPtr->reclenAiLqhkey;
- ndbrequire(totLen >= lqhLen);
- Uint32 endPos = logPos + lqhLen;
- totLen -= lqhLen;
- if (endPos < ZPAGE_SIZE) {
- MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
- &regTcPtr->firstAttrinfo[0],
- lqhLen);
- } else {
- for (Uint32 i = 0; i < lqhLen; i++)
- writeLogWord(signal, regTcPtr->firstAttrinfo[i]);
- endPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- }//if
- AttrbufPtr regAttrinbufptr;
- regAttrinbufptr.i = regTcPtr->firstAttrinbuf;
- while (totLen > 0) {
- logPos = endPos;
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
- Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
- ndbrequire(totLen >= dataLen);
- ndbrequire(dataLen > 0);
- totLen -= dataLen;
- endPos += dataLen;
- if (endPos < ZPAGE_SIZE) {
- MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[logPos],
- &regAttrinbufptr.p->attrbuf[0],
- dataLen);
- } else {
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
- for (Uint32 i = 0; i < dataLen; i++)
- writeLogWord(signal, regAttrinbufptr.p->attrbuf[i]);
- endPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- }//if
- regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
- }//while
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = endPos;
- ndbrequire(regAttrinbufptr.i == RNIL);
-}//Dblqh::writeAttrinfoLab()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEND TUPLE KEY IN KEYINFO SIGNAL(S) ------- */
-/* */
-/* SUBROUTINE SHORT NAME: STU */
-/* ------------------------------------------------------------------------- */
-void Dblqh::sendTupkey(Signal* signal)
-{
- UintR TdataPos = 3;
- BlockReference lqhRef = calcLqhBlockRef(tcConnectptr.p->nextReplica);
- signal->theData[0] = tcConnectptr.p->tcOprec;
- signal->theData[1] = tcConnectptr.p->transid[0];
- signal->theData[2] = tcConnectptr.p->transid[1];
- databufptr.i = tcConnectptr.p->firstTupkeybuf;
- do {
- ptrCheckGuard(databufptr, cdatabufFileSize, databuf);
- signal->theData[TdataPos] = databufptr.p->data[0];
- signal->theData[TdataPos + 1] = databufptr.p->data[1];
- signal->theData[TdataPos + 2] = databufptr.p->data[2];
- signal->theData[TdataPos + 3] = databufptr.p->data[3];
-
- databufptr.i = databufptr.p->nextDatabuf;
- TdataPos += 4;
- if (databufptr.i == RNIL) {
- jam();
- sendSignal(lqhRef, GSN_KEYINFO, signal, TdataPos, JBB);
- return;
- } else if (TdataPos == 23) {
- jam();
- sendSignal(lqhRef, GSN_KEYINFO, signal, 23, JBB);
- TdataPos = 3;
- }
- } while (1);
-}//Dblqh::sendTupkey()
-
-void Dblqh::cleanUp(Signal* signal)
-{
- releaseOprec(signal);
- deleteTransidHash(signal);
- releaseTcrec(signal, tcConnectptr);
-}//Dblqh::cleanUp()
-
-/* --------------------------------------------------------------------------
- * ---- RELEASE ALL RECORDS CONNECTED TO THE OPERATION RECORD AND THE ----
- * OPERATION RECORD ITSELF
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseOprec(Signal* signal)
-{
- UintR Tmpbuf;
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
-/* ---- RELEASE DATA BUFFERS ------------------- */
- DatabufPtr regDatabufptr;
- regDatabufptr.i = regTcPtr->firstTupkeybuf;
-/* --------------------------------------------------------------------------
- * ------- RELEASE DATA BUFFERS -------
- *
- * ------------------------------------------------------------------------- */
-
- while (regDatabufptr.i != RNIL) {
- jam();
- ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
- Tmpbuf = regDatabufptr.p->nextDatabuf;
- regDatabufptr.p->nextDatabuf = cfirstfreeDatabuf;
- cfirstfreeDatabuf = regDatabufptr.i;
- regDatabufptr.i = Tmpbuf;
- }//while
-/* ---- RELEASE ATTRINFO BUFFERS ------------------- */
- AttrbufPtr regAttrinbufptr;
- regAttrinbufptr.i = regTcPtr->firstAttrinbuf;
- /* ########################################################################
- * ####### RELEASE_ATTRINBUF #######
- *
- * ####################################################################### */
- while (regAttrinbufptr.i != RNIL) {
- jam();
- regAttrinbufptr.i= release_attrinbuf(regAttrinbufptr.i);
- }//while
- regTcPtr->firstAttrinbuf = RNIL;
- regTcPtr->lastAttrinbuf = RNIL;
- regTcPtr->firstTupkeybuf = RNIL;
- regTcPtr->lastTupkeybuf = RNIL;
-
- if (regTcPtr->m_dealloc)
- {
- jam();
- regTcPtr->m_dealloc = 0;
-
- if (TRACENR_FLAG)
- TRACENR("DELETED: " << regTcPtr->m_row_id << endl);
-
- TRACE_OP(regTcPtr, "DEALLOC");
-
- signal->theData[0] = regTcPtr->fragmentid;
- signal->theData[1] = regTcPtr->tableref;
- signal->theData[2] = regTcPtr->m_row_id.m_page_no;
- signal->theData[3] = regTcPtr->m_row_id.m_page_idx;
- signal->theData[4] = RNIL;
- EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 5);
- }
-}//Dblqh::releaseOprec()
-
-/* ------------------------------------------------------------------------- */
-/* ------ DELETE TRANSACTION ID FROM HASH TABLE ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::deleteTransidHash(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- TcConnectionrecPtr prevHashptr;
- TcConnectionrecPtr nextHashptr;
-
- prevHashptr.i = regTcPtr->prevHashRec;
- nextHashptr.i = regTcPtr->nextHashRec;
- if (prevHashptr.i != RNIL) {
- jam();
- ptrCheckGuard(prevHashptr, ctcConnectrecFileSize, tcConnectionrec);
- prevHashptr.p->nextHashRec = nextHashptr.i;
- } else {
- jam();
-/* ------------------------------------------------------------------------- */
-/* THE OPERATION WAS PLACED FIRST IN THE LIST OF THE HASH TABLE. NEED TO SET */
-/* A NEW LEADER OF THE LIST. */
-/* ------------------------------------------------------------------------- */
- Uint32 hashIndex = (regTcPtr->transid[0] ^ regTcPtr->tcOprec) & 1023;
- ctransidHash[hashIndex] = nextHashptr.i;
- }//if
- if (nextHashptr.i != RNIL) {
- jam();
- ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
- nextHashptr.p->prevHashRec = prevHashptr.i;
- }//if
-}//Dblqh::deleteTransidHash()
-
-/* -------------------------------------------------------------------------
- * ------- RELEASE OPERATION FROM ACTIVE LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME = RAF
- * ------------------------------------------------------------------------- */
-/* ######################################################################### */
-/* ####### TRANSACTION MODULE ####### */
-/* THIS MODULE HANDLES THE COMMIT AND THE COMPLETE PHASE. */
-/* ######################################################################### */
-void Dblqh::warningReport(Signal* signal, int place)
-{
- switch (place) {
- case 0:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMMIT in wrong state in Dblqh" << endl;
-#endif
- break;
- case 1:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMMIT with wrong transid in Dblqh" << endl;
-#endif
- break;
- case 2:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMPLETE in wrong state in Dblqh" << endl;
-#endif
- break;
- case 3:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMPLETE with wrong transid in Dblqh" << endl;
-#endif
- break;
- case 4:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMMITREQ in wrong state in Dblqh" << endl;
-#endif
- break;
- case 5:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMMITREQ with wrong transid in Dblqh" << endl;
-#endif
- break;
- case 6:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMPLETEREQ in wrong state in Dblqh" << endl;
-#endif
- break;
- case 7:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMPLETEREQ with wrong transid in Dblqh" << endl;
-#endif
- break;
- case 8:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received ABORT with non-existing transid in Dblqh" << endl;
-#endif
- break;
- case 9:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received ABORTREQ with non-existing transid in Dblqh" << endl;
-#endif
- break;
- case 10:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received ABORTREQ in wrong state in Dblqh" << endl;
-#endif
- break;
- case 11:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMMIT when tc-rec released in Dblqh" << endl;
-#endif
- break;
- case 12:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received COMPLETE when tc-rec released in Dblqh" << endl;
-#endif
- break;
- case 13:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received LQHKEYREF when tc-rec released in Dblqh" << endl;
-#endif
- break;
- case 14:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received LQHKEYREF with wrong transid in Dblqh" << endl;
-#endif
- break;
- case 15:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "W: Received LQHKEYREF when already aborting in Dblqh" << endl;
-#endif
- break;
- case 16:
- jam();
- ndbrequire(cstartPhase == ZNIL);
-#ifdef ABORT_TRACE
- ndbout << "W: Received LQHKEYREF in wrong state in Dblqh" << endl;
-#endif
- break;
- default:
- jam();
- break;
- }//switch
- return;
-}//Dblqh::warningReport()
-
-void Dblqh::errorReport(Signal* signal, int place)
-{
- switch (place) {
- case 0:
- jam();
- break;
- case 1:
- jam();
- break;
- case 2:
- jam();
- break;
- case 3:
- jam();
- break;
- default:
- jam();
- break;
- }//switch
- systemErrorLab(signal, __LINE__);
- return;
-}//Dblqh::errorReport()
-
-/* ************************************************************************>>
- * COMMIT: Start commit request from TC. This signal is originally sent as a
- * packed signal and this function is called from execPACKED_SIGNAL.
- * This is the normal commit protocol where TC first send this signal to the
- * backup node which then will send COMMIT to the primary node. If
- * everything is ok the primary node send COMMITTED back to TC.
- * ************************************************************************>> */
-void Dblqh::execCOMMIT(Signal* signal)
-{
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- Uint32 tcIndex = signal->theData[0];
- Uint32 gci = signal->theData[1];
- Uint32 transid1 = signal->theData[2];
- Uint32 transid2 = signal->theData[3];
- jamEntry();
- if (tcIndex >= ttcConnectrecFileSize) {
- errorReport(signal, 0);
- return;
- }//if
- if (ERROR_INSERTED(5011)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000, 4);
- return;
- }//if
- if (ERROR_INSERTED(5012)) {
- SET_ERROR_INSERT_VALUE(5017);
- sendSignalWithDelay(cownref, GSN_COMMIT, signal, 2000, 4);
- return;
- }//if
- tcConnectptr.i = tcIndex;
- ptrAss(tcConnectptr, regTcConnectionrec);
- if ((tcConnectptr.p->transid[0] == transid1) &&
- (tcConnectptr.p->transid[1] == transid2)) {
-
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- TRACE_OP(regTcPtr, "COMMIT");
-
- CRASH_INSERTION(5048);
- if (ERROR_INSERTED(5049))
- {
- SET_ERROR_INSERT_VALUE(5048);
- }
-
- commitReqLab(signal, gci);
- return;
- }//if
- warningReport(signal, 1);
- return;
-}//Dblqh::execCOMMIT()
-
-/* ************************************************************************>>
- * COMMITREQ: Commit request from TC. This is the commit protocol used if
- * one of the nodes is not behaving correctly. TC explicitly sends COMMITREQ
- * to both the backup and primary node and gets a COMMITCONF back if the
- * COMMIT was ok.
- * ************************************************************************>> */
-void Dblqh::execCOMMITREQ(Signal* signal)
-{
- jamEntry();
- Uint32 reqPtr = signal->theData[0];
- BlockReference reqBlockref = signal->theData[1];
- Uint32 gci = signal->theData[2];
- Uint32 transid1 = signal->theData[3];
- Uint32 transid2 = signal->theData[4];
- Uint32 tcOprec = signal->theData[6];
- if (ERROR_INSERTED(5004)) {
- systemErrorLab(signal, __LINE__);
- }
- if (ERROR_INSERTED(5017)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMMITREQ, signal, 2000, 7);
- return;
- }//if
- if (findTransaction(transid1,
- transid2,
- tcOprec) != ZOK) {
- warningReport(signal, 5);
- return;
- }//if
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- switch (regTcPtr->transactionState) {
- case TcConnectionrec::PREPARED:
- case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
- case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
- jam();
-/*-------------------------------------------------------*/
-/* THE NORMAL CASE. */
-/*-------------------------------------------------------*/
- regTcPtr->reqBlockref = reqBlockref;
- regTcPtr->reqRef = reqPtr;
- regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
- commitReqLab(signal, gci);
- return;
- break;
- case TcConnectionrec::COMMITTED:
- jam();
-/*---------------------------------------------------------*/
-/* FOR SOME REASON THE COMMIT PHASE HAVE BEEN */
-/* FINISHED AFTER A TIME OUT. WE NEED ONLY SEND A */
-/* COMMITCONF SIGNAL. */
-/*---------------------------------------------------------*/
- regTcPtr->reqBlockref = reqBlockref;
- regTcPtr->reqRef = reqPtr;
- regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
- signal->theData[0] = regTcPtr->reqRef;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = regTcPtr->transid[0];
- signal->theData[3] = regTcPtr->transid[1];
- sendSignal(regTcPtr->reqBlockref, GSN_COMMITCONF, signal, 4, JBB);
- break;
- case TcConnectionrec::COMMIT_STOPPED:
- case TcConnectionrec::WAIT_TUP_COMMIT:
- jam();
- regTcPtr->reqBlockref = reqBlockref;
- regTcPtr->reqRef = reqPtr;
- regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
- /*empty*/;
- break;
- default:
- jam();
- warningReport(signal, 4);
- return;
- break;
- }//switch
- return;
-}//Dblqh::execCOMMITREQ()
-
-/* ************************************************************************>>
- * COMPLETE : Complete the transaction. Sent as a packed signal from TC.
- * Works the same way as COMMIT protocol. This is the normal case with both
- * primary and backup working (See COMMIT).
- * ************************************************************************>> */
-void Dblqh::execCOMPLETE(Signal* signal)
-{
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- Uint32 tcIndex = signal->theData[0];
- Uint32 transid1 = signal->theData[1];
- Uint32 transid2 = signal->theData[2];
- jamEntry();
- if (tcIndex >= ttcConnectrecFileSize) {
- errorReport(signal, 1);
- return;
- }//if
- if (ERROR_INSERTED(5042)) {
- ndbrequire(false);
- }
- if (ERROR_INSERTED(5013)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
- return;
- }//if
- if (ERROR_INSERTED(5014)) {
- SET_ERROR_INSERT_VALUE(5018);
- sendSignalWithDelay(cownref, GSN_COMPLETE, signal, 2000, 3);
- return;
- }//if
- tcConnectptr.i = tcIndex;
- ptrAss(tcConnectptr, regTcConnectionrec);
- if ((tcConnectptr.p->transactionState == TcConnectionrec::COMMITTED) &&
- (tcConnectptr.p->transid[0] == transid1) &&
- (tcConnectptr.p->transid[1] == transid2)) {
-
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- TRACE_OP(regTcPtr, "COMPLETE");
-
- if (tcConnectptr.p->seqNoReplica != 0 &&
- tcConnectptr.p->activeCreat == Fragrecord::AC_NORMAL) {
- jam();
- localCommitLab(signal);
- return;
- }
- else if (tcConnectptr.p->seqNoReplica == 0)
- {
- jam();
- completeTransLastLab(signal);
- return;
- }
- else
- {
- jam();
- completeTransNotLastLab(signal);
- return;
- }
- }//if
- if (tcConnectptr.p->transactionState != TcConnectionrec::COMMITTED) {
- warningReport(signal, 2);
- } else {
- warningReport(signal, 3);
- }//if
-}//Dblqh::execCOMPLETE()
-
-/* ************************************************************************>>
- * COMPLETEREQ: Complete request from TC. Same as COMPLETE but used if one
- * node is not working ok (See COMMIT).
- * ************************************************************************>> */
-void Dblqh::execCOMPLETEREQ(Signal* signal)
-{
- jamEntry();
- Uint32 reqPtr = signal->theData[0];
- BlockReference reqBlockref = signal->theData[1];
- Uint32 transid1 = signal->theData[2];
- Uint32 transid2 = signal->theData[3];
- Uint32 tcOprec = signal->theData[5];
- if (ERROR_INSERTED(5005)) {
- systemErrorLab(signal, __LINE__);
- }
- if (ERROR_INSERTED(5018)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMPLETEREQ, signal, 2000, 6);
- return;
- }//if
- if (findTransaction(transid1,
- transid2,
- tcOprec) != ZOK) {
- jam();
-/*---------------------------------------------------------*/
-/* FOR SOME REASON THE COMPLETE PHASE STARTED AFTER */
-/* A TIME OUT. THE TRANSACTION IS GONE. WE NEED TO */
-/* REPORT COMPLETION ANYWAY. */
-/*---------------------------------------------------------*/
- signal->theData[0] = reqPtr;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = transid1;
- signal->theData[3] = transid2;
- sendSignal(reqBlockref, GSN_COMPLETECONF, signal, 4, JBB);
- warningReport(signal, 7);
- return;
- }//if
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- switch (regTcPtr->transactionState) {
- case TcConnectionrec::COMMITTED:
- jam();
- regTcPtr->reqBlockref = reqBlockref;
- regTcPtr->reqRef = reqPtr;
- regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
- /*empty*/;
- break;
-/*---------------------------------------------------------*/
-/* THE NORMAL CASE. */
-/*---------------------------------------------------------*/
- case TcConnectionrec::COMMIT_STOPPED:
- case TcConnectionrec::WAIT_TUP_COMMIT:
- jam();
-/*---------------------------------------------------------*/
-/* FOR SOME REASON THE COMPLETE PHASE STARTED AFTER */
-/* A TIME OUT. WE HAVE SET THE PROPER VARIABLES SUCH */
-/* THAT A COMPLETECONF WILL BE SENT WHEN COMPLETE IS */
-/* FINISHED. */
-/*---------------------------------------------------------*/
- regTcPtr->reqBlockref = reqBlockref;
- regTcPtr->reqRef = reqPtr;
- regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
- return;
- break;
- default:
- jam();
- warningReport(signal, 6);
- return;
- break;
- }//switch
- if (regTcPtr->seqNoReplica != 0 &&
- regTcPtr->activeCreat != Fragrecord::AC_NR_COPY) {
- jam();
- localCommitLab(signal);
- }
- else if (regTcPtr->seqNoReplica == 0)
- {
- jam();
- completeTransLastLab(signal);
- }
- else
- {
- jam();
- completeTransNotLastLab(signal);
- }
-}//Dblqh::execCOMPLETEREQ()
-
-/* ************> */
-/* COMPLETED > */
-/* ************> */
-void Dblqh::execLQHKEYCONF(Signal* signal)
-{
- LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
- Uint32 tcIndex = lqhKeyConf->opPtr;
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- jamEntry();
- if (tcIndex >= ttcConnectrecFileSize) {
- errorReport(signal, 2);
- return;
- }//if
- tcConnectptr.i = tcIndex;
- ptrAss(tcConnectptr, regTcConnectionrec);
- switch (tcConnectptr.p->connectState) {
- case TcConnectionrec::LOG_CONNECTED:
- jam();
- completedLab(signal);
- return;
- break;
- case TcConnectionrec::COPY_CONNECTED:
- jam();
- copyCompletedLab(signal);
- return;
- break;
- default:
- jam();
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dblqh::execLQHKEYCONF()
-
-/* ------------------------------------------------------------------------- */
-/* ------- COMMIT PHASE ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::commitReqLab(Signal* signal, Uint32 gci)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
- TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
- regTcPtr->gci = gci;
- if (transState == TcConnectionrec::PREPARED) {
- if (logWriteState == TcConnectionrec::WRITTEN) {
- jam();
- regTcPtr->transactionState = TcConnectionrec::PREPARED_RECEIVED_COMMIT;
- TcConnectionrecPtr saveTcPtr = tcConnectptr;
- Uint32 blockNo = refToBlock(regTcPtr->tcTupBlockref);
- signal->theData[0] = regTcPtr->tupConnectrec;
- signal->theData[1] = gci;
- EXECUTE_DIRECT(blockNo, GSN_TUP_WRITELOG_REQ, signal, 2);
- jamEntry();
- if (regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_QUEUED) {
- jam();
- return;
- }//if
- ndbrequire(regTcPtr->transactionState == TcConnectionrec::LOG_COMMIT_WRITTEN);
- tcConnectptr = saveTcPtr;
- } else if (logWriteState == TcConnectionrec::NOT_STARTED) {
- jam();
- } else if (logWriteState == TcConnectionrec::NOT_WRITTEN) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* IT IS A READ OPERATION OR OTHER OPERATION THAT DO NOT USE THE LOG. */
-/*---------------------------------------------------------------------------*/
-/*---------------------------------------------------------------------------*/
-/* THE LOG HAS NOT BEEN WRITTEN SINCE THE LOG FLAG WAS FALSE. THIS CAN OCCUR */
-/* WHEN WE ARE STARTING A NEW FRAGMENT. */
-/*---------------------------------------------------------------------------*/
- regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
- } else {
- ndbrequire(logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE STATE WAS SET TO NOT_WRITTEN BY THE OPERATION BUT LATER A SCAN OF ALL */
-/* OPERATION RECORD CHANGED IT INTO NOT_WRITTEN_WAIT. THIS INDICATES THAT WE */
-/* ARE WAITING FOR THIS OPERATION TO COMMIT OR ABORT SO THAT WE CAN FIND THE */
-/* STARTING GLOBAL CHECKPOINT OF THIS NEW FRAGMENT. */
-/*---------------------------------------------------------------------------*/
- checkScanTcCompleted(signal);
- }//if
- } else if (transState == TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL) {
- jam();
- regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
- return;
- } else if (transState == TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL) {
- jam();
- } else {
- warningReport(signal, 0);
- return;
- }//if
- if (regTcPtr->seqNoReplica == 0 ||
- regTcPtr->activeCreat == Fragrecord::AC_NR_COPY) {
- jam();
- localCommitLab(signal);
- return;
- }//if
- commitReplyLab(signal);
- return;
-}//Dblqh::commitReqLab()
-
-void Dblqh::execLQH_WRITELOG_REQ(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Uint32 gci = signal->theData[1];
- Uint32 newestGci = cnewestGci;
- TcConnectionrec::LogWriteState logWriteState = regTcPtr->logWriteState;
- TcConnectionrec::TransactionState transState = regTcPtr->transactionState;
- regTcPtr->gci = gci;
- if (gci > newestGci) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* KEEP TRACK OF NEWEST GLOBAL CHECKPOINT THAT LQH HAS HEARD OF. */
-/* ------------------------------------------------------------------------- */
- cnewestGci = gci;
- }//if
- if (logWriteState == TcConnectionrec::WRITTEN) {
-/*---------------------------------------------------------------------------*/
-/* I NEED TO INSERT A COMMIT LOG RECORD SINCE WE ARE WRITING LOG IN THIS */
-/* TRANSACTION. */
-/*---------------------------------------------------------------------------*/
- jam();
- LogPartRecordPtr regLogPartPtr;
- Uint32 noOfLogPages = cnoOfLogPages;
- jam();
- regLogPartPtr.i = regTcPtr->m_log_part_ptr_i;
- ptrCheckGuard(regLogPartPtr, clogPartFileSize, logPartRecord);
- if ((regLogPartPtr.p->logPartState == LogPartRecord::ACTIVE) ||
- (noOfLogPages == 0)) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS LOG PART WAS CURRENTLY ACTIVE WRITING ANOTHER LOG RECORD. WE MUST */
-/* WAIT UNTIL THIS PART HAS COMPLETED ITS OPERATION. */
-/*---------------------------------------------------------------------------*/
-// We must delay the write of commit info to the log to safe-guard against
-// a crash due to lack of log pages. We temporary stop all log writes to this
-// log part to ensure that we don't get a buffer explosion in the delayed
-// signal buffer instead.
-/*---------------------------------------------------------------------------*/
- linkWaitLog(signal, regLogPartPtr);
- if (transState == TcConnectionrec::PREPARED) {
- jam();
- regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL;
- } else {
- jam();
- ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
- regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_QUEUED;
- }//if
- if (regLogPartPtr.p->logPartState == LogPartRecord::IDLE) {
- jam();
- regLogPartPtr.p->logPartState = LogPartRecord::ACTIVE;
- }//if
- return;
- }//if
- writeCommitLog(signal, regLogPartPtr);
- if (transState == TcConnectionrec::PREPARED) {
- jam();
- regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL;
- } else {
- jam();
- ndbrequire(transState == TcConnectionrec::PREPARED_RECEIVED_COMMIT);
- regTcPtr->transactionState = TcConnectionrec::LOG_COMMIT_WRITTEN;
- }//if
- }//if
-}//Dblqh::execLQH_WRITELOG_REQ()
-
-void Dblqh::localCommitLab(Signal* signal)
-{
- FragrecordPtr regFragptr;
- regFragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
- Fragrecord::FragStatus status = regFragptr.p->fragStatus;
- fragptr = regFragptr;
- switch (status) {
- case Fragrecord::FSACTIVE:
- case Fragrecord::CRASH_RECOVERING:
- case Fragrecord::ACTIVE_CREATION:
- jam();
- commitContinueAfterBlockedLab(signal);
- return;
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::COMMIT_STOPPED;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- ndbrequire(false);
- break;
- }//switch
-}//Dblqh::localCommitLab()
-
-void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
-{
-/* ------------------------------------------------------------------------- */
-/*INPUT: TC_CONNECTPTR ACTIVE OPERATION RECORD */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/*CONTINUE HERE AFTER BEING BLOCKED FOR A WHILE DURING LOCAL CHECKPOINT. */
-/*The operation is already removed from the active list since there is no */
-/*chance for any real-time breaks before we need to release it. */
-/* ------------------------------------------------------------------------- */
-/*ALSO AFTER NORMAL PROCEDURE WE CONTINUE */
-/*WE MUST COMMIT TUP BEFORE ACC TO ENSURE THAT NO ONE RACES IN AND SEES A */
-/*DIRTY STATE IN TUP. */
-/* ------------------------------------------------------------------------- */
- Ptr<TcConnectionrec> regTcPtr = tcConnectptr;
- Ptr<Fragrecord> regFragptr = fragptr;
- Uint32 operation = regTcPtr.p->operation;
- Uint32 dirtyOp = regTcPtr.p->dirtyOp;
- Uint32 opSimple = regTcPtr.p->opSimple;
- if (regTcPtr.p->activeCreat != Fragrecord::AC_IGNORED) {
- if (operation != ZREAD) {
- TupCommitReq * const tupCommitReq =
- (TupCommitReq *)signal->getDataPtrSend();
- Uint32 sig0 = regTcPtr.p->tupConnectrec;
- Uint32 tup = refToBlock(regTcPtr.p->tcTupBlockref);
- jam();
- tupCommitReq->opPtr = sig0;
- tupCommitReq->gci = regTcPtr.p->gci;
- tupCommitReq->hashValue = regTcPtr.p->hashValue;
- tupCommitReq->diskpage = RNIL;
- EXECUTE_DIRECT(tup, GSN_TUP_COMMITREQ, signal,
- TupCommitReq::SignalLength);
-
- if(signal->theData[0] != 0)
- {
- regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP_COMMIT;
- return; // TUP_COMMIT was timesliced
- }
-
- if (TRACENR_FLAG)
- {
- TRACENR("COMMIT: ");
- switch (regTcPtr.p->operation) {
- case ZREAD: TRACENR("READ"); break;
- case ZUPDATE: TRACENR("UPDATE"); break;
- case ZWRITE: TRACENR("WRITE"); break;
- case ZINSERT: TRACENR("INSERT"); break;
- case ZDELETE: TRACENR("DELETE"); break;
- }
-
- TRACENR(" tab: " << regTcPtr.p->tableref
- << " frag: " << regTcPtr.p->fragmentid
- << " activeCreat: " << (Uint32)regTcPtr.p->activeCreat);
- if (LqhKeyReq::getNrCopyFlag(regTcPtr.p->reqinfo))
- TRACENR(" NrCopy");
- if (LqhKeyReq::getRowidFlag(regTcPtr.p->reqinfo))
- TRACENR(" rowid: " << regTcPtr.p->m_row_id);
- TRACENR(" key: " << regTcPtr.p->tupkeyData[0]);
- TRACENR(endl);
- }
-
- TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
-
- Uint32 acc = refToBlock(regTcPtr.p->tcAccBlockref);
- signal->theData[0] = regTcPtr.p->accConnectrec;
- EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
-
- } else {
- if(!dirtyOp){
- TRACE_OP(regTcPtr.p, "ACC_COMMITREQ");
-
- Uint32 acc = refToBlock(regTcPtr.p->tcAccBlockref);
- signal->theData[0] = regTcPtr.p->accConnectrec;
- EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
- }
-
- if (dirtyOp)
- {
- jam();
- /**
- * The dirtyRead does not send anything but TRANSID_AI from LDM
- */
- fragptr = regFragptr;
- tcConnectptr = regTcPtr;
- cleanUp(signal);
- return;
- }
-
- /**
- * The simpleRead will send a LQHKEYCONF
- * but have already released the locks
- */
- if (opSimple)
- {
- fragptr = regFragptr;
- tcConnectptr = regTcPtr;
- packLqhkeyreqLab(signal);
- return;
- }
- }
- }//if
- jamEntry();
- fragptr = regFragptr;
- tcConnectptr = regTcPtr;
- tupcommit_conf(signal, regTcPtr.p, regFragptr.p);
-}
-
-void
-Dblqh::tupcommit_conf_callback(Signal* signal, Uint32 tcPtrI)
-{
- jamEntry();
-
- tcConnectptr.i = tcPtrI;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- TcConnectionrec * tcPtr = tcConnectptr.p;
-
- ndbrequire(tcPtr->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
-
- FragrecordPtr regFragptr;
- regFragptr.i = tcPtr->fragmentptr;
- c_fragment_pool.getPtr(regFragptr);
- fragptr = regFragptr;
-
- TRACE_OP(tcPtr, "ACC_COMMITREQ");
-
- Uint32 acc = refToBlock(tcPtr->tcAccBlockref);
- signal->theData[0] = tcPtr->accConnectrec;
- EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
- jamEntry();
-
- tcConnectptr.i = tcPtrI;
- tcConnectptr.p = tcPtr;
- tupcommit_conf(signal, tcPtr, regFragptr.p);
-}
-
-void
-Dblqh::tupcommit_conf(Signal* signal,
- TcConnectionrec * tcPtrP,
- Fragrecord * regFragptr)
-{
- Uint32 dirtyOp = tcPtrP->dirtyOp;
- Uint32 seqNoReplica = tcPtrP->seqNoReplica;
- Uint32 activeCreat = tcPtrP->activeCreat;
- if (tcPtrP->gci > regFragptr->newestGci) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*IT IS THE FIRST TIME THIS GLOBAL CHECKPOINT IS INVOLVED IN UPDATING THIS */
-/*FRAGMENT. UPDATE THE VARIABLE THAT KEEPS TRACK OF NEWEST GCI IN FRAGMENT */
-/* ------------------------------------------------------------------------- */
- regFragptr->newestGci = tcPtrP->gci;
- }//if
- if (dirtyOp != ZTRUE)
- {
- if (seqNoReplica == 0 || activeCreat == Fragrecord::AC_NR_COPY)
- {
- jam();
- commitReplyLab(signal);
- return;
- }//if
- if (seqNoReplica == 0)
- {
- jam();
- completeTransLastLab(signal);
- }
- else
- {
- jam();
- completeTransNotLastLab(signal);
- }
- return;
- } else {
-/* ------------------------------------------------------------------------- */
-/*WE MUST HANDLE DIRTY WRITES IN A SPECIAL WAY. THESE OPERATIONS WILL NOT */
-/*SEND ANY COMMIT OR COMPLETE MESSAGES TO OTHER NODES. THEY WILL MERELY SEND */
-/*THOSE SIGNALS INTERNALLY. */
-/* ------------------------------------------------------------------------- */
- if (tcPtrP->abortState == TcConnectionrec::ABORT_IDLE)
- {
- jam();
- if (activeCreat == Fragrecord::AC_NR_COPY)
- {
- jam();
- ndbrequire(LqhKeyReq::getNrCopyFlag(tcPtrP->reqinfo));
- ndbrequire(tcPtrP->m_nr_delete.m_cnt == 0);
- }
- packLqhkeyreqLab(signal);
- }
- else
- {
- ndbrequire(tcPtrP->abortState != TcConnectionrec::NEW_FROM_TC);
- jam();
- sendLqhTransconf(signal, LqhTransConf::Committed);
- cleanUp(signal);
- }//if
- }//if
-}//Dblqh::commitContinueAfterBlockedLab()
-
-void Dblqh::commitReplyLab(Signal* signal)
-{
-/* -------------------------------------------------------------- */
-/* BACKUP AND STAND-BY REPLICAS ONLY UPDATE THE TRANSACTION STATE */
-/* -------------------------------------------------------------- */
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- TcConnectionrec::AbortState abortState = regTcPtr->abortState;
- regTcPtr->transactionState = TcConnectionrec::COMMITTED;
- if (abortState == TcConnectionrec::ABORT_IDLE) {
- Uint32 clientBlockref = regTcPtr->clientBlockref;
- if (regTcPtr->seqNoReplica == 0) {
- jam();
- sendCommittedTc(signal, clientBlockref);
- return;
- } else {
- jam();
- sendCommitLqh(signal, clientBlockref);
- return;
- }//if
- } else if (regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC) {
- jam();
- signal->theData[0] = regTcPtr->reqRef;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = regTcPtr->transid[0];
- signal->theData[3] = regTcPtr->transid[1];
- sendSignal(tcConnectptr.p->reqBlockref, GSN_COMMITCONF, signal, 4, JBB);
- } else {
- ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
- jam();
- sendLqhTransconf(signal, LqhTransConf::Committed);
- }//if
- return;
-}//Dblqh::commitReplyLab()
-
-/* ------------------------------------------------------------------------- */
-/* ------- COMPLETE PHASE ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::completeTransNotLastLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
- Uint32 clientBlockref = regTcPtr->clientBlockref;
- jam();
- sendCompleteLqh(signal, clientBlockref);
- cleanUp(signal);
- return;
- } else {
- jam();
- completeUnusualLab(signal);
- return;
- }//if
-}//Dblqh::completeTransNotLastLab()
-
-void Dblqh::completeTransLastLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
- Uint32 clientBlockref = regTcPtr->clientBlockref;
- jam();
-/* ------------------------------------------------------------------------- */
-/*DIRTY WRITES WHICH ARE LAST IN THE CHAIN OF REPLICAS WILL SEND COMPLETED */
-/*INSTEAD OF SENDING PREPARED TO THE TC (OR OTHER INITIATOR OF OPERATION). */
-/* ------------------------------------------------------------------------- */
- sendCompletedTc(signal, clientBlockref);
- cleanUp(signal);
- return;
- } else {
- jam();
- completeUnusualLab(signal);
- return;
- }//if
-}//Dblqh::completeTransLastLab()
-
-void Dblqh::completeUnusualLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
- jam();
- sendAborted(signal);
- } else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
- jam();
- sendLqhTransconf(signal, LqhTransConf::Committed);
- } else {
- ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
- jam();
- signal->theData[0] = regTcPtr->reqRef;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = regTcPtr->transid[0];
- signal->theData[3] = regTcPtr->transid[1];
- sendSignal(regTcPtr->reqBlockref,
- GSN_COMPLETECONF, signal, 4, JBB);
- }//if
- cleanUp(signal);
- return;
-}//Dblqh::completeUnusualLab()
-
-/* ========================================================================= */
-/* ======= RELEASE TC CONNECT RECORD ======= */
-/* */
-/* RELEASE A TC CONNECT RECORD TO THE FREELIST. */
-/* ========================================================================= */
-void Dblqh::releaseTcrec(Signal* signal, TcConnectionrecPtr locTcConnectptr)
-{
- jam();
- locTcConnectptr.p->tcTimer = 0;
- locTcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
- locTcConnectptr.p->nextTcConnectrec = cfirstfreeTcConrec;
- cfirstfreeTcConrec = locTcConnectptr.i;
-
- TablerecPtr tabPtr;
- tabPtr.i = locTcConnectptr.p->tableref;
- if(tabPtr.i == RNIL)
- return;
-
- ptrCheckGuard(tabPtr, ctabrecFileSize, tablerec);
-
- /**
- * Normal case
- */
- ndbrequire(tabPtr.p->usageCount > 0);
- tabPtr.p->usageCount--;
-}//Dblqh::releaseTcrec()
-
-void Dblqh::releaseTcrecLog(Signal* signal, TcConnectionrecPtr locTcConnectptr)
-{
- jam();
- locTcConnectptr.p->tcTimer = 0;
- locTcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
- locTcConnectptr.p->nextTcConnectrec = cfirstfreeTcConrec;
- cfirstfreeTcConrec = locTcConnectptr.i;
-
- TablerecPtr tabPtr;
- tabPtr.i = locTcConnectptr.p->tableref;
- if(tabPtr.i == RNIL)
- return;
-
-}//Dblqh::releaseTcrecLog()
-
-/* ------------------------------------------------------------------------- */
-/* ------- ABORT PHASE ------- */
-/* */
-/*THIS PART IS USED AT ERRORS THAT CAUSE ABORT OF TRANSACTION. */
-/* ------------------------------------------------------------------------- */
-/* ***************************************************>> */
-/* ABORT: Abort transaction in connection. Sender TC. */
-/* This is the normal protocol (See COMMIT) */
-/* ***************************************************>> */
-void Dblqh::execABORT(Signal* signal)
-{
- jamEntry();
- Uint32 tcOprec = signal->theData[0];
- BlockReference tcBlockref = signal->theData[1];
- Uint32 transid1 = signal->theData[2];
- Uint32 transid2 = signal->theData[3];
- CRASH_INSERTION(5003);
- if (ERROR_INSERTED(5015)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_ABORT, signal, 2000, 4);
- return;
- }//if
- if (findTransaction(transid1,
- transid2,
- tcOprec) != ZOK) {
- jam();
-
- if(ERROR_INSERTED(5039) &&
- refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
- jam();
- SET_ERROR_INSERT_VALUE(5040);
- return;
- }
-
- if(ERROR_INSERTED(5040) &&
- refToNode(signal->getSendersBlockRef()) != getOwnNodeId()){
- jam();
- SET_ERROR_INSERT_VALUE(5003);
- return;
- }
-
-/* ------------------------------------------------------------------------- */
-// SEND ABORTED EVEN IF NOT FOUND.
-//THE TRANSACTION MIGHT NEVER HAVE ARRIVED HERE.
-/* ------------------------------------------------------------------------- */
- signal->theData[0] = tcOprec;
- signal->theData[1] = transid1;
- signal->theData[2] = transid2;
- signal->theData[3] = cownNodeid;
- signal->theData[4] = ZTRUE;
- sendSignal(tcBlockref, GSN_ABORTED, signal, 5, JBB);
- warningReport(signal, 8);
- return;
- }//if
-
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (ERROR_INSERTED(5100))
- {
- SET_ERROR_INSERT_VALUE(5101);
- return;
- }
- CRASH_INSERTION2(5101, regTcPtr->nextReplica != ZNIL);
-
-/* ------------------------------------------------------------------------- */
-/*A GUIDING DESIGN PRINCIPLE IN HANDLING THESE ERROR SITUATIONS HAVE BEEN */
-/*KEEP IT SIMPLE. THUS WE RATHER INSERT A WAIT AND SET THE ABORT_STATE TO */
-/*ACTIVE RATHER THAN WRITE NEW CODE TO HANDLE EVERY SPECIAL SITUATION. */
-/* ------------------------------------------------------------------------- */
- if (regTcPtr->nextReplica != ZNIL) {
-/* ------------------------------------------------------------------------- */
-// We will immediately send the ABORT message also to the next LQH node in line.
-/* ------------------------------------------------------------------------- */
- BlockReference TLqhRef = calcLqhBlockRef(regTcPtr->nextReplica);
- signal->theData[0] = regTcPtr->tcOprec;
- signal->theData[1] = regTcPtr->tcBlockref;
- signal->theData[2] = regTcPtr->transid[0];
- signal->theData[3] = regTcPtr->transid[1];
- sendSignal(TLqhRef, GSN_ABORT, signal, 4, JBB);
- }//if
- regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
-
- const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- if(commitAckMarker != RNIL)
- {
- jam();
-#ifdef MARKER_TRACE
- {
- CommitAckMarkerPtr tmp;
- m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
- ndbout_c("Ab2 marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2);
- }
-#endif
- m_commitAckMarkerHash.release(commitAckMarker);
- regTcPtr->commitAckMarker = RNIL;
- }
-
- TRACE_OP(regTcPtr, "ABORT");
-
- abortStateHandlerLab(signal);
-
- return;
-}//Dblqh::execABORT()
-
-/* ************************************************************************>>
- * ABORTREQ: Same as ABORT but used in case one node isn't working ok.
- * (See COMMITREQ)
- * ************************************************************************>> */
-void Dblqh::execABORTREQ(Signal* signal)
-{
- jamEntry();
- Uint32 reqPtr = signal->theData[0];
- BlockReference reqBlockref = signal->theData[1];
- Uint32 transid1 = signal->theData[2];
- Uint32 transid2 = signal->theData[3];
- Uint32 tcOprec = signal->theData[5];
- if (ERROR_INSERTED(5006)) {
- systemErrorLab(signal, __LINE__);
- }
- if (ERROR_INSERTED(5016)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_ABORTREQ, signal, 2000, 6);
- return;
- }//if
- if (findTransaction(transid1,
- transid2,
- tcOprec) != ZOK) {
- signal->theData[0] = reqPtr;
- signal->theData[2] = cownNodeid;
- signal->theData[3] = transid1;
- signal->theData[4] = transid2;
- sendSignal(reqBlockref, GSN_ABORTCONF, signal, 5, JBB);
- warningReport(signal, 9);
- return;
- }//if
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->transactionState != TcConnectionrec::PREPARED) {
- warningReport(signal, 10);
- return;
- }//if
- regTcPtr->reqBlockref = reqBlockref;
- regTcPtr->reqRef = reqPtr;
- regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
-
- abortCommonLab(signal);
- return;
-}//Dblqh::execABORTREQ()
-
-/* ************>> */
-/* ACC_TO_REF > */
-/* ************>> */
-void Dblqh::execACC_TO_REF(Signal* signal)
-{
- jamEntry();
- terrorCode = signal->theData[1];
- abortErrorLab(signal);
- return;
-}//Dblqh::execACC_TO_REF()
-
-/* ************> */
-/* ACCKEYREF > */
-/* ************> */
-void Dblqh::execACCKEYREF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- terrorCode = signal->theData[1];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- TcConnectionrec * const tcPtr = tcConnectptr.p;
- switch (tcPtr->transactionState) {
- case TcConnectionrec::WAIT_ACC:
- jam();
- break;
- case TcConnectionrec::WAIT_ACC_ABORT:
- case TcConnectionrec::ABORT_STOPPED:
- case TcConnectionrec::ABORT_QUEUED:
- jam();
-/* ------------------------------------------------------------------------- */
-/*IGNORE SINCE ABORT OF THIS OPERATION IS ONGOING ALREADY. */
-/* ------------------------------------------------------------------------- */
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- const Uint32 errCode = terrorCode;
- tcPtr->errorCode = errCode;
-
- if (TRACENR_FLAG)
- {
- TRACENR("ACCKEYREF: " << errCode << " ");
- switch (tcPtr->operation) {
- case ZREAD: TRACENR("READ"); break;
- case ZUPDATE: TRACENR("UPDATE"); break;
- case ZWRITE: TRACENR("WRITE"); break;
- case ZINSERT: TRACENR("INSERT"); break;
- case ZDELETE: TRACENR("DELETE"); break;
- default: TRACENR("<Unknown: " << tcPtr->operation << ">"); break;
- }
-
- TRACENR(" tab: " << tcPtr->tableref
- << " frag: " << tcPtr->fragmentid
- << " activeCreat: " << (Uint32)tcPtr->activeCreat);
- if (LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo))
- TRACENR(" NrCopy");
- if (LqhKeyReq::getRowidFlag(tcPtr->reqinfo))
- TRACENR(" rowid: " << tcPtr->m_row_id);
- TRACENR(" key: " << tcPtr->tupkeyData[0]);
- TRACENR(endl);
-
- }
-
- ndbrequire(tcPtr->activeCreat == Fragrecord::AC_NORMAL);
- ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
-
- /**
- * Only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
- *
- * Unless it's a simple or dirty read
- *
- * NOT TRUE!
- * 1) op1 - primary insert ok
- * 2) op1 - backup insert fail (log full or what ever)
- * 3) op1 - delete ok @ primary
- * 4) op1 - delete fail @ backup
- *
- * -> ZNO_TUPLE_FOUND is possible
- */
- ndbrequire
- (tcPtr->seqNoReplica == 0 ||
- errCode != ZTUPLE_ALREADY_EXIST ||
- (tcPtr->operation == ZREAD && (tcPtr->dirtyOp || tcPtr->opSimple)));
-
- tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
- abortCommonLab(signal);
- return;
-}//Dblqh::execACCKEYREF()
-
-void Dblqh::localAbortStateHandlerLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->abortState != TcConnectionrec::ABORT_IDLE) {
- jam();
- return;
- }//if
- regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
- regTcPtr->errorCode = terrorCode;
- abortStateHandlerLab(signal);
- return;
-}//Dblqh::localAbortStateHandlerLab()
-
-void Dblqh::abortStateHandlerLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- switch (regTcPtr->transactionState) {
- case TcConnectionrec::PREPARED:
- jam();
-/* ------------------------------------------------------------------------- */
-/*THE OPERATION IS ALREADY PREPARED AND SENT TO THE NEXT LQH OR BACK TO TC. */
-/*WE CAN SIMPLY CONTINUE WITH THE ABORT PROCESS. */
-/*IF IT WAS A CHECK FOR TRANSACTION STATUS THEN WE REPORT THE STATUS TO THE */
-/*NEW TC AND CONTINUE WITH THE NEXT OPERATION IN LQH. */
-/* ------------------------------------------------------------------------- */
- if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
- jam();
- sendLqhTransconf(signal, LqhTransConf::Prepared);
- return;
- }//if
- break;
- case TcConnectionrec::LOG_COMMIT_WRITTEN_WAIT_SIGNAL:
- case TcConnectionrec::LOG_COMMIT_QUEUED_WAIT_SIGNAL:
- jam();
-/* ------------------------------------------------------------------------- */
-// We can only reach these states for multi-updates on a record in a transaction.
-// We know that at least one of those has received the COMMIT signal, thus we
-// declare us only prepared since we then receive the expected COMMIT signal.
-/* ------------------------------------------------------------------------- */
- ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
- sendLqhTransconf(signal, LqhTransConf::Prepared);
- break;
- case TcConnectionrec::WAIT_TUPKEYINFO:
- case TcConnectionrec::WAIT_ATTR:
- jam();
-/* ------------------------------------------------------------------------- */
-/* WE ARE CURRENTLY WAITING FOR MORE INFORMATION. WE CAN START THE ABORT */
-/* PROCESS IMMEDIATELY. THE KEYINFO AND ATTRINFO SIGNALS WILL BE DROPPED */
-/* SINCE THE ABORT STATE WILL BE SET. */
-/* ------------------------------------------------------------------------- */
- break;
- case TcConnectionrec::WAIT_TUP:
- jam();
-/* ------------------------------------------------------------------------- */
-// TUP is currently active. We have to wait for the TUPKEYREF or TUPKEYCONF
-// to arrive since we might otherwise jeopardise the local checkpoint
-// consistency in overload situations.
-/* ------------------------------------------------------------------------- */
- regTcPtr->transactionState = TcConnectionrec::WAIT_TUP_TO_ABORT;
- return;
- case TcConnectionrec::WAIT_ACC:
- jam();
-/* ------------------------------------------------------------------------- */
-// We start the abort immediately since the operation is still in the active
-// list and the fragment cannot have been frozen yet. By sending LCP_HOLDOPCONF
-// as direct signals we avoid the problem that we might find the operation
-// in an unexpected list in ACC.
-// We cannot accept being blocked before aborting ACC here since that would
-// lead to seriously complex issues.
-/* ------------------------------------------------------------------------- */
- abortContinueAfterBlockedLab(signal, false);
- return;
- break;
- case TcConnectionrec::LOG_QUEUED:
- jam();
-/* ------------------------------------------------------------------------- */
-/*CURRENTLY QUEUED FOR LOGGING. WAIT UNTIL THE LOG RECORD HAVE BEEN INSERTED */
-/*AND THEN CONTINUE THE ABORT PROCESS. */
-//Could also be waiting for an overloaded log disk. In this case it is easy
-//to abort when CONTINUEB arrives.
-/* ------------------------------------------------------------------------- */
- return;
- break;
- case TcConnectionrec::STOPPED:
- jam();
- /* ---------------------------------------------------------------------
- * WE ARE CURRENTLY QUEUED FOR ACCESS TO THE FRAGMENT BY A LCP
- * Since nothing has been done, just release operation
- * i.e. no prepare log record has been written
- * so no abort log records needs to be written
- */
- releaseWaitQueue(signal);
- continueAfterLogAbortWriteLab(signal);
- return;
- break;
- case TcConnectionrec::WAIT_AI_AFTER_ABORT:
- jam();
-/* ------------------------------------------------------------------------- */
-/* ABORT OF ACC AND TUP ALREADY COMPLETED. THIS STATE IS ONLY USED WHEN */
-/* CREATING A NEW FRAGMENT. */
-/* ------------------------------------------------------------------------- */
- continueAbortLab(signal);
- return;
- break;
- case TcConnectionrec::WAIT_TUP_TO_ABORT:
- case TcConnectionrec::ABORT_STOPPED:
- case TcConnectionrec::LOG_ABORT_QUEUED:
- case TcConnectionrec::WAIT_ACC_ABORT:
- case TcConnectionrec::ABORT_QUEUED:
- jam();
-/* ------------------------------------------------------------------------- */
-/*ABORT IS ALREADY ONGOING DUE TO SOME ERROR. WE HAVE ALREADY SET THE STATE */
-/*OF THE ABORT SO THAT WE KNOW THAT TC EXPECTS A REPORT. WE CAN THUS SIMPLY */
-/*EXIT. */
-/* ------------------------------------------------------------------------- */
- return;
- break;
- case TcConnectionrec::WAIT_TUP_COMMIT:
- case TcConnectionrec::COMMIT_STOPPED:
- case TcConnectionrec::LOG_COMMIT_QUEUED:
- case TcConnectionrec::COMMIT_QUEUED:
- jam();
-/* ------------------------------------------------------------------------- */
-/*THIS IS ONLY AN ALLOWED STATE IF A DIRTY WRITE OR SIMPLE READ IS PERFORMED.*/
-/*IF WE ARE MERELY CHECKING THE TRANSACTION STATE IT IS ALSO AN ALLOWED STATE*/
-/* ------------------------------------------------------------------------- */
- if (regTcPtr->dirtyOp == ZTRUE) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*COMPLETE THE DIRTY WRITE AND THEN REPORT COMPLETED BACK TO TC. SINCE IT IS */
-/*A DIRTY WRITE IT IS ALLOWED TO COMMIT EVEN IF THE TRANSACTION ABORTS. */
-/* ------------------------------------------------------------------------- */
- return;
- }//if
- if (regTcPtr->opSimple) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*A SIMPLE READ IS CURRENTLY RELEASING THE LOCKS OR WAITING FOR ACCESS TO */
-/*ACC TO CLEAR THE LOCKS. COMPLETE THIS PROCESS AND THEN RETURN AS NORMAL. */
-/*NO DATA HAS CHANGED DUE TO THIS SIMPLE READ ANYWAY. */
-/* ------------------------------------------------------------------------- */
- return;
- }//if
- ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
- jam();
-/* ------------------------------------------------------------------------- */
-/*WE ARE ONLY CHECKING THE STATUS OF THE TRANSACTION. IT IS COMMITTING. */
-/*COMPLETE THE COMMIT LOCALLY AND THEN SEND REPORT OF COMMITTED TO THE NEW TC*/
-/* ------------------------------------------------------------------------- */
- return;
- break;
- case TcConnectionrec::COMMITTED:
- jam();
- ndbrequire(regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC);
-/* ------------------------------------------------------------------------- */
-/*WE ARE CHECKING TRANSACTION STATUS. REPORT COMMITTED AND CONTINUE WITH THE */
-/*NEXT OPERATION. */
-/* ------------------------------------------------------------------------- */
- sendLqhTransconf(signal, LqhTransConf::Committed);
- return;
- break;
- default:
- ndbrequire(false);
-/* ------------------------------------------------------------------------- */
-/*THE STATE WAS NOT AN ALLOWED STATE ON A NORMAL OPERATION. SCANS AND COPY */
-/*FRAGMENT OPERATIONS SHOULD HAVE EXECUTED IN ANOTHER PATH. */
-/* ------------------------------------------------------------------------- */
- break;
- }//switch
- abortCommonLab(signal);
- return;
-}//Dblqh::abortStateHandlerLab()
-
-void Dblqh::abortErrorLab(Signal* signal)
-{
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->abortState == TcConnectionrec::ABORT_IDLE) {
- jam();
- regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
- regTcPtr->errorCode = terrorCode;
- }//if
- abortCommonLab(signal);
- return;
-}//Dblqh::abortErrorLab()
-
-void Dblqh::abortCommonLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- const Uint32 activeCreat = regTcPtr->activeCreat;
- if (commitAckMarker != RNIL)
- {
- /**
- * There is no NR ongoing and we have a marker
- */
- jam();
-#ifdef MARKER_TRACE
- {
- CommitAckMarkerPtr tmp;
- m_commitAckMarkerHash.getPtr(tmp, commitAckMarker);
- ndbout_c("Abo marker[%.8x %.8x]", tmp.p->transid1, tmp.p->transid2);
- }
-#endif
- m_commitAckMarkerHash.release(commitAckMarker);
- regTcPtr->commitAckMarker = RNIL;
- }
-
- if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
- {
- jam();
- if (regTcPtr->m_nr_delete.m_cnt)
- {
- jam();
- /**
- * Let operation wait for pending NR operations
- */
-
-#ifdef VM_TRACE
- /**
- * Only disk table can have pending ops...
- */
- TablerecPtr tablePtr;
- tablePtr.i = regTcPtr->tableref;
- ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
- ndbrequire(tablePtr.p->m_disk_table);
-#endif
- return;
- }
- }
-
- fragptr.i = regTcPtr->fragmentptr;
- if (fragptr.i != RNIL) {
- jam();
- c_fragment_pool.getPtr(fragptr);
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- case Fragrecord::CRASH_RECOVERING:
- case Fragrecord::ACTIVE_CREATION:
- jam();
- abortContinueAfterBlockedLab(signal, true);
- return;
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- regTcPtr->transactionState = TcConnectionrec::ABORT_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- ndbrequire(false);
- break;
- }//switch
- } else {
- jam();
- continueAbortLab(signal);
- }//if
-}//Dblqh::abortCommonLab()
-
-void Dblqh::abortContinueAfterBlockedLab(Signal* signal, bool canBlock)
-{
- /* ------------------------------------------------------------------------
- * INPUT: TC_CONNECTPTR ACTIVE OPERATION RECORD
- * ------------------------------------------------------------------------
- * ------------------------------------------------------------------------
- * CAN COME HERE AS RESTART AFTER BEING BLOCKED BY A LOCAL CHECKPOINT.
- * ------------------------------------------------------------------------
- * ALSO AS PART OF A NORMAL ABORT WITHOUT BLOCKING.
- * WE MUST ABORT TUP BEFORE ACC TO ENSURE THAT NO ONE RACES IN
- * AND SEES A STATE IN TUP.
- * ----------------------------------------------------------------------- */
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
-
- TRACE_OP(regTcPtr, "ACC ABORT");
-
- regTcPtr->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
- signal->theData[0] = regTcPtr->accConnectrec;
- signal->theData[1] = 2; // JOB BUFFER IF NEEDED
- EXECUTE_DIRECT(DBACC, GSN_ACC_ABORTREQ, signal, 2);
-
- if (signal->theData[1] == RNIL)
- {
- jam();
- /* ------------------------------------------------------------------------
- * We need to insert a real-time break by sending ACC_ABORTCONF through the
- * job buffer to ensure that we catch any ACCKEYCONF or TUPKEYCONF or
- * TUPKEYREF that are in the job buffer but not yet processed. Doing
- * everything without that would race and create a state error when they
- * are executed.
- * --------------------------------------------------------------------- */
- return;
- }
-
- execACC_ABORTCONF(signal);
- return;
-}//Dblqh::abortContinueAfterBlockedLab()
-
-/* ******************>> */
-/* ACC_ABORTCONF > */
-/* ******************>> */
-void Dblqh::execACC_ABORTCONF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_ACC_ABORT);
-
- TRACE_OP(regTcPtr, "ACC_ABORTCONF");
- signal->theData[0] = regTcPtr->tupConnectrec;
- EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
-
- jamEntry();
- continueAbortLab(signal);
- return;
-}//Dblqh::execACC_ABORTCONF()
-
-void Dblqh::continueAbortLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- /* ------------------------------------------------------------------------
- * AN ERROR OCCURED IN THE ACTIVE CREATION AFTER THE ABORT PHASE.
- * WE NEED TO CONTINUE WITH A NORMAL ABORT.
- * ------------------------------------------------------------------------
- * ALSO USED FOR NORMAL CLEAN UP AFTER A NORMAL ABORT.
- * ------------------------------------------------------------------------
- * ALSO USED WHEN NO FRAGMENT WAS SET UP ON OPERATION.
- * ------------------------------------------------------------------------ */
- if (regTcPtr->logWriteState == TcConnectionrec::WRITTEN) {
- jam();
- /* ----------------------------------------------------------------------
- * I NEED TO INSERT A ABORT LOG RECORD SINCE WE ARE WRITING LOG IN THIS
- * TRANSACTION.
- * ---------------------------------------------------------------------- */
- initLogPointers(signal);
- if (logPartPtr.p->logPartState == LogPartRecord::ACTIVE) {
- jam();
- /* --------------------------------------------------------------------
- * A PREPARE OPERATION IS CURRENTLY WRITING IN THE LOG.
- * WE MUST WAIT ON OUR TURN TO WRITE THE LOG.
- * IT IS NECESSARY TO WRITE ONE LOG RECORD COMPLETELY
- * AT A TIME OTHERWISE WE WILL SCRAMBLE THE LOG.
- * -------------------------------------------------------------------- */
- linkWaitLog(signal, logPartPtr);
- regTcPtr->transactionState = TcConnectionrec::LOG_ABORT_QUEUED;
- return;
- }//if
- if (cnoOfLogPages == 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-// We must delay the write of commit info to the log to safe-guard against
-// a crash due to lack of log pages. We temporary stop all log writes to this
-// log part to ensure that we don't get a buffer explosion in the delayed
-// signal buffer instead.
-/*---------------------------------------------------------------------------*/
- linkWaitLog(signal, logPartPtr);
- regTcPtr->transactionState = TcConnectionrec::LOG_ABORT_QUEUED;
- if (logPartPtr.p->logPartState == LogPartRecord::IDLE) {
- jam();
- logPartPtr.p->logPartState = LogPartRecord::ACTIVE;
- }//if
- return;
- }//if
- writeAbortLog(signal);
- removeLogTcrec(signal);
- } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_STARTED) {
- jam();
- } else if (regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN) {
- jam();
- /* ------------------------------------------------------------------
- * IT IS A READ OPERATION OR OTHER OPERATION THAT DO NOT USE THE LOG.
- * ------------------------------------------------------------------ */
- /* ------------------------------------------------------------------
- * THE LOG HAS NOT BEEN WRITTEN SINCE THE LOG FLAG WAS FALSE.
- * THIS CAN OCCUR WHEN WE ARE STARTING A NEW FRAGMENT.
- * ------------------------------------------------------------------ */
- regTcPtr->logWriteState = TcConnectionrec::NOT_STARTED;
- } else {
- ndbrequire(regTcPtr->logWriteState == TcConnectionrec::NOT_WRITTEN_WAIT);
- jam();
- /* ----------------------------------------------------------------
- * THE STATE WAS SET TO NOT_WRITTEN BY THE OPERATION BUT LATER
- * A SCAN OF ALL OPERATION RECORD CHANGED IT INTO NOT_WRITTEN_WAIT.
- * THIS INDICATES THAT WE ARE WAITING FOR THIS OPERATION TO COMMIT
- * OR ABORT SO THAT WE CAN FIND THE
- * STARTING GLOBAL CHECKPOINT OF THIS NEW FRAGMENT.
- * ---------------------------------------------------------------- */
- checkScanTcCompleted(signal);
- }//if
- continueAfterLogAbortWriteLab(signal);
- return;
-}//Dblqh::continueAbortLab()
-
-void Dblqh::continueAfterLogAbortWriteLab(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->operation == ZREAD && regTcPtr->dirtyOp)
- {
- jam();
- TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
-
- tcKeyRef->connectPtr = regTcPtr->applOprec;
- tcKeyRef->transId[0] = regTcPtr->transid[0];
- tcKeyRef->transId[1] = regTcPtr->transid[1];
- tcKeyRef->errorCode = regTcPtr->errorCode;
- sendTCKEYREF(signal, regTcPtr->applRef, regTcPtr->clientBlockref, 0);
- cleanUp(signal);
- return;
- }//if
- if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_LQH) {
- LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtrSend();
-
- jam();
- lqhKeyRef->userRef = regTcPtr->clientConnectrec;
- lqhKeyRef->connectPtr = regTcPtr->tcOprec;
- lqhKeyRef->errorCode = regTcPtr->errorCode;
- lqhKeyRef->transId1 = regTcPtr->transid[0];
- lqhKeyRef->transId2 = regTcPtr->transid[1];
- sendSignal(regTcPtr->clientBlockref, GSN_LQHKEYREF, signal,
- LqhKeyRef::SignalLength, JBB);
- } else if (regTcPtr->abortState == TcConnectionrec::ABORT_FROM_TC) {
- jam();
- sendAborted(signal);
- } else if (regTcPtr->abortState == TcConnectionrec::NEW_FROM_TC) {
- jam();
- sendLqhTransconf(signal, LqhTransConf::Aborted);
- } else {
- ndbrequire(regTcPtr->abortState == TcConnectionrec::REQ_FROM_TC);
- jam();
- signal->theData[0] = regTcPtr->reqRef;
- signal->theData[1] = tcConnectptr.i;
- signal->theData[2] = cownNodeid;
- signal->theData[3] = regTcPtr->transid[0];
- signal->theData[4] = regTcPtr->transid[1];
- sendSignal(regTcPtr->reqBlockref, GSN_ABORTCONF,
- signal, 5, JBB);
- }//if
- cleanUp(signal);
-}//Dblqh::continueAfterLogAbortWriteLab()
-
-void
-Dblqh::sendTCKEYREF(Signal* signal, Uint32 ref, Uint32 routeRef, Uint32 cnt)
-{
- const Uint32 nodeId = refToNode(ref);
- const bool connectedToNode = getNodeInfo(nodeId).m_connected;
-
- if (likely(connectedToNode))
- {
- jam();
- sendSignal(ref, GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
- }
- else
- {
- if (routeRef &&
- getNodeInfo(refToNode(routeRef)).m_version >= MAKE_VERSION(5,1,14))
- {
- jam();
- memmove(signal->theData+25, signal->theData, 4*TcKeyRef::SignalLength);
- RouteOrd* ord = (RouteOrd*)signal->getDataPtrSend();
- ord->dstRef = ref;
- ord->srcRef = reference();
- ord->gsn = GSN_TCKEYREF;
- ord->cnt = 0;
- LinearSectionPtr ptr[3];
- ptr[0].p = signal->theData+25;
- ptr[0].sz = TcKeyRef::SignalLength;
- sendSignal(routeRef, GSN_ROUTE_ORD, signal, RouteOrd::SignalLength, JBB,
- ptr, 1);
- }
- else
- {
- jam();
- memmove(signal->theData + 3, signal->theData, 4*TcKeyRef::SignalLength);
- signal->theData[0] = ZRETRY_TCKEYREF;
- signal->theData[1] = cnt + 1;
- signal->theData[2] = ref;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100,
- TcKeyRef::SignalLength + 3);
- }
- }
-}
-
-/* ##########################################################################
- * ####### MODULE TO HANDLE TC FAILURE #######
- *
- * ########################################################################## */
-
-/* ************************************************************************>>
- * NODE_FAILREP: Node failure report. Sender Ndbcntr. Set status of failed
- * node to down and reply with NF_COMPLETEREP to DIH which will report that
- * LQH has completed failure handling.
- * ************************************************************************>> */
-void Dblqh::execNODE_FAILREP(Signal* signal)
-{
- UintR TfoundNodes = 0;
- UintR TnoOfNodes;
- UintR Tdata[MAX_NDB_NODES];
- Uint32 i;
-
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
-
- TnoOfNodes = nodeFail->noOfNodes;
- UintR index = 0;
- for (i = 1; i < MAX_NDB_NODES; i++) {
- jam();
- if(NodeBitmask::get(nodeFail->theNodes, i)){
- jam();
- Tdata[index] = i;
- index++;
- }//if
- }//for
-
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
-
- ndbrequire(index == TnoOfNodes);
- ndbrequire(cnoOfNodes - 1 < MAX_NDB_NODES);
- for (i = 0; i < TnoOfNodes; i++) {
- const Uint32 nodeId = Tdata[i];
- lcpPtr.p->m_EMPTY_LCP_REQ.clear(nodeId);
-
- for (Uint32 j = 0; j < cnoOfNodes; j++) {
- jam();
- if (cnodeData[j] == nodeId){
- jam();
- cnodeStatus[j] = ZNODE_DOWN;
-
- TfoundNodes++;
- }//if
- }//for
- NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
- nfCompRep->blockNo = DBLQH;
- nfCompRep->nodeId = cownNodeid;
- nfCompRep->failedNodeId = Tdata[i];
- sendSignal(DBDIH_REF, GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBB);
- }//for
- ndbrequire(TnoOfNodes == TfoundNodes);
-}//Dblqh::execNODE_FAILREP()
-
-/* ************************************************************************>>
- * LQH_TRANSREQ: Report status of all transactions where TC was coordinated
- * by a crashed TC
- * ************************************************************************>> */
-/* ************************************************************************>>
- * THIS SIGNAL IS RECEIVED AFTER A NODE CRASH.
- * THE NODE HAD A TC AND COORDINATED A NUMBER OF TRANSACTIONS.
- * NOW THE MASTER NODE IS PICKING UP THOSE TRANSACTIONS
- * TO COMPLETE THEM. EITHER ABORT THEM OR COMMIT THEM.
- * ************************************************************************>> */
-void Dblqh::execLQH_TRANSREQ(Signal* signal)
-{
- jamEntry();
- Uint32 newTcPtr = signal->theData[0];
- BlockReference newTcBlockref = signal->theData[1];
- Uint32 oldNodeId = signal->theData[2];
- tcNodeFailptr.i = oldNodeId;
- ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
- if ((tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_TRUE) ||
- (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK)) {
- jam();
- tcNodeFailptr.p->lastNewTcBlockref = newTcBlockref;
- /* ------------------------------------------------------------------------
- * WE HAVE RECEIVED A SIGNAL SPECIFYING THAT WE NEED TO HANDLE THE FAILURE
- * OF A TC. NOW WE RECEIVE ANOTHER SIGNAL WITH THE SAME ORDER. THIS CAN
- * OCCUR IF THE NEW TC FAILS. WE MUST BE CAREFUL IN THIS CASE SO THAT WE DO
- * NOT START PARALLEL ACTIVITIES TRYING TO DO THE SAME THING. WE SAVE THE
- * NEW BLOCK REFERENCE TO THE LAST NEW TC IN A VARIABLE AND ASSIGN TO IT TO
- * NEW_TC_BLOCKREF WHEN THE OLD PROCESS RETURNS TO LQH_TRANS_NEXT. IT IS
- * CERTAIN TO COME THERE SINCE THIS IS THE ONLY PATH TO TAKE CARE OF THE
- * NEXT TC CONNECT RECORD. WE SET THE STATUS TO BREAK TO INDICATE TO THE OLD
- * PROCESS WHAT IS HAPPENING.
- * ------------------------------------------------------------------------ */
- tcNodeFailptr.p->lastNewTcRef = newTcPtr;
- tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_BREAK;
- return;
- }//if
- tcNodeFailptr.p->oldNodeId = oldNodeId;
- tcNodeFailptr.p->newTcBlockref = newTcBlockref;
- tcNodeFailptr.p->newTcRef = newTcPtr;
- tcNodeFailptr.p->tcRecNow = 0;
- tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
- signal->theData[0] = ZLQH_TRANS_NEXT;
- signal->theData[1] = tcNodeFailptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dblqh::execLQH_TRANSREQ()
-
-void Dblqh::lqhTransNextLab(Signal* signal)
-{
- UintR tend;
- UintR tstart;
- UintR guard0;
-
- if (tcNodeFailptr.p->tcFailStatus == TcNodeFailRecord::TC_STATE_BREAK) {
- jam();
- /* ----------------------------------------------------------------------
- * AN INTERRUPTION TO THIS NODE FAIL HANDLING WAS RECEIVED AND A NEW
- * TC HAVE BEEN ASSIGNED TO TAKE OVER THE FAILED TC. PROBABLY THE OLD
- * NEW TC HAVE FAILED.
- * ---------------------------------------------------------------------- */
- tcNodeFailptr.p->newTcBlockref = tcNodeFailptr.p->lastNewTcBlockref;
- tcNodeFailptr.p->newTcRef = tcNodeFailptr.p->lastNewTcRef;
- tcNodeFailptr.p->tcRecNow = 0;
- tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_TRUE;
- }//if
- tstart = tcNodeFailptr.p->tcRecNow;
- tend = tstart + 200;
- guard0 = tend;
- for (tcConnectptr.i = tstart; tcConnectptr.i <= guard0; tcConnectptr.i++) {
- jam();
- if (tcConnectptr.i >= ctcConnectrecFileSize) {
- jam();
- /**
- * Finished with scanning operation record
- *
- * now scan markers
- */
- scanMarkers(signal, tcNodeFailptr.i, 0, RNIL);
- return;
- }//if
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
- if (tcConnectptr.p->transactionState != TcConnectionrec::TC_NOT_CONNECTED) {
- if (tcConnectptr.p->tcScanRec == RNIL) {
- if (refToNode(tcConnectptr.p->tcBlockref) == tcNodeFailptr.p->oldNodeId) {
- if (tcConnectptr.p->operation != ZREAD) {
- jam();
- tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
- tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
- abortStateHandlerLab(signal);
- return;
- } else {
- jam();
- if (tcConnectptr.p->opSimple != ZTRUE) {
- jam();
- tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
- tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
- abortStateHandlerLab(signal);
- return;
- }//if
- }//if
- }//if
- } else {
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- switch(scanptr.p->scanType){
- case ScanRecord::COPY:
- {
- jam();
- if (scanptr.p->scanNodeId == tcNodeFailptr.p->oldNodeId) {
- jam();
- /* ------------------------------------------------------------
- * THE RECEIVER OF THE COPY HAVE FAILED.
- * WE HAVE TO CLOSE THE COPY PROCESS.
- * ----------------------------------------------------------- */
- if (0) ndbout_c("close copy");
- tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
- tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
- closeCopyRequestLab(signal);
- return;
- }
- break;
- }
- case ScanRecord::SCAN:
- {
- jam();
- if (refToNode(tcConnectptr.p->tcBlockref) ==
- tcNodeFailptr.p->oldNodeId) {
- jam();
- tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
- tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
- closeScanRequestLab(signal);
- return;
- }//if
- break;
- }
- default:
- ndbrequire(false);
- }
- }//if
- }//if
- }//if
- }//for
- tcNodeFailptr.p->tcRecNow = tend + 1;
- signal->theData[0] = ZLQH_TRANS_NEXT;
- signal->theData[1] = tcNodeFailptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dblqh::lqhTransNextLab()
-
-void
-Dblqh::scanMarkers(Signal* signal,
- Uint32 tcNodeFail,
- Uint32 startBucket,
- Uint32 i){
-
- jam();
-
- TcNodeFailRecordPtr tcNodeFailPtr;
- tcNodeFailPtr.i = tcNodeFail;
- ptrCheckGuard(tcNodeFailPtr, ctcNodeFailrecFileSize, tcNodeFailRecord);
- const Uint32 crashedTcNodeId = tcNodeFailPtr.p->oldNodeId;
-
- CommitAckMarkerIterator iter;
- if(i == RNIL){
- m_commitAckMarkerHash.next(startBucket, iter);
- } else {
- jam();
- iter.curr.i = i;
- iter.bucket = startBucket;
- m_commitAckMarkerHash.getPtr(iter.curr);
- m_commitAckMarkerHash.next(iter);
- }
-
- const Uint32 RT_BREAK = 256;
- for(i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
- jam();
-
- if(iter.curr.i == RNIL){
- /**
- * Done with iteration
- */
- jam();
-
- tcNodeFailPtr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_FALSE;
- signal->theData[0] = tcNodeFailPtr.p->newTcRef;
- signal->theData[1] = cownNodeid;
- signal->theData[2] = LqhTransConf::LastTransConf;
- sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF,
- signal, 3, JBB);
- return;
- }
-
- if(iter.curr.p->tcNodeId == crashedTcNodeId){
- jam();
-
- /**
- * Found marker belonging to crashed node
- */
- LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
- lqhTransConf->tcRef = tcNodeFailPtr.p->newTcRef;
- lqhTransConf->lqhNodeId = cownNodeid;
- lqhTransConf->operationStatus = LqhTransConf::Marker;
- lqhTransConf->transId1 = iter.curr.p->transid1;
- lqhTransConf->transId2 = iter.curr.p->transid2;
- lqhTransConf->apiRef = iter.curr.p->apiRef;
- lqhTransConf->apiOpRec = iter.curr.p->apiOprec;
- sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF,
- signal, 7, JBB);
-
- signal->theData[0] = ZSCAN_MARKERS;
- signal->theData[1] = tcNodeFailPtr.i;
- signal->theData[2] = iter.bucket;
- signal->theData[3] = iter.curr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- return;
- }
-
- m_commitAckMarkerHash.next(iter);
- }
-
- signal->theData[0] = ZSCAN_MARKERS;
- signal->theData[1] = tcNodeFailPtr.i;
- signal->theData[2] = iter.bucket;
- signal->theData[3] = RNIL;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
-}
-
-/* #########################################################################
- * ####### SCAN MODULE #######
- *
- * #########################################################################
- * -------------------------------------------------------------------------
- * THIS MODULE CONTAINS THE CODE THAT HANDLES A SCAN OF A PARTICULAR FRAGMENT
- * IT OPERATES UNDER THE CONTROL OF TC AND ORDERS ACC TO PERFORM A SCAN OF
- * ALL TUPLES IN THE FRAGMENT. TUP PERFORMS THE NECESSARY SEARCH CONDITIONS
- * TO ENSURE THAT ONLY VALID TUPLES ARE RETURNED TO THE APPLICATION.
- * ------------------------------------------------------------------------- */
-/* *************** */
-/* ACC_SCANCONF > */
-/* *************** */
-void Dblqh::execACC_SCANCONF(Signal* signal)
-{
- AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
- jamEntry();
- scanptr.i = accScanConf->scanPtr;
- c_scanRecordPool.getPtr(scanptr);
- if (scanptr.p->scanState == ScanRecord::WAIT_ACC_SCAN) {
- accScanConfScanLab(signal);
- } else {
- ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_ACC_COPY);
- accScanConfCopyLab(signal);
- }//if
-}//Dblqh::execACC_SCANCONF()
-
-/* ************>> */
-/* ACC_SCANREF > */
-/* ************>> */
-void Dblqh::execACC_SCANREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execACC_SCANREF()
-
-/* ***************>> */
-/* NEXT_SCANCONF > */
-/* ***************>> */
-void Dblqh::execNEXT_SCANCONF(Signal* signal)
-{
- NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
- jamEntry();
- scanptr.i = nextScanConf->scanPtr;
- c_scanRecordPool.getPtr(scanptr);
- if (likely(nextScanConf->localKeyLength == 1))
- {
- jam();
- scanptr.p->m_row_id.assref(nextScanConf->localKey[0]);
- }
- else
- {
- jam();
- scanptr.p->m_row_id.m_page_no = nextScanConf->localKey[0];
- scanptr.p->m_row_id.m_page_idx = nextScanConf->localKey[1];
- }
-
-#ifdef VM_TRACE
- if (signal->getLength() > 2 && nextScanConf->accOperationPtr != RNIL)
- {
- Ptr<TcConnectionrec> regTcPtr;
- regTcPtr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
- ndbassert(regTcPtr.p->fragmentid == nextScanConf->fragId);
- }
-#endif
-
- fragptr.i = scanptr.p->fragPtrI;
- c_fragment_pool.getPtr(fragptr);
- switch (scanptr.p->scanState) {
- case ScanRecord::WAIT_CLOSE_SCAN:
- jam();
- accScanCloseConfLab(signal);
- break;
- case ScanRecord::WAIT_CLOSE_COPY:
- jam();
- accCopyCloseConfLab(signal);
- break;
- case ScanRecord::WAIT_NEXT_SCAN:
- jam();
- nextScanConfScanLab(signal);
- break;
- case ScanRecord::WAIT_NEXT_SCAN_COPY:
- jam();
- nextScanConfCopyLab(signal);
- break;
- case ScanRecord::WAIT_RELEASE_LOCK:
- jam();
- ndbrequire(signal->length() == 1);
- scanLockReleasedLab(signal);
- break;
- default:
- ndbout_c("%d", scanptr.p->scanState);
- ndbrequire(false);
- }//switch
-}//Dblqh::execNEXT_SCANCONF()
-
-/* ***************> */
-/* NEXT_SCANREF > */
-/* ***************> */
-void Dblqh::execNEXT_SCANREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Dblqh::execNEXT_SCANREF()
-
-/* ******************> */
-/* STORED_PROCCONF > */
-/* ******************> */
-void Dblqh::execSTORED_PROCCONF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- Uint32 storedProcId = signal->theData[1];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- switch (scanptr.p->scanState) {
- case ScanRecord::WAIT_STORED_PROC_SCAN:
- jam();
- scanptr.p->scanStoredProcId = storedProcId;
- storedProcConfScanLab(signal);
- break;
- case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
- jam();
- tupScanCloseConfLab(signal);
- break;
- case ScanRecord::WAIT_STORED_PROC_COPY:
- jam();
- scanptr.p->scanStoredProcId = storedProcId;
- storedProcConfCopyLab(signal);
- break;
- case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
- jam();
- tupCopyCloseConfLab(signal);
- break;
- default:
- ndbrequire(false);
- }//switch
-}//Dblqh::execSTORED_PROCCONF()
-
-/* ****************** */
-/* STORED_PROCREF > */
-/* ****************** */
-void Dblqh::execSTORED_PROCREF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- Uint32 errorCode = signal->theData[1];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- 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);
- break;
- default:
- ndbrequire(false);
- }//switch
-}//Dblqh::execSTORED_PROCREF()
-
-/* --------------------------------------------------------------------------
- * ENTER SCAN_NEXTREQ
- * --------------------------------------------------------------------------
- * PRECONDITION:
- * TRANSACTION_STATE = SCAN_STATE
- * SCAN_STATE = WAIT_SCAN_NEXTREQ
- *
- * Case scanLockHold: ZTRUE = Unlock previous round of
- * scanned row(s) and fetch next set of rows.
- * ZFALSE = Fetch new set of rows.
- * Number of rows to read depends on parallelism and how many rows
- * left to scan in the fragment. SCAN_NEXTREQ can also be sent with
- * closeFlag == ZTRUE to close the scan.
- * ------------------------------------------------------------------------- */
-void Dblqh::execSCAN_NEXTREQ(Signal* signal)
-{
- jamEntry();
- const ScanFragNextReq * const nextReq =
- (ScanFragNextReq*)&signal->theData[0];
- const Uint32 transid1 = nextReq->transId1;
- const Uint32 transid2 = nextReq->transId2;
- const Uint32 senderData = nextReq->senderData;
-
- if (findTransaction(transid1, transid2, senderData) != ZOK){
- jam();
- DEBUG(senderData <<
- " Received SCAN_NEXTREQ in LQH with close flag when closed");
- ndbrequire(nextReq->closeFlag == ZTRUE);
- return;
- }
-
- // Crash node if signal sender is same node
- CRASH_INSERTION2(5021, refToNode(signal->senderBlockRef()) == cownNodeid);
- // Crash node if signal sender is NOT same node
- CRASH_INSERTION2(5022, refToNode(signal->senderBlockRef()) != cownNodeid);
-
- if (ERROR_INSERTED(5023)){
- // Drop signal if sender is same node
- if (refToNode(signal->senderBlockRef()) == cownNodeid) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }
- }//if
- if (ERROR_INSERTED(5024)){
- // Drop signal if sender is NOT same node
- if (refToNode(signal->senderBlockRef()) != cownNodeid) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }
- }//if
- if (ERROR_INSERTED(5025)){
- // Delay signal if sender is NOT same node
- if (refToNode(signal->senderBlockRef()) != cownNodeid) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_SCAN_NEXTREQ, signal, 1000,
- signal->length());
- return;
- }
- }//if
- if (ERROR_INSERTED(5030)){
- ndbout << "ERROR 5030" << endl;
- CLEAR_ERROR_INSERT_VALUE;
- // Drop signal
- return;
- }//if
-
- if(ERROR_INSERTED(5036)){
- return;
- }
-
- scanptr.i = tcConnectptr.p->tcScanRec;
- ndbrequire(scanptr.i != RNIL);
- c_scanRecordPool.getPtr(scanptr);
- scanptr.p->scanTcWaiting = ZTRUE;
-
- /* ------------------------------------------------------------------
- * If close flag is set this scan should be closed
- * If we are waiting for SCAN_NEXTREQ set flag to stop scanning and
- * continue execution else set flags and wait until the scan
- * completes itself
- * ------------------------------------------------------------------ */
- if (nextReq->closeFlag == ZTRUE){
- jam();
- if(ERROR_INSERTED(5034)){
- CLEAR_ERROR_INSERT_VALUE;
- }
- if(ERROR_INSERTED(5036)){
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }
- closeScanRequestLab(signal);
- return;
- }//if
-
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
-
- /**
- * Change parameters while running
- * (is currently not supported)
- */
- const Uint32 max_rows = nextReq->batch_size_rows;
- const Uint32 max_bytes = nextReq->batch_size_bytes;
- ndbrequire(scanptr.p->m_max_batch_size_rows == max_rows);
- ndbrequire(scanptr.p->m_max_batch_size_bytes == max_bytes);
-
- /* --------------------------------------------------------------------
- * If scanLockHold = TRUE we need to unlock previous round of
- * scanned records.
- * scanReleaseLocks will set states for this and send a NEXT_SCANREQ.
- * When confirm signal NEXT_SCANCONF arrives we call
- * continueScanNextReqLab to continue scanning new rows and
- * acquiring new locks.
- * -------------------------------------------------------------------- */
- if ((scanptr.p->scanLockHold == ZTRUE) &&
- (scanptr.p->m_curr_batch_size_rows > 0)) {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- scanReleaseLocksLab(signal);
- return;
- }//if
-
- /* -----------------------------------------------------------------------
- * We end up here when scanLockHold = FALSE or no rows was locked from
- * previous round.
- * Simply continue scanning.
- * ----------------------------------------------------------------------- */
- continueScanNextReqLab(signal);
-}//Dblqh::execSCAN_NEXTREQ()
-
-void Dblqh::continueScanNextReqLab(Signal* signal)
-{
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
- closeScanLab(signal);
- return;
- }//if
-
- if(scanptr.p->m_last_row){
- jam();
- scanptr.p->scanCompletedStatus = ZTRUE;
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
- sendScanFragConf(signal, ZFALSE);
- return;
- }
-
- // Update timer on tcConnectRecord
- tcConnectptr.p->tcTimer = cLqhTimeOutCount;
- init_acc_ptr_list(scanptr.p);
- scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
- scanNextLoopLab(signal);
-}//Dblqh::continueScanNextReqLab()
-
-/* -------------------------------------------------------------------------
- * WE NEED TO RELEASE LOCKS BEFORE CONTINUING
- * ------------------------------------------------------------------------- */
-void Dblqh::scanReleaseLocksLab(Signal* signal)
-{
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_RELEASE_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- ndbrequire(false);
- }//switch
- continueScanReleaseAfterBlockedLab(signal);
-}//Dblqh::scanReleaseLocksLab()
-
-void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal)
-{
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- scanptr.p->scanState = ScanRecord::WAIT_RELEASE_LOCK;
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1]=
- get_acc_ptr_from_scan_record(scanptr.p,
- scanptr.p->scanReleaseCounter -1,
- false);
- signal->theData[2] = NextScanReq::ZSCAN_COMMIT;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
-}//Dblqh::continueScanReleaseAfterBlockedLab()
-
-/* -------------------------------------------------------------------------
- * ENTER SCAN_NEXTREQ
- * -------------------------------------------------------------------------
- * SCAN_NEXT_REQ SIGNAL ARRIVED IN THE MIDDLE OF EXECUTION OF THE SCAN.
- * IT WAS A REQUEST TO CLOSE THE SCAN. WE WILL CLOSE THE SCAN IN A
- * CAREFUL MANNER TO ENSURE THAT NO ERROR OCCURS.
- * -------------------------------------------------------------------------
- * PRECONDITION:
- * TRANSACTION_STATE = SCAN_STATE_USED
- * TSCAN_COMPLETED = ZTRUE
- * -------------------------------------------------------------------------
- * WE CAN ALSO ARRIVE AT THIS LABEL AFTER A NODE CRASH OF THE SCAN
- * COORDINATOR.
- * ------------------------------------------------------------------------- */
-void Dblqh::closeScanRequestLab(Signal* signal)
-{
- DEBUG("transactionState = " << tcConnectptr.p->transactionState);
- switch (tcConnectptr.p->transactionState) {
- case TcConnectionrec::SCAN_STATE_USED:
- DEBUG("scanState = " << scanptr.p->scanState);
- switch (scanptr.p->scanState) {
- case ScanRecord::IN_QUEUE:
- jam();
- tupScanCloseConfLab(signal);
- break;
- case ScanRecord::WAIT_NEXT_SCAN:
- jam();
- /* -------------------------------------------------------------------
- * SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
- * ------------------------------------------------------------------- */
- scanptr.p->scanCompletedStatus = ZTRUE;
- break;
- case ScanRecord::WAIT_ACC_SCAN:
- case ScanRecord::WAIT_STORED_PROC_SCAN:
- jam();
- /* -------------------------------------------------------------------
- * WE ARE CURRENTLY STARTING UP THE SCAN. SET COMPLETED STATUS
- * AND WAIT FOR COMPLETION OF STARTUP.
- * ------------------------------------------------------------------- */
- scanptr.p->scanCompletedStatus = ZTRUE;
- break;
- case ScanRecord::WAIT_CLOSE_SCAN:
- case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
- jam();
- /*empty*/;
- break;
- /* -------------------------------------------------------------------
- * CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
- * ------------------------------------------------------------------- */
- case ScanRecord::WAIT_RELEASE_LOCK:
- jam();
- /* -------------------------------------------------------------------
- * WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING THIS
- * WE WILL START TO CLOSE THE SCAN.
- * ------------------------------------------------------------------- */
- scanptr.p->scanCompletedStatus = ZTRUE;
- break;
- case ScanRecord::WAIT_SCAN_NEXTREQ:
- jam();
- /* -------------------------------------------------------------------
- * WE ARE WAITING FOR A SCAN_NEXTREQ FROM SCAN COORDINATOR(TC)
- * WICH HAVE CRASHED. CLOSE THE SCAN
- * ------------------------------------------------------------------- */
- scanptr.p->scanCompletedStatus = ZTRUE;
-
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
-
- if (scanptr.p->scanLockHold == ZTRUE) {
- if (scanptr.p->m_curr_batch_size_rows > 0) {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- scanReleaseLocksLab(signal);
- return;
- }//if
- }//if
- closeScanLab(signal);
- break;
- default:
- ndbrequire(false);
- }//switch
- break;
- case TcConnectionrec::WAIT_SCAN_AI:
- jam();
- /* ---------------------------------------------------------------------
- * 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();
- tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
- ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
- tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
- signal->theData[0] = ZLQH_TRANS_NEXT;
- signal->theData[1] = tcNodeFailptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
- }//if
- tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
- scanptr.p->m_curr_batch_size_rows = 0;
- scanptr.p->m_curr_batch_size_bytes= 0;
- sendScanFragConf(signal, ZTRUE);
- abort_scan(signal, scanptr.i, 0);
- return;
- break;
- case TcConnectionrec::SCAN_TUPKEY:
- case TcConnectionrec::SCAN_FIRST_STOPPED:
- case TcConnectionrec::SCAN_CHECK_STOPPED:
- case TcConnectionrec::SCAN_STOPPED:
- jam();
- /* ---------------------------------------------------------------------
- * SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN.
- * --------------------------------------------------------------------- */
- scanptr.p->scanCompletedStatus = ZTRUE;
- break;
- case TcConnectionrec::SCAN_RELEASE_STOPPED:
- jam();
- /* ---------------------------------------------------------------------
- * WE ARE CURRENTLY RELEASING RECORD LOCKS. AFTER COMPLETING
- * THIS WE WILL START TO CLOSE THE SCAN.
- * --------------------------------------------------------------------- */
- scanptr.p->scanCompletedStatus = ZTRUE;
- break;
- case TcConnectionrec::SCAN_CLOSE_STOPPED:
- jam();
- /* ---------------------------------------------------------------------
- * CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING.
- * --------------------------------------------------------------------- */
- /*empty*/;
- break;
- default:
- ndbrequire(false);
- }//switch
-}//Dblqh::closeScanRequestLab()
-
-/* -------------------------------------------------------------------------
- * ENTER NEXT_SCANCONF
- * -------------------------------------------------------------------------
- * PRECONDITION: SCAN_STATE = WAIT_RELEASE_LOCK
- * ------------------------------------------------------------------------- */
-void Dblqh::scanLockReleasedLab(Signal* signal)
-{
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
-
- if (scanptr.p->scanReleaseCounter == scanptr.p->m_curr_batch_size_rows) {
- if ((scanptr.p->scanErrorCounter > 0) ||
- (scanptr.p->scanCompletedStatus == ZTRUE)) {
- jam();
- 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 {
- jam();
- /*
- * We came here after releasing locks after
- * receiving SCAN_NEXTREQ from TC. We only come here
- * when scanHoldLock == ZTRUE
- */
- scanptr.p->m_curr_batch_size_rows = 0;
- scanptr.p->m_curr_batch_size_bytes = 0;
- continueScanNextReqLab(signal);
- }//if
- } else if (scanptr.p->scanReleaseCounter < scanptr.p->m_curr_batch_size_rows) {
- jam();
- scanptr.p->scanReleaseCounter++;
- scanReleaseLocksLab(signal);
- } else {
- jam();
- /*
- We come here when we have been scanning for a long time and not been able
- to find m_max_batch_size_rows records to return. We needed to release
- the record we didn't want, but now we are returning all found records to
- the API.
- */
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
- sendScanFragConf(signal, ZFALSE);
- }//if
-}//Dblqh::scanLockReleasedLab()
-
-bool
-Dblqh::seize_acc_ptr_list(ScanRecord* scanP, Uint32 batch_size)
-{
- Uint32 i;
- Uint32 attr_buf_recs= (batch_size + 30) / 32;
-
- if (batch_size > 1) {
- if (c_no_attrinbuf_recs < attr_buf_recs) {
- jam();
- return false;
- }
- for (i= 1; i <= attr_buf_recs; i++) {
- scanP->scan_acc_op_ptr[i]= seize_attrinbuf();
- }
- }
- scanP->scan_acc_attr_recs= attr_buf_recs;
- scanP->scan_acc_index = 0;
- return true;
-}
-
-void
-Dblqh::release_acc_ptr_list(ScanRecord* scanP)
-{
- Uint32 i, attr_buf_recs;
- attr_buf_recs= scanP->scan_acc_attr_recs;
-
- for (i= 1; i <= attr_buf_recs; i++) {
- release_attrinbuf(scanP->scan_acc_op_ptr[i]);
- }
- scanP->scan_acc_attr_recs= 0;
- scanP->scan_acc_index = 0;
-}
-
-Uint32
-Dblqh::seize_attrinbuf()
-{
- AttrbufPtr regAttrPtr;
- Uint32 ret_attr_buf;
- ndbrequire(c_no_attrinbuf_recs > 0);
- c_no_attrinbuf_recs--;
- ret_attr_buf= cfirstfreeAttrinbuf;
- regAttrPtr.i= ret_attr_buf;
- ptrCheckGuard(regAttrPtr, cattrinbufFileSize, attrbuf);
- cfirstfreeAttrinbuf= regAttrPtr.p->attrbuf[ZINBUF_NEXT];
- return ret_attr_buf;
-}
-
-Uint32
-Dblqh::release_attrinbuf(Uint32 attr_buf_i)
-{
- Uint32 next_buf;
- AttrbufPtr regAttrPtr;
- c_no_attrinbuf_recs++;
- regAttrPtr.i= attr_buf_i;
- ptrCheckGuard(regAttrPtr, cattrinbufFileSize, attrbuf);
- next_buf= regAttrPtr.p->attrbuf[ZINBUF_NEXT];
- regAttrPtr.p->attrbuf[ZINBUF_NEXT]= cfirstfreeAttrinbuf;
- cfirstfreeAttrinbuf= regAttrPtr.i;
- return next_buf;
-}
-
-void
-Dblqh::init_acc_ptr_list(ScanRecord* scanP)
-{
- scanP->scan_acc_index = 0;
-}
-
-Uint32
-Dblqh::get_acc_ptr_from_scan_record(ScanRecord* scanP,
- Uint32 index,
- bool crash_flag)
-{
- Uint32* acc_ptr;
- if (!((index < MAX_PARALLEL_OP_PER_SCAN) &&
- index < scanP->scan_acc_index)) {
- ndbrequire(crash_flag);
- return RNIL;
- }
- i_get_acc_ptr(scanP, acc_ptr, index);
- return *acc_ptr;
-}
-
-void
-Dblqh::set_acc_ptr_in_scan_record(ScanRecord* scanP,
- Uint32 index, Uint32 acc)
-{
- Uint32 *acc_ptr;
- ndbrequire((index == 0 || scanP->scan_acc_index == index) &&
- (index < MAX_PARALLEL_OP_PER_SCAN));
- scanP->scan_acc_index= index + 1;
- i_get_acc_ptr(scanP, acc_ptr, index);
- *acc_ptr= acc;
-}
-
-/* -------------------------------------------------------------------------
- * SCAN_FRAGREQ: Request to start scanning the specified fragment of a table.
- * ------------------------------------------------------------------------- */
-void Dblqh::execSCAN_FRAGREQ(Signal* signal)
-{
- ScanFragReq * const scanFragReq = (ScanFragReq *)&signal->theData[0];
- ScanFragRef * ref;
- const Uint32 transid1 = scanFragReq->transId1;
- const Uint32 transid2 = scanFragReq->transId2;
- Uint32 errorCode= 0;
- Uint32 senderData;
- Uint32 hashIndex;
- TcConnectionrecPtr nextHashptr;
-
- jamEntry();
- const Uint32 reqinfo = scanFragReq->requestInfo;
- const Uint32 fragId = (scanFragReq->fragmentNoKeyLen & 0xFFFF);
- const Uint32 keyLen = (scanFragReq->fragmentNoKeyLen >> 16);
- tabptr.i = scanFragReq->tableId;
- const Uint32 max_rows = scanFragReq->batch_size_rows;
- const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
- const Uint8 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
- const Uint8 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
-
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- if(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED){
- senderData = scanFragReq->senderData;
- goto error_handler_early_1;
- }
-
- if (cfirstfreeTcConrec != RNIL) {
- seizeTcrec();
- tcConnectptr.p->clientConnectrec = scanFragReq->senderData;
- tcConnectptr.p->clientBlockref = signal->senderBlockRef();
- tcConnectptr.p->savePointId = scanFragReq->savePointId;
- } else {
- jam();
- /* --------------------------------------------------------------------
- * NO FREE TC RECORD AVAILABLE, THUS WE CANNOT HANDLE THE REQUEST.
- * -------------------------------------------------------------------- */
- errorCode = ZNO_TC_CONNECT_ERROR;
- senderData = scanFragReq->senderData;
- goto error_handler_early;
- }//if
- /**
- * A write allways have to get keyinfo
- */
- ndbrequire(scanLockMode == 0 || keyinfo);
-
- ndbrequire(max_rows > 0 && max_rows <= MAX_PARALLEL_OP_PER_SCAN);
- if (!getFragmentrec(signal, fragId)) {
- errorCode = 1231;
- goto error_handler;
- }//if
-
- // Verify scan type vs table type (both sides are boolean)
- if (rangeScan != DictTabInfo::isOrderedIndex(fragptr.p->tableType)) {
- errorCode = 1232;
- goto error_handler;
- }//if
-
- // 1 scan record is reserved for node recovery
- if (cscanNoFreeRec < 2) {
- jam();
- errorCode = ScanFragRef::ZNO_FREE_SCANREC_ERROR;
- goto error_handler;
- }
-
- // XXX adjust cmaxAccOps for range scans and remove this comment
- if ((cbookedAccOps + max_rows) > cmaxAccOps) {
- jam();
- errorCode = ScanFragRef::ZSCAN_BOOK_ACC_OP_ERROR;
- goto error_handler;
- }//if
-
- ndbrequire(c_scanRecordPool.seize(scanptr));
- initScanTc(scanFragReq,
- transid1,
- transid2,
- fragId,
- ZNIL);
- tcConnectptr.p->save1 = 4;
- tcConnectptr.p->primKeyLen = keyLen + 4; // hard coded in execKEYINFO
- errorCode = initScanrec(scanFragReq);
- if (errorCode != ZOK) {
- jam();
- goto error_handler2;
- }//if
- cscanNoFreeRec--;
- cbookedAccOps += max_rows;
-
- hashIndex = (tcConnectptr.p->transid[0] ^ tcConnectptr.p->tcOprec) & 1023;
- nextHashptr.i = ctransidHash[hashIndex];
- ctransidHash[hashIndex] = tcConnectptr.i;
- tcConnectptr.p->prevHashRec = RNIL;
- tcConnectptr.p->nextHashRec = nextHashptr.i;
- if (nextHashptr.i != RNIL) {
- jam();
- /* ---------------------------------------------------------------------
- * ENSURE THAT THE NEXT RECORD HAS SET PREVIOUS TO OUR RECORD
- * IF IT EXISTS
- * --------------------------------------------------------------------- */
- ptrCheckGuard(nextHashptr, ctcConnectrecFileSize, tcConnectionrec);
- nextHashptr.p->prevHashRec = tcConnectptr.i;
- }//if
- if (scanptr.p->scanAiLength > 0) {
- jam();
- tcConnectptr.p->transactionState = TcConnectionrec::WAIT_SCAN_AI;
- return;
- }//if
- continueAfterReceivingAllAiLab(signal);
- return;
-
-error_handler2:
- // no scan number allocated
- c_scanRecordPool.release(scanptr);
-error_handler:
- ref = (ScanFragRef*)&signal->theData[0];
- tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
- ref->senderData = tcConnectptr.p->clientConnectrec;
- ref->transId1 = transid1;
- ref->transId2 = transid2;
- ref->errorCode = errorCode;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
- ScanFragRef::SignalLength, JBB);
- releaseOprec(signal);
- releaseTcrec(signal, tcConnectptr);
- return;
-
- error_handler_early_1:
- if(tabptr.p->tableStatus == Tablerec::NOT_DEFINED){
- jam();
- errorCode = ZTABLE_NOT_DEFINED;
- } else if (tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_ONGOING ||
- tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE){
- jam();
- errorCode = ZDROP_TABLE_IN_PROGRESS;
- } else {
- ndbrequire(0);
- }
- error_handler_early:
- ref = (ScanFragRef*)&signal->theData[0];
- ref->senderData = senderData;
- ref->transId1 = transid1;
- ref->transId2 = transid2;
- ref->errorCode = errorCode;
- sendSignal(signal->senderBlockRef(), GSN_SCAN_FRAGREF, signal,
- ScanFragRef::SignalLength, JBB);
-}//Dblqh::execSCAN_FRAGREQ()
-
-void Dblqh::continueAfterReceivingAllAiLab(Signal* signal)
-{
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
-
- if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
- jam();
- return;
- }
-
- scanptr.p->scanState = ScanRecord::WAIT_ACC_SCAN;
- AccScanReq * req = (AccScanReq*)&signal->theData[0];
- req->senderData = scanptr.i;
- req->senderRef = cownref;
- req->tableId = tcConnectptr.p->tableref;
- req->fragmentNo = tcConnectptr.p->fragmentid;
- req->requestInfo = 0;
- AccScanReq::setLockMode(req->requestInfo, scanptr.p->scanLockMode);
- AccScanReq::setReadCommittedFlag(req->requestInfo, scanptr.p->readCommitted);
- AccScanReq::setDescendingFlag(req->requestInfo, scanptr.p->descending);
-
- if (refToBlock(tcConnectptr.p->clientBlockref) == BACKUP)
- {
- if (scanptr.p->lcpScan)
- {
- AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
- AccScanReq::setLcpScanFlag(req->requestInfo, 1);
- }
- else
- {
- /* If backup scan disktables in disk order */
- AccScanReq::setNoDiskScanFlag(req->requestInfo,
- !tcConnectptr.p->m_disk_table);
- AccScanReq::setLcpScanFlag(req->requestInfo, 0);
- }
- }
- else
- {
-#if BUG_27776_FIXED
- AccScanReq::setNoDiskScanFlag(req->requestInfo,
- !tcConnectptr.p->m_disk_table);
-#else
- AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
-#endif
- AccScanReq::setLcpScanFlag(req->requestInfo, 0);
- }
-
- req->transId1 = tcConnectptr.p->transid[0];
- req->transId2 = tcConnectptr.p->transid[1];
- req->savePointId = tcConnectptr.p->savePointId;
- sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
- AccScanReq::SignalLength, JBB);
-}//Dblqh::continueAfterReceivingAllAiLab()
-
-void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
-{
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- if (saveTupattrbuf(signal, dataPtr, length) == ZOK) {
- if (tcConnectptr.p->currTupAiLen < scanptr.p->scanAiLength) {
- jam();
- } else {
- jam();
- ndbrequire(tcConnectptr.p->currTupAiLen == scanptr.p->scanAiLength);
- continueAfterReceivingAllAiLab(signal);
- }//if
- return;
- }//if
- abort_scan(signal, scanptr.i, ZGET_ATTRINBUF_ERROR);
-}
-
-void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
- jam();
- scanptr.i = scan_ptr_i;
- c_scanRecordPool.getPtr(scanptr);
-
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- finishScanrec(signal);
- releaseScanrec(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::IDLE;
- tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
-
- if(errcode)
- {
- jam();
- ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
- ref->senderData = tcConnectptr.p->clientConnectrec;
- ref->transId1 = tcConnectptr.p->transid[0];
- ref->transId2 = tcConnectptr.p->transid[1];
- ref->errorCode = errcode;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
- ScanFragRef::SignalLength, JBB);
- }
- deleteTransidHash(signal);
- releaseOprec(signal);
- releaseTcrec(signal, tcConnectptr);
-}
-
-/*---------------------------------------------------------------------*/
-/* Send this 'I am alive' signal to TC when it is received from ACC */
-/* We include the scanPtr.i that comes from ACC in signalData[1], this */
-/* tells TC which fragment record to check for a timeout. */
-/*---------------------------------------------------------------------*/
-void Dblqh::execSCAN_HBREP(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- switch(scanptr.p->scanType){
- case ScanRecord::SCAN:
- if (scanptr.p->scanTcWaiting == ZTRUE) {
- jam();
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
-
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- const Uint32 transid1 = signal->theData[1];
- const Uint32 transid2 = signal->theData[2];
- ndbrequire(transid1 == tcConnectptr.p->transid[0] &&
- transid2 == tcConnectptr.p->transid[1]);
-
- // Update counter on tcConnectPtr
- if (tcConnectptr.p->tcTimer != 0){
- tcConnectptr.p->tcTimer = cLqhTimeOutCount;
- } else {
- jam();
- //ndbout << "SCAN_HBREP when tcTimer was off" << endl;
- }
-
- signal->theData[0] = tcConnectptr.p->clientConnectrec;
- signal->theData[1] = tcConnectptr.p->transid[0];
- signal->theData[2] = tcConnectptr.p->transid[1];
- sendSignal(tcConnectptr.p->clientBlockref,
- GSN_SCAN_HBREP, signal, 3, JBB);
- }//if
- break;
- case ScanRecord::COPY:
- // ndbout << "Dblqh::execSCAN_HBREP Dropping SCAN_HBREP" << endl;
- break;
- default:
- ndbrequire(false);
- }
-}
-
-void Dblqh::accScanConfScanLab(Signal* signal)
-{
- AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- /* -----------------------------------------------------------------------
- * PRECONDITION: SCAN_STATE = WAIT_ACC_SCAN
- * ----------------------------------------------------------------------- */
- if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
- jam();
- /* ---------------------------------------------------------------------
- * THE FRAGMENT WAS EMPTY.
- * REPORT SUCCESSFUL COPYING.
- * --------------------------------------------------------------------- */
- tupScanCloseConfLab(signal);
- return;
- }//if
- scanptr.p->scanAccPtr = accScanConf->accPtr;
- if (scanptr.p->rangeScan) {
- jam();
- TuxBoundInfo* req = (TuxBoundInfo*)signal->getDataPtrSend();
- req->errorCode = RNIL;
- req->tuxScanPtrI = scanptr.p->scanAccPtr;
- 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();
- /*
- * Cannot use STORED_PROCREF to abort since even the REF
- * returns a stored proc id. So record error and continue.
- * The scan is already Invalid in TUX and returns empty set.
- */
- tcConnectptr.p->errorCode = req->errorCode;
- }
- }
-
- scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
- if(scanptr.p->scanStoredProcId == RNIL)
- {
- jam();
- 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;
- 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,
- * TSTORED_PROC_ID
- * -------------------------------------------------------------------------
- * PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_SCAN
- * ------------------------------------------------------------------------- */
-void Dblqh::storedProcConfScanLab(Signal* signal)
-{
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
- // STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
- closeScanLab(signal);
- return;
- }//if
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_FIRST_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- jamLine(fragptr.p->fragStatus);
- ndbout_c("fragptr.p->fragStatus: %u",
- fragptr.p->fragStatus);
- ndbrequire(false);
- break;
- }//switch
- continueFirstScanAfterBlockedLab(signal);
-}//Dblqh::storedProcConfScanLab()
-
-void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal)
-{
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = RNIL;
- signal->theData[2] = NextScanReq::ZSCAN_NEXT;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- return;
-}//Dblqh::continueFirstScanAfterBlockedLab()
-
-/* -------------------------------------------------------------------------
- * When executing a scan we must come up to the surface at times to make
- * sure we can quickly start local checkpoints.
- * ------------------------------------------------------------------------- */
-void Dblqh::execCHECK_LCP_STOP(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- if (signal->theData[1] == ZTRUE) {
- jam();
- signal->theData[0] = ZCHECK_LCP_STOP_BLOCKED;
- signal->theData[1] = scanptr.i;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
- signal->theData[0] = RNIL;
- return;
- }//if
- if (fragptr.p->fragStatus != Fragrecord::FSACTIVE) {
- ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED);
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
- signal->theData[0] = RNIL;
- }//if
-}//Dblqh::execCHECK_LCP_STOP()
-
-void Dblqh::checkLcpStopBlockedLab(Signal* signal)
-{
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- continueAfterCheckLcpStopBlocked(signal);
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- ndbrequire(false);
- }//switch
-}//Dblqh::checkLcpStopBlockedLab()
-
-void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
-{
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
- EXECUTE_DIRECT(refToBlock(scanptr.p->scanBlockref), GSN_ACC_CHECK_SCAN,
- signal, 2);
-}//Dblqh::continueAfterCheckLcpStopBlocked()
-
-/* -------------------------------------------------------------------------
- * ENTER NEXT_SCANCONF
- * -------------------------------------------------------------------------
- * PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN
- * ------------------------------------------------------------------------- */
-void Dblqh::nextScanConfScanLab(Signal* signal)
-{
- NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- if (nextScanConf->fragId == RNIL) {
- jam();
- /* ---------------------------------------------------------------------
- * THERE ARE NO MORE TUPLES TO FETCH. IF WE HAVE ANY
- * OPERATIONS STILL NEEDING A LOCK WE REPORT TO THE
- * APPLICATION AND CLOSE THE SCAN WHEN THE NEXT SCAN
- * REQUEST IS RECEIVED. IF WE DO NOT HAVE ANY NEED FOR
- * LOCKS WE CAN CLOSE THE SCAN IMMEDIATELY.
- * --------------------------------------------------------------------- */
- /*************************************************************
- * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
- ************************************************************ */
- if (!scanptr.p->scanLockHold)
- {
- jam();
- closeScanLab(signal);
- return;
- }
-
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- if ((scanptr.p->scanLockHold == ZTRUE) &&
- (scanptr.p->m_curr_batch_size_rows > 0)) {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- scanReleaseLocksLab(signal);
- return;
- }//if
- jam();
- closeScanLab(signal);
- return;
- }//if
-
- if (scanptr.p->m_curr_batch_size_rows > 0) {
- jam();
-
- if((tcConnectptr.p->primKeyLen - 4) == 0)
- scanptr.p->scanCompletedStatus = ZTRUE;
-
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
- sendScanFragConf(signal, ZFALSE);
- return;
- }//if
- closeScanLab(signal);
- return;
- }//if
-
- // If accOperationPtr == RNIL no record was returned by ACC
- Uint32 accOpPtr = nextScanConf->accOperationPtr;
- if (accOpPtr == RNIL)
- {
- jam();
- /*************************************************************
- * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
- ************************************************************ */
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- if ((scanptr.p->scanLockHold == ZTRUE) &&
- (scanptr.p->m_curr_batch_size_rows > 0)) {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- scanReleaseLocksLab(signal);
- return;
- }//if
- jam();
- closeScanLab(signal);
- return;
- }//if
-
- if (scanptr.p->m_curr_batch_size_rows > 0) {
- jam();
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
- sendScanFragConf(signal, ZFALSE);
- return;
- }//if
-
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- sendSignal(scanptr.p->scanBlockref,
- GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- return;
- }//if
- jam();
- set_acc_ptr_in_scan_record(scanptr.p,
- scanptr.p->m_curr_batch_size_rows,
- accOpPtr);
-
- jam();
- nextScanConfLoopLab(signal);
-}//Dblqh::nextScanConfScanLab()
-
-void Dblqh::nextScanConfLoopLab(Signal* signal)
-{
- /* ----------------------------------------------------------------------
- * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
- * ---------------------------------------------------------------------- */
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
- if ((scanptr.p->scanLockHold == ZTRUE) &&
- (scanptr.p->m_curr_batch_size_rows > 0)) {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- scanReleaseLocksLab(signal);
- return;
- }//if
- closeScanLab(signal);
- return;
- }//if
-
- Fragrecord* fragPtrP= fragptr.p;
- if (scanptr.p->rangeScan) {
- jam();
- // for ordered index use primary table
- fragPtrP= c_fragment_pool.getPtr(fragPtrP->tableFragptr);
- }
-
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_TUPKEY;
- if(tcConnectptr.p->m_disk_table)
- {
- next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
- }
- else
- {
- next_scanconf_tupkeyreq(signal, scanptr, tcConnectptr.p, fragPtrP, RNIL);
- }
-}
-
-void
-Dblqh::next_scanconf_load_diskpage(Signal* signal,
- ScanRecordPtr scanPtr,
- Ptr<TcConnectionrec> regTcPtr,
- Fragrecord* fragPtrP)
-{
- jam();
-
- int res;
- Uint32 local_key = scanPtr.p->m_row_id.ref();
-
- if((res= c_tup->load_diskpage_scan(signal,
- regTcPtr.p->tupConnectrec,
- fragPtrP->tupFragptr,
- local_key,
- 0)) > 0)
- {
- next_scanconf_tupkeyreq(signal, scanptr, regTcPtr.p, fragPtrP, res);
- }
- else if(unlikely(res != 0))
- {
- jam();
- TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
- ref->userRef= regTcPtr.i;
- ref->errorCode= ~0;
- execTUPKEYREF(signal);
- }
-}
-
-void
-Dblqh::next_scanconf_load_diskpage_callback(Signal* signal,
- Uint32 callbackData,
- Uint32 disk_page)
-{
- jamEntry();
-
- Ptr<TcConnectionrec> regTcPtr;
- regTcPtr.i= callbackData;
- ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
-
- ScanRecordPtr scanPtr;
- c_scanRecordPool.getPtr(scanPtr, regTcPtr.p->tcScanRec);
-
- if(disk_page > 0)
- {
- FragrecordPtr fragPtr;
- c_fragment_pool.getPtr(fragPtr, regTcPtr.p->fragmentptr);
-
- if (scanPtr.p->rangeScan) {
- jam();
- // for ordered index use primary table
- fragPtr.p = c_fragment_pool.getPtr(fragPtr.p->tableFragptr);
- }
-
- next_scanconf_tupkeyreq(signal, scanPtr, regTcPtr.p, fragPtr.p, disk_page);
- }
- else
- {
- TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
- ref->userRef= callbackData;
- ref->errorCode= disk_page;
- execTUPKEYREF(signal);
- }
-}
-
-void
-Dblqh::next_scanconf_tupkeyreq(Signal* signal,
- Ptr<ScanRecord> scanPtr,
- TcConnectionrec * regTcPtr,
- Fragrecord* fragPtrP,
- Uint32 disk_page)
-{
- jam();
- Uint32 reqinfo = (scanPtr.p->scanLockHold == ZFALSE);
- reqinfo = reqinfo + (regTcPtr->operation << 6);
- reqinfo = reqinfo + (regTcPtr->opExec << 10);
-
- TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
-
- tupKeyReq->connectPtr = regTcPtr->tupConnectrec;
- tupKeyReq->request = reqinfo;
- tupKeyReq->keyRef1 = scanPtr.p->m_row_id.m_page_no;
- tupKeyReq->keyRef2 = scanPtr.p->m_row_id.m_page_idx;
- tupKeyReq->attrBufLen = 0;
- tupKeyReq->opRef = scanPtr.p->scanApiOpPtr;
- tupKeyReq->applRef = scanPtr.p->scanApiBlockref;
- tupKeyReq->storedProcedure = scanPtr.p->scanStoredProcId;
- tupKeyReq->transId1 = regTcPtr->transid[0];
- tupKeyReq->transId2 = regTcPtr->transid[1];
- tupKeyReq->fragPtr = fragPtrP->tupFragptr;
- tupKeyReq->primaryReplica = (regTcPtr->seqNoReplica == 0)?true:false;
- tupKeyReq->coordinatorTC = regTcPtr->tcBlockref;
- tupKeyReq->tcOpIndex = regTcPtr->tcOprec;
- tupKeyReq->savePointId = regTcPtr->savePointId;
- tupKeyReq->disk_page= disk_page;
- Uint32 blockNo = refToBlock(regTcPtr->tcTupBlockref);
- EXECUTE_DIRECT(blockNo, GSN_TUPKEYREQ, signal,
- TupKeyReq::SignalLength);
-}
-
-/* -------------------------------------------------------------------------
- * RECEPTION OF FURTHER KEY INFORMATION WHEN KEY SIZE > 16 BYTES.
- * -------------------------------------------------------------------------
- * PRECONDITION: SCAN_STATE = WAIT_SCAN_KEYINFO
- * ------------------------------------------------------------------------- */
-void
-Dblqh::keyinfoLab(const Uint32 * src, const Uint32 * end)
-{
- do {
- jam();
- 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 = tcConP->fragmentid;
- Uint32 fragPageId = scanP->m_row_id.m_page_no;
- Uint32 pageIndex = scanP->m_row_id.m_page_idx;
-
- if(scanP->rangeScan)
- {
- jam();
- // for ordered index use primary table
- FragrecordPtr tFragPtr;
- tFragPtr.i = fragptr.p->tableFragptr;
- c_fragment_pool.getPtr(tFragPtr);
- tableId = tFragPtr.p->tabRef;
- }
-
- int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst, false);
- jamEntry();
- if(0)
- ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
- tableId, fragId, fragPageId, pageIndex, ret);
- ndbassert(ret > 0);
-
- return ret;
-}
-
-/* -------------------------------------------------------------------------
- * ENTER TUPKEYCONF
- * -------------------------------------------------------------------------
- * PRECONDITION: TRANSACTION_STATE = SCAN_TUPKEY
- * ------------------------------------------------------------------------- */
-void Dblqh::scanTupkeyConfLab(Signal* signal)
-{
- const TupKeyConf * conf = (TupKeyConf *)signal->getDataPtr();
- UintR tdata4 = conf->readLength;
- UintR tdata5 = conf->lastRow;
-
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
-
- Uint32 rows = scanptr.p->m_curr_batch_size_rows;
- Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p, rows, false);
- if (accOpPtr != (Uint32)-1)
- {
- c_acc->execACCKEY_ORD(signal, accOpPtr);
- jamEntry();
- }
- else
- {
- ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
- }
-
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- /* ---------------------------------------------------------------------
- * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
- * --------------------------------------------------------------------- */
- if ((scanptr.p->scanLockHold == ZTRUE) && rows)
- {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- scanReleaseLocksLab(signal);
- return;
- }//if
- jam();
- closeScanLab(signal);
- return;
- }//if
- if (scanptr.p->scanKeyinfoFlag) {
- jam();
- // 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;
- scanptr.p->m_curr_batch_size_rows = rows + 1;
- scanptr.p->m_last_row = tdata5;
- if (scanptr.p->check_scan_batch_completed() | tdata5){
- if (scanptr.p->scanLockHold == ZTRUE) {
- jam();
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
- sendScanFragConf(signal, ZFALSE);
- return;
- } else {
- jam();
- scanptr.p->scanReleaseCounter = rows + 1;
- scanReleaseLocksLab(signal);
- return;
- }
- } else {
- if (scanptr.p->scanLockHold == ZTRUE) {
- jam();
- scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
- } else {
- jam();
- scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
- }
- }
- scanNextLoopLab(signal);
-}//Dblqh::scanTupkeyConfLab()
-
-void Dblqh::scanNextLoopLab(Signal* signal)
-{
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- ndbrequire(false);
- }//switch
- continueScanAfterBlockedLab(signal);
-}//Dblqh::scanNextLoopLab()
-
-void Dblqh::continueScanAfterBlockedLab(Signal* signal)
-{
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- Uint32 accOpPtr;
- if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_ABORT) {
- jam();
- scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_COMMIT;
- accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
- scanptr.p->m_curr_batch_size_rows,
- false);
- scanptr.p->scan_acc_index--;
- } else if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_COMMIT) {
- jam();
- accOpPtr= get_acc_ptr_from_scan_record(scanptr.p,
- scanptr.p->m_curr_batch_size_rows-1,
- false);
- } else {
- jam();
- accOpPtr = RNIL; // The value is not used in ACC
- }//if
- scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = accOpPtr;
- signal->theData[2] = scanptr.p->scanFlag;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
-}//Dblqh::continueScanAfterBlockedLab()
-
-/* -------------------------------------------------------------------------
- * ENTER TUPKEYREF WITH
- * TC_CONNECTPTR,
- * TERROR_CODE
- * -------------------------------------------------------------------------
- * PRECONDITION: TRANSACTION_STATE = SCAN_TUPKEY
- * ------------------------------------------------------------------------- */
-void Dblqh::scanTupkeyRefLab(Signal* signal)
-{
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
-
- Uint32 rows = scanptr.p->m_curr_batch_size_rows;
- Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanptr.p, rows, false);
- if (accOpPtr != (Uint32)-1)
- {
- c_acc->execACCKEY_ORD(signal, accOpPtr);
- }
- else
- {
- ndbassert(refToBlock(scanptr.p->scanBlockref) != DBACC);
- }
-
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- /* ---------------------------------------------------------------------
- * STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
- * --------------------------------------------------------------------- */
- if ((scanptr.p->scanLockHold == ZTRUE) && rows)
- {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- scanReleaseLocksLab(signal);
- return;
- }//if
- jam();
- closeScanLab(signal);
- return;
- }//if
- if ((terrorCode != ZSEARCH_CONDITION_FALSE) &&
- (terrorCode != ZNO_TUPLE_FOUND) &&
- (terrorCode >= ZUSER_ERROR_CODE_LIMIT)) {
- scanptr.p->scanErrorCounter++;
- tcConnectptr.p->errorCode = terrorCode;
-
- if (scanptr.p->scanLockHold == ZTRUE) {
- jam();
- scanptr.p->scanReleaseCounter = 1;
- } else {
- jam();
- scanptr.p->m_curr_batch_size_rows = rows + 1;
- scanptr.p->scanReleaseCounter = rows + 1;
- }//if
- /* --------------------------------------------------------------------
- * WE NEED TO RELEASE ALL LOCKS CURRENTLY
- * HELD BY THIS SCAN.
- * -------------------------------------------------------------------- */
- scanReleaseLocksLab(signal);
- return;
- }//if
- Uint32 time_passed= tcConnectptr.p->tcTimer - cLqhTimeOutCount;
- if (rows) {
- if (time_passed > 1) {
- /* -----------------------------------------------------------------------
- * WE NEED TO ENSURE THAT WE DO NOT SEARCH FOR THE NEXT TUPLE FOR A
- * LONG TIME WHILE WE KEEP A LOCK ON A FOUND TUPLE. WE RATHER REPORT
- * THE FOUND TUPLE IF FOUND TUPLES ARE RARE. If more than 10 ms passed we
- * send the found tuples to the API.
- * ----------------------------------------------------------------------- */
- scanptr.p->scanReleaseCounter = rows + 1;
- scanReleaseLocksLab(signal);
- return;
- }
- } else {
- if (time_passed > 10) {
- jam();
- signal->theData[0]= scanptr.i;
- signal->theData[1]= tcConnectptr.p->transid[0];
- signal->theData[2]= tcConnectptr.p->transid[1];
- execSCAN_HBREP(signal);
- }
- }
- scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT_ABORT;
- scanNextLoopLab(signal);
-}//Dblqh::scanTupkeyRefLab()
-
-/* -------------------------------------------------------------------------
- * THE SCAN HAS BEEN COMPLETED. EITHER BY REACHING THE END OR BY COMMAND
- * FROM THE APPLICATION OR BY SOME SORT OF ERROR CONDITION.
- * ------------------------------------------------------------------------- */
-void Dblqh::closeScanLab(Signal* signal)
-{
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CLOSE_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- ndbrequire(false);
- }//switch
- continueCloseScanAfterBlockedLab(signal);
-}//Dblqh::closeScanLab()
-
-void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
-{
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- scanptr.p->scanState = ScanRecord::WAIT_CLOSE_SCAN;
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = RNIL;
- signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
-}//Dblqh::continueCloseScanAfterBlockedLab()
-
-/* -------------------------------------------------------------------------
- * ENTER NEXT_SCANCONF
- * -------------------------------------------------------------------------
- * PRECONDITION: SCAN_STATE = WAIT_CLOSE_SCAN
- * ------------------------------------------------------------------------- */
-void Dblqh::accScanCloseConfLab(Signal* signal)
-{
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
-
- if((tcConnectptr.p->primKeyLen - 4) > 0 &&
- scanptr.p->scanCompletedStatus != ZTRUE)
- {
- jam();
- 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;
- signal->theData[3] = ZDELETE_STORED_PROC_ID;
- signal->theData[4] = scanptr.p->scanStoredProcId;
- sendSignal(tcConnectptr.p->tcTupBlockref,
- GSN_STORED_PROCREQ, signal, 5, JBB);
-}//Dblqh::accScanCloseConfLab()
-
-/* -------------------------------------------------------------------------
- * ENTER STORED_PROCCONF WITH
- * -------------------------------------------------------------------------
- * PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_SCAN
- * ------------------------------------------------------------------------- */
-void Dblqh::tupScanCloseConfLab(Signal* signal)
-{
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
- jam();
- tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
- ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
- tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
- signal->theData[0] = ZLQH_TRANS_NEXT;
- signal->theData[1] = tcNodeFailptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- } else if (tcConnectptr.p->errorCode != 0) {
- jam();
- ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
- ref->senderData = tcConnectptr.p->clientConnectrec;
- ref->transId1 = tcConnectptr.p->transid[0];
- ref->transId2 = tcConnectptr.p->transid[1];
- ref->errorCode = tcConnectptr.p->errorCode;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
- ScanFragRef::SignalLength, JBB);
- } else {
- jam();
- sendScanFragConf(signal, ZSCAN_FRAG_CLOSED);
- }//if
- finishScanrec(signal);
- releaseScanrec(signal);
- tcConnectptr.p->tcScanRec = RNIL;
- deleteTransidHash(signal);
- releaseOprec(signal);
- releaseTcrec(signal, tcConnectptr);
-}//Dblqh::tupScanCloseConfLab()
-
-/* =========================================================================
- * ======= INITIATE SCAN RECORD =======
- *
- * SUBROUTINE SHORT NAME = ISC
- * ========================================================================= */
-Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
-{
- const Uint32 reqinfo = scanFragReq->requestInfo;
- const Uint32 max_rows = scanFragReq->batch_size_rows;
- const Uint32 max_bytes = scanFragReq->batch_size_bytes;
- const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
- const Uint32 scanLockHold = ScanFragReq::getHoldLockFlag(reqinfo);
- const Uint32 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
- const Uint32 readCommitted = ScanFragReq::getReadCommittedFlag(reqinfo);
- const Uint32 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
- const Uint32 descending = ScanFragReq::getDescendingFlag(reqinfo);
- Uint32 tupScan = ScanFragReq::getTupScanFlag(reqinfo);
- const Uint32 attrLen = ScanFragReq::getAttrLen(reqinfo);
- const Uint32 scanPrio = ScanFragReq::getScanPrio(reqinfo);
-
- scanptr.p->scanKeyinfoFlag = keyinfo;
- scanptr.p->scanLockHold = scanLockHold;
- scanptr.p->scanCompletedStatus = ZFALSE;
- scanptr.p->scanType = ScanRecord::SCAN;
- scanptr.p->scanApiBlockref = scanFragReq->resultRef;
- scanptr.p->scanAiLength = attrLen;
- scanptr.p->scanTcrec = tcConnectptr.i;
- scanptr.p->scanSchemaVersion = scanFragReq->schemaVersion;
-
- scanptr.p->m_curr_batch_size_rows = 0;
- scanptr.p->m_curr_batch_size_bytes= 0;
- scanptr.p->m_max_batch_size_rows = max_rows;
- scanptr.p->m_max_batch_size_bytes = max_bytes;
-
-#if 0
- if (! rangeScan)
- tupScan = 1;
-#endif
-
- 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 = rangeScan;
- scanptr.p->descending = descending;
- scanptr.p->tupScan = tupScan;
- scanptr.p->lcpScan = ScanFragReq::getLcpScanFlag(reqinfo);
- scanptr.p->scanState = ScanRecord::SCAN_FREE;
- scanptr.p->scanFlag = ZFALSE;
- scanptr.p->m_row_id.setNull();
- scanptr.p->scanTcWaiting = ZTRUE;
- scanptr.p->scanNumber = ~0;
- scanptr.p->scanApiOpPtr = scanFragReq->clientOpPtr;
- scanptr.p->m_last_row = 0;
- scanptr.p->scanStoredProcId = RNIL;
- scanptr.p->copyPtr = RNIL;
- if (max_rows == 0 || (max_bytes > 0 && max_rows > max_bytes)){
- jam();
- return ScanFragRef::ZWRONG_BATCH_SIZE;
- }
- if (!seize_acc_ptr_list(scanptr.p, max_rows)){
- jam();
- return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
- }
- /**
- * Used for scan take over
- */
- FragrecordPtr tFragPtr;
- tFragPtr.i = fragptr.p->tableFragptr;
- c_fragment_pool.getPtr(tFragPtr);
- scanptr.p->fragPtrI = fragptr.p->tableFragptr;
-
- /**
- * !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1) = 1-11
- * idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
- */
- tupScan = 0; // Make sure that close tup scan does not start acc scan incorrectly
- 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);
-
- if(free == Fragrecord::ScanNumberMask::NotFound || free >= stop){
- jam();
-
- if(scanPrio == 0){
- jam();
- return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
- }
-
- /**
- * Put on queue
- */
- scanptr.p->scanState = ScanRecord::IN_QUEUE;
- LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
- fragptr.p->m_queuedScans);
- queue.add(scanptr);
- return ZOK;
- }
-
- scanptr.p->scanNumber = free;
- tFragPtr.p->m_scanNumberMask.clear(free);// Update mask
-
- LocalDLList<ScanRecord> active(c_scanRecordPool, fragptr.p->m_activeScans);
- active.add(scanptr);
- if(scanptr.p->scanKeyinfoFlag){
- jam();
-#if defined VM_TRACE || defined ERROR_INSERT
- ScanRecordPtr tmp;
- ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p));
-#endif
-#ifdef TRACE_SCAN_TAKEOVER
- ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d",
- scanptr.p->scanNumber, scanptr.p->fragPtrI,
- tabptr.i, scanFragReq->fragmentNoKeyLen & 0xFFFF,
- fragptr.i, fragptr.p->tableFragptr);
-#endif
- c_scanTakeOverHash.add(scanptr);
- }
- init_acc_ptr_list(scanptr.p);
- return ZOK;
-}
-
-/* =========================================================================
- * ======= INITIATE TC RECORD AT SCAN =======
- *
- * SUBROUTINE SHORT NAME = IST
- * ========================================================================= */
-void Dblqh::initScanTc(const ScanFragReq* req,
- Uint32 transid1,
- Uint32 transid2,
- Uint32 fragId,
- Uint32 nodeId)
-{
- tcConnectptr.p->transid[0] = transid1;
- tcConnectptr.p->transid[1] = transid2;
- tcConnectptr.p->tcScanRec = scanptr.i;
- tcConnectptr.p->tableref = tabptr.i;
- tcConnectptr.p->fragmentid = fragId;
- tcConnectptr.p->fragmentptr = fragptr.i;
- tcConnectptr.p->tcOprec = tcConnectptr.p->clientConnectrec;
- tcConnectptr.p->tcBlockref = tcConnectptr.p->clientBlockref;
- tcConnectptr.p->errorCode = 0;
- tcConnectptr.p->reclenAiLqhkey = 0;
- tcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
- tcConnectptr.p->nextReplica = nodeId;
- tcConnectptr.p->currTupAiLen = 0;
- tcConnectptr.p->opExec = 1;
- 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;
- tcConnectptr.p->m_dealloc = 0;
- tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
- TablerecPtr tTablePtr;
- tTablePtr.i = tabptr.p->primaryTableId;
- ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
- tcConnectptr.p->m_disk_table = tTablePtr.p->m_disk_table &&
- (!req || !ScanFragReq::getNoDiskFlag(req->requestInfo));
-
- tabptr.p->usageCount++;
-}//Dblqh::initScanTc()
-
-/* =========================================================================
- * ======= FINISH SCAN RECORD =======
- *
- * REMOVE SCAN RECORD FROM PER FRAGMENT LIST.
- * ========================================================================= */
-void Dblqh::finishScanrec(Signal* signal)
-{
- release_acc_ptr_list(scanptr.p);
-
- LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
- fragptr.p->m_queuedScans);
-
- if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
- jam();
- queue.release(scanptr);
- return;
- }
-
- if(scanptr.p->scanKeyinfoFlag){
- jam();
- ScanRecordPtr tmp;
-#ifdef TRACE_SCAN_TAKEOVER
- ndbout_c("removing (%d %d)", scanptr.p->scanNumber, scanptr.p->fragPtrI);
-#endif
- c_scanTakeOverHash.remove(tmp, * scanptr.p);
- ndbrequire(tmp.p == scanptr.p);
- }
-
- LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
- scans.release(scanptr);
-
- FragrecordPtr tFragPtr;
- tFragPtr.i = scanptr.p->fragPtrI;
- c_fragment_pool.getPtr(tFragPtr);
-
- const Uint32 scanNumber = scanptr.p->scanNumber;
- ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
- ScanRecordPtr restart;
-
- /**
- * Start on of queued scans
- */
- if(scanNumber == NR_ScanNo || !queue.first(restart)){
- jam();
- tFragPtr.p->m_scanNumberMask.set(scanNumber);
- return;
- }
-
- if(ERROR_INSERTED(5034)){
- jam();
- tFragPtr.p->m_scanNumberMask.set(scanNumber);
- return;
- }
-
- ndbrequire(restart.p->scanState == ScanRecord::IN_QUEUE);
-
- ScanRecordPtr tmpScan = scanptr;
- TcConnectionrecPtr tmpTc = tcConnectptr;
-
- tcConnectptr.i = restart.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- restart.p->scanNumber = scanNumber;
-
- queue.remove(restart);
- scans.add(restart);
- if(restart.p->scanKeyinfoFlag){
- jam();
-#if defined VM_TRACE || defined ERROR_INSERT
- ScanRecordPtr tmp;
- ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p));
-#endif
- c_scanTakeOverHash.add(restart);
-#ifdef TRACE_SCAN_TAKEOVER
- ndbout_c("adding-r (%d %d)", restart.p->scanNumber, restart.p->fragPtrI);
-#endif
- }
-
- /**
- * This state is a bit weird, but that what set in initScanRec
- */
- restart.p->scanState = ScanRecord::SCAN_FREE;
- if(tcConnectptr.p->transactionState == TcConnectionrec::SCAN_STATE_USED)
- {
- scanptr = restart;
- continueAfterReceivingAllAiLab(signal);
- }
- else
- {
- ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_SCAN_AI);
- }
-
- scanptr = tmpScan;
- tcConnectptr = tmpTc;
-}//Dblqh::finishScanrec()
-
-/* =========================================================================
- * ======= RELEASE SCAN RECORD =======
- *
- * RELEASE A SCAN RECORD TO THE FREELIST.
- * ========================================================================= */
-void Dblqh::releaseScanrec(Signal* signal)
-{
- scanptr.p->scanState = ScanRecord::SCAN_FREE;
- scanptr.p->scanType = ScanRecord::ST_IDLE;
- scanptr.p->scanTcWaiting = ZFALSE;
- cbookedAccOps -= scanptr.p->m_max_batch_size_rows;
- cscanNoFreeRec++;
-}//Dblqh::releaseScanrec()
-
-/* ------------------------------------------------------------------------
- * ------- SEND KEYINFO20 TO API -------
- *
- * ------------------------------------------------------------------------ */
-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];
-
- /**
- * Note that this code requires signal->theData to be big enough for
- * a entire key
- */
- const BlockReference ref = scanP->scanApiBlockref;
- const Uint32 scanOp = scanP->m_curr_batch_size_rows;
- const Uint32 nodeId = refToNode(ref);
- const bool connectedToNode = getNodeInfo(nodeId).m_connected;
-#ifdef NOT_USED
- const Uint32 type = getNodeInfo(nodeId).m_type;
- const bool is_api= (type >= NodeInfo::API && type <= NodeInfo::REP);
- const bool old_dest= (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
-#endif
- const bool longable = true; // TODO is_api && !old_dest;
-
- Uint32 * dst = keyInfo->keyData;
- dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
-
- 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) + (fragId << 20);
- keyInfo->transId1 = tcConP->transid[0];
- keyInfo->transId2 = tcConP->transid[1];
-
- Uint32 * src = signal->theData+25;
- if(connectedToNode){
- jam();
-
- if(nodeId != getOwnNodeId()){
- jam();
-
- if(keyLen <= KeyInfo20::DataLength || !longable) {
- while(keyLen > KeyInfo20::DataLength){
- jam();
- MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength);
- sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB);
- src += KeyInfo20::DataLength;;
- keyLen -= KeyInfo20::DataLength;
- }
-
- MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
- sendSignal(ref, GSN_KEYINFO20, signal,
- KeyInfo20::HeaderLength+keyLen, JBB);
- return keyLen;
- }
-
- LinearSectionPtr ptr[3];
- ptr[0].p = src;
- ptr[0].sz = keyLen;
- sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
- JBB, ptr, 1);
- return keyLen;
- }
-
- EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
- KeyInfo20::HeaderLength + keyLen);
- jamEntry();
- return keyLen;
- }
-
- /**
- * If this node does not have a direct connection
- * to the receiving node we want to send the signals
- * routed via the node that controls this read
- */
- Uint32 routeBlockref = tcConP->clientBlockref;
-
- if(keyLen < KeyInfo20::DataLength || !longable){
- jam();
-
- while (keyLen > (KeyInfo20::DataLength - 1)) {
- jam();
- MEMCOPY_NO_WORDS(keyInfo->keyData, src, KeyInfo20::DataLength - 1);
- keyInfo->keyData[KeyInfo20::DataLength-1] = ref;
- sendSignal(routeBlockref, GSN_KEYINFO20_R, signal, 25, JBB);
- src += KeyInfo20::DataLength - 1;
- keyLen -= KeyInfo20::DataLength - 1;
- }
-
- MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
- keyInfo->keyData[keyLen] = ref;
- sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
- KeyInfo20::HeaderLength+keyLen+1, JBB);
- return keyLen;
- }
-
- keyInfo->keyData[0] = ref;
- LinearSectionPtr ptr[3];
- ptr[0].p = src;
- ptr[0].sz = keyLen;
- sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
- KeyInfo20::HeaderLength+1, JBB, ptr, 1);
- return keyLen;
-}
-
-/* ------------------------------------------------------------------------
- * ------- SEND SCAN_FRAGCONF TO TC THAT CONTROLS THE SCAN -------
- *
- * ------------------------------------------------------------------------ */
-void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
-{
- Uint32 completed_ops= scanptr.p->m_curr_batch_size_rows;
- Uint32 total_len= scanptr.p->m_curr_batch_size_bytes;
- scanptr.p->scanTcWaiting = ZFALSE;
-
- if(ERROR_INSERTED(5037)){
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }
- ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
-#ifdef NOT_USED
- NodeId tc_node_id= refToNode(tcConnectptr.p->clientBlockref);
-#endif
- Uint32 trans_id1= tcConnectptr.p->transid[0];
- Uint32 trans_id2= tcConnectptr.p->transid[1];
-
- conf->senderData = tcConnectptr.p->clientConnectrec;
- conf->completedOps = completed_ops;
- conf->fragmentCompleted = scanCompleted;
- conf->transId1 = trans_id1;
- conf->transId2 = trans_id2;
- conf->total_len= total_len;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGCONF,
- signal, ScanFragConf::SignalLength, JBB);
-
- if(!scanptr.p->scanLockHold)
- {
- jam();
- scanptr.p->m_curr_batch_size_rows = 0;
- scanptr.p->m_curr_batch_size_bytes= 0;
- }
-}//Dblqh::sendScanFragConf()
-
-/* ######################################################################### */
-/* ####### NODE RECOVERY MODULE ####### */
-/* */
-/* ######################################################################### */
-/*---------------------------------------------------------------------------*/
-/* */
-/* THIS MODULE IS USED WHEN A NODE HAS FAILED. IT PERFORMS A COPY OF A */
-/* FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL */
-/* CONNECTIONS TO THE FAILED NODE. */
-/*---------------------------------------------------------------------------*/
-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()
-
-/**
- * PREPARE COPY FRAG REQ
- */
-void
-Dblqh::execPREPARE_COPY_FRAG_REQ(Signal* signal)
-{
- jamEntry();
- PrepareCopyFragReq req = *(PrepareCopyFragReq*)signal->getDataPtr();
-
- CRASH_INSERTION(5045);
-
- tabptr.i = req.tableId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
-
- Uint32 max_page = RNIL;
-
- if (getOwnNodeId() != req.startingNodeId)
- {
- jam();
- /**
- * This is currently dead code...
- * but is provided so we can impl. a better scan+delete on
- * starting node wo/ having to change running node
- */
- ndbrequire(getOwnNodeId() == req.copyNodeId);
- c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
-
- PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend();
- conf->senderData = req.senderData;
- conf->senderRef = reference();
- conf->tableId = req.tableId;
- conf->fragId = req.fragId;
- conf->copyNodeId = req.copyNodeId;
- conf->startingNodeId = req.startingNodeId;
- conf->maxPageNo = max_page;
- sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF,
- signal, PrepareCopyFragConf::SignalLength, JBB);
-
- return;
- }
-
- if (! DictTabInfo::isOrderedIndex(tabptr.p->tableType))
- {
- jam();
- ndbrequire(getFragmentrec(signal, req.fragId));
-
- /**
- *
- */
- if (cstartType == NodeState::ST_SYSTEM_RESTART)
- {
- jam();
- signal->theData[0] = fragptr.p->tabRef;
- signal->theData[1] = fragptr.p->fragId;
- sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB);
- }
-
-
- /**
- *
- */
- fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED;
- fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
- fragptr.p->logFlag = Fragrecord::STATE_FALSE;
-
- c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
- }
-
- PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend();
- conf->senderData = req.senderData;
- conf->senderRef = reference();
- conf->tableId = req.tableId;
- conf->fragId = req.fragId;
- conf->copyNodeId = req.copyNodeId;
- conf->startingNodeId = req.startingNodeId;
- conf->maxPageNo = max_page;
- sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF,
- signal, PrepareCopyFragConf::SignalLength, JBB);
-}
-
-/* *************************************** */
-/* COPY_FRAGREQ: Start copying a fragment */
-/* *************************************** */
-void Dblqh::execCOPY_FRAGREQ(Signal* signal)
-{
- jamEntry();
- const CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
- tabptr.i = copyFragReq->tableId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- Uint32 i;
- const Uint32 fragId = copyFragReq->fragId;
- const Uint32 copyPtr = copyFragReq->userPtr;
- const Uint32 userRef = copyFragReq->userRef;
- const Uint32 nodeId = copyFragReq->nodeId;
- const Uint32 gci = copyFragReq->gci;
-
- ndbrequire(cnoActiveCopy < 3);
- ndbrequire(getFragmentrec(signal, fragId));
- ndbrequire(fragptr.p->copyFragState == ZIDLE);
- ndbrequire(cfirstfreeTcConrec != RNIL);
- ndbrequire(fragptr.p->m_scanNumberMask.get(NR_ScanNo));
-
- Uint32 key = fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
-
- Uint32 checkversion = NDB_VERSION >= MAKE_VERSION(5,1,0) ?
- NDBD_UPDATE_FRAG_DIST_KEY_51 : NDBD_UPDATE_FRAG_DIST_KEY_50;
-
- Uint32 nodeCount = copyFragReq->nodeCount;
- NdbNodeBitmask nodemask;
- if (getNodeInfo(refToNode(userRef)).m_version >= checkversion)
- {
- ndbrequire(nodeCount <= MAX_REPLICAS);
- for (i = 0; i<nodeCount; i++)
- nodemask.set(copyFragReq->nodeList[i]);
- }
- Uint32 maxPage = copyFragReq->nodeList[nodeCount];
- Uint32 version = getNodeInfo(refToNode(userRef)).m_version;
- if (ndb_check_prep_copy_frag_version(version) < 2)
- {
- jam();
- maxPage = RNIL;
- }
-
- if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
- jam();
- /**
- * Ordered index doesn't need to be copied
- */
- CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
- conf->userPtr = copyPtr;
- conf->sendingNodeId = cownNodeid;
- conf->startingNodeId = nodeId;
- conf->tableId = tabptr.i;
- conf->fragId = fragId;
- sendSignal(userRef, GSN_COPY_FRAGCONF, signal,
- CopyFragConf::SignalLength, JBB);
- return;
- }//if
-
- LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
- ndbrequire(scans.seize(scanptr));
-/* ------------------------------------------------------------------------- */
-// We keep track of how many operation records in ACC that has been booked.
-// Copy fragment has records always booked and thus need not book any. The
-// most operations in parallel use is the m_max_batch_size_rows.
-// This variable has to be set-up here since it is used by releaseScanrec
-// to unbook operation records in ACC.
-/* ------------------------------------------------------------------------- */
- scanptr.p->m_max_batch_size_rows = 0;
- scanptr.p->rangeScan = 0;
- scanptr.p->tupScan = 0;
- seizeTcrec();
- tcConnectptr.p->clientBlockref = userRef;
-
- /**
- * Remove implicit cast/usage of CopyFragReq
- */
- //initCopyrec(signal);
- scanptr.p->copyPtr = copyPtr;
- scanptr.p->scanType = ScanRecord::COPY;
- scanptr.p->scanNodeId = nodeId;
- scanptr.p->scanTcrec = tcConnectptr.i;
- scanptr.p->scanSchemaVersion = copyFragReq->schemaVersion;
- scanptr.p->scanCompletedStatus = ZFALSE;
- scanptr.p->scanErrorCounter = 0;
- scanptr.p->scanNumber = NR_ScanNo;
- scanptr.p->scanKeyinfoFlag = 0; // Don't put into hash
- scanptr.p->fragPtrI = fragptr.i;
- scanptr.p->scanApiOpPtr = tcConnectptr.i;
- scanptr.p->scanApiBlockref = reference();
- fragptr.p->m_scanNumberMask.clear(NR_ScanNo);
- scanptr.p->scanBlockref = DBTUP_REF;
- scanptr.p->scanLockHold = ZFALSE;
- scanptr.p->m_curr_batch_size_rows = 0;
- scanptr.p->m_curr_batch_size_bytes= 0;
-
- initScanTc(0,
- 0,
- (DBLQH << 20) + (cownNodeid << 8),
- fragId,
- copyFragReq->nodeId);
- cactiveCopy[cnoActiveCopy] = fragptr.i;
- cnoActiveCopy++;
-
- tcConnectptr.p->copyCountWords = 0;
- tcConnectptr.p->tcOprec = tcConnectptr.i;
- tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
- tcConnectptr.p->savePointId = gci;
- scanptr.p->scanState = ScanRecord::WAIT_ACC_COPY;
- AccScanReq * req = (AccScanReq*)&signal->theData[0];
- req->senderData = scanptr.i;
- req->senderRef = cownref;
- req->tableId = tabptr.i;
- req->fragmentNo = fragId;
- req->requestInfo = 0;
- AccScanReq::setLockMode(req->requestInfo, 0);
- AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
- AccScanReq::setNRScanFlag(req->requestInfo, 1);
- AccScanReq::setNoDiskScanFlag(req->requestInfo, 1);
-
- req->transId1 = tcConnectptr.p->transid[0];
- req->transId2 = tcConnectptr.p->transid[1];
- req->savePointId = tcConnectptr.p->savePointId;
- req->maxPage = maxPage;
- sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
- AccScanReq::SignalLength + 1, JBB);
-
- if (! nodemask.isclear())
- {
- ndbrequire(nodemask.get(getOwnNodeId()));
- ndbrequire(nodemask.get(nodeId)); // cpy dest
- nodemask.clear(getOwnNodeId());
- nodemask.clear(nodeId);
-
- UpdateFragDistKeyOrd*
- ord = (UpdateFragDistKeyOrd*)signal->getDataPtrSend();
- ord->tableId = tabptr.i;
- ord->fragId = fragId;
- ord->fragDistributionKey = key;
- i = 0;
- while ((i = nodemask.find(i+1)) != NdbNodeBitmask::NotFound)
- {
- if (getNodeInfo(i).m_version >= checkversion)
- sendSignal(calcLqhBlockRef(i), GSN_UPDATE_FRAG_DIST_KEY_ORD,
- signal, UpdateFragDistKeyOrd::SignalLength, JBB);
- }
- }
- return;
-}//Dblqh::execCOPY_FRAGREQ()
-
-void
-Dblqh::execUPDATE_FRAG_DIST_KEY_ORD(Signal * signal)
-{
- jamEntry();
- UpdateFragDistKeyOrd* ord =(UpdateFragDistKeyOrd*)signal->getDataPtr();
-
- tabptr.i = ord->tableId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- ndbrequire(getFragmentrec(signal, ord->fragId));
- fragptr.p->fragDistributionKey = ord->fragDistributionKey;
-}
-
-void Dblqh::accScanConfCopyLab(Signal* signal)
-{
- AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
-/*--------------------------------------------------------------------------*/
-/* PRECONDITION: SCAN_STATE = WAIT_ACC_COPY */
-/*--------------------------------------------------------------------------*/
- if (accScanConf->flag == AccScanConf::ZEMPTY_FRAGMENT) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE FRAGMENT WAS EMPTY. */
-/* REPORT SUCCESSFUL COPYING. */
-/*---------------------------------------------------------------------------*/
- tupCopyCloseConfLab(signal);
- return;
- }//if
- scanptr.p->scanAccPtr = accScanConf->accPtr;
- scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_COPY;
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- signal->theData[1] = tcConnectptr.p->tableref;
- signal->theData[2] = scanptr.p->scanSchemaVersion;
- signal->theData[3] = ZSTORED_PROC_COPY;
-// theData[4] is not used in TUP with ZSTORED_PROC_COPY
- sendSignal(scanptr.p->scanBlockref, GSN_STORED_PROCREQ, signal, 5, JBB);
- return;
-}//Dblqh::accScanConfCopyLab()
-
-/*---------------------------------------------------------------------------*/
-/* ENTER STORED_PROCCONF WITH */
-/* TC_CONNECTPTR, */
-/* TSTORED_PROC_ID */
-/*---------------------------------------------------------------------------*/
-void Dblqh::storedProcConfCopyLab(Signal* signal)
-{
-/*---------------------------------------------------------------------------*/
-/* PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_COPY */
-/*---------------------------------------------------------------------------*/
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE COPY PROCESS HAVE BEEN COMPLETED, MOST LIKELY DUE TO A NODE FAILURE.*/
-/*---------------------------------------------------------------------------*/
- closeCopyLab(signal);
- return;
- }//if
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::COPY_FIRST_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
- continueFirstCopyAfterBlockedLab(signal);
- return;
-}//Dblqh::storedProcConfCopyLab()
-
-void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal)
-{
- /**
- * Start sending ROWID for all operations from now on
- */
- fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
-
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
-
- if (false && fragptr.p->tabRef > 4)
- {
- ndbout_c("STOPPING COPY X = [ %d %d %d %d ]",
- refToBlock(scanptr.p->scanBlockref),
- scanptr.p->scanAccPtr, RNIL, NextScanReq::ZSCAN_NEXT);
-
- /**
- * RESTART: > DUMP 7020 332 X
- */
- return;
- }
-
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = RNIL;
- signal->theData[2] = NextScanReq::ZSCAN_NEXT;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- return;
-}//Dblqh::continueFirstCopyAfterBlockedLab()
-
-/*---------------------------------------------------------------------------*/
-/* ENTER NEXT_SCANCONF WITH */
-/* SCANPTR, */
-/* TFRAGID, */
-/* TACC_OPPTR, */
-/* TLOCAL_KEY1, */
-/* TLOCAL_KEY2, */
-/* TKEY_LENGTH, */
-/* TKEY1, */
-/* TKEY2, */
-/* TKEY3, */
-/* TKEY4 */
-/*---------------------------------------------------------------------------*/
-/* PRECONDITION: SCAN_STATE = WAIT_NEXT_SCAN_COPY */
-/*---------------------------------------------------------------------------*/
-void Dblqh::nextScanConfCopyLab(Signal* signal)
-{
- NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- if (nextScanConf->fragId == RNIL) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THERE ARE NO MORE TUPLES TO FETCH. WE NEED TO CLOSE */
-/* THE COPY IN ACC AND DELETE THE STORED PROCEDURE IN TUP */
-/*---------------------------------------------------------------------------*/
- if (tcConnectptr.p->copyCountWords == 0) {
- closeCopyLab(signal);
- return;
- }//if
-/*---------------------------------------------------------------------------*/
-// Wait until copying is completed also at the starting node before reporting
-// completion. Signal completion through scanCompletedStatus-flag.
-/*---------------------------------------------------------------------------*/
- scanptr.p->scanCompletedStatus = ZTRUE;
- scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
- if (ERROR_INSERTED(5043))
- {
- CLEAR_ERROR_INSERT_VALUE;
- tcConnectptr.p->copyCountWords = ~0;
- signal->theData[0] = 9999;
- sendSignal(numberToRef(CMVMI, scanptr.p->scanNodeId),
- GSN_NDB_TAMPER, signal, 1, JBA);
- }
- return;
- }//if
-
- TcConnectionrec * tcConP = tcConnectptr.p;
-
- tcConP->m_use_rowid = true;
- tcConP->m_row_id = scanptr.p->m_row_id;
-
- if (signal->getLength() == 7)
- {
- jam();
- ndbrequire(nextScanConf->accOperationPtr == RNIL);
- initCopyTc(signal, ZDELETE);
- set_acc_ptr_in_scan_record(scanptr.p, 0, RNIL);
- tcConP->gci = nextScanConf->gci;
-
- tcConP->primKeyLen = 0;
- tcConP->totSendlenAi = 0;
- tcConP->connectState = TcConnectionrec::COPY_CONNECTED;
-
-/*---------------------------------------------------------------------------*/
-// 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.
-// This is where the constant 56 comes from. For long records this constant
-// will not matter that much. The current maximum is 6000 words outstanding
-// (including a number of those 56 words not really sent). We also have to
-// ensure that there are never more simultaneous usage of these operation
-// records to ensure that node recovery does not fail because of simultaneous
-// scanning.
-/*---------------------------------------------------------------------------*/
- UintR TnoOfWords = 8;
- TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
- TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
-
- /*-----------------------------------------------------------------
- * NOTE for transid1!
- * Transid1 in the tcConnection record is used load regulate the
- * copy(node recovery) process.
- * The number of outstanding words are written in the transid1
- * variable. This will be sent to the starting node in the
- * LQHKEYREQ signal and when the answer is returned in the LQHKEYCONF
- * we can reduce the number of outstanding words and check to see
- * if more LQHKEYREQ signals should be sent.
- *
- * However efficient this method is rather unsafe in such way that
- * it overwrites the transid1 original data.
- *
- * Also see TR 587.
- *----------------------------------------------------------------*/
- tcConP->transid[0] = TnoOfWords; // Data overload, see note!
- packLqhkeyreqLab(signal);
- tcConP->copyCountWords += TnoOfWords;
- scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
- if (tcConP->copyCountWords < cmaxWordsAtNodeRec) {
- nextRecordCopy(signal);
- }
- return;
- }
- else
- {
- // If accOperationPtr == RNIL no record was returned by ACC
- if (nextScanConf->accOperationPtr == RNIL) {
- jam();
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- sendSignal(scanptr.p->scanBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- return;
- }
-
- initCopyTc(signal, ZINSERT);
- set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
-
- Fragrecord* fragPtrP= fragptr.p;
- scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
- tcConP->transactionState = TcConnectionrec::COPY_TUPKEY;
- if(tcConP->m_disk_table)
- {
- next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
- }
- else
- {
- next_scanconf_tupkeyreq(signal, scanptr, tcConP, fragPtrP, RNIL);
- }
- }
-}//Dblqh::nextScanConfCopyLab()
-
-
-/*---------------------------------------------------------------------------*/
-/* USED IN COPYING OPERATION TO RECEIVE ATTRINFO FROM TUP. */
-/*---------------------------------------------------------------------------*/
-/* ************>> */
-/* TRANSID_AI > */
-/* ************>> */
-void Dblqh::execTRANSID_AI(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- Uint32 length = signal->length() - 3;
- ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::COPY_TUPKEY);
- Uint32 * src = &signal->theData[3];
- while(length > 22){
- if (saveTupattrbuf(signal, src, 22) == ZOK) {
- ;
- } else {
- jam();
- tcConnectptr.p->errorCode = ZGET_ATTRINBUF_ERROR;
- return;
- }//if
- src += 22;
- length -= 22;
- }
- if (saveTupattrbuf(signal, src, length) == ZOK) {
- return;
- }
- jam();
- tcConnectptr.p->errorCode = ZGET_ATTRINBUF_ERROR;
-}//Dblqh::execTRANSID_AI()
-
-/*--------------------------------------------------------------------------*/
-/* ENTER TUPKEYCONF WITH */
-/* TC_CONNECTPTR, */
-/* TDATA2, */
-/* TDATA3, */
-/* TDATA4, */
-/* TDATA5 */
-/*--------------------------------------------------------------------------*/
-/* PRECONDITION: TRANSACTION_STATE = COPY_TUPKEY */
-/*--------------------------------------------------------------------------*/
-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;
-
- Uint32 rows = scanP->m_curr_batch_size_rows;
- Uint32 accOpPtr= get_acc_ptr_from_scan_record(scanP, rows, false);
- ndbassert(accOpPtr != (Uint32)-1);
- c_acc->execACCKEY_ORD(signal, accOpPtr);
-
- if (tcConnectptr.p->errorCode != 0) {
- jam();
- closeCopyLab(signal);
- return;
- }//if
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE COPY PROCESS HAVE BEEN CLOSED. MOST LIKELY A NODE FAILURE. */
-/*---------------------------------------------------------------------------*/
- closeCopyLab(signal);
- return;
- }//if
- TcConnectionrec * tcConP = tcConnectptr.p;
- tcConnectptr.p->totSendlenAi = readLength;
- tcConnectptr.p->connectState = TcConnectionrec::COPY_CONNECTED;
-
- // Read primary keys (used to get here via scan keyinfo)
- Uint32* tmp = signal->getDataPtrSend()+24;
- Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
-
- tcConP->gci = tmp[len];
- // 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.
-// This is where the constant 56 comes from. For long records this constant
-// will not matter that much. The current maximum is 6000 words outstanding
-// (including a number of those 56 words not really sent). We also have to
-// ensure that there are never more simultaneous usage of these operation
-// records to ensure that node recovery does not fail because of simultaneous
-// scanning.
-/*---------------------------------------------------------------------------*/
- UintR TnoOfWords = readLength + len;
- TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
- TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
-
- /*-----------------------------------------------------------------
- * NOTE for transid1!
- * Transid1 in the tcConnection record is used load regulate the
- * copy(node recovery) process.
- * The number of outstanding words are written in the transid1
- * variable. This will be sent to the starting node in the
- * LQHKEYREQ signal and when the answer is returned in the LQHKEYCONF
- * we can reduce the number of outstanding words and check to see
- * if more LQHKEYREQ signals should be sent.
- *
- * However efficient this method is rather unsafe in such way that
- * it overwrites the transid1 original data.
- *
- * Also see TR 587.
- *----------------------------------------------------------------*/
- tcConnectptr.p->transid[0] = TnoOfWords; // Data overload, see note!
- packLqhkeyreqLab(signal);
- tcConnectptr.p->copyCountWords += TnoOfWords;
- scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
- if (tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec) {
- nextRecordCopy(signal);
- return;
- }//if
- return;
-}//Dblqh::copyTupkeyConfLab()
-
-/*---------------------------------------------------------------------------*/
-/* ENTER LQHKEYCONF */
-/*---------------------------------------------------------------------------*/
-/* PRECONDITION: CONNECT_STATE = COPY_CONNECTED */
-/*---------------------------------------------------------------------------*/
-void Dblqh::copyCompletedLab(Signal* signal)
-{
- const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
-
- ndbrequire(tcConnectptr.p->transid[1] == lqhKeyConf->transId2);
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- if (tcConnectptr.p->copyCountWords >= cmaxWordsAtNodeRec) {
- tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
-/*---------------------------------------------------------------------------*/
-// Copy to complete, we will not start any new copying.
-/*---------------------------------------------------------------------------*/
- closeCopyLab(signal);
- return;
- }//if
- if (tcConnectptr.p->copyCountWords < cmaxWordsAtNodeRec) {
- jam();
- nextRecordCopy(signal);
- }//if
- return;
- }//if
- tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
- ndbrequire(tcConnectptr.p->copyCountWords <= cmaxWordsAtNodeRec);
- if (tcConnectptr.p->copyCountWords > 0) {
- jam();
- return;
- }//if
-/*---------------------------------------------------------------------------*/
-// No more outstanding copies. We will only start new ones from here if it was
-// stopped before and this only happens when copyCountWords is bigger than the
-// threshold value. Since this did not occur we must be waiting for completion.
-// Check that this is so. If not we crash to find out what is going on.
-/*---------------------------------------------------------------------------*/
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
- closeCopyLab(signal);
- return;
- }//if
-
- if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY &&
- scanptr.p->scanErrorCounter)
- {
- jam();
- closeCopyLab(signal);
- return;
- }
-
- if (scanptr.p->scanState == ScanRecord::WAIT_LQHKEY_COPY) {
- jam();
-/*---------------------------------------------------------------------------*/
-// Make sure that something is in progress. Otherwise we will simply stop
-// and nothing more will happen.
-/*---------------------------------------------------------------------------*/
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- return;
-}//Dblqh::copyCompletedLab()
-
-void Dblqh::nextRecordCopy(Signal* signal)
-{
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- if (scanptr.p->scanState != ScanRecord::WAIT_LQHKEY_COPY) {
- jam();
-/*---------------------------------------------------------------------------*/
-// Make sure that nothing is in progress. Otherwise we will have to simultaneous
-// scans on the same record and this will certainly lead to unexpected
-// behaviour.
-/*---------------------------------------------------------------------------*/
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::COPY_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
- continueCopyAfterBlockedLab(signal);
- return;
-}//Dblqh::nextRecordCopy()
-
-void Dblqh::continueCopyAfterBlockedLab(Signal* signal)
-{
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- tcConnectptr.p->errorCode = 0;
- Uint32 acc_op_ptr= get_acc_ptr_from_scan_record(scanptr.p, 0, false);
- if (acc_op_ptr != RNIL)
- {
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = acc_op_ptr;
- signal->theData[2] = NextScanReq::ZSCAN_NEXT_COMMIT;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- }
- else
- {
- /**
- * No need to commit (unlock)
- */
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = RNIL;
- signal->theData[2] = NextScanReq::ZSCAN_NEXT;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- }
- return;
-}//Dblqh::continueCopyAfterBlockedLab()
-
-void Dblqh::copyLqhKeyRefLab(Signal* signal)
-{
- ndbrequire(tcConnectptr.p->transid[1] == signal->theData[4]);
- Uint32 copyWords = signal->theData[3];
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- scanptr.p->scanErrorCounter++;
- tcConnectptr.p->errorCode = terrorCode;
-
- LqhKeyConf* conf = (LqhKeyConf*)signal->getDataPtrSend();
- conf->transId1 = copyWords;
- conf->transId2 = tcConnectptr.p->transid[1];
- copyCompletedLab(signal);
-}//Dblqh::copyLqhKeyRefLab()
-
-void Dblqh::closeCopyLab(Signal* signal)
-{
- if (tcConnectptr.p->copyCountWords > 0) {
-/*---------------------------------------------------------------------------*/
-// We are still waiting for responses from the starting node.
-// Wait until all of those have arrived until we start the
-// close process.
-/*---------------------------------------------------------------------------*/
- scanptr.p->scanState = ScanRecord::WAIT_LQHKEY_COPY;
- jam();
- return;
- }//if
- tcConnectptr.p->transid[0] = 0;
- tcConnectptr.p->transid[1] = 0;
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
-
- /**
- * Stop sending ROWID for all operations from now on
- */
- fragptr.p->m_copy_started_state = Fragrecord::AC_NORMAL;
-
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- scanptr.p->scanState = ScanRecord::WAIT_CLOSE_COPY;
- switch (fragptr.p->fragStatus) {
- case Fragrecord::FSACTIVE:
- jam();
- break;
- case Fragrecord::BLOCKED:
- jam();
- linkFragQueue(signal);
- tcConnectptr.p->transactionState = TcConnectionrec::COPY_CLOSE_STOPPED;
- return;
- break;
- case Fragrecord::FREE:
- jam();
- case Fragrecord::ACTIVE_CREATION:
- jam();
- case Fragrecord::CRASH_RECOVERING:
- jam();
- case Fragrecord::DEFINED:
- jam();
- case Fragrecord::REMOVING:
- jam();
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
- continueCloseCopyAfterBlockedLab(signal);
- return;
-}//Dblqh::closeCopyLab()
-
-void Dblqh::continueCloseCopyAfterBlockedLab(Signal* signal)
-{
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
- signal->theData[0] = scanptr.p->scanAccPtr;
- signal->theData[1] = RNIL;
- signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
- sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- return;
-}//Dblqh::continueCloseCopyAfterBlockedLab()
-
-/*---------------------------------------------------------------------------*/
-/* ENTER NEXT_SCANCONF WITH */
-/* SCANPTR, */
-/* TFRAGID, */
-/* TACC_OPPTR, */
-/* TLOCAL_KEY1, */
-/* TLOCAL_KEY2, */
-/* TKEY_LENGTH, */
-/* TKEY1, */
-/* TKEY2, */
-/* TKEY3, */
-/* TKEY4 */
-/*---------------------------------------------------------------------------*/
-/* PRECONDITION: SCAN_STATE = WAIT_CLOSE_COPY */
-/*---------------------------------------------------------------------------*/
-void Dblqh::accCopyCloseConfLab(Signal* signal)
-{
- tcConnectptr.i = scanptr.p->scanTcrec;
- scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- signal->theData[1] = tcConnectptr.p->tableref;
- signal->theData[2] = scanptr.p->scanSchemaVersion;
- signal->theData[3] = ZDELETE_STORED_PROC_ID;
- signal->theData[4] = scanptr.p->scanStoredProcId;
- sendSignal(tcConnectptr.p->tcTupBlockref, GSN_STORED_PROCREQ, signal, 5, JBB);
- return;
-}//Dblqh::accCopyCloseConfLab()
-
-/*---------------------------------------------------------------------------*/
-/* ENTER STORED_PROCCONF WITH */
-/* TC_CONNECTPTR, */
-/* TSTORED_PROC_ID */
-/*---------------------------------------------------------------------------*/
-/* PRECONDITION: SCAN_STATE = WAIT_DELETE_STORED_PROC_ID_COPY */
-/*---------------------------------------------------------------------------*/
-void Dblqh::tupCopyCloseConfLab(Signal* signal)
-{
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- fragptr.p->copyFragState = ZIDLE;
-
- if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
- jam();
- tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
- ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
- tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
- signal->theData[0] = ZLQH_TRANS_NEXT;
- signal->theData[1] = tcNodeFailptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
-
- CopyFragRef * const ref = (CopyFragRef *)&signal->theData[0];
- ref->userPtr = scanptr.p->copyPtr;
- ref->sendingNodeId = cownNodeid;
- ref->startingNodeId = scanptr.p->scanNodeId;
- ref->tableId = fragptr.p->tabRef;
- ref->fragId = fragptr.p->fragId;
- ref->errorCode = ZNODE_FAILURE_ERROR;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
- CopyFragRef::SignalLength, JBB);
- } else {
- if (scanptr.p->scanErrorCounter > 0) {
- jam();
- CopyFragRef * const ref = (CopyFragRef *)&signal->theData[0];
- ref->userPtr = scanptr.p->copyPtr;
- ref->sendingNodeId = cownNodeid;
- ref->startingNodeId = scanptr.p->scanNodeId;
- ref->tableId = fragptr.p->tabRef;
- ref->fragId = fragptr.p->fragId;
- ref->errorCode = tcConnectptr.p->errorCode;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
- CopyFragRef::SignalLength, JBB);
- } else {
- jam();
- CopyFragConf * const conf = (CopyFragConf *)&signal->theData[0];
- conf->userPtr = scanptr.p->copyPtr;
- conf->sendingNodeId = cownNodeid;
- conf->startingNodeId = scanptr.p->scanNodeId;
- conf->tableId = tcConnectptr.p->tableref;
- conf->fragId = tcConnectptr.p->fragmentid;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGCONF, signal,
- CopyFragConf::SignalLength, JBB);
- }//if
- }//if
- releaseActiveCopy(signal);
- tcConnectptr.p->tcScanRec = RNIL;
- finishScanrec(signal);
- releaseOprec(signal);
- releaseTcrec(signal, tcConnectptr);
- releaseScanrec(signal);
-}//Dblqh::tupCopyCloseConfLab()
-
-/*---------------------------------------------------------------------------*/
-/* A NODE FAILURE OCCURRED DURING THE COPY PROCESS. WE NEED TO CLOSE THE */
-/* COPY PROCESS SINCE A NODE FAILURE DURING THE COPY PROCESS WILL ALSO */
-/* FAIL THE NODE THAT IS TRYING TO START-UP. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::closeCopyRequestLab(Signal* signal)
-{
- scanptr.p->scanErrorCounter++;
- if (0) ndbout_c("closeCopyRequestLab: scanState: %d", scanptr.p->scanState);
- switch (scanptr.p->scanState) {
- case ScanRecord::WAIT_TUPKEY_COPY:
- case ScanRecord::WAIT_NEXT_SCAN_COPY:
- jam();
-/*---------------------------------------------------------------------------*/
-/* SET COMPLETION STATUS AND WAIT FOR OPPORTUNITY TO STOP THE SCAN. */
-// ALSO SET NO OF WORDS OUTSTANDING TO ZERO TO AVOID ETERNAL WAIT.
-/*---------------------------------------------------------------------------*/
- scanptr.p->scanCompletedStatus = ZTRUE;
- tcConnectptr.p->copyCountWords = 0;
- break;
- case ScanRecord::WAIT_ACC_COPY:
- case ScanRecord::WAIT_STORED_PROC_COPY:
- jam();
-/*---------------------------------------------------------------------------*/
-/* WE ARE CURRENTLY STARTING UP THE SCAN. SET COMPLETED STATUS AND WAIT FOR*/
-/* COMPLETION OF STARTUP. */
-/*---------------------------------------------------------------------------*/
- scanptr.p->scanCompletedStatus = ZTRUE;
- break;
- case ScanRecord::WAIT_CLOSE_COPY:
- case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
- jam();
-/*---------------------------------------------------------------------------*/
-/* CLOSE IS ALREADY ONGOING. WE NEED NOT DO ANYTHING. */
-/*---------------------------------------------------------------------------*/
- break;
- case ScanRecord::WAIT_LQHKEY_COPY:
- jam();
-/*---------------------------------------------------------------------------*/
-/* WE ARE WAITING FOR THE FAILED NODE. THE NODE WILL NEVER COME BACK. */
-// WE NEED TO START THE FAILURE HANDLING IMMEDIATELY.
-// ALSO SET NO OF WORDS OUTSTANDING TO ZERO TO AVOID ETERNAL WAIT.
-/*---------------------------------------------------------------------------*/
- tcConnectptr.p->copyCountWords = 0;
- closeCopyLab(signal);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dblqh::closeCopyRequestLab()
-
-/* ****************************************************** */
-/* COPY_ACTIVEREQ: Change state of a fragment to ACTIVE. */
-/* ****************************************************** */
-void Dblqh::execCOPY_ACTIVEREQ(Signal* signal)
-{
- CRASH_INSERTION(5026);
-
- const CopyActiveReq * const req = (CopyActiveReq *)&signal->theData[0];
- jamEntry();
- Uint32 masterPtr = req->userPtr;
- BlockReference masterRef = req->userRef;
- tabptr.i = req->tableId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- Uint32 fragId = req->fragId;
- ndbrequire(getFragmentrec(signal, fragId));
-
- fragptr.p->fragDistributionKey = req->distributionKey;
-
- ndbrequire(cnoActiveCopy < 3);
- cactiveCopy[cnoActiveCopy] = fragptr.i;
- cnoActiveCopy++;
- fragptr.p->masterBlockref = masterRef;
- fragptr.p->masterPtr = masterPtr;
- if (fragptr.p->fragStatus == Fragrecord::FSACTIVE) {
- jam();
-/*------------------------------------------------------*/
-/* PROCESS HAVE ALREADY BEEN STARTED BY PREVIOUS */
-/* MASTER. WE HAVE ALREADY SET THE PROPER MASTER */
-/* BLOCK REFERENCE. */
-/*------------------------------------------------------*/
- if (fragptr.p->activeTcCounter == 0) {
- jam();
-/*------------------------------------------------------*/
-/* PROCESS WAS EVEN COMPLETED. */
-/*------------------------------------------------------*/
- sendCopyActiveConf(signal, tabptr.i);
- }//if
- return;
- }//if
-
- fragptr.p->fragStatus = Fragrecord::FSACTIVE;
- if (TRACENR_FLAG)
- TRACENR("tab: " << tabptr.i
- << " frag: " << fragId
- << " COPY ACTIVE" << endl);
-
- if (fragptr.p->lcpFlag == Fragrecord::LCP_STATE_TRUE) {
- jam();
- fragptr.p->logFlag = Fragrecord::STATE_TRUE;
- }//if
- fragptr.p->activeTcCounter = 1;
-/*------------------------------------------------------*/
-/* SET IT TO ONE TO ENSURE THAT IT IS NOT POSSIBLE*/
-/* TO DECREASE IT TO ZERO UNTIL WE HAVE COMPLETED */
-/* THE SCAN. */
-/*------------------------------------------------------*/
- signal->theData[0] = ZSCAN_TC_CONNECT;
- signal->theData[1] = 0;
- signal->theData[2] = tabptr.i;
- signal->theData[3] = fragId;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- return;
-}//Dblqh::execCOPY_ACTIVEREQ()
-
-void Dblqh::scanTcConnectLab(Signal* signal, Uint32 tstartTcConnect, Uint32 fragId)
-{
- Uint32 tendTcConnect;
-
- ndbrequire(getFragmentrec(signal, fragId));
- if ((tstartTcConnect + 200) >= ctcConnectrecFileSize) {
- jam();
- tendTcConnect = ctcConnectrecFileSize - 1;
- } else {
- jam();
- tendTcConnect = tstartTcConnect + 200;
- }//if
- for (tcConnectptr.i = tstartTcConnect;
- tcConnectptr.i <= tendTcConnect;
- tcConnectptr.i++) {
- jam();
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
- switch (tcConnectptr.p->logWriteState) {
- case TcConnectionrec::NOT_WRITTEN:
- jam();
- if (fragptr.i == tcConnectptr.p->fragmentptr) {
- jam();
- fragptr.p->activeTcCounter = fragptr.p->activeTcCounter + 1;
- tcConnectptr.p->logWriteState = TcConnectionrec::NOT_WRITTEN_WAIT;
- }//if
- break;
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- }//if
- }//for
- if (tendTcConnect < (ctcConnectrecFileSize - 1)) {
- jam();
- signal->theData[0] = ZSCAN_TC_CONNECT;
- signal->theData[1] = tendTcConnect + 1;
- signal->theData[2] = tabptr.i;
- signal->theData[3] = fragId;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- } else {
- jam();
-/*------------------------------------------------------*/
-/* THE SCAN HAVE BEEN COMPLETED. WE CHECK IF ALL */
-/* OPERATIONS HAVE ALREADY BEEN COMPLETED. */
-/*------------------------------------------------------*/
- ndbrequire(fragptr.p->activeTcCounter > 0);
- fragptr.p->activeTcCounter--;
- if (fragptr.p->activeTcCounter == 0) {
- jam();
-/*------------------------------------------------------*/
-/* SET START GLOBAL CHECKPOINT TO THE NEXT */
-/* CHECKPOINT WE HAVE NOT YET HEARD ANYTHING ABOUT*/
-/* THIS GCP WILL BE COMPLETELY COVERED BY THE LOG.*/
-/*------------------------------------------------------*/
- fragptr.p->startGci = cnewestGci + 1;
- sendCopyActiveConf(signal, tabptr.i);
- }//if
- }//if
- return;
-}//Dblqh::scanTcConnectLab()
-
-/*---------------------------------------------------------------------------*/
-/* A NEW MASTER IS REQUESTING THE STATE IN LQH OF THE COPY FRAGMENT PARTS. */
-/*---------------------------------------------------------------------------*/
-/* ***************>> */
-/* COPY_STATEREQ > */
-/* ***************>> */
-void Dblqh::execCOPY_STATEREQ(Signal* signal)
-{
- jamEntry();
- ndbrequire(0)
-#if 0
- Uint32* dataPtr = &signal->theData[2];
- BlockReference tmasterBlockref = signal->theData[0];
- Uint32 tnoCopy = 0;
- do {
- jam();
- arrGuard(tnoCopy, 4);
- fragptr.i = cactiveCopy[tnoCopy];
- if (fragptr.i == RNIL) {
- jam();
- break;
- }//if
- c_fragment_pool.getPtr(fragptr);
- if (fragptr.p->copyFragState != ZIDLE) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS FRAGMENT IS CURRENTLY ACTIVE IN COPYING THE FRAGMENT. */
-/*---------------------------------------------------------------------------*/
- scanptr.i = fragptr.p->fragScanRec[NR_ScanNo];
- c_scanRecordPool.getPtr(scanptr);
- if (scanptr.p->scanCompletedStatus == ZTRUE) {
- jam();
- dataPtr[3 + (tnoCopy << 2)] = ZCOPY_CLOSING;
- } else {
- jam();
- dataPtr[3 + (tnoCopy << 2)] = ZCOPY_ONGOING;
- }//if
- dataPtr[2 + (tnoCopy << 2)] = scanptr.p->scanSchemaVersion;
- scanptr.p->scanApiBlockref = tmasterBlockref;
- } else {
- ndbrequire(fragptr.p->activeTcCounter != 0);
-/*---------------------------------------------------------------------------*/
-/* COPY FRAGMENT IS COMPLETED AND WE ARE CURRENTLY GETTING THE STARTING */
-/* GCI OF THE NEW REPLICA OF THIS FRAGMENT. */
-/*---------------------------------------------------------------------------*/
- fragptr.p->masterBlockref = tmasterBlockref;
- dataPtr[3 + (tnoCopy << 2)] = ZCOPY_ACTIVATION;
- }//if
- dataPtr[tnoCopy << 2] = fragptr.p->tabRef;
- dataPtr[1 + (tnoCopy << 2)] = fragptr.p->fragId;
- tnoCopy++;
- } while (tnoCopy < cnoActiveCopy);
- signal->theData[0] = cownNodeid;
- signal->theData[1] = tnoCopy;
- sendSignal(tmasterBlockref, GSN_COPY_STATECONF, signal, 18, JBB);
-#endif
- return;
-}//Dblqh::execCOPY_STATEREQ()
-
-/* ========================================================================= */
-/* ======= INITIATE TC RECORD AT COPY FRAGMENT ======= */
-/* */
-/* SUBROUTINE SHORT NAME = ICT */
-/* ========================================================================= */
-void Dblqh::initCopyTc(Signal* signal, Operation_t op)
-{
- tcConnectptr.p->operation = ZREAD;
- tcConnectptr.p->apiVersionNo = 0;
- tcConnectptr.p->opExec = 0; /* NOT INTERPRETED MODE */
- tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
- Uint32 reqinfo = 0;
- LqhKeyReq::setDirtyFlag(reqinfo, 1);
- LqhKeyReq::setSimpleFlag(reqinfo, 1);
- LqhKeyReq::setOperation(reqinfo, op);
- LqhKeyReq::setGCIFlag(reqinfo, 1);
- LqhKeyReq::setNrCopyFlag(reqinfo, 1);
- /* AILen in LQHKEYREQ IS ZERO */
- tcConnectptr.p->reqinfo = reqinfo;
-/* ------------------------------------------------------------------------ */
-/* THE RECEIVING NODE WILL EXPECT THAT IT IS THE LAST NODE AND WILL */
-/* SEND COMPLETED AS THE RESPONSE SIGNAL SINCE DIRTY_OP BIT IS SET. */
-/* ------------------------------------------------------------------------ */
- tcConnectptr.p->nodeAfterNext[0] = ZNIL;
- tcConnectptr.p->nodeAfterNext[1] = ZNIL;
- tcConnectptr.p->tcBlockref = cownref;
- tcConnectptr.p->readlenAi = 0;
- tcConnectptr.p->storedProcId = ZNIL;
- tcConnectptr.p->opExec = 0;
- tcConnectptr.p->nextSeqNoReplica = 0;
- tcConnectptr.p->dirtyOp = ZFALSE;
- tcConnectptr.p->lastReplicaNo = 0;
- tcConnectptr.p->currTupAiLen = 0;
- tcConnectptr.p->tcTimer = cLqhTimeOutCount;
-}//Dblqh::initCopyTc()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEND COPY_ACTIVECONF TO MASTER DIH ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::sendCopyActiveConf(Signal* signal, Uint32 tableId)
-{
- releaseActiveCopy(signal);
- CopyActiveConf * const conf = (CopyActiveConf *)&signal->theData[0];
- conf->userPtr = fragptr.p->masterPtr;
- conf->tableId = tableId;
- conf->fragId = fragptr.p->fragId;
- conf->startingNodeId = cownNodeid;
- conf->startGci = fragptr.p->startGci;
- sendSignal(fragptr.p->masterBlockref, GSN_COPY_ACTIVECONF, signal,
- CopyActiveConf::SignalLength, JBB);
-}//Dblqh::sendCopyActiveConf()
-
-/* ##########################################################################
- * ####### LOCAL CHECKPOINT MODULE #######
- *
- * ##########################################################################
- * --------------------------------------------------------------------------
- * THIS MODULE HANDLES THE EXECUTION AND CONTROL OF LOCAL CHECKPOINTS
- * IT CONTROLS THE LOCAL CHECKPOINTS IN TUP AND ACC. IT DOES ALSO INTERACT
- * WITH DIH TO CONTROL WHICH GLOBAL CHECKPOINTS THAT ARE RECOVERABLE
- * ------------------------------------------------------------------------- */
-void Dblqh::execEMPTY_LCP_REQ(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(5008);
- EmptyLcpReq * const emptyLcpOrd = (EmptyLcpReq*)&signal->theData[0];
-
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
-
- Uint32 nodeId = refToNode(emptyLcpOrd->senderRef);
-
- lcpPtr.p->m_EMPTY_LCP_REQ.set(nodeId);
- lcpPtr.p->reportEmpty = true;
-
- if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE){
- jam();
- bool ok = false;
- switch(clcpCompletedState){
- case LCP_IDLE:
- ok = true;
- sendEMPTY_LCP_CONF(signal, true);
- break;
- case LCP_RUNNING:
- ok = true;
- sendEMPTY_LCP_CONF(signal, false);
- break;
- case LCP_CLOSE_STARTED:
- jam();
- case ACC_LCP_CLOSE_COMPLETED:
- jam();
- case TUP_LCP_CLOSE_COMPLETED:
- jam();
- ok = true;
- break;
- }
- ndbrequire(ok);
-
- }//if
-
- return;
-}//Dblqh::execEMPTY_LCPREQ()
-
-#ifdef NDB_DEBUG_FULL
-static struct TraceLCP {
- void sendSignal(Uint32 ref, Uint32 gsn, Signal* signal,
- Uint32 len, Uint32 prio);
- void save(Signal*);
- void restore(SimulatedBlock&, Signal* sig);
- struct Sig {
- enum {
- Sig_save = 0,
- Sig_send = 1
- } type;
- SignalHeader header;
- Uint32 theData[25];
- };
- Vector<Sig> m_signals;
-} g_trace_lcp;
-template class Vector<TraceLCP::Sig>;
-#else
-#endif
-
-void Dblqh::execLCP_FRAG_ORD(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(5010);
- LcpFragOrd * const lcpFragOrd = (LcpFragOrd *)&signal->theData[0];
-
- Uint32 lcpId = lcpFragOrd->lcpId;
-
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
-
- lcpPtr.p->lastFragmentFlag = lcpFragOrd->lastFragmentFlag;
- if (lcpFragOrd->lastFragmentFlag) {
- jam();
- if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE) {
- jam();
- /* ----------------------------------------------------------
- * NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
- * -------------------------------------------------------- */
- if (cnoOfFragsCheckpointed > 0) {
- jam();
- completeLcpRoundLab(signal, lcpId);
- } else {
- jam();
- sendLCP_COMPLETE_REP(signal, lcpId);
- }//if
- }
- return;
- }//if
- tabptr.i = lcpFragOrd->tableId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
-
- ndbrequire(tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_ONGOING ||
- tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE ||
- tabptr.p->tableStatus == Tablerec::TABLE_DEFINED);
-
- ndbrequire(getFragmentrec(signal, lcpFragOrd->fragmentId));
-
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- ndbrequire(!lcpPtr.p->lcpQueued);
-
- if (c_lcpId < lcpFragOrd->lcpId) {
- jam();
-
- lcpPtr.p->firstFragmentFlag= true;
-
- c_lcpId = lcpFragOrd->lcpId;
- ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_IDLE);
- setLogTail(signal, lcpFragOrd->keepGci);
- ndbrequire(clcpCompletedState == LCP_IDLE);
- clcpCompletedState = LCP_RUNNING;
- }
- cnoOfFragsCheckpointed++;
-
- if(tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE){
- jam();
- LcpRecord::FragOrd fragOrd;
- fragOrd.fragPtrI = fragptr.i;
- fragOrd.lcpFragOrd = * lcpFragOrd;
- sendLCP_FRAG_REP(signal, fragOrd);
- return;
- }
-
- if (lcpPtr.p->lcpState != LcpRecord::LCP_IDLE) {
- ndbrequire(lcpPtr.p->lcpQueued == false);
- lcpPtr.p->lcpQueued = true;
- lcpPtr.p->queuedFragment.fragPtrI = fragptr.i;
- lcpPtr.p->queuedFragment.lcpFragOrd = * lcpFragOrd;
- return;
- }//if
-
- lcpPtr.p->currentFragment.fragPtrI = fragptr.i;
- lcpPtr.p->currentFragment.lcpFragOrd = * lcpFragOrd;
-
- sendLCP_FRAGIDREQ(signal);
-}//Dblqh::execLCP_FRAGORD()
-
-void Dblqh::execLCP_PREPARE_REF(Signal* signal)
-{
- jamEntry();
-
- LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtr();
-
- lcpPtr.i = ref->senderData;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
-
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- c_fragment_pool.getPtr(fragptr);
-
- ndbrequire(ref->tableId == fragptr.p->tabRef);
- ndbrequire(ref->fragmentId == fragptr.p->fragId);
-
- tabptr.i = ref->tableId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
-
- ndbrequire(lcpPtr.p->m_outstanding);
- lcpPtr.p->m_outstanding--;
-
- /**
- * Only BACKUP is allowed to ref LCP_PREPARE
- */
- ndbrequire(refToBlock(signal->getSendersBlockRef()) == BACKUP);
- lcpPtr.p->m_error = ref->errorCode;
-
- if (lcpPtr.p->m_outstanding == 0)
- {
- jam();
-
- if(lcpPtr.p->firstFragmentFlag)
- {
- jam();
- LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
- lcpPtr.p->firstFragmentFlag= false;
- *ord = lcpPtr.p->currentFragment.lcpFragOrd;
- EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
- jamEntry();
-
- /**
- * First fragment mean that last LCP is complete :-)
- */
- EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
- jamEntry();
- }
-
- lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
- contChkpNextFragLab(signal);
- }
-}
-
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_PTR:LCP_STATE = WAIT_FRAGID
- * --------------------------------------------------------------------------
- * WE NOW HAVE THE LOCAL FRAGMENTS THAT THE LOCAL CHECKPOINT WILL USE.
- * -------------------------------------------------------------------------- */
-void Dblqh::execLCP_PREPARE_CONF(Signal* signal)
-{
- jamEntry();
-
- LcpPrepareConf* conf= (LcpPrepareConf*)signal->getDataPtr();
-
- lcpPtr.i = conf->senderData;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
-
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- c_fragment_pool.getPtr(fragptr);
-
- if (refToBlock(signal->getSendersBlockRef()) != PGMAN)
- {
- ndbrequire(conf->tableId == fragptr.p->tabRef);
- ndbrequire(conf->fragmentId == fragptr.p->fragId);
- }
-
- ndbrequire(lcpPtr.p->m_outstanding);
- lcpPtr.p->m_outstanding--;
- if (lcpPtr.p->m_outstanding == 0)
- {
- jam();
-
- if(lcpPtr.p->firstFragmentFlag)
- {
- jam();
- LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
- lcpPtr.p->firstFragmentFlag= false;
- *ord = lcpPtr.p->currentFragment.lcpFragOrd;
- EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
- jamEntry();
-
- /**
- * First fragment mean that last LCP is complete :-)
- */
- EXECUTE_DIRECT(TSMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
- jamEntry();
- }
-
- if (lcpPtr.p->m_error)
- {
- jam();
-
- lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
- contChkpNextFragLab(signal);
- return;
- }
-
- lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_HOLDOPS;
- lcpPtr.p->lcpState = LcpRecord::LCP_START_CHKP;
-
- /* ----------------------------------------------------------------------
- * UPDATE THE MAX_GCI_IN_LCP AND MAX_GCI_COMPLETED_IN_LCP NOW BEFORE
- * ACTIVATING THE FRAGMENT AGAIN.
- * --------------------------------------------------------------------- */
- ndbrequire(lcpPtr.p->currentFragment.lcpFragOrd.lcpNo < MAX_LCP_STORED);
- fragptr.p->maxGciInLcp = fragptr.p->newestGci;
- fragptr.p->maxGciCompletedInLcp = cnewestCompletedGci;
-
- {
- LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
- *ord = lcpPtr.p->currentFragment.lcpFragOrd;
- EXECUTE_DIRECT(LGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
- jamEntry();
-
- *ord = lcpPtr.p->currentFragment.lcpFragOrd;
- EXECUTE_DIRECT(DBTUP, GSN_LCP_FRAG_ORD, signal, signal->length());
- jamEntry();
- }
-
- BackupFragmentReq* req= (BackupFragmentReq*)signal->getDataPtr();
- req->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- req->fragmentNo = 0;
- req->backupPtr = m_backup_ptr;
- req->backupId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
- req->count = 0;
-
-#ifdef NDB_DEBUG_FULL
- if(ERROR_INSERTED(5904))
- {
- g_trace_lcp.sendSignal(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal,
- BackupFragmentReq::SignalLength, JBB);
- }
- else
-#endif
- {
- if (ERROR_INSERTED(5044) &&
- (fragptr.p->tabRef == c_error_insert_table_id) &&
- fragptr.p->fragId) // Not first frag
- {
- /**
- * Force CRASH_INSERTION in 10s
- */
- ndbout_c("table: %d frag: %d", fragptr.p->tabRef, fragptr.p->fragId);
- SET_ERROR_INSERT_VALUE(5027);
- sendSignalWithDelay(reference(), GSN_START_RECREQ, signal, 10000, 1);
- }
- else
- {
- sendSignal(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal,
- BackupFragmentReq::SignalLength, JBB);
- }
- }
- }
-}
-
-void Dblqh::execBACKUP_FRAGMENT_REF(Signal* signal)
-{
- BackupFragmentRef *ref= (BackupFragmentRef*)signal->getDataPtr();
- char buf[100];
- BaseString::snprintf(buf,sizeof(buf),
- "Unable to store fragment during LCP. NDBFS Error: %u",
- ref->errorCode);
-
- progError(__LINE__,
- (ref->errorCode & FsRef::FS_ERR_BIT)?
- NDBD_EXIT_AFS_UNKNOWN
- : ref->errorCode,
- buf);
-}
-
-void Dblqh::execBACKUP_FRAGMENT_CONF(Signal* signal)
-{
- jamEntry();
- //BackupFragmentConf* conf= (BackupFragmentConf*)signal->getDataPtr();
-
- lcpPtr.i = 0;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_START_CHKP);
- lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
-
- /* ------------------------------------------------------------------------
- * THE LOCAL CHECKPOINT HAS BEEN COMPLETED. IT IS NOW TIME TO START
- * A LOCAL CHECKPOINT ON THE NEXT FRAGMENT OR COMPLETE THIS LCP ROUND.
- * ------------------------------------------------------------------------
- * WE START BY SENDING LCP_REPORT TO DIH TO REPORT THE COMPLETED LCP.
- * TO CATER FOR NODE CRASHES WE SEND IT IN PARALLEL TO ALL NODES.
- * ----------------------------------------------------------------------- */
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- c_fragment_pool.getPtr(fragptr);
-
- contChkpNextFragLab(signal);
- return;
-}//Dblqh::lcpCompletedLab()
-
-void
-Dblqh::sendLCP_FRAG_REP(Signal * signal,
- const LcpRecord::FragOrd & fragOrd) const {
-
- const Fragrecord* fragPtrP = c_fragment_pool.getConstPtr(fragOrd.fragPtrI);
-
- ndbrequire(fragOrd.lcpFragOrd.lcpNo < MAX_LCP_STORED);
- LcpFragRep * const lcpReport = (LcpFragRep *)&signal->theData[0];
- lcpReport->nodeId = cownNodeid;
- lcpReport->lcpId = fragOrd.lcpFragOrd.lcpId;
- lcpReport->lcpNo = fragOrd.lcpFragOrd.lcpNo;
- lcpReport->tableId = fragOrd.lcpFragOrd.tableId;
- lcpReport->fragId = fragOrd.lcpFragOrd.fragmentId;
- lcpReport->maxGciCompleted = fragPtrP->maxGciCompletedInLcp;
- lcpReport->maxGciStarted = fragPtrP->maxGciInLcp;
-
- for (Uint32 i = 0; i < cnoOfNodes; i++) {
- jam();
- Uint32 nodeId = cnodeData[i];
- if(cnodeStatus[i] == ZNODE_UP){
- jam();
- BlockReference Tblockref = calcDihBlockRef(nodeId);
- sendSignal(Tblockref, GSN_LCP_FRAG_REP, signal,
- LcpFragRep::SignalLength, JBB);
- }//if
- }//for
-}
-
-void Dblqh::contChkpNextFragLab(Signal* signal)
-{
- /* ------------------------------------------------------------------------
- * UPDATE THE LATEST LOCAL CHECKPOINT COMPLETED ON FRAGMENT.
- * UPDATE THE LCP_ID OF THIS CHECKPOINT.
- * REMOVE THE LINK BETWEEN THE FRAGMENT RECORD AND THE LCP RECORD.
- * ----------------------------------------------------------------------- */
- if (fragptr.p->fragStatus == Fragrecord::BLOCKED) {
- jam();
- /**
- * LCP of fragment complete
- * but restarting of operations isn't
- */
- lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP;
- return;
- }//if
-
- /**
- * Send rep when fragment is done + unblocked
- */
- sendLCP_FRAG_REP(signal, lcpPtr.p->currentFragment);
-
- /* ------------------------------------------------------------------------
- * WE ALSO RELEASE THE LOCAL LCP RECORDS.
- * ----------------------------------------------------------------------- */
- if (lcpPtr.p->lcpQueued) {
- jam();
- /* ----------------------------------------------------------------------
- * Transfer the state from the queued to the active LCP.
- * --------------------------------------------------------------------- */
- lcpPtr.p->lcpQueued = false;
- lcpPtr.p->currentFragment = lcpPtr.p->queuedFragment;
-
- /* ----------------------------------------------------------------------
- * START THE QUEUED LOCAL CHECKPOINT.
- * --------------------------------------------------------------------- */
- sendLCP_FRAGIDREQ(signal);
- return;
- }//if
-
- lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
- if (lcpPtr.p->lastFragmentFlag){
- jam();
- /* ----------------------------------------------------------------------
- * NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
- * --------------------------------------------------------------------- */
- completeLcpRoundLab(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
- return;
- }//if
-
- if (lcpPtr.p->reportEmpty) {
- jam();
- sendEMPTY_LCP_CONF(signal, false);
- }//if
- return;
-}//Dblqh::contChkpNextFragLab()
-
-void Dblqh::sendLCP_FRAGIDREQ(Signal* signal)
-{
- TablerecPtr tabPtr;
- tabPtr.i = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- ptrAss(tabPtr, tablerec);
- if(tabPtr.p->tableStatus == Tablerec::PREP_DROP_TABLE_ONGOING ||
- tabPtr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE){
- jam();
- /**
- * Fake that the fragment is done
- */
- contChkpNextFragLab(signal);
- return;
- }
-
- lcpPtr.p->m_error = 0;
- lcpPtr.p->m_outstanding = 1;
-
- ndbrequire(tabPtr.p->tableStatus == Tablerec::TABLE_DEFINED);
-
- lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_FRAGID;
- LcpPrepareReq* req= (LcpPrepareReq*)signal->getDataPtr();
- req->senderData = lcpPtr.i;
- req->senderRef = reference();
- req->lcpNo = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
- req->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- req->fragmentId = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
- req->lcpId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId % MAX_LCP_STORED;
- req->backupPtr = m_backup_ptr;
- req->backupId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
- sendSignal(BACKUP_REF, GSN_LCP_PREPARE_REQ, signal,
- LcpPrepareReq::SignalLength, JBB);
-
-}//Dblqh::sendLCP_FRAGIDREQ()
-
-void Dblqh::sendEMPTY_LCP_CONF(Signal* signal, bool idle)
-{
-
- EmptyLcpConf * const rep = (EmptyLcpConf*)&signal->theData[0];
- /* ----------------------------------------------------------------------
- * We have been requested to report when there are no more local
- * waiting to be started or ongoing. In this signal we also report
- * the last completed fragments state.
- * ---------------------------------------------------------------------- */
- rep->senderNodeId = getOwnNodeId();
- if(!idle){
- jam();
- rep->idle = 0 ;
- rep->tableId = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- rep->fragmentId = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
- rep->lcpNo = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
- rep->lcpId = lcpPtr.p->currentFragment.lcpFragOrd.lcpId;
- } else {
- jam();
- rep->idle = 1;
- rep->tableId = ~0;
- rep->fragmentId = ~0;
- rep->lcpNo = ~0;
- rep->lcpId = c_lcpId;
- }
-
- for (Uint32 i = 0; i < cnoOfNodes; i++) {
- jam();
- Uint32 nodeId = cnodeData[i];
- if (lcpPtr.p->m_EMPTY_LCP_REQ.get(nodeId)) {
- jam();
-
- BlockReference blockref = calcDihBlockRef(nodeId);
- sendSignal(blockref, GSN_EMPTY_LCP_CONF, signal,
- EmptyLcpConf::SignalLength, JBB);
- }//if
- }//for
-
- lcpPtr.p->reportEmpty = false;
- lcpPtr.p->m_EMPTY_LCP_REQ.clear();
-}//Dblqh::sendEMPTY_LCPCONF()
-
-/* --------------------------------------------------------------------------
- * THE LOCAL CHECKPOINT ROUND IS NOW COMPLETED. SEND COMPLETED MESSAGE
- * TO THE MASTER DIH.
- * ------------------------------------------------------------------------- */
-void Dblqh::completeLcpRoundLab(Signal* signal, Uint32 lcpId)
-{
- clcpCompletedState = LCP_CLOSE_STARTED;
-
- EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
- req->senderData= lcpPtr.i;
- req->senderRef= reference();
- req->backupPtr= m_backup_ptr;
- req->backupId= lcpId;
- sendSignal(BACKUP_REF, GSN_END_LCP_REQ, signal,
- EndLcpReq::SignalLength, JBB);
-
- sendSignal(PGMAN_REF, GSN_END_LCP_REQ, signal,
- EndLcpReq::SignalLength, JBB);
-
- sendSignal(LGMAN_REF, GSN_END_LCP_REQ, signal,
- EndLcpReq::SignalLength, JBB);
-
- EXECUTE_DIRECT(TSMAN, GSN_END_LCP_REQ, signal, EndLcpReq::SignalLength);
- jamEntry();
-
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- lcpPtr.p->m_outstanding = 3;
- return;
-}//Dblqh::completeLcpRoundLab()
-
-void Dblqh::execEND_LCPCONF(Signal* signal)
-{
- jamEntry();
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
-
- ndbrequire(clcpCompletedState == LCP_CLOSE_STARTED);
- ndbrequire(lcpPtr.p->m_outstanding);
-
- lcpPtr.p->m_outstanding--;
- if(lcpPtr.p->m_outstanding == 0)
- {
- jam();
- clcpCompletedState = LCP_IDLE;
- sendLCP_COMPLETE_REP(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
- }
-}//Dblqh::execEND_LCPCONF()
-
-void Dblqh::sendLCP_COMPLETE_REP(Signal* signal, Uint32 lcpId)
-{
- cnoOfFragsCheckpointed = 0;
- ndbrequire((cnoOfNodes - 1) < (MAX_NDB_NODES - 1));
- /* ------------------------------------------------------------------------
- * WE SEND COMP_LCP_ROUND TO ALL NODES TO PREPARE FOR NODE CRASHES.
- * ----------------------------------------------------------------------- */
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- lcpPtr.p->lastFragmentFlag = false;
- lcpPtr.p->firstFragmentFlag = false;
-
- LcpCompleteRep* rep = (LcpCompleteRep*)signal->getDataPtrSend();
- rep->nodeId = getOwnNodeId();
- rep->lcpId = lcpId;
- rep->blockNo = DBLQH;
-
- for (Uint32 i = 0; i < cnoOfNodes; i++) {
- jam();
- Uint32 nodeId = cnodeData[i];
- if(cnodeStatus[i] == ZNODE_UP){
- jam();
-
- BlockReference blockref = calcDihBlockRef(nodeId);
- sendSignal(blockref, GSN_LCP_COMPLETE_REP, signal,
- LcpCompleteRep::SignalLength, JBB);
- }//if
- }//for
-
- if(lcpPtr.p->reportEmpty){
- jam();
- sendEMPTY_LCP_CONF(signal, true);
- }
-
- if (getNodeState().getNodeRestartInProgress() && cstartRecReq != 3)
- {
- jam();
- ndbrequire(cstartRecReq == 2);
- cstartRecReq = 3;
- }
- return;
-
-}//Dblqh::sendCOMP_LCP_ROUND()
-
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEND ACC_LCPREQ AND TUP_LCPREQ ------- */
-/* */
-/* INPUT: LCP_PTR LOCAL CHECKPOINT RECORD */
-/* FRAGPTR FRAGMENT RECORD */
-/* SUBROUTINE SHORT NAME = STL */
-/* ------------------------------------------------------------------------- */
-void Dblqh::sendStartLcp(Signal* signal)
-{
-}//Dblqh::sendStartLcp()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SET THE LOG TAIL IN THE LOG FILES ------- */
-/* */
-/*THIS SUBROUTINE HAVE BEEN BUGGY AND IS RATHER COMPLEX. IT IS IMPORTANT TO */
-/*REMEMBER THAT WE SEARCH FROM THE TAIL UNTIL WE REACH THE HEAD (CURRENT). */
-/*THE TAIL AND HEAD CAN BE ON THE SAME MBYTE. WE SEARCH UNTIL WE FIND A MBYTE*/
-/*THAT WE NEED TO KEEP. WE THEN SET THE TAIL TO BE THE PREVIOUS. IF WE DO */
-/*NOT FIND A MBYTE THAT WE NEED TO KEEP UNTIL WE REACH THE HEAD THEN WE USE */
-/*THE HEAD AS TAIL. FINALLY WE HAVE TO MOVE BACK THE TAIL TO ALSO INCLUDE */
-/*ALL PREPARE RECORDS. THIS MEANS THAT LONG-LIVED TRANSACTIONS ARE DANGEROUS */
-/*FOR SHORT LOGS. */
-/* ------------------------------------------------------------------------- */
-
-// this function has not been verified yet
-Uint32 Dblqh::remainingLogSize(const LogFileRecordPtr &sltCurrLogFilePtr,
- const LogPartRecordPtr &sltLogPartPtr)
-{
- Uint32 hf = sltCurrLogFilePtr.p->fileNo*clogFileSize+sltCurrLogFilePtr.p->currentMbyte;
- Uint32 tf = sltLogPartPtr.p->logTailFileNo*clogFileSize+sltLogPartPtr.p->logTailMbyte;
- Uint32 sz = sltLogPartPtr.p->noLogFiles*clogFileSize;
- if (tf > hf) hf += sz;
- return sz-(hf-tf);
-}
-
-void Dblqh::setLogTail(Signal* signal, Uint32 keepGci)
-{
- LogPartRecordPtr sltLogPartPtr;
- LogFileRecordPtr sltLogFilePtr;
-#if 0
- LogFileRecordPtr sltCurrLogFilePtr;
-#endif
- UintR tsltMbyte;
- UintR tsltStartMbyte;
- UintR tsltIndex;
- UintR tsltFlag;
-
- for (sltLogPartPtr.i = 0; sltLogPartPtr.i < 4; sltLogPartPtr.i++) {
- jam();
- ptrAss(sltLogPartPtr, logPartRecord);
- findLogfile(signal, sltLogPartPtr.p->logTailFileNo,
- sltLogPartPtr, &sltLogFilePtr);
-
-#if 0
- sltCurrLogFilePtr.i = sltLogPartPtr.p->currentLogfile;
- ptrCheckGuard(sltCurrLogFilePtr, clogFileFileSize, logFileRecord);
- infoEvent("setLogTail: Available log file %d size = %d[mbytes]+%d[words]", sltLogPartPtr.i,
- remainingLogSize(sltCurrLogFilePtr, sltLogPartPtr), sltCurrLogFilePtr.p->remainingWordsInMbyte);
-#endif
-
- tsltMbyte = sltLogPartPtr.p->logTailMbyte;
- tsltStartMbyte = tsltMbyte;
- tsltFlag = ZFALSE;
- if (sltLogFilePtr.i == sltLogPartPtr.p->currentLogfile) {
-/* ------------------------------------------------------------------------- */
-/*THE LOG AND THE TAIL IS ALREADY IN THE SAME FILE. */
-/* ------------------------------------------------------------------------- */
- if (sltLogFilePtr.p->currentMbyte >= sltLogPartPtr.p->logTailMbyte) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*THE CURRENT MBYTE IS AHEAD OF OR AT THE TAIL. THUS WE WILL ONLY LOOK FOR */
-/*THE TAIL UNTIL WE REACH THE CURRENT MBYTE WHICH IS IN THIS LOG FILE. */
-/*IF THE LOG TAIL IS AHEAD OF THE CURRENT MBYTE BUT IN THE SAME LOG FILE */
-/*THEN WE HAVE TO SEARCH THROUGH ALL FILES BEFORE WE COME TO THE CURRENT */
-/*MBYTE. WE ALWAYS STOP WHEN WE COME TO THE CURRENT MBYTE SINCE THE TAIL */
-/*CAN NEVER BE BEFORE THE HEAD. */
-/* ------------------------------------------------------------------------- */
- tsltFlag = ZTRUE;
- }//if
- }//if
-
-/* ------------------------------------------------------------------------- */
-/*NOW START SEARCHING FOR THE NEW TAIL, STARTING AT THE CURRENT TAIL AND */
-/*PROCEEDING UNTIL WE FIND A MBYTE WHICH IS NEEDED TO KEEP OR UNTIL WE REACH */
-/*CURRENT MBYTE (THE HEAD). */
-/* ------------------------------------------------------------------------- */
- SLT_LOOP:
- for (tsltIndex = tsltStartMbyte;
- tsltIndex <= clogFileSize - 1;
- tsltIndex++) {
- if (sltLogFilePtr.p->logMaxGciStarted[tsltIndex] >= keepGci) {
-/* ------------------------------------------------------------------------- */
-/*WE ARE NOT ALLOWED TO STEP THE LOG ANY FURTHER AHEAD */
-/*SET THE NEW LOG TAIL AND CONTINUE WITH NEXT LOG PART. */
-/*THIS MBYTE IS NOT TO BE INCLUDED SO WE NEED TO STEP BACK ONE MBYTE. */
-/* ------------------------------------------------------------------------- */
- if (tsltIndex != 0) {
- jam();
- tsltMbyte = tsltIndex - 1;
- } else {
- jam();
-/* ------------------------------------------------------------------------- */
-/*STEPPING BACK INCLUDES ALSO STEPPING BACK TO THE PREVIOUS LOG FILE. */
-/* ------------------------------------------------------------------------- */
- tsltMbyte = clogFileSize - 1;
- sltLogFilePtr.i = sltLogFilePtr.p->prevLogFile;
- ptrCheckGuard(sltLogFilePtr, clogFileFileSize, logFileRecord);
- }//if
- goto SLT_BREAK;
- } else {
- jam();
- if (tsltFlag == ZTRUE) {
-/* ------------------------------------------------------------------------- */
-/*WE ARE IN THE SAME FILE AS THE CURRENT MBYTE AND WE CAN REACH THE CURRENT */
-/*MBYTE BEFORE WE REACH A NEW TAIL. */
-/* ------------------------------------------------------------------------- */
- if (tsltIndex == sltLogFilePtr.p->currentMbyte) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*THE TAIL OF THE LOG IS ACTUALLY WITHIN THE CURRENT MBYTE. THUS WE SET THE */
-/*LOG TAIL TO BE THE CURRENT MBYTE. */
-/* ------------------------------------------------------------------------- */
- tsltMbyte = sltLogFilePtr.p->currentMbyte;
- goto SLT_BREAK;
- }//if
- }//if
- }//if
- }//for
- sltLogFilePtr.i = sltLogFilePtr.p->nextLogFile;
- ptrCheckGuard(sltLogFilePtr, clogFileFileSize, logFileRecord);
- if (sltLogFilePtr.i == sltLogPartPtr.p->currentLogfile) {
- jam();
- tsltFlag = ZTRUE;
- }//if
- tsltStartMbyte = 0;
- goto SLT_LOOP;
- SLT_BREAK:
- jam();
- {
- UintR ToldTailFileNo = sltLogPartPtr.p->logTailFileNo;
- UintR ToldTailMByte = sltLogPartPtr.p->logTailMbyte;
-
- arrGuard(tsltMbyte, clogFileSize);
- sltLogPartPtr.p->logTailFileNo =
- sltLogFilePtr.p->logLastPrepRef[tsltMbyte] >> 16;
-/* ------------------------------------------------------------------------- */
-/*SINCE LOG_MAX_GCI_STARTED ONLY KEEP TRACK OF COMMIT LOG RECORDS WE ALSO */
-/*HAVE TO STEP BACK THE TAIL SO THAT WE INCLUDE ALL PREPARE RECORDS */
-/*NEEDED FOR THOSE COMMIT RECORDS IN THIS MBYTE. THIS IS A RATHER */
-/*CONSERVATIVE APPROACH BUT IT WORKS. */
-/* ------------------------------------------------------------------------- */
- sltLogPartPtr.p->logTailMbyte =
- sltLogFilePtr.p->logLastPrepRef[tsltMbyte] & 65535;
- if ((ToldTailFileNo != sltLogPartPtr.p->logTailFileNo) ||
- (ToldTailMByte != sltLogPartPtr.p->logTailMbyte)) {
- jam();
- if (sltLogPartPtr.p->logPartState == LogPartRecord::TAIL_PROBLEM) {
- if (sltLogPartPtr.p->firstLogQueue == RNIL) {
- jam();
- sltLogPartPtr.p->logPartState = LogPartRecord::IDLE;
- } else {
- jam();
- sltLogPartPtr.p->logPartState = LogPartRecord::ACTIVE;
- }//if
- }//if
- }//if
- }
-#if 0
- infoEvent("setLogTail: Available log file %d size = %d[mbytes]+%d[words]", sltLogPartPtr.i,
- remainingLogSize(sltCurrLogFilePtr, sltLogPartPtr), sltCurrLogFilePtr.p->remainingWordsInMbyte);
-#endif
- }//for
-
-}//Dblqh::setLogTail()
-
-/* ######################################################################### */
-/* ####### GLOBAL CHECKPOINT MODULE ####### */
-/* */
-/* ######################################################################### */
-/*---------------------------------------------------------------------------*/
-/* THIS MODULE HELPS DIH IN DISCOVERING WHEN GLOBAL CHECKPOINTS ARE */
-/* RECOVERABLE. IT HANDLES THE REQUEST GCP_SAVEREQ THAT REQUESTS LQH TO */
-/* SAVE A PARTICULAR GLOBAL CHECKPOINT TO DISK AND RESPOND WHEN COMPLETED. */
-/*---------------------------------------------------------------------------*/
-/* *************** */
-/* GCP_SAVEREQ > */
-/* *************** */
-void Dblqh::execGCP_SAVEREQ(Signal* signal)
-{
- jamEntry();
- const GCPSaveReq * const saveReq = (GCPSaveReq *)&signal->theData[0];
-
- if (ERROR_INSERTED(5000)) {
- systemErrorLab(signal, __LINE__);
- }
-
- if (ERROR_INSERTED(5007)){
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_GCP_SAVEREQ, signal, 10000,
- signal->length());
- return;
- }
-
- const Uint32 dihBlockRef = saveReq->dihBlockRef;
- const Uint32 dihPtr = saveReq->dihPtr;
- const Uint32 gci = saveReq->gci;
-
- if(getNodeState().startLevel >= NodeState::SL_STOPPING_4){
- GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
- saveRef->dihPtr = dihPtr;
- saveRef->nodeId = getOwnNodeId();
- saveRef->gci = gci;
- saveRef->errorCode = GCPSaveRef::NodeShutdownInProgress;
- sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
- GCPSaveRef::SignalLength, JBB);
- return;
- }
-
- if (getNodeState().getNodeRestartInProgress() && cstartRecReq < 2)
- {
- GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
- saveRef->dihPtr = dihPtr;
- saveRef->nodeId = getOwnNodeId();
- saveRef->gci = gci;
- saveRef->errorCode = GCPSaveRef::NodeRestartInProgress;
- sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
- GCPSaveRef::SignalLength, JBB);
- return;
- }
-
- ndbrequire(gci >= cnewestCompletedGci);
-
- if (gci == cnewestCompletedGci) {
-/*---------------------------------------------------------------------------*/
-/* GLOBAL CHECKPOINT HAVE ALREADY BEEN HANDLED. REQUEST MUST HAVE BEEN SENT */
-/* FROM NEW MASTER DIH. */
-/*---------------------------------------------------------------------------*/
- if (ccurrentGcprec == RNIL) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS INDICATES THAT WE HAVE ALREADY SENT GCP_SAVECONF TO PREVIOUS MASTER. */
-/* WE SIMPLY SEND IT ALSO TO THE NEW MASTER. */
-/*---------------------------------------------------------------------------*/
- GCPSaveConf * const saveConf = (GCPSaveConf*)&signal->theData[0];
- saveConf->dihPtr = dihPtr;
- saveConf->nodeId = getOwnNodeId();
- saveConf->gci = cnewestCompletedGci;
- sendSignal(dihBlockRef, GSN_GCP_SAVECONF, signal,
- GCPSaveConf::SignalLength, JBA);
- return;
- }
- jam();
-/*---------------------------------------------------------------------------*/
-/* WE HAVE NOT YET SENT THE RESPONSE TO THE OLD MASTER. WE WILL SET THE NEW */
-/* RECEIVER OF THE RESPONSE AND THEN EXIT SINCE THE PROCESS IS ALREADY */
-/* STARTED. */
-/*---------------------------------------------------------------------------*/
- gcpPtr.i = ccurrentGcprec;
- ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
- gcpPtr.p->gcpUserptr = dihPtr;
- gcpPtr.p->gcpBlockref = dihBlockRef;
- return;
- }//if
-
- ndbrequire(ccurrentGcprec == RNIL);
- cnewestCompletedGci = gci;
- if (gci > cnewestGci) {
- jam();
- cnewestGci = gci;
- }//if
-
- if(getNodeState().getNodeRestartInProgress() && cstartRecReq < 3)
- {
- GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0];
- saveRef->dihPtr = dihPtr;
- saveRef->nodeId = getOwnNodeId();
- saveRef->gci = gci;
- saveRef->errorCode = GCPSaveRef::NodeRestartInProgress;
- sendSignal(dihBlockRef, GSN_GCP_SAVEREF, signal,
- GCPSaveRef::SignalLength, JBB);
- return;
- }
-
- ccurrentGcprec = 0;
- gcpPtr.i = ccurrentGcprec;
- ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
-
- gcpPtr.p->gcpBlockref = dihBlockRef;
- gcpPtr.p->gcpUserptr = dihPtr;
- gcpPtr.p->gcpId = gci;
- bool tlogActive = false;
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- ptrAss(logPartPtr, logPartRecord);
- if (logPartPtr.p->logPartState == LogPartRecord::ACTIVE) {
- jam();
- logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_TRUE;
- tlogActive = true;
- } else {
- jam();
- logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- writeCompletedGciLog(signal);
- }//if
- }//for
- if (tlogActive == true) {
- jam();
- return;
- }//if
- initGcpRecLab(signal);
- startTimeSupervision(signal);
- return;
-}//Dblqh::execGCP_SAVEREQ()
-
-/* ------------------------------------------------------------------------- */
-/* START TIME SUPERVISION OF THE LOG PARTS. */
-/* ------------------------------------------------------------------------- */
-void Dblqh::startTimeSupervision(Signal* signal)
-{
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
-/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* WE HAVE TO START CHECKING IF THE LOG IS TO BE WRITTEN EVEN IF PAGES ARE */
-/* FULL. INITIALISE THE VALUES OF WHERE WE ARE IN THE LOG CURRENTLY. */
-/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
- logPartPtr.p->logPartTimer = 0;
- logPartPtr.p->logTimer = 1;
- signal->theData[0] = ZTIME_SUPERVISION;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//for
-}//Dblqh::startTimeSupervision()
-
-/*---------------------------------------------------------------------------*/
-/* WE SET THE GLOBAL CHECKPOINT VARIABLES AFTER WRITING THE COMPLETED GCI LOG*/
-/* RECORD. THIS ENSURES THAT WE WILL ENCOUNTER THE COMPLETED GCI RECORD WHEN */
-/* WE EXECUTE THE FRAGMENT LOG. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::initGcpRecLab(Signal* signal)
-{
-/* ======================================================================== */
-/* ======= INITIATE GCP RECORD ======= */
-/* */
-/* SUBROUTINE SHORT NAME = IGR */
-/* ======================================================================== */
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
-/*--------------------------------------------------*/
-/* BY SETTING THE GCPREC = 0 WE START THE */
-/* CHECKING BY CHECK_GCP_COMPLETED. THIS */
-/* CHECKING MUST NOT BE STARTED UNTIL WE HAVE */
-/* INSERTED ALL COMPLETE GCI LOG RECORDS IN */
-/* ALL LOG PARTS. */
-/*--------------------------------------------------*/
- logPartPtr.p->gcprec = 0;
- gcpPtr.p->gcpLogPartState[logPartPtr.i] = ZWAIT_DISK;
- gcpPtr.p->gcpSyncReady[logPartPtr.i] = ZFALSE;
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- gcpPtr.p->gcpFilePtr[logPartPtr.i] = logFilePtr.i;
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- if (logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] == ZPAGE_HEADER_SIZE) {
- jam();
-/*--------------------------------------------------*/
-/* SINCE THE CURRENT FILEPAGE POINTS AT THE */
-/* NEXT WORD TO BE WRITTEN WE HAVE TO ADJUST */
-/* FOR THIS BY DECREASING THE FILE PAGE BY ONE*/
-/* IF NO WORD HAS BEEN WRITTEN ON THE CURRENT */
-/* FILEPAGE. */
-/*--------------------------------------------------*/
- gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage - 1;
- gcpPtr.p->gcpWordNo[logPartPtr.i] = ZPAGE_SIZE - 1;
- } else {
- jam();
- gcpPtr.p->gcpPageNo[logPartPtr.i] = logFilePtr.p->currentFilepage;
- gcpPtr.p->gcpWordNo[logPartPtr.i] =
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] - 1;
- }//if
- }//for
- return;
-}//Dblqh::initGcpRecLab()
-
-/* ========================================================================= */
-/* ==== CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED AFTER A COMPLETED===== */
-/* DISK WRITE. */
-/* */
-/* SUBROUTINE SHORT NAME = CGC */
-/* ========================================================================= */
-void Dblqh::checkGcpCompleted(Signal* signal,
- Uint32 tcgcPageWritten,
- Uint32 tcgcWordWritten)
-{
- UintR tcgcFlag;
- UintR tcgcJ;
-
- gcpPtr.i = logPartPtr.p->gcprec;
- if (gcpPtr.i != RNIL) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* IF THE GLOBAL CHECKPOINT IS NOT WAITING FOR COMPLETION THEN WE CAN QUIT */
-/* THE SEARCH IMMEDIATELY. */
-/* ------------------------------------------------------------------------- */
- ptrCheckGuard(gcpPtr, cgcprecFileSize, gcpRecord);
- if (gcpPtr.p->gcpFilePtr[logPartPtr.i] == logFilePtr.i) {
-/* ------------------------------------------------------------------------- */
-/* IF THE COMPLETED DISK OPERATION WAS ON ANOTHER FILE THAN THE ONE WE ARE */
-/* WAITING FOR, THEN WE CAN ALSO QUIT THE SEARCH IMMEDIATELY. */
-/* ------------------------------------------------------------------------- */
- if (tcgcPageWritten < gcpPtr.p->gcpPageNo[logPartPtr.i]) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
-/* ------------------------------------------------------------------------- */
- return;
- } else {
- if (tcgcPageWritten == gcpPtr.p->gcpPageNo[logPartPtr.i]) {
- if (tcgcWordWritten < gcpPtr.p->gcpWordNo[logPartPtr.i]) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* THIS LOG PART HAVE NOT YET WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
-/* ------------------------------------------------------------------------- */
- return;
- }//if
- }//if
- }//if
-/* ------------------------------------------------------------------------- */
-/* THIS LOG PART HAVE WRITTEN THE GLOBAL CHECKPOINT TO DISK. */
-/* ------------------------------------------------------------------------- */
- logPartPtr.p->gcprec = RNIL;
- gcpPtr.p->gcpLogPartState[logPartPtr.i] = ZON_DISK;
- tcgcFlag = ZTRUE;
- for (tcgcJ = 0; tcgcJ <= 3; tcgcJ++) {
- jam();
- if (gcpPtr.p->gcpLogPartState[tcgcJ] != ZON_DISK) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*ALL LOG PARTS HAVE NOT SAVED THIS GLOBAL CHECKPOINT TO DISK YET. WAIT FOR */
-/*THEM TO COMPLETE. */
-/* ------------------------------------------------------------------------- */
- tcgcFlag = ZFALSE;
- }//if
- }//for
- if (tcgcFlag == ZTRUE) {
- jam();
-/* ------------------------------------------------------------------------- */
-/*WE HAVE FOUND A COMPLETED GLOBAL CHECKPOINT OPERATION. WE NOW NEED TO SEND */
-/*GCP_SAVECONF, REMOVE THE GCP RECORD FROM THE LIST OF WAITING GCP RECORDS */
-/*ON THIS LOG PART AND RELEASE THE GCP RECORD. */
-// After changing the log implementation we need to perform a FSSYNCREQ on all
-// log files where the last log word resided first before proceeding.
-/* ------------------------------------------------------------------------- */
- UintR Ti;
- for (Ti = 0; Ti < 4; Ti++) {
- LogFileRecordPtr loopLogFilePtr;
- loopLogFilePtr.i = gcpPtr.p->gcpFilePtr[Ti];
- ptrCheckGuard(loopLogFilePtr, clogFileFileSize, logFileRecord);
- if (loopLogFilePtr.p->logFileStatus == LogFileRecord::OPEN) {
- jam();
- signal->theData[0] = loopLogFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = gcpPtr.p->gcpFilePtr[Ti];
- sendSignal(NDBFS_REF, GSN_FSSYNCREQ, signal, 3, JBA);
- } else {
- ndbrequire((loopLogFilePtr.p->logFileStatus ==
- LogFileRecord::CLOSED) ||
- (loopLogFilePtr.p->logFileStatus ==
- LogFileRecord::CLOSING_WRITE_LOG) ||
- (loopLogFilePtr.p->logFileStatus ==
- LogFileRecord::OPENING_WRITE_LOG));
- signal->theData[0] = loopLogFilePtr.i;
- execFSSYNCCONF(signal);
- }//if
- }//for
- return;
- }//if
- }//if
- }//if
-}//Dblqh::checkGcpCompleted()
-
-void
-Dblqh::execFSSYNCCONF(Signal* signal)
-{
- GcpRecordPtr localGcpPtr;
- LogFileRecordPtr localLogFilePtr;
- LogPartRecordPtr localLogPartPtr;
- localLogFilePtr.i = signal->theData[0];
- ptrCheckGuard(localLogFilePtr, clogFileFileSize, logFileRecord);
- localLogPartPtr.i = localLogFilePtr.p->logPartRec;
- localGcpPtr.i = ccurrentGcprec;
- ptrCheckGuard(localGcpPtr, cgcprecFileSize, gcpRecord);
- localGcpPtr.p->gcpSyncReady[localLogPartPtr.i] = ZTRUE;
- UintR Ti;
- for (Ti = 0; Ti < 4; Ti++) {
- jam();
- if (localGcpPtr.p->gcpSyncReady[Ti] == ZFALSE) {
- jam();
- return;
- }//if
- }//for
- GCPSaveConf * const saveConf = (GCPSaveConf *)&signal->theData[0];
- saveConf->dihPtr = localGcpPtr.p->gcpUserptr;
- saveConf->nodeId = getOwnNodeId();
- saveConf->gci = localGcpPtr.p->gcpId;
- sendSignal(localGcpPtr.p->gcpBlockref, GSN_GCP_SAVECONF, signal,
- GCPSaveConf::SignalLength, JBA);
- ccurrentGcprec = RNIL;
-}//Dblqh::execFSSYNCCONF()
-
-
-/* ######################################################################### */
-/* ####### FILE HANDLING MODULE ####### */
-/* */
-/* ######################################################################### */
-/* THIS MODULE HANDLES RESPONSE MESSAGES FROM THE FILE SYSTEM */
-/* ######################################################################### */
-/* ######################################################################### */
-/* SIGNAL RECEPTION MODULE */
-/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
-/* */
-/* THIS MODULE CHECKS THE STATE AND JUMPS TO THE PROPER PART OF THE FILE */
-/* HANDLING MODULE. */
-/* ######################################################################### */
-/* *************** */
-/* FSCLOSECONF > */
-/* *************** */
-void Dblqh::execFSCLOSECONF(Signal* signal)
-{
- jamEntry();
- logFilePtr.i = signal->theData[0];
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- switch (logFilePtr.p->logFileStatus) {
- case LogFileRecord::CLOSE_SR_INVALIDATE_PAGES:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
-
- logPartPtr.i = logFilePtr.p->logPartRec;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
-
- exitFromInvalidate(signal);
- return;
- case LogFileRecord::CLOSING_INIT:
- jam();
- closingInitLab(signal);
- return;
- case LogFileRecord::CLOSING_SR:
- jam();
- closingSrLab(signal);
- return;
- case LogFileRecord::CLOSING_EXEC_SR:
- jam();
- closeExecSrLab(signal);
- return;
- case LogFileRecord::CLOSING_EXEC_SR_COMPLETED:
- jam();
- closeExecSrCompletedLab(signal);
- return;
- case LogFileRecord::CLOSING_WRITE_LOG:
- jam();
- closeWriteLogLab(signal);
- return;
- case LogFileRecord::CLOSING_EXEC_LOG:
- jam();
- closeExecLogLab(signal);
- return;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
-}//Dblqh::execFSCLOSECONF()
-
-
-/* ************>> */
-/* FSOPENCONF > */
-/* ************>> */
-void Dblqh::execFSOPENCONF(Signal* signal)
-{
- jamEntry();
- initFsopenconf(signal);
- switch (logFilePtr.p->logFileStatus) {
- case LogFileRecord::OPEN_SR_INVALIDATE_PAGES:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- readFileInInvalidate(signal, false);
- return;
- case LogFileRecord::OPENING_INIT:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openFileInitLab(signal);
- return;
- case LogFileRecord::OPEN_SR_FRONTPAGE:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openSrFrontpageLab(signal);
- return;
- case LogFileRecord::OPEN_SR_LAST_FILE:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openSrLastFileLab(signal);
- return;
- case LogFileRecord::OPEN_SR_NEXT_FILE:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openSrNextFileLab(signal);
- return;
- case LogFileRecord::OPEN_EXEC_SR_START:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openExecSrStartLab(signal);
- return;
- case LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openExecSrNewMbyteLab(signal);
- return;
- case LogFileRecord::OPEN_SR_FOURTH_PHASE:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openSrFourthPhaseLab(signal);
- return;
- case LogFileRecord::OPEN_SR_FOURTH_NEXT:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openSrFourthNextLab(signal);
- return;
- case LogFileRecord::OPEN_SR_FOURTH_ZERO:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openSrFourthZeroLab(signal);
- return;
- case LogFileRecord::OPENING_WRITE_LOG:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- return;
- case LogFileRecord::OPEN_EXEC_LOG:
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
- openExecLogLab(signal);
- return;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
-}//Dblqh::execFSOPENCONF()
-
-void
-Dblqh::execFSOPENREF(Signal* signal)
-{
- jamEntry();
- FsRef* ref = (FsRef*)signal->getDataPtr();
- Uint32 err = ref->errorCode;
- if (err == FsRef::fsErrInvalidFileSize)
- {
- char buf[256];
- BaseString::snprintf(buf, sizeof(buf),
- "Invalid file size for redo logfile, "
- " size only changable with --initial");
- progError(__LINE__,
- NDBD_EXIT_INVALID_CONFIG,
- buf);
- return;
- }
-
- SimulatedBlock::execFSOPENREF(signal);
-}
-
-/* ************>> */
-/* FSREADCONF > */
-/* ************>> */
-void Dblqh::execFSREADCONF(Signal* signal)
-{
- jamEntry();
- initFsrwconf(signal, false);
-
- switch (lfoPtr.p->lfoState) {
- case LogFileOperationRecord::READ_SR_LAST_MBYTE:
- jam();
- releaseLfo(signal);
- readSrLastMbyteLab(signal);
- return;
- case LogFileOperationRecord::READ_SR_FRONTPAGE:
- jam();
- releaseLfo(signal);
- readSrFrontpageLab(signal);
- return;
- case LogFileOperationRecord::READ_SR_LAST_FILE:
- jam();
- releaseLfo(signal);
- readSrLastFileLab(signal);
- return;
- case LogFileOperationRecord::READ_SR_NEXT_FILE:
- jam();
- releaseLfo(signal);
- readSrNextFileLab(signal);
- return;
- case LogFileOperationRecord::READ_EXEC_SR:
- jam();
- readExecSrLab(signal);
- return;
- case LogFileOperationRecord::READ_EXEC_LOG:
- jam();
- readExecLogLab(signal);
- return;
- case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
- jam();
- invalidateLogAfterLastGCI(signal);
- return;
- case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
- jam();
- releaseLfo(signal);
- readSrFourthPhaseLab(signal);
- return;
- case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
- jam();
- releaseLfo(signal);
- readSrFourthZeroLab(signal);
- return;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
-}//Dblqh::execFSREADCONF()
-
-/* ************>> */
-/* FSREADCONF > */
-/* ************>> */
-void Dblqh::execFSREADREF(Signal* signal)
-{
- jamEntry();
- lfoPtr.i = signal->theData[0];
- ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
- switch (lfoPtr.p->lfoState) {
- case LogFileOperationRecord::READ_SR_LAST_MBYTE:
- jam();
- break;
- case LogFileOperationRecord::READ_SR_FRONTPAGE:
- jam();
- break;
- case LogFileOperationRecord::READ_SR_LAST_FILE:
- jam();
- break;
- case LogFileOperationRecord::READ_SR_NEXT_FILE:
- jam();
- break;
- case LogFileOperationRecord::READ_EXEC_SR:
- jam();
- break;
- case LogFileOperationRecord::READ_EXEC_LOG:
- jam();
- break;
- case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
- jam();
- break;
- case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
- jam();
- break;
- case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
- jam()
- break;
- default:
- jam();
- break;
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system read failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
- fsRefError(signal,__LINE__,msg);
- }
-}//Dblqh::execFSREADREF()
-
-/* *************** */
-/* FSWRITECONF > */
-/* *************** */
-void Dblqh::execFSWRITECONF(Signal* signal)
-{
- jamEntry();
- initFsrwconf(signal, true);
- switch (lfoPtr.p->lfoState) {
- case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
- jam();
- invalidateLogAfterLastGCI(signal);
- CRASH_INSERTION(5047);
- return;
- case LogFileOperationRecord::WRITE_PAGE_ZERO:
- jam();
- writePageZeroLab(signal);
- return;
- case LogFileOperationRecord::LAST_WRITE_IN_FILE:
- jam();
- lastWriteInFileLab(signal);
- return;
- case LogFileOperationRecord::INIT_WRITE_AT_END:
- jam();
- initWriteEndLab(signal);
- return;
- case LogFileOperationRecord::INIT_FIRST_PAGE:
- jam();
- initFirstPageLab(signal);
- return;
- case LogFileOperationRecord::WRITE_GCI_ZERO:
- jam();
- writeGciZeroLab(signal);
- return;
- case LogFileOperationRecord::WRITE_DIRTY:
- jam();
- writeDirtyLab(signal);
- return;
- case LogFileOperationRecord::WRITE_INIT_MBYTE:
- jam();
- writeInitMbyteLab(signal);
- return;
- case LogFileOperationRecord::ACTIVE_WRITE_LOG:
- jam();
- writeLogfileLab(signal);
- return;
- case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
- jam();
- firstPageWriteLab(signal);
- return;
- case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0:
- jam();
- // We are done...send completed signal and exit this phase.
- releaseLfo(signal);
- signal->theData[0] = ZSR_FOURTH_COMP;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
-}//Dblqh::execFSWRITECONF()
-
-/* ************>> */
-/* FSWRITEREF > */
-/* ************>> */
-void Dblqh::execFSWRITEREF(Signal* signal)
-{
- jamEntry();
- lfoPtr.i = signal->theData[0];
- ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
- terrorCode = signal->theData[1];
- switch (lfoPtr.p->lfoState) {
- case LogFileOperationRecord::WRITE_PAGE_ZERO:
- jam();
- break;
- case LogFileOperationRecord::LAST_WRITE_IN_FILE:
- jam();
- break;
- case LogFileOperationRecord::INIT_WRITE_AT_END:
- jam();
- break;
- case LogFileOperationRecord::INIT_FIRST_PAGE:
- jam();
- break;
- case LogFileOperationRecord::WRITE_GCI_ZERO:
- jam();
- break;
- case LogFileOperationRecord::WRITE_DIRTY:
- jam();
- break;
- case LogFileOperationRecord::WRITE_INIT_MBYTE:
- jam();
- break;
- case LogFileOperationRecord::ACTIVE_WRITE_LOG:
- jam();
- break;
- case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
- jam();
- break;
- case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
- jam();
- systemErrorLab(signal, __LINE__);
- default:
- jam();
- break;
- }//switch
- {
- char msg[100];
- sprintf(msg, "File system write failed during LogFileOperationRecord state %d", (Uint32)lfoPtr.p->lfoState);
- fsRefError(signal,__LINE__,msg);
- }
-}//Dblqh::execFSWRITEREF()
-
-
-/* ========================================================================= */
-/* ======= INITIATE WHEN RECEIVING FSOPENCONF ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initFsopenconf(Signal* signal)
-{
- logFilePtr.i = signal->theData[0];
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logFilePtr.p->fileRef = signal->theData[1];
- logPartPtr.i = logFilePtr.p->logPartRec;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logFilePtr.p->currentMbyte = 0;
- logFilePtr.p->filePosition = 0;
-}//Dblqh::initFsopenconf()
-
-/* ========================================================================= */
-/* ======= INITIATE WHEN RECEIVING FSREADCONF AND FSWRITECONF ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initFsrwconf(Signal* signal, bool write)
-{
- LogPageRecordPtr logP;
- Uint32 noPages, totPages;
- lfoPtr.i = signal->theData[0];
- ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
- totPages= lfoPtr.p->noPagesRw;
- logFilePtr.i = lfoPtr.p->logFileRec;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPartPtr.i = logFilePtr.p->logPartRec;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logPagePtr.i = lfoPtr.p->firstLfoPage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logP= logPagePtr;
- noPages= 1;
- ndbassert(totPages > 0);
- for (;;)
- {
- logP.p->logPageWord[ZPOS_IN_WRITING]= 0;
- logP.p->logPageWord[ZPOS_IN_FREE_LIST]= 0;
- if (noPages == totPages)
- return;
- if (write)
- logP.i= logP.p->logPageWord[ZNEXT_PAGE];
- else
- logP.i= lfoPtr.p->logPageArray[noPages];
- ptrCheckGuard(logP, clogPageFileSize, logPageRecord);
- noPages++;
- }
-}//Dblqh::initFsrwconf()
-
-/* ######################################################################### */
-/* NORMAL OPERATION MODULE */
-/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
-/* */
-/* THIS PART HANDLES THE NORMAL OPENING, CLOSING AND WRITING OF LOG FILES */
-/* DURING NORMAL OPERATION. */
-/* ######################################################################### */
-/*---------------------------------------------------------------------------*/
-/* THIS SIGNAL IS USED TO SUPERVISE THAT THE LOG RECORDS ARE NOT KEPT IN MAIN*/
-/* MEMORY FOR MORE THAN 1 SECOND TO ACHIEVE THE PROPER RELIABILITY. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::timeSup(Signal* signal)
-{
- LogPageRecordPtr origLogPagePtr;
- Uint32 wordWritten;
-
- jamEntry();
- logPartPtr.i = signal->theData[0];
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- if (logPartPtr.p->logPartTimer != logPartPtr.p->logTimer) {
- jam();
-/*--------------------------------------------------------------------------*/
-/* THIS LOG PART HAS NOT WRITTEN TO DISK DURING THE LAST SECOND. */
-/*--------------------------------------------------------------------------*/
- switch (logPartPtr.p->logPartState) {
- case LogPartRecord::FILE_CHANGE_PROBLEM:
- jam();
-/*--------------------------------------------------------------------------*/
-/* THIS LOG PART HAS PROBLEMS IN CHANGING FILES MAKING IT IMPOSSIBLE */
-// TO WRITE TO THE FILE CURRENTLY. WE WILL COMEBACK LATER AND SEE IF
-// THE PROBLEM HAS BEEN FIXED.
-/*--------------------------------------------------------------------------*/
- case LogPartRecord::ACTIVE:
- jam();
-/*---------------------------------------------------------------------------*/
-/* AN OPERATION IS CURRENTLY ACTIVE IN WRITING THIS LOG PART. WE THUS CANNOT */
-/* WRITE ANYTHING TO DISK AT THIS MOMENT. WE WILL SEND A SIGNAL DELAYED FOR */
-/* 10 MS AND THEN TRY AGAIN. POSSIBLY THE LOG PART WILL HAVE BEEN WRITTEN */
-/* UNTIL THEN OR ELSE IT SHOULD BE FREE TO WRITE AGAIN. */
-/*---------------------------------------------------------------------------*/
- signal->theData[0] = ZTIME_SUPERVISION;
- signal->theData[1] = logPartPtr.i;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
- return;
- break;
- case LogPartRecord::IDLE:
- case LogPartRecord::TAIL_PROBLEM:
- jam();
-/*---------------------------------------------------------------------------*/
-/* IDLE AND NOT WRITTEN TO DISK IN A SECOND. ALSO WHEN WE HAVE A TAIL PROBLEM*/
-/* WE HAVE TO WRITE TO DISK AT TIMES. WE WILL FIRST CHECK WHETHER ANYTHING */
-/* AT ALL HAVE BEEN WRITTEN TO THE PAGES BEFORE WRITING TO DISK. */
-/*---------------------------------------------------------------------------*/
-/* WE HAVE TO WRITE TO DISK IN ALL CASES SINCE THERE COULD BE INFORMATION */
-/* STILL IN THE LOG THAT WAS GENERATED BEFORE THE PREVIOUS TIME SUPERVISION */
-/* BUT AFTER THE LAST DISK WRITE. THIS PREVIOUSLY STOPPED ALL DISK WRITES */
-/* WHEN NO MORE LOG WRITES WERE PERFORMED (THIS HAPPENED WHEN LOG GOT FULL */
-/* AND AFTER LOADING THE INITIAL RECORDS IN INITIAL START). */
-/*---------------------------------------------------------------------------*/
- if (((logFilePtr.p->currentFilepage + 1) & (ZPAGES_IN_MBYTE -1)) == 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS IS THE LAST PAGE IN THIS MBYTE. WRITE NEXT LOG AND SWITCH TO NEXT */
-/* MBYTE. */
-/*---------------------------------------------------------------------------*/
- changeMbyte(signal);
- } else {
-/*---------------------------------------------------------------------------*/
-/* WRITE THE LOG PAGE TO DISK EVEN IF IT IS NOT FULL. KEEP PAGE AND WRITE A */
-/* COPY. THE ORIGINAL PAGE WILL BE WRITTEN AGAIN LATER ON. */
-/*---------------------------------------------------------------------------*/
- wordWritten = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] - 1;
- origLogPagePtr.i = logPagePtr.i;
- origLogPagePtr.p = logPagePtr.p;
- seizeLogpage(signal);
- MEMCOPY_NO_WORDS(&logPagePtr.p->logPageWord[0],
- &origLogPagePtr.p->logPageWord[0],
- wordWritten + 1);
- ndbrequire(wordWritten < ZPAGE_SIZE);
- if (logFilePtr.p->noLogpagesInBuffer > 0) {
- jam();
- completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
-/*---------------------------------------------------------------------------*/
-/*SINCE WE ARE ONLY WRITING PART OF THE LAST PAGE WE HAVE TO UPDATE THE WORD */
-/*WRITTEN TO REFLECT THE REAL LAST WORD WRITTEN. WE ALSO HAVE TO MOVE THE */
-/*FILE POSITION ONE STEP BACKWARDS SINCE WE ARE NOT WRITING THE LAST PAGE */
-/*COMPLETELY. IT WILL BE WRITTEN AGAIN. */
-/*---------------------------------------------------------------------------*/
- lfoPtr.p->lfoWordWritten = wordWritten;
- logFilePtr.p->filePosition = logFilePtr.p->filePosition - 1;
- } else {
- if (wordWritten == (ZPAGE_HEADER_SIZE - 1)) {
-/*---------------------------------------------------------------------------*/
-/*THIS IS POSSIBLE BUT VERY UNLIKELY. IF THE PAGE WAS COMPLETED AFTER THE LAST*/
-/*WRITE TO DISK THEN NO_LOG_PAGES_IN_BUFFER > 0 AND IF NOT WRITTEN SINCE LAST*/
-/*WRITE TO DISK THEN THE PREVIOUS PAGE MUST HAVE BEEN WRITTEN BY SOME */
-/*OPERATION AND THAT BECAME COMPLETELY FULL. IN ANY CASE WE NEED NOT WRITE AN*/
-/*EMPTY PAGE TO DISK. */
-/*---------------------------------------------------------------------------*/
- jam();
- releaseLogpage(signal);
- } else {
- jam();
- writeSinglePage(signal, logFilePtr.p->currentFilepage,
- wordWritten, __LINE__);
- lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
- }//if
- }//if
- }//if
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- }//if
- logPartPtr.p->logTimer++;
- return;
-}//Dblqh::timeSup()
-
-void Dblqh::writeLogfileLab(Signal* signal)
-{
-/*---------------------------------------------------------------------------*/
-/* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK */
-/* WRITE. */
-/*---------------------------------------------------------------------------*/
- switch (logFilePtr.p->fileChangeState) {
- case LogFileRecord::NOT_ONGOING:
- jam();
- checkGcpCompleted(signal,
- ((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
- lfoPtr.p->lfoWordWritten);
- break;
-#if 0
- case LogFileRecord::BOTH_WRITES_ONGOING:
- jam();
- ndbout_c("not crashing!!");
- // Fall-through
-#endif
- case LogFileRecord::WRITE_PAGE_ZERO_ONGOING:
- case LogFileRecord::LAST_WRITE_ONGOING:
- jam();
- logFilePtr.p->lastPageWritten = (lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1;
- logFilePtr.p->lastWordWritten = lfoPtr.p->lfoWordWritten;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
- releaseLfoPages(signal);
- releaseLfo(signal);
- return;
-}//Dblqh::writeLogfileLab()
-
-void Dblqh::closeWriteLogLab(Signal* signal)
-{
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
- return;
-}//Dblqh::closeWriteLogLab()
-
-/* ######################################################################### */
-/* FILE CHANGE MODULE */
-/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
-/* */
-/*THIS PART OF THE FILE MODULE HANDLES WHEN WE ARE CHANGING LOG FILE DURING */
-/*NORMAL OPERATION. WE HAVE TO BE CAREFUL WHEN WE ARE CHANGING LOG FILE SO */
-/*THAT WE DO NOT COMPLICATE THE SYSTEM RESTART PROCESS TOO MUCH. */
-/*THE IDEA IS THAT WE START BY WRITING THE LAST WRITE IN THE OLD FILE AND WE */
-/*ALSO WRITE THE FIRST PAGE OF THE NEW FILE CONCURRENT WITH THAT. THIS FIRST */
-/*PAGE IN THE NEW FILE DO NOT CONTAIN ANY LOG RECORDS OTHER THAN A DESCRIPTOR*/
-/*CONTAINING INFORMATION ABOUT GCI'S NEEDED AT SYSTEM RESTART AND A NEXT LOG */
-/*RECORD. */
-/* */
-/*WHEN BOTH OF THOSE WRITES HAVE COMPLETED WE ALSO WRITE PAGE ZERO IN FILE */
-/*ZERO. THE ONLY INFORMATION WHICH IS INTERESTING HERE IS THE NEW FILE NUMBER*/
-/* */
-/*IF OPTIMISATIONS ARE NEEDED OF THE LOG HANDLING THEN IT IS POSSIBLE TO */
-/*AVOID WRITING THE FIRST PAGE OF THE NEW PAGE IMMEDIATELY. THIS COMPLICATES */
-/*THE SYSTEM RESTART AND ONE HAS TO TAKE SPECIAL CARE WITH FILE ZERO. IT IS */
-/*HOWEVER NO LARGE PROBLEM TO CHANGE INTO THIS SCENARIO. TO AVOID ALSO THE */
-/*WRITING OF PAGE ZERO IS ALSO POSSIBLE BUT COMPLICATES THE DESIGN EVEN */
-/*FURTHER. IT GETS FAIRLY COMPLEX TO FIND THE END OF THE LOG. SOME SORT OF */
-/*BINARY SEARCH IS HOWEVER MOST LIKELY A GOOD METHODOLOGY FOR THIS. */
-/* ######################################################################### */
-void Dblqh::firstPageWriteLab(Signal* signal)
-{
- releaseLfo(signal);
-/*---------------------------------------------------------------------------*/
-/* RELEASE PAGE ZERO IF THE FILE IS NOT FILE 0. */
-/*---------------------------------------------------------------------------*/
- Uint32 fileNo = logFilePtr.p->fileNo;
- if (fileNo != 0) {
- jam();
- releaseLogpage(signal);
- }//if
-/*---------------------------------------------------------------------------*/
-/* IF A NEW FILE HAS BEEN OPENED WE SHALL ALWAYS ALSO WRITE TO PAGE O IN */
-/* FILE 0. THE AIM IS TO MAKE RESTARTS EASIER BY SPECIFYING WHICH IS THE */
-/* LAST FILE WHERE LOGGING HAS STARTED. */
-/*---------------------------------------------------------------------------*/
-/* FIRST CHECK WHETHER THE LAST WRITE IN THE PREVIOUS FILE HAVE COMPLETED */
-/*---------------------------------------------------------------------------*/
- if (logFilePtr.p->fileChangeState == LogFileRecord::BOTH_WRITES_ONGOING) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE LAST WRITE WAS STILL ONGOING. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->fileChangeState = LogFileRecord::LAST_WRITE_ONGOING;
- return;
- } else {
- jam();
- ndbrequire(logFilePtr.p->fileChangeState == LogFileRecord::FIRST_WRITE_ONGOING);
-/*---------------------------------------------------------------------------*/
-/* WRITE TO PAGE 0 IN IN FILE 0 NOW. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->fileChangeState = LogFileRecord::WRITE_PAGE_ZERO_ONGOING;
- if (fileNo == 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* IF THE NEW FILE WAS 0 THEN WE HAVE ALREADY WRITTEN PAGE ZERO IN FILE 0. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
- return;
- } else {
- jam();
-/*---------------------------------------------------------------------------*/
-/* WRITE PAGE ZERO IN FILE ZERO. LOG_FILE_REC WILL REFER TO THE LOG FILE WE */
-/* HAVE JUST WRITTEN PAGE ZERO IN TO GET HOLD OF LOG_FILE_PTR FOR THIS */
-/* RECORD QUICKLY. THIS IS NEEDED TO GET HOLD OF THE FILE_CHANGE_STATE. */
-/* THE ONLY INFORMATION WE WANT TO CHANGE IS THE LAST FILE NUMBER IN THE */
-/* FILE DESCRIPTOR. THIS IS USED AT SYSTEM RESTART TO FIND THE END OF THE */
-/* LOG PART. */
-/*---------------------------------------------------------------------------*/
- Uint32 currLogFile = logFilePtr.i;
- logFilePtr.i = logPartPtr.p->firstLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logFilePtr.p->logPageZero;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
- lfoPtr.p->logFileRec = currLogFile;
- lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
- return;
- }//if
- }//if
-}//Dblqh::firstPageWriteLab()
-
-void Dblqh::lastWriteInFileLab(Signal* signal)
-{
- LogFileRecordPtr locLogFilePtr;
-/*---------------------------------------------------------------------------*/
-/* CHECK IF ANY GLOBAL CHECKPOINTS ARE COMPLETED DUE TO THIS COMPLETED DISK */
-/* WRITE. */
-/*---------------------------------------------------------------------------*/
- checkGcpCompleted(signal,
- ((lfoPtr.p->lfoPageNo + lfoPtr.p->noPagesRw) - 1),
- (ZPAGE_SIZE - 1));
- releaseLfoPages(signal);
- releaseLfo(signal);
-/*---------------------------------------------------------------------------*/
-/* IF THE FILE IS NOT IN USE OR THE NEXT FILE TO BE USED WE WILL CLOSE IT. */
-/*---------------------------------------------------------------------------*/
- locLogFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
- if (logFilePtr.i != locLogFilePtr.i) {
- if (logFilePtr.i != locLogFilePtr.p->nextLogFile) {
- if (logFilePtr.p->fileNo != 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE FILE IS NOT FILE ZERO EITHER. WE WILL NOT CLOSE FILE ZERO SINCE WE */
-/* USE IT TO KEEP TRACK OF THE CURRENT LOG FILE BY WRITING PAGE ZERO IN */
-/* FILE ZERO. */
-/*---------------------------------------------------------------------------*/
-/* WE WILL CLOSE THE FILE. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_WRITE_LOG;
- closeFile(signal, logFilePtr, __LINE__);
- }//if
- }//if
- }//if
-/*---------------------------------------------------------------------------*/
-/* IF A NEW FILE HAS BEEN OPENED WE SHALL ALWAYS ALSO WRITE TO PAGE O IN */
-/* FILE 0. THE AIM IS TO MAKE RESTARTS EASIER BY SPECIFYING WHICH IS THE */
-/* LAST FILE WHERE LOGGING HAS STARTED. */
-/*---------------------------------------------------------------------------*/
-/* FIRST CHECK WHETHER THE FIRST WRITE IN THE NEW FILE HAVE COMPLETED */
-/* THIS STATE INFORMATION IS IN THE NEW LOG FILE AND THUS WE HAVE TO MOVE */
-/* THE LOG FILE POINTER TO THIS LOG FILE. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- if (logFilePtr.p->fileChangeState == LogFileRecord::BOTH_WRITES_ONGOING) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE FIRST WRITE WAS STILL ONGOING. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->fileChangeState = LogFileRecord::FIRST_WRITE_ONGOING;
- return;
- } else {
- ndbrequire(logFilePtr.p->fileChangeState == LogFileRecord::LAST_WRITE_ONGOING);
-/*---------------------------------------------------------------------------*/
-/* WRITE TO PAGE 0 IN IN FILE 0 NOW. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->fileChangeState = LogFileRecord::WRITE_PAGE_ZERO_ONGOING;
- Uint32 fileNo = logFilePtr.p->fileNo;
- if (fileNo == 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* IF THE NEW FILE WAS 0 THEN WE HAVE ALREADY WRITTEN PAGE ZERO IN FILE 0. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
- return;
- } else {
- jam();
-/*---------------------------------------------------------------------------*/
-/* WRITE PAGE ZERO IN FILE ZERO. LOG_FILE_REC WILL REFER TO THE LOG FILE WE */
-/* HAVE JUST WRITTEN PAGE ZERO IN TO GET HOLD OF LOG_FILE_PTR FOR THIS */
-/* RECORD QUICKLY. THIS IS NEEDED TO GET HOLD OF THE FILE_CHANGE_STATE. */
-/* THE ONLY INFORMATION WE WANT TO CHANGE IS THE LAST FILE NUMBER IN THE */
-/* FILE DESCRIPTOR. THIS IS USED AT SYSTEM RESTART TO FIND THE END OF THE */
-/* LOG PART. */
-/*---------------------------------------------------------------------------*/
- Uint32 currLogFile = logFilePtr.i;
- logFilePtr.i = logPartPtr.p->firstLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logFilePtr.p->logPageZero;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
- lfoPtr.p->logFileRec = currLogFile;
- lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
- return;
- }//if
- }//if
-}//Dblqh::lastWriteInFileLab()
-
-void Dblqh::writePageZeroLab(Signal* signal)
-{
- if (logPartPtr.p->logPartState == LogPartRecord::FILE_CHANGE_PROBLEM)
- {
- if (logPartPtr.p->firstLogQueue == RNIL)
- {
- jam();
- logPartPtr.p->logPartState = LogPartRecord::IDLE;
- }
- else
- {
- jam();
- logPartPtr.p->logPartState = LogPartRecord::ACTIVE;
- }
- }
-
- logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
-/*---------------------------------------------------------------------------*/
-/* IT COULD HAVE ARRIVED PAGE WRITES TO THE CURRENT FILE WHILE WE WERE */
-/* WAITING FOR THIS DISK WRITE TO COMPLETE. THEY COULD NOT CHECK FOR */
-/* COMPLETED GLOBAL CHECKPOINTS. THUS WE SHOULD DO THAT NOW INSTEAD. */
-/*---------------------------------------------------------------------------*/
- checkGcpCompleted(signal,
- logFilePtr.p->lastPageWritten,
- logFilePtr.p->lastWordWritten);
- releaseLfo(signal);
- return;
-}//Dblqh::writePageZeroLab()
-
-/* ######################################################################### */
-/* INITIAL START MODULE */
-/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
-/* */
-/*THIS MODULE INITIALISES ALL THE LOG FILES THAT ARE NEEDED AT A SYSTEM */
-/*RESTART AND WHICH ARE USED DURING NORMAL OPERATIONS. IT CREATES THE FILES */
-/*AND SETS A PROPER SIZE OF THEM AND INITIALISES THE FIRST PAGE IN EACH FILE */
-/* ######################################################################### */
-void Dblqh::openFileInitLab(Signal* signal)
-{
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN_INIT;
- seizeLogpage(signal);
- writeSinglePage(signal, (clogFileSize * ZPAGES_IN_MBYTE) - 1,
- ZPAGE_SIZE - 1, __LINE__);
- lfoPtr.p->lfoState = LogFileOperationRecord::INIT_WRITE_AT_END;
- return;
-}//Dblqh::openFileInitLab()
-
-void Dblqh::initWriteEndLab(Signal* signal)
-{
- releaseLfo(signal);
- initLogpage(signal);
- if (logFilePtr.p->fileNo == 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* PAGE ZERO IN FILE ZERO MUST SET LOG LAP TO ONE SINCE IT HAS STARTED */
-/* WRITING TO THE LOG, ALSO GLOBAL CHECKPOINTS ARE SET TO ZERO. */
-/*---------------------------------------------------------------------------*/
- logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
- logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = 0;
- logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] = 0;
- logFilePtr.p->logMaxGciStarted[0] = 0;
- logFilePtr.p->logMaxGciCompleted[0] = 0;
- }//if
-/*---------------------------------------------------------------------------*/
-/* REUSE CODE FOR INITIALISATION OF FIRST PAGE IN ALL LOG FILES. */
-/*---------------------------------------------------------------------------*/
- writeFileHeaderOpen(signal, ZINIT);
- return;
-}//Dblqh::initWriteEndLab()
-
-void Dblqh::initFirstPageLab(Signal* signal)
-{
- releaseLfo(signal);
- if (logFilePtr.p->fileNo == 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* IN FILE ZERO WE WILL INSERT A PAGE ONE WHERE WE WILL INSERT A COMPLETED */
-/* GCI RECORD FOR GCI = 0. */
-/*---------------------------------------------------------------------------*/
- initLogpage(signal);
- logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE] = ZCOMPLETED_GCI_TYPE;
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + 1] = 1;
- writeSinglePage(signal, 1, ZPAGE_SIZE - 1, __LINE__);
- lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_GCI_ZERO;
- return;
- }//if
- logFilePtr.p->currentMbyte = 1;
- writeInitMbyte(signal);
- return;
-}//Dblqh::initFirstPageLab()
-
-void Dblqh::writeGciZeroLab(Signal* signal)
-{
- releaseLfo(signal);
- logFilePtr.p->currentMbyte = 1;
- writeInitMbyte(signal);
- return;
-}//Dblqh::writeGciZeroLab()
-
-void Dblqh::writeInitMbyteLab(Signal* signal)
-{
- releaseLfo(signal);
- logFilePtr.p->currentMbyte = logFilePtr.p->currentMbyte + 1;
- if (logFilePtr.p->currentMbyte == clogFileSize) {
- jam();
- releaseLogpage(signal);
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_INIT;
- closeFile(signal, logFilePtr, __LINE__);
- return;
- }//if
- writeInitMbyte(signal);
- return;
-}//Dblqh::writeInitMbyteLab()
-
-void Dblqh::closingInitLab(Signal* signal)
-{
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
- logPartPtr.i = logFilePtr.p->logPartRec;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- if (logFilePtr.p->nextLogFile == logPartPtr.p->firstLogfile) {
- jam();
- checkInitCompletedLab(signal);
- return;
- } else {
- jam();
- logFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- openLogfileInit(signal);
- }//if
- return;
-}//Dblqh::closingInitLab()
-
-void Dblqh::checkInitCompletedLab(Signal* signal)
-{
- logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE_COMPLETED;
-/*---------------------------------------------------------------------------*/
-/* WE HAVE NOW INITIALISED ALL FILES IN THIS LOG PART. WE CAN NOW SET THE */
-/* THE LOG LAP TO ONE SINCE WE WILL START WITH LOG LAP ONE. LOG LAP = ZERO */
-/* MEANS THIS PART OF THE LOG IS NOT WRITTEN YET. */
-/*---------------------------------------------------------------------------*/
- logPartPtr.p->logLap = 1;
- logPartPtr.i = 0;
-CHECK_LOG_PARTS_LOOP:
- ptrAss(logPartPtr, logPartRecord);
- if (logPartPtr.p->logPartState != LogPartRecord::SR_FIRST_PHASE_COMPLETED) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS PART HAS STILL NOT COMPLETED. WAIT FOR THIS TO OCCUR. */
-/*---------------------------------------------------------------------------*/
- return;
- }//if
- if (logPartPtr.i == 3) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* ALL LOG PARTS ARE COMPLETED. NOW WE CAN CONTINUE WITH THE RESTART */
-/* PROCESSING. THE NEXT STEP IS TO PREPARE FOR EXECUTING OPERATIONS. THUS WE */
-/* NEED TO INITIALISE ALL NEEDED DATA AND TO OPEN FILE ZERO AND THE NEXT AND */
-/* TO SET THE CURRENT LOG PAGE TO BE PAGE 1 IN FILE ZERO. */
-/*---------------------------------------------------------------------------*/
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- ptrAss(logPartPtr, logPartRecord);
- signal->theData[0] = ZINIT_FOURTH;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//for
- return;
- } else {
- jam();
- logPartPtr.i = logPartPtr.i + 1;
- goto CHECK_LOG_PARTS_LOOP;
- }//if
-}//Dblqh::checkInitCompletedLab()
-
-/* ========================================================================= */
-/* ======= INITIATE LOG FILE OPERATION RECORD WHEN ALLOCATED ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initLfo(Signal* signal)
-{
- lfoPtr.p->firstLfoPage = RNIL;
- lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
- lfoPtr.p->logFileRec = logFilePtr.i;
- lfoPtr.p->noPagesRw = 0;
- lfoPtr.p->lfoPageNo = ZNIL;
-}//Dblqh::initLfo()
-
-/* ========================================================================= */
-/* ======= INITIATE LOG FILE WHEN ALLOCATED ======= */
-/* */
-/* INPUT: TFILE_NO NUMBER OF THE FILE INITIATED */
-/* LOG_PART_PTR NUMBER OF LOG PART */
-/* SUBROUTINE SHORT NAME = IL */
-/* ========================================================================= */
-void Dblqh::initLogfile(Signal* signal, Uint32 fileNo)
-{
- UintR tilTmp;
- UintR tilIndex;
-
- logFilePtr.p->currentFilepage = 0;
- logFilePtr.p->currentLogpage = RNIL;
- logFilePtr.p->fileName[0] = (UintR)-1;
- logFilePtr.p->fileName[1] = (UintR)-1; /* = H'FFFFFFFF = -1 */
- logFilePtr.p->fileName[2] = fileNo; /* Sfile_no */
- tilTmp = 1; /* VERSION 1 OF FILE NAME */
- tilTmp = (tilTmp << 8) + 1; /* FRAGMENT LOG => .FRAGLOG AS EXTENSION */
- tilTmp = (tilTmp << 8) + (8 + logPartPtr.i); /* DIRECTORY = D(8+Part)/DBLQH */
- tilTmp = (tilTmp << 8) + 255; /* IGNORE Pxx PART OF FILE NAME */
- logFilePtr.p->fileName[3] = tilTmp;
-/* ========================================================================= */
-/* FILE NAME BECOMES /D2/DBLQH/Tpart_no/Sfile_no.FRAGLOG */
-/* ========================================================================= */
- logFilePtr.p->fileNo = fileNo;
- logFilePtr.p->filePosition = 0;
- logFilePtr.p->firstLfo = RNIL;
- logFilePtr.p->lastLfo = RNIL;
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
- logFilePtr.p->logPartRec = logPartPtr.i;
- logFilePtr.p->noLogpagesInBuffer = 0;
- logFilePtr.p->firstFilledPage = RNIL;
- logFilePtr.p->lastFilledPage = RNIL;
- logFilePtr.p->lastPageWritten = 0;
- logFilePtr.p->logPageZero = RNIL;
- logFilePtr.p->currentMbyte = 0;
- for (tilIndex = 0; tilIndex < clogFileSize; tilIndex++) {
- logFilePtr.p->logMaxGciCompleted[tilIndex] = (UintR)-1;
- logFilePtr.p->logMaxGciStarted[tilIndex] = (UintR)-1;
- logFilePtr.p->logLastPrepRef[tilIndex] = 0;
- }//for
-}//Dblqh::initLogfile()
-
-/* ========================================================================= */
-/* ======= INITIATE LOG PAGE WHEN ALLOCATED ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initLogpage(Signal* signal)
-{
- TcConnectionrecPtr ilpTcConnectptr;
-
- logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = logPartPtr.p->logLap;
- logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED] =
- logPartPtr.p->logPartNewestCompletedGCI;
- logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED] = cnewestGci;
- logPagePtr.p->logPageWord[ZPOS_VERSION] = NDB_VERSION;
- logPagePtr.p->logPageWord[ZPOS_NO_LOG_FILES] = logPartPtr.p->noLogFiles;
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
- ilpTcConnectptr.i = logPartPtr.p->firstLogTcrec;
- if (ilpTcConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(ilpTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
- (ilpTcConnectptr.p->logStartFileNo << 16) +
- (ilpTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE);
- } else {
- jam();
- logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF] =
- (logFilePtr.p->fileNo << 16) +
- (logFilePtr.p->currentFilepage >> ZTWOLOG_NO_PAGES_IN_MBYTE);
- }//if
-}//Dblqh::initLogpage()
-
-/* ------------------------------------------------------------------------- */
-/* ------- OPEN LOG FILE FOR READ AND WRITE ------- */
-/* */
-/* SUBROUTINE SHORT NAME = OFR */
-/* ------------------------------------------------------------------------- */
-void Dblqh::openFileRw(Signal* signal, LogFileRecordPtr olfLogFilePtr)
-{
- FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
- signal->theData[0] = cownref;
- signal->theData[1] = olfLogFilePtr.i;
- signal->theData[2] = olfLogFilePtr.p->fileName[0];
- signal->theData[3] = olfLogFilePtr.p->fileName[1];
- signal->theData[4] = olfLogFilePtr.p->fileName[2];
- signal->theData[5] = olfLogFilePtr.p->fileName[3];
- signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_CHECK_SIZE;
- if (c_o_direct)
- signal->theData[6] |= FsOpenReq::OM_DIRECT;
- req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
- Uint64 sz = clogFileSize;
- sz *= 1024; sz *= 1024;
- req->file_size_hi = sz >> 32;
- req->file_size_lo = sz & 0xFFFFFFFF;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-}//Dblqh::openFileRw()
-
-/* ------------------------------------------------------------------------- */
-/* ------- OPEN LOG FILE DURING INITIAL START ------- */
-/* */
-/* SUBROUTINE SHORT NAME = OLI */
-/* ------------------------------------------------------------------------- */
-void Dblqh::openLogfileInit(Signal* signal)
-{
- logFilePtr.p->logFileStatus = LogFileRecord::OPENING_INIT;
- FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
- signal->theData[0] = cownref;
- signal->theData[1] = logFilePtr.i;
- signal->theData[2] = logFilePtr.p->fileName[0];
- signal->theData[3] = logFilePtr.p->fileName[1];
- signal->theData[4] = logFilePtr.p->fileName[2];
- signal->theData[5] = logFilePtr.p->fileName[3];
- signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE | FsOpenReq::OM_AUTOSYNC;
- if (c_o_direct)
- signal->theData[6] |= FsOpenReq::OM_DIRECT;
- req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-}//Dblqh::openLogfileInit()
-
-/* OPEN FOR READ/WRITE, DO CREATE AND DO TRUNCATE FILE */
-/* ------------------------------------------------------------------------- */
-/* ------- OPEN NEXT LOG FILE ------- */
-/* */
-/* SUBROUTINE SHORT NAME = ONL */
-/* ------------------------------------------------------------------------- */
-void Dblqh::openNextLogfile(Signal* signal)
-{
- LogFileRecordPtr onlLogFilePtr;
-
- if (logPartPtr.p->noLogFiles > 2) {
- jam();
-/* -------------------------------------------------- */
-/* IF ONLY 1 OR 2 LOG FILES EXIST THEN THEY ARE */
-/* ALWAYS OPEN AND THUS IT IS NOT NECESSARY TO */
-/* OPEN THEM NOW. */
-/* -------------------------------------------------- */
- onlLogFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(onlLogFilePtr, clogFileFileSize, logFileRecord);
- if (onlLogFilePtr.p->logFileStatus != LogFileRecord::CLOSED) {
- ndbrequire(onlLogFilePtr.p->fileNo == 0);
- return;
- }//if
- onlLogFilePtr.p->logFileStatus = LogFileRecord::OPENING_WRITE_LOG;
- FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
- signal->theData[0] = cownref;
- signal->theData[1] = onlLogFilePtr.i;
- signal->theData[2] = onlLogFilePtr.p->fileName[0];
- signal->theData[3] = onlLogFilePtr.p->fileName[1];
- signal->theData[4] = onlLogFilePtr.p->fileName[2];
- signal->theData[5] = onlLogFilePtr.p->fileName[3];
- signal->theData[6] = FsOpenReq::OM_READWRITE | FsOpenReq::OM_AUTOSYNC | FsOpenReq::OM_CHECK_SIZE;
- if (c_o_direct)
- signal->theData[6] |= FsOpenReq::OM_DIRECT;
- req->auto_sync_size = MAX_REDO_PAGES_WITHOUT_SYNCH * sizeof(LogPageRecord);
- Uint64 sz = clogFileSize;
- sz *= 1024; sz *= 1024;
- req->file_size_hi = sz >> 32;
- req->file_size_lo = sz & 0xFFFFFFFF;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
- }//if
-}//Dblqh::openNextLogfile()
-
- /* OPEN FOR READ/WRITE, DON'T CREATE AND DON'T TRUNCATE FILE */
-/* ------------------------------------------------------------------------- */
-/* ------- RELEASE LFO RECORD ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::releaseLfo(Signal* signal)
-{
-#ifdef VM_TRACE
- // Check that lfo record isn't already in free list
- LogFileOperationRecordPtr TlfoPtr;
- TlfoPtr.i = cfirstfreeLfo;
- while (TlfoPtr.i != RNIL){
- ptrCheckGuard(TlfoPtr, clfoFileSize, logFileOperationRecord);
- ndbrequire(TlfoPtr.i != lfoPtr.i);
- TlfoPtr.i = TlfoPtr.p->nextLfo;
- }
-#endif
- lfoPtr.p->nextLfo = cfirstfreeLfo;
- lfoPtr.p->lfoTimer = 0;
- cfirstfreeLfo = lfoPtr.i;
- lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
-}//Dblqh::releaseLfo()
-
-/* ------------------------------------------------------------------------- */
-/* ------- RELEASE ALL LOG PAGES CONNECTED TO A LFO RECORD ------- */
-/* */
-/* SUBROUTINE SHORT NAME = RLP */
-/* ------------------------------------------------------------------------- */
-void Dblqh::releaseLfoPages(Signal* signal)
-{
- LogPageRecordPtr rlpLogPagePtr;
-
- logPagePtr.i = lfoPtr.p->firstLfoPage;
-RLP_LOOP:
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- rlpLogPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
- releaseLogpage(signal);
- if (rlpLogPagePtr.i != RNIL) {
- jam();
- logPagePtr.i = rlpLogPagePtr.i;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- goto RLP_LOOP;
- }//if
- lfoPtr.p->firstLfoPage = RNIL;
-}//Dblqh::releaseLfoPages()
-
-/* ------------------------------------------------------------------------- */
-/* ------- RELEASE LOG PAGE ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::releaseLogpage(Signal* signal)
-{
-#ifdef VM_TRACE
- // Check that log page isn't already in free list
- ndbrequire(logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] == 0);
-#endif
-
- cnoOfLogPages++;
- logPagePtr.p->logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage;
- logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
- logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
- cfirstfreeLogPage = logPagePtr.i;
-}//Dblqh::releaseLogpage()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEIZE LFO RECORD ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::seizeLfo(Signal* signal)
-{
- lfoPtr.i = cfirstfreeLfo;
- ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
- cfirstfreeLfo = lfoPtr.p->nextLfo;
- lfoPtr.p->nextLfo = RNIL;
- lfoPtr.p->lfoTimer = cLqhTimeOutCount;
-}//Dblqh::seizeLfo()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEIZE LOG FILE RECORD ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::seizeLogfile(Signal* signal)
-{
- logFilePtr.i = cfirstfreeLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
-/* ------------------------------------------------------------------------- */
-/*IF LIST IS EMPTY THEN A SYSTEM CRASH IS INVOKED SINCE LOG_FILE_PTR = RNIL */
-/* ------------------------------------------------------------------------- */
- cfirstfreeLogFile = logFilePtr.p->nextLogFile;
- logFilePtr.p->nextLogFile = RNIL;
-}//Dblqh::seizeLogfile()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEIZE LOG PAGE RECORD ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::seizeLogpage(Signal* signal)
-{
- cnoOfLogPages--;
- logPagePtr.i = cfirstfreeLogPage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
-/* ------------------------------------------------------------------------- */
-/*IF LIST IS EMPTY THEN A SYSTEM CRASH IS INVOKED SINCE LOG_PAGE_PTR = RNIL */
-/* ------------------------------------------------------------------------- */
- cfirstfreeLogPage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
- logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
- logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] = 0;
-}//Dblqh::seizeLogpage()
-
-/* ------------------------------------------------------------------------- */
-/* ------- WRITE FILE DESCRIPTOR INFORMATION ------- */
-/* */
-/* SUBROUTINE SHORT NAME: WFD */
-// Pointer handling:
-// logFilePtr in
-// logPartPtr in
-/* ------------------------------------------------------------------------- */
-void Dblqh::writeFileDescriptor(Signal* signal)
-{
- TcConnectionrecPtr wfdTcConnectptr;
- UintR twfdFileNo;
- UintR twfdMbyte;
-
-/* -------------------------------------------------- */
-/* START BY WRITING TO LOG FILE RECORD */
-/* -------------------------------------------------- */
- arrGuard(logFilePtr.p->currentMbyte, clogFileSize);
- logFilePtr.p->logMaxGciCompleted[logFilePtr.p->currentMbyte] =
- logPartPtr.p->logPartNewestCompletedGCI;
- logFilePtr.p->logMaxGciStarted[logFilePtr.p->currentMbyte] = cnewestGci;
- wfdTcConnectptr.i = logPartPtr.p->firstLogTcrec;
- if (wfdTcConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(wfdTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- twfdFileNo = wfdTcConnectptr.p->logStartFileNo;
- twfdMbyte = wfdTcConnectptr.p->logStartPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
- logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
- (twfdFileNo << 16) + twfdMbyte;
- } else {
- jam();
- logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
- (logFilePtr.p->fileNo << 16) + logFilePtr.p->currentMbyte;
- }//if
-}//Dblqh::writeFileDescriptor()
-
-/* ------------------------------------------------------------------------- */
-/* ------- WRITE THE HEADER PAGE OF A NEW FILE ------- */
-/* */
-/* SUBROUTINE SHORT NAME: WMO */
-/* ------------------------------------------------------------------------- */
-void Dblqh::writeFileHeaderOpen(Signal* signal, Uint32 wmoType)
-{
- UintR twmoNoLogDescriptors;
-
-/* -------------------------------------------------- */
-/* WRITE HEADER INFORMATION IN THE NEW FILE. */
-/* -------------------------------------------------- */
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_LOG_TYPE] = ZFD_TYPE;
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] =
- logFilePtr.p->fileNo;
- if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
- jam();
- twmoNoLogDescriptors = cmaxLogFilesInPageZero;
- } else {
- jam();
- twmoNoLogDescriptors = logPartPtr.p->noLogFiles;
- }//if
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD] =
- twmoNoLogDescriptors;
-
- {
- Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
- LogFileRecordPtr filePtr = logFilePtr;
- for (Uint32 fd = 0; fd < twmoNoLogDescriptors; fd++)
- {
- jam();
- ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
- for (Uint32 mb = 0; mb < clogFileSize; mb ++)
- {
- jam();
- Uint32 pos0 = pos + fd * (ZFD_MBYTE_SIZE * clogFileSize) + mb;
- Uint32 pos1 = pos0 + clogFileSize;
- Uint32 pos2 = pos1 + clogFileSize;
- arrGuard(pos0, ZPAGE_SIZE);
- arrGuard(pos1, ZPAGE_SIZE);
- arrGuard(pos2, ZPAGE_SIZE);
- logPagePtr.p->logPageWord[pos0] = filePtr.p->logMaxGciCompleted[mb];
- logPagePtr.p->logPageWord[pos1] = filePtr.p->logMaxGciStarted[mb];
- logPagePtr.p->logPageWord[pos2] = filePtr.p->logLastPrepRef[mb];
- }
- filePtr.i = filePtr.p->prevLogFile;
- }
- pos += (twmoNoLogDescriptors * ZFD_MBYTE_SIZE * clogFileSize);
- arrGuard(pos, ZPAGE_SIZE);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = pos;
- logPagePtr.p->logPageWord[pos] = ZNEXT_LOG_RECORD_TYPE;
- }
-
-/* ------------------------------------------------------- */
-/* THIS IS A SPECIAL WRITE OF THE FIRST PAGE IN THE */
-/* LOG FILE. THIS HAS SPECIAL SIGNIFANCE TO FIND */
-/* THE END OF THE LOG AT SYSTEM RESTART. */
-/* ------------------------------------------------------- */
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
- if (wmoType == ZINIT) {
- jam();
- lfoPtr.p->lfoState = LogFileOperationRecord::INIT_FIRST_PAGE;
- } else {
- jam();
- lfoPtr.p->lfoState = LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE;
- }//if
- logFilePtr.p->filePosition = 1;
- if (wmoType == ZNORMAL) {
- jam();
-/* -------------------------------------------------- */
-/* ALLOCATE A NEW PAGE SINCE THE CURRENT IS */
-/* WRITTEN. */
-/* -------------------------------------------------- */
- seizeLogpage(signal);
- initLogpage(signal);
- logFilePtr.p->currentLogpage = logPagePtr.i;
- logFilePtr.p->currentFilepage = logFilePtr.p->currentFilepage + 1;
- }//if
-}//Dblqh::writeFileHeaderOpen()
-
-/* -------------------------------------------------- */
-/* THE NEW FILE POSITION WILL ALWAYS BE 1 SINCE */
-/* WE JUST WROTE THE FIRST PAGE IN THE LOG FILE */
-/* -------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------- WRITE A MBYTE HEADER DURING INITIAL START ------- */
-/* */
-/* SUBROUTINE SHORT NAME: WIM */
-/* ------------------------------------------------------------------------- */
-void Dblqh::writeInitMbyte(Signal* signal)
-{
- initLogpage(signal);
- writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE,
- ZPAGE_SIZE - 1, __LINE__);
- lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_INIT_MBYTE;
-}//Dblqh::writeInitMbyte()
-
-/* ------------------------------------------------------------------------- */
-/* ------- WRITE A SINGLE PAGE INTO A FILE ------- */
-/* */
-/* INPUT: TWSP_PAGE_NO THE PAGE NUMBER WRITTEN */
-/* SUBROUTINE SHORT NAME: WSP */
-/* ------------------------------------------------------------------------- */
-void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo,
- Uint32 wordWritten, Uint32 place)
-{
- seizeLfo(signal);
- initLfo(signal);
- lfoPtr.p->firstLfoPage = logPagePtr.i;
- logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
-
- writeDbgInfoPageHeader(logPagePtr, place, pageNo, wordWritten);
- // Calculate checksum for page
- logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
-
- lfoPtr.p->lfoPageNo = pageNo;
- lfoPtr.p->lfoWordWritten = wordWritten;
- lfoPtr.p->noPagesRw = 1;
-/* -------------------------------------------------- */
-/* SET TIMER ON THIS LOG PART TO SIGNIFY THAT A */
-/* LOG RECORD HAS BEEN SENT AT THIS TIME. */
-/* -------------------------------------------------- */
- logPartPtr.p->logPartTimer = logPartPtr.p->logTimer;
- signal->theData[0] = logFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = lfoPtr.i;
- signal->theData[3] = ZLIST_OF_PAIRS_SYNCH;
- signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
- signal->theData[5] = 1; /* ONE PAGE WRITTEN */
- signal->theData[6] = logPagePtr.i;
- signal->theData[7] = pageNo;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
-
- if (DEBUG_REDO)
- ndbout_c("writeSingle 1 page at part: %u file: %u pos: %u",
- logPartPtr.i,
- logFilePtr.p->fileNo,
- pageNo);
-}//Dblqh::writeSinglePage()
-
-/* ##########################################################################
- * SYSTEM RESTART PHASE ONE MODULE
- * THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
- *
- * THIS MODULE CONTAINS THE CODE FOR THE FIRST PHASE OF THE SYSTEM RESTART.
- * THE AIM OF THIS PHASE IS TO FIND THE END OF THE LOG AND TO FIND
- * INFORMATION ABOUT WHERE GLOBAL CHECKPOINTS ARE COMPLETED AND STARTED
- * IN THE LOG. THIS INFORMATION IS NEEDED TO START PHASE THREE OF
- * THE SYSTEM RESTART.
- * ########################################################################## */
-/* --------------------------------------------------------------------------
- * A SYSTEM RESTART OR NODE RESTART IS ONGOING. WE HAVE NOW OPENED FILE 0
- * NOW WE NEED TO READ PAGE 0 TO FIND WHICH LOG FILE THAT WAS OPEN AT
- * CRASH TIME.
- * -------------------------------------------------------------------------- */
-void Dblqh::openSrFrontpageLab(Signal* signal)
-{
- readSinglePage(signal, 0);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FRONTPAGE;
- return;
-}//Dblqh::openSrFrontpageLab()
-
-/* -------------------------------------------------------------------------
- * WE HAVE NOW READ PAGE 0 IN FILE 0. CHECK THE LAST OPEN FILE. ACTUALLY THE
- * LAST OPEN FILE COULD BE THE NEXT AFTER THAT. CHECK THAT FIRST. WHEN THE
- * LAST WAS FOUND WE CAN FIND ALL THE NEEDED INFORMATION WHERE TO START AND
- * STOP READING THE LOG.
- * -------------------------------------------------------------------------- */
-void Dblqh::readSrFrontpageLab(Signal* signal)
-{
- Uint32 fileNo = logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO];
- if (fileNo == 0) {
- jam();
- /* ----------------------------------------------------------------------
- * FILE 0 WAS ALSO LAST FILE SO WE DO NOT NEED TO READ IT AGAIN.
- * ---------------------------------------------------------------------- */
- readSrLastFileLab(signal);
- return;
- }//if
- /* ------------------------------------------------------------------------
- * CLOSE FILE 0 SO THAT WE HAVE CLOSED ALL FILES WHEN STARTING TO READ
- * THE FRAGMENT LOG. ALSO RELEASE PAGE ZERO.
- * ------------------------------------------------------------------------ */
- releaseLogpage(signal);
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
- closeFile(signal, logFilePtr, __LINE__);
- LogFileRecordPtr locLogFilePtr;
- findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_LAST_FILE;
- openFileRw(signal, locLogFilePtr);
- return;
-}//Dblqh::readSrFrontpageLab()
-
-void Dblqh::openSrLastFileLab(Signal* signal)
-{
- readSinglePage(signal, 0);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_FILE;
- return;
-}//Dblqh::openSrLastFileLab()
-
-void Dblqh::readSrLastFileLab(Signal* signal)
-{
- logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
- if (DEBUG_REDO)
- ndbout_c("readSrLastFileLab part: %u logExecState: %u logPartState: %u logLap: %u",
- logPartPtr.i,
- logPartPtr.p->logExecState,
- logPartPtr.p->logPartState,
- logPartPtr.p->logLap);
- if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
- jam();
- initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
- } else {
- jam();
- initGciInLogFileRec(signal, logPartPtr.p->noLogFiles);
- }//if
- releaseLogpage(signal);
- /* ------------------------------------------------------------------------
- * NOW WE HAVE FOUND THE LAST LOG FILE. WE ALSO NEED TO FIND THE LAST
- * MBYTE THAT WAS LAST WRITTEN BEFORE THE SYSTEM CRASH.
- * ------------------------------------------------------------------------ */
- logPartPtr.p->lastLogfile = logFilePtr.i;
- readSinglePage(signal, 0);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_MBYTE;
- logFilePtr.p->currentMbyte = 0;
- return;
-}//Dblqh::readSrLastFileLab()
-
-void Dblqh::readSrLastMbyteLab(Signal* signal)
-{
- if (logPartPtr.p->lastMbyte == ZNIL) {
- if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] < logPartPtr.p->logLap) {
- jam();
- logPartPtr.p->lastMbyte = logFilePtr.p->currentMbyte - 1;
- }//if
- }//if
- arrGuard(logFilePtr.p->currentMbyte, clogFileSize);
- logFilePtr.p->logMaxGciCompleted[logFilePtr.p->currentMbyte] =
- logPagePtr.p->logPageWord[ZPOS_MAX_GCI_COMPLETED];
- logFilePtr.p->logMaxGciStarted[logFilePtr.p->currentMbyte] =
- logPagePtr.p->logPageWord[ZPOS_MAX_GCI_STARTED];
- logFilePtr.p->logLastPrepRef[logFilePtr.p->currentMbyte] =
- logPagePtr.p->logPageWord[ZLAST_LOG_PREP_REF];
- releaseLogpage(signal);
- if (logFilePtr.p->currentMbyte < (clogFileSize - 1)) {
- jam();
- logFilePtr.p->currentMbyte++;
- readSinglePage(signal, ZPAGES_IN_MBYTE * logFilePtr.p->currentMbyte);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_LAST_MBYTE;
- return;
- } else {
- jam();
- /* ----------------------------------------------------------------------
- * THE LOG WAS IN THE LAST MBYTE WHEN THE CRASH OCCURRED SINCE ALL
- * LOG LAPS ARE EQUAL TO THE CURRENT LOG LAP.
- * ---------------------------------------------------------------------- */
- if (logPartPtr.p->lastMbyte == ZNIL) {
- jam();
- logPartPtr.p->lastMbyte = clogFileSize - 1;
- }//if
- }//if
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
- closeFile(signal, logFilePtr, __LINE__);
- if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) {
- Uint32 fileNo;
- if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
- jam();
- fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
- } else {
- jam();
- fileNo =
- (logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
- cmaxLogFilesInPageZero;
- }//if
- if (fileNo == 0) {
- jam();
- /* --------------------------------------------------------------------
- * AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE
- * MOMENT.
- * -------------------------------------------------------------------- */
- fileNo = 1;
- logPartPtr.p->srRemainingFiles =
- logPartPtr.p->noLogFiles - (cmaxLogFilesInPageZero - 1);
- } else {
- jam();
- logPartPtr.p->srRemainingFiles =
- logPartPtr.p->noLogFiles - cmaxLogFilesInPageZero;
- }//if
- LogFileRecordPtr locLogFilePtr;
- findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
- openFileRw(signal, locLogFilePtr);
- return;
- }//if
- /* ------------------------------------------------------------------------
- * THERE WERE NO NEED TO READ ANY MORE PAGE ZERO IN OTHER FILES.
- * WE NOW HAVE ALL THE NEEDED INFORMATION ABOUT THE GCI'S THAT WE NEED.
- * NOW JUST WAIT FOR CLOSE OPERATIONS TO COMPLETE.
- * ------------------------------------------------------------------------ */
- return;
-}//Dblqh::readSrLastMbyteLab()
-
-void Dblqh::openSrNextFileLab(Signal* signal)
-{
- readSinglePage(signal, 0);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_NEXT_FILE;
- return;
-}//Dblqh::openSrNextFileLab()
-
-void Dblqh::readSrNextFileLab(Signal* signal)
-{
- if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
- jam();
- initGciInLogFileRec(signal, cmaxLogFilesInPageZero);
- } else {
- jam();
- initGciInLogFileRec(signal, logPartPtr.p->srRemainingFiles);
- }//if
- releaseLogpage(signal);
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_SR;
- closeFile(signal, logFilePtr, __LINE__);
- if (logPartPtr.p->srRemainingFiles > cmaxLogFilesInPageZero) {
- Uint32 fileNo;
- if (logFilePtr.p->fileNo >= cmaxLogFilesInPageZero) {
- jam();
- fileNo = logFilePtr.p->fileNo - cmaxLogFilesInPageZero;
- } else {
- jam();
- fileNo =
- (logPartPtr.p->noLogFiles + logFilePtr.p->fileNo) -
- cmaxLogFilesInPageZero;
- }//if
- if (fileNo == 0) {
- jam();
- /* --------------------------------------------------------------------
- * AVOID USING FILE 0 AGAIN SINCE THAT IS PROBABLY CLOSING AT THE MOMENT.
- * -------------------------------------------------------------------- */
- fileNo = 1;
- logPartPtr.p->srRemainingFiles =
- logPartPtr.p->srRemainingFiles - (cmaxLogFilesInPageZero - 1);
- } else {
- jam();
- logPartPtr.p->srRemainingFiles =
- logPartPtr.p->srRemainingFiles - cmaxLogFilesInPageZero;
- }//if
- LogFileRecordPtr locLogFilePtr;
- findLogfile(signal, fileNo, logPartPtr, &locLogFilePtr);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_NEXT_FILE;
- openFileRw(signal, locLogFilePtr);
- }//if
- /* ------------------------------------------------------------------------
- * THERE WERE NO NEED TO READ ANY MORE PAGE ZERO IN OTHER FILES.
- * WE NOW HAVE ALL THE NEEDED INFORMATION ABOUT THE GCI'S THAT WE NEED.
- * NOW JUST WAIT FOR CLOSE OPERATIONS TO COMPLETE.
- * ------------------------------------------------------------------------ */
- return;
-}//Dblqh::readSrNextFileLab()
-
-void Dblqh::closingSrLab(Signal* signal)
-{
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
- logPartPtr.i = logFilePtr.p->logPartRec;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logFilePtr.i = logPartPtr.p->firstLogfile;
- do {
- jam();
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- if (logFilePtr.p->logFileStatus != LogFileRecord::CLOSED) {
- jam();
- /* --------------------------------------------------------------------
- * EXIT AND WAIT FOR REMAINING LOG FILES TO COMPLETE THEIR WORK.
- * -------------------------------------------------------------------- */
- return;
- }//if
- logFilePtr.i = logFilePtr.p->nextLogFile;
- } while (logFilePtr.i != logPartPtr.p->firstLogfile);
- /* ------------------------------------------------------------------------
- * ALL FILES IN THIS PART HAVE BEEN CLOSED. THIS INDICATES THAT THE FIRST
- * PHASE OF THE SYSTEM RESTART HAVE BEEN CONCLUDED FOR THIS LOG PART.
- * CHECK IF ALL OTHER LOG PARTS ARE ALSO COMPLETED.
- * ------------------------------------------------------------------------ */
- logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE_COMPLETED;
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
- if (logPartPtr.p->logPartState != LogPartRecord::SR_FIRST_PHASE_COMPLETED) {
- jam();
- /* --------------------------------------------------------------------
- * EXIT AND WAIT FOR THE REST OF THE LOG PARTS TO COMPLETE.
- * -------------------------------------------------------------------- */
- return;
- }//if
- }//for
- /* ------------------------------------------------------------------------
- * THE FIRST PHASE HAVE BEEN COMPLETED.
- * ------------------------------------------------------------------------ */
- signal->theData[0] = ZSR_PHASE3_START;
- signal->theData[1] = ZSR_PHASE1_COMPLETED;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dblqh::closingSrLab()
-
-/* ##########################################################################
- * ####### SYSTEM RESTART PHASE TWO MODULE #######
- *
- * THIS MODULE HANDLES THE SYSTEM RESTART WHERE LQH CONTROLS TUP AND ACC TO
- * ENSURE THAT THEY HAVE KNOWLEDGE OF ALL FRAGMENTS AND HAVE DONE THE NEEDED
- * READING OF DATA FROM FILE AND EXECUTION OF LOCAL LOGS. THIS PROCESS
- * EXECUTES CONCURRENTLY WITH PHASE ONE OF THE SYSTEM RESTART. THIS PHASE
- * FINDS THE INFORMATION ABOUT THE FRAGMENT LOG NEEDED TO EXECUTE THE FRAGMENT
- * LOG.
- * WHEN TUP AND ACC HAVE PREPARED ALL FRAGMENTS THEN LQH ORDERS THOSE LQH'S
- * THAT ARE RESPONSIBLE TO EXECUTE THE FRAGMENT LOGS TO DO SO. IT IS POSSIBLE
- * THAT ANOTHER NODE EXECUTES THE LOG FOR A FRAGMENT RESIDING AT THIS NODE.
- * ########################################################################## */
-/* ***************>> */
-/* START_FRAGREQ > */
-/* ***************>> */
-void Dblqh::execSTART_FRAGREQ(Signal* signal)
-{
- const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
- jamEntry();
-
- tabptr.i = startFragReq->tableId;
- Uint32 fragId = startFragReq->fragId;
-
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- if (!getFragmentrec(signal, fragId)) {
- startFragRefLab(signal);
- return;
- }//if
- tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
-
- Uint32 lcpNo = startFragReq->lcpNo;
- Uint32 noOfLogNodes = startFragReq->noOfLogNodes;
- Uint32 lcpId = startFragReq->lcpId;
-
- ndbrequire(noOfLogNodes <= 4);
- fragptr.p->fragStatus = Fragrecord::CRASH_RECOVERING;
- fragptr.p->srBlockref = startFragReq->userRef;
- fragptr.p->srUserptr = startFragReq->userPtr;
- fragptr.p->srChkpnr = lcpNo;
- if (lcpNo == (MAX_LCP_STORED - 1)) {
- jam();
- fragptr.p->lcpId[lcpNo] = lcpId;
- } else if (lcpNo < (MAX_LCP_STORED - 1)) {
- jam();
- fragptr.p->lcpId[lcpNo] = lcpId;
- } else {
- ndbrequire(lcpNo == ZNIL);
- jam();
- }//if
- fragptr.p->srNoLognodes = noOfLogNodes;
- fragptr.p->logFlag = Fragrecord::STATE_FALSE;
- fragptr.p->srStatus = Fragrecord::SS_IDLE;
-
- if (noOfLogNodes > 0) {
- jam();
- for (Uint32 i = 0; i < noOfLogNodes; i++) {
- jam();
- fragptr.p->srStartGci[i] = startFragReq->startGci[i];
- fragptr.p->srLastGci[i] = startFragReq->lastGci[i];
- fragptr.p->srLqhLognode[i] = startFragReq->lqhLogNode[i];
- }//for
- fragptr.p->newestGci = startFragReq->lastGci[noOfLogNodes - 1];
- } else {
- fragptr.p->newestGci = cnewestGci;
- }//if
-
- if (lcpNo == ZNIL)
- {
- jam();
- /**
- * THERE WAS NO LOCAL CHECKPOINT AVAILABLE FOR THIS FRAGMENT. WE DO
- * NOT NEED TO READ IN THE LOCAL FRAGMENT.
- */
- /**
- * Or this is not "first" fragment in table
- * RESTORE_LCP_REQ will currently restore all fragments
- */
- c_lcp_complete_fragments.add(fragptr);
-
- signal->theData[0] = tabptr.i;
- signal->theData[1] = fragId;
- sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB);
- c_tup->disk_restart_lcp_id(tabptr.i, fragId, RNIL);
- jamEntry();
- return;
- }
- else
- {
- jam();
- c_tup->disk_restart_lcp_id(tabptr.i, fragId, lcpId);
- jamEntry();
- }
-
- c_lcpId = (c_lcpId == 0 ? lcpId : c_lcpId);
- c_lcpId = (c_lcpId < lcpId ? c_lcpId : lcpId);
- c_lcp_waiting_fragments.add(fragptr);
- if(c_lcp_restoring_fragments.isEmpty())
- send_restore_lcp(signal);
-}//Dblqh::execSTART_FRAGREQ()
-
-void
-Dblqh::send_restore_lcp(Signal * signal)
-{
- c_lcp_waiting_fragments.first(fragptr);
- c_lcp_waiting_fragments.remove(fragptr);
- c_lcp_restoring_fragments.add(fragptr);
-
- RestoreLcpReq* req= (RestoreLcpReq*)signal->getDataPtrSend();
- req->senderData = fragptr.i;
- req->senderRef = reference();
- req->tableId = fragptr.p->tabRef;
- req->fragmentId = fragptr.p->fragId;
- req->lcpNo = fragptr.p->srChkpnr;
- req->lcpId = fragptr.p->lcpId[fragptr.p->srChkpnr];
-
- sendSignal(RESTORE_REF, GSN_RESTORE_LCP_REQ, signal,
- RestoreLcpReq::SignalLength, JBB);
-}
-
-void Dblqh::startFragRefLab(Signal* signal)
-{
- const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
- BlockReference userRef = startFragReq->userRef;
- Uint32 userPtr = startFragReq->userPtr;
- signal->theData[0] = userPtr;
- signal->theData[1] = terrorCode;
- signal->theData[2] = cownNodeid;
- sendSignal(userRef, GSN_START_FRAGREF, signal, 3, JBB);
- return;
-}//Dblqh::startFragRefLab()
-
-void Dblqh::execRESTORE_LCP_REF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
- return;
-}
-
-void Dblqh::execRESTORE_LCP_CONF(Signal* signal)
-{
- jamEntry();
- RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
- fragptr.i = conf->senderData;
- c_fragment_pool.getPtr(fragptr);
-
- c_lcp_restoring_fragments.remove(fragptr);
- c_lcp_complete_fragments.add(fragptr);
-
- /**
- * Disable expand check in ACC
- * before running REDO
- */
- tabptr.i = fragptr.p->tabRef;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
-
- signal->theData[0] = fragptr.p->tabRef;
- signal->theData[1] = fragptr.p->fragId;
- sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB);
-
- if (!c_lcp_waiting_fragments.isEmpty())
- {
- send_restore_lcp(signal);
- return;
- }
-
- if (c_lcp_restoring_fragments.isEmpty() && cstartRecReq == 1)
- {
- jam();
- /* ----------------------------------------------------------------
- * WE HAVE ALSO RECEIVED AN INDICATION THAT NO MORE FRAGMENTS
- * NEEDS RESTART.
- * NOW IT IS TIME TO START EXECUTING THE UNDO LOG.
- * ----------------------------------------------------------------
- * WE ARE NOW IN A POSITION TO ORDER TUP AND ACC TO START
- * EXECUTING THEIR UNDO LOGS. THIS MUST BE DONE BEFORE THE
- * FRAGMENT LOGS CAN BE EXECUTED.
- * ---------------------------------------------------------------- */
- csrExecUndoLogState = EULS_STARTED;
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- lcpPtr.p->m_outstanding = 1;
-
- signal->theData[0] = c_lcpId;
- sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
- return;
- }
-}
-
-/* ***************> */
-/* START_RECREQ > */
-/* ***************> */
-void Dblqh::execSTART_RECREQ(Signal* signal)
-{
- CRASH_INSERTION(5027);
-
- jamEntry();
- StartRecReq * const req = (StartRecReq*)&signal->theData[0];
- cmasterDihBlockref = req->senderRef;
-
- crestartOldestGci = req->keepGci;
- crestartNewestGci = req->lastCompletedGci;
- cnewestGci = req->newestGci;
-
- ndbrequire(req->receivingNodeId == cownNodeid);
-
- cnewestCompletedGci = cnewestGci;
- cstartRecReq = 1;
- for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) {
- ptrAss(logPartPtr, logPartRecord);
- logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
- }//for
- /* ------------------------------------------------------------------------
- * WE HAVE TO SET THE OLDEST AND THE NEWEST GLOBAL CHECKPOINT IDENTITY
- * THAT WILL SURVIVE THIS SYSTEM RESTART. THIS IS NEEDED SO THAT WE CAN
- * SET THE LOG HEAD AND LOG TAIL PROPERLY BEFORE STARTING THE SYSTEM AGAIN.
- * WE ALSO NEED TO SET CNEWEST_GCI TO ENSURE THAT LOG RECORDS ARE EXECUTED
- * WITH A PROPER GCI.
- *------------------------------------------------------------------------ */
-
- if (c_lcp_restoring_fragments.isEmpty())
- {
- jam();
- csrExecUndoLogState = EULS_STARTED;
-
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- lcpPtr.p->m_outstanding = 1;
-
- signal->theData[0] = c_lcpId;
- sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
- }//if
-}//Dblqh::execSTART_RECREQ()
-
-/* ***************>> */
-/* START_RECCONF > */
-/* ***************>> */
-void Dblqh::execSTART_RECCONF(Signal* signal)
-{
- jamEntry();
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- ndbrequire(csrExecUndoLogState == EULS_STARTED);
- ndbrequire(lcpPtr.p->m_outstanding);
-
- Uint32 sender= signal->theData[0];
-
- lcpPtr.p->m_outstanding--;
- if(lcpPtr.p->m_outstanding)
- {
- jam();
- return;
- }
-
- switch(refToBlock(sender)){
- case TSMAN:
- jam();
- break;
- case LGMAN:
- jam();
- lcpPtr.p->m_outstanding++;
- signal->theData[0] = c_lcpId;
- sendSignal(TSMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
- return;
- break;
- default:
- ndbrequire(false);
- }
-
- jam();
- csrExecUndoLogState = EULS_COMPLETED;
-
- if(cstartType == NodeState::ST_INITIAL_NODE_RESTART)
- {
- jam();
- cstartRecReq = 2;
-
- StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend();
- conf->startingNodeId = getOwnNodeId();
- sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal,
- StartRecConf::SignalLength, JBB);
- return;
- }
-
- startExecSr(signal);
-}
-
-/* ***************> */
-/* START_RECREF > */
-/* ***************> */
-void Dblqh::execSTART_RECREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execSTART_RECREF()
-
-/* ***************>> */
-/* START_EXEC_SR > */
-/* ***************>> */
-void Dblqh::execSTART_EXEC_SR(Signal* signal)
-{
- jamEntry();
- fragptr.i = signal->theData[0];
- Uint32 next = RNIL;
-
- if (fragptr.i == RNIL)
- {
- jam();
- /* ----------------------------------------------------------------------
- * NO MORE FRAGMENTS TO START EXECUTING THE LOG ON.
- * SEND EXEC_SRREQ TO ALL LQH TO INDICATE THAT THIS NODE WILL
- * NOT REQUEST ANY MORE FRAGMENTS TO EXECUTE THE FRAGMENT LOG ON.
- * ----------------------------------------------------------------------
- * WE NEED TO SEND THOSE SIGNALS EVEN IF WE HAVE NOT REQUESTED
- * ANY FRAGMENTS PARTICIPATE IN THIS PHASE.
- * --------------------------------------------------------------------- */
- NodeReceiverGroup rg(DBLQH, m_sr_nodes);
- signal->theData[0] = cownNodeid;
- sendSignal(rg, GSN_EXEC_SRREQ, signal, 1, JBB);
- return;
- } else {
- jam();
- c_lcp_complete_fragments.getPtr(fragptr);
- next = fragptr.p->nextList;
-
- if (fragptr.p->srNoLognodes > csrPhasesCompleted)
- {
- jam();
- cnoOutstandingExecFragReq++;
-
- Uint32 index = csrPhasesCompleted;
- arrGuard(index, MAX_LOG_EXEC);
- BlockReference ref = calcLqhBlockRef(fragptr.p->srLqhLognode[index]);
- fragptr.p->srStatus = Fragrecord::SS_STARTED;
-
- /* --------------------------------------------------------------------
- * SINCE WE CAN HAVE SEVERAL LQH NODES PER FRAGMENT WE CALCULATE
- * THE LQH POINTER IN SUCH A WAY THAT WE CAN DEDUCE WHICH OF THE
- * LQH NODES THAT HAS RESPONDED WHEN EXEC_FRAGCONF IS RECEIVED.
- * ------------------------------------------------------------------- */
- ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
- execFragReq->userPtr = fragptr.i;
- execFragReq->userRef = cownref;
- execFragReq->tableId = fragptr.p->tabRef;
- execFragReq->fragId = fragptr.p->fragId;
- execFragReq->startGci = fragptr.p->srStartGci[index];
- execFragReq->lastGci = fragptr.p->srLastGci[index];
- sendSignal(ref, GSN_EXEC_FRAGREQ, signal,
- ExecFragReq::SignalLength, JBB);
-
- }
- signal->theData[0] = next;
- sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
- }//if
- return;
-}//Dblqh::execSTART_EXEC_SR()
-
-/* ***************> */
-/* EXEC_FRAGREQ > */
-/* ***************> */
-/* --------------------------------------------------------------------------
- * THIS SIGNAL IS USED TO REQUEST THAT A FRAGMENT PARTICIPATES IN EXECUTING
- * THE LOG IN THIS NODE.
- * ------------------------------------------------------------------------- */
-void Dblqh::execEXEC_FRAGREQ(Signal* signal)
-{
- ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
- jamEntry();
- tabptr.i = execFragReq->tableId;
- Uint32 fragId = execFragReq->fragId;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- ndbrequire(getFragmentrec(signal, fragId));
-
- ndbrequire(fragptr.p->execSrNoReplicas < 4);
- fragptr.p->execSrBlockref[fragptr.p->execSrNoReplicas] = execFragReq->userRef;
- fragptr.p->execSrUserptr[fragptr.p->execSrNoReplicas] = execFragReq->userPtr;
- fragptr.p->execSrStartGci[fragptr.p->execSrNoReplicas] = execFragReq->startGci;
- fragptr.p->execSrLastGci[fragptr.p->execSrNoReplicas] = execFragReq->lastGci;
- fragptr.p->execSrStatus = Fragrecord::ACTIVE;
- fragptr.p->execSrNoReplicas++;
- cnoFragmentsExecSr++;
- return;
-}//Dblqh::execEXEC_FRAGREQ()
-
-void Dblqh::sendExecFragRefLab(Signal* signal)
-{
- ExecFragReq * const execFragReq = (ExecFragReq *)&signal->theData[0];
- BlockReference retRef = execFragReq->userRef;
- Uint32 retPtr = execFragReq->userPtr;
-
- signal->theData[0] = retPtr;
- signal->theData[1] = terrorCode;
- sendSignal(retRef, GSN_EXEC_FRAGREF, signal, 2, JBB);
- return;
-}//Dblqh::sendExecFragRefLab()
-
-/* ***************>> */
-/* EXEC_FRAGCONF > */
-/* ***************>> */
-void Dblqh::execEXEC_FRAGCONF(Signal* signal)
-{
- jamEntry();
- fragptr.i = signal->theData[0];
- c_fragment_pool.getPtr(fragptr);
- fragptr.p->srStatus = Fragrecord::SS_COMPLETED;
-
- ndbrequire(cnoOutstandingExecFragReq);
- cnoOutstandingExecFragReq--;
- if (fragptr.p->srNoLognodes == csrPhasesCompleted + 1)
- {
- jam();
-
- fragptr.p->logFlag = Fragrecord::STATE_TRUE;
- fragptr.p->fragStatus = Fragrecord::FSACTIVE;
-
- signal->theData[0] = fragptr.p->srUserptr;
- signal->theData[1] = cownNodeid;
- sendSignal(fragptr.p->srBlockref, GSN_START_FRAGCONF, signal, 2, JBB);
- }
-
- return;
-}//Dblqh::execEXEC_FRAGCONF()
-
-/* ***************> */
-/* EXEC_FRAGREF > */
-/* ***************> */
-void Dblqh::execEXEC_FRAGREF(Signal* signal)
-{
- jamEntry();
- terrorCode = signal->theData[1];
- systemErrorLab(signal, __LINE__);
- return;
-}//Dblqh::execEXEC_FRAGREF()
-
-/* *************** */
-/* EXEC_SRCONF > */
-/* *************** */
-void Dblqh::execEXEC_SRCONF(Signal* signal)
-{
- jamEntry();
- Uint32 nodeId = signal->theData[0];
- arrGuard(nodeId, MAX_NDB_NODES);
- m_sr_exec_sr_conf.set(nodeId);
-
- if (!m_sr_nodes.equal(m_sr_exec_sr_conf))
- {
- jam();
- /* ------------------------------------------------------------------
- * ALL NODES HAVE NOT REPORTED COMPLETION OF EXECUTING FRAGMENT
- * LOGS YET.
- * ----------------------------------------------------------------- */
- return;
- }
-
- /* ------------------------------------------------------------------------
- * CLEAR NODE SYSTEM RESTART EXECUTION STATE TO PREPARE FOR NEXT PHASE OF
- * LOG EXECUTION.
- * ----------------------------------------------------------------------- */
- m_sr_exec_sr_conf.clear();
-
- /* ------------------------------------------------------------------------
- * NOW CHECK IF ALL FRAGMENTS IN THIS PHASE HAVE COMPLETED. IF SO START THE
- * NEXT PHASE.
- * ----------------------------------------------------------------------- */
- ndbrequire(cnoOutstandingExecFragReq == 0);
-
- execSrCompletedLab(signal);
- return;
-}//Dblqh::execEXEC_SRCONF()
-
-void Dblqh::execSrCompletedLab(Signal* signal)
-{
- csrPhasesCompleted++;
- /* ------------------------------------------------------------------------
- * ALL FRAGMENTS WERE COMPLETED. THIS PHASE IS COMPLETED. IT IS NOW TIME TO
- * START THE NEXT PHASE.
- * ----------------------------------------------------------------------- */
- if (csrPhasesCompleted >= 4) {
- jam();
- /* ----------------------------------------------------------------------
- * THIS WAS THE LAST PHASE. WE HAVE NOW COMPLETED THE EXECUTION THE
- * FRAGMENT LOGS IN ALL NODES. BEFORE WE SEND START_RECCONF TO THE
- * MASTER DIH TO INDICATE A COMPLETED SYSTEM RESTART IT IS NECESSARY
- * TO FIND THE HEAD AND THE TAIL OF THE LOG WHEN NEW OPERATIONS START
- * TO COME AGAIN.
- *
- * THE FIRST STEP IS TO FIND THE HEAD AND TAIL MBYTE OF EACH LOG PART.
- * TO DO THIS WE REUSE THE CONTINUEB SIGNAL SR_LOG_LIMITS. THEN WE
- * HAVE TO FIND THE ACTUAL PAGE NUMBER AND PAGE INDEX WHERE TO
- * CONTINUE WRITING THE LOG AFTER THE SYSTEM RESTART.
- * --------------------------------------------------------------------- */
- for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
- logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_STARTED;
- logPartPtr.p->logLastGci = crestartNewestGci;
- logPartPtr.p->logStartGci = crestartOldestGci;
- logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
- if (logPartPtr.p->headFileNo == ZNIL) {
- jam();
- /* -----------------------------------------------------------------
- * IF WE HAVEN'T FOUND ANY HEAD OF THE LOG THEN WE ARE IN SERIOUS
- * PROBLEM. THIS SHOULD NOT OCCUR. IF IT OCCURS ANYWAY THEN WE
- * HAVE TO FIND A CURE FOR THIS PROBLEM.
- * ----------------------------------------------------------------- */
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- signal->theData[0] = ZSR_LOG_LIMITS;
- signal->theData[1] = logPartPtr.i;
- signal->theData[2] = logPartPtr.p->lastLogfile;
- signal->theData[3] = logPartPtr.p->lastMbyte;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- }//for
- return;
- } else {
- jam();
- /* ----------------------------------------------------------------------
- * THERE ARE YET MORE PHASES TO RESTART.
- * WE MUST INITIALISE DATA FOR NEXT PHASE AND SEND START SIGNAL.
- * --------------------------------------------------------------------- */
- csrPhaseStarted = ZSR_PHASE1_COMPLETED; // Set correct state first...
- startExecSr(signal);
- }//if
- return;
-}//Dblqh::execSrCompletedLab()
-
-/* ************>> */
-/* EXEC_SRREQ > */
-/* ************>> */
-void Dblqh::execEXEC_SRREQ(Signal* signal)
-{
- jamEntry();
- Uint32 nodeId = signal->theData[0];
- ndbrequire(nodeId < MAX_NDB_NODES);
- m_sr_exec_sr_req.set(nodeId);
- if (!m_sr_exec_sr_req.equal(m_sr_nodes))
- {
- jam();
- return;
- }
-
- /* ------------------------------------------------------------------------
- * CLEAR NODE SYSTEM RESTART STATE TO PREPARE FOR NEXT PHASE OF LOG
- * EXECUTION
- * ----------------------------------------------------------------------- */
- m_sr_exec_sr_req.clear();
-
- if (csrPhasesCompleted != 0) {
- /* ----------------------------------------------------------------------
- * THE FIRST PHASE MUST ALWAYS EXECUTE THE LOG.
- * --------------------------------------------------------------------- */
- if (cnoFragmentsExecSr == 0) {
- jam();
- /* --------------------------------------------------------------------
- * THERE WERE NO FRAGMENTS THAT NEEDED TO EXECUTE THE LOG IN THIS PHASE.
- * ------------------------------------------------------------------- */
- srPhase3Comp(signal);
- return;
- }//if
- }//if
- /* ------------------------------------------------------------------------
- * NOW ALL NODES HAVE SENT ALL EXEC_FRAGREQ. NOW WE CAN START EXECUTING THE
- * LOG FROM THE MINIMUM GCI NEEDED UNTIL THE MAXIMUM GCI NEEDED.
- *
- * WE MUST FIRST CHECK IF THE FIRST PHASE OF THE SYSTEM RESTART HAS BEEN
- * COMPLETED. THIS HANDLING IS PERFORMED IN THE FILE SYSTEM MODULE
- * ----------------------------------------------------------------------- */
- signal->theData[0] = ZSR_PHASE3_START;
- signal->theData[1] = ZSR_PHASE2_COMPLETED;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dblqh::execEXEC_SRREQ()
-
-/* ######################################################################### */
-/* SYSTEM RESTART PHASE THREE MODULE */
-/* THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING. */
-/* */
-/* THIS MODULE IS CONCERNED WITH EXECUTING THE FRAGMENT LOG. IT DOES ALSO */
-/* CONTAIN SIGNAL RECEPTIONS LQHKEYCONF AND LQHKEYREF SINCE LQHKEYREQ IS USED*/
-/* TO EXECUTE THE LOG RECORDS. */
-/* */
-/* BEFORE IT STARTS IT HAS BEEN DECIDED WHERE TO START AND WHERE TO STOP */
-/* READING THE FRAGMENT LOG BY USING THE INFORMATION ABOUT GCI DISCOVERED IN */
-/* PHASE ONE OF THE SYSTEM RESTART. */
-/* ######################################################################### */
-/*---------------------------------------------------------------------------*/
-/* PHASE THREE OF THE SYSTEM RESTART CAN NOW START. ONE OF THE PHASES HAVE */
-/* COMPLETED. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::srPhase3Start(Signal* signal)
-{
- UintR tsrPhaseStarted;
-
- jamEntry();
-
- tsrPhaseStarted = signal->theData[1];
- if (csrPhaseStarted == ZSR_NO_PHASE_STARTED) {
- jam();
- csrPhaseStarted = tsrPhaseStarted;
- return;
- }//if
- ndbrequire(csrPhaseStarted != tsrPhaseStarted);
- ndbrequire(csrPhaseStarted != ZSR_BOTH_PHASES_STARTED);
-
- csrPhaseStarted = ZSR_BOTH_PHASES_STARTED;
- for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
- logPartPtr.p->logPartState = LogPartRecord::SR_THIRD_PHASE_STARTED;
- logPartPtr.p->logStartGci = (UintR)-1;
- if (csrPhasesCompleted == 0) {
- jam();
- /* --------------------------------------------------------------------
- * THE FIRST PHASE WE MUST ENSURE THAT IT REACHES THE END OF THE LOG.
- * ------------------------------------------------------------------- */
- logPartPtr.p->logLastGci = crestartNewestGci;
- } else {
- jam();
- logPartPtr.p->logLastGci = 2;
- }//if
- }//for
-
- jam();
- c_lcp_complete_fragments.first(fragptr);
- signal->theData[0] = ZSR_GCI_LIMITS;
- signal->theData[1] = fragptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dblqh::srPhase3Start()
-
-/* --------------------------------------------------------------------------
- * WE NOW WE NEED TO FIND THE LIMITS WITHIN WHICH TO EXECUTE
- * THE FRAGMENT LOG
- * ------------------------------------------------------------------------- */
-void Dblqh::srGciLimits(Signal* signal)
-{
- jamEntry();
- fragptr.i = signal->theData[0];
- Uint32 loopCount = 0;
- logPartPtr.i = 0;
- ptrAss(logPartPtr, logPartRecord);
- while (fragptr.i != RNIL){
- jam();
- c_lcp_complete_fragments.getPtr(fragptr);
- ndbrequire(fragptr.p->execSrNoReplicas - 1 < 4);
- for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
- jam();
- if (fragptr.p->execSrStartGci[i] < logPartPtr.p->logStartGci) {
- jam();
- logPartPtr.p->logStartGci = fragptr.p->execSrStartGci[i];
- }//if
- if (fragptr.p->execSrLastGci[i] > logPartPtr.p->logLastGci) {
- jam();
- logPartPtr.p->logLastGci = fragptr.p->execSrLastGci[i];
- }
- }
-
- loopCount++;
- if (loopCount > 20) {
- jam();
- signal->theData[0] = ZSR_GCI_LIMITS;
- signal->theData[1] = fragptr.p->nextList;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
- } else {
- jam();
- fragptr.i = fragptr.p->nextList;
- }//if
- }
-
- for(Uint32 i = 1; i<4; i++)
- {
- LogPartRecordPtr tmp;
- tmp.i = i;
- ptrAss(tmp, logPartRecord);
- tmp.p->logStartGci = logPartPtr.p->logStartGci;
- tmp.p->logLastGci = logPartPtr.p->logLastGci;
- }
-
- if (logPartPtr.p->logStartGci == (UintR)-1) {
- jam();
- /* --------------------------------------------------------------------
- * THERE WERE NO FRAGMENTS TO INSTALL WE WILL EXECUTE THE LOG AS
- * SHORT AS POSSIBLE TO REACH THE END OF THE LOG. THIS WE DO BY
- * STARTING AT THE STOP GCI.
- * ------------------------------------------------------------------- */
- logPartPtr.p->logStartGci = logPartPtr.p->logLastGci;
- }//if
-
- for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
- logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_STOP;
- signal->theData[0] = ZSR_LOG_LIMITS;
- signal->theData[1] = logPartPtr.i;
- signal->theData[2] = logPartPtr.p->lastLogfile;
- signal->theData[3] = logPartPtr.p->lastMbyte;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- }//for
-}//Dblqh::srGciLimits()
-
-/* --------------------------------------------------------------------------
- * IT IS NOW TIME TO FIND WHERE TO START EXECUTING THE LOG.
- * THIS SIGNAL IS SENT FOR EACH LOG PART AND STARTS THE EXECUTION
- * OF THE LOG FOR THIS PART.
- *-------------------------------------------------------------------------- */
-void Dblqh::srLogLimits(Signal* signal)
-{
- Uint32 tlastPrepRef;
- Uint32 tmbyte;
-
- jamEntry();
- logPartPtr.i = signal->theData[0];
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logFilePtr.i = signal->theData[1];
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- tmbyte = signal->theData[2];
- Uint32 loopCount = 0;
- /* ------------------------------------------------------------------------
- * WE ARE SEARCHING FOR THE START AND STOP MBYTE OF THE LOG THAT IS TO BE
- * EXECUTED.
- * ----------------------------------------------------------------------- */
- while(true) {
- ndbrequire(tmbyte < clogFileSize);
- if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP) {
- if (logFilePtr.p->logMaxGciCompleted[tmbyte] <= logPartPtr.p->logLastGci) {
- jam();
- /* --------------------------------------------------------------------
- * WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST
- * MBYTE WHICH IS TO BE INCLUDED IN THE LOG EXECUTION. THE STOP GCI
- * HAS NOT BEEN COMPLETED BEFORE THIS MBYTE. THUS THIS MBYTE HAVE
- * TO BE EXECUTED.
- * ------------------------------------------------------------------- */
- logPartPtr.p->stopLogfile = logFilePtr.i;
- logPartPtr.p->stopMbyte = tmbyte;
- logPartPtr.p->logExecState = LogPartRecord::LES_SEARCH_START;
- }//if
- }//if
- /* ------------------------------------------------------------------------
- * WHEN WE HAVEN'T FOUND THE STOP MBYTE IT IS NOT NECESSARY TO LOOK FOR THE
- * START MBYTE. THE REASON IS THE FOLLOWING LOGIC CHAIN:
- * MAX_GCI_STARTED >= MAX_GCI_COMPLETED >= LAST_GCI >= START_GCI
- * THUS MAX_GCI_STARTED >= START_GCI. THUS MAX_GCI_STARTED < START_GCI CAN
- * NOT BE TRUE AS WE WILL CHECK OTHERWISE.
- * ----------------------------------------------------------------------- */
- if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_START) {
- if (logFilePtr.p->logMaxGciStarted[tmbyte] < logPartPtr.p->logStartGci) {
- jam();
- /* --------------------------------------------------------------------
- * WE HAVE NOW FOUND THE START OF THE EXECUTION OF THE LOG.
- * WE STILL HAVE TO MOVE IT BACKWARDS TO ALSO INCLUDE THE
- * PREPARE RECORDS WHICH WERE STARTED IN A PREVIOUS MBYTE.
- * ------------------------------------------------------------------- */
- tlastPrepRef = logFilePtr.p->logLastPrepRef[tmbyte];
- logPartPtr.p->startMbyte = tlastPrepRef & 65535;
- LogFileRecordPtr locLogFilePtr;
- findLogfile(signal, tlastPrepRef >> 16, logPartPtr, &locLogFilePtr);
- logPartPtr.p->startLogfile = locLogFilePtr.i;
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
- }//if
- }//if
- if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG) {
- if (tmbyte == 0) {
- jam();
- tmbyte = clogFileSize - 1;
- logFilePtr.i = logFilePtr.p->prevLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- } else {
- jam();
- tmbyte--;
- }//if
- if (logPartPtr.p->lastLogfile == logFilePtr.i) {
- ndbrequire(logPartPtr.p->lastMbyte != tmbyte);
- }//if
- if (loopCount > 20) {
- jam();
- signal->theData[0] = ZSR_LOG_LIMITS;
- signal->theData[1] = logPartPtr.i;
- signal->theData[2] = logFilePtr.i;
- signal->theData[3] = tmbyte;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- return;
- }//if
- loopCount++;
- } else {
- jam();
- break;
- }//if
- }//while
-
- if (DEBUG_REDO)
- {
- LogFileRecordPtr tmp;
- tmp.i = logPartPtr.p->stopLogfile;
- ptrCheckGuard(tmp, clogFileFileSize, logFileRecord);
- ndbout_c("srLogLimits part: %u start file: %u mb: %u stop file: %u mb: %u",
- logPartPtr.i,
- tlastPrepRef >> 16,
- tlastPrepRef & 65535,
- tmp.p->fileNo,
- logPartPtr.p->stopMbyte);
- }
-
- /* ------------------------------------------------------------------------
- * WE HAVE NOW FOUND BOTH THE START AND THE STOP OF THE LOG. NOW START
- * EXECUTING THE LOG. THE FIRST ACTION IS TO OPEN THE LOG FILE WHERE TO
- * START EXECUTING THE LOG.
- * ----------------------------------------------------------------------- */
- if (logPartPtr.p->logPartState == LogPartRecord::SR_THIRD_PHASE_STARTED) {
- jam();
- logFilePtr.i = logPartPtr.p->startLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_SR_START;
- openFileRw(signal, logFilePtr);
- } else {
- jam();
- ndbrequire(logPartPtr.p->logPartState == LogPartRecord::SR_FOURTH_PHASE_STARTED);
- /* --------------------------------------------------------------------
- * WE HAVE NOW FOUND THE TAIL MBYTE IN THE TAIL FILE.
- * SET THOSE PARAMETERS IN THE LOG PART.
- * WE HAVE ALSO FOUND THE HEAD MBYTE. WE STILL HAVE TO SEARCH
- * FOR THE PAGE NUMBER AND PAGE INDEX WHERE TO SET THE HEAD.
- * ------------------------------------------------------------------- */
- logFilePtr.i = logPartPtr.p->startLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPartPtr.p->logTailFileNo = logFilePtr.p->fileNo;
- logPartPtr.p->logTailMbyte = logPartPtr.p->startMbyte;
- /* --------------------------------------------------------------------
- * THE HEAD WE ACTUALLY FOUND DURING EXECUTION OF LOG SO WE USE
- * THIS INFO HERE RATHER THAN THE MBYTE WE FOUND TO BE THE HEADER.
- * ------------------------------------------------------------------- */
- LogFileRecordPtr locLogFilePtr;
- findLogfile(signal, logPartPtr.p->headFileNo, logPartPtr, &locLogFilePtr);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_PHASE;
- openFileRw(signal, locLogFilePtr);
- }//if
- return;
-}//Dblqh::srLogLimits()
-
-void Dblqh::openExecSrStartLab(Signal* signal)
-{
- logPartPtr.p->currentLogfile = logFilePtr.i;
- logFilePtr.p->currentMbyte = logPartPtr.p->startMbyte;
- /* ------------------------------------------------------------------------
- * WE NEED A TC CONNECT RECORD TO HANDLE EXECUTION OF LOG RECORDS.
- * ------------------------------------------------------------------------ */
- seizeTcrec();
- logPartPtr.p->logTcConrec = tcConnectptr.i;
- /* ------------------------------------------------------------------------
- * THE FIRST LOG RECORD TO EXECUTE IS ALWAYS AT A NEW MBYTE.
- * SET THE NUMBER OF PAGES IN THE MAIN MEMORY BUFFER TO ZERO AS AN INITIAL
- * VALUE. THIS VALUE WILL BE UPDATED AND ENSURED THAT IT RELEASES PAGES IN
- * THE SUBROUTINE READ_EXEC_SR.
- * ----------------------------------------------------------------------- */
- logPartPtr.p->mmBufferSize = 0;
- readExecSrNewMbyte(signal);
- return;
-}//Dblqh::openExecSrStartLab()
-
-/* ---------------------------------------------------------------------------
- * WE WILL ALWAYS ENSURE THAT WE HAVE AT LEAST 16 KBYTE OF LOG PAGES WHEN WE
- * START READING A LOG RECORD. THE ONLY EXCEPTION IS WHEN WE COME CLOSE TO A
- * MBYTE BOUNDARY. SINCE WE KNOW THAT LOG RECORDS ARE NEVER WRITTEN ACROSS A
- * MBYTE BOUNDARY THIS IS NOT A PROBLEM.
- *
- * WE START BY READING 64 KBYTE BEFORE STARTING TO EXECUTE THE LOG RECORDS.
- * WHEN WE COME BELOW 64 KBYTE WE READ ANOTHER SET OF LOG PAGES. WHEN WE
- * GO BELOW 16 KBYTE WE WAIT UNTIL THE READ PAGES HAVE ENTERED THE BLOCK.
- * ------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------
- * NEW PAGES FROM LOG FILE DURING EXECUTION OF LOG HAS ARRIVED.
- * ------------------------------------------------------------------------- */
-void Dblqh::readExecSrLab(Signal* signal)
-{
- buildLinkedLogPageList(signal);
- /* ------------------------------------------------------------------------
- * WE NEED TO SET THE CURRENT PAGE INDEX OF THE FIRST PAGE SINCE IT CAN BE
- * USED IMMEDIATELY WITHOUT ANY OTHER INITIALISATION. THE REST OF THE PAGES
- * WILL BE INITIALISED BY READ_LOGWORD.
- * ----------------------------------------------------------------------- */
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
- if (logPartPtr.p->logExecState ==
- LogPartRecord::LES_WAIT_READ_EXEC_SR_NEW_MBYTE) {
- jam();
- /* ----------------------------------------------------------------------
- * THIS IS THE FIRST READ DURING THE EXECUTION OF THIS MBYTE. SET THE
- * NEW CURRENT LOG PAGE TO THE FIRST OF THESE PAGES. CHANGE
- * LOG_EXEC_STATE TO ENSURE THAT WE START EXECUTION OF THE LOG.
- * --------------------------------------------------------------------- */
- logFilePtr.p->currentFilepage = logFilePtr.p->currentMbyte *
- ZPAGES_IN_MBYTE;
- logPartPtr.p->prevFilepage = logFilePtr.p->currentFilepage;
- logFilePtr.p->currentLogpage = lfoPtr.p->firstLfoPage;
- logPartPtr.p->prevLogpage = logFilePtr.p->currentLogpage;
- }//if
- moveToPageRef(signal);
- releaseLfo(signal);
- /* ------------------------------------------------------------------------
- * NOW WE HAVE COMPLETED THE RECEPTION OF THESE PAGES.
- * NOW CHECK IF WE NEED TO READ MORE PAGES.
- * ----------------------------------------------------------------------- */
- checkReadExecSr(signal);
- if (logPartPtr.p->logExecState == LogPartRecord::LES_EXEC_LOG) {
- jam();
- signal->theData[0] = ZEXEC_SR;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
- }//if
- return;
-}//Dblqh::readExecSrLab()
-
-void Dblqh::openExecSrNewMbyteLab(Signal* signal)
-{
- readExecSrNewMbyte(signal);
- return;
-}//Dblqh::openExecSrNewMbyteLab()
-
-void Dblqh::closeExecSrLab(Signal* signal)
-{
- LogFileRecordPtr locLogFilePtr;
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
- logPartPtr.i = logFilePtr.p->logPartRec;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- locLogFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE;
- openFileRw(signal, locLogFilePtr);
- return;
-}//Dblqh::closeExecSrLab()
-
-void Dblqh::writeDirtyLab(Signal* signal)
-{
- releaseLfo(signal);
- signal->theData[0] = logPartPtr.i;
- execSr(signal);
- return;
-}//Dblqh::writeDirtyLab()
-
-/* --------------------------------------------------------------------------
- * EXECUTE A LOG RECORD WITHIN THE CURRENT MBYTE.
- * ------------------------------------------------------------------------- */
-void Dblqh::execSr(Signal* signal)
-{
- LogFileRecordPtr nextLogFilePtr;
- LogPageRecordPtr tmpLogPagePtr;
- Uint32 logWord;
- Uint32 line;
- const char * crash_msg = 0;
-
- jamEntry();
- logPartPtr.i = signal->theData[0];
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
-
- do {
- jam();
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logPartPtr.p->prevLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- if (logPagePtr.p->logPageWord[ZPOS_DIRTY] == ZDIRTY) {
- jam();
- switch (logPartPtr.p->logExecState) {
- case LogPartRecord::LES_EXEC_LOG_COMPLETED:
- case LogPartRecord::LES_EXEC_LOG_NEW_FILE:
- case LogPartRecord::LES_EXEC_LOG_NEW_MBYTE:
- jam();
- /* ------------------------------------------------------------------
- * IN THIS WE HAVE COMPLETED EXECUTION OF THE CURRENT LOG PAGE
- * AND CAN WRITE IT TO DISK SINCE IT IS DIRTY.
- * ----------------------------------------------------------------- */
- writeDirty(signal, __LINE__);
- return;
- break;
- case LogPartRecord::LES_EXEC_LOG:
- jam();
- /* --------------------------------------------------------------------
- * IN THIS CASE WE ONLY WRITE THE PAGE TO DISK IF WE HAVE COMPLETED
- * EXECUTION OF LOG RECORDS BELONGING TO THIS LOG PAGE.
- * ------------------------------------------------------------------- */
- if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
- jam();
- writeDirty(signal, __LINE__);
- return;
- }//if
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- }//if
- if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
- jam();
- logPartPtr.p->prevLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
- logPartPtr.p->prevFilepage++;
- continue;
- }//if
- switch (logPartPtr.p->logExecState) {
- case LogPartRecord::LES_EXEC_LOG_COMPLETED:
- jam();
- releaseMmPages(signal);
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_SR_COMPLETED;
- closeFile(signal, logFilePtr, __LINE__);
- return;
- break;
- case LogPartRecord::LES_EXEC_LOG_NEW_MBYTE:
- jam();
- logFilePtr.p->currentMbyte++;
- readExecSrNewMbyte(signal);
- return;
- break;
- case LogPartRecord::LES_EXEC_LOG_NEW_FILE:
- jam();
- nextLogFilePtr.i = logFilePtr.p->nextLogFile;
- logPartPtr.p->currentLogfile = nextLogFilePtr.i;
- ptrCheckGuard(nextLogFilePtr, clogFileFileSize, logFileRecord);
- nextLogFilePtr.p->currentMbyte = 0;
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_SR;
- closeFile(signal, logFilePtr, __LINE__);
- return;
- break;
- case LogPartRecord::LES_EXEC_LOG:
- jam();
- /*empty*/;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPartPtr.p->savePageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- if (logPartPtr.p->execSrPagesRead < ZMIN_READ_BUFFER_SIZE) {
- /* --------------------------------------------------------------------
- * THERE WERE LESS THAN 16 KBYTE OF LOG PAGES REMAINING. WE WAIT UNTIL
- * THE NEXT 64 KBYTE ARRIVES UNTIL WE CONTINUE AGAIN.
- * ------------------------------------------------------------------- */
- if ((logPartPtr.p->execSrPagesRead +
- logPartPtr.p->execSrPagesExecuted) < ZPAGES_IN_MBYTE) {
- jam();
- /* ------------------------------------------------------------------
- * WE ONLY STOP AND WAIT IF THERE MORE PAGES TO READ. IF IT IS NOT
- * THEN IT IS THE END OF THE MBYTE AND WE WILL CONTINUE. IT IS NO
- * RISK THAT A LOG RECORD WE FIND WILL NOT BE READ AT THIS TIME
- * SINCE THE LOG RECORDS NEVER SPAN OVER A MBYTE BOUNDARY.
- * ----------------------------------------------------------------- */
- readExecSr(signal);
- logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR;
- return;
- }//if
- }//if
- logWord = readLogword(signal);
- switch (logWord) {
-/* ========================================================================= */
-/* ========================================================================= */
- case ZPREP_OP_TYPE:
- {
- logWord = readLogword(signal);
- stepAhead(signal, logWord - 2);
- break;
- }
-/* ========================================================================= */
-/* ========================================================================= */
- case ZINVALID_COMMIT_TYPE:
- jam();
- stepAhead(signal, ZCOMMIT_LOG_SIZE - 1);
- break;
-/* ========================================================================= */
-/* ========================================================================= */
- case ZCOMMIT_TYPE:
- {
- CommitLogRecord commitLogRecord;
- jam();
- tcConnectptr.i = logPartPtr.p->logTcConrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- readCommitLog(signal, &commitLogRecord);
- if (tcConnectptr.p->gci > crestartNewestGci) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS LOG RECORD MUST BE IGNORED. IT IS PART OF A GLOBAL CHECKPOINT WHICH */
-/* WILL BE INVALIDATED BY THE SYSTEM RESTART. IF NOT INVALIDATED IT MIGHT BE */
-/* EXECUTED IN A FUTURE SYSTEM RESTART. */
-/*---------------------------------------------------------------------------*/
- tmpLogPagePtr.i = logPartPtr.p->prevLogpage;
- ptrCheckGuard(tmpLogPagePtr, clogPageFileSize, logPageRecord);
- arrGuard(logPartPtr.p->savePageIndex, ZPAGE_SIZE);
- tmpLogPagePtr.p->logPageWord[logPartPtr.p->savePageIndex] =
- ZINVALID_COMMIT_TYPE;
- tmpLogPagePtr.p->logPageWord[ZPOS_DIRTY] = ZDIRTY;
- } else {
- jam();
-/*---------------------------------------------------------------------------*/
-/* CHECK IF I AM SUPPOSED TO EXECUTE THIS LOG RECORD. IF I AM THEN SAVE PAGE */
-/* INDEX IN CURRENT LOG PAGE SINCE IT WILL BE OVERWRITTEN WHEN EXECUTING THE */
-/* LOG RECORD. */
-/*---------------------------------------------------------------------------*/
- logPartPtr.p->execSrExecuteIndex = 0;
- Uint32 result = checkIfExecLog(signal);
- if (result == ZOK) {
- jam();
-//*---------------------------------------------------------------------------*/
-/* IN A NODE RESTART WE WILL NEVER END UP HERE SINCE NO FRAGMENTS HAVE BEEN */
-/* DEFINED YET. THUS NO EXTRA CHECKING FOR NODE RESTART IS NECESSARY. */
-/*---------------------------------------------------------------------------*/
- logPartPtr.p->savePageIndex =
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- tcConnectptr.p->fragmentptr = fragptr.i;
- findPageRef(signal, &commitLogRecord);
- logPartPtr.p->execSrLogPageIndex = commitLogRecord.startPageIndex;
- if (logPagePtr.i != RNIL) {
- jam();
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = commitLogRecord.startPageIndex;
- logPartPtr.p->execSrLogPage = logPagePtr.i;
- execLogRecord(signal);
- return;
- }//if
- logPartPtr.p->execSrStartPageNo = commitLogRecord.startPageNo;
- logPartPtr.p->execSrStopPageNo = commitLogRecord.stopPageNo;
- findLogfile(signal, commitLogRecord.fileNo, logPartPtr, &logFilePtr);
- logPartPtr.p->execSrExecLogFile = logFilePtr.i;
- if (logFilePtr.i == logPartPtr.p->currentLogfile) {
- jam();
- readExecLog(signal);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
- return;
- } else {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THE FILE IS CURRENTLY NOT OPEN. WE MUST OPEN IT BEFORE WE CAN READ FROM */
-/* THE FILE. */
-/*---------------------------------------------------------------------------*/
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN_EXEC_LOG;
- openFileRw(signal, logFilePtr);
- return;
- }//if
- }//if
- }//if
- break;
- }
-/* ========================================================================= */
-/* ========================================================================= */
- case ZABORT_TYPE:
- jam();
- stepAhead(signal, ZABORT_LOG_SIZE - 1);
- break;
-/* ========================================================================= */
-/* ========================================================================= */
- case ZFD_TYPE:
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS IS THE FIRST ITEM WE ENCOUNTER IN A NEW FILE. AT THIS MOMENT WE SHALL*/
-/* SIMPLY BYPASS IT. IT HAS NO SIGNIFANCE WHEN EXECUTING THE LOG. IT HAS ITS */
-/* SIGNIFANCE WHEN FINDING THE START END THE END OF THE LOG. */
-/* WE HARDCODE THE PAGE INDEX SINCE THIS SHOULD NEVER BE FOUND AT ANY OTHER */
-/* PLACE THAN IN THE FIRST PAGE OF A NEW FILE IN THE FIRST POSITION AFTER THE*/
-/* HEADER. */
-/*---------------------------------------------------------------------------*/
- if (unlikely(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] !=
- (ZPAGE_HEADER_SIZE + ZPOS_NO_FD)))
- {
- line = __LINE__;
- logWord = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- crash_msg = "ZFD_TYPE at incorrect position!";
- goto crash;
- }
- {
- Uint32 noFdDescriptors =
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_NO_FD];
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
- (ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE) +
- (noFdDescriptors * ZFD_MBYTE_SIZE * clogFileSize);
- }
- break;
-/* ========================================================================= */
-/* ========================================================================= */
- case ZNEXT_LOG_RECORD_TYPE:
- jam();
- stepAhead(signal, ZPAGE_SIZE - logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]);
- break;
-/* ========================================================================= */
-/* ========================================================================= */
- case ZNEXT_MBYTE_TYPE:
-/*---------------------------------------------------------------------------*/
-/* WE WILL SKIP A PART OF THE LOG FILE. ACTUALLY THE NEXT POINTER IS TO */
-/* A NEW MBYTE. THEREFORE WE WILL START UP A NEW MBYTE. THIS NEW MBYTE IS */
-/* HOWEVER ONLY STARTED IF IT IS NOT AFTER THE STOP MBYTE. */
-/* IF WE HAVE REACHED THE END OF THE STOP MBYTE THEN THE EXECUTION OF THE LOG*/
-/* IS COMPLETED. */
-/*---------------------------------------------------------------------------*/
- if (logPartPtr.p->currentLogfile == logPartPtr.p->stopLogfile) {
- if (logFilePtr.p->currentMbyte == logPartPtr.p->stopMbyte) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* THIS WAS THE LAST MBYTE TO EXECUTE IN THIS LOG PART. WE SHOULD HAVE FOUND */
-/* A COMPLETED GCI RECORD OF THE LAST GCI BEFORE THIS. FOR SOME REASON THIS */
-/* RECORD WAS NOT AVAILABLE ON THE LOG. CRASH THE SYSTEM, A VERY SERIOUS */
-/* ERROR WHICH WE MUST REALLY WORK HARD TO AVOID. */
-/*---------------------------------------------------------------------------*/
-/*---------------------------------------------------------------------------*/
-/* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM. */
-/*---------------------------------------------------------------------------*/
- line = __LINE__;
- logWord = ZNEXT_MBYTE_TYPE;
- crash_msg = "end of log wo/ having found last GCI";
- goto crash;
- }//if
- }//if
-/*---------------------------------------------------------------------------*/
-/* START EXECUTION OF A NEW MBYTE IN THE LOG. */
-/*---------------------------------------------------------------------------*/
- if (logFilePtr.p->currentMbyte < (clogFileSize - 1)) {
- jam();
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_NEW_MBYTE;
- } else {
- ndbrequire(logFilePtr.p->currentMbyte == (clogFileSize - 1));
- jam();
-/*---------------------------------------------------------------------------*/
-/* WE HAVE TO CHANGE FILE. CLOSE THIS ONE AND THEN OPEN THE NEXT. */
-/*---------------------------------------------------------------------------*/
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_NEW_FILE;
- }//if
- break;
-/* ========================================================================= */
-/* ========================================================================= */
- case ZCOMPLETED_GCI_TYPE:
- jam();
- logWord = readLogword(signal);
- if (DEBUG_REDO)
- ndbout_c("found gci: %u part: %u file: %u page: %u",
- logWord,
- logPartPtr.i,
- logFilePtr.p->fileNo,
- logFilePtr.p->currentFilepage);
- if (logWord == logPartPtr.p->logLastGci) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* IF IT IS THE LAST GCI TO LIVE AFTER SYSTEM RESTART THEN WE RECORD THE NEXT*/
-/* WORD AS THE NEW HEADER OF THE LOG FILE. OTHERWISE WE SIMPLY IGNORE THIS */
-/* LOG RECORD. */
-/*---------------------------------------------------------------------------*/
- if (csrPhasesCompleted == 0) {
- jam();
-/*---------------------------------------------------------------------------*/
-/*WE ONLY RECORD THE HEAD OF THE LOG IN THE FIRST LOG ROUND OF LOG EXECUTION.*/
-/*---------------------------------------------------------------------------*/
- logPartPtr.p->headFileNo = logFilePtr.p->fileNo;
- logPartPtr.p->headPageNo = logFilePtr.p->currentFilepage;
- logPartPtr.p->headPageIndex =
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
- if (DEBUG_REDO)
- ndbout_c("execSr part: %u logLap: %u",
- logPartPtr.i, logPartPtr.p->logLap);
- }//if
-/*---------------------------------------------------------------------------*/
-/* THERE IS NO NEED OF EXECUTING PAST THIS LINE SINCE THERE WILL ONLY BE LOG */
-/* RECORDS THAT WILL BE OF NO INTEREST. THUS CLOSE THE FILE AND START THE */
-/* NEXT PHASE OF THE SYSTEM RESTART. */
-/*---------------------------------------------------------------------------*/
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_COMPLETED;
- }//if
- break;
- default:
- jam();
-/* ========================================================================= */
-/* ========================================================================= */
-/*---------------------------------------------------------------------------*/
-/* SEND A SIGNAL TO THE SIGNAL LOG AND THEN CRASH THE SYSTEM. */
-/*---------------------------------------------------------------------------*/
- line = __LINE__;
- crash_msg = "Invalid logword";
- goto crash;
- break;
- }//switch
-/*---------------------------------------------------------------------------*/
-// We continue to execute log records until we find a proper one to execute or
-// that we reach a new page.
-/*---------------------------------------------------------------------------*/
- } while (1);
- return;
-
-crash:
- signal->theData[0] = RNIL;
- signal->theData[1] = logPartPtr.i;
- Uint32 tmp = logFilePtr.p->fileName[3];
- tmp = (tmp >> 8) & 0xff;// To get the Directory, DXX.
- signal->theData[2] = tmp;
- signal->theData[3] = logFilePtr.p->fileNo;
- signal->theData[4] = logFilePtr.p->currentMbyte;
- signal->theData[5] = logFilePtr.p->currentFilepage;
- signal->theData[6] = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- signal->theData[7] = logWord;
- signal->theData[8] = line;
-
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Error while reading REDO log. from %d\n"
- "D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d : %s",
- signal->theData[8],
- signal->theData[2],
- signal->theData[3],
- signal->theData[4],
- signal->theData[5],
- signal->theData[6],
- signal->theData[7],
- crash_msg ? crash_msg : "");
-
- progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
-}//Dblqh::execSr()
-
-/*---------------------------------------------------------------------------*/
-/* THIS SIGNAL IS ONLY RECEIVED TO BE CAPTURED IN THE SIGNAL LOG. IT IS */
-/* ALSO USED TO CRASH THE SYSTEM AFTER SENDING A SIGNAL TO THE LOG. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::execDEBUG_SIG(Signal* signal)
-{
-/*
-2.5 TEMPORARY VARIABLES
------------------------
-*/
- jamEntry();
- //logPagePtr.i = signal->theData[0];
- //tdebug = logPagePtr.p->logPageWord[0];
-
- char buf[100];
- BaseString::snprintf(buf, 100,
- "Error while reading REDO log. from %d\n"
- "D=%d, F=%d Mb=%d FP=%d W1=%d W2=%d",
- signal->theData[8],
- signal->theData[2], signal->theData[3], signal->theData[4],
- signal->theData[5], signal->theData[6], signal->theData[7]);
-
- progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
-
- return;
-}//Dblqh::execDEBUG_SIG()
-
-/*---------------------------------------------------------------------------*/
-/*---------------------------------------------------------------------------*/
-void Dblqh::closeExecLogLab(Signal* signal)
-{
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
- signal->theData[0] = ZEXEC_SR;
- signal->theData[1] = logFilePtr.p->logPartRec;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dblqh::closeExecLogLab()
-
-void Dblqh::openExecLogLab(Signal* signal)
-{
- readExecLog(signal);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_LOG;
- return;
-}//Dblqh::openExecLogLab()
-
-void Dblqh::readExecLogLab(Signal* signal)
-{
- buildLinkedLogPageList(signal);
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOGREC_FROM_FILE;
- logPartPtr.p->execSrLfoRec = lfoPtr.i;
- logPartPtr.p->execSrLogPage = logPagePtr.i;
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
- logPartPtr.p->execSrLogPageIndex;
- execLogRecord(signal);
- return;
-}//Dblqh::readExecLogLab()
-
-/*---------------------------------------------------------------------------*/
-/* THIS CODE IS USED TO EXECUTE A LOG RECORD WHEN IT'S DATA HAVE BEEN LOCATED*/
-/* AND TRANSFERRED INTO MEMORY. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::execLogRecord(Signal* signal)
-{
- jamEntry();
-
- tcConnectptr.i = logPartPtr.p->logTcConrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- tcConnectptr.p->m_log_part_ptr_i = fragptr.p->m_log_part_ptr_i;
-
- // Read a log record and prepare it for execution
- readLogHeader(signal);
- readKey(signal);
- readAttrinfo(signal);
- initReqinfoExecSr(signal);
- arrGuard(logPartPtr.p->execSrExecuteIndex, 4);
- BlockReference ref = fragptr.p->execSrBlockref[logPartPtr.p->execSrExecuteIndex];
- tcConnectptr.p->nextReplica = refToNode(ref);
- tcConnectptr.p->connectState = TcConnectionrec::LOG_CONNECTED;
- tcConnectptr.p->tcOprec = tcConnectptr.i;
- packLqhkeyreqLab(signal);
- return;
-}//Dblqh::execLogRecord()
-
-//----------------------------------------------------------------------------
-// This function invalidates log pages after the last GCI record in a
-// system/node restart. This is to ensure that the end of the log is
-// consistent. This function is executed last in start phase 3.
-// RT 450. EDTJAMO.
-//----------------------------------------------------------------------------
-void Dblqh::invalidateLogAfterLastGCI(Signal* signal) {
-
- jam();
- if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG_INVALIDATE) {
- jam();
- systemError(signal, __LINE__);
- }
-
- if (logFilePtr.p->fileNo != logPartPtr.p->invalidateFileNo) {
- jam();
- systemError(signal, __LINE__);
- }
-
- switch (lfoPtr.p->lfoState) {
- case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
- jam();
- // Check if this page must be invalidated.
- // If the log lap number on a page after the head of the tail is the same
- // as the actual log lap number we must invalidate this page. Otherwise it
- // could be impossible to find the end of the log in a later system/node
- // restart.
- if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap)
- {
- // This page must be invalidated.
- // We search for end
- // read next
- releaseLfo(signal);
- releaseLogpage(signal);
- readFileInInvalidate(signal, true);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
- return;
- }
-
- /**
- * We found the "last" page to invalidate...
- * Invalidate backwards until head...
- */
-
- // Fall through...
- case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
- jam();
-
- releaseLfo(signal);
- releaseLogpage(signal);
-
- // Step backwards...
- logPartPtr.p->invalidatePageNo--;
-
- if (logPartPtr.p->invalidatePageNo == 0)
- {
- jam();
-
- if (logFilePtr.p->fileNo == 0)
- {
- /**
- * We're wrapping in the log...
- * update logLap
- */
- logPartPtr.p->logLap--;
- ndbrequire(logPartPtr.p->logLap); // Should always be > 0
- if (DEBUG_REDO)
- ndbout_c("invalidateLogAfterLastGCI part: %u wrap from file 0 -> logLap: %u",
- logPartPtr.i, logPartPtr.p->logLap);
- }
-
- /**
- * Move to prev file
- */
- logFilePtr.i = logFilePtr.p->prevLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
- logPartPtr.p->invalidatePageNo = clogFileSize * ZPAGES_IN_MBYTE - 1;
- }
-
- if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo &&
- logPartPtr.p->invalidatePageNo == logPartPtr.p->headPageNo)
- {
- /**
- * Done...
- */
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
-
- logFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
-
- // Close files if necessary. Current file and the next file should be
- // left open.
- exitFromInvalidate(signal);
- return;
- }
-
- seizeLogpage(signal);
-
- /**
- * Make page really empty
- */
- bzero(logPagePtr.p, sizeof(LogPageRecord));
- writeSinglePage(signal, logPartPtr.p->invalidatePageNo,
- ZPAGE_SIZE - 1, __LINE__);
-
- lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES;
- return;
- default:
- jam();
- systemError(signal, __LINE__);
- return;
- break;
- }
-}//Dblqh::invalidateLogAfterLastGCI
-
-void Dblqh::readFileInInvalidate(Signal* signal, bool stepNext)
-{
- jam();
-
- if (stepNext)
- {
- logPartPtr.p->invalidatePageNo++;
- if (logPartPtr.p->invalidatePageNo == (clogFileSize * ZPAGES_IN_MBYTE))
- {
- // We continue in the next file.
- logFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo;
- // Page 0 is used for file descriptors.
- logPartPtr.p->invalidatePageNo = 1;
-
- if (logFilePtr.p->fileNo == 0)
- {
- /**
- * We're wrapping in the log...
- * update logLap
- */
- logPartPtr.p->logLap++;
- if (DEBUG_REDO)
- ndbout_c("readFileInInvalidate part: %u wrap to file 0 -> logLap: %u",
- logPartPtr.i, logPartPtr.p->logLap);
- }
- if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN)
- {
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_INVALIDATE_PAGES;
- openFileRw(signal, logFilePtr);
- return;
- }
- }
- }
-
- // Contact NDBFS. Real time break.
- readSinglePage(signal, logPartPtr.p->invalidatePageNo);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
-}
-
-void Dblqh::exitFromInvalidate(Signal* signal) {
- jam();
-
-loop:
- logFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
-
- if (logFilePtr.i == logPartPtr.p->currentLogfile)
- {
- jam();
- goto done;
- }
-
- if (logFilePtr.p->fileNo == 0)
- {
- jam();
- /**
- * Logfile 0 shoult *not* be closed
- */
- goto loop;
- }
-
- if (logFilePtr.p->logFileStatus == LogFileRecord::CLOSED)
- {
- jam();
- goto done;
- }
-
- jam();
- ndbrequire(logFilePtr.p->logFileStatus == LogFileRecord::OPEN);
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSE_SR_INVALIDATE_PAGES;
- closeFile(signal, logFilePtr, __LINE__);
- return;
-
-done:
- if (DEBUG_REDO)
- ndbout_c("exitFromInvalidate part: %u head file: %u page: %u",
- logPartPtr.i,
- logPartPtr.p->headFileNo,
- logPartPtr.p->headPageNo);
-
- logFilePtr.i = logPartPtr.p->firstLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logFilePtr.p->logPageZero;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] =
- logPartPtr.p->headFileNo;
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
-
- lfoPtr.p->logFileRec = logFilePtr.i;
- lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0;
- return;
-}
-
-/*---------------------------------------------------------------------------*/
-/* THE EXECUTION OF A LOG RECORD IS COMPLETED. RELEASE PAGES IF THEY WERE */
-/* READ FROM DISK FOR THIS PARTICULAR OPERATION. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::completedLab(Signal* signal)
-{
- Uint32 result = returnExecLog(signal);
-/*---------------------------------------------------------------------------*/
-/* ENTER COMPLETED WITH */
-/* LQH_CONNECTPTR */
-/*---------------------------------------------------------------------------*/
- if (result == ZOK) {
- jam();
- execLogRecord(signal);
- return;
- } else if (result == ZNOT_OK) {
- jam();
- signal->theData[0] = ZEXEC_SR;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- } else {
- jam();
- /*empty*/;
- }//if
-/*---------------------------------------------------------------------------*/
-/* WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE PROCEEDING IN */
-/* RARE CASES. */
-/*---------------------------------------------------------------------------*/
- return;
-}//Dblqh::completedLab()
-
-/*---------------------------------------------------------------------------*/
-/* EXECUTION OF LOG RECORD WAS NOT SUCCESSFUL. CHECK IF IT IS OK ANYWAY, */
-/* THEN EXECUTE THE NEXT LOG RECORD. */
-/*---------------------------------------------------------------------------*/
-void Dblqh::logLqhkeyrefLab(Signal* signal)
-{
- Uint32 result = returnExecLog(signal);
- switch (tcConnectptr.p->operation) {
- case ZUPDATE:
- case ZDELETE:
- jam();
- if (unlikely(terrorCode != ZNO_TUPLE_FOUND))
- goto error;
- break;
- case ZINSERT:
- jam();
- if (unlikely(terrorCode != ZTUPLE_ALREADY_EXIST && terrorCode != 899))
- goto error;
-
- break;
- default:
- goto error;
- }
-
- if (result == ZOK) {
- jam();
- execLogRecord(signal);
- return;
- } else if (result == ZNOT_OK) {
- jam();
- signal->theData[0] = ZEXEC_SR;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- } else {
- jam();
- /*empty*/;
- }//if
- /* ------------------------------------------------------------------------
- * WE HAVE TO WAIT FOR CLOSING OF THE EXECUTED LOG FILE BEFORE
- * PROCEEDING IN RARE CASES.
- * ----------------------------------------------------------------------- */
- return;
-error:
- BaseString tmp;
- tmp.appfmt("You have found a bug!"
- " Failed op (%s) during REDO table: %d fragment: %d err: %d",
- tcConnectptr.p->operation == ZINSERT ? "INSERT" :
- tcConnectptr.p->operation == ZUPDATE ? "UPDATE" :
- tcConnectptr.p->operation == ZDELETE ? "DELETE" :
- tcConnectptr.p->operation == ZWRITE ? "WRITE" : "<unknown>",
- tcConnectptr.p->tableref,
- tcConnectptr.p->fragmentid,
- terrorCode);
- progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
- tmp.c_str());
-}//Dblqh::logLqhkeyrefLab()
-
-void Dblqh::closeExecSrCompletedLab(Signal* signal)
-{
- logFilePtr.p->logFileStatus = LogFileRecord::CLOSED;
- signal->theData[0] = logFilePtr.p->logPartRec;
- execLogComp(signal);
- return;
-}//Dblqh::closeExecSrCompletedLab()
-
-/* --------------------------------------------------------------------------
- * ONE OF THE LOG PARTS HAVE COMPLETED EXECUTING THE LOG. CHECK IF ALL LOG
- * PARTS ARE COMPLETED. IF SO START SENDING EXEC_FRAGCONF AND EXEC_SRCONF.
- * ------------------------------------------------------------------------- */
-void Dblqh::execLogComp(Signal* signal)
-{
- logPartPtr.i = signal->theData[0];
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logPartPtr.p->logPartState = LogPartRecord::SR_THIRD_PHASE_COMPLETED;
- /* ------------------------------------------------------------------------
- * WE MUST RELEASE THE TC CONNECT RECORD HERE SO THAT IT CAN BE REUSED.
- * ----------------------------------------------------------------------- */
- tcConnectptr.i = logPartPtr.p->logTcConrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- releaseTcrecLog(signal, tcConnectptr);
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
- if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_COMPLETED) {
- if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_STARTED) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- } else {
- jam();
- /* ------------------------------------------------------------------
- * THIS LOG PART WAS NOT COMPLETED YET. EXIT AND WAIT FOR IT
- * TO COMPLETE
- * ----------------------------------------------------------------- */
- return;
- }//if
- }//if
- }//for
- /* ------------------------------------------------------------------------
- * ALL LOG PARTS HAVE COMPLETED THE EXECUTION OF THE LOG. WE CAN NOW START
- * SENDING THE EXEC_FRAGCONF SIGNALS TO ALL INVOLVED FRAGMENTS.
- * ----------------------------------------------------------------------- */
- jam();
- c_lcp_complete_fragments.first(fragptr);
- signal->theData[0] = ZSEND_EXEC_CONF;
- signal->theData[1] = fragptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//Dblqh::execLogComp()
-
-/* --------------------------------------------------------------------------
- * GO THROUGH THE FRAGMENT RECORDS TO DEDUCE TO WHICH SHALL BE SENT
- * EXEC_FRAGCONF AFTER COMPLETING THE EXECUTION OF THE LOG.
- * ------------------------------------------------------------------------- */
-void Dblqh::sendExecConf(Signal* signal)
-{
- jamEntry();
- fragptr.i = signal->theData[0];
- Uint32 loopCount = 0;
- while (fragptr.i != RNIL) {
- c_lcp_complete_fragments.getPtr(fragptr);
- Uint32 next = fragptr.p->nextList;
- if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
- jam();
- ndbrequire(fragptr.p->execSrNoReplicas - 1 < 4);
- for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
- jam();
- signal->theData[0] = fragptr.p->execSrUserptr[i];
- sendSignal(fragptr.p->execSrBlockref[i], GSN_EXEC_FRAGCONF,
- signal, 1, JBB);
- }//for
- fragptr.p->execSrNoReplicas = 0;
- }//if
- loopCount++;
- if (loopCount > 20) {
- jam();
- signal->theData[0] = ZSEND_EXEC_CONF;
- signal->theData[1] = next;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
- } else {
- jam();
- fragptr.i = next;
- }//if
- }//while
- /* ----------------------------------------------------------------------
- * WE HAVE NOW SENT ALL EXEC_FRAGCONF. NOW IT IS TIME TO SEND
- * EXEC_SRCONF TO ALL NODES.
- * --------------------------------------------------------------------- */
- srPhase3Comp(signal);
-}//Dblqh::sendExecConf()
-
-/* --------------------------------------------------------------------------
- * PHASE 3 HAS NOW COMPLETED. INFORM ALL OTHER NODES OF THIS EVENT.
- * ------------------------------------------------------------------------- */
-void Dblqh::srPhase3Comp(Signal* signal)
-{
- jamEntry();
-
- signal->theData[0] = cownNodeid;
- NodeReceiverGroup rg(DBLQH, m_sr_nodes);
- sendSignal(rg, GSN_EXEC_SRCONF, signal, 1, JBB);
- return;
-}//Dblqh::srPhase3Comp()
-
-/* ##########################################################################
- * SYSTEM RESTART PHASE FOUR MODULE
- * THIS MODULE IS A SUB-MODULE OF THE FILE SYSTEM HANDLING.
- *
- * THIS MODULE SETS UP THE HEAD AND TAIL POINTERS OF THE LOG PARTS IN THE
- * FRAGMENT LOG. WHEN IT IS COMPLETED IT REPORTS TO THE MASTER DIH THAT
- * IT HAS COMPLETED THE PART OF THE SYSTEM RESTART WHERE THE DATABASE IS
- * LOADED.
- * IT ALSO OPENS THE CURRENT LOG FILE AND THE NEXT AND SETS UP THE FIRST
- * LOG PAGE WHERE NEW LOG DATA IS TO BE INSERTED WHEN THE SYSTEM STARTS
- * AGAIN.
- *
- * THIS PART IS ACTUALLY EXECUTED FOR ALL RESTART TYPES.
- * ######################################################################### */
-void Dblqh::initFourth(Signal* signal)
-{
- LogFileRecordPtr locLogFilePtr;
- jamEntry();
- logPartPtr.i = signal->theData[0];
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- crestartNewestGci = 1;
- crestartOldestGci = 1;
- /* ------------------------------------------------------------------------
- * INITIALISE LOG PART AND LOG FILES AS NEEDED.
- * ----------------------------------------------------------------------- */
- logPartPtr.p->headFileNo = 0;
- logPartPtr.p->headPageNo = 1;
- logPartPtr.p->headPageIndex = ZPAGE_HEADER_SIZE + 2;
- logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_STARTED;
- logPartPtr.p->logTailFileNo = 0;
- logPartPtr.p->logTailMbyte = 0;
- locLogFilePtr.i = logPartPtr.p->firstLogfile;
- ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_PHASE;
- openFileRw(signal, locLogFilePtr);
- return;
-}//Dblqh::initFourth()
-
-void Dblqh::openSrFourthPhaseLab(Signal* signal)
-{
- /* ------------------------------------------------------------------------
- * WE HAVE NOW OPENED THE HEAD LOG FILE WE WILL NOW START READING IT
- * FROM THE HEAD MBYTE TO FIND THE NEW HEAD OF THE LOG.
- * ----------------------------------------------------------------------- */
- readSinglePage(signal, logPartPtr.p->headPageNo);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FOURTH_PHASE;
- return;
-}//Dblqh::openSrFourthPhaseLab()
-
-void Dblqh::readSrFourthPhaseLab(Signal* signal)
-{
- if(c_diskless){
- jam();
- logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
- }
-
- /* ------------------------------------------------------------------------
- * INITIALISE ALL LOG PART INFO AND LOG FILE INFO THAT IS NEEDED TO
- * START UP THE SYSTEM.
- * ------------------------------------------------------------------------
- * INITIALISE THE NEWEST GLOBAL CHECKPOINT IDENTITY AND THE NEWEST
- * COMPLETED GLOBAL CHECKPOINT IDENITY AS THE NEWEST THAT WAS RESTARTED.
- * ------------------------------------------------------------------------
- * INITIALISE THE HEAD PAGE INDEX IN THIS PAGE.
- * ASSIGN IT AS THE CURRENT LOGPAGE.
- * ASSIGN THE FILE AS THE CURRENT LOG FILE.
- * ASSIGN THE CURRENT FILE NUMBER FROM THE CURRENT LOG FILE AND THE NEXT
- * FILE NUMBER FROM THE NEXT LOG FILE.
- * ASSIGN THE CURRENT FILEPAGE FROM HEAD PAGE NUMBER.
- * ASSIGN THE CURRENT MBYTE BY DIVIDING PAGE NUMBER BY 128.
- * INITIALISE LOG LAP TO BE THE LOG LAP AS FOUND IN THE HEAD PAGE.
- * WE HAVE TO CALCULATE THE NUMBER OF REMAINING WORDS IN THIS MBYTE.
- * ----------------------------------------------------------------------- */
- cnewestGci = crestartNewestGci;
- cnewestCompletedGci = crestartNewestGci;
- logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
- logPartPtr.p->currentLogfile = logFilePtr.i;
- logFilePtr.p->filePosition = logPartPtr.p->headPageNo;
- logFilePtr.p->currentMbyte =
- logPartPtr.p->headPageNo >> ZTWOLOG_NO_PAGES_IN_MBYTE;
- logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING;
- logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP];
- logFilePtr.p->currentFilepage = logPartPtr.p->headPageNo;
- logFilePtr.p->currentLogpage = logPagePtr.i;
-
- initLogpage(signal);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->headPageIndex;
- logFilePtr.p->remainingWordsInMbyte =
- ((
- ((logFilePtr.p->currentMbyte + 1) * ZPAGES_IN_MBYTE) -
- logFilePtr.p->currentFilepage) *
- (ZPAGE_SIZE - ZPAGE_HEADER_SIZE)) -
- (logPartPtr.p->headPageIndex - ZPAGE_HEADER_SIZE);
- /* ------------------------------------------------------------------------
- * THE NEXT STEP IS TO OPEN THE NEXT LOG FILE (IF THERE IS ONE).
- * ----------------------------------------------------------------------- */
- if (logFilePtr.p->nextLogFile != logFilePtr.i) {
- LogFileRecordPtr locLogFilePtr;
- jam();
- locLogFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
- locLogFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_NEXT;
- openFileRw(signal, locLogFilePtr);
- } else {
- jam();
- /* ----------------------------------------------------------------------
- * THIS CAN ONLY OCCUR IF WE HAVE ONLY ONE LOG FILE. THIS LOG FILE MUST
- * BE LOG FILE ZERO AND THAT IS THE FILE WE CURRENTLY HAVE READ.
- * THUS WE CAN CONTINUE IMMEDIATELY TO READ PAGE ZERO IN FILE ZERO.
- * --------------------------------------------------------------------- */
- openSrFourthZeroSkipInitLab(signal);
- return;
- }//if
- return;
-}//Dblqh::readSrFourthPhaseLab()
-
-void Dblqh::openSrFourthNextLab(Signal* signal)
-{
- /* ------------------------------------------------------------------------
- * WE MUST ALSO HAVE FILE 0 OPEN ALL THE TIME.
- * ----------------------------------------------------------------------- */
- logFilePtr.i = logPartPtr.p->firstLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- if (logFilePtr.p->logFileStatus == LogFileRecord::OPEN) {
- jam();
- openSrFourthZeroSkipInitLab(signal);
- return;
- } else {
- jam();
- logFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_FOURTH_ZERO;
- openFileRw(signal, logFilePtr);
- }//if
- return;
-}//Dblqh::openSrFourthNextLab()
-
-void Dblqh::openSrFourthZeroLab(Signal* signal)
-{
- openSrFourthZeroSkipInitLab(signal);
- return;
-}//Dblqh::openSrFourthZeroLab()
-
-void Dblqh::openSrFourthZeroSkipInitLab(Signal* signal)
-{
- if (logFilePtr.i == logPartPtr.p->currentLogfile) {
- if (logFilePtr.p->currentFilepage == 0) {
- jam();
- /* -------------------------------------------------------------------
- * THE HEADER PAGE IN THE LOG IS PAGE ZERO IN FILE ZERO.
- * THIS SHOULD NEVER OCCUR.
- * ------------------------------------------------------------------- */
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- }//if
- readSinglePage(signal, 0);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_FOURTH_ZERO;
- return;
-}//Dblqh::openSrFourthZeroSkipInitLab()
-
-void Dblqh::readSrFourthZeroLab(Signal* signal)
-{
- logFilePtr.p->logPageZero = logPagePtr.i;
- // --------------------------------------------------------------------
- // This is moved to invalidateLogAfterLastGCI(), RT453.
- // signal->theData[0] = ZSR_FOURTH_COMP;
- // signal->theData[1] = logPartPtr.i;
- // sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- // --------------------------------------------------------------------
-
- // Need to invalidate log pages after the head of the log. RT 453. EDTJAMO.
- // Set the start of the invalidation.
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPartPtr.p->invalidateFileNo = logPartPtr.p->headFileNo;
- logPartPtr.p->invalidatePageNo = logPartPtr.p->headPageNo;
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_INVALIDATE;
-
- readFileInInvalidate(signal, true);
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES;
- return;
-}//Dblqh::readSrFourthZeroLab()
-
-/* --------------------------------------------------------------------------
- * ONE OF THE LOG PARTS HAVE COMPLETED PHASE FOUR OF THE SYSTEM RESTART.
- * CHECK IF ALL LOG PARTS ARE COMPLETED. IF SO SEND START_RECCONF
- * ------------------------------------------------------------------------- */
-void Dblqh::srFourthComp(Signal* signal)
-{
- jamEntry();
- logPartPtr.i = signal->theData[0];
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logPartPtr.p->logPartState = LogPartRecord::SR_FOURTH_PHASE_COMPLETED;
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- jam();
- ptrAss(logPartPtr, logPartRecord);
- if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_COMPLETED) {
- if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_STARTED) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- } else {
- jam();
- /* ------------------------------------------------------------------
- * THIS LOG PART WAS NOT COMPLETED YET.
- * EXIT AND WAIT FOR IT TO COMPLETE
- * ----------------------------------------------------------------- */
- return;
- }//if
- }//if
- }//for
- /* ------------------------------------------------------------------------
- * ALL LOG PARTS HAVE COMPLETED PHASE FOUR OF THE SYSTEM RESTART.
- * WE CAN NOW SEND START_RECCONF TO THE MASTER DIH IF IT WAS A
- * SYSTEM RESTART. OTHERWISE WE WILL CONTINUE WITH AN INITIAL START.
- * SET LOG PART STATE TO IDLE TO
- * INDICATE THAT NOTHING IS GOING ON IN THE LOG PART.
- * ----------------------------------------------------------------------- */
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- ptrAss(logPartPtr, logPartRecord);
- logPartPtr.p->logPartState = LogPartRecord::IDLE;
- }//for
-
- if ((cstartType == NodeState::ST_INITIAL_START) ||
- (cstartType == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
-
- ndbrequire(cinitialStartOngoing == ZTRUE);
- cinitialStartOngoing = ZFALSE;
-
- checkStartCompletedLab(signal);
- return;
- } else if ((cstartType == NodeState::ST_NODE_RESTART) ||
- (cstartType == NodeState::ST_SYSTEM_RESTART)) {
- jam();
-
- if(cstartType == NodeState::ST_SYSTEM_RESTART)
- {
- jam();
- if (c_lcp_complete_fragments.first(fragptr))
- {
- jam();
- signal->theData[0] = ZENABLE_EXPAND_CHECK;
- signal->theData[1] = fragptr.i;
- sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 2, JBB);
- return;
- }
- }
- cstartRecReq = 2;
- StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend();
- conf->startingNodeId = getOwnNodeId();
- sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal,
- StartRecConf::SignalLength, JBB);
- } else {
- ndbrequire(false);
- }//if
- return;
-}//Dblqh::srFourthComp()
-
-/* ######################################################################### */
-/* ####### ERROR MODULE ####### */
-/* */
-/* ######################################################################### */
-
-/*---------------------------------------------------------------------------*/
-/* AN ERROR OCCURRED THAT WE WILL NOT TREAT AS SYSTEM ERROR. MOST OFTEN THIS */
-/* WAS CAUSED BY AN ERRONEUS SIGNAL SENT BY ANOTHER NODE. WE DO NOT WISH TO */
-/* CRASH BECAUSE OF FAULTS IN OTHER NODES. THUS WE ONLY REPORT A WARNING. */
-/* THIS IS CURRENTLY NOT IMPLEMENTED AND FOR THE MOMENT WE GENERATE A SYSTEM */
-/* ERROR SINCE WE WANT TO FIND FAULTS AS QUICKLY AS POSSIBLE IN A TEST PHASE.*/
-/* IN A LATER PHASE WE WILL CHANGE THIS TO BE A WARNING MESSAGE INSTEAD. */
-/*---------------------------------------------------------------------------*/
-/*---------------------------------------------------------------------------*/
-/* THIS TYPE OF ERROR SHOULD NOT GENERATE A SYSTEM ERROR IN A PRODUCT */
-/* RELEASE. THIS IS A TEMPORARY SOLUTION DURING TEST PHASE TO QUICKLY */
-/* FIND ERRORS. NORMALLY THIS SHOULD GENERATE A WARNING MESSAGE ONTO */
-/* SOME ERROR LOGGER. THIS WILL LATER BE IMPLEMENTED BY SOME SIGNAL. */
-/*---------------------------------------------------------------------------*/
-/* ------ SYSTEM ERROR SITUATIONS ------- */
-/* IN SITUATIONS WHERE THE STATE IS ERRONEOUS OR IF THE ERROR OCCURS IN */
-/* THE COMMIT, COMPLETE OR ABORT PHASE, WE PERFORM A CRASH OF THE AXE VM*/
-/*---------------------------------------------------------------------------*/
-
-void Dblqh::systemErrorLab(Signal* signal, int line)
-{
- 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. */
-/*************************************************************************>*/
-}//Dblqh::systemErrorLab()
-
-/* ------- ERROR SITUATIONS ------- */
-
-void Dblqh::aiStateErrorCheckLab(Signal* signal, Uint32* dataPtr, Uint32 length)
-{
- ndbrequire(tcConnectptr.p->abortState != TcConnectionrec::ABORT_IDLE);
- if (tcConnectptr.p->transactionState != TcConnectionrec::IDLE) {
- jam();
-/*************************************************************************>*/
-/* TRANSACTION ABORT IS ONGOING. IT CAN STILL BE A PART OF AN */
-/* OPERATION THAT SHOULD CONTINUE SINCE THE TUPLE HAS NOT ARRIVED */
-/* YET. THIS IS POSSIBLE IF ACTIVE CREATION OF THE FRAGMENT IS */
-/* ONGOING. */
-/*************************************************************************>*/
- if (tcConnectptr.p->activeCreat == Fragrecord::AC_IGNORED) {
- jam();
-/*************************************************************************>*/
-/* ONGOING ABORTS DURING ACTIVE CREATION MUST SAVE THE ATTRIBUTE INFO*/
-/* SO THAT IT CAN BE SENT TO THE NEXT NODE IN THE COMMIT CHAIN. THIS */
-/* IS NEEDED SINCE ALL ABORTS DURING CREATION OF A FRAGMENT ARE NOT */
-/* REALLY ERRORS. A MISSING TUPLE TO BE UPDATED SIMPLY MEANS THAT */
-/* IT HASN'T BEEN TRANSFERRED TO THE NEW REPLICA YET. */
-/*************************************************************************>*/
-/*************************************************************************>*/
-/* AFTER THIS ERROR THE ABORT MUST BE COMPLETED. TO ENSURE THIS SET */
-/* ACTIVE CREATION TO FALSE. THIS WILL ENSURE THAT THE ABORT IS */
-/* COMPLETED. */
-/*************************************************************************>*/
- if (saveTupattrbuf(signal, dataPtr, length) == ZOK) {
- jam();
- if (tcConnectptr.p->transactionState ==
- TcConnectionrec::WAIT_AI_AFTER_ABORT) {
- if (tcConnectptr.p->currTupAiLen == tcConnectptr.p->totReclenAi) {
- jam();
-/*************************************************************************>*/
-/* WE WERE WAITING FOR MORE ATTRIBUTE INFO AFTER A SUCCESSFUL ABORT */
-/* IN ACTIVE CREATION STATE. THE TRANSACTION SHOULD CONTINUE AS IF */
-/* IT WAS COMMITTED. NOW ALL INFO HAS ARRIVED AND WE CAN CONTINUE */
-/* WITH NORMAL PROCESSING AS IF THE TRANSACTION WAS PREPARED. */
-/* SINCE THE FRAGMENT IS UNDER CREATION WE KNOW THAT LOGGING IS */
-/* DISABLED. WE STILL HAVE TO CATER FOR DIRTY OPERATION OR NOT. */
-/*************************************************************************>*/
- tcConnectptr.p->abortState = TcConnectionrec::ABORT_IDLE;
- rwConcludedAiLab(signal);
- return;
- } else {
- ndbrequire(tcConnectptr.p->currTupAiLen < tcConnectptr.p->totReclenAi);
- jam();
- return; /* STILL WAITING FOR MORE ATTRIBUTE INFO */
- }//if
- }//if
- } else {
- jam();
-/*************************************************************************>*/
-/* AFTER THIS ERROR THE ABORT MUST BE COMPLETED. TO ENSURE THIS SET */
-/* ACTIVE CREATION TO ABORT. THIS WILL ENSURE THAT THE ABORT IS */
-/* COMPLETED AND THAT THE ERROR CODE IS PROPERLY SET */
-/*************************************************************************>*/
- tcConnectptr.p->errorCode = terrorCode;
- tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
- if (tcConnectptr.p->transactionState ==
- TcConnectionrec::WAIT_AI_AFTER_ABORT) {
- jam();
-/*************************************************************************>*/
-/* ABORT IS ALREADY COMPLETED. WE NEED TO RESTART IT FROM WHERE IT */
-/* WAS INTERRUPTED. */
-/*************************************************************************>*/
- continueAbortLab(signal);
- return;
- } else {
- jam();
- return;
-/*************************************************************************>*/
-// Abort is ongoing. It will complete since we set the activeCreat = ZFALSE
-/*************************************************************************>*/
- }//if
- }//if
- }//if
- }//if
-/*************************************************************************>*/
-/* TRANSACTION HAVE BEEN ABORTED. THUS IGNORE ALL SIGNALS BELONGING TO IT. */
-/*************************************************************************>*/
- return;
-}//Dblqh::aiStateErrorCheckLab()
-
-void Dblqh::takeOverErrorLab(Signal* signal)
-{
- terrorCode = ZTAKE_OVER_ERROR;
- abortErrorLab(signal);
- return;
-}//Dblqh::takeOverErrorLab()
-
-/* ##########################################################################
- * TEST MODULE
- * ######################################################################### */
-#ifdef VM_TRACE
-void Dblqh::execTESTSIG(Signal* signal)
-{
- jamEntry();
- Uint32 userpointer = signal->theData[0];
- BlockReference userblockref = signal->theData[1];
- Uint32 testcase = signal->theData[2];
-
- signal->theData[0] = userpointer;
- signal->theData[1] = cownref;
- signal->theData[2] = testcase;
- sendSignal(userblockref, GSN_TESTSIG, signal, 25, JBB);
- return;
-}//Dblqh::execTESTSIG()
-
-/* *************** */
-/* MEMCHECKREQ > */
-/* *************** */
-/* ************************************************************************>>
- * THIS SIGNAL IS PURELY FOR TESTING PURPOSES. IT CHECKS THE FREE LIST
- * AND REPORTS THE NUMBER OF FREE RECORDS.
- * THIS CAN BE DONE TO ENSURE THAT NO RECORDS HAS BEEN LOST
- * ************************************************************************> */
-void Dblqh::execMEMCHECKREQ(Signal* signal)
-{
- Uint32* dataPtr = &signal->theData[0];
- jamEntry();
- BlockReference userblockref = signal->theData[0];
- Uint32 index = 0;
- for (Uint32 i = 0; i < 7; i++)
- dataPtr[i] = 0;
- addfragptr.i = cfirstfreeAddfragrec;
- while (addfragptr.i != RNIL) {
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- addfragptr.i = addfragptr.p->nextAddfragrec;
- dataPtr[index]++;
- }//while
- index++;
- attrinbufptr.i = cfirstfreeAttrinbuf;
- while (attrinbufptr.i != RNIL) {
- ptrCheckGuard(attrinbufptr, cattrinbufFileSize, attrbuf);
- attrinbufptr.i = attrinbufptr.p->attrbuf[ZINBUF_NEXT];
- dataPtr[index]++;
- }//while
- index++;
- databufptr.i = cfirstfreeDatabuf;
- while (databufptr.i != RNIL) {
- ptrCheckGuard(databufptr, cdatabufFileSize, databuf);
- databufptr.i = databufptr.p->nextDatabuf;
- dataPtr[index]++;
- }//while
- index++;
- for (tabptr.i = 0;
- tabptr.i < ctabrecFileSize;
- tabptr.i++) {
- ptrAss(tabptr, tablerec);
- if (tabptr.p->tableStatus == Tablerec::NOT_DEFINED) {
- dataPtr[index]++;
- }//if
- }//for
- index++;
- tcConnectptr.i = cfirstfreeTcConrec;
- while (tcConnectptr.i != RNIL) {
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- tcConnectptr.i = tcConnectptr.p->nextTcConnectrec;
- dataPtr[index]++;
- }//while
- sendSignal(userblockref, GSN_MEMCHECKCONF, signal, 10, JBB);
- return;
-}//Dblqh::execMEMCHECKREQ()
-
-#endif
-
-/* ************************************************************************* */
-/* ************************* STATEMENT BLOCKS ****************************** */
-/* ************************************************************************* */
-/* ========================================================================= */
-/* ====== BUILD LINKED LIST OF LOG PAGES AFTER RECEIVING FSREADCONF ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::buildLinkedLogPageList(Signal* signal)
-{
- LogPageRecordPtr bllLogPagePtr;
-
- arrGuard(lfoPtr.p->noPagesRw - 1, 16);
- arrGuard(lfoPtr.p->noPagesRw, 16);
- for (UintR tbllIndex = 0; tbllIndex < lfoPtr.p->noPagesRw; tbllIndex++) {
- jam();
- /* ----------------------------------------------------------------------
- * BUILD LINKED LIST BUT ALSO ENSURE THAT PAGE IS NOT SEEN AS DIRTY
- * INITIALLY.
- * --------------------------------------------------------------------- */
- bllLogPagePtr.i = lfoPtr.p->logPageArray[tbllIndex];
- ptrCheckGuard(bllLogPagePtr, clogPageFileSize, logPageRecord);
-
-// #if VM_TRACE
-// // Check logPage checksum before modifying it
-// Uint32 calcCheckSum = calcPageCheckSum(bllLogPagePtr);
-// Uint32 checkSum = bllLogPagePtr.p->logPageWord[ZPOS_CHECKSUM];
-// if (checkSum != calcCheckSum) {
-// ndbout << "Redolog: Checksum failure." << endl;
-// progError(__LINE__, NDBD_EXIT_NDBREQUIRE, "Redolog: Checksum failure.");
-// }
-// #endif
-
- bllLogPagePtr.p->logPageWord[ZNEXT_PAGE] =
- lfoPtr.p->logPageArray[tbllIndex + 1];
- bllLogPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
- }//for
- bllLogPagePtr.i = lfoPtr.p->logPageArray[lfoPtr.p->noPagesRw - 1];
- ptrCheckGuard(bllLogPagePtr, clogPageFileSize, logPageRecord);
- bllLogPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
-}//Dblqh::buildLinkedLogPageList()
-
-/* =========================================================================
- * ======= CHANGE TO NEXT MBYTE IN LOG =======
- *
- * ========================================================================= */
-void Dblqh::changeMbyte(Signal* signal)
-{
- writeNextLog(signal);
- writeFileDescriptor(signal);
-}//Dblqh::changeMbyte()
-
-/* ========================================================================= */
-/* ====== CHECK IF THIS COMMIT LOG RECORD IS TO BE EXECUTED ======= */
-/* */
-/* SUBROUTINE SHORT NAME = CEL */
-/* ========================================================================= */
-Uint32 Dblqh::checkIfExecLog(Signal* signal)
-{
- tabptr.i = tcConnectptr.p->tableref;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- if (getFragmentrec(signal, tcConnectptr.p->fragmentid) &&
- (table_version_major(tabptr.p->schemaVersion) == table_version_major(tcConnectptr.p->schemaVersion))) {
- if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
- if (fragptr.p->execSrNoReplicas > logPartPtr.p->execSrExecuteIndex) {
- ndbrequire((fragptr.p->execSrNoReplicas - 1) < 4);
- for (Uint32 i = logPartPtr.p->execSrExecuteIndex;
- i < fragptr.p->execSrNoReplicas;
- i++) {
- jam();
- if (tcConnectptr.p->gci >= fragptr.p->execSrStartGci[i]) {
- if (tcConnectptr.p->gci <= fragptr.p->execSrLastGci[i]) {
- jam();
- logPartPtr.p->execSrExecuteIndex = i;
- return ZOK;
- }//if
- }//if
- }//for
- }//if
- }//if
- }//if
- return ZNOT_OK;
-}//Dblqh::checkIfExecLog()
-
-/* ========================================================================= */
-/* == CHECK IF THERE IS LESS THAN 192 KBYTE IN THE BUFFER PLUS INCOMING === */
-/* READS ALREADY STARTED. IF SO IS THE CASE THEN START ANOTHER READ IF */
-/* THERE ARE MORE PAGES IN THIS MBYTE. */
-/* */
-/* ========================================================================= */
-void Dblqh::checkReadExecSr(Signal* signal)
-{
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
- logPartPtr.p->execSrPagesRead = logPartPtr.p->execSrPagesRead + 8;
- logPartPtr.p->execSrPagesReading = logPartPtr.p->execSrPagesReading - 8;
- if ((logPartPtr.p->execSrPagesRead + logPartPtr.p->execSrPagesReading) <
- ZREAD_AHEAD_SIZE) {
- jam();
- /* ----------------------------------------------------------------------
- * WE HAVE LESS THAN 64 KBYTE OF LOG PAGES REMAINING IN MEMORY OR ON
- * ITS WAY TO MAIN MEMORY. READ IN 8 MORE PAGES.
- * --------------------------------------------------------------------- */
- if ((logPartPtr.p->execSrPagesRead + logPartPtr.p->execSrPagesExecuted) <
- ZPAGES_IN_MBYTE) {
- jam();
- /* --------------------------------------------------------------------
- * THERE ARE MORE PAGES TO READ IN THIS MBYTE. READ THOSE FIRST
- * IF >= ZPAGES_IN_MBYTE THEN THERE ARE NO MORE PAGES TO READ. THUS
- * WE PROCEED WITH EXECUTION OF THE LOG.
- * ------------------------------------------------------------------- */
- readExecSr(signal);
- logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR;
- }//if
- }//if
-}//Dblqh::checkReadExecSr()
-
-/* ========================================================================= */
-/* ==== CHECK IF START OF NEW FRAGMENT IS COMPLETED AND WE CAN ======= */
-/* ==== GET THE START GCI ======= */
-/* */
-/* SUBROUTINE SHORT NAME = CTC */
-/* ========================================================================= */
-void Dblqh::checkScanTcCompleted(Signal* signal)
-{
- tcConnectptr.p->logWriteState = TcConnectionrec::NOT_STARTED;
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- fragptr.p->activeTcCounter = fragptr.p->activeTcCounter - 1;
- if (fragptr.p->activeTcCounter == 0) {
- jam();
- fragptr.p->startGci = cnewestGci + 1;
- tabptr.i = tcConnectptr.p->tableref;
- ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- sendCopyActiveConf(signal, tcConnectptr.p->tableref);
- }//if
-}//Dblqh::checkScanTcCompleted()
-
-/* ------------------------------------------------------------------------- */
-/* ------ CLOSE A FILE DURING EXECUTION OF FRAGMENT LOG ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::closeFile(Signal* signal,
- LogFileRecordPtr clfLogFilePtr, Uint32 line)
-{
- signal->theData[0] = clfLogFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = clfLogFilePtr.i;
- signal->theData[3] = ZCLOSE_NO_DELETE;
- signal->theData[4] = line;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 5, JBA);
-}//Dblqh::closeFile()
-
-
-/* ---------------------------------------------------------------- */
-/* ---------------- A LOG PAGE HAVE BEEN COMPLETED ---------------- */
-/* */
-/* SUBROUTINE SHORT NAME = CLP */
-// Input Pointers:
-// logFilePtr
-// logPagePtr
-// logPartPtr
-// Defines lfoPtr
-/* ---------------------------------------------------------------- */
-void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place)
-{
- LogPageRecordPtr clpLogPagePtr;
- LogPageRecordPtr wlpLogPagePtr;
- UintR twlpNoPages;
- UintR twlpType;
-
- if (logFilePtr.p->firstFilledPage == RNIL) {
- jam();
- logFilePtr.p->firstFilledPage = logPagePtr.i;
- } else {
- jam();
- clpLogPagePtr.i = logFilePtr.p->lastFilledPage;
- ptrCheckGuard(clpLogPagePtr, clogPageFileSize, logPageRecord);
- clpLogPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i;
- }//if
- logFilePtr.p->lastFilledPage = logPagePtr.i;
- logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
- logFilePtr.p->noLogpagesInBuffer = logFilePtr.p->noLogpagesInBuffer + 1;
- if (logFilePtr.p->noLogpagesInBuffer != ZMAX_PAGES_WRITTEN) {
- if (clpType != ZLAST_WRITE_IN_FILE) {
- if (clpType != ZENFORCE_WRITE) {
- jam();
- return;
- }//if
- }//if
- }//if
- twlpType = clpType;
-/* ------------------------------------------------------------------------- */
-/* ------ WRITE A SET OF LOG PAGES TO DISK ------- */
-/* */
-/* SUBROUTINE SHORT NAME: WLP */
-/* ------------------------------------------------------------------------- */
- seizeLfo(signal);
- initLfo(signal);
- Uint32* dataPtr = &signal->theData[6];
- twlpNoPages = 0;
- wlpLogPagePtr.i = logFilePtr.p->firstFilledPage;
- do {
- dataPtr[twlpNoPages] = wlpLogPagePtr.i;
- twlpNoPages++;
- ptrCheckGuard(wlpLogPagePtr, clogPageFileSize, logPageRecord);
-
- writeDbgInfoPageHeader(wlpLogPagePtr, place,
- logFilePtr.p->filePosition + twlpNoPages - 1,
- ZPAGE_SIZE);
- // Calculate checksum for page
- wlpLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(wlpLogPagePtr);
- wlpLogPagePtr.i = wlpLogPagePtr.p->logPageWord[ZNEXT_PAGE];
- } while (wlpLogPagePtr.i != RNIL);
- ndbrequire(twlpNoPages < 9);
- dataPtr[twlpNoPages] = logFilePtr.p->filePosition;
-/* -------------------------------------------------- */
-/* SET TIMER ON THIS LOG PART TO SIGNIFY THAT A */
-/* LOG RECORD HAS BEEN SENT AT THIS TIME. */
-/* -------------------------------------------------- */
- logPartPtr.p->logPartTimer = logPartPtr.p->logTimer;
- signal->theData[0] = logFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = lfoPtr.i;
- if (twlpType == ZLAST_WRITE_IN_FILE) {
- jam();
- signal->theData[3] = ZLIST_OF_MEM_PAGES_SYNCH;
- } else {
- jam();
- signal->theData[3] = ZLIST_OF_MEM_PAGES;
- }//if
- signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
- signal->theData[5] = twlpNoPages;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 15, JBA);
-
- if (DEBUG_REDO)
- ndbout_c("writing %d pages at part: %u file: %u pos: %u",
- twlpNoPages,
- logPartPtr.i,
- logFilePtr.p->fileNo,
- logFilePtr.p->filePosition);
-
- if (twlpType == ZNORMAL) {
- jam();
- lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
- } else if (twlpType == ZLAST_WRITE_IN_FILE) {
- jam();
- lfoPtr.p->lfoState = LogFileOperationRecord::LAST_WRITE_IN_FILE;
- } else {
- ndbrequire(twlpType == ZENFORCE_WRITE);
- jam();
- lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
- }//if
- /* ----------------------------------------------------------------------- */
- /* ------ MOVE PAGES FROM LOG FILE TO LFO RECORD ------- */
- /* */
- /* ----------------------------------------------------------------------- */
- /* -------------------------------------------------- */
- /* MOVE PAGES TO LFO RECORD AND REMOVE THEM */
- /* FROM LOG FILE RECORD. */
- /* -------------------------------------------------- */
- lfoPtr.p->firstLfoPage = logFilePtr.p->firstFilledPage;
- logFilePtr.p->firstFilledPage = RNIL;
- logFilePtr.p->lastFilledPage = RNIL;
- logFilePtr.p->noLogpagesInBuffer = 0;
-
- lfoPtr.p->noPagesRw = twlpNoPages;
- lfoPtr.p->lfoPageNo = logFilePtr.p->filePosition;
- lfoPtr.p->lfoWordWritten = ZPAGE_SIZE - 1;
- logFilePtr.p->filePosition += twlpNoPages;
-}//Dblqh::completedLogPage()
-
-/* ---------------------------------------------------------------- */
-/* ---------------- DELETE FRAGMENT RECORD ------------------------ */
-/* */
-/* SUBROUTINE SHORT NAME = DFR */
-/* ---------------------------------------------------------------- */
-void Dblqh::deleteFragrec(Uint32 fragId)
-{
- Uint32 indexFound= RNIL;
- fragptr.i = RNIL;
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabptr.p->fragid[i] == fragId) {
- fragptr.i = tabptr.p->fragrec[i];
- indexFound = i;
- break;
- }//if
- }//for
- if (fragptr.i != RNIL) {
- jam();
- c_fragment_pool.getPtr(fragptr);
- tabptr.p->fragid[indexFound] = ZNIL;
- tabptr.p->fragrec[indexFound] = RNIL;
- fragptr.p->fragStatus = Fragrecord::FREE;
- c_fragment_pool.release(fragptr);
- }//if
-}//Dblqh::deleteFragrec()
-
-/* ------------------------------------------------------------------------- */
-/* ------- FIND LOG FILE RECORD GIVEN FILE NUMBER ------- */
-/* */
-/* INPUT: TFLF_FILE_NO THE FILE NUMBER */
-/* FLF_LOG_PART_PTR THE LOG PART RECORD */
-/* OUTPUT: FLF_LOG_FILE_PTR THE FOUND LOG FILE RECORD */
-/* SUBROUTINE SHORT NAME = FLF */
-/* ------------------------------------------------------------------------- */
-void Dblqh::findLogfile(Signal* signal,
- Uint32 fileNo,
- LogPartRecordPtr flfLogPartPtr,
- LogFileRecordPtr* parLogFilePtr)
-{
- LogFileRecordPtr locLogFilePtr;
- locLogFilePtr.i = flfLogPartPtr.p->firstLogfile;
- Uint32 loopCount = 0;
- while (true) {
- ptrCheckGuard(locLogFilePtr, clogFileFileSize, logFileRecord);
- if (locLogFilePtr.p->fileNo == fileNo) {
- jam();
- ndbrequire(loopCount == fileNo);
- parLogFilePtr->i = locLogFilePtr.i;
- parLogFilePtr->p = locLogFilePtr.p;
- return;
- }//if
- locLogFilePtr.i = locLogFilePtr.p->nextLogFile;
- loopCount++;
- if (loopCount >= flfLogPartPtr.p->noLogFiles &&
- getNodeState().startLevel != NodeState::SL_STARTED)
- {
- goto error;
- }
- ndbrequire(loopCount < flfLogPartPtr.p->noLogFiles);
- }//while
-
-error:
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "Unable to restart, failed while reading redo."
- " Likely invalid change of configuration");
- progError(__LINE__,
- NDBD_EXIT_INVALID_CONFIG,
- buf);
-}//Dblqh::findLogfile()
-
-/* ------------------------------------------------------------------------- */
-/* ------ FIND PAGE REFERENCE IN MEMORY BUFFER AT LOG EXECUTION ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::findPageRef(Signal* signal, CommitLogRecord* commitLogRecord)
-{
- UintR tfprIndex;
-
- logPagePtr.i = RNIL;
- if (ERROR_INSERTED(5020)) {
- // Force system to read page from disk
- return;
- }
- pageRefPtr.i = logPartPtr.p->lastPageRef;
- do {
- ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
- if (commitLogRecord->fileNo == pageRefPtr.p->prFileNo) {
- if (commitLogRecord->startPageNo >= pageRefPtr.p->prPageNo) {
- if (commitLogRecord->startPageNo < (Uint16) (pageRefPtr.p->prPageNo + 8)) {
- jam();
- tfprIndex = commitLogRecord->startPageNo - pageRefPtr.p->prPageNo;
- logPagePtr.i = pageRefPtr.p->pageRef[tfprIndex];
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- return;
- }//if
- }//if
- }//if
- pageRefPtr.i = pageRefPtr.p->prPrev;
- } while (pageRefPtr.i != RNIL);
-}//Dblqh::findPageRef()
-
-/* ------------------------------------------------------------------------- */
-/* ------ GET FIRST OPERATION QUEUED FOR LOGGING ------- */
-/* */
-/* SUBROUTINE SHORT NAME = GFL */
-/* ------------------------------------------------------------------------- */
-void Dblqh::getFirstInLogQueue(Signal* signal)
-{
- TcConnectionrecPtr gflTcConnectptr;
-/* -------------------------------------------------- */
-/* GET THE FIRST FROM THE LOG QUEUE AND REMOVE */
-/* IT FROM THE QUEUE. */
-/* -------------------------------------------------- */
- gflTcConnectptr.i = logPartPtr.p->firstLogQueue;
- ptrCheckGuard(gflTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- logPartPtr.p->firstLogQueue = gflTcConnectptr.p->nextTcLogQueue;
- if (logPartPtr.p->firstLogQueue == RNIL) {
- jam();
- logPartPtr.p->lastLogQueue = RNIL;
- }//if
-}//Dblqh::getFirstInLogQueue()
-
-/* ---------------------------------------------------------------- */
-/* ---------------- GET FRAGMENT RECORD --------------------------- */
-/* INPUT: TFRAGID FRAGMENT ID LOOKING FOR */
-/* TABPTR TABLE ID */
-/* SUBROUTINE SHORT NAME = GFR */
-/* ---------------------------------------------------------------- */
-bool Dblqh::getFragmentrec(Signal* signal, Uint32 fragId)
-{
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabptr.p->fragid[i] == fragId) {
- fragptr.i = tabptr.p->fragrec[i];
- c_fragment_pool.getPtr(fragptr);
- return true;
- }//if
- }//for
- return false;
-}//Dblqh::getFragmentrec()
-
-/* ========================================================================= */
-/* ====== INITIATE FRAGMENT RECORD ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseAddfragrec(Signal* signal)
-{
- if (caddfragrecFileSize != 0) {
- for (addfragptr.i = 0; addfragptr.i < caddfragrecFileSize; addfragptr.i++) {
- ptrAss(addfragptr, addFragRecord);
- addfragptr.p->addfragStatus = AddFragRecord::FREE;
- addfragptr.p->nextAddfragrec = addfragptr.i + 1;
- }//for
- addfragptr.i = caddfragrecFileSize - 1;
- ptrAss(addfragptr, addFragRecord);
- addfragptr.p->nextAddfragrec = RNIL;
- cfirstfreeAddfragrec = 0;
- } else {
- jam();
- cfirstfreeAddfragrec = RNIL;
- }//if
-}//Dblqh::initialiseAddfragrec()
-
-/* ========================================================================= */
-/* ====== INITIATE ATTRIBUTE IN AND OUT DATA BUFFER ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseAttrbuf(Signal* signal)
-{
- if (cattrinbufFileSize != 0) {
- for (attrinbufptr.i = 0;
- attrinbufptr.i < cattrinbufFileSize;
- attrinbufptr.i++) {
- refresh_watch_dog();
- ptrAss(attrinbufptr, attrbuf);
- attrinbufptr.p->attrbuf[ZINBUF_NEXT] = attrinbufptr.i + 1;
- }//for
- /* NEXT ATTRINBUF */
- attrinbufptr.i = cattrinbufFileSize - 1;
- ptrAss(attrinbufptr, attrbuf);
- attrinbufptr.p->attrbuf[ZINBUF_NEXT] = RNIL; /* NEXT ATTRINBUF */
- cfirstfreeAttrinbuf = 0;
- } else {
- jam();
- cfirstfreeAttrinbuf = RNIL;
- }//if
-}//Dblqh::initialiseAttrbuf()
-
-/* ========================================================================= */
-/* ====== INITIATE DATA BUFFER ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseDatabuf(Signal* signal)
-{
- if (cdatabufFileSize != 0) {
- for (databufptr.i = 0; databufptr.i < cdatabufFileSize; databufptr.i++) {
- refresh_watch_dog();
- ptrAss(databufptr, databuf);
- databufptr.p->nextDatabuf = databufptr.i + 1;
- }//for
- databufptr.i = cdatabufFileSize - 1;
- ptrAss(databufptr, databuf);
- databufptr.p->nextDatabuf = RNIL;
- cfirstfreeDatabuf = 0;
- } else {
- jam();
- cfirstfreeDatabuf = RNIL;
- }//if
-}//Dblqh::initialiseDatabuf()
-
-/* ========================================================================= */
-/* ====== INITIATE FRAGMENT RECORD ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseFragrec(Signal* signal)
-{
-
- SLList<Fragrecord> tmp(c_fragment_pool);
- while(tmp.seize(fragptr))
- {
- refresh_watch_dog();
- new (fragptr.p) Fragrecord();
- fragptr.p->fragStatus = Fragrecord::FREE;
- fragptr.p->execSrStatus = Fragrecord::IDLE;
- fragptr.p->srStatus = Fragrecord::SS_IDLE;
- }
- tmp.release();
-}//Dblqh::initialiseFragrec()
-
-/* ========================================================================= */
-/* ====== INITIATE FRAGMENT RECORD ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseGcprec(Signal* signal)
-{
- UintR tigpIndex;
-
- if (cgcprecFileSize != 0) {
- for (gcpPtr.i = 0; gcpPtr.i < cgcprecFileSize; gcpPtr.i++) {
- ptrAss(gcpPtr, gcpRecord);
- for (tigpIndex = 0; tigpIndex <= 3; tigpIndex++) {
- gcpPtr.p->gcpLogPartState[tigpIndex] = ZIDLE;
- gcpPtr.p->gcpSyncReady[tigpIndex] = ZFALSE;
- }//for
- }//for
- }//if
-}//Dblqh::initialiseGcprec()
-
-/* ========================================================================= */
-/* ====== INITIATE LCP RECORD ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseLcpRec(Signal* signal)
-{
- if (clcpFileSize != 0) {
- for (lcpPtr.i = 0; lcpPtr.i < clcpFileSize; lcpPtr.i++) {
- ptrAss(lcpPtr, lcpRecord);
- lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
- lcpPtr.p->lcpQueued = false;
- lcpPtr.p->reportEmpty = false;
- lcpPtr.p->firstFragmentFlag = false;
- lcpPtr.p->lastFragmentFlag = false;
- }//for
- }//if
-}//Dblqh::initialiseLcpRec()
-
-/* ========================================================================= */
-/* ====== INITIATE LOG FILE OPERATION RECORD ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseLfo(Signal* signal)
-{
- if (clfoFileSize != 0) {
- for (lfoPtr.i = 0; lfoPtr.i < clfoFileSize; lfoPtr.i++) {
- ptrAss(lfoPtr, logFileOperationRecord);
- lfoPtr.p->lfoState = LogFileOperationRecord::IDLE;
- lfoPtr.p->lfoTimer = 0;
- lfoPtr.p->nextLfo = lfoPtr.i + 1;
- }//for
- lfoPtr.i = clfoFileSize - 1;
- ptrAss(lfoPtr, logFileOperationRecord);
- lfoPtr.p->nextLfo = RNIL;
- cfirstfreeLfo = 0;
- } else {
- jam();
- cfirstfreeLfo = RNIL;
- }//if
-}//Dblqh::initialiseLfo()
-
-/* ========================================================================= */
-/* ====== INITIATE LOG FILE RECORD ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseLogFile(Signal* signal)
-{
- if (clogFileFileSize != 0) {
- for (logFilePtr.i = 0; logFilePtr.i < clogFileFileSize; logFilePtr.i++) {
- ptrAss(logFilePtr, logFileRecord);
- logFilePtr.p->nextLogFile = logFilePtr.i + 1;
- logFilePtr.p->logFileStatus = LogFileRecord::LFS_IDLE;
-
- logFilePtr.p->logLastPrepRef = new Uint32[clogFileSize];
- logFilePtr.p->logMaxGciCompleted = new Uint32[clogFileSize];
- logFilePtr.p->logMaxGciStarted = new Uint32[clogFileSize];
-
- if (logFilePtr.p->logLastPrepRef == 0 ||
- logFilePtr.p->logMaxGciCompleted == 0 ||
- logFilePtr.p->logMaxGciStarted == 0)
- {
- char buf[256];
- BaseString::snprintf(buf, sizeof(buf),
- "Failed to alloc mbyte(%u) arrays for logfile %u",
- clogFileSize, logFilePtr.i);
- progError(__LINE__, NDBD_EXIT_MEMALLOC, buf);
- }
-
- }//for
- logFilePtr.i = clogFileFileSize - 1;
- ptrAss(logFilePtr, logFileRecord);
- logFilePtr.p->nextLogFile = RNIL;
- cfirstfreeLogFile = 0;
- } else {
- jam();
- cfirstfreeLogFile = RNIL;
- }//if
-}//Dblqh::initialiseLogFile()
-
-/* ========================================================================= */
-/* ====== INITIATE LOG PAGES ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseLogPage(Signal* signal)
-{
- if (clogPageFileSize != 0) {
- for (logPagePtr.i = 0; logPagePtr.i < clogPageFileSize; logPagePtr.i++) {
- refresh_watch_dog();
- ptrAss(logPagePtr, logPageRecord);
- logPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i + 1;
- logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
- logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
- }//for
- logPagePtr.i = clogPageFileSize - 1;
- ptrAss(logPagePtr, logPageRecord);
- logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
- cfirstfreeLogPage = 0;
- } else {
- jam();
- cfirstfreeLogPage = RNIL;
- }//if
- cnoOfLogPages = clogPageFileSize;
-}//Dblqh::initialiseLogPage()
-
-/* =========================================================================
- * ====== INITIATE LOG PART RECORD =======
- *
- * ========================================================================= */
-void Dblqh::initialiseLogPart(Signal* signal)
-{
- for (logPartPtr.i = 0; logPartPtr.i <= 3; logPartPtr.i++) {
- ptrAss(logPartPtr, logPartRecord);
- logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
- logPartPtr.p->LogLqhKeyReqSent = ZFALSE;
- logPartPtr.p->logPartNewestCompletedGCI = (UintR)-1;
- }//for
-}//Dblqh::initialiseLogPart()
-
-void Dblqh::initialisePageRef(Signal* signal)
-{
- if (cpageRefFileSize != 0) {
- for (pageRefPtr.i = 0;
- pageRefPtr.i < cpageRefFileSize;
- pageRefPtr.i++) {
- ptrAss(pageRefPtr, pageRefRecord);
- pageRefPtr.p->prNext = pageRefPtr.i + 1;
- }//for
- pageRefPtr.i = cpageRefFileSize - 1;
- ptrAss(pageRefPtr, pageRefRecord);
- pageRefPtr.p->prNext = RNIL;
- cfirstfreePageRef = 0;
- } else {
- jam();
- cfirstfreePageRef = RNIL;
- }//if
-}//Dblqh::initialisePageRef()
-
-/* ==========================================================================
- * ======= INITIATE RECORDS =======
- *
- * TAKES CARE OF INITIATION OF ALL RECORDS IN THIS BLOCK.
- * ========================================================================= */
-void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data,
- Uint32 retRef, Uint32 retData)
-{
- Uint32 i;
- switch (data) {
- case 0:
- jam();
- m_sr_nodes.clear();
- m_sr_exec_sr_req.clear();
- m_sr_exec_sr_conf.clear();
- for (i = 0; i < 1024; i++) {
- ctransidHash[i] = RNIL;
- }//for
- for (i = 0; i < 4; i++) {
- cactiveCopy[i] = RNIL;
- }//for
- cnoActiveCopy = 0;
- ccurrentGcprec = RNIL;
- caddNodeState = ZFALSE;
- cstartRecReq = 0;
- cnewestGci = 0;
- cnewestCompletedGci = 0;
- crestartOldestGci = 0;
- crestartNewestGci = 0;
- csrPhaseStarted = ZSR_NO_PHASE_STARTED;
- csrPhasesCompleted = 0;
- cmasterDihBlockref = 0;
- cnoFragmentsExecSr = 0;
- clcpCompletedState = LCP_IDLE;
- csrExecUndoLogState = EULS_IDLE;
- c_lcpId = 0;
- cnoOfFragsCheckpointed = 0;
- break;
- case 1:
- jam();
- initialiseAddfragrec(signal);
- break;
- case 2:
- jam();
- initialiseAttrbuf(signal);
- break;
- case 3:
- jam();
- initialiseDatabuf(signal);
- break;
- case 4:
- jam();
- initialiseFragrec(signal);
- break;
- case 5:
- jam();
- initialiseGcprec(signal);
- initialiseLcpRec(signal);
- break;
- case 6:
- jam();
- initialiseLogPage(signal);
- break;
- case 7:
- jam();
- initialiseLfo(signal);
- break;
- case 8:
- jam();
- initialiseLogFile(signal);
- initialiseLogPart(signal);
- break;
- case 9:
- jam();
- initialisePageRef(signal);
- break;
- case 10:
- jam();
- initialiseScanrec(signal);
- break;
- case 11:
- jam();
- initialiseTabrec(signal);
- break;
- case 12:
- jam();
- initialiseTcNodeFailRec(signal);
- initialiseTcrec(signal);
- {
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = retData;
- sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
- }
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
-
- signal->theData[0] = ZINITIALISE_RECORDS;
- signal->theData[1] = data + 1;
- signal->theData[2] = 0;
- signal->theData[3] = retRef;
- signal->theData[4] = retData;
- sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 5, JBB);
-
- return;
-}//Dblqh::initialiseRecordsLab()
-
-/* ==========================================================================
- * ======= INITIATE TC CONNECTION RECORD =======
- *
- * ========================================================================= */
-void Dblqh::initialiseScanrec(Signal* signal)
-{
- ndbrequire(cscanrecFileSize > 1);
- DLList<ScanRecord> tmp(c_scanRecordPool);
- while (tmp.seize(scanptr)){
- //new (scanptr.p) ScanRecord();
- refresh_watch_dog();
- scanptr.p->scanType = ScanRecord::ST_IDLE;
- scanptr.p->scanState = ScanRecord::SCAN_FREE;
- scanptr.p->scanTcWaiting = ZFALSE;
- scanptr.p->nextHash = RNIL;
- scanptr.p->prevHash = RNIL;
- scanptr.p->scan_acc_index= 0;
- scanptr.p->scan_acc_attr_recs= 0;
- }
- tmp.release();
-}//Dblqh::initialiseScanrec()
-
-/* ==========================================================================
- * ======= INITIATE TABLE RECORD =======
- *
- * ========================================================================= */
-void Dblqh::initialiseTabrec(Signal* signal)
-{
- if (ctabrecFileSize != 0) {
- for (tabptr.i = 0; tabptr.i < ctabrecFileSize; tabptr.i++) {
- refresh_watch_dog();
- ptrAss(tabptr, tablerec);
- tabptr.p->tableStatus = Tablerec::NOT_DEFINED;
- tabptr.p->usageCount = 0;
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- tabptr.p->fragid[i] = ZNIL;
- tabptr.p->fragrec[i] = RNIL;
- }//for
- }//for
- }//if
-}//Dblqh::initialiseTabrec()
-
-/* ==========================================================================
- * ======= INITIATE TC CONNECTION RECORD =======
- *
- * ========================================================================= */
-void Dblqh::initialiseTcrec(Signal* signal)
-{
- if (ctcConnectrecFileSize != 0) {
- for (tcConnectptr.i = 0;
- tcConnectptr.i < ctcConnectrecFileSize;
- tcConnectptr.i++) {
- refresh_watch_dog();
- ptrAss(tcConnectptr, tcConnectionrec);
- tcConnectptr.p->transactionState = TcConnectionrec::TC_NOT_CONNECTED;
- tcConnectptr.p->tcScanRec = RNIL;
- tcConnectptr.p->logWriteState = TcConnectionrec::NOT_STARTED;
- tcConnectptr.p->firstAttrinbuf = RNIL;
- tcConnectptr.p->lastAttrinbuf = RNIL;
- tcConnectptr.p->firstTupkeybuf = RNIL;
- tcConnectptr.p->lastTupkeybuf = RNIL;
- tcConnectptr.p->tcTimer = 0;
- tcConnectptr.p->nextTcConnectrec = tcConnectptr.i + 1;
- }//for
- tcConnectptr.i = ctcConnectrecFileSize - 1;
- ptrAss(tcConnectptr, tcConnectionrec);
- tcConnectptr.p->nextTcConnectrec = RNIL;
- cfirstfreeTcConrec = 0;
- } else {
- jam();
- cfirstfreeTcConrec = RNIL;
- }//if
-}//Dblqh::initialiseTcrec()
-
-/* ==========================================================================
- * ======= INITIATE TC CONNECTION RECORD =======
- *
- * ========================================================================= */
-void Dblqh::initialiseTcNodeFailRec(Signal* signal)
-{
- if (ctcNodeFailrecFileSize != 0) {
- for (tcNodeFailptr.i = 0;
- tcNodeFailptr.i < ctcNodeFailrecFileSize;
- tcNodeFailptr.i++) {
- ptrAss(tcNodeFailptr, tcNodeFailRecord);
- tcNodeFailptr.p->tcFailStatus = TcNodeFailRecord::TC_STATE_FALSE;
- }//for
- }//if
-}//Dblqh::initialiseTcNodeFailRec()
-
-/* ==========================================================================
- * ======= INITIATE FRAGMENT RECORD =======
- *
- * SUBROUTINE SHORT NAME = IF
- * ========================================================================= */
-void Dblqh::initFragrec(Signal* signal,
- Uint32 tableId,
- Uint32 fragId,
- Uint32 copyType)
-{
- new (fragptr.p) Fragrecord();
- fragptr.p->m_scanNumberMask.set(); // All is free
- fragptr.p->accBlockref = caccBlockref;
- fragptr.p->firstWaitQueue = RNIL;
- fragptr.p->lastWaitQueue = RNIL;
- fragptr.p->fragStatus = Fragrecord::DEFINED;
- fragptr.p->fragCopy = copyType;
- fragptr.p->tupBlockref = ctupBlockref;
- fragptr.p->tuxBlockref = ctuxBlockref;
- fragptr.p->logFlag = Fragrecord::STATE_TRUE;
- fragptr.p->lcpFlag = Fragrecord::LCP_STATE_TRUE;
- for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
- fragptr.p->lcpId[i] = 0;
- }//for
- fragptr.p->maxGciCompletedInLcp = 0;
- fragptr.p->maxGciInLcp = 0;
- fragptr.p->copyFragState = ZIDLE;
- fragptr.p->newestGci = cnewestGci;
- fragptr.p->tabRef = tableId;
- fragptr.p->fragId = fragId;
- fragptr.p->srStatus = Fragrecord::SS_IDLE;
- fragptr.p->execSrStatus = Fragrecord::IDLE;
- fragptr.p->execSrNoReplicas = 0;
- fragptr.p->fragDistributionKey = 0;
- fragptr.p->activeTcCounter = 0;
- fragptr.p->tableFragptr = RNIL;
-}//Dblqh::initFragrec()
-
-/* ==========================================================================
- * ======= INITIATE FRAGMENT RECORD FOR SYSTEM RESTART =======
- *
- * SUBROUTINE SHORT NAME = IFS
- * ========================================================================= */
-
-/* ==========================================================================
- * ======= INITIATE INFORMATION ABOUT GLOBAL CHECKPOINTS =======
- * IN LOG FILE RECORDS
- *
- * INPUT: LOG_FILE_PTR CURRENT LOG FILE
- * TNO_FD_DESCRIPTORS THE NUMBER OF FILE DESCRIPTORS
- * TO READ FROM THE LOG PAGE
- * LOG_PAGE_PTR PAGE ZERO IN LOG FILE
- * SUBROUTINE SHORT NAME = IGL
- * ========================================================================= */
-void Dblqh::initGciInLogFileRec(Signal* signal, Uint32 noFdDescriptors)
-{
- LogFileRecordPtr filePtr = logFilePtr;
- Uint32 pos = ZPAGE_HEADER_SIZE + ZFD_HEADER_SIZE;
- for (Uint32 fd = 0; fd < noFdDescriptors; fd++)
- {
- jam();
- for (Uint32 mb = 0; mb < clogFileSize; mb++)
- {
- jam();
- Uint32 pos0 = pos + fd * (ZFD_MBYTE_SIZE * clogFileSize) + mb;
- Uint32 pos1 = pos0 + clogFileSize;
- Uint32 pos2 = pos1 + clogFileSize;
- arrGuard(pos0, ZPAGE_SIZE);
- arrGuard(pos1, ZPAGE_SIZE);
- arrGuard(pos2, ZPAGE_SIZE);
- filePtr.p->logMaxGciCompleted[mb] = logPagePtr.p->logPageWord[pos0];
- filePtr.p->logMaxGciStarted[mb] = logPagePtr.p->logPageWord[pos1];
- filePtr.p->logLastPrepRef[mb] = logPagePtr.p->logPageWord[pos2];
- }
- if (fd + 1 < noFdDescriptors)
- {
- jam();
- filePtr.i = filePtr.p->prevLogFile;
- ptrCheckGuard(filePtr, clogFileFileSize, logFileRecord);
- }
- }
-}//Dblqh::initGciInLogFileRec()
-
-/* ==========================================================================
- * ======= INITIATE LCP RECORD WHEN USED FOR SYSTEM RESTART =======
- *
- * SUBROUTINE SHORT NAME = ILS
- * ========================================================================= */
-void Dblqh::initLcpSr(Signal* signal,
- Uint32 lcpNo,
- Uint32 lcpId,
- Uint32 tableId,
- Uint32 fragId,
- Uint32 fragPtr)
-{
- lcpPtr.p->lcpQueued = false;
- lcpPtr.p->currentFragment.fragPtrI = fragPtr;
- lcpPtr.p->currentFragment.lcpFragOrd.lcpNo = lcpNo;
- lcpPtr.p->currentFragment.lcpFragOrd.lcpId = lcpId;
- lcpPtr.p->currentFragment.lcpFragOrd.tableId = tableId;
- lcpPtr.p->currentFragment.lcpFragOrd.fragmentId = fragId;
- lcpPtr.p->lcpState = LcpRecord::LCP_SR_WAIT_FRAGID;
-}//Dblqh::initLcpSr()
-
-/* ==========================================================================
- * ======= INITIATE LOG PART =======
- *
- * ========================================================================= */
-void Dblqh::initLogpart(Signal* signal)
-{
- logPartPtr.p->execSrLogPage = RNIL;
- logPartPtr.p->execSrLogPageIndex = ZNIL;
- logPartPtr.p->execSrExecuteIndex = 0;
- logPartPtr.p->noLogFiles = cnoLogFiles;
- logPartPtr.p->logLap = 0;
- logPartPtr.p->logTailFileNo = 0;
- logPartPtr.p->logTailMbyte = 0;
- logPartPtr.p->lastMbyte = ZNIL;
- logPartPtr.p->logPartState = LogPartRecord::SR_FIRST_PHASE;
- logPartPtr.p->logExecState = LogPartRecord::LES_IDLE;
- logPartPtr.p->firstLogTcrec = RNIL;
- logPartPtr.p->lastLogTcrec = RNIL;
- logPartPtr.p->firstLogQueue = RNIL;
- logPartPtr.p->lastLogQueue = RNIL;
- logPartPtr.p->gcprec = RNIL;
- logPartPtr.p->firstPageRef = RNIL;
- logPartPtr.p->lastPageRef = RNIL;
- logPartPtr.p->headFileNo = ZNIL;
- logPartPtr.p->headPageNo = ZNIL;
- logPartPtr.p->headPageIndex = ZNIL;
-}//Dblqh::initLogpart()
-
-/* ==========================================================================
- * ======= INITIATE LOG POINTERS =======
- *
- * ========================================================================= */
-void Dblqh::initLogPointers(Signal* signal)
-{
- logPartPtr.i = tcConnectptr.p->m_log_part_ptr_i;
- ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
- logFilePtr.i = logPartPtr.p->currentLogfile;
- ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
-}//Dblqh::initLogPointers()
-
-/* ------------------------------------------------------------------------- */
-/* ------- INIT REQUEST INFO BEFORE EXECUTING A LOG RECORD ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::initReqinfoExecSr(Signal* signal)
-{
- UintR Treqinfo = 0;
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- LqhKeyReq::setKeyLen(Treqinfo, regTcPtr->primKeyLen);
-/* ------------------------------------------------------------------------- */
-/* NUMBER OF BACKUPS AND STANDBYS ARE ZERO AND NEED NOT BE SET. */
-/* REPLICA TYPE IS CLEARED BY SEND_LQHKEYREQ. */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* SET LAST REPLICA NUMBER TO ZERO (BIT 10-11) */
-/* ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* SET DIRTY FLAG */
-/* ------------------------------------------------------------------------- */
- LqhKeyReq::setDirtyFlag(Treqinfo, 1);
-/* ------------------------------------------------------------------------- */
-/* SET SIMPLE TRANSACTION */
-/* ------------------------------------------------------------------------- */
- LqhKeyReq::setSimpleFlag(Treqinfo, 1);
- LqhKeyReq::setGCIFlag(Treqinfo, 1);
-/* ------------------------------------------------------------------------- */
-/* SET OPERATION TYPE AND LOCK MODE (NEVER READ OPERATION OR SCAN IN LOG) */
-/* ------------------------------------------------------------------------- */
- LqhKeyReq::setOperation(Treqinfo, regTcPtr->operation);
- regTcPtr->reqinfo = Treqinfo;
-/* ------------------------------------------------------------------------ */
-/* NO OF BACKUP IS SET TO ONE AND NUMBER OF STANDBY NODES IS SET TO ZERO. */
-/* THUS THE RECEIVING NODE WILL EXPECT THAT IT IS THE LAST NODE AND WILL */
-/* SEND COMPLETED AS THE RESPONSE SIGNAL SINCE DIRTY_OP BIT IS SET. */
-/* ------------------------------------------------------------------------ */
-/* ------------------------------------------------------------------------- */
-/* SET REPLICA TYPE TO PRIMARY AND NUMBER OF REPLICA TO ONE */
-/* ------------------------------------------------------------------------- */
- regTcPtr->lastReplicaNo = 0;
- regTcPtr->apiVersionNo = 0;
- regTcPtr->nextSeqNoReplica = 0;
- regTcPtr->opExec = 0;
- regTcPtr->storedProcId = ZNIL;
- regTcPtr->readlenAi = 0;
- regTcPtr->nodeAfterNext[0] = ZNIL;
- regTcPtr->nodeAfterNext[1] = ZNIL;
- regTcPtr->dirtyOp = ZFALSE;
- regTcPtr->tcBlockref = cownref;
-}//Dblqh::initReqinfoExecSr()
-
-/* --------------------------------------------------------------------------
- * ------- INSERT FRAGMENT -------
- *
- * ------------------------------------------------------------------------- */
-bool Dblqh::insertFragrec(Signal* signal, Uint32 fragId)
-{
- terrorCode = ZOK;
- if(c_fragment_pool.seize(fragptr) == false)
- {
- terrorCode = ZNO_FREE_FRAGMENTREC;
- return false;
- }
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabptr.p->fragid[i] == ZNIL) {
- jam();
- tabptr.p->fragid[i] = fragId;
- tabptr.p->fragrec[i] = fragptr.i;
- return true;
- }//if
- }//for
- c_fragment_pool.release(fragptr);
- terrorCode = ZTOO_MANY_FRAGMENTS;
- return false;
-}//Dblqh::insertFragrec()
-
-/* --------------------------------------------------------------------------
- * ------- LINK OPERATION IN ACTIVE LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME: LFQ
-// Input Pointers:
-// tcConnectptr
-// fragptr
-* ------------------------------------------------------------------------- */
-void Dblqh::linkFragQueue(Signal* signal)
-{
- TcConnectionrecPtr lfqTcConnectptr;
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Fragrecord * const regFragPtr = fragptr.p;
- Uint32 tcIndex = tcConnectptr.i;
-
- lfqTcConnectptr.i = regFragPtr->lastWaitQueue;
- regTcPtr->nextTc = RNIL;
- regFragPtr->lastWaitQueue = tcIndex;
- regTcPtr->prevTc = lfqTcConnectptr.i;
- ndbrequire(regTcPtr->listState == TcConnectionrec::NOT_IN_LIST);
- regTcPtr->listState = TcConnectionrec::WAIT_QUEUE_LIST;
- if (lfqTcConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(lfqTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- lfqTcConnectptr.p->nextTc = tcIndex;
- } else {
- regFragPtr->firstWaitQueue = tcIndex;
- }//if
- return;
-}//Dblqh::linkFragQueue()
-
-/* -------------------------------------------------------------------------
- * ------- LINK OPERATION INTO WAITING FOR LOGGING -------
- *
- * SUBROUTINE SHORT NAME = LWL
-// Input Pointers:
-// tcConnectptr
-// logPartPtr
- * ------------------------------------------------------------------------- */
-void Dblqh::linkWaitLog(Signal* signal, LogPartRecordPtr regLogPartPtr)
-{
- TcConnectionrecPtr lwlTcConnectptr;
-
-/* -------------------------------------------------- */
-/* LINK ACTIVE OPERATION INTO QUEUE WAITING FOR */
-/* ACCESS TO THE LOG PART. */
-/* -------------------------------------------------- */
- lwlTcConnectptr.i = regLogPartPtr.p->lastLogQueue;
- if (lwlTcConnectptr.i == RNIL) {
- jam();
- regLogPartPtr.p->firstLogQueue = tcConnectptr.i;
- } else {
- jam();
- ptrCheckGuard(lwlTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- lwlTcConnectptr.p->nextTcLogQueue = tcConnectptr.i;
- }//if
- regLogPartPtr.p->lastLogQueue = tcConnectptr.i;
- tcConnectptr.p->nextTcLogQueue = RNIL;
- if (regLogPartPtr.p->LogLqhKeyReqSent == ZFALSE) {
- jam();
- regLogPartPtr.p->LogLqhKeyReqSent = ZTRUE;
- signal->theData[0] = ZLOG_LQHKEYREQ;
- signal->theData[1] = regLogPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
-}//Dblqh::linkWaitLog()
-
-/* --------------------------------------------------------------------------
- * ------- START THE NEXT OPERATION ON THIS LOG PART IF ANY -------
- * ------- OPERATIONS ARE QUEUED. -------
- *
- * SUBROUTINE SHORT NAME = LNS
-// Input Pointers:
-// tcConnectptr
-// logPartPtr
- * ------------------------------------------------------------------------- */
-void Dblqh::logNextStart(Signal* signal)
-{
- LogPartRecordPtr lnsLogPartPtr;
- UintR tlnsStillWaiting;
- LogPartRecord * const regLogPartPtr = logPartPtr.p;
-
- if ((regLogPartPtr->firstLogQueue == RNIL) &&
- (regLogPartPtr->logPartState == LogPartRecord::ACTIVE) &&
- (regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE)) {
-// --------------------------------------------------------------------------
-// Optimised route for the common case
-// --------------------------------------------------------------------------
- regLogPartPtr->logPartState = LogPartRecord::IDLE;
- return;
- }//if
- if (regLogPartPtr->firstLogQueue != RNIL) {
- jam();
- if (regLogPartPtr->LogLqhKeyReqSent == ZFALSE) {
- jam();
- regLogPartPtr->LogLqhKeyReqSent = ZTRUE;
- signal->theData[0] = ZLOG_LQHKEYREQ;
- signal->theData[1] = logPartPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
- } else {
- if (regLogPartPtr->logPartState == LogPartRecord::ACTIVE) {
- jam();
- regLogPartPtr->logPartState = LogPartRecord::IDLE;
- } else {
- jam();
- }//if
- }//if
- if (regLogPartPtr->waitWriteGciLog != LogPartRecord::WWGL_TRUE) {
- jam();
- return;
- } else {
- jam();
-/* --------------------------------------------------------------------------
- * A COMPLETE GCI LOG RECORD IS WAITING TO BE WRITTEN. WE GIVE THIS HIGHEST
- * PRIORITY AND WRITE IT IMMEDIATELY. AFTER WRITING IT WE CHECK IF ANY MORE
- * LOG PARTS ARE WAITING. IF NOT WE SEND A SIGNAL THAT INITIALISES THE GCP
- * RECORD TO WAIT UNTIL ALL COMPLETE GCI LOG RECORDS HAVE REACHED TO DISK.
- * -------------------------------------------------------------------------- */
- writeCompletedGciLog(signal);
- logPartPtr.p->waitWriteGciLog = LogPartRecord::WWGL_FALSE;
- tlnsStillWaiting = ZFALSE;
- for (lnsLogPartPtr.i = 0; lnsLogPartPtr.i < 4; lnsLogPartPtr.i++) {
- jam();
- ptrAss(lnsLogPartPtr, logPartRecord);
- if (lnsLogPartPtr.p->waitWriteGciLog == LogPartRecord::WWGL_TRUE) {
- jam();
- tlnsStillWaiting = ZTRUE;
- }//if
- }//for
- if (tlnsStillWaiting == ZFALSE) {
- jam();
- signal->theData[0] = ZINIT_GCP_REC;
- sendSignal(cownref, GSN_CONTINUEB, signal, 1, JBB);
- }//if
- }//if
-}//Dblqh::logNextStart()
-
-/* --------------------------------------------------------------------------
- * ------- MOVE PAGES FROM LFO RECORD TO PAGE REFERENCE RECORD -------
- * WILL ALWAYS MOVE 8 PAGES TO A PAGE REFERENCE RECORD.
- *
- * SUBROUTINE SHORT NAME = MPR
- * ------------------------------------------------------------------------- */
-void Dblqh::moveToPageRef(Signal* signal)
-{
- LogPageRecordPtr mprLogPagePtr;
- PageRefRecordPtr mprPageRefPtr;
- UintR tmprIndex;
-
-/* --------------------------------------------------------------------------
- * ------- INSERT PAGE REFERENCE RECORD -------
- *
- * INPUT: LFO_PTR LOG FILE OPERATION RECORD
- * LOG_PART_PTR LOG PART RECORD
- * PAGE_REF_PTR THE PAGE REFERENCE RECORD TO BE INSERTED.
- * ------------------------------------------------------------------------- */
- PageRefRecordPtr iprPageRefPtr;
-
- if ((logPartPtr.p->mmBufferSize + 8) >= ZMAX_MM_BUFFER_SIZE) {
- jam();
- pageRefPtr.i = logPartPtr.p->firstPageRef;
- ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
- releasePrPages(signal);
- removePageRef(signal);
- } else {
- jam();
- logPartPtr.p->mmBufferSize = logPartPtr.p->mmBufferSize + 8;
- }//if
- seizePageRef(signal);
- if (logPartPtr.p->firstPageRef == RNIL) {
- jam();
- logPartPtr.p->firstPageRef = pageRefPtr.i;
- } else {
- jam();
- iprPageRefPtr.i = logPartPtr.p->lastPageRef;
- ptrCheckGuard(iprPageRefPtr, cpageRefFileSize, pageRefRecord);
- iprPageRefPtr.p->prNext = pageRefPtr.i;
- }//if
- pageRefPtr.p->prPrev = logPartPtr.p->lastPageRef;
- logPartPtr.p->lastPageRef = pageRefPtr.i;
-
- pageRefPtr.p->prFileNo = logFilePtr.p->fileNo;
- pageRefPtr.p->prPageNo = lfoPtr.p->lfoPageNo;
- tmprIndex = 0;
- mprLogPagePtr.i = lfoPtr.p->firstLfoPage;
-MPR_LOOP:
- arrGuard(tmprIndex, 8);
- pageRefPtr.p->pageRef[tmprIndex] = mprLogPagePtr.i;
- tmprIndex = tmprIndex + 1;
- ptrCheckGuard(mprLogPagePtr, clogPageFileSize, logPageRecord);
- mprLogPagePtr.i = mprLogPagePtr.p->logPageWord[ZNEXT_PAGE];
- if (mprLogPagePtr.i != RNIL) {
- jam();
- goto MPR_LOOP;
- }//if
- mprPageRefPtr.i = pageRefPtr.p->prPrev;
- if (mprPageRefPtr.i != RNIL) {
- jam();
- ptrCheckGuard(mprPageRefPtr, cpageRefFileSize, pageRefRecord);
- mprLogPagePtr.i = mprPageRefPtr.p->pageRef[7];
- ptrCheckGuard(mprLogPagePtr, clogPageFileSize, logPageRecord);
- mprLogPagePtr.p->logPageWord[ZNEXT_PAGE] = pageRefPtr.p->pageRef[0];
- }//if
-}//Dblqh::moveToPageRef()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ THE ATTRINFO FROM THE LOG ------- */
-/* */
-/* SUBROUTINE SHORT NAME = RA */
-/* ------------------------------------------------------------------------- */
-void Dblqh::readAttrinfo(Signal* signal)
-{
- Uint32 remainingLen = tcConnectptr.p->totSendlenAi;
- if (remainingLen == 0) {
- jam();
- tcConnectptr.p->reclenAiLqhkey = 0;
- return;
- }//if
- Uint32 dataLen = remainingLen;
- if (remainingLen > 5)
- dataLen = 5;
- readLogData(signal, dataLen, &tcConnectptr.p->firstAttrinfo[0]);
- tcConnectptr.p->reclenAiLqhkey = dataLen;
- remainingLen -= dataLen;
- while (remainingLen > 0) {
- jam();
- dataLen = remainingLen;
- if (remainingLen > 22)
- dataLen = 22;
- seizeAttrinbuf(signal);
- readLogData(signal, dataLen, &attrinbufptr.p->attrbuf[0]);
- attrinbufptr.p->attrbuf[ZINBUF_DATA_LEN] = dataLen;
- remainingLen -= dataLen;
- }//while
-}//Dblqh::readAttrinfo()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ COMMIT LOG ------- */
-/* */
-/* SUBROUTINE SHORT NAME = RCL */
-/* ------------------------------------------------------------------------- */
-void Dblqh::readCommitLog(Signal* signal, CommitLogRecord* commitLogRecord)
-{
- Uint32 trclPageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- if ((trclPageIndex + (ZCOMMIT_LOG_SIZE - 1)) < ZPAGE_SIZE) {
- jam();
- tcConnectptr.p->tableref = logPagePtr.p->logPageWord[trclPageIndex + 0];
- tcConnectptr.p->schemaVersion = logPagePtr.p->logPageWord[trclPageIndex + 1];
- tcConnectptr.p->fragmentid = logPagePtr.p->logPageWord[trclPageIndex + 2];
- commitLogRecord->fileNo = logPagePtr.p->logPageWord[trclPageIndex + 3];
- commitLogRecord->startPageNo = logPagePtr.p->logPageWord[trclPageIndex + 4];
- commitLogRecord->startPageIndex = logPagePtr.p->logPageWord[trclPageIndex + 5];
- commitLogRecord->stopPageNo = logPagePtr.p->logPageWord[trclPageIndex + 6];
- tcConnectptr.p->gci = logPagePtr.p->logPageWord[trclPageIndex + 7];
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
- (trclPageIndex + ZCOMMIT_LOG_SIZE) - 1;
- } else {
- jam();
- tcConnectptr.p->tableref = readLogword(signal);
- tcConnectptr.p->schemaVersion = readLogword(signal);
- tcConnectptr.p->fragmentid = readLogword(signal);
- commitLogRecord->fileNo = readLogword(signal);
- commitLogRecord->startPageNo = readLogword(signal);
- commitLogRecord->startPageIndex = readLogword(signal);
- commitLogRecord->stopPageNo = readLogword(signal);
- tcConnectptr.p->gci = readLogword(signal);
- }//if
- tcConnectptr.p->transid[0] = logPartPtr.i + 65536;
- tcConnectptr.p->transid[1] = (DBLQH << 20) + (cownNodeid << 8);
-}//Dblqh::readCommitLog()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ LOG PAGES FROM DISK IN ORDER TO EXECUTE A LOG ------- */
-/* RECORD WHICH WAS NOT FOUND IN MAIN MEMORY. */
-/* */
-/* SUBROUTINE SHORT NAME = REL */
-/* ------------------------------------------------------------------------- */
-void Dblqh::readExecLog(Signal* signal)
-{
- UintR trelIndex;
- UintR trelI;
-
- seizeLfo(signal);
- initLfo(signal);
- trelI = logPartPtr.p->execSrStopPageNo - logPartPtr.p->execSrStartPageNo;
- arrGuard(trelI + 1, 16);
- lfoPtr.p->logPageArray[trelI + 1] = logPartPtr.p->execSrStartPageNo;
- for (trelIndex = logPartPtr.p->execSrStopPageNo; (trelIndex >= logPartPtr.p->execSrStartPageNo) &&
- (UintR)~trelIndex; trelIndex--) {
- jam();
- seizeLogpage(signal);
- arrGuard(trelI, 16);
- lfoPtr.p->logPageArray[trelI] = logPagePtr.i;
- trelI--;
- }//for
- lfoPtr.p->lfoPageNo = logPartPtr.p->execSrStartPageNo;
- lfoPtr.p->noPagesRw = (logPartPtr.p->execSrStopPageNo -
- logPartPtr.p->execSrStartPageNo) + 1;
- lfoPtr.p->firstLfoPage = lfoPtr.p->logPageArray[0];
- signal->theData[0] = logFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = lfoPtr.i;
- signal->theData[3] = ZLIST_OF_MEM_PAGES; // edtjamo TR509 //ZLIST_OF_PAIRS;
- signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
- signal->theData[5] = lfoPtr.p->noPagesRw;
- signal->theData[6] = lfoPtr.p->logPageArray[0];
- signal->theData[7] = lfoPtr.p->logPageArray[1];
- signal->theData[8] = lfoPtr.p->logPageArray[2];
- signal->theData[9] = lfoPtr.p->logPageArray[3];
- signal->theData[10] = lfoPtr.p->logPageArray[4];
- signal->theData[11] = lfoPtr.p->logPageArray[5];
- signal->theData[12] = lfoPtr.p->logPageArray[6];
- signal->theData[13] = lfoPtr.p->logPageArray[7];
- signal->theData[14] = lfoPtr.p->logPageArray[8];
- signal->theData[15] = lfoPtr.p->logPageArray[9];
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 16, JBA);
-
- if (DEBUG_REDO)
- ndbout_c("readExecLog %u page at part: %u file: %u pos: %u",
- lfoPtr.p->noPagesRw,
- logPartPtr.i,
- logFilePtr.p->fileNo,
- logPartPtr.p->execSrStartPageNo);
-
-}//Dblqh::readExecLog()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG ------- */
-/* */
-/* SUBROUTINE SHORT NAME = RES */
-/* ------------------------------------------------------------------------- */
-void Dblqh::readExecSrNewMbyte(Signal* signal)
-{
- logFilePtr.p->currentFilepage = logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE;
- logFilePtr.p->filePosition = logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE;
- logPartPtr.p->execSrPagesRead = 0;
- logPartPtr.p->execSrPagesReading = 0;
- logPartPtr.p->execSrPagesExecuted = 0;
- readExecSr(signal);
- logPartPtr.p->logExecState = LogPartRecord::LES_WAIT_READ_EXEC_SR_NEW_MBYTE;
-}//Dblqh::readExecSrNewMbyte()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ 64 KBYTES WHEN EXECUTING THE FRAGMENT LOG ------- */
-/* */
-/* SUBROUTINE SHORT NAME = RES */
-/* ------------------------------------------------------------------------- */
-void Dblqh::readExecSr(Signal* signal)
-{
- UintR tresPageid;
- UintR tresIndex;
-
- tresPageid = logFilePtr.p->filePosition;
- seizeLfo(signal);
- initLfo(signal);
- for (tresIndex = 7; (UintR)~tresIndex; tresIndex--) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* GO BACKWARDS SINCE WE INSERT AT THE BEGINNING AND WE WANT THAT FIRST PAGE */
-/* SHALL BE FIRST AND LAST PAGE LAST. */
-/* ------------------------------------------------------------------------- */
- seizeLogpage(signal);
- lfoPtr.p->logPageArray[tresIndex] = logPagePtr.i;
- }//for
- lfoPtr.p->lfoState = LogFileOperationRecord::READ_EXEC_SR;
- lfoPtr.p->lfoPageNo = tresPageid;
- logFilePtr.p->filePosition = logFilePtr.p->filePosition + 8;
- logPartPtr.p->execSrPagesReading = logPartPtr.p->execSrPagesReading + 8;
- lfoPtr.p->noPagesRw = 8;
- lfoPtr.p->firstLfoPage = lfoPtr.p->logPageArray[0];
- signal->theData[0] = logFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = lfoPtr.i;
- signal->theData[3] = ZLIST_OF_MEM_PAGES;
- signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
- signal->theData[5] = 8;
- signal->theData[6] = lfoPtr.p->logPageArray[0];
- signal->theData[7] = lfoPtr.p->logPageArray[1];
- signal->theData[8] = lfoPtr.p->logPageArray[2];
- signal->theData[9] = lfoPtr.p->logPageArray[3];
- signal->theData[10] = lfoPtr.p->logPageArray[4];
- signal->theData[11] = lfoPtr.p->logPageArray[5];
- signal->theData[12] = lfoPtr.p->logPageArray[6];
- signal->theData[13] = lfoPtr.p->logPageArray[7];
- signal->theData[14] = tresPageid;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA);
-
- if (DEBUG_REDO)
- ndbout_c("readExecSr %u page at part: %u file: %u pos: %u",
- 8,
- logPartPtr.i,
- logFilePtr.p->fileNo,
- tresPageid);
-
-}//Dblqh::readExecSr()
-
-/* ------------------------------------------------------------------------- */
-/* ------------ READ THE PRIMARY KEY FROM THE LOG ---------------- */
-/* */
-/* SUBROUTINE SHORT NAME = RK */
-/* --------------------------------------------------------------------------*/
-void Dblqh::readKey(Signal* signal)
-{
- Uint32 remainingLen = tcConnectptr.p->primKeyLen;
- ndbrequire(remainingLen != 0);
- Uint32 dataLen = remainingLen;
- if (remainingLen > 4)
- dataLen = 4;
- readLogData(signal, dataLen, &tcConnectptr.p->tupkeyData[0]);
- remainingLen -= dataLen;
- while (remainingLen > 0) {
- jam();
- seizeTupkeybuf(signal);
- dataLen = remainingLen;
- if (dataLen > 4)
- dataLen = 4;
- readLogData(signal, dataLen, &databufptr.p->data[0]);
- remainingLen -= dataLen;
- }//while
-}//Dblqh::readKey()
-
-/* ------------------------------------------------------------------------- */
-/* ------------ READ A NUMBER OF WORDS FROM LOG INTO CDATA ---------------- */
-/* */
-/* SUBROUTINE SHORT NAME = RLD */
-/* --------------------------------------------------------------------------*/
-void Dblqh::readLogData(Signal* signal, Uint32 noOfWords, Uint32* dataPtr)
-{
- ndbrequire(noOfWords < 32);
- Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- if ((logPos + noOfWords) >= ZPAGE_SIZE) {
- for (Uint32 i = 0; i < noOfWords; i++)
- dataPtr[i] = readLogwordExec(signal);
- } else {
- MEMCOPY_NO_WORDS(dataPtr, &logPagePtr.p->logPageWord[logPos], noOfWords);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + noOfWords;
- }//if
-}//Dblqh::readLogData()
-
-/* ------------------------------------------------------------------------- */
-/* ------------ READ THE LOG HEADER OF A PREPARE LOG HEADER ---------------- */
-/* */
-/* SUBROUTINE SHORT NAME = RLH */
-/* --------------------------------------------------------------------------*/
-void Dblqh::readLogHeader(Signal* signal)
-{
- Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- if ((logPos + ZLOG_HEAD_SIZE) < ZPAGE_SIZE) {
- jam();
- tcConnectptr.p->hashValue = logPagePtr.p->logPageWord[logPos + 2];
- tcConnectptr.p->operation = logPagePtr.p->logPageWord[logPos + 3];
- tcConnectptr.p->totSendlenAi = logPagePtr.p->logPageWord[logPos + 4];
- tcConnectptr.p->primKeyLen = logPagePtr.p->logPageWord[logPos + 5];
- tcConnectptr.p->m_row_id.m_page_no = logPagePtr.p->logPageWord[logPos + 6];
- tcConnectptr.p->m_row_id.m_page_idx = logPagePtr.p->logPageWord[logPos+ 7];
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + ZLOG_HEAD_SIZE;
- } else {
- jam();
- readLogwordExec(signal); /* IGNORE PREPARE LOG RECORD TYPE */
- readLogwordExec(signal); /* IGNORE LOG RECORD SIZE */
- tcConnectptr.p->hashValue = readLogwordExec(signal);
- tcConnectptr.p->operation = readLogwordExec(signal);
- tcConnectptr.p->totSendlenAi = readLogwordExec(signal);
- tcConnectptr.p->primKeyLen = readLogwordExec(signal);
- tcConnectptr.p->m_row_id.m_page_no = readLogwordExec(signal);
- tcConnectptr.p->m_row_id.m_page_idx = readLogwordExec(signal);
- }//if
-
- tcConnectptr.p->m_use_rowid = (tcConnectptr.p->operation == ZINSERT);
-}//Dblqh::readLogHeader()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ A WORD FROM THE LOG ------- */
-/* */
-/* OUTPUT: TLOG_WORD */
-/* SUBROUTINE SHORT NAME = RLW */
-/* ------------------------------------------------------------------------- */
-Uint32 Dblqh::readLogword(Signal* signal)
-{
- Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- ndbrequire(logPos < ZPAGE_SIZE);
- Uint32 logWord = logPagePtr.p->logPageWord[logPos];
- logPos++;
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
- if (logPos >= ZPAGE_SIZE) {
- jam();
- logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
- logFilePtr.p->currentLogpage = logPagePtr.i;
- logFilePtr.p->currentFilepage++;
- logPartPtr.p->execSrPagesRead--;
- logPartPtr.p->execSrPagesExecuted++;
- }//if
- return logWord;
-}//Dblqh::readLogword()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ A WORD FROM THE LOG WHEN EXECUTING A LOG RECORD ------- */
-/* */
-/* OUTPUT: TLOG_WORD */
-/* SUBROUTINE SHORT NAME = RWE */
-/* ------------------------------------------------------------------------- */
-Uint32 Dblqh::readLogwordExec(Signal* signal)
-{
- Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- ndbrequire(logPos < ZPAGE_SIZE);
- Uint32 logWord = logPagePtr.p->logPageWord[logPos];
- logPos++;
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos;
- if (logPos >= ZPAGE_SIZE) {
- jam();
- logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
- if (logPagePtr.i != RNIL){
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
- } else {
- // Reading word at the last pos in the last page
- // Don't step forward to next page!
- jam();
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]++;
- }
- }//if
- return logWord;
-}//Dblqh::readLogwordExec()
-
-/* ------------------------------------------------------------------------- */
-/* ------- READ A SINGLE PAGE FROM THE LOG ------- */
-/* */
-/* INPUT: TRSP_PAGE_NO */
-/* SUBROUTINE SHORT NAME = RSP */
-/* ------------------------------------------------------------------------- */
-void Dblqh::readSinglePage(Signal* signal, Uint32 pageNo)
-{
- seizeLfo(signal);
- initLfo(signal);
- seizeLogpage(signal);
- lfoPtr.p->firstLfoPage = logPagePtr.i;
- lfoPtr.p->lfoPageNo = pageNo;
- lfoPtr.p->noPagesRw = 1;
- signal->theData[0] = logFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = lfoPtr.i;
- signal->theData[3] = ZLIST_OF_PAIRS;
- signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
- signal->theData[5] = 1;
- signal->theData[6] = logPagePtr.i;
- signal->theData[7] = pageNo;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
-
- if (DEBUG_REDO)
- ndbout_c("readSinglePage 1 page at part: %u file: %u pos: %u",
- logPartPtr.i,
- logFilePtr.p->fileNo,
- pageNo);
-
-}//Dblqh::readSinglePage()
-
-/* --------------------------------------------------------------------------
- * ------- REMOVE COPY FRAGMENT FROM ACTIVE COPY LIST -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseActiveCopy(Signal* signal)
-{
- /* MUST BE 8 BIT */
- UintR tracFlag;
- UintR tracIndex;
-
- tracFlag = ZFALSE;
- for (tracIndex = 0; tracIndex < 4; tracIndex++) {
- if (tracFlag == ZFALSE) {
- jam();
- if (cactiveCopy[tracIndex] == fragptr.i) {
- jam();
- tracFlag = ZTRUE;
- }//if
- } else {
- if (tracIndex < 3) {
- jam();
- cactiveCopy[tracIndex - 1] = cactiveCopy[tracIndex];
- } else {
- jam();
- cactiveCopy[3] = RNIL;
- }//if
- }//if
- }//for
- ndbrequire(tracFlag == ZTRUE);
- cnoActiveCopy--;
-}//Dblqh::releaseActiveCopy()
-
-
-/* --------------------------------------------------------------------------
- * ------- RELEASE ADD FRAGMENT RECORD -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseAddfragrec(Signal* signal)
-{
- addfragptr.p->addfragStatus = AddFragRecord::FREE;
- addfragptr.p->nextAddfragrec = cfirstfreeAddfragrec;
- cfirstfreeAddfragrec = addfragptr.i;
-}//Dblqh::releaseAddfragrec()
-
-/* --------------------------------------------------------------------------
- * ------- RELEASE A PAGE REFERENCE RECORD. -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::releasePageRef(Signal* signal)
-{
- pageRefPtr.p->prNext = cfirstfreePageRef;
- cfirstfreePageRef = pageRefPtr.i;
-}//Dblqh::releasePageRef()
-
-/* --------------------------------------------------------------------------
- * --- RELEASE ALL PAGES IN THE MM BUFFER AFTER EXECUTING THE LOG ON IT. ----
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseMmPages(Signal* signal)
-{
-RMP_LOOP:
- jam();
- pageRefPtr.i = logPartPtr.p->firstPageRef;
- if (pageRefPtr.i != RNIL) {
- jam();
- ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
- releasePrPages(signal);
- removePageRef(signal);
- goto RMP_LOOP;
- }//if
-}//Dblqh::releaseMmPages()
-
-/* --------------------------------------------------------------------------
- * ------- RELEASE A SET OF PAGES AFTER EXECUTING THE LOG ON IT. -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::releasePrPages(Signal* signal)
-{
- UintR trppIndex;
-
- for (trppIndex = 0; trppIndex <= 7; trppIndex++) {
- jam();
- logPagePtr.i = pageRefPtr.p->pageRef[trppIndex];
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- releaseLogpage(signal);
- }//for
-}//Dblqh::releasePrPages()
-
-/* --------------------------------------------------------------------------
- * ------- RELEASE OPERATION FROM WAIT QUEUE LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME : RWA
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseWaitQueue(Signal* signal)
-{
- TcConnectionrecPtr rwaTcNextConnectptr;
- TcConnectionrecPtr rwaTcPrevConnectptr;
-
- fragptr.i = tcConnectptr.p->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- rwaTcPrevConnectptr.i = tcConnectptr.p->prevTc;
- rwaTcNextConnectptr.i = tcConnectptr.p->nextTc;
- if (tcConnectptr.p->listState != TcConnectionrec::WAIT_QUEUE_LIST) {
- jam();
- systemError(signal, __LINE__);
- }//if
- tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
- if (rwaTcNextConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(rwaTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- rwaTcNextConnectptr.p->prevTc = rwaTcPrevConnectptr.i;
- } else {
- jam();
- fragptr.p->lastWaitQueue = rwaTcPrevConnectptr.i;
- }//if
- if (rwaTcPrevConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(rwaTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- rwaTcPrevConnectptr.p->nextTc = rwaTcNextConnectptr.i;
- } else {
- jam();
- fragptr.p->firstWaitQueue = rwaTcNextConnectptr.i;
- }//if
-}//Dblqh::releaseWaitQueue()
-
-/* --------------------------------------------------------------------------
- * ------- REMOVE OPERATION RECORD FROM LIST ON LOG PART OF NOT -------
- * COMPLETED OPERATIONS IN THE LOG.
- *
- * SUBROUTINE SHORT NAME = RLO
- * ------------------------------------------------------------------------- */
-void Dblqh::removeLogTcrec(Signal* signal)
-{
- TcConnectionrecPtr rloTcNextConnectptr;
- TcConnectionrecPtr rloTcPrevConnectptr;
- rloTcPrevConnectptr.i = tcConnectptr.p->prevLogTcrec;
- rloTcNextConnectptr.i = tcConnectptr.p->nextLogTcrec;
- if (rloTcNextConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
- } else {
- jam();
- logPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
- }//if
- if (rloTcPrevConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
- } else {
- jam();
- logPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
- }//if
-}//Dblqh::removeLogTcrec()
-
-/* --------------------------------------------------------------------------
- * ------- REMOVE PAGE REFERENCE RECORD FROM LIST IN THIS LOG PART -------
- *
- * SUBROUTINE SHORT NAME = RPR
- * ------------------------------------------------------------------------- */
-void Dblqh::removePageRef(Signal* signal)
-{
- PageRefRecordPtr rprPageRefPtr;
-
- pageRefPtr.i = logPartPtr.p->firstPageRef;
- if (pageRefPtr.i != RNIL) {
- jam();
- ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
- if (pageRefPtr.p->prNext == RNIL) {
- jam();
- logPartPtr.p->lastPageRef = RNIL;
- logPartPtr.p->firstPageRef = RNIL;
- } else {
- jam();
- logPartPtr.p->firstPageRef = pageRefPtr.p->prNext;
- rprPageRefPtr.i = pageRefPtr.p->prNext;
- ptrCheckGuard(rprPageRefPtr, cpageRefFileSize, pageRefRecord);
- rprPageRefPtr.p->prPrev = RNIL;
- }//if
- releasePageRef(signal);
- }//if
-}//Dblqh::removePageRef()
-
-/* ------------------------------------------------------------------------- */
-/* ------- RETURN FROM EXECUTION OF LOG ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-Uint32 Dblqh::returnExecLog(Signal* signal)
-{
- tcConnectptr.p->connectState = TcConnectionrec::CONNECTED;
- initLogPointers(signal);
- logPartPtr.p->execSrExecuteIndex++;
- Uint32 result = checkIfExecLog(signal);
- if (result == ZOK) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* THIS LOG RECORD WILL BE EXECUTED AGAIN TOWARDS ANOTHER NODE. */
-/* ------------------------------------------------------------------------- */
- logPagePtr.i = logPartPtr.p->execSrLogPage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] =
- logPartPtr.p->execSrLogPageIndex;
- } else {
- jam();
-/* ------------------------------------------------------------------------- */
-/* NO MORE EXECUTION OF THIS LOG RECORD. */
-/* ------------------------------------------------------------------------- */
- if (logPartPtr.p->logExecState ==
- LogPartRecord::LES_EXEC_LOGREC_FROM_FILE) {
- jam();
-/* ------------------------------------------------------------------------- */
-/* THE LOG RECORD WAS READ FROM DISK. RELEASE ITS PAGES IMMEDIATELY. */
-/* ------------------------------------------------------------------------- */
- lfoPtr.i = logPartPtr.p->execSrLfoRec;
- ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
- releaseLfoPages(signal);
- releaseLfo(signal);
- logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG;
- if (logPartPtr.p->execSrExecLogFile != logPartPtr.p->currentLogfile) {
- jam();
- LogFileRecordPtr clfLogFilePtr;
- clfLogFilePtr.i = logPartPtr.p->execSrExecLogFile;
- ptrCheckGuard(clfLogFilePtr, clogFileFileSize, logFileRecord);
- clfLogFilePtr.p->logFileStatus = LogFileRecord::CLOSING_EXEC_LOG;
- closeFile(signal, clfLogFilePtr, __LINE__);
- result = ZCLOSE_FILE;
- }//if
- }//if
- logPartPtr.p->execSrExecuteIndex = 0;
- logPartPtr.p->execSrLogPage = RNIL;
- logPartPtr.p->execSrLogPageIndex = ZNIL;
- logPagePtr.i = logFilePtr.p->currentLogpage;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPartPtr.p->savePageIndex;
- }//if
- return result;
-}//Dblqh::returnExecLog()
-
-/* --------------------------------------------------------------------------
- * ------- SEIZE ADD FRAGMENT RECORD ------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::seizeAddfragrec(Signal* signal)
-{
- addfragptr.i = cfirstfreeAddfragrec;
- ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
- cfirstfreeAddfragrec = addfragptr.p->nextAddfragrec;
-}//Dblqh::seizeAddfragrec()
-
-/* --------------------------------------------------------------------------
- * ------- SEIZE FRAGMENT RECORD -------
- *
- * ------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------------- */
-/* ------- SEIZE A PAGE REFERENCE RECORD. ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::seizePageRef(Signal* signal)
-{
- pageRefPtr.i = cfirstfreePageRef;
- ptrCheckGuard(pageRefPtr, cpageRefFileSize, pageRefRecord);
- cfirstfreePageRef = pageRefPtr.p->prNext;
- pageRefPtr.p->prNext = RNIL;
-}//Dblqh::seizePageRef()
-
-/* --------------------------------------------------------------------------
- * ------- SEND ABORTED -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::sendAborted(Signal* signal)
-{
- UintR TlastInd;
- if (tcConnectptr.p->nextReplica == ZNIL) {
- TlastInd = ZTRUE;
- } else {
- TlastInd = ZFALSE;
- }//if
- signal->theData[0] = tcConnectptr.p->tcOprec;
- signal->theData[1] = tcConnectptr.p->transid[0];
- signal->theData[2] = tcConnectptr.p->transid[1];
- signal->theData[3] = cownNodeid;
- signal->theData[4] = TlastInd;
- sendSignal(tcConnectptr.p->tcBlockref, GSN_ABORTED, signal, 5, JBB);
- return;
-}//Dblqh::sendAborted()
-
-/* --------------------------------------------------------------------------
- * ------- SEND LQH_TRANSCONF -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::sendLqhTransconf(Signal* signal, LqhTransConf::OperationStatus stat)
-{
- tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
- ptrCheckGuard(tcNodeFailptr, ctcNodeFailrecFileSize, tcNodeFailRecord);
-
- Uint32 reqInfo = 0;
- LqhTransConf::setReplicaType(reqInfo, tcConnectptr.p->replicaType);
- LqhTransConf::setReplicaNo(reqInfo, tcConnectptr.p->seqNoReplica);
- LqhTransConf::setLastReplicaNo(reqInfo, tcConnectptr.p->lastReplicaNo);
- LqhTransConf::setSimpleFlag(reqInfo, tcConnectptr.p->opSimple);
- LqhTransConf::setDirtyFlag(reqInfo, tcConnectptr.p->dirtyOp);
- LqhTransConf::setOperation(reqInfo, tcConnectptr.p->operation);
-
- LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
- lqhTransConf->tcRef = tcNodeFailptr.p->newTcRef;
- lqhTransConf->lqhNodeId = cownNodeid;
- lqhTransConf->operationStatus = stat;
- lqhTransConf->lqhConnectPtr = tcConnectptr.i;
- lqhTransConf->transId1 = tcConnectptr.p->transid[0];
- lqhTransConf->transId2 = tcConnectptr.p->transid[1];
- lqhTransConf->oldTcOpRec = tcConnectptr.p->tcOprec;
- lqhTransConf->requestInfo = reqInfo;
- lqhTransConf->gci = tcConnectptr.p->gci;
- lqhTransConf->nextNodeId1 = tcConnectptr.p->nextReplica;
- lqhTransConf->nextNodeId2 = tcConnectptr.p->nodeAfterNext[0];
- lqhTransConf->nextNodeId3 = tcConnectptr.p->nodeAfterNext[1];
- lqhTransConf->apiRef = tcConnectptr.p->applRef;
- lqhTransConf->apiOpRec = tcConnectptr.p->applOprec;
- lqhTransConf->tableId = tcConnectptr.p->tableref;
- sendSignal(tcNodeFailptr.p->newTcBlockref, GSN_LQH_TRANSCONF,
- signal, LqhTransConf::SignalLength, JBB);
- tcNodeFailptr.p->tcRecNow = tcConnectptr.i + 1;
- signal->theData[0] = ZLQH_TRANS_NEXT;
- signal->theData[1] = tcNodeFailptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
-}//Dblqh::sendLqhTransconf()
-
-/* --------------------------------------------------------------------------
- * ------- START ANOTHER PHASE OF LOG EXECUTION -------
- * RESET THE VARIABLES NEEDED BY THIS PROCESS AND SEND THE START SIGNAL
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::startExecSr(Signal* signal)
-{
- cnoFragmentsExecSr = 0;
- cnoOutstandingExecFragReq = 0;
- c_lcp_complete_fragments.first(fragptr);
- signal->theData[0] = fragptr.i;
- sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
-}//Dblqh::startExecSr()
-
-/* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
- * ¤¤¤¤¤¤¤ LOG MODULE ¤¤¤¤¤¤¤
- * ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ */
-/* --------------------------------------------------------------------------
- * ------- STEP FORWARD IN FRAGMENT LOG DURING LOG EXECUTION -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::stepAhead(Signal* signal, Uint32 stepAheadWords)
-{
- UintR tsaPos;
-
- tsaPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- while ((stepAheadWords + tsaPos) >= ZPAGE_SIZE) {
- jam();
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_SIZE;
- stepAheadWords = stepAheadWords - (ZPAGE_SIZE - tsaPos);
- logFilePtr.p->currentLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
- logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
- logFilePtr.p->currentFilepage++;
- ptrCheckGuardErr(logPagePtr, clogPageFileSize, logPageRecord,
- NDBD_EXIT_SR_REDOLOG);
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
- logPartPtr.p->execSrPagesRead--;
- logPartPtr.p->execSrPagesExecuted++;
- tsaPos = ZPAGE_HEADER_SIZE;
- }//while
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = stepAheadWords + tsaPos;
-}//Dblqh::stepAhead()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE A ABORT LOG RECORD -------
- *
- * SUBROUTINE SHORT NAME: WAL
- * ------------------------------------------------------------------------- */
-void Dblqh::writeAbortLog(Signal* signal)
-{
- if ((ZABORT_LOG_SIZE + ZNEXT_LOG_SIZE) >
- logFilePtr.p->remainingWordsInMbyte) {
- jam();
- changeMbyte(signal);
- }//if
- logFilePtr.p->remainingWordsInMbyte =
- logFilePtr.p->remainingWordsInMbyte - ZABORT_LOG_SIZE;
- writeLogWord(signal, ZABORT_TYPE);
- writeLogWord(signal, tcConnectptr.p->transid[0]);
- writeLogWord(signal, tcConnectptr.p->transid[1]);
-}//Dblqh::writeAbortLog()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE A COMMIT LOG RECORD -------
- *
- * SUBROUTINE SHORT NAME: WCL
- * ------------------------------------------------------------------------- */
-void Dblqh::writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr)
-{
- LogFileRecordPtr regLogFilePtr;
- LogPageRecordPtr regLogPagePtr;
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- regLogFilePtr.i = regLogPartPtr.p->currentLogfile;
- ptrCheckGuard(regLogFilePtr, clogFileFileSize, logFileRecord);
- regLogPagePtr.i = regLogFilePtr.p->currentLogpage;
- Uint32 twclTmp = regLogFilePtr.p->remainingWordsInMbyte;
- ptrCheckGuard(regLogPagePtr, clogPageFileSize, logPageRecord);
- logPartPtr = regLogPartPtr;
- logFilePtr = regLogFilePtr;
- logPagePtr = regLogPagePtr;
- if ((ZCOMMIT_LOG_SIZE + ZNEXT_LOG_SIZE) > twclTmp) {
- jam();
- changeMbyte(signal);
- twclTmp = logFilePtr.p->remainingWordsInMbyte;
- }//if
-
- Uint32 twclLogPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- Uint32 tableId = regTcPtr->tableref;
- Uint32 schemaVersion = regTcPtr->schemaVersion;
- Uint32 fragId = regTcPtr->fragmentid;
- Uint32 fileNo = regTcPtr->logStartFileNo;
- Uint32 startPageNo = regTcPtr->logStartPageNo;
- Uint32 pageIndex = regTcPtr->logStartPageIndex;
- Uint32 stopPageNo = regTcPtr->logStopPageNo;
- Uint32 gci = regTcPtr->gci;
- logFilePtr.p->remainingWordsInMbyte = twclTmp - ZCOMMIT_LOG_SIZE;
-
- if ((twclLogPos + ZCOMMIT_LOG_SIZE) >= ZPAGE_SIZE) {
- writeLogWord(signal, ZCOMMIT_TYPE);
- writeLogWord(signal, tableId);
- writeLogWord(signal, schemaVersion);
- writeLogWord(signal, fragId);
- writeLogWord(signal, fileNo);
- writeLogWord(signal, startPageNo);
- writeLogWord(signal, pageIndex);
- writeLogWord(signal, stopPageNo);
- writeLogWord(signal, gci);
- } else {
- Uint32* dataPtr = &logPagePtr.p->logPageWord[twclLogPos];
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = twclLogPos + ZCOMMIT_LOG_SIZE;
- dataPtr[0] = ZCOMMIT_TYPE;
- dataPtr[1] = tableId;
- dataPtr[2] = schemaVersion;
- dataPtr[3] = fragId;
- dataPtr[4] = fileNo;
- dataPtr[5] = startPageNo;
- dataPtr[6] = pageIndex;
- dataPtr[7] = stopPageNo;
- dataPtr[8] = gci;
- }//if
- TcConnectionrecPtr rloTcNextConnectptr;
- TcConnectionrecPtr rloTcPrevConnectptr;
- rloTcPrevConnectptr.i = regTcPtr->prevLogTcrec;
- rloTcNextConnectptr.i = regTcPtr->nextLogTcrec;
- if (rloTcNextConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(rloTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- rloTcNextConnectptr.p->prevLogTcrec = rloTcPrevConnectptr.i;
- } else {
- regLogPartPtr.p->lastLogTcrec = rloTcPrevConnectptr.i;
- }//if
- if (rloTcPrevConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(rloTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- rloTcPrevConnectptr.p->nextLogTcrec = rloTcNextConnectptr.i;
- } else {
- regLogPartPtr.p->firstLogTcrec = rloTcNextConnectptr.i;
- }//if
-}//Dblqh::writeCommitLog()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE A COMPLETED GCI LOG RECORD -------
- *
- * SUBROUTINE SHORT NAME: WCG
-// Input Pointers:
-// logFilePtr
-// logPartPtr
- * ------------------------------------------------------------------------- */
-void Dblqh::writeCompletedGciLog(Signal* signal)
-{
- if ((ZCOMPLETED_GCI_LOG_SIZE + ZNEXT_LOG_SIZE) >
- logFilePtr.p->remainingWordsInMbyte) {
- jam();
- changeMbyte(signal);
- }//if
-
- logFilePtr.p->remainingWordsInMbyte =
- logFilePtr.p->remainingWordsInMbyte - ZCOMPLETED_GCI_LOG_SIZE;
-
- if (DEBUG_REDO)
- ndbout_c("writeCompletedGciLog gci: %u part: %u file: %u page: %u",
- cnewestCompletedGci,
- logPartPtr.i,
- logFilePtr.p->fileNo,
- logFilePtr.p->currentFilepage);
-
- writeLogWord(signal, ZCOMPLETED_GCI_TYPE);
- writeLogWord(signal, cnewestCompletedGci);
- logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci;
-}//Dblqh::writeCompletedGciLog()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE A DIRTY PAGE DURING LOG EXECUTION -------
- *
- * SUBROUTINE SHORT NAME: WD
- * ------------------------------------------------------------------------- */
-void Dblqh::writeDirty(Signal* signal, Uint32 place)
-{
- logPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
-
- ndbassert(logPartPtr.p->prevFilepage ==
- logPagePtr.p->logPageWord[ZPOS_PAGE_NO]);
- writeDbgInfoPageHeader(logPagePtr, place, logPartPtr.p->prevFilepage,
- ZPAGE_SIZE);
- // Calculate checksum for page
- logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
-
- seizeLfo(signal);
- initLfo(signal);
- lfoPtr.p->lfoPageNo = logPartPtr.p->prevFilepage;
- lfoPtr.p->noPagesRw = 1;
- lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_DIRTY;
- lfoPtr.p->firstLfoPage = logPagePtr.i;
- signal->theData[0] = logFilePtr.p->fileRef;
- signal->theData[1] = cownref;
- signal->theData[2] = lfoPtr.i;
- signal->theData[3] = ZLIST_OF_PAIRS_SYNCH;
- signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD;
- signal->theData[5] = 1;
- signal->theData[6] = logPagePtr.i;
- signal->theData[7] = logPartPtr.p->prevFilepage;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
-
- if (DEBUG_REDO)
- ndbout_c("writeDirty 1 page at part: %u file: %u pos: %u",
- logPartPtr.i,
- logFilePtr.p->fileNo,
- logPartPtr.p->prevFilepage);
-
-}//Dblqh::writeDirty()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE A WORD INTO THE LOG, CHECK FOR NEW PAGE -------
- *
- * SUBROUTINE SHORT NAME: WLW
- * ------------------------------------------------------------------------- */
-void Dblqh::writeLogWord(Signal* signal, Uint32 data)
-{
- Uint32 logPos = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX];
- ndbrequire(logPos < ZPAGE_SIZE);
- logPagePtr.p->logPageWord[logPos] = data;
- logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + 1;
- if ((logPos + 1) == ZPAGE_SIZE) {
- jam();
- completedLogPage(signal, ZNORMAL, __LINE__);
- seizeLogpage(signal);
- initLogpage(signal);
- logFilePtr.p->currentLogpage = logPagePtr.i;
- logFilePtr.p->currentFilepage++;
- }//if
-}//Dblqh::writeLogWord()
-
-/* --------------------------------------------------------------------------
- * ------- WRITE A NEXT LOG RECORD AND CHANGE TO NEXT MBYTE -------
- *
- * SUBROUTINE SHORT NAME: WNL
-// Input Pointers:
-// logFilePtr(Redefines)
-// logPagePtr (Redefines)
-// logPartPtr
- * ------------------------------------------------------------------------- */
-void Dblqh::writeNextLog(Signal* signal)
-{
- LogFileRecordPtr wnlNextLogFilePtr;
- UintR twnlNextFileNo;
- UintR twnlNewMbyte;
- UintR twnlRemWords;
- UintR twnlNextMbyte;
-
-/* -------------------------------------------------- */
-/* CALCULATE THE NEW NUMBER OF REMAINING WORDS */
-/* AS 128*2036 WHERE 128 * 8 KBYTE = 1 MBYTE */
-/* AND 2036 IS THE NUMBER OF WORDS IN A PAGE */
-/* THAT IS USED FOR LOG INFORMATION. */
-/* -------------------------------------------------- */
- twnlRemWords = ZPAGE_SIZE - ZPAGE_HEADER_SIZE;
- twnlRemWords = twnlRemWords * ZPAGES_IN_MBYTE;
- wnlNextLogFilePtr.i = logFilePtr.p->nextLogFile;
- ptrCheckGuard(wnlNextLogFilePtr, clogFileFileSize, logFileRecord);
-/* -------------------------------------------------- */
-/* WRITE THE NEXT LOG RECORD. */
-/* -------------------------------------------------- */
- ndbrequire(logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] < ZPAGE_SIZE);
- logPagePtr.p->logPageWord[logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]] =
- ZNEXT_MBYTE_TYPE;
- if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
- jam();
-/* -------------------------------------------------- */
-/* CALCULATE THE NEW REMAINING WORDS WHEN */
-/* CHANGING LOG FILE IS PERFORMED */
-/* -------------------------------------------------- */
- twnlRemWords = twnlRemWords - (ZPAGE_SIZE - ZPAGE_HEADER_SIZE);
-/* -------------------------------------------------- */
-/* ENSURE THAT THE LOG PAGES ARE WRITTEN AFTER */
-/* WE HAVE CHANGED MBYTE. */
-/* -------------------------------------------------- */
-/* ENSURE LAST PAGE IN PREVIOUS MBYTE IS */
-/* WRITTEN AND THAT THE STATE OF THE WRITE IS */
-/* PROPERLY SET. */
-/* -------------------------------------------------- */
-/* WE HAVE TO CHANGE LOG FILE */
-/* -------------------------------------------------- */
- completedLogPage(signal, ZLAST_WRITE_IN_FILE, __LINE__);
- if (wnlNextLogFilePtr.p->fileNo == 0) {
- jam();
-/* -------------------------------------------------- */
-/* WE HAVE FINALISED A LOG LAP, START FROM LOG */
-/* FILE 0 AGAIN */
-/* -------------------------------------------------- */
- logPartPtr.p->logLap++;
- }//if
- logPartPtr.p->currentLogfile = wnlNextLogFilePtr.i;
- logFilePtr.i = wnlNextLogFilePtr.i;
- logFilePtr.p = wnlNextLogFilePtr.p;
- twnlNewMbyte = 0;
- } else {
- jam();
-/* -------------------------------------------------- */
-/* INCREMENT THE CURRENT MBYTE */
-/* SET PAGE INDEX TO PAGE HEADER SIZE */
-/* -------------------------------------------------- */
- completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
- twnlNewMbyte = logFilePtr.p->currentMbyte + 1;
- }//if
-/* -------------------------------------------------- */
-/* CHANGE TO NEW LOG FILE IF NECESSARY */
-/* UPDATE THE FILE POSITION TO THE NEW MBYTE */
-/* FOUND IN PAGE PART OF TNEXT_LOG_PTR */
-/* ALLOCATE AND INITIATE A NEW PAGE SINCE WE */
-/* HAVE SENT THE PREVIOUS PAGE TO DISK. */
-/* SET THE NEW NUMBER OF REMAINING WORDS IN THE */
-/* NEW MBYTE ALLOCATED. */
-/* -------------------------------------------------- */
- logFilePtr.p->currentMbyte = twnlNewMbyte;
- logFilePtr.p->filePosition = twnlNewMbyte * ZPAGES_IN_MBYTE;
- logFilePtr.p->currentFilepage = twnlNewMbyte * ZPAGES_IN_MBYTE;
- logFilePtr.p->remainingWordsInMbyte = twnlRemWords;
- seizeLogpage(signal);
- if (logFilePtr.p->currentMbyte == 0) {
- jam();
- logFilePtr.p->lastPageWritten = 0;
- if (logFilePtr.p->fileNo == 0) {
- jam();
- releaseLogpage(signal);
- logPagePtr.i = logFilePtr.p->logPageZero;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
- }//if
- }//if
- initLogpage(signal);
- logFilePtr.p->currentLogpage = logPagePtr.i;
- if (logFilePtr.p->currentMbyte == 0) {
- jam();
-/* -------------------------------------------------- */
-/* THIS IS A NEW FILE, WRITE THE FILE DESCRIPTOR*/
-/* ALSO OPEN THE NEXT LOG FILE TO ENSURE THAT */
-/* THIS FILE IS OPEN WHEN ITS TURN COMES. */
-/* -------------------------------------------------- */
- writeFileHeaderOpen(signal, ZNORMAL);
- openNextLogfile(signal);
- logFilePtr.p->fileChangeState = LogFileRecord::BOTH_WRITES_ONGOING;
- }//if
- if (logFilePtr.p->fileNo == logPartPtr.p->logTailFileNo) {
- if (logFilePtr.p->currentMbyte == logPartPtr.p->logTailMbyte) {
- jam();
-/* -------------------------------------------------- */
-/* THE HEAD AND TAIL HAS MET. THIS SHOULD NEVER */
-/* OCCUR. CAN HAPPEN IF THE LOCAL CHECKPOINTS */
-/* TAKE FAR TOO LONG TIME. SO TIMING PROBLEMS */
-/* CAN INVOKE THIS SYSTEM CRASH. HOWEVER ONLY */
-/* VERY SERIOUS TIMING PROBLEMS. */
-/* -------------------------------------------------- */
- systemError(signal, __LINE__);
- }//if
- }//if
- if (logFilePtr.p->currentMbyte == (clogFileSize - 1)) {
- jam();
- twnlNextMbyte = 0;
- if (logFilePtr.p->fileChangeState != LogFileRecord::NOT_ONGOING) {
- jam();
- logPartPtr.p->logPartState = LogPartRecord::FILE_CHANGE_PROBLEM;
- }//if
- twnlNextFileNo = wnlNextLogFilePtr.p->fileNo;
- } else {
- jam();
- twnlNextMbyte = logFilePtr.p->currentMbyte + 1;
- twnlNextFileNo = logFilePtr.p->fileNo;
- }//if
- if (twnlNextFileNo == logPartPtr.p->logTailFileNo) {
- if (logPartPtr.p->logTailMbyte == twnlNextMbyte) {
- jam();
-/* -------------------------------------------------- */
-/* THE NEXT MBYTE WILL BE THE TAIL. WE MUST */
-/* STOP LOGGING NEW OPERATIONS. THIS OPERATION */
-/* ALLOWED TO PASS. ALSO COMMIT, NEXT, COMPLETED*/
-/* GCI, ABORT AND FRAGMENT SPLIT IS ALLOWED. */
-/* OPERATIONS ARE ALLOWED AGAIN WHEN THE TAIL */
-/* IS MOVED FORWARD AS A RESULT OF A START_LCP */
-/* _ROUND SIGNAL ARRIVING FROM DBDIH. */
-/* -------------------------------------------------- */
- logPartPtr.p->logPartState = LogPartRecord::TAIL_PROBLEM;
- }//if
- }//if
-}//Dblqh::writeNextLog()
-
-void
-Dblqh::execDUMP_STATE_ORD(Signal* signal)
-{
- jamEntry();
- DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
- Uint32 arg= dumpState->args[0];
- if(dumpState->args[0] == DumpStateOrd::CommitAckMarkersSize){
- infoEvent("LQH: m_commitAckMarkerPool: %d free size: %d",
- m_commitAckMarkerPool.getNoOfFree(),
- m_commitAckMarkerPool.getSize());
- }
- if(dumpState->args[0] == DumpStateOrd::CommitAckMarkersDump){
- infoEvent("LQH: m_commitAckMarkerPool: %d free size: %d",
- m_commitAckMarkerPool.getNoOfFree(),
- m_commitAckMarkerPool.getSize());
-
- CommitAckMarkerIterator iter;
- for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
- m_commitAckMarkerHash.next(iter)){
- infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
- " ApiRef: 0x%x apiOprec: 0x%x TcNodeId: %d",
- iter.curr.i,
- iter.curr.p->transid1,
- iter.curr.p->transid2,
- iter.curr.p->apiRef,
- iter.curr.p->apiOprec,
- iter.curr.p->tcNodeId);
- }
- }
-
- // Dump info about number of log pages
- if(dumpState->args[0] == DumpStateOrd::LqhDumpNoLogPages){
- infoEvent("LQH: Log pages : %d Free: %d",
- clogPageFileSize,
- cnoOfLogPages);
- }
-
- // Dump all defined tables that LQH knowns about
- if(dumpState->args[0] == DumpStateOrd::LqhDumpAllDefinedTabs){
- for(Uint32 i = 0; i<ctabrecFileSize; i++){
- TablerecPtr tabPtr;
- tabPtr.i = i;
- ptrAss(tabPtr, tablerec);
- if(tabPtr.p->tableStatus != Tablerec::NOT_DEFINED){
- infoEvent("Table %d Status: %d Usage: %d",
- i, tabPtr.p->tableStatus, tabPtr.p->usageCount);
-
- for (Uint32 j = 0; j<MAX_FRAG_PER_NODE; j++)
- {
- FragrecordPtr fragPtr;
- if ((fragPtr.i = tabPtr.p->fragrec[j]) != RNIL)
- {
- c_fragment_pool.getPtr(fragPtr);
- infoEvent(" frag: %d distKey: %u",
- tabPtr.p->fragid[j],
- fragPtr.p->fragDistributionKey);
- }
- }
- }
- }
- return;
- }
-
- // Dump all ScanRecords
- if (dumpState->args[0] == DumpStateOrd::LqhDumpAllScanRec){
- Uint32 recordNo = 0;
- if (signal->length() == 1)
- infoEvent("LQH: Dump all ScanRecords - size: %d",
- cscanrecFileSize);
- else if (signal->length() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
-
- if (recordNo < cscanrecFileSize-1){
- dumpState->args[0] = DumpStateOrd::LqhDumpAllScanRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- return;
- }
-
- // Dump all active ScanRecords
- if (dumpState->args[0] == DumpStateOrd::LqhDumpAllActiveScanRec){
- Uint32 recordNo = 0;
- if (signal->length() == 1)
- infoEvent("LQH: Dump active ScanRecord - size: %d",
- cscanrecFileSize);
- else if (signal->length() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- ScanRecordPtr sp;
- sp.i = recordNo;
- c_scanRecordPool.getPtr(scanptr);
- if (sp.p->scanState != ScanRecord::SCAN_FREE){
- dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
- }
-
- if (recordNo < cscanrecFileSize-1){
- dumpState->args[0] = DumpStateOrd::LqhDumpAllActiveScanRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- return;
- }
-
- if(dumpState->args[0] == DumpStateOrd::LqhDumpOneScanRec){
- Uint32 recordNo = RNIL;
- if (signal->length() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- if (recordNo >= cscanrecFileSize)
- return;
-
- ScanRecordPtr sp;
- sp.i = recordNo;
- c_scanRecordPool.getPtr(sp);
- infoEvent("Dblqh::ScanRecord[%d]: state=%d, type=%d, "
- "complStatus=%d, scanNodeId=%d",
- sp.i,
- sp.p->scanState,
- sp.p->scanType,
- sp.p->scanCompletedStatus,
- sp.p->scanNodeId);
- infoEvent(" apiBref=0x%x, scanAccPtr=%d",
- sp.p->scanApiBlockref,
- sp.p->scanAccPtr);
- infoEvent(" copyptr=%d, ailen=%d, complOps=%d, concurrOps=%d",
- sp.p->copyPtr,
- sp.p->scanAiLength,
- sp.p->m_curr_batch_size_rows,
- sp.p->m_max_batch_size_rows);
- infoEvent(" errCnt=%d, schV=%d",
- sp.p->scanErrorCounter,
- sp.p->scanSchemaVersion);
- infoEvent(" stpid=%d, flag=%d, lhold=%d, lmode=%d, num=%d",
- sp.p->scanStoredProcId,
- sp.p->scanFlag,
- sp.p->scanLockHold,
- sp.p->scanLockMode,
- sp.p->scanNumber);
- infoEvent(" relCount=%d, TCwait=%d, TCRec=%d, KIflag=%d",
- sp.p->scanReleaseCounter,
- sp.p->scanTcWaiting,
- sp.p->scanTcrec,
- sp.p->scanKeyinfoFlag);
- return;
- }
- if(dumpState->args[0] == DumpStateOrd::LqhDumpLcpState){
-
- infoEvent("== LQH LCP STATE ==");
- infoEvent(" clcpCompletedState=%d, c_lcpId=%d, cnoOfFragsCheckpointed=%d",
- clcpCompletedState,
- c_lcpId,
- cnoOfFragsCheckpointed);
-
- LcpRecordPtr TlcpPtr;
- // Print information about the current local checkpoint
- TlcpPtr.i = 0;
- ptrAss(TlcpPtr, lcpRecord);
- infoEvent(" lcpState=%d lastFragmentFlag=%d",
- TlcpPtr.p->lcpState, TlcpPtr.p->lastFragmentFlag);
- infoEvent("currentFragment.fragPtrI=%d",
- TlcpPtr.p->currentFragment.fragPtrI);
- infoEvent("currentFragment.lcpFragOrd.tableId=%d",
- TlcpPtr.p->currentFragment.lcpFragOrd.tableId);
- infoEvent(" lcpQueued=%d reportEmpty=%d",
- TlcpPtr.p->lcpQueued,
- TlcpPtr.p->reportEmpty);
- char buf[8*_NDB_NODE_BITMASK_SIZE+1];
- infoEvent(" m_EMPTY_LCP_REQ=%d",
- TlcpPtr.p->m_EMPTY_LCP_REQ.getText(buf));
-
- return;
- }
-
-#ifdef ERROR_INSERT
-#ifdef NDB_DEBUG_FULL
- if(dumpState->args[0] == DumpStateOrd::LCPContinue){
- switch(cerrorInsert){
- case 5904:
- CLEAR_ERROR_INSERT_VALUE;
- g_trace_lcp.restore(*globalData.getBlock(BACKUP), signal);
- return;
- default:
- return;
- }
- }
-#endif
-#endif
-
- 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 %d",
- 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];
- if (signal->getLength() == 2)
- {
- SET_ERROR_INSERT_VALUE(5042);
- }
- else
- {
- SET_ERROR_INSERT_VALUE(dumpState->args[2]);
- }
- }
-
- TcConnectionrec *regTcConnectionrec = tcConnectionrec;
- Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- if(arg == 2306)
- {
- for(Uint32 i = 0; i<1024; i++)
- {
- TcConnectionrecPtr tcRec;
- tcRec.i = ctransidHash[i];
- while(tcRec.i != RNIL)
- {
- ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
- ndbout << "TcConnectionrec " << tcRec.i;
- signal->theData[0] = 2307;
- signal->theData[1] = tcRec.i;
- execDUMP_STATE_ORD(signal);
- tcRec.i = tcRec.p->nextHashRec;
- }
- }
- }
-
- if(arg == 2307 || arg == 2308)
- {
- TcConnectionrecPtr tcRec;
- tcRec.i = signal->theData[1];
- ptrCheckGuard(tcRec, ttcConnectrecFileSize, regTcConnectionrec);
-
- ndbout << " transactionState = " << tcRec.p->transactionState<<endl;
- ndbout << " operation = " << tcRec.p->operation<<endl;
- ndbout << " tcNodeFailrec = " << tcRec.p->tcNodeFailrec
- << " seqNoReplica = " << tcRec.p->seqNoReplica
- << endl;
- ndbout << " replicaType = " << tcRec.p->replicaType
- << " reclenAiLqhkey = " << tcRec.p->reclenAiLqhkey
- << " opExec = " << tcRec.p->opExec
- << endl;
- ndbout << " opSimple = " << tcRec.p->opSimple
- << " nextSeqNoReplica = " << tcRec.p->nextSeqNoReplica
- << " lockType = " << tcRec.p->lockType
- << endl;
- ndbout << " lastReplicaNo = " << tcRec.p->lastReplicaNo
- << " indTakeOver = " << tcRec.p->indTakeOver
- << " dirtyOp = " << tcRec.p->dirtyOp
- << endl;
- ndbout << " activeCreat = " << tcRec.p->activeCreat
- << " tcBlockref = " << hex << tcRec.p->tcBlockref
- << " reqBlockref = " << hex << tcRec.p->reqBlockref
- << " primKeyLen = " << tcRec.p->primKeyLen
- << " nrcopyflag = " << LqhKeyReq::getNrCopyFlag(tcRec.p->reqinfo)
- << endl;
- ndbout << " nextReplica = " << tcRec.p->nextReplica
- << " tcBlockref = " << hex << tcRec.p->tcBlockref
- << " reqBlockref = " << hex << tcRec.p->reqBlockref
- << " primKeyLen = " << tcRec.p->primKeyLen
- << endl;
- ndbout << " logStopPageNo = " << tcRec.p->logStopPageNo
- << " logStartPageNo = " << tcRec.p->logStartPageNo
- << " logStartPageIndex = " << tcRec.p->logStartPageIndex
- << endl;
- ndbout << " errorCode = " << tcRec.p->errorCode
- << " clientBlockref = " << hex << tcRec.p->clientBlockref
- << " applRef = " << hex << tcRec.p->applRef
- << " totSendlenAi = " << tcRec.p->totSendlenAi
- << endl;
- ndbout << " totReclenAi = " << tcRec.p->totReclenAi
- << " tcScanRec = " << tcRec.p->tcScanRec
- << " tcScanInfo = " << tcRec.p->tcScanInfo
- << " tcOprec = " << hex << tcRec.p->tcOprec
- << endl;
- ndbout << " tableref = " << tcRec.p->tableref
- << " simpleTcConnect = " << tcRec.p->simpleTcConnect
- << " storedProcId = " << tcRec.p->storedProcId
- << " schemaVersion = " << tcRec.p->schemaVersion
- << endl;
- ndbout << " reqinfo = " << tcRec.p->reqinfo
- << " reqRef = " << tcRec.p->reqRef
- << " readlenAi = " << tcRec.p->readlenAi
- << " prevTc = " << tcRec.p->prevTc
- << endl;
- ndbout << " prevLogTcrec = " << tcRec.p->prevLogTcrec
- << " prevHashRec = " << tcRec.p->prevHashRec
- << " nodeAfterNext0 = " << tcRec.p->nodeAfterNext[0]
- << " nodeAfterNext1 = " << tcRec.p->nodeAfterNext[1]
- << endl;
- ndbout << " nextTcConnectrec = " << tcRec.p->nextTcConnectrec
- << " nextTc = " << tcRec.p->nextTc
- << " nextTcLogQueue = " << tcRec.p->nextTcLogQueue
- << " nextLogTcrec = " << tcRec.p->nextLogTcrec
- << endl;
- ndbout << " nextHashRec = " << tcRec.p->nextHashRec
- << " logWriteState = " << tcRec.p->logWriteState
- << " logStartFileNo = " << tcRec.p->logStartFileNo
- << " listState = " << tcRec.p->listState
- << endl;
- ndbout << " lastAttrinbuf = " << tcRec.p->lastAttrinbuf
- << " lastTupkeybuf = " << tcRec.p->lastTupkeybuf
- << " hashValue = " << tcRec.p->hashValue
- << endl;
- ndbout << " gci = " << tcRec.p->gci
- << " fragmentptr = " << tcRec.p->fragmentptr
- << " fragmentid = " << tcRec.p->fragmentid
- << " firstTupkeybuf = " << tcRec.p->firstTupkeybuf
- << endl;
- ndbout << " firstAttrinbuf = " << tcRec.p->firstAttrinbuf
- << " currTupAiLen = " << tcRec.p->currTupAiLen
- << " currReclenAi = " << tcRec.p->currReclenAi
- << endl;
- ndbout << " tcTimer = " << tcRec.p->tcTimer
- << " clientConnectrec = " << tcRec.p->clientConnectrec
- << " applOprec = " << hex << tcRec.p->applOprec
- << " abortState = " << tcRec.p->abortState
- << endl;
- ndbout << " transid0 = " << hex << tcRec.p->transid[0]
- << " transid1 = " << hex << tcRec.p->transid[1]
- << " tupkeyData0 = " << tcRec.p->tupkeyData[0]
- << " tupkeyData1 = " << tcRec.p->tupkeyData[1]
- << endl;
- ndbout << " tupkeyData2 = " << tcRec.p->tupkeyData[2]
- << " tupkeyData3 = " << tcRec.p->tupkeyData[3]
- << " m_nr_delete.m_cnt = " << tcRec.p->m_nr_delete.m_cnt
- << endl;
- switch (tcRec.p->transactionState) {
-
- case TcConnectionrec::SCAN_STATE_USED:
- if (tcRec.p->tcScanRec < cscanrecFileSize){
- ScanRecordPtr TscanPtr;
- c_scanRecordPool.getPtr(TscanPtr, tcRec.p->tcScanRec);
- ndbout << " scanState = " << TscanPtr.p->scanState << endl;
- //TscanPtr.p->scanLocalref[2];
- ndbout << " copyPtr="<<TscanPtr.p->copyPtr
- << " scanAccPtr="<<TscanPtr.p->scanAccPtr
- << " scanAiLength="<<TscanPtr.p->scanAiLength
- << endl;
- ndbout << " m_curr_batch_size_rows="<<
- TscanPtr.p->m_curr_batch_size_rows
- << " m_max_batch_size_rows="<<
- TscanPtr.p->m_max_batch_size_rows
- << " scanErrorCounter="<<TscanPtr.p->scanErrorCounter
- << endl;
- ndbout << " scanSchemaVersion="<<TscanPtr.p->scanSchemaVersion
- << " scanStoredProcId="<<TscanPtr.p->scanStoredProcId
- << " scanTcrec="<<TscanPtr.p->scanTcrec
- << endl;
- ndbout << " scanType="<<TscanPtr.p->scanType
- << " scanApiBlockref="<<TscanPtr.p->scanApiBlockref
- << " scanNodeId="<<TscanPtr.p->scanNodeId
- << " scanCompletedStatus="<<TscanPtr.p->scanCompletedStatus
- << endl;
- ndbout << " scanFlag="<<TscanPtr.p->scanFlag
- << " scanLockHold="<<TscanPtr.p->scanLockHold
- << " scanLockMode="<<TscanPtr.p->scanLockMode
- << " scanNumber="<<TscanPtr.p->scanNumber
- << endl;
- ndbout << " scanReleaseCounter="<<TscanPtr.p->scanReleaseCounter
- << " scanTcWaiting="<<TscanPtr.p->scanTcWaiting
- << " scanKeyinfoFlag="<<TscanPtr.p->scanKeyinfoFlag
- << endl;
- } else{
- ndbout << "No connected scan record found" << endl;
- }
- break;
- default:
- break;
- }
- ndbrequire(arg != 2308);
- }
-
-#ifdef ERROR_INSERT
- if (arg == 5712 || arg == 5713)
- {
- if (arg == 5712)
- {
- traceopout = &ndbout;
- }
- else if (arg == 5713)
- {
- traceopout = tracenrout;
- }
- SET_ERROR_INSERT_VALUE(arg);
- }
-#endif
-
-}//Dblqh::execDUMP_STATE_ORD()
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* ---------------------- TRIGGER HANDLING ------------------------ */
-/* ---------------------------------------------------------------- */
-/* */
-/* All trigger signals from TRIX are forwarded top TUP */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-// Trigger signals
-void
-Dblqh::execCREATE_TRIG_REQ(Signal* signal)
-{
- jamEntry();
-
- sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ, signal,
- CreateTrigReq::SignalLength, JBB);
-}
-
-void
-Dblqh::execCREATE_TRIG_CONF(Signal* signal)
-{
- jamEntry();
-
- sendSignal(DBDICT_REF, GSN_CREATE_TRIG_CONF, signal,
- CreateTrigConf::SignalLength, JBB);
-}
-
-void
-Dblqh::execCREATE_TRIG_REF(Signal* signal)
-{
- jamEntry();
-
- sendSignal(DBDICT_REF, GSN_CREATE_TRIG_REF, signal,
- CreateTrigRef::SignalLength, JBB);
-}
-
-void
-Dblqh::execDROP_TRIG_REQ(Signal* signal)
-{
- jamEntry();
-
- sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ, signal,
- DropTrigReq::SignalLength, JBB);
-}
-
-void
-Dblqh::execDROP_TRIG_CONF(Signal* signal)
-{
- jamEntry();
-
- sendSignal(DBDICT_REF, GSN_DROP_TRIG_CONF, signal,
- DropTrigConf::SignalLength, JBB);
-}
-
-void
-Dblqh::execDROP_TRIG_REF(Signal* signal)
-{
- jamEntry();
-
- sendSignal(DBDICT_REF, GSN_DROP_TRIG_REF, signal,
- DropTrigRef::SignalLength, JBB);
-}
-
-Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){
- Uint32 checkSum = 37;
-#ifdef VM_TRACE
- for (Uint32 i = (ZPOS_CHECKSUM+1); i<ZPAGE_SIZE; i++)
- checkSum = logP.p->logPageWord[i] ^ checkSum;
-#endif
- return checkSum;
- }
-
-#ifdef NDB_DEBUG_FULL
-#ifdef ERROR_INSERT
-void
-TraceLCP::sendSignal(Uint32 ref, Uint32 gsn, Signal* signal,
- Uint32 len, Uint32 prio)
-{
- Sig s;
- s.type = Sig::Sig_send;
- s.header = signal->header;
- s.header.theVerId_signalNumber = gsn;
- s.header.theReceiversBlockNumber = ref;
- s.header.theLength = len;
- memcpy(s.theData, signal->theData, 4 * len);
- m_signals.push_back(s);
- assert(signal->getNoOfSections() == 0);
-}
-
-void
-TraceLCP::save(Signal* signal){
- Sig s;
- s.type = Sig::Sig_save;
- s.header = signal->header;
- memcpy(s.theData, signal->theData, 4 * signal->getLength());
- m_signals.push_back(s);
- assert(signal->getNoOfSections() == 0);
-}
-
-void
-TraceLCP::restore(SimulatedBlock& lqh, Signal* sig){
- Uint32 cnt = m_signals.size();
- for(Uint32 i = 0; i<cnt; i++){
- sig->header = m_signals[i].header;
- memcpy(sig->theData, m_signals[i].theData, 4 * sig->getLength());
- switch(m_signals[i].type){
- case Sig::Sig_send:
- lqh.sendSignal(sig->header.theReceiversBlockNumber,
- sig->header.theVerId_signalNumber,
- sig,
- sig->header.theLength,
- JBB);
- break;
- case Sig::Sig_save:
- lqh.executeFunction(sig->header.theVerId_signalNumber, sig);
- break;
- }
- }
- m_signals.clear();
-}
-#endif
-#endif
-
-void Dblqh::writeDbgInfoPageHeader(LogPageRecordPtr logP, Uint32 place,
- Uint32 pageNo, Uint32 wordWritten)
-{
- logP.p->logPageWord[ZPOS_LOG_TIMER]= logPartPtr.p->logTimer;
- logP.p->logPageWord[ZPOS_PREV_PAGE_NO]= logP.p->logPageWord[ZPOS_PAGE_NO];
- logP.p->logPageWord[ZPOS_PAGE_I]= logP.i;
- logP.p->logPageWord[ZPOS_PLACE_WRITTEN_FROM]= place;
- logP.p->logPageWord[ZPOS_PAGE_NO]= pageNo;
- logP.p->logPageWord[ZPOS_PAGE_FILE_NO]= logFilePtr.p->fileNo;
- logP.p->logPageWord[ZPOS_WORD_WRITTEN]= wordWritten;
- logP.p->logPageWord[ZPOS_IN_WRITING]= 1;
-}
-
-#if defined ERROR_INSERT
-void
-Dblqh::TRACE_OP_DUMP(const Dblqh::TcConnectionrec* regTcPtr, const char * pos)
-{
- (* traceopout)
- << "[ " << hex << regTcPtr->transid[0]
- << " " << hex << regTcPtr->transid[1] << " ] " << dec
- << pos
- << " " << (Operation_t)regTcPtr->operation
- << " " << regTcPtr->tableref
- << "(" << regTcPtr->fragmentid << ")"
- << "(" << (regTcPtr->seqNoReplica == 0 ? "P" : "B") << ")" ;
-
- {
- (* traceopout) << "key=[" << hex;
- Uint32 i;
- for(i = 0; i<regTcPtr->primKeyLen && i < 4; i++){
- (* traceopout) << hex << regTcPtr->tupkeyData[i] << " ";
- }
-
- DatabufPtr regDatabufptr;
- regDatabufptr.i = regTcPtr->firstTupkeybuf;
- while(i < regTcPtr->primKeyLen)
- {
- ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
- for(Uint32 j = 0; j<4 && i<regTcPtr->primKeyLen; j++, i++)
- (* traceopout) << hex << regDatabufptr.p->data[j] << " ";
- }
- (* traceopout) << "] ";
- }
-
- if (regTcPtr->m_use_rowid)
- (* traceopout) << " " << regTcPtr->m_row_id;
- (* traceopout) << endl;
-}
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dblqh/Makefile.am b/storage/ndb/src/kernel/blocks/dblqh/Makefile.am
deleted file mode 100644
index 31612b5c25e..00000000000
--- a/storage/ndb/src/kernel/blocks/dblqh/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (C) 2004-2005 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-EXTRA_PROGRAMS = ndbd_redo_log_reader
-
-ndbd_redo_log_reader_SOURCES = redoLogReader/records.cpp \
- redoLogReader/reader.cpp
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
-
-ndbd_redo_log_reader_LDFLAGS = @ndb_bin_am_ldflags@ \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a
diff --git a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/reader.cpp b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/reader.cpp
deleted file mode 100644
index ea483527c15..00000000000
--- a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/reader.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-/* Copyright (c) 2003-2005, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-//----------------------------------------------------------------
-// REDOLOGFILEREADER
-// Reads a redo log file and checks it for errors and/or prints
-// the file in a human readable format.
-//
-// Usage: redoLogFileReader <file> [-noprint] [-nocheck]
-// [-mbyte <0-15>] [-mbyteHeaders] [-pageHeaders]
-//
-//----------------------------------------------------------------
-
-
-#include <ndb_global.h>
-
-#include "records.hpp"
-
-#define RETURN_ERROR 1
-#define RETURN_OK 0
-
-#define FROM_BEGINNING 0
-
-void usage(const char * prg);
-Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords);
-void readArguments(int argc, const char** argv);
-void doExit();
-
-FILE * f= 0;
-char fileName[256];
-bool theDumpFlag = false;
-bool thePrintFlag = true;
-bool theCheckFlag = true;
-bool onlyPageHeaders = false;
-bool onlyMbyteHeaders = false;
-bool onlyFileDesc = false;
-bool firstLap = true;
-Uint32 startAtMbyte = 0;
-Uint32 startAtPage = 0;
-Uint32 startAtPageIndex = 0;
-Uint32 *redoLogPage;
-
-NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read a redo log file", 16384) {
- int wordIndex = 0;
- int oldWordIndex = 0;
- Uint32 recordType = 1234567890;
-
- PageHeader *thePageHeader;
- CompletedGCIRecord *cGCIrecord;
- PrepareOperationRecord *poRecord;
- NextLogRecord *nlRecord;
- FileDescriptor *fdRecord;
- CommitTransactionRecord *ctRecord;
- InvalidCommitTransactionRecord *ictRecord;
- NextMbyteRecord *nmRecord;
- AbortTransactionRecord *atRecord;
-
- readArguments(argc, argv);
-
- f = fopen(fileName, "rb");
- if(!f){
- perror("Error: open file");
- exit(RETURN_ERROR);
- }
-
- Uint32 tmpFileOffset = startAtMbyte * PAGESIZE * NO_PAGES_IN_MBYTE * sizeof(Uint32);
- if (fseek(f, tmpFileOffset, FROM_BEGINNING)) {
- perror("Error: Move in file");
- exit(RETURN_ERROR);
- }
-
- redoLogPage = new Uint32[PAGESIZE*NO_PAGES_IN_MBYTE];
- Uint32 words_from_previous_page = 0;
-
- // Loop for every mbyte.
- bool lastPage = false;
- for (Uint32 j = startAtMbyte; j < NO_MBYTE_IN_FILE && !lastPage; j++) {
-
- readFromFile(f, redoLogPage, PAGESIZE*NO_PAGES_IN_MBYTE);
-
- words_from_previous_page = 0;
-
- // Loop for every page.
- for (int i = 0; i < NO_PAGES_IN_MBYTE; i++) {
- wordIndex = 0;
- thePageHeader = (PageHeader *) &redoLogPage[i*PAGESIZE];
- // Print out mbyte number, page number and page index.
- ndbout << j << ":" << i << ":" << wordIndex << endl
- << " " << j*32 + i << ":" << wordIndex << " ";
- if (thePrintFlag) ndbout << (*thePageHeader);
- if (theCheckFlag) {
- if(!thePageHeader->check()) {
- ndbout << "Error in thePageHeader->check()" << endl;
- doExit();
- }
-
- Uint32 checkSum = 37;
- for (int ps = 1; ps < PAGESIZE; ps++)
- checkSum = redoLogPage[i*PAGESIZE+ps] ^ checkSum;
-
- if (checkSum != redoLogPage[i*PAGESIZE]){
- ndbout << "WRONG CHECKSUM: checksum = " << redoLogPage[i*PAGESIZE]
- << " expected = " << checkSum << endl;
- doExit();
- }
- else
- ndbout << "expected checksum: " << checkSum << endl;
-
- }
-
- lastPage = i != 0 && thePageHeader->lastPage();
- Uint32 lastWord = thePageHeader->lastWord();
-
- if (onlyMbyteHeaders) {
- // Show only the first page header in every mbyte of the file.
- break;
- }
-
- if (onlyPageHeaders) {
- // Show only page headers. Continue with the next page in this for loop.
- continue;
- }
-
-
- wordIndex = thePageHeader->getLogRecordSize() - words_from_previous_page;
- Uint32 *redoLogPagePos = redoLogPage + i*PAGESIZE;
- if (words_from_previous_page)
- {
- memmove(redoLogPagePos + wordIndex ,
- redoLogPagePos - words_from_previous_page,
- words_from_previous_page*4);
- }
-
- do {
- if (words_from_previous_page)
- {
- // Print out mbyte number, page number and word index.
- ndbout << j << ":" << i-1 << ":" << PAGESIZE-words_from_previous_page << endl
- << j << ":" << i << ":" << wordIndex+words_from_previous_page << endl
- << " " << j*32 + i-1 << ":" << PAGESIZE-words_from_previous_page << " ";
- words_from_previous_page = 0;
- }
- else
- {
- // Print out mbyte number, page number and word index.
- ndbout << j << ":" << i << ":" << wordIndex << endl
- << " " << j*32 + i << ":" << wordIndex << " ";
- }
- redoLogPagePos = redoLogPage + i*PAGESIZE + wordIndex;
- oldWordIndex = wordIndex;
- recordType = *redoLogPagePos;
- switch(recordType) {
- case ZFD_TYPE:
- fdRecord = (FileDescriptor *) redoLogPagePos;
- if (thePrintFlag) ndbout << (*fdRecord);
- if (theCheckFlag) {
- if(!fdRecord->check()) {
- ndbout << "Error in fdRecord->check()" << endl;
- doExit();
- }
- }
- if (onlyFileDesc) {
- delete [] redoLogPage;
- exit(RETURN_OK);
- }
- wordIndex += fdRecord->getLogRecordSize();
- break;
-
- case ZNEXT_LOG_RECORD_TYPE:
- nlRecord = (NextLogRecord *) redoLogPagePos;
- wordIndex += nlRecord->getLogRecordSize(wordIndex);
- if (wordIndex <= PAGESIZE) {
- if (thePrintFlag) ndbout << (*nlRecord);
- if (theCheckFlag) {
- if(!nlRecord->check()) {
- ndbout << "Error in nlRecord->check()" << endl;
- doExit();
- }
- }
- }
- break;
-
- case ZCOMPLETED_GCI_TYPE:
- cGCIrecord = (CompletedGCIRecord *) redoLogPagePos;
- wordIndex += cGCIrecord->getLogRecordSize();
- if (wordIndex <= PAGESIZE) {
- if (thePrintFlag) ndbout << (*cGCIrecord);
- if (theCheckFlag) {
- if(!cGCIrecord->check()) {
- ndbout << "Error in cGCIrecord->check()" << endl;
- doExit();
- }
- }
- }
- break;
-
- case ZPREP_OP_TYPE:
- poRecord = (PrepareOperationRecord *) redoLogPagePos;
- wordIndex += poRecord->getLogRecordSize(PAGESIZE-wordIndex);
- if (wordIndex <= PAGESIZE) {
- if (thePrintFlag) ndbout << (*poRecord);
- if (theCheckFlag) {
- if(!poRecord->check()) {
- ndbout << "Error in poRecord->check()" << endl;
- doExit();
- }
- }
- }
- break;
-
- case ZCOMMIT_TYPE:
- ctRecord = (CommitTransactionRecord *) redoLogPagePos;
- wordIndex += ctRecord->getLogRecordSize();
- if (wordIndex <= PAGESIZE) {
- if (thePrintFlag) ndbout << (*ctRecord);
- if (theCheckFlag) {
- if(!ctRecord->check()) {
- ndbout << "Error in ctRecord->check()" << endl;
- doExit();
- }
- }
- }
- break;
-
- case ZINVALID_COMMIT_TYPE:
- ictRecord = (InvalidCommitTransactionRecord *) redoLogPagePos;
- wordIndex += ictRecord->getLogRecordSize();
- if (wordIndex <= PAGESIZE) {
- if (thePrintFlag) ndbout << (*ictRecord);
- if (theCheckFlag) {
- if(!ictRecord->check()) {
- ndbout << "Error in ictRecord->check()" << endl;
- doExit();
- }
- }
- }
- break;
-
- case ZNEXT_MBYTE_TYPE:
- nmRecord = (NextMbyteRecord *) redoLogPagePos;
- if (thePrintFlag) ndbout << (*nmRecord);
- i = NO_PAGES_IN_MBYTE;
- break;
-
- case ZABORT_TYPE:
- atRecord = (AbortTransactionRecord *) redoLogPagePos;
- wordIndex += atRecord->getLogRecordSize();
- if (wordIndex <= PAGESIZE) {
- if (thePrintFlag) ndbout << (*atRecord);
- if (theCheckFlag) {
- if(!atRecord->check()) {
- ndbout << "Error in atRecord->check()" << endl;
- doExit();
- }
- }
- }
- break;
-
- case ZNEW_PREP_OP_TYPE:
- case ZFRAG_SPLIT_TYPE:
- ndbout << endl << "Record type = " << recordType << " not implemented." << endl;
- doExit();
-
- default:
- ndbout << " ------ERROR: UNKNOWN RECORD TYPE------" << endl;
-
- // Print out remaining data in this page
- for (int k = wordIndex; k < PAGESIZE; k++){
- Uint32 unknown = redoLogPage[i*PAGESIZE + k];
- ndbout_c("%-30d%-12u%-12x", k, unknown, unknown);
- }
-
- doExit();
- }
- } while(wordIndex < lastWord && i < NO_PAGES_IN_MBYTE);
-
-
- if (lastPage)
- {
- if (theDumpFlag)
- {
- ndbout << " ------PAGE END: DUMPING REST OF PAGE------" << endl;
- for (int k = wordIndex > PAGESIZE ? oldWordIndex : wordIndex;
- k < PAGESIZE; k++)
- {
- Uint32 word = redoLogPage[i*PAGESIZE + k];
- ndbout_c("%-30d%-12u%-12x", k, word, word);
- }
- }
- break;
- }
- if (wordIndex > PAGESIZE) {
- words_from_previous_page = PAGESIZE - oldWordIndex;
- ndbout << " ----------- Record continues on next page -----------" << endl;
- } else {
- wordIndex = 0;
- words_from_previous_page = 0;
- }
- ndbout << endl;
- }//for
- ndbout << endl;
- if (startAtMbyte != 0) {
- break;
- }
- }//for
- fclose(f);
- delete [] redoLogPage;
- exit(RETURN_OK);
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-Uint32 readFromFile(FILE * f, Uint32 *toPtr, Uint32 sizeInWords) {
- Uint32 noOfReadWords;
- if ( !(noOfReadWords = fread(toPtr, sizeof(Uint32), sizeInWords, f)) ) {
- ndbout << "Error reading file" << endl;
- doExit();
- }
-
- return noOfReadWords;
-}
-
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-
-void usage(const char * prg){
- ndbout << endl << "Usage: " << endl << prg
- << " <Binary log file> [-noprint] [-nocheck] [-mbyte <0-15>] "
- << "[-mbyteheaders] [-pageheaders] [-filedescriptors] [-page <0-31>] "
- << "[-pageindex <12-8191>]"
- << endl << endl;
-
-}
-void readArguments(int argc, const char** argv)
-{
- if(argc < 2 || argc > 9){
- usage(argv[0]);
- doExit();
- }
-
- strcpy(fileName, argv[1]);
- argc--;
-
- int i = 2;
- while (argc > 1)
- {
- if (strcmp(argv[i], "-noprint") == 0) {
- thePrintFlag = false;
- } else if (strcmp(argv[i], "-dump") == 0) {
- theDumpFlag = true;
- } else if (strcmp(argv[i], "-nocheck") == 0) {
- theCheckFlag = false;
- } else if (strcmp(argv[i], "-mbyteheaders") == 0) {
- onlyMbyteHeaders = true;
- } else if (strcmp(argv[i], "-pageheaders") == 0) {
- onlyPageHeaders = true;
- } else if (strcmp(argv[i], "-filedescriptors") == 0) {
- onlyFileDesc = true;
- } else if (strcmp(argv[i], "-mbyte") == 0) {
- startAtMbyte = atoi(argv[i+1]);
- if (startAtMbyte > 15) {
- usage(argv[0]);
- doExit();
- }
- argc--;
- i++;
- } else if (strcmp(argv[i], "-page") == 0) {
- startAtPage = atoi(argv[i+1]);
- if (startAtPage > 31) {
- usage(argv[0]);
- doExit();
- }
- argc--;
- i++;
- } else if (strcmp(argv[i], "-pageindex") == 0) {
- startAtPageIndex = atoi(argv[i+1]);
- if (startAtPageIndex > 8191 || startAtPageIndex < 12) {
- usage(argv[0]);
- doExit();
- }
- argc--;
- i++;
- } else {
- usage(argv[0]);
- doExit();
- }
- argc--;
- i++;
- }
-
-}
-
-void doExit() {
- ndbout << "Error in redoLogReader(). Exiting!" << endl;
- if (f) fclose(f);
- delete [] redoLogPage;
- exit(RETURN_ERROR);
-}
diff --git a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
deleted file mode 100644
index 6431b4ba9b6..00000000000
--- a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "records.hpp"
-
-void printOut(const char *string, Uint32 value) {
- ndbout_c("%-30s%-12u%-12x", string, value, value);
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-bool AbortTransactionRecord::check() {
- // Not implemented yet.
- return true;
-}
-
-Uint32 AbortTransactionRecord::getLogRecordSize() {
- return ABORTTRANSACTIONRECORDSIZE;
-}
-
-NdbOut& operator<<(NdbOut& no, const AbortTransactionRecord& atr) {
- no << "----------ABORT TRANSACTION RECORD-------------" << endl << endl;
- printOut("Record type:", atr.m_recordType);
- printOut("TransactionId1:", atr.m_transactionId1);
- printOut("TransactionId2:", atr.m_transactionId2);
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-bool NextMbyteRecord::check() {
- // Not implemented yet.
- return true;
-}
-
-Uint32 NextMbyteRecord::getLogRecordSize() {
- return NEXTMBYTERECORDSIZE;
-}
-
-NdbOut& operator<<(NdbOut& no, const NextMbyteRecord& nmr) {
- no << "----------NEXT MBYTE RECORD--------------------" << endl << endl;
- printOut("Record type:", nmr.m_recordType);
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-bool CommitTransactionRecord::check() {
- // Not implemented yet.
- return true;
-}
-
-Uint32 CommitTransactionRecord::getLogRecordSize() {
- return COMMITTRANSACTIONRECORDSIZE;
-}
-
-NdbOut& operator<<(NdbOut& no, const CommitTransactionRecord& ctr) {
- no << "----------COMMIT TRANSACTION RECORD------------" << endl << endl;
- printOut("Record type:", ctr.m_recordType);
- printOut("TableId", ctr.m_tableId);
- printOut("SchemaVersion:", ctr.m_schemaVersion);
- printOut("FfragmentId", ctr.m_fragmentId);
- printOut("File no. of Prep. Op.", ctr.m_fileNumberOfPrepareOperation);
- printOut("Start page no. of Prep. Op.", ctr.m_startPageNumberOfPrepareOperation);
- printOut("Start page index of Prep. Op.", ctr.m_startPageIndexOfPrepareOperation);
- printOut("Stop page no. of Prep. Op.", ctr.m_stopPageNumberOfPrepareOperation);
- printOut("GlobalCheckpoint", ctr.m_globalCheckpoint);
-
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-bool InvalidCommitTransactionRecord::check() {
- // Not implemented yet.
- return true;
-}
-
-Uint32 InvalidCommitTransactionRecord::getLogRecordSize() {
- return COMMITTRANSACTIONRECORDSIZE;
-}
-
-NdbOut& operator<<(NdbOut& no, const InvalidCommitTransactionRecord& ictr) {
- no << "------INVALID COMMIT TRANSACTION RECORD--------" << endl << endl;
- printOut("Record type:", ictr.m_recordType);
- printOut("TableId", ictr.m_tableId);
- printOut("FfragmentId", ictr.m_fragmentId);
- printOut("File no. of Prep. Op.", ictr.m_fileNumberOfPrepareOperation);
- printOut("Start page no. of Prep. Op.", ictr.m_startPageNumberOfPrepareOperation);
- printOut("Start page index of Prep. Op.", ictr.m_startPageIndexOfPrepareOperation);
- printOut("Stop page no. of Prep. Op.", ictr.m_stopPageNumberOfPrepareOperation);
- printOut("GlobalCheckpoint", ictr.m_globalCheckpoint);
-
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-bool PrepareOperationRecord::check() {
- // Not fully implemented.
- if (m_operationType == 3 && m_attributeLength != 0)
- return false;
-
- if (m_logRecordSize != (m_attributeLength + m_keyLength + 8))
- return false;
-
- return true;
-}
-
-Uint32 PrepareOperationRecord::getLogRecordSize(Uint32 wordsRead) {
- if (wordsRead < 2)
- return 2; // make sure we read more
- return m_logRecordSize;
-}
-
-NdbOut& operator<<(NdbOut& no, const PrepareOperationRecord& por) {
- no << "-----------PREPARE OPERATION RECORD------------" << endl << endl;
- printOut("Record type:", por.m_recordType);
- printOut("logRecordSize:", por.m_logRecordSize);
- printOut("hashValue:", por.m_hashValue);
- switch (por.m_operationType) {
- case 0:
- ndbout_c("%-30s%-12u%-6s", "operationType:",
- por.m_operationType, "read");
- break;
- case 1:
- ndbout_c("%-30s%-12u%-6s", "operationType:",
- por.m_operationType, "update");
- break;
- case 2:
- ndbout_c("%-30s%-12u%-6s", "operationType:",
- por.m_operationType, "insert");
- break;
- case 3:
- ndbout_c("%-30s%-12u%-6s", "operationType:",
- por.m_operationType, "delete");
- break;
- default:
- printOut("operationType:", por.m_operationType);
- }
- printOut("page_no: ", por.m_page_no);
- printOut("page_idx: ", por.m_page_idx);
- printOut("attributeLength:", por.m_attributeLength);
- printOut("keyLength:", por.m_keyLength);
-
-#if 1
- // Print keydata
- Uint32* p = (Uint32*)&por.m_keyInfo;
- for(Uint32 i=0; i < por.m_keyLength; i++){
- printOut("keydata:", *p);
- p++;
- }
-
- // Print attrdata
- for(Uint32 i=0; i < por.m_attributeLength; i++){
- printOut("attrdata:", *p);
- p++;
- }
-#endif
-
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-bool CompletedGCIRecord::check() {
- // Not implemented yet.
- return true;
-}
-
-Uint32 CompletedGCIRecord::getLogRecordSize() {
- return COMPLETEDGCIRECORDSIZE;
-}
-
-NdbOut& operator<<(NdbOut& no, const CompletedGCIRecord& cGCIr) {
- no << "-----------COMPLETED GCI RECORD----------------" << endl << endl;
- printOut("Record type:", cGCIr.m_recordType);
- printOut("Completed GCI:", cGCIr.m_theCompletedGCI);
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-bool NextLogRecord::check() {
- // Not implemented yet.
- return true;
-}
-
-Uint32 NextLogRecord::getLogRecordSize(Uint32 pageIndex) {
- return PAGESIZE - pageIndex;
-}
-
-NdbOut& operator<<(NdbOut& no, const NextLogRecord& nl) {
- no << "-----------NEXT LOG RECORD --------------------" << endl << endl;
- printOut("Record type:", nl.m_recordType);
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-Uint32 PageHeader::getLogRecordSize() {
- return PAGEHEADERSIZE;
-}
-
-bool PageHeader::check() {
- // Not implemented yet.
- return true;
-}
-
-bool PageHeader::lastPage()
-{
- return m_next_page == 0xffffff00;
-}
-
-Uint32 PageHeader::lastWord()
-{
- return m_current_page_index;
-}
-
-
-NdbOut& operator<<(NdbOut& no, const PageHeader& ph) {
- no << "------------PAGE HEADER------------------------" << endl << endl;
- ndbout_c("%-30s%-12s%-12s\n", "", "Decimal", "Hex");
- printOut("Checksum:", ph.m_checksum);
- printOut("Laps since initial start:", ph.m_lap);
- printOut("Max gci completed:", ph.m_max_gci_completed);
- printOut("Max gci started:", ph.m_max_gci_started);
- printOut("Ptr to next page:", ph.m_next_page);
- printOut("Ptr to previous page:", ph.m_previous_page);
- printOut("Ndb version:", ph.m_ndb_version);
- printOut("Number of log files:", ph.m_number_of_logfiles);
- printOut("Current page index:", ph.m_current_page_index);
- printOut("Oldest prepare op. file No.:", ph.m_old_prepare_file_number);
- printOut("Oldest prepare op. page ref.:", ph.m_old_prepare_page_reference);
- printOut("Dirty flag:", ph.m_dirty_flag);
- printOut("Write Timer:", ph.m_log_timer);
- printOut("Page i-val:", ph.m_page_i_value);
- printOut("Place written:", ph.m_place_written_from);
- printOut("Page No in File:", ph.m_page_no);
- printOut("File No:", ph.m_file_no);
- printOut("Word Written:", ph.m_word_written);
- printOut("In Writing (should be 1)", ph.m_in_writing_flag);
- printOut("Prev Page No (can be garbage)", ph.m_prev_page_no);
- printOut("In Free List (should be 0):", ph.m_in_free_list);
- no << endl;
- return no;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-Uint32 FileDescriptor::getLogRecordSize() {
- return FILEDESCRIPTORHEADERSIZE
- + m_fdHeader.m_noOfDescriptors * FILEDESCRIPTORRECORDSIZE;
-}
-
-NdbOut& operator<<(NdbOut& no, const FileDescriptor& fd) {
- no << "-------FILE DESCRIPTOR HEADER------------------" << endl << endl;
- printOut("Record type:", fd.m_fdHeader.m_recordType);
- printOut("Number of file descriptors:", fd.m_fdHeader.m_noOfDescriptors);
- printOut("File number:", fd.m_fdHeader.m_fileNo);
- ndbout << endl;
- for(Uint32 i = 0; i < fd.m_fdHeader.m_noOfDescriptors; i++) {
- fd.printARecord(i);
- }
- return no;
-}
-
-void FileDescriptor::printARecord( Uint32 recordIndex ) const {
- ndbout << "------------------FILE DESCRIPTOR " << recordIndex
- <<" ---------------------" << endl << endl;
- ndbout_c("%-30s%-12s%-12s\n", "", "Decimal", "Hex");
-
- for(int i = 1; i <= NO_MBYTE_IN_FILE; i++) {
- ndbout_c("%s%2d%s%-12u%-12x", "Max GCI completed, mbyte ", i, ": ",
- m_fdRecord[recordIndex].m_maxGciCompleted[i-1],
- m_fdRecord[recordIndex].m_maxGciCompleted[i-1]);
- }
- for(int i = 1; i <= NO_MBYTE_IN_FILE; i++) {
- ndbout_c("%s%2d%s%-12u%-12x", "Max GCI started, mbyte ", i, ": ",
- m_fdRecord[recordIndex].m_maxGciStarted[i-1],
- m_fdRecord[recordIndex].m_maxGciStarted[i-1]);
- }
- for(int i = 1; i <= NO_MBYTE_IN_FILE; i++) {
- ndbout_c("%s%2d%s%-12u%-12x", "Last prepared ref, mbyte ", i, ": ",
- m_fdRecord[recordIndex].m_lastPreparedReference[i-1],
- m_fdRecord[recordIndex].m_lastPreparedReference[i-1]);
- }
- ndbout << endl;
-}
-
-bool FileDescriptor::check() {
- // Not implemented yet.
- return true;
-}
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
diff --git a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
deleted file mode 100644
index abdb57e8646..00000000000
--- a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <NdbMain.h>
-#include <NdbOut.hpp>
-#include <ndb_types.h>
-
-#define ZNEW_PREP_OP_TYPE 0
-#define ZPREP_OP_TYPE 1
-#define ZCOMMIT_TYPE 2
-#define ZABORT_TYPE 3
-#define ZFD_TYPE 4
-#define ZFRAG_SPLIT_TYPE 5
-#define ZNEXT_LOG_RECORD_TYPE 6
-#define ZNEXT_MBYTE_TYPE 7
-#define ZCOMPLETED_GCI_TYPE 8
-#define ZINVALID_COMMIT_TYPE 9
-
-#define MAX_FILE_DESCRIPTORS 40
-#define NO_MBYTE_IN_FILE 16
-
-#define PAGESIZE 8192
-#define NO_PAGES_IN_MBYTE 32
-#define NO_MBYTE_IN_FILE 16
-
-#define COMMITTRANSACTIONRECORDSIZE 9
-#define COMPLETEDGCIRECORDSIZE 2
-#define PAGEHEADERSIZE 32
-#define FILEDESCRIPTORHEADERSIZE 3
-#define FILEDESCRIPTORRECORDSIZE 48
-#define NEXTMBYTERECORDSIZE 1
-#define ABORTTRANSACTIONRECORDSIZE 3
-
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-class AbortTransactionRecord {
- friend NdbOut& operator<<(NdbOut&, const AbortTransactionRecord&);
-public:
- bool check();
- Uint32 getLogRecordSize();
-protected:
- Uint32 m_recordType;
- Uint32 m_transactionId1;
- Uint32 m_transactionId2;
-};
-
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-class NextMbyteRecord {
- friend NdbOut& operator<<(NdbOut&, const NextMbyteRecord&);
-public:
- bool check();
- Uint32 getLogRecordSize();
-protected:
- Uint32 m_recordType;
-};
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-
-class PrepareOperationRecord {
- friend NdbOut& operator<<(NdbOut&, const PrepareOperationRecord&);
-public:
- bool check();
- Uint32 getLogRecordSize(Uint32 wordsRead);
-
-protected:
- Uint32 m_recordType;
- Uint32 m_logRecordSize;
- Uint32 m_hashValue;
- Uint32 m_operationType; // 0 READ, 1 UPDATE, 2 INSERT, 3 DELETE
- Uint32 m_attributeLength;
- Uint32 m_keyLength;
- Uint32 m_page_no;
- Uint32 m_page_idx;
- Uint32 *m_keyInfo; // In this order
- Uint32 *m_attrInfo;// In this order
-};
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-class CompletedGCIRecord {
- friend NdbOut& operator<<(NdbOut&, const CompletedGCIRecord&);
-public:
- bool check();
- Uint32 getLogRecordSize();
-protected:
- Uint32 m_recordType;
- Uint32 m_theCompletedGCI;
-};
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-class NextLogRecord {
- friend NdbOut& operator<<(NdbOut&, const NextLogRecord&);
-public:
- bool check();
- Uint32 getLogRecordSize(Uint32);
-protected:
- Uint32 m_recordType;
-};
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-class PageHeader {
- friend NdbOut& operator<<(NdbOut&, const PageHeader&);
-public:
- bool check();
- Uint32 getLogRecordSize();
- bool lastPage();
- Uint32 lastWord();
-protected:
- Uint32 m_checksum;
- Uint32 m_lap;
- Uint32 m_max_gci_completed;
- Uint32 m_max_gci_started;
- Uint32 m_next_page;
- Uint32 m_previous_page;
- Uint32 m_ndb_version;
- Uint32 m_number_of_logfiles;
- Uint32 m_current_page_index;
- Uint32 m_old_prepare_file_number;
- Uint32 m_old_prepare_page_reference;
- Uint32 m_dirty_flag;
-/* Debug info Start */
- Uint32 m_log_timer;
- Uint32 m_page_i_value;
- Uint32 m_place_written_from;
- Uint32 m_page_no;
- Uint32 m_file_no;
- Uint32 m_word_written;
- Uint32 m_in_writing_flag;
- Uint32 m_prev_page_no;
- Uint32 m_in_free_list;
-/* Debug info End */
-};
-
-//----------------------------------------------------------------
-// File descriptor.
-//----------------------------------------------------------------
-
-class FileDescriptorHeader {
-public:
- Uint32 m_recordType;
- Uint32 m_noOfDescriptors;
- Uint32 m_fileNo;
-};
-
-class FileDescriptorRecord {
-public:
- Uint32 m_maxGciCompleted[16];
- Uint32 m_maxGciStarted[16];
- Uint32 m_lastPreparedReference[16];
-};
-
-class FileDescriptor {
- friend NdbOut& operator<<(NdbOut&, const FileDescriptor&);
-public:
- bool check();
- Uint32 getLogRecordSize();
-protected:
- void printARecord( Uint32 ) const;
- FileDescriptorHeader m_fdHeader;
- FileDescriptorRecord m_fdRecord[1];
-};
-
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-class CommitTransactionRecord {
- friend NdbOut& operator<<(NdbOut&, const CommitTransactionRecord&);
-public:
- bool check();
- Uint32 getLogRecordSize();
-protected:
- Uint32 m_recordType;
- Uint32 m_tableId;
- Uint32 m_schemaVersion;
- Uint32 m_fragmentId;
- Uint32 m_fileNumberOfPrepareOperation;
- Uint32 m_startPageNumberOfPrepareOperation;
- Uint32 m_startPageIndexOfPrepareOperation;
- Uint32 m_stopPageNumberOfPrepareOperation;
- Uint32 m_globalCheckpoint;
-};
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-class InvalidCommitTransactionRecord {
- friend NdbOut& operator<<(NdbOut&, const InvalidCommitTransactionRecord&);
-public:
- bool check();
- Uint32 getLogRecordSize();
-protected:
- Uint32 m_recordType;
- Uint32 m_tableId;
- Uint32 m_fragmentId;
- Uint32 m_fileNumberOfPrepareOperation;
- Uint32 m_startPageNumberOfPrepareOperation;
- Uint32 m_startPageIndexOfPrepareOperation;
- Uint32 m_stopPageNumberOfPrepareOperation;
- Uint32 m_globalCheckpoint;
-};
-
-//----------------------------------------------------------------
-//
-//----------------------------------------------------------------
-
-struct NextLogRec {
-
-};
-
-struct NewPrepareOperation {
-
-};
-
-struct FragmentSplit {
-
-};
diff --git a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
deleted file mode 100644
index 90338cb58cd..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ /dev/null
@@ -1,1978 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBTC_H
-#define DBTC_H
-
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <SimulatedBlock.hpp>
-#include <DLHashTable.hpp>
-#include <SLList.hpp>
-#include <DLList.hpp>
-#include <DLFifoList.hpp>
-#include <DataBuffer.hpp>
-#include <Bitmask.hpp>
-#include <AttributeList.hpp>
-#include <signaldata/AttrInfo.hpp>
-#include <signaldata/LqhTransConf.hpp>
-#include <signaldata/LqhKey.hpp>
-#include <signaldata/TrigAttrInfo.hpp>
-#include <signaldata/TcIndx.hpp>
-#include <signaldata/TransIdAI.hpp>
-#include <signaldata/EventReport.hpp>
-#include <trigger_definitions.h>
-#include <SignalCounter.hpp>
-
-#ifdef DBTC_C
-/*
- * 2.2 LOCAL SYMBOLS
- * -----------------
- */
-#define Z8NIL 255
-#define ZAPI_CONNECT_FILESIZE 20
-#define ZATTRBUF_FILESIZE 4000
-#define ZCLOSED 2
-#define ZCOMMITING 0 /* VALUE FOR TRANSTATUS */
-#define ZCOMMIT_SETUP 2
-#define ZCONTINUE_ABORT_080 4
-#define ZDATABUF_FILESIZE 4000
-#define ZGCP_FILESIZE 10
-#define ZINBUF_DATA_LEN 24 /* POSITION OF 'DATA LENGHT'-VARIABLE. */
-#define ZINBUF_NEXT 27 /* POSITION OF 'NEXT'-VARIABLE. */
-#define ZINBUF_PREV 26 /* POSITION OF 'PREVIOUS'-VARIABLE. */
-#define ZINTSPH1 1
-#define ZINTSPH2 2
-#define ZINTSPH3 3
-#define ZINTSPH6 6
-#define ZLASTPHASE 255
-#define ZMAX_DATA_IN_LQHKEYREQ 12
-#define ZNODEBUF_FILESIZE 2000
-#define ZNR_OF_SEIZE 10
-#define ZSCANREC_FILE_SIZE 100
-#define ZSCAN_FRAGREC_FILE_SIZE 400
-#define ZSCAN_OPREC_FILE_SIZE 400
-#define ZSEND_ATTRINFO 0
-#define ZSPH1 1
-#define ZTABREC_FILESIZE 16
-#define ZTAKE_OVER_ACTIVE 1
-#define ZTAKE_OVER_IDLE 0
-#define ZTC_CONNECT_FILESIZE 200
-#define ZTCOPCONF_SIZE 6
-
-// ----------------------------------------
-// Error Codes for Scan
-// ----------------------------------------
-#define ZNO_CONCURRENCY_ERROR 242
-#define ZTOO_HIGH_CONCURRENCY_ERROR 244
-#define ZNO_SCANREC_ERROR 245
-#define ZNO_FRAGMENT_ERROR 246
-#define ZSCAN_AI_LEN_ERROR 269
-#define ZSCAN_LQH_ERROR 270
-#define ZSCAN_FRAG_LQH_ERROR 274
-
-#define ZSCANTIME_OUT_ERROR 296
-#define ZSCANTIME_OUT_ERROR2 297
-
-// ----------------------------------------
-// Error Codes for transactions
-// ----------------------------------------
-#define ZSTATE_ERROR 202
-#define ZLENGTH_ERROR 207 // Also Scan
-#define ZERO_KEYLEN_ERROR 208
-#define ZSIGNAL_ERROR 209
-#define ZGET_ATTRBUF_ERROR 217 // Also Scan
-#define ZGET_DATAREC_ERROR 218
-#define ZMORE_AI_IN_TCKEYREQ_ERROR 220
-#define ZCOMMITINPROGRESS 230
-#define ZROLLBACKNOTALLOWED 232
-#define ZNO_FREE_TC_CONNECTION 233 // Also Scan
-#define ZABORTINPROGRESS 237
-#define ZPREPAREINPROGRESS 238
-#define ZWRONG_SCHEMA_VERSION_ERROR 241 // Also Scan
-#define ZSCAN_NODE_ERROR 250
-#define ZTRANS_STATUS_ERROR 253
-#define ZTIME_OUT_ERROR 266
-#define ZSIMPLE_READ_WITHOUT_AI 271
-#define ZNO_AI_WITH_UPDATE 272
-#define ZSEIZE_API_COPY_ERROR 275
-#define ZSCANINPROGRESS 276
-#define ZABORT_ERROR 277
-#define ZCOMMIT_TYPE_ERROR 278
-
-#define ZNO_FREE_TC_MARKER 279
-#define ZNODE_SHUTDOWN_IN_PROGRESS 280
-#define ZCLUSTER_SHUTDOWN_IN_PROGRESS 281
-#define ZWRONG_STATE 282
-#define ZCLUSTER_IN_SINGLEUSER_MODE 299
-
-#define ZDROP_TABLE_IN_PROGRESS 283
-#define ZNO_SUCH_TABLE 284
-#define ZUNKNOWN_TABLE_ERROR 285
-#define ZNODEFAIL_BEFORE_COMMIT 286
-#define ZINDEX_CORRUPT_ERROR 287
-
-// ----------------------------------------
-// Seize error
-// ----------------------------------------
-#define ZNO_FREE_API_CONNECTION 219
-#define ZSYSTEM_NOT_STARTED_ERROR 203
-
-// ----------------------------------------
-// Release errors
-// ----------------------------------------
-#define ZINVALID_CONNECTION 229
-
-
-#define ZNOT_FOUND 626
-#define ZALREADYEXIST 630
-#define ZNOTUNIQUE 893
-
-#define ZINVALID_KEY 290
-#endif
-
-class Dbtc: public SimulatedBlock {
-public:
- enum ConnectionState {
- CS_CONNECTED = 0,
- CS_DISCONNECTED = 1,
- CS_STARTED = 2,
- CS_RECEIVING = 3,
- CS_PREPARED = 4,
- CS_START_PREPARING = 5,
- CS_REC_PREPARING = 6,
- CS_RESTART = 7,
- CS_ABORTING = 8,
- CS_COMPLETING = 9,
- CS_COMPLETE_SENT = 10,
- CS_PREPARE_TO_COMMIT = 11,
- CS_COMMIT_SENT = 12,
- CS_START_COMMITTING = 13,
- CS_COMMITTING = 14,
- CS_REC_COMMITTING = 15,
- CS_WAIT_ABORT_CONF = 16,
- CS_WAIT_COMPLETE_CONF = 17,
- CS_WAIT_COMMIT_CONF = 18,
- CS_FAIL_ABORTING = 19,
- CS_FAIL_ABORTED = 20,
- CS_FAIL_PREPARED = 21,
- CS_FAIL_COMMITTING = 22,
- CS_FAIL_COMMITTED = 23,
- CS_FAIL_COMPLETED = 24,
- CS_START_SCAN = 25
- };
-
- enum OperationState {
- OS_CONNECTING_DICT = 0,
- OS_CONNECTED = 1,
- OS_OPERATING = 2,
- OS_PREPARED = 3,
- OS_COMMITTING = 4,
- OS_COMMITTED = 5,
- OS_COMPLETING = 6,
- OS_COMPLETED = 7,
- OS_RESTART = 8,
- OS_ABORTING = 9,
- OS_ABORT_SENT = 10,
- OS_TAKE_OVER = 11,
- OS_WAIT_DIH = 12,
- OS_WAIT_KEYINFO = 13,
- OS_WAIT_ATTR = 14,
- OS_WAIT_COMMIT_CONF = 15,
- OS_WAIT_ABORT_CONF = 16,
- OS_WAIT_COMPLETE_CONF = 17,
- OS_WAIT_SCAN = 18
- };
-
- enum AbortState {
- AS_IDLE = 0,
- AS_ACTIVE = 1
- };
-
- enum HostState {
- HS_ALIVE = 0,
- HS_DEAD = 1
- };
-
- enum LqhTransState {
- LTS_IDLE = 0,
- LTS_ACTIVE = 1
- };
-
- enum FailState {
- FS_IDLE = 0,
- FS_LISTENING = 1,
- FS_COMPLETING = 2
- };
-
- enum SystemStartState {
- SSS_TRUE = 0,
- SSS_FALSE = 1
- };
-
- enum TimeOutCheckState {
- TOCS_TRUE = 0,
- TOCS_FALSE = 1
- };
-
- enum ReturnSignal {
- RS_NO_RETURN = 0,
- RS_TCKEYCONF = 1,
- RS_TC_COMMITCONF = 3,
- RS_TCROLLBACKCONF = 4,
- RS_TCROLLBACKREP = 5
- };
-
- enum IndexOperationState {
- IOS_NOOP = 0,
- IOS_INDEX_ACCESS = 1,
- IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF = 2,
- IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI = 3,
- IOS_INDEX_OPERATION = 4
- };
-
- enum IndexState {
- IS_BUILDING = 0, // build in progress, start state at create
- IS_ONLINE = 1 // ready to use
- };
-
-
- /**--------------------------------------------------------------------------
- * LOCAL SYMBOLS PER 'SYMBOL-VALUED' VARIABLE
- *
- *
- * NSYMB ZAPI_CONNECT_FILESIZE = 20
- * NSYMB ZTC_CONNECT_FILESIZE = 200
- * NSYMB ZHOST_FILESIZE = 16
- * NSYMB ZDATABUF_FILESIZE = 4000
- * NSYMB ZATTRBUF_FILESIZE = 4000
- * NSYMB ZGCP_FILESIZE = 10
- *
- *
- * ABORTED CODES
- * TPHASE NSYMB ZSPH1 = 1
- * NSYMB ZLASTPHASE = 255
- *
- *
- * LQH_TRANS
- * NSYMB ZTRANS_ABORTED = 1
- * NSYMB ZTRANS_PREPARED = 2
- * NSYMB ZTRANS_COMMITTED = 3
- * NSYMB ZCOMPLETED_LQH_TRANS = 4
- * NSYMB ZTRANS_COMPLETED = 5
- *
- *
- * TAKE OVER
- * NSYMB ZTAKE_OVER_IDLE = 0
- * NSYMB ZTAKE_OVER_ACTIVE = 1
- *
- * ATTRBUF (ATTRBUF_RECORD)
- * NSYMB ZINBUF_DATA_LEN = 24
- * NSYMB ZINBUF_NEXTFREE = 25 (NOT USED )
- * NSYMB ZINBUF_PREV = 26
- * NSYMB ZINBUF_NEXT = 27
- -------------------------------------------------------------------------*/
- /*
- 2.3 RECORDS AND FILESIZES
- -------------------------
- */
- /* **************************************************************** */
- /* ---------------------------------------------------------------- */
- /* ------------------- TRIGGER AND INDEX DATA --------------------- */
- /* ---------------------------------------------------------------- */
- /* **************************************************************** */
- /* ********* DEFINED TRIGGER DATA ********* */
- /* THIS RECORD FORMS LISTS OF ACTIVE */
- /* TRIGGERS FOR EACH TABLE. */
- /* THE RECORDS ARE MANAGED BY A TRIGGER */
- /* POOL WHERE A TRIGGER RECORD IS SEIZED */
- /* WHEN A TRIGGER IS ACTIVATED AND RELEASED */
- /* WHEN THE TRIGGER IS DEACTIVATED. */
- /* **************************************** */
- struct TcDefinedTriggerData {
- TcDefinedTriggerData() {}
- /**
- * Trigger id, used to identify the trigger
- */
- UintR triggerId;
-
- /**
- * Trigger type, defines what the trigger is used for
- */
- TriggerType::Value triggerType;
-
- /**
- * Trigger type, defines what the trigger is used for
- */
- TriggerEvent::Value triggerEvent;
-
- /**
- * Attribute mask, defines what attributes are to be monitored
- * Can be seen as a compact representation of SQL column name list
- */
- Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
-
- /**
- * Next ptr (used in pool/list)
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
-
- /**
- * Index id, only used by secondary_index triggers. This is same as
- * index table id in DICT.
- **/
- Uint32 indexId;
-
- /**
- * Prev pointer (used in list)
- */
- Uint32 prevList;
-
- inline void print(NdbOut & s) const {
- s << "[DefinedTriggerData = " << triggerId << "]";
- }
- };
- typedef Ptr<TcDefinedTriggerData> DefinedTriggerPtr;
-
- /**
- * Pool of trigger data record
- */
- ArrayPool<TcDefinedTriggerData> c_theDefinedTriggerPool;
-
- /**
- * The list of active triggers
- */
- DLList<TcDefinedTriggerData> c_theDefinedTriggers;
-
- typedef DataBuffer<11> AttributeBuffer;
-
- AttributeBuffer::DataBufferPool c_theAttributeBufferPool;
-
- UintR c_transactionBufferSpace;
-
-
- /* ********** FIRED TRIGGER DATA ********** */
- /* THIS RECORD FORMS LISTS OF FIRED */
- /* TRIGGERS FOR A TRANSACTION. */
- /* THE RECORDS ARE MANAGED BY A TRIGGER */
- /* POOL WHERE A TRIGGER RECORD IS SEIZED */
- /* WHEN A TRIGGER IS ACTIVATED AND RELEASED */
- /* WHEN THE TRIGGER IS DEACTIVATED. */
- /* **************************************** */
- struct TcFiredTriggerData {
- TcFiredTriggerData() {}
-
- /**
- * Trigger id, used to identify the trigger
- **/
- Uint32 triggerId;
-
- /**
- * The operation that fired the trigger
- */
- Uint32 fireingOperation;
-
- /**
- * The fragment id of the firing operation. This will be appended
- * to the Primary Key such that the record can be found even in the
- * case of user defined partitioning.
- */
- Uint32 fragId;
-
- /**
- * Used for scrapping in case of node failure
- */
- Uint32 nodeId;
-
- /**
- * Trigger attribute info, primary key value(s)
- */
- AttributeBuffer::Head keyValues;
-
- /**
- * Trigger attribute info, attribute value(s) before operation
- */
- AttributeBuffer::Head beforeValues;
-
- /**
- * Trigger attribute info, attribute value(s) after operation
- */
- AttributeBuffer::Head afterValues;
-
- /**
- * Next ptr (used in pool/list)
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- Uint32 nextHash;
- };
-
- /**
- * Prev pointer (used in list)
- */
- union {
- Uint32 prevList;
- Uint32 prevHash;
- };
-
- inline void print(NdbOut & s) const {
- s << "[FiredTriggerData = " << triggerId << "]";
- }
-
- inline Uint32 hashValue() const {
- return fireingOperation ^ nodeId;
- }
-
- inline bool equal(const TcFiredTriggerData & rec) const {
- return fireingOperation == rec.fireingOperation && nodeId == rec.nodeId;
- }
- };
- typedef Ptr<TcFiredTriggerData> FiredTriggerPtr;
-
- /**
- * Pool of trigger data record
- */
- ArrayPool<TcFiredTriggerData> c_theFiredTriggerPool;
- DLHashTable<TcFiredTriggerData> c_firedTriggerHash;
- AttributeBuffer::DataBufferPool c_theTriggerAttrInfoPool;
-
- Uint32 c_maxNumberOfDefinedTriggers;
- Uint32 c_maxNumberOfFiredTriggers;
-
- struct AttrInfoRecord {
- /**
- * Pre-allocated AttrInfo signal
- */
- AttrInfo attrInfo;
-
- /**
- * Next ptr (used in pool/list)
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- /**
- * Prev pointer (used in list)
- */
- Uint32 prevList;
- };
-
-
- /* ************* INDEX DATA *************** */
- /* THIS RECORD FORMS LISTS OF ACTIVE */
- /* INDEX FOR EACH TABLE. */
- /* THE RECORDS ARE MANAGED BY A INDEX */
- /* POOL WHERE AN INDEX RECORD IS SEIZED */
- /* WHEN AN INDEX IS CREATED AND RELEASED */
- /* WHEN THE INDEX IS DROPPED. */
- /* **************************************** */
- struct TcIndexData {
- /**
- * IndexState
- */
- IndexState indexState;
-
- /**
- * Index id, same as index table id in DICT
- */
- Uint32 indexId;
-
- /**
- * Index attribute list. Only the length is used in v21x.
- */
- AttributeList attributeList;
-
- /**
- * Primary table id, the primary table to be indexed
- */
- Uint32 primaryTableId;
-
- /**
- * Primary key position in secondary table
- */
- Uint32 primaryKeyPos;
-
- /**
- * Next ptr (used in pool/list)
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- /**
- * Prev pointer (used in list)
- */
- Uint32 prevList;
- };
-
- typedef Ptr<TcIndexData> TcIndexDataPtr;
-
- /**
- * Pool of index data record
- */
- ArrayPool<TcIndexData> c_theIndexPool;
-
- /**
- * The list of defined indexes
- */
- DLList<TcIndexData> c_theIndexes;
- UintR c_maxNumberOfIndexes;
-
- struct TcIndexOperation {
- TcIndexOperation(AttributeBuffer::DataBufferPool & abp) :
- indexOpState(IOS_NOOP),
- expectedKeyInfo(0),
- keyInfo(abp),
- expectedAttrInfo(0),
- attrInfo(abp),
- expectedTransIdAI(0),
- transIdAI(abp),
- indexReadTcConnect(RNIL)
- {}
-
- ~TcIndexOperation()
- {
- }
-
- // Index data
- Uint32 indexOpId;
- IndexOperationState indexOpState; // Used to mark on-going TcKeyReq
- Uint32 expectedKeyInfo;
- AttributeBuffer keyInfo; // For accumulating IndxKeyInfo
- Uint32 expectedAttrInfo;
- AttributeBuffer attrInfo; // For accumulating IndxAttrInfo
- Uint32 expectedTransIdAI;
- AttributeBuffer transIdAI; // For accumulating TransId_AI
-
- TcKeyReq tcIndxReq;
- UintR connectionIndex;
- UintR indexReadTcConnect; //
-
- /**
- * Next ptr (used in pool/list)
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- /**
- * Prev pointer (used in list)
- */
- Uint32 prevList;
- };
-
- typedef Ptr<TcIndexOperation> TcIndexOperationPtr;
-
- /**
- * Pool of index data record
- */
- ArrayPool<TcIndexOperation> c_theIndexOperationPool;
-
- UintR c_maxNumberOfIndexOperations;
-
- /************************** API CONNECT RECORD ***********************
- * The API connect record contains the connection record to which the
- * application connects.
- *
- * The application can send one operation at a time. It can send a
- * new operation immediately after sending the previous operation.
- * Thereby several operations can be active in one transaction within TC.
- * This is achieved by using the API connect record.
- * Each active operation is handled by the TC connect record.
- * As soon as the TC connect record has sent the
- * request to the LQH it is ready to receive new operations.
- * The LQH connect record takes care of waiting for an operation to
- * complete.
- * When an operation has completed on the LQH connect record,
- * a new operation can be started on this LQH connect record.
- *******************************************************************
- *
- * API CONNECT RECORD ALIGNED TO BE 256 BYTES
- ********************************************************************/
-
- /*******************************************************************>*/
- // We break out the API Timer for optimisation on scanning rather than
- // on fast access.
- /*******************************************************************>*/
- inline void setApiConTimer(Uint32 apiConPtrI, Uint32 value, Uint32 line){
- c_apiConTimer[apiConPtrI] = value;
- c_apiConTimer_line[apiConPtrI] = line;
- }
-
- inline Uint32 getApiConTimer(Uint32 apiConPtrI) const {
- return c_apiConTimer[apiConPtrI];
- }
- UintR* c_apiConTimer;
- UintR* c_apiConTimer_line;
-
- struct ApiConnectRecord {
- ApiConnectRecord(ArrayPool<TcFiredTriggerData> & firedTriggerPool,
- ArrayPool<TcIndexOperation> & seizedIndexOpPool):
- theFiredTriggers(firedTriggerPool),
- isIndexOp(false),
- theSeizedIndexOperations(seizedIndexOpPool)
- {}
-
- //---------------------------------------------------
- // First 16 byte cache line. Hot variables.
- //---------------------------------------------------
- ConnectionState apiConnectstate;
- UintR transid[2];
- UintR firstTcConnect;
- NdbNodeBitmask m_transaction_nodes;
-
- //---------------------------------------------------
- // Second 16 byte cache line. Hot variables.
- //---------------------------------------------------
- UintR lqhkeyconfrec;
- UintR cachePtr;
- UintR currSavePointId;
- UintR counter;
-
- //---------------------------------------------------
- // Third 16 byte cache line. First and second cache
- // line plus this will be enough for copy API records.
- // Variables used in late phases.
- //---------------------------------------------------
- UintR nextGcpConnect;
- UintR prevGcpConnect;
- UintR gcpPointer;
- UintR ndbapiConnect;
-
- //---------------------------------------------------
- // Fourth 16 byte cache line. Only used in late phases.
- // Plus 4 bytes of error handling.
- //---------------------------------------------------
- UintR nextApiConnect;
- BlockReference ndbapiBlockref;
- UintR apiCopyRecord;
- UintR globalcheckpointid;
-
- //---------------------------------------------------
- // Second 64 byte cache line starts. First 16 byte
- // cache line in this one. Variables primarily used
- // in early phase.
- //---------------------------------------------------
- UintR lastTcConnect;
- UintR lqhkeyreqrec;
- AbortState abortState;
- Uint32 buddyPtr;
- Uint8 m_exec_flag;
- Uint8 unused2;
- Uint8 takeOverRec;
- Uint8 currentReplicaNo;
-
- //---------------------------------------------------
- // Error Handling variables. If cache line 32 bytes
- // ensures that cache line is still only read in
- // early phases.
- //---------------------------------------------------
- union {
- UintR apiScanRec;
- UintR commitAckMarker;
- };
- UintR currentTcConnect;
- BlockReference tcBlockref;
- Uint16 returncode;
- Uint16 takeOverInd;
-
- //---------------------------------------------------
- // Second 64 byte cache line. Third 16 byte cache line
- // in this one. Variables primarily used in early phase
- // and checked in late phase.
- // Fourth cache line is the tcSendArray that is used
- // when two and three operations are responded to in
- // parallel. The first two entries in tcSendArray is
- // part of the third cache line.
- //---------------------------------------------------
- //---------------------------------------------------
- // timeOutCounter is used waiting for ABORTCONF, COMMITCONF
- // and COMPLETECONF
- //---------------------------------------------------
- UintR failureNr;
- Uint8 tckeyrec; // Ändrad från R
- Uint8 tcindxrec;
- Uint8 apiFailState; // Ändrad från R
- Uint8 singleUserMode;
- ReturnSignal returnsignal;
- Uint8 timeOutCounter;
-
- UintR tcSendArray[6];
-
- // Trigger data
-
- /**
- * The list of fired triggers
- */
- DLFifoList<TcFiredTriggerData> theFiredTriggers;
-
- bool triggerPending; // Used to mark waiting for a CONTINUEB
-
- // Index data
-
- Uint8 isIndexOp; // Used to mark on-going TcKeyReq as indx table access
- bool indexOpReturn;
- UintR noIndexOp; // No outstanding index ops
-
- // Index op return context
- UintR indexOp;
- UintR clientData;
- Uint32 errorData;
- UintR attrInfoLen;
-
- UintR accumulatingIndexOp;
- UintR executingIndexOp;
- UintR tcIndxSendArray[6];
- DLList<TcIndexOperation> theSeizedIndexOperations;
- };
-
- typedef Ptr<ApiConnectRecord> ApiConnectRecordPtr;
-
-
- /************************** TC CONNECT RECORD ************************/
- /* *******************************************************************/
- /* TC CONNECT RECORD KEEPS ALL INFORMATION TO CARRY OUT A TRANSACTION*/
- /* THE TRANSACTION CONTROLLER ESTABLISHES CONNECTIONS TO DIFFERENT */
- /* BLOCKS TO CARRY OUT THE TRANSACTION. THERE CAN BE SEVERAL RECORDS */
- /* PER ACTIVE TRANSACTION. THE TC CONNECT RECORD COOPERATES WITH THE */
- /* API CONNECT RECORD FOR COMMUNICATION WITH THE API AND WITH THE */
- /* LQH CONNECT RECORD FOR COMMUNICATION WITH THE LQH'S INVOLVED IN */
- /* THE TRANSACTION. TC CONNECT RECORD IS PERMANENTLY CONNECTED TO A */
- /* RECORD IN DICT AND ONE IN DIH. IT CONTAINS A LIST OF ACTIVE LQH */
- /* CONNECT RECORDS AND A LIST OF STARTED BUT NOT ACTIVE LQH CONNECT */
- /* RECORDS. IT DOES ALSO CONTAIN A LIST OF ALL OPERATIONS THAT ARE */
- /* EXECUTED WITH THE TC CONNECT RECORD. */
- /*******************************************************************>*/
- /* TC_CONNECT RECORD ALIGNED TO BE 128 BYTES */
- /*******************************************************************>*/
- struct TcConnectRecord {
- //---------------------------------------------------
- // First 16 byte cache line. Those variables are only
- // used in error cases.
- //---------------------------------------------------
- UintR tcOprec; /* TC OPREC of operation being taken over */
- Uint16 failData[4]; /* Failed nodes when taking over an operation */
- UintR nextTcFailHash;
-
- //---------------------------------------------------
- // Second 16 byte cache line. Those variables are used
- // from LQHKEYCONF to sending COMMIT and COMPLETED.
- //---------------------------------------------------
- UintR lastLqhCon; /* Connect record in last replicas Lqh record */
- Uint16 lastLqhNodeId; /* Node id of last replicas Lqh */
- Uint16 m_execAbortOption;/* TcKeyReq::ExecuteAbortOption */
- UintR commitAckMarker; /* CommitMarker I value */
-
- //---------------------------------------------------
- // Third 16 byte cache line. The hottest variables.
- //---------------------------------------------------
- OperationState tcConnectstate; /* THE STATE OF THE CONNECT*/
- UintR apiConnect; /* POINTER TO API CONNECT RECORD */
- UintR nextTcConnect; /* NEXT TC RECORD*/
- Uint8 dirtyOp;
- Uint8 opSimple;
- Uint8 lastReplicaNo; /* NUMBER OF THE LAST REPLICA IN THE OPERATION */
- Uint8 noOfNodes; /* TOTAL NUMBER OF NODES IN OPERATION */
- Uint8 operation; /* OPERATION TYPE */
- /* 0 = READ REQUEST */
- /* 1 = UPDATE REQUEST */
- /* 2 = INSERT REQUEST */
- /* 3 = DELETE REQUEST */
-
- //---------------------------------------------------
- // Fourth 16 byte cache line. The mildly hot variables.
- // tcNodedata expands 4 Bytes into the next cache line
- // with indexes almost never used.
- //---------------------------------------------------
- UintR clientData; /* SENDERS OPERATION POINTER */
- UintR dihConnectptr; /* CONNECTION TO DIH BLOCK ON THIS NODE */
- UintR prevTcConnect; /* DOUBLY LINKED LIST OF TC CONNECT RECORDS*/
- UintR savePointId;
-
- Uint16 tcNodedata[4];
-
- // Trigger data
- FiredTriggerPtr accumulatingTriggerData;
- UintR noFiredTriggers;
- UintR noReceivedTriggers;
- UintR triggerExecutionCount;
- UintR triggeringOperation;
- UintR savedState[LqhKeyConf::SignalLength];
-
- // Index data
- Uint8 isIndexOp; // Used to mark on-going TcKeyReq as index table access
- UintR indexOp;
- UintR currentIndexId;
- UintR attrInfoLen;
- };
-
- friend struct TcConnectRecord;
-
- typedef Ptr<TcConnectRecord> TcConnectRecordPtr;
-
- // ********************** CACHE RECORD **************************************
- //---------------------------------------------------------------------------
- // This record is used between reception of TCKEYREQ and sending of LQHKEYREQ
- // It is separatedso as to improve the cache hit rate and also to minimise
- // the necessary memory storage in NDB Cluster.
- //---------------------------------------------------------------------------
-
- struct CacheRecord {
- //---------------------------------------------------
- // First 16 byte cache line. Variables used by
- // ATTRINFO processing.
- //---------------------------------------------------
- UintR firstAttrbuf; /* POINTER TO LINKED LIST OF ATTRIBUTE BUFFERS */
- UintR lastAttrbuf; /* POINTER TO LINKED LIST OF ATTRIBUTE BUFFERS */
- UintR currReclenAi;
- Uint16 attrlength; /* ATTRIBUTE INFORMATION LENGTH */
- Uint16 save1;
-
- //---------------------------------------------------
- // Second 16 byte cache line. Variables initiated by
- // TCKEYREQ and used in LQHKEYREQ.
- //---------------------------------------------------
- UintR attrinfo15[4];
-
- //---------------------------------------------------
- // Third 16 byte cache line. Variables initiated by
- // TCKEYREQ and used in LQHKEYREQ.
- //---------------------------------------------------
- UintR attrinfo0;
- UintR schemaVersion;/* SCHEMA VERSION USED IN TRANSACTION */
- UintR tableref; /* POINTER TO THE TABLE IN WHICH THE FRAGMENT EXISTS*/
- Uint16 apiVersionNo;
- Uint16 keylen; /* KEY LENGTH SENT BY REQUEST SIGNAL */
-
- //---------------------------------------------------
- // Fourth 16 byte cache line. Variables initiated by
- // TCKEYREQ and used in LQHKEYREQ.
- //---------------------------------------------------
- UintR keydata[4]; /* RECEIVES FIRST 16 BYTES OF TUPLE KEY */
-
- //---------------------------------------------------
- // First 16 byte cache line in second 64 byte cache
- // line. Diverse use.
- //---------------------------------------------------
- UintR fragmentid; /* THE COMPUTED FRAGMENT ID */
- UintR hashValue; /* THE HASH VALUE USED TO LOCATE FRAGMENT */
-
- Uint8 distributionKeyIndicator;
- Uint8 m_special_hash; // collation or distribution key
- Uint8 m_no_disk_flag;
- Uint8 lenAiInTckeyreq; /* LENGTH OF ATTRIBUTE INFORMATION IN TCKEYREQ */
-
- Uint8 fragmentDistributionKey; /* DIH generation no */
-
- /**
- * EXECUTION MODE OF OPERATION
- * 0 = NORMAL EXECUTION, 1 = INTERPRETED EXECUTION
- */
- Uint8 opExec;
-
- Uint8 unused;
- Uint8 unused1;
-
- //---------------------------------------------------
- // Second 16 byte cache line in second 64 byte cache
- // line. Diverse use.
- //---------------------------------------------------
- UintR distributionKey;
- UintR nextCacheRec;
- UintR unused3;
- Uint32 scanInfo;
-
- //---------------------------------------------------
- // Third 16 byte cache line in second 64
- // byte cache line. Diverse use.
- //---------------------------------------------------
- Uint32 unused4;
- Uint32 scanTakeOverInd;
- UintR firstKeybuf; /* POINTER THE LINKED LIST OF KEY BUFFERS */
- UintR lastKeybuf; /* VARIABLE POINTING TO THE LAST KEY BUFFER */
-
- //---------------------------------------------------
- // Fourth 16 byte cache line in second 64
- // byte cache line. Not used currently.
- //---------------------------------------------------
- UintR packedCacheVar[4];
- };
-
- typedef Ptr<CacheRecord> CacheRecordPtr;
-
- /* ************************ HOST RECORD ********************************** */
- /********************************************************/
- /* THIS RECORD CONTAINS ALIVE-STATUS ON ALL NODES IN THE*/
- /* SYSTEM */
- /********************************************************/
- /* THIS RECORD IS ALIGNED TO BE 128 BYTES. */
- /********************************************************/
- struct HostRecord {
- HostState hostStatus;
- LqhTransState lqhTransStatus;
- bool inPackedList;
- UintR noOfPackedWordsLqh;
- UintR packedWordsLqh[26];
- UintR noOfWordsTCKEYCONF;
- UintR packedWordsTCKEYCONF[30];
- UintR noOfWordsTCINDXCONF;
- UintR packedWordsTCINDXCONF[30];
- BlockReference hostLqhBlockRef;
-
- enum NodeFailBits
- {
- NF_TAKEOVER = 0x1,
- NF_CHECK_SCAN = 0x2,
- NF_CHECK_TRANSACTION = 0x4,
- NF_CHECK_DROP_TAB = 0x8,
- NF_NODE_FAIL_BITS = 0xF // All bits...
- };
- Uint32 m_nf_bits;
- NdbNodeBitmask m_lqh_trans_conf;
- }; /* p2c: size = 128 bytes */
-
- typedef Ptr<HostRecord> HostRecordPtr;
-
- /* *********** TABLE RECORD ********************************************* */
-
- /********************************************************/
- /* THIS RECORD CONTAINS THE CURRENT SCHEMA VERSION OF */
- /* ALL TABLES IN THE SYSTEM. */
- /********************************************************/
- struct TableRecord {
- TableRecord() {}
- Uint32 currentSchemaVersion;
- Uint16 m_flags;
- Uint8 tableType;
- Uint8 singleUserMode;
-
- enum {
- TR_ENABLED = 1 << 0,
- TR_DROPPING = 1 << 1,
- TR_STORED_TABLE = 1 << 2
- };
- Uint8 get_enabled() const { return (m_flags & TR_ENABLED) != 0; }
- Uint8 get_dropping() const { return (m_flags & TR_DROPPING) != 0; }
- Uint8 get_storedTable() const { return (m_flags & TR_STORED_TABLE) != 0; }
- void set_enabled(Uint8 f) { f ? m_flags |= (Uint16)TR_ENABLED : m_flags &= ~(Uint16)TR_ENABLED; }
- void set_dropping(Uint8 f) { f ? m_flags |= (Uint16)TR_DROPPING : m_flags &= ~(Uint16)TR_DROPPING; }
- void set_storedTable(Uint8 f) { f ? m_flags |= (Uint16)TR_STORED_TABLE : m_flags &= ~(Uint16)TR_STORED_TABLE; }
-
- Uint8 noOfKeyAttr;
- Uint8 hasCharAttr;
- Uint8 noOfDistrKeys;
- Uint8 hasVarKeys;
-
- bool checkTable(Uint32 schemaVersion) const {
- return get_enabled() && !get_dropping() &&
- (table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
- }
-
- Uint32 getErrorCode(Uint32 schemaVersion) const;
-
- struct DropTable {
- Uint32 senderRef;
- Uint32 senderData;
- SignalCounter waitDropTabCount;
- } dropTable;
- };
- typedef Ptr<TableRecord> TableRecordPtr;
-
- /**
- * There is max 16 ScanFragRec's for
- * each scan started in TC. Each ScanFragRec is used by
- * a scan fragment "process" that scans one fragment at a time.
- * It will receive max 16 tuples in each request
- */
- struct ScanFragRec {
- ScanFragRec(){
- stopFragTimer();
- lqhBlockref = 0;
- scanFragState = IDLE;
- scanRec = RNIL;
- }
- /**
- * ScanFragState
- * WAIT_GET_PRIMCONF : Waiting for DIGETPRIMCONF when starting a new
- * fragment scan
- * LQH_ACTIVE : The scan process has sent a command to LQH and is
- * waiting for the response
- * LQH_ACTIVE_CLOSE : The scan process has sent close to LQH and is
- * waiting for the response
- * DELIVERED : The result have been delivered, this scan frag process
- * are waiting for a SCAN_NEXTREQ to tell us to continue scanning
- * RETURNING_FROM_DELIVERY : SCAN_NEXTREQ received and continuing scan
- * soon
- * QUEUED_FOR_DELIVERY : Result queued in TC and waiting for delivery
- * to API
- * COMPLETED : The fragment scan processes has completed and finally
- * sent a SCAN_PROCCONF
- */
- enum ScanFragState {
- IDLE = 0,
- WAIT_GET_PRIMCONF = 1,
- LQH_ACTIVE = 2,
- DELIVERED = 4,
- QUEUED_FOR_DELIVERY = 6,
- COMPLETED = 7
- };
- // Timer for checking timeout of this fragment scan
- Uint32 scanFragTimer;
-
- // Id of the current scanned fragment
- Uint32 scanFragId;
-
- // Blockreference of LQH
- BlockReference lqhBlockref;
-
- // getNodeInfo.m_connectCount, set at seize used so that
- // I don't accidently kill a starting node
- Uint32 m_connectCount;
-
- // State of this fragment scan
- ScanFragState scanFragState;
-
- // Id of the ScanRecord this fragment scan belongs to
- Uint32 scanRec;
-
- // The value of fragmentCompleted in the last received SCAN_FRAGCONF
- Uint8 m_scan_frag_conf_status;
-
- inline void startFragTimer(Uint32 timeVal){
- scanFragTimer = timeVal;
- }
- inline void stopFragTimer(void){
- scanFragTimer = 0;
- }
-
- Uint32 m_ops;
- Uint32 m_chksum;
- Uint32 m_apiPtr;
- Uint32 m_totalLen;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
-
- typedef Ptr<ScanFragRec> ScanFragRecPtr;
- typedef LocalDLList<ScanFragRec> ScanFragList;
-
- /**
- * Each scan allocates one ScanRecord to store information
- * about the current scan
- *
- */
- struct ScanRecord {
- ScanRecord() {}
- /** NOTE! This is the old comment for ScanState. - MASV
- * STATE TRANSITIONS OF SCAN_STATE. SCAN_STATE IS THE STATE
- * VARIABLE OF THE RECEIVE AND DELIVERY PROCESS.
- * THE PROCESS HAS THREE STEPS IT GOES THROUGH.
- * 1) THE INITIAL STATES WHEN RECEIVING DATA FOR THE SCAN.
- * - WAIT_SCAN_TAB_INFO
- * - WAIT_AI
- * - WAIT_FRAGMENT_COUNT
- * 2) THE EXECUTION STATES WHEN THE SCAN IS PERFORMED.
- * - SCAN_NEXT_ORDERED
- * - DELIVERED
- * - QUEUED_DELIVERED
- * 3) THE CLOSING STATE WHEN THE SCAN PROCESS IS CLOSING UP
- * EVERYTHING.
- * - CLOSING_SCAN
- * INITIAL START WHEN SCAN_TABREQ RECEIVED
- * -> WAIT_SCAN_TAB_INFO (IF ANY SCAN_TABINFO TO BE RECEIVED)
- * -> WAIT_AI (IF NO SCAN_TAB_INFO BUT ATTRINFO IS RECEIVED)
- * -> WAIT_FRAGMENT_COUNT (IF NEITHER SCAN_TABINFO OR ATTRINFO
- * RECEIVED)
- *
- * WAIT_SCAN_TAB_INFO TRANSITIONS:
- * -> WAIT_SCAN_TABINFO (WHEN MORE SCAN_TABINFO RECEIVED)
- * -> WAIT_AI (WHEN ATTRINFO RECEIVED AFTER RECEIVING ALL
- * SCAN_TABINFO)
- * -> WAIT_FRAGMENT_COUNT (WHEN NO ATTRINFO RECEIVED AFTER
- * RECEIVING ALL SCAN_TABINFO )
- * WAIT_AI TRANSITIONS:
- * -> WAIT_AI (WHEN MORE ATTRINFO RECEIVED)
- * -> WAIT_FRAGMENT_COUNT (WHEN ALL ATTRINFO RECEIVED)
- *
- * WAIT_FRAGMENT_COUNT TRANSITIONS:
- * -> SCAN_NEXT_ORDERED
- *
- * SCAN_NEXT_ORDERED TRANSITIONS:
- * -> DELIVERED (WHEN FIRST SCAN_FRAGCONF ARRIVES WITH OPERATIONS
- * TO REPORT IN IT)
- * -> CLOSING_SCAN (WHEN SCAN IS CLOSED BY SCAN_NEXTREQ OR BY SOME
- * ERROR)
- *
- * DELIVERED TRANSITIONS:
- * -> SCAN_NEXT_ORDERED (IF SCAN_NEXTREQ ARRIVES BEFORE ANY NEW
- * OPERATIONS TO REPORT ARRIVES)
- * -> QUEUED_DELIVERED (IF NEW OPERATION TO REPORT ARRIVES BEFORE
- * SCAN_NEXTREQ)
- * -> CLOSING_SCAN (WHEN SCAN IS CLOSED BY SCAN_NEXTREQ OR BY SOME
- * ERROR)
- *
- * QUEUED_DELIVERED TRANSITIONS:
- * -> DELIVERED (WHEN SCAN_NEXTREQ ARRIVES AND QUEUED OPERATIONS
- * TO REPORT ARE SENT TO THE APPLICATION)
- * -> CLOSING_SCAN (WHEN SCAN IS CLOSED BY SCAN_NEXTREQ OR BY
- * SOME ERROR)
- */
- enum ScanState {
- IDLE = 0,
- WAIT_SCAN_TAB_INFO = 1,
- WAIT_AI = 2,
- WAIT_FRAGMENT_COUNT = 3,
- RUNNING = 4,
- CLOSING_SCAN = 5
- };
-
- // State of this scan
- ScanState scanState;
-
- DLList<ScanFragRec>::Head m_running_scan_frags; // Currently in LQH
- union { Uint32 m_queued_count; Uint32 scanReceivedOperations; };
- DLList<ScanFragRec>::Head m_queued_scan_frags; // In TC !sent to API
- DLList<ScanFragRec>::Head m_delivered_scan_frags;// Delivered to API
-
- // Id of the next fragment to be scanned. Used by scan fragment
- // processes when they are ready for the next fragment
- Uint32 scanNextFragId;
-
- // Total number of fragments in the table we are scanning
- Uint32 scanNoFrag;
-
- // Index of next ScanRecords when in free list
- Uint32 nextScan;
-
- // Length of expected attribute information
- union { Uint32 scanAiLength; Uint32 m_booked_fragments_count; };
-
- Uint32 scanKeyLen;
-
- // Reference to ApiConnectRecord
- Uint32 scanApiRec;
-
- // Reference to TcConnectRecord
- Uint32 scanTcrec;
-
- // Number of scan frag processes that belong to this scan
- Uint32 scanParallel;
-
- // Schema version used by this scan
- Uint32 scanSchemaVersion;
-
- // Index of stored procedure belonging to this scan
- Uint32 scanStoredProcId;
-
- // The index of table that is scanned
- Uint32 scanTableref;
-
- // Number of operation records per scanned fragment
- // Number of operations in first batch
- // Max number of bytes per batch
- union {
- Uint16 first_batch_size_rows;
- Uint16 batch_size_rows;
- };
- Uint32 batch_byte_size;
-
- Uint32 scanRequestInfo; // ScanFrag format
-
- // Close is ordered
- bool m_close_scan_req;
- };
- typedef Ptr<ScanRecord> ScanRecordPtr;
-
- /* **********************************************************************$ */
- /* ******$ DATA BUFFER ******$ */
- /* */
- /* THIS BUFFER IS USED AS A GENERAL DATA STORAGE. */
- /* **********************************************************************$ */
- struct DatabufRecord {
- UintR data[4];
- /* 4 * 1 WORD = 4 WORD */
- UintR nextDatabuf;
- }; /* p2c: size = 20 bytes */
-
- typedef Ptr<DatabufRecord> DatabufRecordPtr;
-
- /* **********************************************************************$ */
- /* ******$ ATTRIBUTE INFORMATION RECORD ******$ */
- /*
- * CAN CONTAIN ONE (1) ATTRINFO SIGNAL. ONE SIGNAL CONTAINS 24 ATTR.
- * INFO WORDS. BUT 32 ELEMENTS ARE USED TO MAKE PLEX HAPPY.
- * SOME OF THE ELEMENTS ARE USED TO THE FOLLOWING THINGS:
- * DATA LENGHT IN THIS RECORD IS STORED IN THE ELEMENT INDEXED BY
- * ZINBUF_DATA_LEN.
- * NEXT FREE ATTRBUF IS POINTED OUT BY THE ELEMENT INDEXED BY
- * PREVIOUS ATTRBUF IS POINTED OUT BY THE ELEMENT INDEXED BY ZINBUF_PREV
- * (NOT USED YET).
- * NEXT ATTRBUF IS POINTED OUT BY THE ELEMENT INDEXED BY ZINBUF_NEXT. */
- /* ******************************************************************** */
- struct AttrbufRecord {
- UintR attrbuf[32];
- }; /* p2c: size = 128 bytes */
-
- typedef Ptr<AttrbufRecord> AttrbufRecordPtr;
-
- /*************************************************************************>*/
- /* GLOBAL CHECKPOINT INFORMATION RECORD */
- /* */
- /* THIS RECORD IS USED TO STORE THE GLOBALCHECKPOINT NUMBER AND A
- * COUNTER DURING THE COMPLETION PHASE OF THE TRANSACTION */
- /*************************************************************************>*/
- /* */
- /* GCP RECORD ALIGNED TO BE 32 BYTES */
- /*************************************************************************>*/
- struct GcpRecord {
- UintR gcpUnused1[2]; /* p2c: Not used */
- UintR firstApiConnect;
- UintR lastApiConnect;
- UintR gcpId;
- UintR nextGcp;
- UintR gcpUnused2; /* p2c: Not used */
- Uint16 gcpNomoretransRec;
- }; /* p2c: size = 32 bytes */
-
- typedef Ptr<GcpRecord> GcpRecordPtr;
-
- /*************************************************************************>*/
- /* TC_FAIL_RECORD */
- /* THIS RECORD IS USED WHEN HANDLING TAKE OVER OF ANOTHER FAILED
- * TC NODE. */
- /*************************************************************************>*/
- struct TcFailRecord {
- Uint16 queueList[MAX_NDB_NODES];
- Uint8 takeOverProcState[MAX_NDB_NODES];
- UintR completedTakeOver;
- UintR currentHashIndexTakeOver;
- FailState failStatus;
- Uint16 queueIndex;
- Uint16 takeOverNode;
- }; /* p2c: size = 64 bytes */
-
- typedef Ptr<TcFailRecord> TcFailRecordPtr;
-
-public:
- Dbtc(Block_context&);
- virtual ~Dbtc();
-
-private:
- BLOCK_DEFINES(Dbtc);
-
- // Transit signals
- void execPACKED_SIGNAL(Signal* signal);
- void execABORTED(Signal* signal);
- void execATTRINFO(Signal* signal);
- void execCONTINUEB(Signal* signal);
- void execKEYINFO(Signal* signal);
- void execSCAN_NEXTREQ(Signal* signal);
- void execSCAN_PROCREQ(Signal* signal);
- void execSCAN_PROCCONF(Signal* signal);
- void execTAKE_OVERTCREQ(Signal* signal);
- void execTAKE_OVERTCCONF(Signal* signal);
- void execLQHKEYREF(Signal* signal);
- void execTRANSID_AI_R(Signal* signal);
- void execKEYINFO20_R(Signal* signal);
- void execROUTE_ORD(Signal* signal);
- // Received signals
- void execDUMP_STATE_ORD(Signal* signal);
- void execSEND_PACKED(Signal* signal);
- void execCOMPLETED(Signal* signal);
- void execCOMMITTED(Signal* signal);
- void execDIGETNODESREF(Signal* signal);
- void execDIGETPRIMCONF(Signal* signal);
- void execDIGETPRIMREF(Signal* signal);
- void execDISEIZECONF(Signal* signal);
- void execDIVERIFYCONF(Signal* signal);
- void execDI_FCOUNTCONF(Signal* signal);
- void execDI_FCOUNTREF(Signal* signal);
- void execGCP_NOMORETRANS(Signal* signal);
- void execLQHKEYCONF(Signal* signal);
- void execNDB_STTOR(Signal* signal);
- void execREAD_NODESCONF(Signal* signal);
- void execREAD_NODESREF(Signal* signal);
- void execSTTOR(Signal* signal);
- void execTC_COMMITREQ(Signal* signal);
- void execTC_CLOPSIZEREQ(Signal* signal);
- void execTCGETOPSIZEREQ(Signal* signal);
- void execTCKEYREQ(Signal* signal);
- void execTCRELEASEREQ(Signal* signal);
- void execTCSEIZEREQ(Signal* signal);
- void execTCROLLBACKREQ(Signal* signal);
- void execTC_HBREP(Signal* signal);
- void execTC_SCHVERREQ(Signal* signal);
- void execSCAN_TABREQ(Signal* signal);
- void execSCAN_TABINFO(Signal* signal);
- void execSCAN_FRAGCONF(Signal* signal);
- void execSCAN_FRAGREF(Signal* signal);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execLQH_TRANSCONF(Signal* signal);
- void execCOMPLETECONF(Signal* signal);
- void execCOMMITCONF(Signal* signal);
- void execABORTCONF(Signal* signal);
- void execNODE_FAILREP(Signal* signal);
- void execINCL_NODEREQ(Signal* signal);
- void execTIME_SIGNAL(Signal* signal);
- void execAPI_FAILREQ(Signal* signal);
- void execSCAN_HBREP(Signal* signal);
-
- void execABORT_ALL_REQ(Signal* signal);
-
- void execCREATE_TRIG_REQ(Signal* signal);
- void execDROP_TRIG_REQ(Signal* signal);
- void execFIRE_TRIG_ORD(Signal* signal);
- void execTRIG_ATTRINFO(Signal* signal);
- void execCREATE_INDX_REQ(Signal* signal);
- void execDROP_INDX_REQ(Signal* signal);
- void execTCINDXREQ(Signal* signal);
- void execINDXKEYINFO(Signal* signal);
- void execINDXATTRINFO(Signal* signal);
- void execALTER_INDX_REQ(Signal* signal);
-
- // Index table lookup
- void execTCKEYCONF(Signal* signal);
- void execTCKEYREF(Signal* signal);
- void execTRANSID_AI(Signal* signal);
- void execTCROLLBACKREP(Signal* signal);
-
- void execCREATE_TAB_REQ(Signal* signal);
- void execPREP_DROP_TAB_REQ(Signal* signal);
- void execDROP_TAB_REQ(Signal* signal);
- void execWAIT_DROP_TAB_REF(Signal* signal);
- void execWAIT_DROP_TAB_CONF(Signal* signal);
- void checkWaitDropTabFailedLqh(Signal*, Uint32 nodeId, Uint32 tableId);
- void execALTER_TAB_REQ(Signal* signal);
- void set_timeout_value(Uint32 timeOut);
- void set_appl_timeout_value(Uint32 timeOut);
- void set_no_parallel_takeover(Uint32);
- void updateBuddyTimer(ApiConnectRecordPtr);
-
- // Statement blocks
- void updatePackedList(Signal* signal, HostRecord* ahostptr,
- Uint16 ahostIndex);
- void clearTcNodeData(Signal* signal,
- UintR TLastLqhIndicator,
- UintR Tstart);
- void errorReport(Signal* signal, int place);
- void warningReport(Signal* signal, int place);
- void printState(Signal* signal, int place);
- int seizeTcRecord(Signal* signal);
- int seizeCacheRecord(Signal* signal);
- void TCKEY_abort(Signal* signal, int place);
- void copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR copyLen);
- void reportNodeFailed(Signal* signal, Uint32 nodeId);
- void sendPackedTCKEYCONF(Signal* signal,
- HostRecord * ahostptr,
- UintR hostId);
- void sendPackedTCINDXCONF(Signal* signal,
- HostRecord * ahostptr,
- UintR hostId);
- void sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr);
- void sendCommitLqh(Signal* signal,
- TcConnectRecord * const regTcPtr);
- void sendCompleteLqh(Signal* signal,
- TcConnectRecord * const regTcPtr);
- void sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord *);
- void sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord *);
- void checkStartTimeout(Signal* signal);
- void checkStartFragTimeout(Signal* signal);
- void timeOutFoundFragLab(Signal* signal, Uint32 TscanConPtr);
- void timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr);
- int releaseAndAbort(Signal* signal);
- void findApiConnectFail(Signal* signal);
- void findTcConnectFail(Signal* signal);
- void initApiConnectFail(Signal* signal);
- void initTcConnectFail(Signal* signal);
- void initTcFail(Signal* signal);
- void releaseTakeOver(Signal* signal);
- void setupFailData(Signal* signal);
- void updateApiStateFail(Signal* signal);
- void updateTcStateFail(Signal* signal);
- void handleApiFailState(Signal* signal, UintR anApiConnectptr);
- void handleFailedApiNode(Signal* signal,
- UintR aFailedNode,
- UintR anApiConnectPtr);
- void handleScanStop(Signal* signal, UintR aFailedNode);
- void initScanTcrec(Signal* signal);
- void initScanrec(ScanRecordPtr, const class ScanTabReq*,
- const UintR scanParallel,
- const UintR noOprecPerFrag);
- void initScanfragrec(Signal* signal);
- void releaseScanResources(ScanRecordPtr, bool not_started = false);
- ScanRecordPtr seizeScanrec(Signal* signal);
- void sendScanFragReq(Signal*, ScanRecord*, ScanFragRec*);
- void sendScanTabConf(Signal* signal, ScanRecordPtr);
- void close_scan_req(Signal*, ScanRecordPtr, bool received_req);
- void close_scan_req_send_conf(Signal*, ScanRecordPtr);
-
- void checkGcp(Signal* signal);
- void commitGciHandling(Signal* signal, UintR Tgci);
- void copyApi(Signal* signal);
- void DIVER_node_fail_handling(Signal* signal, UintR Tgci);
- 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,
- bool releaseIndexOperations = false);
- void initattrbuf(Signal* signal);
- void initdatabuf(Signal* signal);
- void initgcp(Signal* signal);
- void inithost(Signal* signal);
- void initialiseScanrec(Signal* signal);
- void initialiseScanFragrec(Signal* signal);
- void initialiseScanOprec(Signal* signal);
- void initTable(Signal* signal);
- void initialiseTcConnect(Signal* signal);
- void linkApiToGcp(Signal* signal);
- void linkGciInGcilist(Signal* signal);
- void linkKeybuf(Signal* signal);
- void linkTcInConnectionlist(Signal* signal);
- void releaseAbortResources(Signal* signal);
- void releaseApiCon(Signal* signal, UintR aApiConnectPtr);
- void releaseApiConCopy(Signal* signal);
- void releaseApiConnectFail(Signal* signal);
- void releaseAttrinfo();
- void releaseGcp(Signal* signal);
- void releaseKeys();
- void releaseDirtyRead(Signal*, ApiConnectRecordPtr, TcConnectRecord*);
- void releaseDirtyWrite(Signal* signal);
- void releaseTcCon();
- void releaseTcConnectFail(Signal* signal);
- void releaseTransResources(Signal* signal);
- void saveAttrbuf(Signal* signal);
- void seizeApiConnect(Signal* signal);
- void seizeApiConnectCopy(Signal* signal);
- void seizeApiConnectFail(Signal* signal);
- void seizeDatabuf(Signal* signal);
- void seizeGcp(Signal* signal);
- void seizeTcConnect(Signal* signal);
- void seizeTcConnectFail(Signal* signal);
- void sendApiCommit(Signal* signal);
- void sendAttrinfo(Signal* signal,
- UintR TattrinfoPtr,
- AttrbufRecord * const regAttrPtr,
- UintR TBref);
- void sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr);
- void sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len);
- void sendlqhkeyreq(Signal* signal, BlockReference TBRef);
- void sendSystemError(Signal* signal, int line);
- void sendtckeyconf(Signal* signal, UintR TcommitFlag);
- void sendTcIndxConf(Signal* signal, UintR TcommitFlag);
- void unlinkApiConnect(Signal* signal);
- void unlinkGcp(Signal* signal);
- void unlinkReadyTcCon(Signal* signal);
- void handleFailedOperation(Signal* signal,
- const LqhKeyRef * const lqhKeyRef,
- bool gotLqhKeyRef);
- void markOperationAborted(ApiConnectRecord * const regApiPtr,
- TcConnectRecord * const regTcPtr);
- void clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
- TcConnectRecord * const regTcPtr);
- // Trigger and index handling
- int saveINDXKEYINFO(Signal* signal,
- TcIndexOperation* indexOp,
- const Uint32 *src,
- Uint32 len);
- bool receivedAllINDXKEYINFO(TcIndexOperation* indexOp);
- int saveINDXATTRINFO(Signal* signal,
- TcIndexOperation* indexOp,
- const Uint32 *src,
- Uint32 len);
- bool receivedAllINDXATTRINFO(TcIndexOperation* indexOp);
- bool saveTRANSID_AI(Signal* signal,
- TcIndexOperation* indexOp,
- const Uint32 *src,
- Uint32 len);
- bool receivedAllTRANSID_AI(TcIndexOperation* indexOp);
- void readIndexTable(Signal* signal,
- ApiConnectRecord* regApiPtr,
- TcIndexOperation* indexOp);
- void executeIndexOperation(Signal* signal,
- ApiConnectRecord* regApiPtr,
- TcIndexOperation* indexOp);
- bool seizeIndexOperation(ApiConnectRecord* regApiPtr,
- TcIndexOperationPtr& indexOpPtr);
- void releaseIndexOperation(ApiConnectRecord* regApiPtr,
- TcIndexOperation* indexOp);
- void releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr);
- void setupIndexOpReturn(ApiConnectRecord* regApiPtr,
- TcConnectRecord* regTcPtr);
-
- void saveTriggeringOpState(Signal* signal,
- TcConnectRecord* trigOp);
- void restoreTriggeringOpState(Signal* signal,
- TcConnectRecord* trigOp);
- void continueTriggeringOp(Signal* signal,
- TcConnectRecord* trigOp);
-
- void scheduleFiredTrigger(ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr);
- void executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr);
- void executeTrigger(Signal* signal,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr);
- void executeIndexTrigger(Signal* signal,
- TcDefinedTriggerData* definedTriggerData,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr);
- void insertIntoIndexTable(Signal* signal,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr,
- TcIndexData* indexData,
- bool holdOperation = false);
- void deleteFromIndexTable(Signal* signal,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr,
- TcIndexData* indexData,
- bool holdOperation = false);
- void releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers);
- // Generated statement blocks
- 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);
- void signalErrorRefuseLab(Signal* signal);
- void abort080Lab(Signal* signal);
- void packKeyData000Lab(Signal* signal, BlockReference TBRef, Uint32 len);
- void abortScanLab(Signal* signal, ScanRecordPtr, Uint32 errCode,
- bool not_started = false);
- void sendAbortedAfterTimeout(Signal* signal, int Tcheck);
- void abort010Lab(Signal* signal);
- void abort015Lab(Signal* signal);
- void packLqhkeyreq(Signal* signal, BlockReference TBRef);
- void packLqhkeyreq040Lab(Signal* signal,
- UintR anAttrBufIndex,
- BlockReference TBRef);
- void packLqhkeyreq040Lab(Signal* signal);
- void returnFromQueuedDeliveryLab(Signal* signal);
- void startTakeOverLab(Signal* signal);
- void toCompleteHandlingLab(Signal* signal);
- void toCommitHandlingLab(Signal* signal);
- void toAbortHandlingLab(Signal* signal);
- void abortErrorLab(Signal* signal);
- void nodeTakeOverCompletedLab(Signal* signal);
- void ndbsttorry010Lab(Signal* signal);
- void commit020Lab(Signal* signal);
- void complete010Lab(Signal* signal);
- void releaseAtErrorLab(Signal* signal);
- void seizeDatabuferrorLab(Signal* signal);
- void scanAttrinfoLab(Signal* signal, UintR Tlen);
- void seizeAttrbuferrorLab(Signal* signal);
- void attrinfoDihReceivedLab(Signal* signal);
- void aiErrorLab(Signal* signal);
- void attrinfo020Lab(Signal* signal);
- void scanReleaseResourcesLab(Signal* signal);
- void scanCompletedLab(Signal* signal);
- void scanError(Signal* signal, ScanRecordPtr, Uint32 errorCode);
- void diverify010Lab(Signal* signal);
- void intstartphase2x010Lab(Signal* signal);
- void intstartphase3x010Lab(Signal* signal);
- void sttorryLab(Signal* signal);
- void abortBeginErrorLab(Signal* signal);
- void tabStateErrorLab(Signal* signal);
- void wrongSchemaVersionErrorLab(Signal* signal);
- void noFreeConnectionErrorLab(Signal* signal);
- void tckeyreq050Lab(Signal* signal);
- void timeOutFoundLab(Signal* signal, UintR anAdd, Uint32 errCode);
- void completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd);
- void completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd);
- void completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd);
- void timeOutLoopStartLab(Signal* signal, Uint32 apiConnectPtr);
- void initialiseRecordsLab(Signal* signal, UintR Tdata0, Uint32, Uint32);
- void tckeyreq020Lab(Signal* signal);
- void intstartphase2x020Lab(Signal* signal);
- void intstartphase1x010Lab(Signal* signal);
- void startphase1x010Lab(Signal* signal);
-
- void lqhKeyConf_checkTransactionState(Signal * signal,
- Ptr<ApiConnectRecord> regApiPtr);
-
- void checkDropTab(Signal* signal);
-
- void checkScanActiveInFailedLqh(Signal* signal,
- Uint32 scanPtrI,
- Uint32 failedNodeId);
- void checkScanFragList(Signal*, Uint32 failedNodeId, ScanRecord * scanP,
- LocalDLList<ScanFragRec>::Head&);
-
- void nodeFailCheckTransactions(Signal*,Uint32 transPtrI,Uint32 failedNodeId);
- void checkNodeFailComplete(Signal* signal, Uint32 failedNodeId, Uint32 bit);
-
- // Initialisation
- void initData();
- void initRecords();
-
- // Transit signals
-
-
- ApiConnectRecord *apiConnectRecord;
- ApiConnectRecordPtr apiConnectptr;
- UintR capiConnectFilesize;
-
- TcConnectRecord *tcConnectRecord;
- TcConnectRecordPtr tcConnectptr;
- UintR ctcConnectFilesize;
-
- CacheRecord *cacheRecord;
- CacheRecordPtr cachePtr;
- UintR ccacheFilesize;
-
- AttrbufRecord *attrbufRecord;
- AttrbufRecordPtr attrbufptr;
- UintR cattrbufFilesize;
-
- HostRecord *hostRecord;
- HostRecordPtr hostptr;
- UintR chostFilesize;
- NdbNodeBitmask c_alive_nodes;
-
- GcpRecord *gcpRecord;
- GcpRecordPtr gcpPtr;
- UintR cgcpFilesize;
-
- TableRecord *tableRecord;
- UintR ctabrecFilesize;
-
- UintR thashValue;
- UintR tdistrHashValue;
-
- UintR ttransid_ptr;
- UintR cfailure_nr;
- UintR coperationsize;
- UintR ctcTimer;
- UintR cDbHbInterval;
-
- ApiConnectRecordPtr tmpApiConnectptr;
- UintR tcheckGcpId;
-
- struct TransCounters {
- TransCounters() {}
- enum { Off, Timer, Started } c_trans_status;
- UintR cattrinfoCount;
- UintR ctransCount;
- UintR ccommitCount;
- UintR creadCount;
- UintR csimpleReadCount;
- UintR cwriteCount;
- UintR cabortCount;
- UintR cconcurrentOp;
- Uint32 c_scan_count;
- Uint32 c_range_scan_count;
- void reset () {
- cattrinfoCount = ctransCount = ccommitCount = creadCount =
- csimpleReadCount = cwriteCount = cabortCount =
- c_scan_count = c_range_scan_count = 0;
- }
- Uint32 report(Signal* signal){
- signal->theData[0] = NDB_LE_TransReportCounters;
- signal->theData[1] = ctransCount;
- signal->theData[2] = ccommitCount;
- signal->theData[3] = creadCount;
- signal->theData[4] = csimpleReadCount;
- signal->theData[5] = cwriteCount;
- signal->theData[6] = cattrinfoCount;
- signal->theData[7] = cconcurrentOp;
- signal->theData[8] = cabortCount;
- signal->theData[9] = c_scan_count;
- signal->theData[10] = c_range_scan_count;
- return 11;
- }
- } c_counters;
-
- Uint16 cownNodeid;
- Uint16 terrorCode;
-
- UintR cfirstfreeAttrbuf;
- UintR cfirstfreeTcConnect;
- UintR cfirstfreeApiConnectCopy;
- UintR cfirstfreeCacheRec;
-
- UintR cfirstgcp;
- UintR clastgcp;
- UintR cfirstfreeGcp;
- UintR cfirstfreeScanrec;
-
- TableRecordPtr tabptr;
- UintR cfirstfreeApiConnectFail;
- UintR cfirstfreeApiConnect;
-
- UintR cfirstfreeDatabuf;
- BlockReference cdihblockref;
- BlockReference cownref; /* OWN BLOCK REFERENCE */
-
- ApiConnectRecordPtr timeOutptr;
-
- ScanRecord *scanRecord;
- UintR cscanrecFileSize;
-
- UnsafeArrayPool<ScanFragRec> c_scan_frag_pool;
- ScanFragRecPtr scanFragptr;
-
- UintR cscanFragrecFileSize;
- UintR cdatabufFilesize;
-
- BlockReference cdictblockref;
- BlockReference cerrorBlockref;
- BlockReference clqhblockref;
- BlockReference cndbcntrblockref;
-
- Uint16 csignalKey;
- Uint16 csystemnodes;
- Uint16 cnodes[4];
- NodeId cmasterNodeId;
- UintR cnoParallelTakeOver;
- TimeOutCheckState ctimeOutCheckFragActive;
-
- UintR ctimeOutCheckFragCounter;
- UintR ctimeOutCheckCounter;
- UintR ctimeOutValue;
- UintR ctimeOutCheckDelay;
- Uint32 ctimeOutCheckHeartbeat;
- Uint32 ctimeOutCheckLastHeartbeat;
- Uint32 ctimeOutMissedHeartbeats;
- Uint32 c_appl_timeout_value;
-
- SystemStartState csystemStart;
- TimeOutCheckState ctimeOutCheckActive;
-
- BlockReference capiFailRef;
- UintR cpackedListIndex;
- Uint16 cpackedList[MAX_NODES];
- UintR capiConnectClosing[MAX_NODES];
- UintR con_lineNodes;
-
- DatabufRecord *databufRecord;
- DatabufRecordPtr databufptr;
- DatabufRecordPtr tmpDatabufptr;
-
- UintR treqinfo;
- UintR ttransid1;
- UintR ttransid2;
-
- UintR tabortInd;
-
- NodeId tnodeid;
- BlockReference tblockref;
-
- LqhTransConf::OperationStatus ttransStatus;
- UintR ttcOprec;
- NodeId tfailedNodeId;
- Uint8 tcurrentReplicaNo;
- Uint8 tpad1;
-
- UintR tgci;
- UintR tapplRef;
- UintR tapplOprec;
-
- UintR tindex;
- UintR tmaxData;
- UintR tmp;
-
- UintR tnodes;
- BlockReference tusersblkref;
- UintR tuserpointer;
- UintR tloadCode;
-
- UintR tconfig1;
- UintR tconfig2;
-
- UintR cdata[32];
- UintR ctransidFailHash[512];
- UintR ctcConnectFailHash[1024];
-
- /**
- * Commit Ack handling
- */
-public:
- struct CommitAckMarker {
- CommitAckMarker() {}
- Uint32 transid1;
- Uint32 transid2;
- union { Uint32 nextPool; Uint32 nextHash; };
- Uint32 prevHash;
- Uint32 apiConnectPtr;
- Uint16 apiNodeId;
- Uint16 noOfLqhs;
- Uint16 lqhNodeId[MAX_REPLICAS];
-
- inline bool equal(const CommitAckMarker & p) const {
- return ((p.transid1 == transid1) && (p.transid2 == transid2));
- }
-
- inline Uint32 hashValue() const {
- return transid1;
- }
- };
-private:
- typedef Ptr<CommitAckMarker> CommitAckMarkerPtr;
- typedef DLHashTable<CommitAckMarker>::Iterator CommitAckMarkerIterator;
-
- ArrayPool<CommitAckMarker> m_commitAckMarkerPool;
- DLHashTable<CommitAckMarker> m_commitAckMarkerHash;
-
- void execTC_COMMIT_ACK(Signal* signal);
- void sendRemoveMarkers(Signal*, const CommitAckMarker *);
- void sendRemoveMarker(Signal* signal,
- NodeId nodeId,
- Uint32 transid1,
- Uint32 transid2);
- void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket);
-
- bool getAllowStartTransaction(Uint32 nodeId, Uint32 table_single_user_mode) const {
- if (unlikely(getNodeState().getSingleUserMode()))
- {
- if (getNodeState().getSingleUserApi() == nodeId || table_single_user_mode)
- return true;
- else
- return false;
- }
- return getNodeState().startLevel < NodeState::SL_STOPPING_2;
- }
-
- void checkAbortAllTimeout(Signal* signal, Uint32 sleepTime);
- struct AbortAllRecord {
- AbortAllRecord(){ clientRef = 0; }
- Uint32 clientData;
- BlockReference clientRef;
-
- Uint32 oldTimeOutValue;
- };
- AbortAllRecord c_abortRec;
-
- /************************** API CONNECT RECORD ***********************/
- /* *******************************************************************/
- /* THE API CONNECT RECORD CONTAINS THE CONNECTION RECORD TO WHICH THE*/
- /* APPLICATION CONNECTS. THE APPLICATION CAN SEND ONE OPERATION AT A */
- /* TIME. IT CAN SEND A NEW OPERATION IMMEDIATELY AFTER SENDING THE */
- /* PREVIOUS OPERATION. THEREBY SEVERAL OPERATIONS CAN BE ACTIVE IN */
- /* ONE TRANSACTION WITHIN TC. THIS IS ACHIEVED BY USING THE API */
- /* CONNECT RECORD. EACH ACTIVE OPERATION IS HANDLED BY THE TC */
- /* CONNECT RECORD. AS SOON AS THE TC CONNECT RECORD HAS SENT THE */
- /* REQUEST TO THE LQH IT IS READY TO RECEIVE NEW OPERATIONS. THE */
- /* LQH CONNECT RECORD TAKES CARE OF WAITING FOR AN OPERATION TO */
- /* COMPLETE. WHEN AN OPERATION HAS COMPLETED ON THE LQH CONNECT */
- /* RECORD A NEW OPERATION CAN BE STARTED ON THIS LQH CONNECT RECORD. */
- /*******************************************************************>*/
- /* */
- /* API CONNECT RECORD ALIGNED TO BE 256 BYTES */
- /*******************************************************************>*/
- /************************** TC CONNECT RECORD ************************/
- /* *******************************************************************/
- /* TC CONNECT RECORD KEEPS ALL INFORMATION TO CARRY OUT A TRANSACTION*/
- /* THE TRANSACTION CONTROLLER ESTABLISHES CONNECTIONS TO DIFFERENT */
- /* BLOCKS TO CARRY OUT THE TRANSACTION. THERE CAN BE SEVERAL RECORDS */
- /* PER ACTIVE TRANSACTION. THE TC CONNECT RECORD COOPERATES WITH THE */
- /* API CONNECT RECORD FOR COMMUNICATION WITH THE API AND WITH THE */
- /* LQH CONNECT RECORD FOR COMMUNICATION WITH THE LQH'S INVOLVED IN */
- /* THE TRANSACTION. TC CONNECT RECORD IS PERMANENTLY CONNECTED TO A */
- /* RECORD IN DICT AND ONE IN DIH. IT CONTAINS A LIST OF ACTIVE LQH */
- /* CONNECT RECORDS AND A LIST OF STARTED BUT NOT ACTIVE LQH CONNECT */
- /* RECORDS. IT DOES ALSO CONTAIN A LIST OF ALL OPERATIONS THAT ARE */
- /* EXECUTED WITH THE TC CONNECT RECORD. */
- /*******************************************************************>*/
- /* TC_CONNECT RECORD ALIGNED TO BE 128 BYTES */
- /*******************************************************************>*/
- UintR cfirstfreeTcConnectFail;
-
- /* POINTER FOR THE LQH RECORD*/
- /* ************************ HOST RECORD ********************************* */
- /********************************************************/
- /* THIS RECORD CONTAINS ALIVE-STATUS ON ALL NODES IN THE*/
- /* SYSTEM */
- /********************************************************/
- /* THIS RECORD IS ALIGNED TO BE 8 BYTES. */
- /********************************************************/
- /* ************************ TABLE RECORD ******************************** */
- /********************************************************/
- /* THIS RECORD CONTAINS THE CURRENT SCHEMA VERSION OF */
- /* ALL TABLES IN THE SYSTEM. */
- /********************************************************/
- /*-------------------------------------------------------------------------*/
- /* THE TC CONNECTION USED BY THIS SCAN. */
- /*-------------------------------------------------------------------------*/
- /*-------------------------------------------------------------------------*/
- /* LENGTH READ FOR A PARTICULAR SCANNED OPERATION. */
- /*-------------------------------------------------------------------------*/
- /*-------------------------------------------------------------------------*/
- /* REFERENCE TO THE SCAN RECORD FOR THIS SCAN PROCESS. */
- /*-------------------------------------------------------------------------*/
- /* *********************************************************************** */
- /* ******$ DATA BUFFER ******$ */
- /* */
- /* THIS BUFFER IS USED AS A GENERAL DATA STORAGE. */
- /* *********************************************************************** */
- /* *********************************************************************** */
- /* ******$ ATTRIBUTE INFORMATION RECORD ******$ */
- /*
- CAN CONTAIN ONE (1) ATTRINFO SIGNAL. ONE SIGNAL CONTAINS 24 ATTR.
- INFO WORDS. BUT 32 ELEMENTS ARE USED TO MAKE PLEX HAPPY.
- SOME OF THE ELEMENTS ARE USED TO THE FOLLOWING THINGS:
- DATA LENGHT IN THIS RECORD IS STORED IN THE ELEMENT INDEXED BY
- ZINBUF_DATA_LEN.
- NEXT FREE ATTRBUF IS POINTED OUT BY THE ELEMENT INDEXED BY
- PREVIOUS ATTRBUF IS POINTED OUT BY THE ELEMENT INDEXED BY ZINBUF_PREV
- (NOT USED YET).
- NEXT ATTRBUF IS POINTED OUT BY THE ELEMENT INDEXED BY ZINBUF_NEXT.
- */
- /* ********************************************************************** */
- /**************************************************************************/
- /* GLOBAL CHECKPOINT INFORMATION RECORD */
- /* */
- /* THIS RECORD IS USED TO STORE THE GCP NUMBER AND A COUNTER */
- /* DURING THE COMPLETION PHASE OF THE TRANSACTION */
- /**************************************************************************/
- /* */
- /* GCP RECORD ALIGNED TO BE 32 BYTES */
- /**************************************************************************/
- /**************************************************************************/
- /* TC_FAIL_RECORD */
- /* THIS RECORD IS USED WHEN HANDLING TAKE OVER OF ANOTHER FAILED TC NODE.*/
- /**************************************************************************/
- TcFailRecord *tcFailRecord;
- TcFailRecordPtr tcNodeFailptr;
- /**************************************************************************/
- // Temporary variables that are not allowed to use for storage between
- // signals. They
- // can only be used in a signal to transfer values between subroutines.
- // In the long run
- // those variables should be removed and exchanged for stack
- // variable communication.
- /**************************************************************************/
-
- Uint32 c_gcp_ref;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
deleted file mode 100644
index 22a1d7edb36..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
+++ /dev/null
@@ -1,378 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTC_C
-#include "Dbtc.hpp"
-#include <pc.hpp>
-#include <ndb_limits.h>
-#include <Properties.hpp>
-#include <Configuration.hpp>
-
-#define DEBUG(x) { ndbout << "TC::" << x << endl; }
-
-
-void Dbtc::initData()
-{
- cattrbufFilesize = ZATTRBUF_FILESIZE;
- capiConnectFilesize = ZAPI_CONNECT_FILESIZE;
- ccacheFilesize = ZAPI_CONNECT_FILESIZE;
- chostFilesize = MAX_NODES;
- cdatabufFilesize = ZDATABUF_FILESIZE;
- cgcpFilesize = ZGCP_FILESIZE;
- cscanrecFileSize = ZSCANREC_FILE_SIZE;
- cscanFragrecFileSize = ZSCAN_FRAGREC_FILE_SIZE;
- ctabrecFilesize = ZTABREC_FILESIZE;
- ctcConnectFilesize = ZTC_CONNECT_FILESIZE;
- cdihblockref = DBDIH_REF;
- cdictblockref = DBDICT_REF;
- clqhblockref = DBLQH_REF;
- cerrorBlockref = NDBCNTR_REF;
-
- // Records with constant sizes
- tcFailRecord = (TcFailRecord*)allocRecord("TcFailRecord",
- sizeof(TcFailRecord), 1);
-
- // Variables
- ctcTimer = 0;
-
- // Trigger and index pools
- c_theDefinedTriggerPool.setSize(c_maxNumberOfDefinedTriggers);
- c_theFiredTriggerPool.setSize(c_maxNumberOfFiredTriggers);
- c_theIndexPool.setSize(c_maxNumberOfIndexes);
- c_theIndexOperationPool.setSize(c_maxNumberOfIndexOperations);
- c_theAttributeBufferPool.setSize(c_transactionBufferSpace);
- c_firedTriggerHash.setSize((c_maxNumberOfFiredTriggers+10)/10);
-}//Dbtc::initData()
-
-void Dbtc::initRecords()
-{
- void *p;
- // Records with dynamic sizes
- cacheRecord = (CacheRecord*)allocRecord("CacheRecord",
- sizeof(CacheRecord),
- ccacheFilesize);
-
- apiConnectRecord = (ApiConnectRecord*)allocRecord("ApiConnectRecord",
- sizeof(ApiConnectRecord),
- capiConnectFilesize);
-
- for(unsigned i = 0; i<capiConnectFilesize; i++) {
- p = &apiConnectRecord[i];
- new (p) ApiConnectRecord(c_theFiredTriggerPool,
- c_theIndexOperationPool);
- }
- // Init all fired triggers
- DLFifoList<TcFiredTriggerData> triggers(c_theFiredTriggerPool);
- FiredTriggerPtr tptr;
- while(triggers.seize(tptr) == true) {
- p= tptr.p;
- new (p) TcFiredTriggerData();
- }
- triggers.release();
-
- /*
- // Init all index records
- ArrayList<TcIndexData> indexes(c_theIndexPool);
- TcIndexDataPtr iptr;
- while(indexes.seize(iptr) == true) {
- new (iptr.p) TcIndexData(c_theAttrInfoListPool);
- }
- indexes.release();
- */
-
- // Init all index operation records
- SLList<TcIndexOperation> indexOps(c_theIndexOperationPool);
- TcIndexOperationPtr ioptr;
- while(indexOps.seize(ioptr) == true) {
- p= ioptr.p;
- new (p) TcIndexOperation(c_theAttributeBufferPool);
- }
- indexOps.release();
-
- c_apiConTimer = (UintR*)allocRecord("ApiConTimer",
- sizeof(UintR),
- capiConnectFilesize);
-
- c_apiConTimer_line = (UintR*)allocRecord("ApiConTimer_line",
- sizeof(UintR),
- capiConnectFilesize);
-
- tcConnectRecord = (TcConnectRecord*)allocRecord("TcConnectRecord",
- sizeof(TcConnectRecord),
- ctcConnectFilesize);
-
- m_commitAckMarkerPool.setSize(capiConnectFilesize);
- m_commitAckMarkerHash.setSize(512);
-
- hostRecord = (HostRecord*)allocRecord("HostRecord",
- sizeof(HostRecord),
- chostFilesize);
-
- tableRecord = (TableRecord*)allocRecord("TableRecord",
- sizeof(TableRecord),
- ctabrecFilesize);
-
- scanRecord = (ScanRecord*)allocRecord("ScanRecord",
- sizeof(ScanRecord),
- cscanrecFileSize);
-
-
- c_scan_frag_pool.setSize(cscanFragrecFileSize);
- {
- ScanFragRecPtr ptr;
- SLList<ScanFragRec> tmp(c_scan_frag_pool);
- while(tmp.seize(ptr)) {
- new (ptr.p) ScanFragRec();
- }
- tmp.release();
- }
-
- indexOps.release();
-
- databufRecord = (DatabufRecord*)allocRecord("DatabufRecord",
- sizeof(DatabufRecord),
- cdatabufFilesize);
-
- attrbufRecord = (AttrbufRecord*)allocRecord("AttrbufRecord",
- sizeof(AttrbufRecord),
- cattrbufFilesize);
-
- gcpRecord = (GcpRecord*)allocRecord("GcpRecord",
- sizeof(GcpRecord),
- cgcpFilesize);
-
-}//Dbtc::initRecords()
-
-Dbtc::Dbtc(Block_context& ctx):
- SimulatedBlock(DBTC, ctx),
- c_theDefinedTriggers(c_theDefinedTriggerPool),
- c_firedTriggerHash(c_theFiredTriggerPool),
- c_maxNumberOfDefinedTriggers(0),
- c_maxNumberOfFiredTriggers(0),
- c_theIndexes(c_theIndexPool),
- c_maxNumberOfIndexes(0),
- c_maxNumberOfIndexOperations(0),
- m_commitAckMarkerHash(m_commitAckMarkerPool)
-{
- BLOCK_CONSTRUCTOR(Dbtc);
-
- const ndb_mgm_configuration_iterator * p =
- ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Uint32 transactionBufferMemory = 0;
- Uint32 maxNoOfIndexes = 0, maxNoOfConcurrentIndexOperations = 0;
- Uint32 maxNoOfTriggers = 0, maxNoOfFiredTriggers = 0;
-
- ndb_mgm_get_int_parameter(p, CFG_DB_TRANS_BUFFER_MEM,
- &transactionBufferMemory);
- ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE,
- &maxNoOfIndexes);
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_INDEX_OPS,
- &maxNoOfConcurrentIndexOperations);
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
- &maxNoOfTriggers);
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGER_OPS,
- &maxNoOfFiredTriggers);
-
- c_transactionBufferSpace =
- transactionBufferMemory / AttributeBuffer::getSegmentSize();
- c_maxNumberOfIndexes = maxNoOfIndexes;
- c_maxNumberOfIndexOperations = maxNoOfConcurrentIndexOperations;
- c_maxNumberOfDefinedTriggers = maxNoOfTriggers;
- c_maxNumberOfFiredTriggers = maxNoOfFiredTriggers;
-
- // Transit signals
- addRecSignal(GSN_PACKED_SIGNAL, &Dbtc::execPACKED_SIGNAL);
- addRecSignal(GSN_ABORTED, &Dbtc::execABORTED);
- addRecSignal(GSN_ATTRINFO, &Dbtc::execATTRINFO);
- addRecSignal(GSN_CONTINUEB, &Dbtc::execCONTINUEB);
- addRecSignal(GSN_KEYINFO, &Dbtc::execKEYINFO);
- addRecSignal(GSN_SCAN_NEXTREQ, &Dbtc::execSCAN_NEXTREQ);
- addRecSignal(GSN_TAKE_OVERTCREQ, &Dbtc::execTAKE_OVERTCREQ);
- addRecSignal(GSN_TAKE_OVERTCCONF, &Dbtc::execTAKE_OVERTCCONF);
- addRecSignal(GSN_LQHKEYREF, &Dbtc::execLQHKEYREF);
-
- // Received signals
-
- addRecSignal(GSN_DUMP_STATE_ORD, &Dbtc::execDUMP_STATE_ORD);
- addRecSignal(GSN_SEND_PACKED, &Dbtc::execSEND_PACKED);
- addRecSignal(GSN_SCAN_HBREP, &Dbtc::execSCAN_HBREP);
- addRecSignal(GSN_COMPLETED, &Dbtc::execCOMPLETED);
- addRecSignal(GSN_COMMITTED, &Dbtc::execCOMMITTED);
- addRecSignal(GSN_DIGETPRIMCONF, &Dbtc::execDIGETPRIMCONF);
- addRecSignal(GSN_DIGETPRIMREF, &Dbtc::execDIGETPRIMREF);
- addRecSignal(GSN_DISEIZECONF, &Dbtc::execDISEIZECONF);
- addRecSignal(GSN_DIVERIFYCONF, &Dbtc::execDIVERIFYCONF);
- addRecSignal(GSN_DI_FCOUNTCONF, &Dbtc::execDI_FCOUNTCONF);
- addRecSignal(GSN_DI_FCOUNTREF, &Dbtc::execDI_FCOUNTREF);
- addRecSignal(GSN_GCP_NOMORETRANS, &Dbtc::execGCP_NOMORETRANS);
- addRecSignal(GSN_LQHKEYCONF, &Dbtc::execLQHKEYCONF);
- addRecSignal(GSN_NDB_STTOR, &Dbtc::execNDB_STTOR);
- addRecSignal(GSN_READ_NODESCONF, &Dbtc::execREAD_NODESCONF);
- addRecSignal(GSN_READ_NODESREF, &Dbtc::execREAD_NODESREF);
- addRecSignal(GSN_STTOR, &Dbtc::execSTTOR);
- addRecSignal(GSN_TC_COMMITREQ, &Dbtc::execTC_COMMITREQ);
- addRecSignal(GSN_TC_CLOPSIZEREQ, &Dbtc::execTC_CLOPSIZEREQ);
- addRecSignal(GSN_TCGETOPSIZEREQ, &Dbtc::execTCGETOPSIZEREQ);
- addRecSignal(GSN_TCKEYREQ, &Dbtc::execTCKEYREQ);
- addRecSignal(GSN_TCRELEASEREQ, &Dbtc::execTCRELEASEREQ);
- addRecSignal(GSN_TCSEIZEREQ, &Dbtc::execTCSEIZEREQ);
- addRecSignal(GSN_TCROLLBACKREQ, &Dbtc::execTCROLLBACKREQ);
- addRecSignal(GSN_TC_HBREP, &Dbtc::execTC_HBREP);
- addRecSignal(GSN_TC_SCHVERREQ, &Dbtc::execTC_SCHVERREQ);
- addRecSignal(GSN_SCAN_TABREQ, &Dbtc::execSCAN_TABREQ);
- addRecSignal(GSN_SCAN_FRAGCONF, &Dbtc::execSCAN_FRAGCONF);
- addRecSignal(GSN_SCAN_FRAGREF, &Dbtc::execSCAN_FRAGREF);
- addRecSignal(GSN_READ_CONFIG_REQ, &Dbtc::execREAD_CONFIG_REQ, true);
- addRecSignal(GSN_LQH_TRANSCONF, &Dbtc::execLQH_TRANSCONF);
- addRecSignal(GSN_COMPLETECONF, &Dbtc::execCOMPLETECONF);
- addRecSignal(GSN_COMMITCONF, &Dbtc::execCOMMITCONF);
- addRecSignal(GSN_ABORTCONF, &Dbtc::execABORTCONF);
- addRecSignal(GSN_NODE_FAILREP, &Dbtc::execNODE_FAILREP);
- addRecSignal(GSN_INCL_NODEREQ, &Dbtc::execINCL_NODEREQ);
- addRecSignal(GSN_TIME_SIGNAL, &Dbtc::execTIME_SIGNAL);
- addRecSignal(GSN_API_FAILREQ, &Dbtc::execAPI_FAILREQ);
-
- addRecSignal(GSN_TC_COMMIT_ACK, &Dbtc::execTC_COMMIT_ACK);
- addRecSignal(GSN_ABORT_ALL_REQ, &Dbtc::execABORT_ALL_REQ);
-
- addRecSignal(GSN_CREATE_TRIG_REQ, &Dbtc::execCREATE_TRIG_REQ);
- addRecSignal(GSN_DROP_TRIG_REQ, &Dbtc::execDROP_TRIG_REQ);
- addRecSignal(GSN_FIRE_TRIG_ORD, &Dbtc::execFIRE_TRIG_ORD);
- addRecSignal(GSN_TRIG_ATTRINFO, &Dbtc::execTRIG_ATTRINFO);
-
- addRecSignal(GSN_CREATE_INDX_REQ, &Dbtc::execCREATE_INDX_REQ);
- addRecSignal(GSN_DROP_INDX_REQ, &Dbtc::execDROP_INDX_REQ);
- addRecSignal(GSN_TCINDXREQ, &Dbtc::execTCINDXREQ);
- addRecSignal(GSN_INDXKEYINFO, &Dbtc::execINDXKEYINFO);
- addRecSignal(GSN_INDXATTRINFO, &Dbtc::execINDXATTRINFO);
- addRecSignal(GSN_ALTER_INDX_REQ, &Dbtc::execALTER_INDX_REQ);
-
- addRecSignal(GSN_TRANSID_AI_R, &Dbtc::execTRANSID_AI_R);
- addRecSignal(GSN_KEYINFO20_R, &Dbtc::execKEYINFO20_R);
-
- // Index table lookup
- addRecSignal(GSN_TCKEYCONF, &Dbtc::execTCKEYCONF);
- addRecSignal(GSN_TCKEYREF, &Dbtc::execTCKEYREF);
- addRecSignal(GSN_TRANSID_AI, &Dbtc::execTRANSID_AI);
- addRecSignal(GSN_TCROLLBACKREP, &Dbtc::execTCROLLBACKREP);
-
- //addRecSignal(GSN_CREATE_TAB_REQ, &Dbtc::execCREATE_TAB_REQ);
- addRecSignal(GSN_DROP_TAB_REQ, &Dbtc::execDROP_TAB_REQ);
- addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbtc::execPREP_DROP_TAB_REQ);
- addRecSignal(GSN_WAIT_DROP_TAB_REF, &Dbtc::execWAIT_DROP_TAB_REF);
- addRecSignal(GSN_WAIT_DROP_TAB_CONF, &Dbtc::execWAIT_DROP_TAB_CONF);
-
- addRecSignal(GSN_ALTER_TAB_REQ, &Dbtc::execALTER_TAB_REQ);
- addRecSignal(GSN_ROUTE_ORD, &Dbtc::execROUTE_ORD);
-
- 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,
- &tcConnectptr,
- &cachePtr,
- &attrbufptr,
- &hostptr,
- &gcpPtr,
- &tmpApiConnectptr,
- &timeOutptr,
- &scanFragptr,
- &databufptr,
- &tmpDatabufptr };
- init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
- }
-#endif
- 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;
-}//Dbtc::Dbtc()
-
-Dbtc::~Dbtc()
-{
- // Records with dynamic sizes
- deallocRecord((void **)&cacheRecord, "CacheRecord",
- sizeof(CacheRecord),
- ccacheFilesize);
-
- deallocRecord((void **)&apiConnectRecord, "ApiConnectRecord",
- sizeof(ApiConnectRecord),
- capiConnectFilesize);
-
- deallocRecord((void **)&tcConnectRecord, "TcConnectRecord",
- sizeof(TcConnectRecord),
- ctcConnectFilesize);
-
- deallocRecord((void **)&hostRecord, "HostRecord",
- sizeof(HostRecord),
- chostFilesize);
-
- deallocRecord((void **)&tableRecord, "TableRecord",
- sizeof(TableRecord),
- ctabrecFilesize);
-
- deallocRecord((void **)&scanRecord, "ScanRecord",
- sizeof(ScanRecord),
- cscanrecFileSize);
-
- deallocRecord((void **)&databufRecord, "DatabufRecord",
- sizeof(DatabufRecord),
- cdatabufFilesize);
-
- deallocRecord((void **)&attrbufRecord, "AttrbufRecord",
- sizeof(AttrbufRecord),
- cattrbufFilesize);
-
- deallocRecord((void **)&gcpRecord, "GcpRecord",
- sizeof(GcpRecord),
- cgcpFilesize);
-
- deallocRecord((void **)&tcFailRecord, "TcFailRecord",
- sizeof(TcFailRecord), 1);
-
- deallocRecord((void **)&c_apiConTimer, "ApiConTimer",
- sizeof(UintR),
- capiConnectFilesize);
-
- deallocRecord((void **)&c_apiConTimer_line, "ApiConTimer",
- sizeof(UintR),
- capiConnectFilesize);
-}//Dbtc::~Dbtc()
-
-BLOCK_FUNCTIONS(Dbtc)
-
diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
deleted file mode 100644
index f4b0e07854c..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ /dev/null
@@ -1,13612 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTC_C
-
-#include "Dbtc.hpp"
-#include "md5_hash.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <my_sys.h>
-#include <ndb_rand.h>
-
-#include <signaldata/EventReport.hpp>
-#include <signaldata/TcKeyReq.hpp>
-#include <signaldata/TcKeyConf.hpp>
-#include <signaldata/TcKeyRef.hpp>
-#include <signaldata/KeyInfo.hpp>
-#include <signaldata/AttrInfo.hpp>
-#include <signaldata/TransIdAI.hpp>
-#include <signaldata/TcRollbackRep.hpp>
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/NFCompleteRep.hpp>
-#include <signaldata/LqhKey.hpp>
-#include <signaldata/TcCommit.hpp>
-#include <signaldata/TcContinueB.hpp>
-#include <signaldata/TcKeyFailConf.hpp>
-#include <signaldata/AbortAll.hpp>
-#include <signaldata/DihFragCount.hpp>
-#include <signaldata/ScanFrag.hpp>
-#include <signaldata/ScanTab.hpp>
-#include <signaldata/PrepDropTab.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/AlterTab.hpp>
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/DropTrig.hpp>
-#include <signaldata/FireTrigOrd.hpp>
-#include <signaldata/TrigAttrInfo.hpp>
-#include <signaldata/CreateIndx.hpp>
-#include <signaldata/DropIndx.hpp>
-#include <signaldata/AlterIndx.hpp>
-#include <signaldata/ScanTab.hpp>
-#include <signaldata/SystemError.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/DisconnectRep.hpp>
-#include <signaldata/TcHbRep.hpp>
-
-#include <signaldata/PrepDropTab.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/TcIndx.hpp>
-#include <signaldata/IndxKeyInfo.hpp>
-#include <signaldata/IndxAttrInfo.hpp>
-#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>
-
-#include <signaldata/RouteOrd.hpp>
-
-// Use DEBUG to print messages that should be
-// seen only when we debug the product
-#ifdef VM_TRACE
-#define DEBUG(x) ndbout << "DBTC: "<< x << endl;
-#else
-#define DEBUG(x)
-#endif
-
-#define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
-
-#ifdef VM_TRACE
-NdbOut &
-operator<<(NdbOut& out, Dbtc::ConnectionState state){
- switch(state){
- case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
- case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
- case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
- case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
- case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
- case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
- case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
- case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
- case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
- case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
- case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
- case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
- case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
- case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
- case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
- case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
- case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
- case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
- case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
- case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
- case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
- case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
- case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
- case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
- case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
- case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
- default:
- out << "Unknown: " << (int)state; break;
- }
- return out;
-}
-NdbOut &
-operator<<(NdbOut& out, Dbtc::OperationState state){
- out << (int)state;
- return out;
-}
-NdbOut &
-operator<<(NdbOut& out, Dbtc::AbortState state){
- out << (int)state;
- return out;
-}
-NdbOut &
-operator<<(NdbOut& out, Dbtc::ReturnSignal state){
- out << (int)state;
- return out;
-}
-NdbOut &
-operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
- out << (int)state;
- return out;
-}
-NdbOut &
-operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
- out << (int)state;
- return out;
-}
-#endif
-
-void
-Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
-{
- if (apiPtr.p->buddyPtr != RNIL) {
- jam();
- ApiConnectRecordPtr buddyApiPtr;
- buddyApiPtr.i = apiPtr.p->buddyPtr;
- ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
- if (getApiConTimer(buddyApiPtr.i) != 0) {
- if ((apiPtr.p->transid[0] == buddyApiPtr.p->transid[0]) &&
- (apiPtr.p->transid[1] == buddyApiPtr.p->transid[1])) {
- jam();
- setApiConTimer(buddyApiPtr.i, ctcTimer, __LINE__);
- } else {
- jam();
- // Not a buddy anymore since not the same transid
- apiPtr.p->buddyPtr = RNIL;
- }//if
- }//if
- }//if
-}
-
-void Dbtc::execCONTINUEB(Signal* signal)
-{
- UintR tcase;
-
- jamEntry();
- tcase = signal->theData[0];
- UintR Tdata0 = signal->theData[1];
- UintR Tdata1 = signal->theData[2];
- UintR Tdata2 = signal->theData[3];
- switch (tcase) {
- case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
- jam();
- ndbrequire(false);
- return;
- case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
- jam();
- tcNodeFailptr.i = Tdata0;
- ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
- completeTransAtTakeOverLab(signal, Tdata1);
- return;
- case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
- jam();
- timeOutLoopStartLab(signal, Tdata0);
- return;
- case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
- jam();
- tnodeid = Tdata0;
- tcNodeFailptr.i = 0;
- ptrAss(tcNodeFailptr, tcFailRecord);
- nodeTakeOverCompletedLab(signal);
- return;
- case TcContinueB::ZINITIALISE_RECORDS:
- jam();
- initialiseRecordsLab(signal, Tdata0, Tdata2, signal->theData[4]);
- return;
- case TcContinueB::ZSEND_COMMIT_LOOP:
- jam();
- apiConnectptr.i = Tdata0;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- tcConnectptr.i = Tdata1;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- commit020Lab(signal);
- return;
- case TcContinueB::ZSEND_COMPLETE_LOOP:
- jam();
- apiConnectptr.i = Tdata0;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- tcConnectptr.i = Tdata1;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- complete010Lab(signal);
- return;
- case TcContinueB::ZHANDLE_FAILED_API_NODE:
- jam();
- handleFailedApiNode(signal, Tdata0, Tdata1);
- return;
- case TcContinueB::ZTRANS_EVENT_REP:
- jam();
- /* -------------------------------------------------------------------- */
- // Report information about transaction activity once per second.
- /* -------------------------------------------------------------------- */
- if (c_counters.c_trans_status == TransCounters::Timer){
- Uint32 len = c_counters.report(signal);
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
-
- c_counters.reset();
- signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
- }
- return;
- case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
- jam();
- timeOutLoopStartFragLab(signal, Tdata0);
- return;
- case TcContinueB::ZABORT_BREAK:
- jam();
- tcConnectptr.i = Tdata0;
- apiConnectptr.i = Tdata1;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- apiConnectptr.p->counter--;
- abort015Lab(signal);
- return;
- case TcContinueB::ZABORT_TIMEOUT_BREAK:
- jam();
- tcConnectptr.i = Tdata0;
- apiConnectptr.i = Tdata1;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- apiConnectptr.p->counter--;
- sendAbortedAfterTimeout(signal, 1);
- return;
- case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
- jam();
- removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
- return;
- case TcContinueB::ZWAIT_ABORT_ALL:
- jam();
- checkAbortAllTimeout(signal, Tdata0);
- return;
- case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
- jam();
- checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
- return;
- case TcContinueB::ZNF_CHECK_TRANSACTIONS:
- jam();
- nodeFailCheckTransactions(signal, Tdata0, Tdata1);
- return;
- case TcContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH:
- jam();
- checkWaitDropTabFailedLqh(signal, Tdata0, Tdata1);
- return;
- case TcContinueB::TRIGGER_PENDING:
- jam();
- ApiConnectRecordPtr transPtr;
- transPtr.i = Tdata0;
- ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
- transPtr.p->triggerPending = false;
- executeTriggers(signal, &transPtr);
- return;
- case TcContinueB::DelayTCKEYCONF:
- jam();
- apiConnectptr.i = Tdata0;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- sendtckeyconf(signal, Tdata1);
- return;
- default:
- ndbrequire(false);
- }//switch
-}
-
-void Dbtc::execDIGETNODESREF(Signal* signal)
-{
- jamEntry();
- terrorCode = signal->theData[1];
- releaseAtErrorLab(signal);
-}
-
-void Dbtc::execINCL_NODEREQ(Signal* signal)
-{
- jamEntry();
- tblockref = signal->theData[0];
- hostptr.i = signal->theData[1];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- hostptr.p->hostStatus = HS_ALIVE;
- c_alive_nodes.set(hostptr.i);
-
- signal->theData[0] = hostptr.i;
- signal->theData[1] = cownref;
-
- if (ERROR_INSERTED(8039))
- {
- CLEAR_ERROR_INSERT_VALUE;
- Uint32 save = signal->theData[0];
- signal->theData[0] = 9999;
- sendSignal(numberToRef(CMVMI, hostptr.i),
- GSN_NDB_TAMPER, signal, 1, JBB);
- signal->theData[0] = save;
- sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
- return;
- }
-
- sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
-}
-
-void Dbtc::execREAD_NODESREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}
-
-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];
- tabptr.p->m_flags = 0;
- tabptr.p->set_storedTable((bool)signal->theData[2]);
- BlockReference retRef = signal->theData[3];
- tabptr.p->tableType = (Uint8)signal->theData[4];
- BlockReference retPtr = signal->theData[5];
- Uint32 noOfKeyAttr = signal->theData[6];
- tabptr.p->singleUserMode = (Uint8)signal->theData[7];
- ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
-
- const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
- ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
-
- ndbrequire(tabptr.p->get_enabled() == false);
- tabptr.p->set_enabled(true);
- tabptr.p->set_dropping(false);
- tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
- tabptr.p->hasCharAttr = desc->hasCharAttr;
- tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
- tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
- signal->theData[0] = tabptr.i;
- signal->theData[1] = retPtr;
- sendSignal(retRef, GSN_TC_SCHVERCONF, signal, 2, JBB);
-}//Dbtc::execTC_SCHVERREQ()
-
-void
-Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
-{
- jamEntry();
-
- PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
-
- TableRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
-
- if(!tabPtr.p->get_enabled()){
- jam();
- PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->tableId = tabPtr.i;
- ref->errorCode = PrepDropTabRef::NoSuchTable;
- sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
- PrepDropTabRef::SignalLength, JBB);
- return;
- }
-
- if(tabPtr.p->get_dropping()){
- jam();
- PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->tableId = tabPtr.i;
- ref->errorCode = PrepDropTabRef::DropInProgress;
- sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
- PrepDropTabRef::SignalLength, JBB);
- return;
- }
-
- tabPtr.p->set_dropping(true);
- tabPtr.p->dropTable.senderRef = senderRef;
- tabPtr.p->dropTable.senderData = senderData;
-
- {
- WaitDropTabReq * req = (WaitDropTabReq*)signal->getDataPtrSend();
- req->tableId = tabPtr.i;
- req->senderRef = reference();
-
- HostRecordPtr hostPtr;
- tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor();
- for (hostPtr.i = 1; hostPtr.i < MAX_NDB_NODES; hostPtr.i++) {
- jam();
- ptrAss(hostPtr, hostRecord);
- if (hostPtr.p->hostStatus == HS_ALIVE) {
- jam();
- tabPtr.p->dropTable.waitDropTabCount.setWaitingFor(hostPtr.i);
- sendSignal(calcLqhBlockRef(hostPtr.i), GSN_WAIT_DROP_TAB_REQ,
- signal, WaitDropTabReq::SignalLength, JBB);
- }//for
- }//if
-
- ndbrequire(tabPtr.p->dropTable.waitDropTabCount.done() != true);
- }
-}
-
-void
-Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal)
-{
- jamEntry();
- WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
-
- TableRecordPtr tabPtr;
- tabPtr.i = conf->tableId;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
-
- ndbrequire(tabPtr.p->get_dropping() == true);
- Uint32 nodeId = refToNode(conf->senderRef);
- tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
-
- if(!tabPtr.p->dropTable.waitDropTabCount.done()){
- jam();
- return;
- }
-
- {
- PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
- conf->tableId = tabPtr.i;
- conf->senderRef = reference();
- conf->senderData = tabPtr.p->dropTable.senderData;
- sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal,
- PrepDropTabConf::SignalLength, JBB);
- tabPtr.p->dropTable.senderRef = 0;
- }
-}
-
-void
-Dbtc::execWAIT_DROP_TAB_REF(Signal* signal)
-{
- jamEntry();
- WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr();
-
- TableRecordPtr tabPtr;
- tabPtr.i = ref->tableId;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
-
- ndbrequire(tabPtr.p->get_dropping() == true);
- Uint32 nodeId = refToNode(ref->senderRef);
- tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
-
- ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable ||
- ref->errorCode == WaitDropTabRef::NF_FakeErrorREF);
-
- if(!tabPtr.p->dropTable.waitDropTabCount.done()){
- jam();
- return;
- }
-
- {
- PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
- conf->tableId = tabPtr.i;
- conf->senderRef = reference();
- conf->senderData = tabPtr.p->dropTable.senderData;
- sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal,
- PrepDropTabConf::SignalLength, JBB);
- tabPtr.p->dropTable.senderRef = 0;
- }
-}
-
-void
-Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId)
-{
-
- TableRecordPtr tabPtr;
- tabPtr.i = tableId;
-
- WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
- conf->tableId = tableId;
-
- const Uint32 RT_BREAK = 16;
- for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabrecFilesize; i++, tabPtr.i++){
- jam();
- ptrAss(tabPtr, tableRecord);
- if(tabPtr.p->get_enabled() && tabPtr.p->get_dropping()){
- if(tabPtr.p->dropTable.waitDropTabCount.isWaitingFor(nodeId)){
- jam();
- conf->senderRef = calcLqhBlockRef(nodeId);
- execWAIT_DROP_TAB_CONF(signal);
- tabPtr.i++;
- break;
- }
- }
- }
-
- if(tabPtr.i == ctabrecFilesize){
- /**
- * Finished
- */
- jam();
- checkNodeFailComplete(signal, nodeId, HostRecord::NF_CHECK_DROP_TAB);
- return;
- }
-
- signal->theData[0] = TcContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH;
- signal->theData[1] = nodeId;
- signal->theData[2] = tabPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-}
-
-void
-Dbtc::execDROP_TAB_REQ(Signal* signal)
-{
- jamEntry();
-
- DropTabReq* req = (DropTabReq*)signal->getDataPtr();
-
- TableRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
-
- if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
- jam();
- DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->tableId = tabPtr.i;
- ref->errorCode = DropTabRef::NoSuchTable;
- sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
- DropTabRef::SignalLength, JBB);
- return;
- }
-
- if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
- jam();
- DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->tableId = tabPtr.i;
- ref->errorCode = DropTabRef::DropWoPrep;
- sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
- DropTabRef::SignalLength, JBB);
- return;
- }
-
- tabPtr.p->set_enabled(false);
- tabPtr.p->set_dropping(false);
-
- DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
- conf->tableId = tabPtr.i;
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
- PrepDropTabConf::SignalLength, JBB);
-}
-
-void Dbtc::execALTER_TAB_REQ(Signal * signal)
-{
- AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
- const Uint32 changeMask = req->changeMask;
- const Uint32 tableId = req->tableId;
- const Uint32 tableVersion = req->tableVersion;
- const Uint32 gci = req->gci;
- AlterTabReq::RequestType requestType =
- (AlterTabReq::RequestType) req->requestType;
-
- TableRecordPtr tabPtr;
- tabPtr.i = req->tableId;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
- tabPtr.p->currentSchemaVersion = tableVersion;
-
- // Request handled successfully
- AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->changeMask = changeMask;
- conf->tableId = tableId;
- conf->tableVersion = tableVersion;
- conf->gci = gci;
- conf->requestType = requestType;
- sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
- AlterTabConf::SignalLength, JBB);
-}
-
-/* ***************************************************************************/
-/* START / RESTART */
-/* ***************************************************************************/
-void Dbtc::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- initData();
-
- UintR apiConnect;
- UintR tcConnect;
- UintR tables;
- UintR localScan;
- UintR tcScan;
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
-
- ccacheFilesize = (apiConnect/3) + 1;
- capiConnectFilesize = apiConnect;
- ctcConnectFilesize = tcConnect;
- ctabrecFilesize = tables;
- cscanrecFileSize = tcScan;
- cscanFragrecFileSize = localScan;
-
- initRecords();
- initialiseRecordsLab(signal, 0, ref, senderData);
-
- Uint32 val = 3000;
- ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
- set_timeout_value(val);
-
- val = 1500;
- ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
- cDbHbInterval = (val < 10) ? 10 : val;
-
- val = 3000;
- ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
- set_appl_timeout_value(val);
-
- val = 1;
- //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
- set_no_parallel_takeover(val);
-
- ctimeOutCheckDelay = 50; // 500ms
-}//Dbtc::execSIZEALT_REP()
-
-void Dbtc::execSTTOR(Signal* signal)
-{
- Uint16 tphase;
-
- jamEntry();
- /* START CASE */
- tphase = signal->theData[1];
- csignalKey = signal->theData[6];
- switch (tphase) {
- case ZSPH1:
- jam();
- startphase1x010Lab(signal);
- return;
- default:
- jam();
- sttorryLab(signal); /* START PHASE 255 */
- return;
- }//switch
-}//Dbtc::execSTTOR()
-
-void Dbtc::sttorryLab(Signal* signal)
-{
- signal->theData[0] = csignalKey;
- signal->theData[1] = 3; /* BLOCK CATEGORY */
- signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
- signal->theData[3] = ZSPH1;
- signal->theData[4] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
-}//Dbtc::sttorryLab()
-
-/* ***************************************************************************/
-/* INTERNAL START / RESTART */
-/*****************************************************************************/
-void Dbtc::execNDB_STTOR(Signal* signal)
-{
- Uint16 tndbstartphase;
- Uint16 tstarttype;
-
- jamEntry();
- tusersblkref = signal->theData[0];
- tnodeid = signal->theData[1];
- tndbstartphase = signal->theData[2]; /* START PHASE */
- tstarttype = signal->theData[3]; /* START TYPE */
- switch (tndbstartphase) {
- case ZINTSPH1:
- jam();
- intstartphase1x010Lab(signal);
- return;
- case ZINTSPH2:
- jam();
- intstartphase2x010Lab(signal);
- return;
- case ZINTSPH3:
- jam();
- intstartphase3x010Lab(signal); /* SEIZE CONNECT RECORD IN EACH LQH*/
-// Start transaction event reporting.
- c_counters.c_trans_status = TransCounters::Timer;
- c_counters.reset();
- signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 1);
- return;
- case ZINTSPH6:
- jam();
- csystemStart = SSS_TRUE;
- break;
- default:
- jam();
- break;
- }//switch
- ndbsttorry010Lab(signal);
- return;
-}//Dbtc::execNDB_STTOR()
-
-void Dbtc::ndbsttorry010Lab(Signal* signal)
-{
- signal->theData[0] = cownref;
- sendSignal(cndbcntrblockref, GSN_NDB_STTORRY, signal, 1, JBB);
-}//Dbtc::ndbsttorry010Lab()
-
-void
-Dbtc::set_timeout_value(Uint32 timeOut)
-{
- timeOut = timeOut / 10;
- if (timeOut < 2) {
- jam();
- timeOut = 100;
- }//if
- ctimeOutValue = timeOut;
-}
-
-void
-Dbtc::set_appl_timeout_value(Uint32 timeOut)
-{
- if (timeOut)
- {
- timeOut /= 10;
- if (timeOut < ctimeOutValue) {
- jam();
- c_appl_timeout_value = ctimeOutValue;
- }//if
- }
- c_appl_timeout_value = timeOut;
-}
-
-void
-Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
-{
- if (noParallelTakeOver == 0) {
- jam();
- noParallelTakeOver = 1;
- } else if (noParallelTakeOver > MAX_NDB_NODES) {
- jam();
- noParallelTakeOver = MAX_NDB_NODES;
- }//if
- cnoParallelTakeOver = noParallelTakeOver;
-}
-
-/* ***************************************************************************/
-/* S T A R T P H A S E 1 X */
-/* INITIALISE BLOCKREF AND BLOCKNUMBERS */
-/* ***************************************************************************/
-void Dbtc::startphase1x010Lab(Signal* signal)
-{
- csystemStart = SSS_FALSE;
- ctimeOutCheckCounter = 0;
- ctimeOutCheckFragCounter = 0;
- ctimeOutMissedHeartbeats = 0;
- ctimeOutCheckHeartbeat = 0;
- ctimeOutCheckLastHeartbeat = 0;
- ctimeOutCheckActive = TOCS_FALSE;
- ctimeOutCheckFragActive = TOCS_FALSE;
- sttorryLab(signal);
-}//Dbtc::startphase1x010Lab()
-
-/*****************************************************************************/
-/* I N T S T A R T P H A S E 1 X */
-/* INITIALISE ALL RECORDS. */
-/*****************************************************************************/
-void Dbtc::intstartphase1x010Lab(Signal* signal)
-{
- cownNodeid = tnodeid;
- cownref = calcTcBlockRef(cownNodeid);
- clqhblockref = calcLqhBlockRef(cownNodeid);
- cdihblockref = calcDihBlockRef(cownNodeid);
- cdictblockref = calcDictBlockRef(cownNodeid);
- cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
- cerrorBlockref = calcNdbCntrBlockRef(cownNodeid);
- coperationsize = 0;
- cfailure_nr = 0;
- ndbsttorry010Lab(signal);
-}//Dbtc::intstartphase1x010Lab()
-
-/*****************************************************************************/
-/* I N T S T A R T P H A S E 2 X */
-/* SET-UP LOCAL CONNECTIONS. */
-/*****************************************************************************/
-void Dbtc::intstartphase2x010Lab(Signal* signal)
-{
- tcConnectptr.i = cfirstfreeTcConnect;
- intstartphase2x020Lab(signal);
-}//Dbtc::intstartphase2x010Lab()
-
-void Dbtc::intstartphase2x020Lab(Signal* signal)
-{
- if (tcConnectptr.i == RNIL) {
- jam();
- ndbsttorry010Lab(signal);
- return;
- }//if
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- tcConnectptr.p->tcConnectstate = OS_CONNECTING_DICT;
-/* ****************** */
-/* DISEIZEREQ < */
-/* ****************** */
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- sendSignal(cdihblockref, GSN_DISEIZEREQ, signal, 2, JBB);
-}//Dbtc::intstartphase2x020Lab()
-
-void Dbtc::execDISEIZECONF(Signal* signal)
-{
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- tcConnectptr.p->dihConnectptr = signal->theData[1];
- tcConnectptr.i = tcConnectptr.p->nextTcConnect;
- intstartphase2x020Lab(signal);
-}//Dbtc::execDISEIZECONF()
-
-/*****************************************************************************/
-/* I N T S T A R T P H A S E 3 X */
-/* PREPARE DISTRIBUTED CONNECTIONS */
-/*****************************************************************************/
-void Dbtc::intstartphase3x010Lab(Signal* signal)
-{
- signal->theData[0] = cownref;
- sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
-}//Dbtc::intstartphase3x010Lab()
-
-void Dbtc::execREAD_NODESCONF(Signal* signal)
-{
- UintR guard0;
-
- jamEntry();
-
- ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
-
- csystemnodes = readNodes->noOfNodes;
- cmasterNodeId = readNodes->masterNodeId;
-
- con_lineNodes = 0;
- arrGuard(csystemnodes, MAX_NDB_NODES);
- guard0 = csystemnodes - 1;
- arrGuard(guard0, MAX_NDB_NODES); // Check not zero nodes
-
- for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
- jam();
- if (NodeBitmask::get(readNodes->allNodes, i)) {
- hostptr.i = i;
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
-
- if (NodeBitmask::get(readNodes->inactiveNodes, i)) {
- jam();
- hostptr.p->hostStatus = HS_DEAD;
- } else {
- jam();
- con_lineNodes++;
- hostptr.p->hostStatus = HS_ALIVE;
- c_alive_nodes.set(i);
- }//if
- }//if
- }//for
- ndbsttorry010Lab(signal);
-}//Dbtc::execREAD_NODESCONF()
-
-/*****************************************************************************/
-/* A P I _ F A I L R E Q */
-// An API node has failed for some reason. We need to disconnect all API
-// connections to the API node. This also includes
-/*****************************************************************************/
-void Dbtc::execAPI_FAILREQ(Signal* signal)
-{
- /***************************************************************************
- * Set the block reference to return API_FAILCONF to. Set the number of api
- * connects currently closing to one to indicate that we are still in the
- * process of going through the api connect records. Thus checking for zero
- * can only be true after all api connect records have been checked.
- **************************************************************************/
- jamEntry();
- capiFailRef = signal->theData[1];
- arrGuard(signal->theData[0], MAX_NODES);
- capiConnectClosing[signal->theData[0]] = 1;
- handleFailedApiNode(signal, signal->theData[0], (UintR)0);
-}
-
-void
-Dbtc::handleFailedApiNode(Signal* signal,
- UintR TapiFailedNode,
- UintR TapiConnectPtr)
-{
- UintR TloopCount = 0;
- arrGuard(TapiFailedNode, MAX_NODES);
- apiConnectptr.i = TapiConnectPtr;
- do {
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
- if (TapiNode == TapiFailedNode) {
-#ifdef VM_TRACE
- if (apiConnectptr.p->apiFailState != ZFALSE) {
- ndbout << "Error in previous API fail handling discovered" << endl
- << " apiConnectptr.i = " << apiConnectptr.i << endl
- << " apiConnectstate = " << apiConnectptr.p->apiConnectstate
- << endl
- << " ndbapiBlockref = " << hex
- << apiConnectptr.p->ndbapiBlockref << endl
- << " apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
- << endl;
- if (apiConnectptr.p->lastTcConnect != RNIL){
- jam();
- tcConnectptr.i = apiConnectptr.p->lastTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- ndbout << " tcConnectptr.i = " << tcConnectptr.i << endl
- << " tcConnectstate = " << tcConnectptr.p->tcConnectstate
- << endl;
- }
- }//if
-#endif
-
- apiConnectptr.p->returnsignal = RS_NO_RETURN;
- /***********************************************************************/
- // The connected node is the failed node.
- /**********************************************************************/
- switch(apiConnectptr.p->apiConnectstate) {
- case CS_DISCONNECTED:
- /*********************************************************************/
- // These states do not need any special handling.
- // Simply continue with the next.
- /*********************************************************************/
- jam();
- break;
- case CS_ABORTING:
- /*********************************************************************/
- // This could actually mean that the API connection is already
- // ready to release if the abortState is IDLE.
- /*********************************************************************/
- if (apiConnectptr.p->abortState == AS_IDLE) {
- jam();
- releaseApiCon(signal, apiConnectptr.i);
- } else {
- jam();
- capiConnectClosing[TapiFailedNode]++;
- apiConnectptr.p->apiFailState = ZTRUE;
- }//if
- break;
- case CS_WAIT_ABORT_CONF:
- case CS_WAIT_COMMIT_CONF:
- case CS_START_COMMITTING:
- case CS_PREPARE_TO_COMMIT:
- case CS_COMMITTING:
- case CS_COMMIT_SENT:
- /*********************************************************************/
- // These states indicate that an abort process or commit process is
- // already ongoing. We will set a state in the api record indicating
- // that the API node has failed.
- // Also we will increase the number of outstanding api records to
- // wait for before we can respond with API_FAILCONF.
- /*********************************************************************/
- jam();
- capiConnectClosing[TapiFailedNode]++;
- apiConnectptr.p->apiFailState = ZTRUE;
- break;
- case CS_START_SCAN:
- /*********************************************************************/
- // The api record was performing a scan operation. We need to check
- // on the scan state. Since completing a scan process might involve
- // sending several signals we will increase the loop count by 64.
- /*********************************************************************/
- jam();
-
- apiConnectptr.p->apiFailState = ZTRUE;
- capiConnectClosing[TapiFailedNode]++;
-
- ScanRecordPtr scanPtr;
- scanPtr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
- close_scan_req(signal, scanPtr, true);
-
- TloopCount += 64;
- break;
- case CS_CONNECTED:
- case CS_REC_COMMITTING:
- case CS_RECEIVING:
- case CS_STARTED:
- /*********************************************************************/
- // The api record was in the process of performing a transaction but
- // had not yet sent all information.
- // We need to initiate an ABORT since the API will not provide any
- // more information.
- // Since the abort can send many signals we will insert a real-time
- // break after checking this record.
- /*********************************************************************/
- jam();
- apiConnectptr.p->apiFailState = ZTRUE;
- capiConnectClosing[TapiFailedNode]++;
- abort010Lab(signal);
- TloopCount = 256;
- break;
- case CS_PREPARED:
- jam();
- case CS_REC_PREPARING:
- jam();
- case CS_START_PREPARING:
- jam();
- /*********************************************************************/
- // Not implemented yet.
- /*********************************************************************/
- systemErrorLab(signal, __LINE__);
- break;
- case CS_RESTART:
- jam();
- case CS_COMPLETING:
- jam();
- case CS_COMPLETE_SENT:
- jam();
- case CS_WAIT_COMPLETE_CONF:
- jam();
- case CS_FAIL_ABORTING:
- jam();
- case CS_FAIL_ABORTED:
- jam();
- case CS_FAIL_PREPARED:
- jam();
- case CS_FAIL_COMMITTING:
- jam();
- case CS_FAIL_COMMITTED:
- /*********************************************************************/
- // These states are only valid on copy and fail API connections.
- /*********************************************************************/
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- break;
- }//switch
- } else {
- jam();
- }//if
- apiConnectptr.i++;
- if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
- jam();
- /**
- * Finished with scanning connection record
- *
- * Now scan markers
- */
- removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
- return;
- }//if
- } while (TloopCount++ < 256);
- signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
- signal->theData[1] = TapiFailedNode;
- signal->theData[2] = apiConnectptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
-}//Dbtc::handleFailedApiNode()
-
-void
-Dbtc::removeMarkerForFailedAPI(Signal* signal,
- Uint32 nodeId,
- Uint32 startBucket)
-{
- TcFailRecordPtr node_fail_ptr;
- node_fail_ptr.i = 0;
- ptrAss(node_fail_ptr, tcFailRecord);
- if(node_fail_ptr.p->failStatus != FS_IDLE) {
- jam();
- DEBUG("Restarting removeMarkerForFailedAPI");
- /**
- * TC take-over in progress
- * needs to restart as this
- * creates new markers
- */
- signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
- signal->theData[1] = nodeId;
- signal->theData[2] = 0;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
- return;
- }
-
- CommitAckMarkerIterator iter;
- m_commitAckMarkerHash.next(startBucket, iter);
-
- const Uint32 RT_BREAK = 256;
- for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
- jam();
-
- if(iter.curr.i == RNIL){
- jam();
- /**
- * Done with iteration
- */
- capiConnectClosing[nodeId]--;
- if (capiConnectClosing[nodeId] == 0) {
- jam();
- /********************************************************************/
- // No outstanding ABORT or COMMIT's of this failed API node.
- // We can respond with API_FAILCONF
- /********************************************************************/
- signal->theData[0] = nodeId;
- signal->theData[1] = cownref;
- sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
- }
- return;
- }
-
- if(iter.curr.p->apiNodeId == nodeId){
- jam();
-
- /**
- * Check so that the record is not still in use
- *
- */
- ApiConnectRecordPtr apiConnectPtr;
- apiConnectPtr.i = iter.curr.p->apiConnectPtr;
- ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord);
- if(apiConnectPtr.p->commitAckMarker == iter.curr.i){
- jam();
- /**
- * The record is still active
- *
- * Don't remove it, but continueb instead
- */
- break;
- }
- sendRemoveMarkers(signal, iter.curr.p);
- m_commitAckMarkerHash.release(iter.curr);
-
- break;
- }
- m_commitAckMarkerHash.next(iter);
- }
-
- signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
- signal->theData[1] = nodeId;
- signal->theData[2] = iter.bucket;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
-}
-
-void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
-{
- ApiConnectRecordPtr TlocalApiConnectptr;
- UintR TfailedApiNode;
-
- TlocalApiConnectptr.i = TapiConnectptr;
- ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
- TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
- arrGuard(TfailedApiNode, MAX_NODES);
- capiConnectClosing[TfailedApiNode]--;
- releaseApiCon(signal, TapiConnectptr);
- TlocalApiConnectptr.p->apiFailState = ZFALSE;
- if (capiConnectClosing[TfailedApiNode] == 0) {
- jam();
- signal->theData[0] = TfailedApiNode;
- signal->theData[1] = cownref;
- sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
- }//if
-}//Dbtc::handleApiFailState()
-
-/****************************************************************************
- * T C S E I Z E R E Q
- * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
- * TRANSACTION
- * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
- * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
- ****************************************************************************/
-void Dbtc::execTCSEIZEREQ(Signal* signal)
-{
- UintR tapiPointer;
- BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
-
- jamEntry();
- tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
- tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
-
- const NodeState::StartLevel sl =
- (NodeState::StartLevel)getNodeState().startLevel;
-
- const NodeId senderNodeId = refToNode(tapiBlockref);
- const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
-
- {
- {
- if (!(sl == NodeState::SL_STARTED ||
- (sl == NodeState::SL_STARTING && local == true))) {
- jam();
-
- Uint32 errCode = 0;
- if(!local)
- {
- switch(sl){
- case NodeState::SL_STARTING:
- errCode = ZSYSTEM_NOT_STARTED_ERROR;
- break;
- case NodeState::SL_STOPPING_1:
- case NodeState::SL_STOPPING_2:
- if (getNodeState().getSingleUserMode())
- break;
- case NodeState::SL_STOPPING_3:
- case NodeState::SL_STOPPING_4:
- if(getNodeState().stopping.systemShutdown)
- errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
- else
- errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
- break;
- case NodeState::SL_SINGLEUSER:
- break;
- default:
- errCode = ZWRONG_STATE;
- break;
- }
- if (errCode)
- {
- signal->theData[0] = tapiPointer;
- signal->theData[1] = errCode;
- sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
- return;
- }
- }//if (!(sl == SL_SINGLEUSER))
- } //if
- }
- }
-
- seizeApiConnect(signal);
- if (terrorCode == ZOK) {
- jam();
- apiConnectptr.p->ndbapiConnect = tapiPointer;
- apiConnectptr.p->ndbapiBlockref = tapiBlockref;
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = apiConnectptr.i;
- sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 2, JBB);
- return;
- }
-
- signal->theData[0] = tapiPointer;
- signal->theData[1] = terrorCode;
- sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
-}//Dbtc::execTCSEIZEREQ()
-
-/****************************************************************************/
-/* T C R E L E A S E Q */
-/* REQUEST TO RELEASE A CONNECT RECORD */
-/****************************************************************************/
-void Dbtc::execTCRELEASEREQ(Signal* signal)
-{
- UintR tapiPointer;
- BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
-
- jamEntry();
- tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
- tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
- tuserpointer = signal->theData[2];
- if (tapiPointer >= capiConnectFilesize) {
- jam();
- signal->theData[0] = tuserpointer;
- signal->theData[1] = ZINVALID_CONNECTION;
- signal->theData[2] = __LINE__;
- sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
- return;
- } else {
- jam();
- apiConnectptr.i = tapiPointer;
- }//if
- ptrAss(apiConnectptr, apiConnectRecord);
- if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) {
- jam();
- signal->theData[0] = tuserpointer;
- sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
- } else {
- if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
- if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
- (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
- apiConnectptr.p->abortState == AS_IDLE) ||
- (apiConnectptr.p->apiConnectstate == CS_STARTED &&
- apiConnectptr.p->firstTcConnect == RNIL))
- {
- jam(); /* JUST REPLY OK */
- apiConnectptr.p->m_transaction_nodes.clear();
- releaseApiCon(signal, apiConnectptr.i);
- signal->theData[0] = tuserpointer;
- sendSignal(tapiBlockref,
- GSN_TCRELEASECONF, signal, 1, JBB);
- } else {
- jam();
- signal->theData[0] = tuserpointer;
- signal->theData[1] = ZINVALID_CONNECTION;
- signal->theData[2] = __LINE__;
- signal->theData[3] = apiConnectptr.p->apiConnectstate;
- sendSignal(tapiBlockref,
- GSN_TCRELEASEREF, signal, 4, JBB);
- }
- } else {
- jam();
- signal->theData[0] = tuserpointer;
- signal->theData[1] = ZINVALID_CONNECTION;
- signal->theData[2] = __LINE__;
- signal->theData[3] = tapiBlockref;
- signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
- sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
- }//if
- }//if
-}//Dbtc::execTCRELEASEREQ()
-
-/****************************************************************************/
-// Error Handling for TCKEYREQ messages
-/****************************************************************************/
-void Dbtc::signalErrorRefuseLab(Signal* signal)
-{
- ptrGuard(apiConnectptr);
- if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
- jam();
- apiConnectptr.p->abortState = AS_IDLE;
- apiConnectptr.p->apiConnectstate = CS_ABORTING;
- }//if
- sendSignalErrorRefuseLab(signal);
-}//Dbtc::signalErrorRefuseLab()
-
-void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
-{
- ndbassert(false);
- ptrGuard(apiConnectptr);
- if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
- jam();
- ndbrequire(false);
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = signal->theData[ttransid_ptr];
- signal->theData[2] = signal->theData[ttransid_ptr + 1];
- signal->theData[3] = ZSIGNAL_ERROR;
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
- signal, 4, JBB);
- }
-}//Dbtc::sendSignalErrorRefuseLab()
-
-void Dbtc::abortBeginErrorLab(Signal* signal)
-{
- apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
- apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
- abortErrorLab(signal);
-}//Dbtc::abortBeginErrorLab()
-
-void Dbtc::printState(Signal* signal, int place)
-{
-#ifdef VM_TRACE // Change to if 0 to disable these printouts
- ndbout << "-- Dbtc::printState -- " << endl;
- ndbout << "Received from place = " << place
- << " apiConnectptr.i = " << apiConnectptr.i
- << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
- ndbout << "ctcTimer = " << ctcTimer
- << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
- << " Transid = " << apiConnectptr.p->transid[0]
- << " " << apiConnectptr.p->transid[1] << endl;
- ndbout << " apiTimer = " << getApiConTimer(apiConnectptr.i)
- << " counter = " << apiConnectptr.p->counter
- << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
- << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl;
- ndbout << "abortState = " << apiConnectptr.p->abortState
- << " apiScanRec = " << apiConnectptr.p->apiScanRec
- << " returncode = " << apiConnectptr.p->returncode << endl;
- ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
- << " returnsignal = " << apiConnectptr.p->returnsignal
- << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
- if (apiConnectptr.p->cachePtr != RNIL) {
- jam();
- CacheRecord *localCacheRecord = cacheRecord;
- UintR TcacheFilesize = ccacheFilesize;
- UintR TcachePtr = apiConnectptr.p->cachePtr;
- if (TcachePtr < TcacheFilesize) {
- jam();
- CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
- ndbout << "currReclenAi = " << regCachePtr->currReclenAi
- << " attrlength = " << regCachePtr->attrlength
- << " tableref = " << regCachePtr->tableref
- << " keylen = " << regCachePtr->keylen << endl;
- } else {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- }//if
-#endif
- return;
-}//Dbtc::printState()
-
-void
-Dbtc::TCKEY_abort(Signal* signal, int place)
-{
- switch (place) {
- case 0:
- jam();
- terrorCode = ZSTATE_ERROR;
- apiConnectptr.p->firstTcConnect = RNIL;
- printState(signal, 4);
- abortBeginErrorLab(signal);
- return;
- case 1:
- jam();
- printState(signal, 3);
- sendSignalErrorRefuseLab(signal);
- return;
- case 2:{
- printState(signal, 6);
- const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
- const Uint32 t1 = tcKeyReq->transId1;
- const Uint32 t2 = tcKeyReq->transId2;
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = t1;
- signal->theData[2] = t2;
- signal->theData[3] = ZABORT_ERROR;
- ndbrequire(false);
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
- signal, 4, JBB);
- return;
- }
- case 3:
- jam();
- printState(signal, 7);
- noFreeConnectionErrorLab(signal);
- return;
- case 4:
- jam();
- terrorCode = ZERO_KEYLEN_ERROR;
- releaseAtErrorLab(signal);
- return;
- case 5:
- jam();
- terrorCode = ZNO_AI_WITH_UPDATE;
- releaseAtErrorLab(signal);
- return;
- case 6:
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
-
- case 7:
- jam();
- tabStateErrorLab(signal);
- return;
-
- case 8:
- jam();
- wrongSchemaVersionErrorLab(signal);
- return;
-
- case 9:
- jam();
- terrorCode = ZSTATE_ERROR;
- releaseAtErrorLab(signal);
- return;
-
- case 10:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 11:
- jam();
- terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
- releaseAtErrorLab(signal);
- return;
-
- case 12:
- jam();
- terrorCode = ZSIMPLE_READ_WITHOUT_AI;
- releaseAtErrorLab(signal);
- return;
-
- case 13:
- jam();
- switch (tcConnectptr.p->tcConnectstate) {
- case OS_WAIT_KEYINFO:
- jam();
- printState(signal, 8);
- terrorCode = ZSTATE_ERROR;
- abortErrorLab(signal);
- return;
- default:
- jam();
- /********************************************************************/
- /* MISMATCH BETWEEN STATE ON API CONNECTION AND THIS */
- /* PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB */
- /* INTERNAL ERROR. */
- /********************************************************************/
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
- return;
-
- case 15:
- jam();
- terrorCode = ZSCAN_NODE_ERROR;
- releaseAtErrorLab(signal);
- return;
-
- case 16:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 17:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 18:
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
-
- case 19:
- jam();
- return;
-
- case 20:
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
-
- case 21:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 22:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 23:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 24:
- jam();
- seizeAttrbuferrorLab(signal);
- return;
-
- case 25:
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
-
- case 26:
- jam();
- return;
-
- case 27:
- systemErrorLab(signal, __LINE__);
- jam();
- return;
-
- case 28:
- jam();
- // NOT USED
- return;
-
- case 29:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 30:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 31:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 32:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 33:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 34:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 35:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 36:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 37:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 38:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 39:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 40:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 41:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 42:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 43:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 44:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 45:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 46:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 47:
- jam();
- terrorCode = apiConnectptr.p->returncode;
- releaseAtErrorLab(signal);
- return;
-
- case 48:
- jam();
- terrorCode = ZCOMMIT_TYPE_ERROR;
- releaseAtErrorLab(signal);
- return;
-
- case 49:
- jam();
- abortErrorLab(signal);
- return;
-
- case 50:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
-
- case 51:
- jam();
- abortErrorLab(signal);
- return;
-
- case 52:
- jam();
- abortErrorLab(signal);
- return;
-
- case 53:
- jam();
- abortErrorLab(signal);
- return;
-
- case 54:
- jam();
- abortErrorLab(signal);
- return;
-
- case 55:
- jam();
- printState(signal, 5);
- sendSignalErrorRefuseLab(signal);
- return;
-
- case 56:{
- jam();
- terrorCode = ZNO_FREE_TC_MARKER;
- abortErrorLab(signal);
- return;
- }
- case 57:{
- jam();
- /**
- * Initialize object before starting error handling
- */
- initApiConnectRec(signal, apiConnectptr.p, true);
-start_failure:
- switch(getNodeState().startLevel){
- case NodeState::SL_STOPPING_2:
- if (getNodeState().getSingleUserMode())
- {
- terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
- break;
- }
- case NodeState::SL_STOPPING_3:
- case NodeState::SL_STOPPING_4:
- if(getNodeState().stopping.systemShutdown)
- terrorCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
- else
- terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
- break;
- case NodeState::SL_SINGLEUSER:
- terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
- break;
- case NodeState::SL_STOPPING_1:
- if (getNodeState().getSingleUserMode())
- {
- terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
- break;
- }
- default:
- terrorCode = ZWRONG_STATE;
- break;
- }
- abortErrorLab(signal);
- return;
- }
-
- case 58:{
- jam();
- releaseAtErrorLab(signal);
- return;
- }
-
- case 59:{
- jam();
- terrorCode = ZABORTINPROGRESS;
- abortErrorLab(signal);
- return;
- }
-
- case 60:
- {
- jam();
- initApiConnectRec(signal, apiConnectptr.p, true);
- apiConnectptr.p->m_exec_flag = 1;
- goto start_failure;
- }
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
-}
-
-static
-inline
-bool
-compare_transid(Uint32* val0, Uint32* val1)
-{
- Uint32 tmp0 = val0[0] ^ val1[0];
- Uint32 tmp1 = val0[1] ^ val1[1];
- return (tmp0 | tmp1) == 0;
-}
-
-void Dbtc::execKEYINFO(Signal* signal)
-{
- jamEntry();
- apiConnectptr.i = signal->theData[0];
- tmaxData = 20;
- if (apiConnectptr.i >= capiConnectFilesize) {
- TCKEY_abort(signal, 18);
- return;
- }//if
- ptrAss(apiConnectptr, apiConnectRecord);
- ttransid_ptr = 1;
- if (compare_transid(apiConnectptr.p->transid, signal->theData+1) == false)
- {
- TCKEY_abort(signal, 19);
- return;
- }//if
- switch (apiConnectptr.p->apiConnectstate) {
- case CS_RECEIVING:
- case CS_REC_COMMITTING:
- case CS_START_SCAN:
- jam();
- /*empty*/;
- break;
- /* OK */
- case CS_ABORTING:
- jam();
- return; /* IGNORE */
- case CS_CONNECTED:
- jam();
- /****************************************************************>*/
- /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
- /* SET STATE TO ABORTING. */
- /****************************************************************>*/
- printState(signal, 11);
- signalErrorRefuseLab(signal);
- return;
- case CS_STARTED:
- jam();
- /****************************************************************>*/
- /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
- /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
- /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
- /****************************************************************>*/
- terrorCode = ZSIGNAL_ERROR;
- printState(signal, 2);
- abortErrorLab(signal);
- return;
- default:
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }//switch
-
- CacheRecord *localCacheRecord = cacheRecord;
- UintR TcacheFilesize = ccacheFilesize;
- UintR TcachePtr = apiConnectptr.p->cachePtr;
- UintR TtcTimer = ctcTimer;
- CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
- if (TcachePtr >= TcacheFilesize) {
- TCKEY_abort(signal, 42);
- return;
- }//if
- setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
- cachePtr.i = TcachePtr;
- cachePtr.p = regCachePtr;
-
- tcConnectptr.i = apiConnectptr.p->lastTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- switch (tcConnectptr.p->tcConnectstate) {
- case OS_WAIT_KEYINFO:
- jam();
- tckeyreq020Lab(signal);
- return;
- case OS_WAIT_SCAN:
- break;
- default:
- jam();
- terrorCode = ZSTATE_ERROR;
- abortErrorLab(signal);
- return;
- }//switch
-
- UintR TdataPos = 0;
- UintR TkeyLen = regCachePtr->keylen;
- UintR Tlen = regCachePtr->save1;
-
- do {
- if (cfirstfreeDatabuf == RNIL) {
- jam();
- seizeDatabuferrorLab(signal);
- return;
- }//if
- linkKeybuf(signal);
- arrGuard(TdataPos, 19);
- databufptr.p->data[0] = signal->theData[TdataPos + 3];
- databufptr.p->data[1] = signal->theData[TdataPos + 4];
- databufptr.p->data[2] = signal->theData[TdataPos + 5];
- databufptr.p->data[3] = signal->theData[TdataPos + 6];
- Tlen = Tlen + 4;
- TdataPos = TdataPos + 4;
- if (Tlen < TkeyLen) {
- jam();
- if (TdataPos >= tmaxData) {
- jam();
- /*----------------------------------------------------*/
- /** EXIT AND WAIT FOR SIGNAL KEYINFO OR KEYINFO9 **/
- /** WHEN EITHER OF THE SIGNALS IS RECEIVED A JUMP **/
- /** TO LABEL "KEYINFO_LABEL" IS DONE. THEN THE **/
- /** PROGRAM RETURNS TO LABEL TCKEYREQ020 **/
- /*----------------------------------------------------*/
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- regCachePtr->save1 = Tlen;
- return;
- }//if
- } else {
- jam();
- return;
- }//if
- } while (1);
- return;
-}//Dbtc::execKEYINFO()
-
-/*---------------------------------------------------------------------------*/
-/* */
-/* MORE THAN FOUR WORDS OF KEY DATA. WE NEED TO PACK THIS IN KEYINFO SIGNALS.*/
-/* WE WILL ALWAYS PACK 4 WORDS AT A TIME. */
-/*---------------------------------------------------------------------------*/
-void Dbtc::packKeyData000Lab(Signal* signal,
- BlockReference TBRef,
- Uint32 totalLen)
-{
- CacheRecord * const regCachePtr = cachePtr.p;
-
- jam();
- Uint32 len = 0;
- databufptr.i = regCachePtr->firstKeybuf;
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- Uint32 * dst = signal->theData+3;
- ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
-
- do {
- jam();
- databufptr.i = databufptr.p->nextDatabuf;
- dst[len + 0] = databufptr.p->data[0];
- dst[len + 1] = databufptr.p->data[1];
- dst[len + 2] = databufptr.p->data[2];
- dst[len + 3] = databufptr.p->data[3];
- len += 4;
- if (totalLen <= 4) {
- jam();
- /*---------------------------------------------------------------------*/
- /* LAST PACK OF KEY DATA HAVE BEEN SENT */
- /*---------------------------------------------------------------------*/
- /* THERE WERE UNSENT INFORMATION, SEND IT. */
- /*---------------------------------------------------------------------*/
- sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
- return;
- } else if(len == KeyInfo::DataLength){
- jam();
- len = 0;
- sendSignal(TBRef, GSN_KEYINFO, signal, 3 + KeyInfo::DataLength, JBB);
- }
- totalLen -= 4;
- ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
- } while (1);
-}//Dbtc::packKeyData000Lab()
-
-void Dbtc::tckeyreq020Lab(Signal* signal)
-{
- CacheRecord * const regCachePtr = cachePtr.p;
- UintR TdataPos = 0;
- UintR TkeyLen = regCachePtr->keylen;
- UintR Tlen = regCachePtr->save1;
-
- do {
- if (cfirstfreeDatabuf == RNIL) {
- jam();
- seizeDatabuferrorLab(signal);
- return;
- }//if
- linkKeybuf(signal);
- arrGuard(TdataPos, 19);
- databufptr.p->data[0] = signal->theData[TdataPos + 3];
- databufptr.p->data[1] = signal->theData[TdataPos + 4];
- databufptr.p->data[2] = signal->theData[TdataPos + 5];
- databufptr.p->data[3] = signal->theData[TdataPos + 6];
- Tlen = Tlen + 4;
- TdataPos = TdataPos + 4;
- if (Tlen < TkeyLen) {
- jam();
- if (TdataPos >= tmaxData) {
- jam();
- /*----------------------------------------------------*/
- /** EXIT AND WAIT FOR SIGNAL KEYINFO OR KEYINFO9 **/
- /** WHEN EITHER OF THE SIGNALS IS RECEIVED A JUMP **/
- /** TO LABEL "KEYINFO_LABEL" IS DONE. THEN THE **/
- /** PROGRAM RETURNS TO LABEL TCKEYREQ020 **/
- /*----------------------------------------------------*/
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- regCachePtr->save1 = Tlen;
- tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
- return;
- }//if
- } else {
- jam();
- tckeyreq050Lab(signal);
- return;
- }//if
- } while (1);
- return;
-}//Dbtc::tckeyreq020Lab()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SAVE ATTRIBUTE INFORMATION IN OPERATION RECORD ------- */
-/* ------------------------------------------------------------------------- */
-void Dbtc::saveAttrbuf(Signal* signal)
-{
- CacheRecord * const regCachePtr = cachePtr.p;
- UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
- UintR TattrbufFilesize = cattrbufFilesize;
- UintR TTcfirstAttrbuf = regCachePtr->firstAttrbuf;
- UintR Tlen = signal->length() - 3;
- AttrbufRecord *localAttrbufRecord = attrbufRecord;
-
- AttrbufRecord * const regAttrPtr = &localAttrbufRecord[TfirstfreeAttrbuf];
- if (TfirstfreeAttrbuf >= TattrbufFilesize) {
- TCKEY_abort(signal, 21);
- return;
- }//if
- UintR Tnext = regAttrPtr->attrbuf[ZINBUF_NEXT];
- if (TTcfirstAttrbuf == RNIL) {
- jam();
- regCachePtr->firstAttrbuf = TfirstfreeAttrbuf;
- } else {
- AttrbufRecordPtr saAttrbufptr;
-
- saAttrbufptr.i = regCachePtr->lastAttrbuf;
- jam();
- if (saAttrbufptr.i >= TattrbufFilesize) {
- TCKEY_abort(signal, 22);
- return;
- }//if
- saAttrbufptr.p = &localAttrbufRecord[saAttrbufptr.i];
- saAttrbufptr.p->attrbuf[ZINBUF_NEXT] = TfirstfreeAttrbuf;
- }//if
-
- cfirstfreeAttrbuf = Tnext;
- regAttrPtr->attrbuf[ZINBUF_NEXT] = RNIL;
- regCachePtr->lastAttrbuf = TfirstfreeAttrbuf;
- regAttrPtr->attrbuf[ZINBUF_DATA_LEN] = Tlen;
-
- UintR Tdata1 = signal->theData[3];
- UintR Tdata2 = signal->theData[4];
- UintR Tdata3 = signal->theData[5];
- UintR Tdata4 = signal->theData[6];
- UintR Tdata5 = signal->theData[7];
- UintR Tdata6 = signal->theData[8];
- UintR Tdata7 = signal->theData[9];
- UintR Tdata8 = signal->theData[10];
-
- regAttrPtr->attrbuf[0] = Tdata1;
- regAttrPtr->attrbuf[1] = Tdata2;
- regAttrPtr->attrbuf[2] = Tdata3;
- regAttrPtr->attrbuf[3] = Tdata4;
- regAttrPtr->attrbuf[4] = Tdata5;
- regAttrPtr->attrbuf[5] = Tdata6;
- regAttrPtr->attrbuf[6] = Tdata7;
- regAttrPtr->attrbuf[7] = Tdata8;
-
- if (Tlen > 8) {
-
- Tdata1 = signal->theData[11];
- Tdata2 = signal->theData[12];
- Tdata3 = signal->theData[13];
- Tdata4 = signal->theData[14];
- Tdata5 = signal->theData[15];
- Tdata6 = signal->theData[16];
- Tdata7 = signal->theData[17];
-
- regAttrPtr->attrbuf[8] = Tdata1;
- regAttrPtr->attrbuf[9] = Tdata2;
- regAttrPtr->attrbuf[10] = Tdata3;
- regAttrPtr->attrbuf[11] = Tdata4;
- regAttrPtr->attrbuf[12] = Tdata5;
- regAttrPtr->attrbuf[13] = Tdata6;
- regAttrPtr->attrbuf[14] = Tdata7;
- jam();
- if (Tlen > 15) {
-
- Tdata1 = signal->theData[18];
- Tdata2 = signal->theData[19];
- Tdata3 = signal->theData[20];
- Tdata4 = signal->theData[21];
- Tdata5 = signal->theData[22];
- Tdata6 = signal->theData[23];
- Tdata7 = signal->theData[24];
-
- jam();
- regAttrPtr->attrbuf[15] = Tdata1;
- regAttrPtr->attrbuf[16] = Tdata2;
- regAttrPtr->attrbuf[17] = Tdata3;
- regAttrPtr->attrbuf[18] = Tdata4;
- regAttrPtr->attrbuf[19] = Tdata5;
- regAttrPtr->attrbuf[20] = Tdata6;
- regAttrPtr->attrbuf[21] = Tdata7;
- }//if
- }//if
-}//Dbtc::saveAttrbuf()
-
-void Dbtc::execATTRINFO(Signal* signal)
-{
- UintR Tdata1 = signal->theData[0];
- UintR Tlength = signal->length();
- UintR TapiConnectFilesize = capiConnectFilesize;
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
- jamEntry();
- apiConnectptr.i = Tdata1;
- ttransid_ptr = 1;
- if (Tdata1 >= TapiConnectFilesize) {
- DEBUG("Drop ATTRINFO, wrong apiConnectptr");
- TCKEY_abort(signal, 18);
- return;
- }//if
-
- ApiConnectRecord * const regApiPtr = &localApiConnectRecord[Tdata1];
- apiConnectptr.p = regApiPtr;
-
- if (compare_transid(regApiPtr->transid, signal->theData+1) == false)
- {
- DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
- << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
- TCKEY_abort(signal, 19);
- return;
- }//if
- if (Tlength < 4) {
- DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
- TCKEY_abort(signal, 20);
- return;
- }
- Tlength -= 3;
- UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
- UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
- UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
-
- if (TcompBOTH) {
- jam();
- if (ERROR_INSERTED(8015)) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- if (ERROR_INSERTED(8016)) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- CacheRecord *localCacheRecord = cacheRecord;
- UintR TcacheFilesize = ccacheFilesize;
- UintR TcachePtr = regApiPtr->cachePtr;
- UintR TtcTimer = ctcTimer;
- CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
- if (TcachePtr >= TcacheFilesize) {
- TCKEY_abort(signal, 43);
- return;
- }//if
- UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
- UintR TcurrReclenAi = regCachePtr->currReclenAi;
- UintR TattrLen = regCachePtr->attrlength;
-
- setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
- cachePtr.i = TcachePtr;
- cachePtr.p = regCachePtr;
- TcurrReclenAi = TcurrReclenAi + Tlength;
- regCachePtr->currReclenAi = TcurrReclenAi;
- int TattrlengthRemain = TattrLen - TcurrReclenAi;
-
- if (TfirstfreeAttrbuf == RNIL) {
- DEBUG("No more attrinfo buffers");
- TCKEY_abort(signal, 24);
- return;
- }//if
- saveAttrbuf(signal);
- if (TattrlengthRemain == 0) {
- /****************************************************************>*/
- /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
- /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
- /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
- /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
- /* OPERATIONS. */
- /****************************************************************>*/
- UintR TlastConnect = regApiPtr->lastTcConnect;
- if (TcompRECEIVING) {
- jam();
- regApiPtr->apiConnectstate = CS_STARTED;
- } else {
- jam();
- regApiPtr->apiConnectstate = CS_START_COMMITTING;
- }//if
- tcConnectptr.i = TlastConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- attrinfoDihReceivedLab(signal);
- } else if (TattrlengthRemain < 0) {
- jam();
- DEBUG("ATTRINFO wrong total length="<<Tlength
- <<", TattrlengthRemain="<<TattrlengthRemain
- <<", TattrLen="<<TattrLen
- <<", TcurrReclenAi="<<TcurrReclenAi);
- tcConnectptr.i = regApiPtr->lastTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- aiErrorLab(signal);
- }//if
- return;
- } else if (regApiPtr->apiConnectstate == CS_START_SCAN) {
- jam();
- scanAttrinfoLab(signal, Tlength);
- return;
- } else {
- switch (regApiPtr->apiConnectstate) {
- case CS_ABORTING:
- jam();
- /* JUST IGNORE THE SIGNAL*/
- // DEBUG("Drop ATTRINFO, CS_ABORTING");
- return;
- case CS_CONNECTED:
- jam();
- /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
- // DEBUG("Drop ATTRINFO, CS_CONNECTED");
- return;
- case CS_STARTED:
- jam();
- /****************************************************************>*/
- /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
- /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
- /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
- /****************************************************************>*/
- terrorCode = ZSIGNAL_ERROR;
- printState(signal, 1);
- abortErrorLab(signal);
- return;
- default:
- jam();
- /****************************************************************>*/
- /* SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
- /* SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED. */
- /****************************************************************>*/
- DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
- printState(signal, 9);
- return;
- }//switch
- }//if
-}//Dbtc::execATTRINFO()
-
-/* *********************************************************************>> */
-/* */
-/* MODULE: HASH MODULE */
-/* DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION */
-/* *********************************************************************> */
-void Dbtc::hash(Signal* signal)
-{
- DatabufRecordPtr locDatabufptr;
- UintR ti;
- UintR Tdata0;
- UintR Tdata1;
- UintR Tdata2;
- UintR Tdata3;
- UintR* Tdata32;
-
- CacheRecord * const regCachePtr = cachePtr.p;
- Tdata32 = signal->theData;
-
- Tdata0 = regCachePtr->keydata[0];
- Tdata1 = regCachePtr->keydata[1];
- Tdata2 = regCachePtr->keydata[2];
- Tdata3 = regCachePtr->keydata[3];
- Tdata32[0] = Tdata0;
- Tdata32[1] = Tdata1;
- Tdata32[2] = Tdata2;
- Tdata32[3] = Tdata3;
- if (regCachePtr->keylen > 4) {
- locDatabufptr.i = regCachePtr->firstKeybuf;
- ti = 4;
- while (locDatabufptr.i != RNIL) {
- ptrCheckGuard(locDatabufptr, cdatabufFilesize, databufRecord);
- 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
- }//if
-
- 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 = regCachePtr->distributionKey;
- } else {
- jam();
- tdistrHashValue = tmp[1];
- }//if
-}//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 hasVarKeys = tabPtrP->hasVarKeys;
- const bool hasCharAttr = tabPtrP->hasCharAttr;
- const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
-
- Uint32 *dst = (Uint32*)Tmp;
- Uint32 dstPos = 0;
- Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
- Uint32 * keyPartLenPtr;
- if(hasCharAttr || (compute_distkey && hasVarKeys))
- {
- 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(compute_distkey)
- {
- 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
----------------------------
-*/
-/* ========================================================================= */
-/* ======= INIT_API_CONNECT_REC ======= */
-/* */
-/* ========================================================================= */
-void Dbtc::initApiConnectRec(Signal* signal,
- ApiConnectRecord * const regApiPtr,
- bool releaseIndexOperations)
-{
- const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
- UintR TfailureNr = cfailure_nr;
- UintR TtransCount = c_counters.ctransCount;
- UintR Ttransid0 = tcKeyReq->transId1;
- UintR Ttransid1 = tcKeyReq->transId2;
-
- regApiPtr->m_exec_flag = 0;
- regApiPtr->returncode = 0;
- regApiPtr->returnsignal = RS_TCKEYCONF;
- ndbassert(regApiPtr->firstTcConnect == RNIL);
- regApiPtr->firstTcConnect = RNIL;
- regApiPtr->lastTcConnect = RNIL;
- regApiPtr->globalcheckpointid = 0;
- regApiPtr->lqhkeyconfrec = 0;
- regApiPtr->lqhkeyreqrec = 0;
- regApiPtr->tckeyrec = 0;
- regApiPtr->tcindxrec = 0;
- regApiPtr->failureNr = TfailureNr;
- regApiPtr->transid[0] = Ttransid0;
- regApiPtr->transid[1] = Ttransid1;
- regApiPtr->commitAckMarker = RNIL;
- regApiPtr->buddyPtr = RNIL;
- regApiPtr->currSavePointId = 0;
- regApiPtr->m_transaction_nodes.clear();
- regApiPtr->singleUserMode = 0;
- // Trigger data
- releaseFiredTriggerData(&regApiPtr->theFiredTriggers),
- // Index data
- regApiPtr->indexOpReturn = false;
- regApiPtr->noIndexOp = 0;
- if(releaseIndexOperations)
- releaseAllSeizedIndexOperations(regApiPtr);
-
- c_counters.ctransCount = TtransCount + 1;
-}//Dbtc::initApiConnectRec()
-
-int
-Dbtc::seizeTcRecord(Signal* signal)
-{
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
- UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
- UintR TtcConnectFilesize = ctcConnectFilesize;
- tcConnectptr.i = TfirstfreeTcConnect;
- if (TfirstfreeTcConnect >= TtcConnectFilesize) {
- int place = 3;
- if (TfirstfreeTcConnect != RNIL) {
- place = 10;
- }//if
- TCKEY_abort(signal, place);
- return 1;
- }//if
- //--------------------------------------------------------------------------
- // Optimised version of ptrAss(tcConnectptr, tcConnectRecord)
- //--------------------------------------------------------------------------
- TcConnectRecord * const regTcPtr =
- &localTcConnectRecord[TfirstfreeTcConnect];
-
- UintR TconcurrentOp = c_counters.cconcurrentOp;
- UintR TlastTcConnect = regApiPtr->lastTcConnect;
- UintR TtcConnectptrIndex = tcConnectptr.i;
- TcConnectRecordPtr tmpTcConnectptr;
-
- cfirstfreeTcConnect = regTcPtr->nextTcConnect;
- tcConnectptr.p = regTcPtr;
-
- c_counters.cconcurrentOp = TconcurrentOp + 1;
- regTcPtr->prevTcConnect = TlastTcConnect;
- regTcPtr->nextTcConnect = RNIL;
- regTcPtr->accumulatingTriggerData.i = RNIL;
- regTcPtr->accumulatingTriggerData.p = NULL;
- regTcPtr->noFiredTriggers = 0;
- regTcPtr->noReceivedTriggers = 0;
- regTcPtr->triggerExecutionCount = 0;
- regTcPtr->triggeringOperation = RNIL;
- regTcPtr->isIndexOp = false;
- regTcPtr->indexOp = RNIL;
- regTcPtr->currentIndexId = RNIL;
-
- regApiPtr->lastTcConnect = TtcConnectptrIndex;
-
- if (TlastTcConnect == RNIL) {
- jam();
- regApiPtr->firstTcConnect = TtcConnectptrIndex;
- } else {
- tmpTcConnectptr.i = TlastTcConnect;
- jam();
- ptrCheckGuard(tmpTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
- tmpTcConnectptr.p->nextTcConnect = TtcConnectptrIndex;
- }//if
- return 0;
-}//Dbtc::seizeTcRecord()
-
-int
-Dbtc::seizeCacheRecord(Signal* signal)
-{
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
- UintR TcacheFilesize = ccacheFilesize;
- CacheRecord *localCacheRecord = cacheRecord;
- if (TfirstfreeCacheRec >= TcacheFilesize) {
- TCKEY_abort(signal, 41);
- return 1;
- }//if
- CacheRecord * const regCachePtr = &localCacheRecord[TfirstfreeCacheRec];
-
- regApiPtr->cachePtr = TfirstfreeCacheRec;
- cfirstfreeCacheRec = regCachePtr->nextCacheRec;
- cachePtr.i = TfirstfreeCacheRec;
- cachePtr.p = regCachePtr;
-
-#ifdef VM_TRACE
- // This is a good place to check that resources have
- // been properly released from CacheRecord
- ndbrequire(regCachePtr->firstKeybuf == RNIL);
- ndbrequire(regCachePtr->lastKeybuf == RNIL);
-#endif
- regCachePtr->firstKeybuf = RNIL;
- regCachePtr->lastKeybuf = RNIL;
- regCachePtr->firstAttrbuf = RNIL;
- regCachePtr->lastAttrbuf = RNIL;
- regCachePtr->currReclenAi = 0;
- return 0;
-}//Dbtc::seizeCacheRecord()
-
-/*****************************************************************************/
-/* T C K E Y R E Q */
-/* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN */
-/* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST */
-/* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES */
-/* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA */
-/*****************************************************************************/
-void Dbtc::execTCKEYREQ(Signal* signal)
-{
- Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
- UintR compare_transid1, compare_transid2;
- UintR titcLenAiInTckeyreq;
- UintR TkeyLength;
- const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
- UintR Treqinfo;
-
- jamEntry();
- /*-------------------------------------------------------------------------
- * Common error routines are used for several signals, they need to know
- * where to find the transaction identifier in the signal.
- *-------------------------------------------------------------------------*/
- const UintR TapiIndex = tcKeyReq->apiConnectPtr;
- const UintR TapiMaxIndex = capiConnectFilesize;
- const UintR TtabIndex = tcKeyReq->tableId;
- const UintR TtabMaxIndex = ctabrecFilesize;
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
- ttransid_ptr = 6;
- apiConnectptr.i = TapiIndex;
- if (TapiIndex >= TapiMaxIndex) {
- TCKEY_abort(signal, 6);
- return;
- }//if
- if (TtabIndex >= TtabMaxIndex) {
- TCKEY_abort(signal, 7);
- return;
- }//if
-
- Treqinfo = tcKeyReq->requestInfo;
- //--------------------------------------------------------------------------
- // Optimised version of ptrAss(tabptr, tableRecord)
- // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
- //--------------------------------------------------------------------------
- ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex];
- apiConnectptr.p = regApiPtr;
-
- Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
- Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo);
-
- Uint8 isIndexOp = regApiPtr->isIndexOp;
- bool isIndexOpReturn = regApiPtr->indexOpReturn;
- regApiPtr->isIndexOp = false; // Reset marker
- regApiPtr->m_exec_flag |= TexecFlag;
- TableRecordPtr localTabptr;
- localTabptr.i = TtabIndex;
- localTabptr.p = &tableRecord[TtabIndex];
- switch (regApiPtr->apiConnectstate) {
- case CS_CONNECTED:{
- if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
- //---------------------------------------------------------------------
- // Initialise API connect record if transaction is started.
- //---------------------------------------------------------------------
- jam();
- initApiConnectRec(signal, regApiPtr);
- regApiPtr->m_exec_flag = TexecFlag;
- } else {
- if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
- /*------------------------------------------------------------------
- * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
- * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
- * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
- *-----------------------------------------------------------------*/
- TCKEY_abort(signal, 0);
- return;
- } else {
- /**
- * getAllowStartTransaction(sendersNodeId) == false
- */
- TCKEY_abort(signal, TexecFlag ? 60 : 57);
- return;
- }//if
- }
- }
- break;
- case CS_STARTED:
- if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
- {
- /**
- * If last operation in last transaction was a simple/dirty read
- * it does not have to be committed or rollbacked hence,
- * the state will be CS_STARTED
- */
- jam();
- if (unlikely(getNodeState().getSingleUserMode()) &&
- getNodeState().getSingleUserApi() != sendersNodeId &&
- !localTabptr.p->singleUserMode)
- {
- TCKEY_abort(signal, TexecFlag ? 60 : 57);
- return;
- }
- initApiConnectRec(signal, regApiPtr);
- regApiPtr->m_exec_flag = TexecFlag;
- } else {
- //----------------------------------------------------------------------
- // Transaction is started already.
- // Check that the operation is on the same transaction.
- //-----------------------------------------------------------------------
- compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
- compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
- jam();
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- TCKEY_abort(signal, 1);
- return;
- }//if
- }
- break;
- case CS_ABORTING:
- if (regApiPtr->abortState == AS_IDLE) {
- if (TstartFlag == 1) {
- if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
- TCKEY_abort(signal, TexecFlag ? 60 : 57);
- return;
- }
- //--------------------------------------------------------------------
- // Previous transaction had been aborted and the abort was completed.
- // It is then OK to start a new transaction again.
- //--------------------------------------------------------------------
- jam();
- initApiConnectRec(signal, regApiPtr);
- regApiPtr->m_exec_flag = TexecFlag;
- } else if(TexecFlag) {
- TCKEY_abort(signal, 59);
- return;
- } else {
- //--------------------------------------------------------------------
- // The current transaction was aborted successfully.
- // We will not do anything before we receive an operation
- // with a start indicator. We will ignore this signal.
- //--------------------------------------------------------------------
- jam();
- DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
- return;
- }//if
- } else {
- //----------------------------------------------------------------------
- // Previous transaction is still aborting
- //----------------------------------------------------------------------
- jam();
- if (TstartFlag == 1) {
- //--------------------------------------------------------------------
- // If a new transaction tries to start while the old is
- // still aborting, we will report this to the starting API.
- //--------------------------------------------------------------------
- TCKEY_abort(signal, 2);
- return;
- } else if(TexecFlag) {
- TCKEY_abort(signal, 59);
- return;
- }
- //----------------------------------------------------------------------
- // Ignore signals without start indicator set when aborting transaction.
- //----------------------------------------------------------------------
- DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
- return;
- }//if
- break;
- case CS_START_COMMITTING:
- jam();
- if(isIndexOpReturn || TcKeyReq::getExecutingTrigger(Treqinfo)){
- break;
- }
- default:
- jam();
- /*----------------------------------------------------------------------
- * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
- * WHEN IT WAS NOT EXPECTED TO.
- * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
- * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
- * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
- * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
- * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
- *---------------------------------------------------------------------*/
- TCKEY_abort(signal, 55);
- return;
- }//switch
-
- if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
- ;
- } else {
- /*-----------------------------------------------------------------------*/
- /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT. */
- /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED. */
- /*-----------------------------------------------------------------------*/
- TCKEY_abort(signal, 8);
- return;
- }//if
-
- //-------------------------------------------------------------------------
- // Error Insertion for testing purposes. Test to see what happens when no
- // more TC records available.
- //-------------------------------------------------------------------------
- if (ERROR_INSERTED(8032)) {
- TCKEY_abort(signal, 3);
- return;
- }//if
-
- if (seizeTcRecord(signal) != 0) {
- return;
- }//if
-
- if (seizeCacheRecord(signal) != 0) {
- return;
- }//if
-
- TcConnectRecord * const regTcPtr = tcConnectptr.p;
- CacheRecord * const regCachePtr = cachePtr.p;
-
- /*
- INIT_TC_CONNECT_REC
- -------------------------
- */
- /* ---------------------------------------------------------------------- */
- /* ------- INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS ------- */
- /* */
- /* ---------------------------------------------------------------------- */
-
- UintR TapiVersionNo = TcKeyReq::getAPIVersion(tcKeyReq->attrLen);
- UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
- regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
- regCachePtr->apiVersionNo = TapiVersionNo;
-
- UintR TapiConnectptrIndex = apiConnectptr.i;
- UintR TsenderData = tcKeyReq->senderData;
- UintR TattrLen = TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
- UintR TattrinfoCount = c_counters.cattrinfoCount;
-
- regTcPtr->apiConnect = TapiConnectptrIndex;
- regTcPtr->clientData = TsenderData;
- regTcPtr->commitAckMarker = RNIL;
- regTcPtr->isIndexOp = isIndexOp;
- regTcPtr->indexOp = regApiPtr->executingIndexOp;
- regTcPtr->savePointId = regApiPtr->currSavePointId;
- regApiPtr->executingIndexOp = RNIL;
-
- regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
-
- if (TcKeyReq::getExecutingTrigger(Treqinfo)) {
- // Save the TcOperationPtr for fireing operation
- regTcPtr->triggeringOperation = TsenderData;
- }
-
- if (TexecFlag){
- Uint32 currSPId = regApiPtr->currSavePointId;
- regApiPtr->currSavePointId = ++currSPId;
- }
-
- regCachePtr->attrlength = TattrLen;
- c_counters.cattrinfoCount = TattrinfoCount + TattrLen;
-
- UintR TtabptrIndex = localTabptr.i;
- UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
- Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
- regCachePtr->tableref = TtabptrIndex;
- regCachePtr->schemaVersion = TtableSchemaVersion;
- regTcPtr->operation = TOperationType;
-
- Uint8 TSimpleFlag = TcKeyReq::getSimpleFlag(Treqinfo);
- Uint8 TDirtyFlag = TcKeyReq::getDirtyFlag(Treqinfo);
- Uint8 TInterpretedFlag = TcKeyReq::getInterpretedFlag(Treqinfo);
- Uint8 TDistrKeyFlag = TcKeyReq::getDistributionKeyFlag(Treqinfo);
- Uint8 TNoDiskFlag = TcKeyReq::getNoDiskFlag(Treqinfo);
- Uint8 TexecuteFlag = TexecFlag;
-
- regTcPtr->dirtyOp = TDirtyFlag;
- regTcPtr->opSimple = TSimpleFlag;
- regCachePtr->opExec = TInterpretedFlag;
- regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
- regCachePtr->m_no_disk_flag = TNoDiskFlag;
-
- //-------------------------------------------------------------
- // The next step is to read the upto three conditional words.
- //-------------------------------------------------------------
- Uint32 TkeyIndex;
- Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
- {
- Uint32 TDistrGHIndex = TcKeyReq::getScanIndFlag(Treqinfo);
- Uint32 TDistrKeyIndex = TDistrGHIndex;
-
- Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
-
- regCachePtr->scanTakeOverInd = TDistrGHIndex;
- regCachePtr->scanInfo = TscanInfo;
-
- regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
-
- TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
- }
- Uint32* TkeyDataPtr = &TOptionalDataPtr[TkeyIndex];
-
- UintR Tdata1 = TkeyDataPtr[0];
- UintR Tdata2 = TkeyDataPtr[1];
- UintR Tdata3 = TkeyDataPtr[2];
- UintR Tdata4 = TkeyDataPtr[3];
- UintR Tdata5;
-
- regCachePtr->keydata[0] = Tdata1;
- regCachePtr->keydata[1] = Tdata2;
- regCachePtr->keydata[2] = Tdata3;
- regCachePtr->keydata[3] = Tdata4;
-
- TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
- Uint32 TAIDataIndex;
- if (TkeyLength > 8) {
- TAIDataIndex = TkeyIndex + 8;
- } else {
- if (TkeyLength == 0) {
- TCKEY_abort(signal, 4);
- return;
- }//if
- TAIDataIndex = TkeyIndex + TkeyLength;
- }//if
- Uint32* TAIDataPtr = &TOptionalDataPtr[TAIDataIndex];
-
- titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
- 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];
- Tdata4 = TAIDataPtr[3];
- Tdata5 = TAIDataPtr[4];
-
- regCachePtr->attrinfo0 = Tdata1;
- regCachePtr->attrinfo15[0] = Tdata2;
- regCachePtr->attrinfo15[1] = Tdata3;
- regCachePtr->attrinfo15[2] = Tdata4;
- regCachePtr->attrinfo15[3] = Tdata5;
-
- if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
- Uint32 TreadCount = c_counters.creadCount;
- jam();
- c_counters.creadCount = TreadCount + 1;
- } else {
- if(regApiPtr->commitAckMarker == RNIL){
- jam();
- CommitAckMarkerPtr tmp;
- if(!m_commitAckMarkerHash.seize(tmp)){
- TCKEY_abort(signal, 56);
- return;
- } else {
- regTcPtr->commitAckMarker = tmp.i;
- regApiPtr->commitAckMarker = tmp.i;
- tmp.p->transid1 = tcKeyReq->transId1;
- tmp.p->transid2 = tcKeyReq->transId2;
- tmp.p->apiNodeId = refToNode(regApiPtr->ndbapiBlockref);
- tmp.p->apiConnectPtr = TapiIndex;
- tmp.p->noOfLqhs = 0;
-#if defined VM_TRACE || defined ERROR_INSERT
- {
- CommitAckMarkerPtr check;
- ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
- }
-#endif
- m_commitAckMarkerHash.add(tmp);
- }
- }
-
- UintR TwriteCount = c_counters.cwriteCount;
- UintR Toperationsize = coperationsize;
- /* --------------------------------------------------------------------
- * THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
- * THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
- * TEMP TABLES DON'T PARTICIPATE.
- * -------------------------------------------------------------------- */
- if (localTabptr.p->get_storedTable()) {
- coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
- }
- c_counters.cwriteCount = TwriteCount + 1;
- switch (TOperationType) {
- case ZUPDATE:
- case ZINSERT:
- case ZDELETE:
- case ZWRITE:
- jam();
- break;
- default:
- TCKEY_abort(signal, 9);
- return;
- }//switch
- }//if
-
- Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
- regTcPtr->m_execAbortOption = TabortOption;
-
- /*-------------------------------------------------------------------------
- * Check error handling per operation
- * If CommitFlag is set state accordingly and check for early abort
- *------------------------------------------------------------------------*/
- if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
- ndbrequire(TexecuteFlag);
- regApiPtr->apiConnectstate = CS_REC_COMMITTING;
- } else {
- /* ---------------------------------------------------------------------
- * PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
- * ---------------------------------------------------------------------
- * ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
- * IF PREPARE TRANSACTION THEN
- * API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
- * SET STATE TO PREPARING
- * --------------------------------------------------------------------- */
- if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
- jam();
- // Trigger execution at commit
- regApiPtr->apiConnectstate = CS_REC_COMMITTING;
- } else {
- jam();
- regApiPtr->apiConnectstate = CS_RECEIVING;
- }//if
- }//if
- if (TkeyLength <= 4) {
- tckeyreq050Lab(signal);
- return;
- } else {
- if (cfirstfreeDatabuf != RNIL) {
- jam();
- linkKeybuf(signal);
- Tdata1 = TkeyDataPtr[4];
- Tdata2 = TkeyDataPtr[5];
- Tdata3 = TkeyDataPtr[6];
- Tdata4 = TkeyDataPtr[7];
-
- DatabufRecord * const regDataPtr = databufptr.p;
- regDataPtr->data[0] = Tdata1;
- regDataPtr->data[1] = Tdata2;
- regDataPtr->data[2] = Tdata3;
- regDataPtr->data[3] = Tdata4;
- } else {
- jam();
- seizeDatabuferrorLab(signal);
- return;
- }//if
- if (TkeyLength <= 8) {
- jam();
- tckeyreq050Lab(signal);
- return;
- } else {
- jam();
- /* --------------------------------------------------------------------
- * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
- * SAVE STATE AND WAIT FOR KEYINFO
- * --------------------------------------------------------------------*/
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- regCachePtr->save1 = 8;
- regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
- return;
- }//if
- }//if
- return;
-}//Dbtc::execTCKEYREQ()
-
-void Dbtc::tckeyreq050Lab(Signal* signal)
-{
- UintR tnoOfBackup;
- 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;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
-
- UintR TtcTimer = ctcTimer;
- UintR ThashValue = thashValue;
- UintR TdistrHashValue = tdistrHashValue;
- UintR TdihConnectptr = regTcPtr->dihConnectptr;
- UintR Ttableref = regCachePtr->tableref;
-
- TableRecordPtr localTabptr;
- localTabptr.i = Ttableref;
- localTabptr.p = &tableRecord[localTabptr.i];
- Uint32 schemaVersion = regCachePtr->schemaVersion;
- if(localTabptr.p->checkTable(schemaVersion)){
- ;
- } else {
- terrorCode = localTabptr.p->getErrorCode(schemaVersion);
- TCKEY_abort(signal, 58);
- return;
- }
-
- setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
- regCachePtr->hashValue = ThashValue;
-
- signal->theData[0] = TdihConnectptr;
- signal->theData[1] = Ttableref;
- signal->theData[2] = TdistrHashValue;
- signal->theData[3] = 0;
- signal->theData[4] = 0;
- signal->theData[5] = 0;
- signal->theData[6] = 0;
-
- /*-------------------------------------------------------------*/
- /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
- /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE */
- /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION. */
- /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
- /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
- /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB. */
- /*-------------------------------------------------------------*/
- EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
- UintR TerrorIndicator = signal->theData[0];
- jamEntry();
- if (TerrorIndicator != 0) {
- execDIGETNODESREF(signal);
- return;
- }
-
- if(ERROR_INSERTED(8050) && signal->theData[3] != getOwnNodeId())
- {
- ndbassert(false);
- signal->theData[1] = 626;
- execDIGETNODESREF(signal);
- return;
- }
-
- /****************>>*/
- /* DIGETNODESCONF >*/
- /* ***************>*/
-
- UintR Tdata1 = signal->theData[1];
- UintR Tdata2 = signal->theData[2];
- UintR Tdata3 = signal->theData[3];
- UintR Tdata4 = signal->theData[4];
- UintR Tdata5 = signal->theData[5];
- UintR Tdata6 = signal->theData[6];
-
- regCachePtr->fragmentid = Tdata1;
- tnodeinfo = Tdata2;
-
- regTcPtr->tcNodedata[0] = Tdata3;
- regTcPtr->tcNodedata[1] = Tdata4;
- regTcPtr->tcNodedata[2] = Tdata5;
- regTcPtr->tcNodedata[3] = Tdata6;
-
- Uint8 Toperation = regTcPtr->operation;
- Uint8 Tdirty = regTcPtr->dirtyOp;
- tnoOfBackup = tnodeinfo & 3;
- tnoOfStandby = (tnodeinfo >> 8) & 3;
-
- regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
- if (Toperation == ZREAD || Toperation == ZREAD_EX) {
- if (Tdirty == 1) {
- jam();
- /*-------------------------------------------------------------*/
- /* A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND */
- /* BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS */
- /* NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION */
- /* WITH SIMPLE READS. */
- /*-------------------------------------------------------------*/
- arrGuard(tnoOfBackup, MAX_REPLICAS);
- UintR Tindex;
- UintR TownNode = cownNodeid;
- for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
- UintR Tnode = regTcPtr->tcNodedata[Tindex];
- jam();
- if (Tnode == TownNode) {
- jam();
- regTcPtr->tcNodedata[0] = Tnode;
- }//if
- }//for
- if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
- {
- for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
- {
- UintR Tnode = regTcPtr->tcNodedata[Tindex];
- jam();
- if (Tnode != TownNode) {
- jam();
- regTcPtr->tcNodedata[0] = Tnode;
- ndbout_c("Choosing %d", Tnode);
- }//if
- }//for
- }
- }//if
- jam();
- regTcPtr->lastReplicaNo = 0;
- regTcPtr->noOfNodes = 1;
- } else {
- UintR TlastReplicaNo;
- jam();
- TlastReplicaNo = tnoOfBackup + tnoOfStandby;
- regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
- regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
- }//if
- if (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength) {
- /****************************************************************>*/
- /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
- /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
- /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
- /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
- /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
- /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET. */
- /****************************************************************>*/
- switch (regApiPtr->apiConnectstate) {
- case CS_RECEIVING:
- jam();
- regApiPtr->apiConnectstate = CS_STARTED;
- break;
- case CS_REC_COMMITTING:
- jam();
- regApiPtr->apiConnectstate = CS_START_COMMITTING;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
- attrinfoDihReceivedLab(signal);
- return;
- } else {
- if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength) {
- TtcTimer = ctcTimer;
- jam();
- setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
- regTcPtr->tcConnectstate = OS_WAIT_ATTR;
- return;
- } else {
- TCKEY_abort(signal, 11);
- return;
- }//if
- }//if
- return;
-}//Dbtc::tckeyreq050Lab()
-
-void Dbtc::attrinfoDihReceivedLab(Signal* signal)
-{
- CacheRecord * const regCachePtr = cachePtr.p;
- TcConnectRecord * const regTcPtr = tcConnectptr.p;
- Uint16 Tnode = regTcPtr->tcNodedata[0];
-
- TableRecordPtr localTabptr;
- localTabptr.i = regCachePtr->tableref;
- localTabptr.p = &tableRecord[localTabptr.i];
-
- if(localTabptr.p->checkTable(regCachePtr->schemaVersion)){
- ;
- } else {
- terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
- TCKEY_abort(signal, 58);
- return;
- }
- arrGuard(Tnode, MAX_NDB_NODES);
- packLqhkeyreq(signal, calcLqhBlockRef(Tnode));
-}//Dbtc::attrinfoDihReceivedLab()
-
-void Dbtc::packLqhkeyreq(Signal* signal,
- BlockReference TBRef)
-{
- CacheRecord * const regCachePtr = cachePtr.p;
- UintR Tkeylen = regCachePtr->keylen;
- UintR TfirstAttrbuf = regCachePtr->firstAttrbuf;
- sendlqhkeyreq(signal, TBRef);
- if (Tkeylen > 4) {
- packKeyData000Lab(signal, TBRef, Tkeylen - 4);
- releaseKeys();
- }//if
- packLqhkeyreq040Lab(signal,
- TfirstAttrbuf,
- TBRef);
-}//Dbtc::packLqhkeyreq()
-
-void Dbtc::sendlqhkeyreq(Signal* signal,
- BlockReference TBRef)
-{
- UintR tslrAttrLen;
- UintR Tdata10;
- TcConnectRecord * const regTcPtr = tcConnectptr.p;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- CacheRecord * const regCachePtr = cachePtr.p;
- Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
- UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(8002)) {
- systemErrorLab(signal, __LINE__);
- }//if
- if (ERROR_INSERTED(8007)) {
- if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8008)) {
- if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8009)) {
- if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8010)) {
- if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
- return;
- }//if
- }//if
-#endif
-
- tslrAttrLen = 0;
- LqhKeyReq::setAttrLen(tslrAttrLen, regCachePtr->attrlength);
- /* ---------------------------------------------------------------------- */
- // Bit16 == 0 since StoredProcedures are not yet supported.
- /* ---------------------------------------------------------------------- */
- LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
- LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
-
- Tdata10 = 0;
- sig0 = regTcPtr->opSimple;
- sig1 = regTcPtr->operation;
- sig2 = regTcPtr->dirtyOp;
- bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
- LqhKeyReq::setKeyLen(Tdata10, regCachePtr->keylen);
- LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
- if (unlikely(version < NDBD_ROWID_VERSION))
- {
- Uint32 op = regTcPtr->operation;
- Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
- LqhKeyReq::setLockType(Tdata10, lock);
- }
- /* ---------------------------------------------------------------------- */
- // Indicate Application Reference is present in bit 15
- /* ---------------------------------------------------------------------- */
- LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
- LqhKeyReq::setDirtyFlag(Tdata10, sig2);
- LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
- LqhKeyReq::setSimpleFlag(Tdata10, sig0);
- LqhKeyReq::setOperation(Tdata10, sig1);
- LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
-
- /* -----------------------------------------------------------------------
- * Sequential Number of first LQH = 0, bit 22-23
- * IF ATTRIBUTE INFORMATION IS SENT IN TCKEYREQ,
- * IT IS ALSO SENT IN LQHKEYREQ
- * ----------------------------------------------------------------------- */
- LqhKeyReq::setAIInLqhKeyReq(Tdata10, regCachePtr->lenAiInTckeyreq);
- /* -----------------------------------------------------------------------
- * Bit 27 == 0 since TC record is the same as the client record.
- * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
- * ----------------------------------------------------------------------- */
- //LqhKeyReq::setAPIVersion(Tdata10, regCachePtr->apiVersionNo);
- Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- const Uint32 noOfLqhs = regTcPtr->noOfNodes;
- if(commitAckMarker != RNIL){
- jam();
- LqhKeyReq::setMarkerFlag(Tdata10, 1);
-
- CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
-
- /**
- * Populate LQH array
- */
- tmp->noOfLqhs = noOfLqhs;
- for(Uint32 i = 0; i<noOfLqhs; i++){
- tmp->lqhNodeId[i] = regTcPtr->tcNodedata[i];
- }
- }
-
- /* ************************************************************> */
- /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT */
- /* IS SENT TO A PRIMARY NODE. */
- /* ************************************************************> */
-
- LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
-
- sig0 = tcConnectptr.i;
- sig2 = regCachePtr->hashValue;
- sig4 = cownref;
- sig5 = regTcPtr->savePointId;
-
- lqhKeyReq->clientConnectPtr = sig0;
- lqhKeyReq->attrLen = tslrAttrLen;
- lqhKeyReq->hashValue = sig2;
- lqhKeyReq->requestInfo = Tdata10;
- lqhKeyReq->tcBlockref = sig4;
- lqhKeyReq->savePointId = sig5;
-
- sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
- sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
- sig2 = regApiPtr->transid[0];
- sig3 = regApiPtr->transid[1];
- sig4 = (regTcPtr->isIndexOp == 2) ? reference() : regApiPtr->ndbapiBlockref;
- sig5 = regTcPtr->clientData;
- sig6 = regCachePtr->scanInfo;
-
- if (! dirtyRead)
- {
- regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
- regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
- regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
- regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
- }
-
- lqhKeyReq->tableSchemaVersion = sig0;
- lqhKeyReq->fragmentData = sig1;
- lqhKeyReq->transId1 = sig2;
- lqhKeyReq->transId2 = sig3;
- lqhKeyReq->scanInfo = sig6;
-
- lqhKeyReq->variableData[0] = sig4;
- lqhKeyReq->variableData[1] = sig5;
-
- UintR nextPos = 2;
-
- if (regTcPtr->lastReplicaNo > 1) {
- sig0 = (UintR)regTcPtr->tcNodedata[2] +
- (UintR)(regTcPtr->tcNodedata[3] << 16);
- lqhKeyReq->variableData[nextPos] = sig0;
- nextPos++;
- }//if
-
- sig0 = regCachePtr->keydata[0];
- sig1 = regCachePtr->keydata[1];
- sig2 = regCachePtr->keydata[2];
- sig3 = regCachePtr->keydata[3];
- UintR Tkeylen = regCachePtr->keylen;
-
- lqhKeyReq->variableData[nextPos + 0] = sig0;
- lqhKeyReq->variableData[nextPos + 1] = sig1;
- lqhKeyReq->variableData[nextPos + 2] = sig2;
- lqhKeyReq->variableData[nextPos + 3] = sig3;
-
- if (Tkeylen < 4) {
- nextPos += Tkeylen;
- } else {
- nextPos += 4;
- }//if
-
- sig0 = regCachePtr->attrinfo0;
- sig1 = regCachePtr->attrinfo15[0];
- sig2 = regCachePtr->attrinfo15[1];
- sig3 = regCachePtr->attrinfo15[2];
- sig4 = regCachePtr->attrinfo15[3];
- UintR TlenAi = regCachePtr->lenAiInTckeyreq;
-
- lqhKeyReq->variableData[nextPos + 0] = sig0;
- lqhKeyReq->variableData[nextPos + 1] = sig1;
- lqhKeyReq->variableData[nextPos + 2] = sig2;
- lqhKeyReq->variableData[nextPos + 3] = sig3;
- lqhKeyReq->variableData[nextPos + 4] = sig4;
-
- nextPos += TlenAi;
-
- // Reset trigger count
- regTcPtr->accumulatingTriggerData.i = RNIL;
- regTcPtr->accumulatingTriggerData.p = NULL;
- regTcPtr->noFiredTriggers = 0;
- regTcPtr->triggerExecutionCount = 0;
-
- sendSignal(TBRef, GSN_LQHKEYREQ, signal,
- nextPos + LqhKeyReq::FixedSignalLength, JBB);
-}//Dbtc::sendlqhkeyreq()
-
-void Dbtc::packLqhkeyreq040Lab(Signal* signal,
- UintR anAttrBufIndex,
- BlockReference TBRef)
-{
- TcConnectRecord * const regTcPtr = tcConnectptr.p;
-#ifdef ERROR_INSERT
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- if (ERROR_INSERTED(8009)) {
- if (regApiPtr->apiConnectstate == CS_STARTED) {
- attrbufptr.i = RNIL;
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8010)) {
- if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
- attrbufptr.i = RNIL;
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
-#endif
-
- UintR TattrbufFilesize = cattrbufFilesize;
- AttrbufRecord *localAttrbufRecord = attrbufRecord;
- while (1) {
- if (anAttrBufIndex == RNIL) {
- UintR TtcTimer = ctcTimer;
- UintR Tread = (regTcPtr->operation == ZREAD);
- UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
- UintR Tboth = Tread & Tdirty;
- setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
- jam();
- /*--------------------------------------------------------------------
- * WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
- *---------------------------------------------------------------------*/
- releaseAttrinfo();
- if (Tboth) {
- jam();
- releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
- return;
- }//if
- regTcPtr->tcConnectstate = OS_OPERATING;
- return;
- }//if
- if (anAttrBufIndex < TattrbufFilesize) {
- AttrbufRecord * const regAttrPtr = &localAttrbufRecord[anAttrBufIndex];
- anAttrBufIndex = regAttrPtr->attrbuf[ZINBUF_NEXT];
- sendAttrinfo(signal,
- tcConnectptr.i,
- regAttrPtr,
- TBRef);
- } else {
- TCKEY_abort(signal, 17);
- return;
- }//if
- }//while
-}//Dbtc::packLqhkeyreq040Lab()
-
-/* ========================================================================= */
-/* ------- RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD ------- */
-/* ========================================================================= */
-void Dbtc::releaseAttrinfo()
-{
- UintR Tmp;
- AttrbufRecordPtr Tattrbufptr;
- CacheRecord * const regCachePtr = cachePtr.p;
- UintR TattrbufFilesize = cattrbufFilesize;
- UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
- Tattrbufptr.i = regCachePtr->firstAttrbuf;
- AttrbufRecord *localAttrbufRecord = attrbufRecord;
-
- while (Tattrbufptr.i < TattrbufFilesize) {
- Tattrbufptr.p = &localAttrbufRecord[Tattrbufptr.i];
- Tmp = Tattrbufptr.p->attrbuf[ZINBUF_NEXT];
- Tattrbufptr.p->attrbuf[ZINBUF_NEXT] = TfirstfreeAttrbuf;
- TfirstfreeAttrbuf = Tattrbufptr.i;
- Tattrbufptr.i = Tmp;
- jam();
- }//while
- if (Tattrbufptr.i == RNIL) {
-//---------------------------------------------------
-// Now we will release the cache record at the same
-// time as releasing the attrinfo records.
-//---------------------------------------------------
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
- UintR TCacheIndex = cachePtr.i;
- cfirstfreeAttrbuf = TfirstfreeAttrbuf;
- regCachePtr->nextCacheRec = TfirstfreeCacheRec;
- cfirstfreeCacheRec = TCacheIndex;
- regApiPtr->cachePtr = RNIL;
- return;
- }//if
- systemErrorLab(0, __LINE__);
- return;
-}//Dbtc::releaseAttrinfo()
-
-/* ========================================================================= */
-/* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION ------- */
-/* ========================================================================= */
-void Dbtc::releaseDirtyRead(Signal* signal,
- ApiConnectRecordPtr regApiPtr,
- TcConnectRecord* regTcPtr)
-{
- Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
- Uint32 TclientData = regTcPtr->clientData;
- Uint32 Tnode = regTcPtr->tcNodedata[0];
- Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
- Uint32 TsimpleReadCount = c_counters.csimpleReadCount;
- ConnectionState state = regApiPtr.p->apiConnectstate;
-
- regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
- regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
- regApiPtr.p->tckeyrec = Ttckeyrec + 2;
-
- unlinkReadyTcCon(signal);
- releaseTcCon();
-
- /**
- * No LQHKEYCONF in Simple/Dirty read
- * Therefore decrese no LQHKEYCONF(REF) we are waiting for
- */
- c_counters.csimpleReadCount = TsimpleReadCount + 1;
- regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
-
- if(Tlqhkeyreqrec == 0)
- {
- /**
- * Special case of lqhKeyConf_checkTransactionState:
- * - commit with zero operations: handle only for simple read
- */
- sendtckeyconf(signal, state == CS_START_COMMITTING);
- regApiPtr.p->apiConnectstate =
- (state == CS_START_COMMITTING ? CS_CONNECTED : state);
- setApiConTimer(regApiPtr.i, 0, __LINE__);
-
- return;
- }
-
- /**
- * Emulate LQHKEYCONF
- */
- lqhKeyConf_checkTransactionState(signal, regApiPtr);
-}//Dbtc::releaseDirtyRead()
-
-/* ------------------------------------------------------------------------- */
-/* ------- CHECK IF ALL TC CONNECTIONS ARE COMPLETED ------- */
-/* ------------------------------------------------------------------------- */
-void Dbtc::unlinkReadyTcCon(Signal* signal)
-{
- TcConnectRecordPtr urtTcConnectptr;
-
- TcConnectRecord * const regTcPtr = tcConnectptr.p;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
- UintR TtcConnectFilesize = ctcConnectFilesize;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- if (regTcPtr->prevTcConnect != RNIL) {
- jam();
- urtTcConnectptr.i = regTcPtr->prevTcConnect;
- ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
- urtTcConnectptr.p->nextTcConnect = regTcPtr->nextTcConnect;
- } else {
- jam();
- regApiPtr->firstTcConnect = regTcPtr->nextTcConnect;
- }//if
- if (regTcPtr->nextTcConnect != RNIL) {
- jam();
- urtTcConnectptr.i = regTcPtr->nextTcConnect;
- ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
- urtTcConnectptr.p->prevTcConnect = regTcPtr->prevTcConnect;
- } else {
- jam();
- regApiPtr->lastTcConnect = tcConnectptr.p->prevTcConnect;
- }//if
-}//Dbtc::unlinkReadyTcCon()
-
-void Dbtc::releaseTcCon()
-{
- TcConnectRecord * const regTcPtr = tcConnectptr.p;
- UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
- UintR TconcurrentOp = c_counters.cconcurrentOp;
- UintR TtcConnectptrIndex = tcConnectptr.i;
-
- regTcPtr->tcConnectstate = OS_CONNECTED;
- regTcPtr->nextTcConnect = TfirstfreeTcConnect;
- regTcPtr->apiConnect = RNIL;
- regTcPtr->isIndexOp = false;
- regTcPtr->indexOp = RNIL;
- cfirstfreeTcConnect = TtcConnectptrIndex;
- c_counters.cconcurrentOp = TconcurrentOp - 1;
-}//Dbtc::releaseTcCon()
-
-void Dbtc::execPACKED_SIGNAL(Signal* signal)
-{
- LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
-
- UintR Ti;
- UintR Tstep = 0;
- UintR Tlength;
- UintR TpackedData[28];
- UintR Tdata1, Tdata2, Tdata3, Tdata4;
-
- jamEntry();
- Tlength = signal->length();
- if (Tlength > 25) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- Uint32* TpackDataPtr;
- for (Ti = 0; Ti < Tlength; Ti += 4) {
- Uint32* TsigDataPtr = &signal->theData[Ti];
- Tdata1 = TsigDataPtr[0];
- Tdata2 = TsigDataPtr[1];
- Tdata3 = TsigDataPtr[2];
- Tdata4 = TsigDataPtr[3];
-
- TpackDataPtr = &TpackedData[Ti];
- TpackDataPtr[0] = Tdata1;
- TpackDataPtr[1] = Tdata2;
- TpackDataPtr[2] = Tdata3;
- TpackDataPtr[3] = Tdata4;
- }//for
- while (Tlength > Tstep) {
-
- TpackDataPtr = &TpackedData[Tstep];
- Tdata1 = TpackDataPtr[0];
- Tdata2 = TpackDataPtr[1];
- Tdata3 = TpackDataPtr[2];
-
- lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
- lqhKeyConf->opPtr = Tdata2;
- lqhKeyConf->userRef = Tdata3;
-
- switch (Tdata1 >> 28) {
- case ZCOMMITTED:
- signal->header.theLength = 3;
- execCOMMITTED(signal);
- Tstep += 3;
- break;
- case ZCOMPLETED:
- signal->header.theLength = 3;
- execCOMPLETED(signal);
- Tstep += 3;
- break;
- case ZLQHKEYCONF:
- jam();
- Tdata1 = TpackDataPtr[3];
- Tdata2 = TpackDataPtr[4];
- Tdata3 = TpackDataPtr[5];
- Tdata4 = TpackDataPtr[6];
-
- lqhKeyConf->readLen = Tdata1;
- lqhKeyConf->transId1 = Tdata2;
- lqhKeyConf->transId2 = Tdata3;
- lqhKeyConf->noFiredTriggers = Tdata4;
- signal->header.theLength = LqhKeyConf::SignalLength;
- execLQHKEYCONF(signal);
- Tstep += LqhKeyConf::SignalLength;
- break;
- default:
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
- }//while
- return;
-}//Dbtc::execPACKED_SIGNAL()
-
-void Dbtc::execLQHKEYCONF(Signal* signal)
-{
- const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
- UintR compare_transid1, compare_transid2;
- BlockReference tlastLqhBlockref;
- UintR tlastLqhConnect;
- UintR treadlenAi;
- UintR TtcConnectptrIndex;
- UintR TtcConnectFilesize = ctcConnectFilesize;
-
- tlastLqhConnect = lqhKeyConf->connectPtr;
- TtcConnectptrIndex = lqhKeyConf->opPtr;
- tlastLqhBlockref = lqhKeyConf->userRef;
- treadlenAi = lqhKeyConf->readLen;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
-
- /*------------------------------------------------------------------------
- * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
- * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
- * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
- * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
- * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
- * OPERATIONS ON THE LQH CONNECT RECORD.
- *------------------------------------------------------------------------
- * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
- * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
- * PROBLEM WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
- * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
- * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
- * BEFORE ACCEPTING THIS SIGNAL.
- * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
- * this.
- * This is more reason to ignore the signal if not all states are correct.
- *------------------------------------------------------------------------*/
- if (TtcConnectptrIndex >= TtcConnectFilesize) {
- TCKEY_abort(signal, 25);
- return;
- }//if
- TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
- OperationState TtcConnectstate = regTcPtr->tcConnectstate;
- tcConnectptr.i = TtcConnectptrIndex;
- tcConnectptr.p = regTcPtr;
- if (TtcConnectstate != OS_OPERATING) {
- warningReport(signal, 23);
- return;
- }//if
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
- UintR TapiConnectptrIndex = regTcPtr->apiConnect;
- UintR TapiConnectFilesize = capiConnectFilesize;
- UintR Ttrans1 = lqhKeyConf->transId1;
- UintR Ttrans2 = lqhKeyConf->transId2;
- Uint32 noFired = lqhKeyConf->noFiredTriggers;
-
- if (TapiConnectptrIndex >= TapiConnectFilesize) {
- TCKEY_abort(signal, 29);
- return;
- }//if
- Ptr<ApiConnectRecord> regApiPtr;
- regApiPtr.i = TapiConnectptrIndex;
- regApiPtr.p = &localApiConnectRecord[TapiConnectptrIndex];
- apiConnectptr.i = TapiConnectptrIndex;
- apiConnectptr.p = regApiPtr.p;
- compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
- compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- warningReport(signal, 24);
- return;
- }//if
-
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(8029)) {
- systemErrorLab(signal, __LINE__);
- }//if
- if (ERROR_INSERTED(8003)) {
- if (regApiPtr.p->apiConnectstate == CS_STARTED) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8004)) {
- if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8005)) {
- if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8006)) {
- if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- }//if
- if (ERROR_INSERTED(8023)) {
- SET_ERROR_INSERT_VALUE(8024);
- return;
- }//if
-#endif
- UintR TtcTimer = ctcTimer;
- regTcPtr->lastLqhCon = tlastLqhConnect;
- regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
- regTcPtr->noFiredTriggers = noFired;
-
- UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
- UintR TclientData = regTcPtr->clientData;
- UintR TdirtyOp = regTcPtr->dirtyOp;
- Uint32 TopSimple = regTcPtr->opSimple;
- Uint32 Toperation = regTcPtr->operation;
- ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
- if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
- TCKEY_abort(signal, 30);
- return;
- }
- if (TapiConnectstate == CS_ABORTING) {
- warningReport(signal, 27);
- return;
- }//if
-
- setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
-
- if (regTcPtr->isIndexOp) {
- jam();
- // This was an internal TCKEYREQ
- // will be returned unpacked
- regTcPtr->attrInfoLen = treadlenAi;
- } else {
- if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
- jam();
- /*
- * Skip counting triggering operations the first round
- * since they will enter execLQHKEYCONF a second time
- * Skip counting internally generated TcKeyReq
- */
- regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
- regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
- regApiPtr.p->tckeyrec = Ttckeyrec + 2;
- }//if
- }//if
- if (TdirtyOp == ZTRUE)
- {
- UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
- jam();
- releaseDirtyWrite(signal);
- regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
- }
- else if (Toperation == ZREAD && TopSimple)
- {
- UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
- jam();
- unlinkReadyTcCon(signal);
- releaseTcCon();
- regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
- }
- else
- {
- jam();
- if (noFired == 0) {
- jam();
- // No triggers to execute
- UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
- regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
- regTcPtr->tcConnectstate = OS_PREPARED;
- }
- }//if
-
- /**
- * And now decide what to do next
- */
- if (regTcPtr->triggeringOperation != RNIL) {
- jam();
- // This operation was created by a trigger execting operation
- // Restart it if we have executed all it's triggers
- TcConnectRecordPtr opPtr;
-
- opPtr.i = regTcPtr->triggeringOperation;
- ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
- opPtr.p->triggerExecutionCount--;
- if (opPtr.p->triggerExecutionCount == 0) {
- /*
- We have completed current trigger execution
- Continue triggering operation
- */
- jam();
- continueTriggeringOp(signal, opPtr.p);
- }
- } else if (noFired == 0) {
- // This operation did not fire any triggers, finish operation
- jam();
- if (regTcPtr->isIndexOp) {
- jam();
- setupIndexOpReturn(regApiPtr.p, regTcPtr);
- }
- lqhKeyConf_checkTransactionState(signal, regApiPtr);
- } else {
- // We have fired triggers
- jam();
- saveTriggeringOpState(signal, regTcPtr);
- if (regTcPtr->noReceivedTriggers == noFired)
- {
- // We have received all data
- jam();
- executeTriggers(signal, &regApiPtr);
- }
- // else wait for more trigger data
- }
-}//Dbtc::execLQHKEYCONF()
-
-void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
- TcConnectRecord* regTcPtr)
-{
- regApiPtr->indexOpReturn = true;
- regApiPtr->indexOp = regTcPtr->indexOp;
- regApiPtr->clientData = regTcPtr->clientData;
- regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
-}
-
-/**
- * lqhKeyConf_checkTransactionState
- *
- * This functions checks state variables, and
- * decides if it should wait for more LQHKEYCONF signals
- * or if it should start commiting
- */
-void
-Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
- Ptr<ApiConnectRecord> regApiPtr)
-{
-/*---------------------------------------------------------------*/
-/* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
-/* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN */
-/* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE */
-/* WHOLE TRANSACTION */
-/* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF */
-/* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
-/* TRANSACTION */
-/*---------------------------------------------------------------*/
- ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
- UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
- UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
- int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
-
- switch (TapiConnectstate) {
- case CS_START_COMMITTING:
- if (TnoOfOutStanding == 0) {
- jam();
- diverify010Lab(signal);
- return;
- } else if (TnoOfOutStanding > 0) {
- if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
- jam();
- sendtckeyconf(signal, 0);
- return;
- } else if (regApiPtr.p->indexOpReturn) {
- jam();
- sendtckeyconf(signal, 0);
- return;
- }//if
- jam();
- return;
- } else {
- TCKEY_abort(signal, 44);
- return;
- }//if
- return;
- case CS_STARTED:
- case CS_RECEIVING:
- if (TnoOfOutStanding == 0) {
- jam();
- sendtckeyconf(signal, 2);
- return;
- } else {
- if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
- jam();
- sendtckeyconf(signal, 0);
- return;
- } else if (regApiPtr.p->indexOpReturn) {
- jam();
- sendtckeyconf(signal, 0);
- return;
- }//if
- jam();
- }//if
- return;
- case CS_REC_COMMITTING:
- if (TnoOfOutStanding > 0) {
- if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
- jam();
- sendtckeyconf(signal, 0);
- return;
- } else if (regApiPtr.p->indexOpReturn) {
- jam();
- sendtckeyconf(signal, 0);
- return;
- }//if
- jam();
- return;
- }//if
- TCKEY_abort(signal, 45);
- return;
- case CS_CONNECTED:
- jam();
-/*---------------------------------------------------------------*/
-/* WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY */
-/* CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE */
-/* COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS. */
-/*---------------------------------------------------------------*/
- regApiPtr.p->tckeyrec = 0;
- return;
- default:
- TCKEY_abort(signal, 46);
- return;
- }//switch
-}//Dbtc::lqhKeyConf_checkTransactionState()
-
-void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
-{
- if(ERROR_INSERTED(8049)){
- CLEAR_ERROR_INSERT_VALUE;
- signal->theData[0] = TcContinueB::DelayTCKEYCONF;
- signal->theData[1] = apiConnectptr.i;
- signal->theData[2] = TcommitFlag;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
- return;
- }
-
- HostRecordPtr localHostptr;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- const UintR TopWords = (UintR)regApiPtr->tckeyrec;
- localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
- const Uint32 type = getNodeInfo(localHostptr.i).m_type;
- const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
- const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
- const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
- ptrAss(localHostptr, hostRecord);
- UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF;
- UintR confInfo = 0;
- TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
- TcKeyConf::setMarkerFlag(confInfo, Tmarker);
- const UintR TpacketLen = 6 + TopWords;
- regApiPtr->tckeyrec = 0;
-
- if (regApiPtr->indexOpReturn) {
- jam();
- // Return internally generated TCKEY
- TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
- TcKeyConf::setNoOfOperations(confInfo, 1);
- tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
- tcKeyConf->gci = regApiPtr->globalcheckpointid;
- tcKeyConf->confInfo = confInfo;
- tcKeyConf->transId1 = regApiPtr->transid[0];
- tcKeyConf->transId2 = regApiPtr->transid[1];
- tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
- tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
- Uint32 sigLen = TcKeyConf::StaticLength + TcKeyConf::OperationLength;
- EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
- regApiPtr->indexOpReturn = false;
- if (TopWords == 0) {
- jam();
- return; // No queued TcKeyConf
- }//if
- }//if
- if(TcommitFlag){
- jam();
- regApiPtr->m_exec_flag = 0;
- }
- TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
- if ((TpacketLen > 25) || !is_api){
- TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
-
- jam();
- tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
- tcKeyConf->gci = regApiPtr->globalcheckpointid;;
- tcKeyConf->confInfo = confInfo;
- tcKeyConf->transId1 = regApiPtr->transid[0];
- tcKeyConf->transId2 = regApiPtr->transid[1];
- copyFromToLen(&regApiPtr->tcSendArray[0],
- (UintR*)&tcKeyConf->operations,
- (UintR)ZTCOPCONF_SIZE);
- sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCKEYCONF, signal, (TpacketLen - 1), JBB);
- return;
- } else if (((TcurrLen + TpacketLen) > 25) && (TcurrLen > 0)) {
- jam();
- sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
- TcurrLen = 0;
- } else {
- jam();
- updatePackedList(signal, localHostptr.p, localHostptr.i);
- }//if
- // -------------------------------------------------------------------------
- // The header contains the block reference of receiver plus the real signal
- // length - 3, since we have the real signal length plus one additional word
- // for the header we have to do - 4.
- // -------------------------------------------------------------------------
- UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
- UintR Tpack1 = regApiPtr->ndbapiConnect;
- UintR Tpack2 = regApiPtr->globalcheckpointid;
- UintR Tpack3 = confInfo;
- UintR Tpack4 = regApiPtr->transid[0];
- UintR Tpack5 = regApiPtr->transid[1];
-
- localHostptr.p->noOfWordsTCKEYCONF = TcurrLen + TpacketLen;
-
- localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 0] = Tpack0;
- localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 1] = Tpack1;
- localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 2] = Tpack2;
- localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 3] = Tpack3;
- localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 4] = Tpack4;
- localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 5] = Tpack5;
-
- UintR Ti;
- for (Ti = 6; Ti < TpacketLen; Ti++) {
- localHostptr.p->packedWordsTCKEYCONF[TcurrLen + Ti] =
- regApiPtr->tcSendArray[Ti - 6];
- }//for
-}//Dbtc::sendtckeyconf()
-
-void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
-{
- UintR Tindex = 0;
- UintR Ti;
- while (Tlen >= 4) {
- UintR Tdata0 = sourceBuffer[Tindex + 0];
- UintR Tdata1 = sourceBuffer[Tindex + 1];
- UintR Tdata2 = sourceBuffer[Tindex + 2];
- UintR Tdata3 = sourceBuffer[Tindex + 3];
- Tlen -= 4;
- destBuffer[Tindex + 0] = Tdata0;
- destBuffer[Tindex + 1] = Tdata1;
- destBuffer[Tindex + 2] = Tdata2;
- destBuffer[Tindex + 3] = Tdata3;
- Tindex += 4;
- }//while
- for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
- destBuffer[Tindex] = sourceBuffer[Tindex];
- }//for
-}//Dbtc::copyFromToLen()
-
-void Dbtc::execSEND_PACKED(Signal* signal)
-{
- HostRecordPtr Thostptr;
- HostRecord *localHostRecord = hostRecord;
- UintR i;
- UintR TpackedListIndex = cpackedListIndex;
- jamEntry();
- for (i = 0; i < TpackedListIndex; i++) {
- Thostptr.i = cpackedList[i];
- ptrAss(Thostptr, localHostRecord);
- arrGuard(Thostptr.i - 1, MAX_NODES - 1);
- UintR TnoOfPackedWordsLqh = Thostptr.p->noOfPackedWordsLqh;
- UintR TnoOfWordsTCKEYCONF = Thostptr.p->noOfWordsTCKEYCONF;
- UintR TnoOfWordsTCINDXCONF = Thostptr.p->noOfWordsTCINDXCONF;
- jam();
- if (TnoOfPackedWordsLqh > 0) {
- jam();
- sendPackedSignalLqh(signal, Thostptr.p);
- }//if
- if (TnoOfWordsTCKEYCONF > 0) {
- jam();
- sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
- }//if
- if (TnoOfWordsTCINDXCONF > 0) {
- jam();
- sendPackedTCINDXCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
- }//if
- Thostptr.p->inPackedList = false;
- }//for
- cpackedListIndex = 0;
- return;
-}//Dbtc::execSEND_PACKED()
-
-void
-Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
-{
- if (ahostptr->inPackedList == false) {
- UintR TpackedListIndex = cpackedListIndex;
- jam();
- ahostptr->inPackedList = true;
- cpackedList[TpackedListIndex] = ahostIndex;
- cpackedListIndex = TpackedListIndex + 1;
- }//if
-}//Dbtc::updatePackedList()
-
-void Dbtc::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
-{
- UintR Tj;
- UintR TnoOfWords = ahostptr->noOfPackedWordsLqh;
- for (Tj = 0; Tj < TnoOfWords; Tj += 4) {
- UintR sig0 = ahostptr->packedWordsLqh[Tj + 0];
- UintR sig1 = ahostptr->packedWordsLqh[Tj + 1];
- UintR sig2 = ahostptr->packedWordsLqh[Tj + 2];
- UintR sig3 = ahostptr->packedWordsLqh[Tj + 3];
- signal->theData[Tj + 0] = sig0;
- signal->theData[Tj + 1] = sig1;
- signal->theData[Tj + 2] = sig2;
- signal->theData[Tj + 3] = sig3;
- }//for
- ahostptr->noOfPackedWordsLqh = 0;
- sendSignal(ahostptr->hostLqhBlockRef,
- GSN_PACKED_SIGNAL,
- signal,
- TnoOfWords,
- JBB);
-}//Dbtc::sendPackedSignalLqh()
-
-void Dbtc::sendPackedTCKEYCONF(Signal* signal,
- HostRecord * ahostptr,
- UintR hostId)
-{
- UintR Tj;
- UintR TnoOfWords = ahostptr->noOfWordsTCKEYCONF;
- BlockReference TBref = numberToRef(API_PACKED, hostId);
- for (Tj = 0; Tj < ahostptr->noOfWordsTCKEYCONF; Tj += 4) {
- UintR sig0 = ahostptr->packedWordsTCKEYCONF[Tj + 0];
- UintR sig1 = ahostptr->packedWordsTCKEYCONF[Tj + 1];
- UintR sig2 = ahostptr->packedWordsTCKEYCONF[Tj + 2];
- UintR sig3 = ahostptr->packedWordsTCKEYCONF[Tj + 3];
- signal->theData[Tj + 0] = sig0;
- signal->theData[Tj + 1] = sig1;
- signal->theData[Tj + 2] = sig2;
- signal->theData[Tj + 3] = sig3;
- }//for
- ahostptr->noOfWordsTCKEYCONF = 0;
- sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
-}//Dbtc::sendPackedTCKEYCONF()
-
-void Dbtc::sendPackedTCINDXCONF(Signal* signal,
- HostRecord * ahostptr,
- UintR hostId)
-{
- UintR Tj;
- UintR TnoOfWords = ahostptr->noOfWordsTCINDXCONF;
- BlockReference TBref = numberToRef(API_PACKED, hostId);
- for (Tj = 0; Tj < ahostptr->noOfWordsTCINDXCONF; Tj += 4) {
- UintR sig0 = ahostptr->packedWordsTCINDXCONF[Tj + 0];
- UintR sig1 = ahostptr->packedWordsTCINDXCONF[Tj + 1];
- UintR sig2 = ahostptr->packedWordsTCINDXCONF[Tj + 2];
- UintR sig3 = ahostptr->packedWordsTCINDXCONF[Tj + 3];
- signal->theData[Tj + 0] = sig0;
- signal->theData[Tj + 1] = sig1;
- signal->theData[Tj + 2] = sig2;
- signal->theData[Tj + 3] = sig3;
- }//for
- ahostptr->noOfWordsTCINDXCONF = 0;
- sendSignal(TBref, GSN_TCINDXCONF, signal, TnoOfWords, JBB);
-}//Dbtc::sendPackedTCINDXCONF()
-
-/*
-4.3.11 DIVERIFY
----------------
-*/
-/*****************************************************************************/
-/* D I V E R I F Y */
-/* */
-/*****************************************************************************/
-void Dbtc::diverify010Lab(Signal* signal)
-{
- UintR TfirstfreeApiConnectCopy = cfirstfreeApiConnectCopy;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- signal->theData[0] = apiConnectptr.i;
- if (ERROR_INSERTED(8022)) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
-
- if (regApiPtr->lqhkeyreqrec)
- {
- if (TfirstfreeApiConnectCopy != RNIL) {
- seizeApiConnectCopy(signal);
- regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
- /*-----------------------------------------------------------------------
- * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
- * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
- * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
- * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
- *---------------------------------------------------------------------*/
- EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal, 1);
- if (signal->theData[2] == 0) {
- execDIVERIFYCONF(signal);
- }
- return;
- } else {
- /*-----------------------------------------------------------------------
- * There were no free copy connections available. We must abort the
- * transaction since otherwise we will have a problem with the report
- * to the application.
- * This should more or less not happen but if it happens we do
- * not want to crash and we do not want to create code to handle it
- * properly since it is difficult to test it and will be complex to
- * handle a problem more or less not occurring.
- *---------------------------------------------------------------------*/
- terrorCode = ZSEIZE_API_COPY_ERROR;
- abortErrorLab(signal);
- return;
- }
- }
- else
- {
- jam();
- sendtckeyconf(signal, 1);
- regApiPtr->apiConnectstate = CS_CONNECTED;
- regApiPtr->m_transaction_nodes.clear();
- setApiConTimer(apiConnectptr.i, 0,__LINE__);
- }
-}//Dbtc::diverify010Lab()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEIZE_API_CONNECT ------- */
-/* SEIZE CONNECT RECORD FOR A REQUEST */
-/* ------------------------------------------------------------------------- */
-void Dbtc::seizeApiConnectCopy(Signal* signal)
-{
- ApiConnectRecordPtr locApiConnectptr;
-
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
- UintR TapiConnectFilesize = capiConnectFilesize;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
-
- locApiConnectptr.i = cfirstfreeApiConnectCopy;
- ptrCheckGuard(locApiConnectptr, TapiConnectFilesize, localApiConnectRecord);
- cfirstfreeApiConnectCopy = locApiConnectptr.p->nextApiConnect;
- locApiConnectptr.p->nextApiConnect = RNIL;
- regApiPtr->apiCopyRecord = locApiConnectptr.i;
- regApiPtr->triggerPending = false;
- regApiPtr->isIndexOp = false;
-}//Dbtc::seizeApiConnectCopy()
-
-void Dbtc::execDIVERIFYCONF(Signal* signal)
-{
- UintR TapiConnectptrIndex = signal->theData[0];
- UintR TapiConnectFilesize = capiConnectFilesize;
- UintR Tgci = signal->theData[1];
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
- jamEntry();
- if (ERROR_INSERTED(8017)) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- if (TapiConnectptrIndex >= TapiConnectFilesize) {
- TCKEY_abort(signal, 31);
- return;
- }//if
- ApiConnectRecord * const regApiPtr =
- &localApiConnectRecord[TapiConnectptrIndex];
- ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
- UintR TApifailureNr = regApiPtr->failureNr;
- UintR Tfailure_nr = cfailure_nr;
- apiConnectptr.i = TapiConnectptrIndex;
- apiConnectptr.p = regApiPtr;
- if (TapiConnectstate != CS_PREPARE_TO_COMMIT) {
- TCKEY_abort(signal, 32);
- return;
- }//if
- /*--------------------------------------------------------------------------
- * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
- * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
- * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
- * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
- * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
- *-------------------------------------------------------------------------*/
- if (TApifailureNr != Tfailure_nr) {
- DIVER_node_fail_handling(signal, Tgci);
- return;
- }//if
- commitGciHandling(signal, Tgci);
-
- /**************************************************************************
- * C O M M I T
- * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
- **************************************************************************/
-
- UintR TtcConnectptrIndex = regApiPtr->firstTcConnect;
- UintR TtcConnectFilesize = ctcConnectFilesize;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
-
- regApiPtr->counter = regApiPtr->lqhkeyconfrec;
- regApiPtr->apiConnectstate = CS_COMMITTING;
- if (TtcConnectptrIndex >= TtcConnectFilesize) {
- TCKEY_abort(signal, 33);
- return;
- }//if
- TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
- tcConnectptr.i = TtcConnectptrIndex;
- tcConnectptr.p = regTcPtr;
- commit020Lab(signal);
-}//Dbtc::execDIVERIFYCONF()
-
-/*--------------------------------------------------------------------------*/
-/* COMMIT_GCI_HANDLING */
-/* SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT. */
-/*--------------------------------------------------------------------------*/
-void Dbtc::commitGciHandling(Signal* signal, UintR Tgci)
-{
- GcpRecordPtr localGcpPointer;
-
- UintR TgcpFilesize = cgcpFilesize;
- UintR Tfirstgcp = cfirstgcp;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- GcpRecord *localGcpRecord = gcpRecord;
-
- regApiPtr->globalcheckpointid = Tgci;
- if (Tfirstgcp != RNIL) {
- /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
- localGcpPointer.i = Tfirstgcp;
- ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
- do {
- if (regApiPtr->globalcheckpointid == localGcpPointer.p->gcpId) {
- jam();
- gcpPtr.i = localGcpPointer.i;
- gcpPtr.p = localGcpPointer.p;
- linkApiToGcp(signal);
- return;
- } else {
- localGcpPointer.i = localGcpPointer.p->nextGcp;
- jam();
- if (localGcpPointer.i != RNIL) {
- jam();
- ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
- continue;
- }//if
- }//if
- seizeGcp(signal);
- linkApiToGcp(signal);
- return;
- } while (1);
- } else {
- jam();
- seizeGcp(signal);
- linkApiToGcp(signal);
- }//if
-}//Dbtc::commitGciHandling()
-
-/* --------------------------------------------------------------------------*/
-/* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
-/* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS */
-/* LINKED OUT OF THE LIST. */
-/*---------------------------------------------------------------------------*/
-void Dbtc::linkApiToGcp(Signal* signal)
-{
- ApiConnectRecordPtr localApiConnectptr;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- GcpRecord * const regGcpPtr = gcpPtr.p;
- UintR TapiConnectptrIndex = apiConnectptr.i;
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
- regApiPtr->nextGcpConnect = RNIL;
- if (regGcpPtr->firstApiConnect == RNIL) {
- regGcpPtr->firstApiConnect = TapiConnectptrIndex;
- jam();
- } else {
- UintR TapiConnectFilesize = capiConnectFilesize;
- localApiConnectptr.i = regGcpPtr->lastApiConnect;
- jam();
- ptrCheckGuard(localApiConnectptr,
- TapiConnectFilesize, localApiConnectRecord);
- localApiConnectptr.p->nextGcpConnect = TapiConnectptrIndex;
- }//if
- UintR TlastApiConnect = regGcpPtr->lastApiConnect;
- regApiPtr->gcpPointer = gcpPtr.i;
- regApiPtr->prevGcpConnect = TlastApiConnect;
- regGcpPtr->lastApiConnect = TapiConnectptrIndex;
-}//Dbtc::linkApiToGcp()
-
-void Dbtc::seizeGcp(Signal* signal)
-{
- GcpRecordPtr tmpGcpPointer;
- GcpRecordPtr localGcpPointer;
-
- UintR Tfirstgcp = cfirstgcp;
- UintR Tglobalcheckpointid = apiConnectptr.p->globalcheckpointid;
- UintR TgcpFilesize = cgcpFilesize;
- GcpRecord *localGcpRecord = gcpRecord;
-
- localGcpPointer.i = cfirstfreeGcp;
- ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
- UintR TfirstfreeGcp = localGcpPointer.p->nextGcp;
- localGcpPointer.p->gcpId = Tglobalcheckpointid;
- localGcpPointer.p->nextGcp = RNIL;
- localGcpPointer.p->firstApiConnect = RNIL;
- localGcpPointer.p->lastApiConnect = RNIL;
- localGcpPointer.p->gcpNomoretransRec = ZFALSE;
- cfirstfreeGcp = TfirstfreeGcp;
-
- if (Tfirstgcp == RNIL) {
- jam();
- cfirstgcp = localGcpPointer.i;
- } else {
- tmpGcpPointer.i = clastgcp;
- jam();
- ptrCheckGuard(tmpGcpPointer, TgcpFilesize, localGcpRecord);
- tmpGcpPointer.p->nextGcp = localGcpPointer.i;
- }//if
- clastgcp = localGcpPointer.i;
- gcpPtr = localGcpPointer;
-}//Dbtc::seizeGcp()
-
-/*---------------------------------------------------------------------------*/
-// Send COMMIT messages to all LQH operations involved in the transaction.
-/*---------------------------------------------------------------------------*/
-void Dbtc::commit020Lab(Signal* signal)
-{
- TcConnectRecordPtr localTcConnectptr;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- UintR TtcConnectFilesize = ctcConnectFilesize;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
-
- localTcConnectptr.p = tcConnectptr.p;
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- UintR Tcount = 0;
- do {
- /*-----------------------------------------------------------------------
- * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
- *-----------------------------------------------------------------------*/
- /* *********< */
- /* COMMIT < */
- /* *********< */
- localTcConnectptr.i = localTcConnectptr.p->nextTcConnect;
- localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
- sendCommitLqh(signal, localTcConnectptr.p);
-
- if (localTcConnectptr.i != RNIL) {
- Tcount = Tcount + 1;
- if (Tcount < 16 && !ERROR_INSERTED(8057)) {
- ptrCheckGuard(localTcConnectptr,
- TtcConnectFilesize, localTcConnectRecord);
- jam();
- continue;
- } else {
- jam();
- if (ERROR_INSERTED(8014)) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
- signal->theData[1] = apiConnectptr.i;
- signal->theData[2] = localTcConnectptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- return;
- }//if
- } else {
- jam();
- if (ERROR_INSERTED(8057))
- CLEAR_ERROR_INSERT_VALUE;
-
- regApiPtr->apiConnectstate = CS_COMMIT_SENT;
- return;
- }//if
- } while (1);
-}//Dbtc::commit020Lab()
-
-void Dbtc::sendCommitLqh(Signal* signal,
- TcConnectRecord * const regTcPtr)
-{
- HostRecordPtr Thostptr;
- UintR ThostFilesize = chostFilesize;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- Thostptr.i = regTcPtr->lastLqhNodeId;
- ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
- if (Thostptr.p->noOfPackedWordsLqh > 21) {
- jam();
- sendPackedSignalLqh(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
- UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
- UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
- UintR Tdata1 = regTcPtr->lastLqhCon;
- UintR Tdata2 = regApiPtr->globalcheckpointid;
- UintR Tdata3 = regApiPtr->transid[0];
- UintR Tdata4 = regApiPtr->transid[1];
-
- TDataPtr[0] = Tdata1 | (ZCOMMIT << 28);
- TDataPtr[1] = Tdata2;
- TDataPtr[2] = Tdata3;
- TDataPtr[3] = Tdata4;
- Thostptr.p->noOfPackedWordsLqh = Tindex + 4;
-}//Dbtc::sendCommitLqh()
-
-void
-Dbtc::DIVER_node_fail_handling(Signal* signal, UintR Tgci)
-{
- /*------------------------------------------------------------------------
- * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
- * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
- * ABORT AND THE COMMIT CASES WE NEED TO SET-UP THE DATA FOR THE
- * ABORT/COMMIT/COMPLETE HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
- *------------------------------------------------------------------------*/
- tabortInd = ZFALSE;
- setupFailData(signal);
- if (false && tabortInd == ZFALSE) {
- jam();
- commitGciHandling(signal, Tgci);
- toCommitHandlingLab(signal);
- } else {
- jam();
- apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
- apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
- toAbortHandlingLab(signal);
- }//if
- return;
-}//Dbtc::DIVER_node_fail_handling()
-
-
-/* ------------------------------------------------------------------------- */
-/* ------- ENTER COMMITTED ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dbtc::execCOMMITTED(Signal* signal)
-{
- TcConnectRecordPtr localTcConnectptr;
- ApiConnectRecordPtr localApiConnectptr;
-
- UintR TtcConnectFilesize = ctcConnectFilesize;
- UintR TapiConnectFilesize = capiConnectFilesize;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(8018)) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- if (ERROR_INSERTED(8030)) {
- systemErrorLab(signal, __LINE__);
- }//if
- if (ERROR_INSERTED(8025)) {
- SET_ERROR_INSERT_VALUE(8026);
- return;
- }//if
- if (ERROR_INSERTED(8041)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
- return;
- }//if
- if (ERROR_INSERTED(8042)) {
- SET_ERROR_INSERT_VALUE(8046);
- sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
- return;
- }//if
-#endif
- localTcConnectptr.i = signal->theData[0];
- jamEntry();
- ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
- localApiConnectptr.i = localTcConnectptr.p->apiConnect;
- if (localTcConnectptr.p->tcConnectstate != OS_COMMITTING) {
- warningReport(signal, 4);
- return;
- }//if
- ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
- localApiConnectRecord);
- UintR Tcounter = localApiConnectptr.p->counter - 1;
- ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
- UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
- UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
- Tdata1 = Tdata1 | Tdata2;
- bool TcheckCondition =
- (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
-
- setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
- localApiConnectptr.p->counter = Tcounter;
- localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
- if (Tdata1 != 0) {
- warningReport(signal, 5);
- return;
- }//if
- if (TcheckCondition) {
- jam();
- /*-------------------------------------------------------*/
- // We have not sent all COMMIT requests yet. We could be
- // in the state that all sent are COMMITTED but we are
- // still waiting for a CONTINUEB to send the rest of the
- // COMMIT requests.
- /*-------------------------------------------------------*/
- return;
- }//if
- if (ERROR_INSERTED(8020)) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- /*-------------------------------------------------------*/
- /* THE ENTIRE TRANSACTION IS NOW COMMITED */
- /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION. */
- /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
- /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A */
- /* NEW API CONNECT RECORD. */
- /*-------------------------------------------------------*/
-
- apiConnectptr = localApiConnectptr;
- sendApiCommit(signal);
-
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- localTcConnectptr.i = regApiPtr->firstTcConnect;
- UintR Tlqhkeyconfrec = regApiPtr->lqhkeyconfrec;
- ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
- regApiPtr->counter = Tlqhkeyconfrec;
-
- tcConnectptr = localTcConnectptr;
- complete010Lab(signal);
- return;
-
-}//Dbtc::execCOMMITTED()
-
-/*-------------------------------------------------------*/
-/* SEND_API_COMMIT */
-/* SEND COMMIT DECISION TO THE API. */
-/*-------------------------------------------------------*/
-void Dbtc::sendApiCommit(Signal* signal)
-{
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
-
- if (regApiPtr->returnsignal == RS_TCKEYCONF) {
- sendtckeyconf(signal, 1);
- } else if (regApiPtr->returnsignal == RS_TC_COMMITCONF) {
- jam();
- TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
- if(regApiPtr->commitAckMarker == RNIL){
- jam();
- commitConf->apiConnectPtr = regApiPtr->ndbapiConnect;
- } else {
- jam();
- commitConf->apiConnectPtr = regApiPtr->ndbapiConnect | 1;
- }
- commitConf->transId1 = regApiPtr->transid[0];
- commitConf->transId2 = regApiPtr->transid[1];
- commitConf->gci = regApiPtr->globalcheckpointid;
-
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
- TcCommitConf::SignalLength, JBB);
- } else if (regApiPtr->returnsignal == RS_NO_RETURN) {
- jam();
- } else {
- TCKEY_abort(signal, 37);
- return;
- }//if
- UintR TapiConnectFilesize = capiConnectFilesize;
- UintR TcommitCount = c_counters.ccommitCount;
- UintR TapiIndex = apiConnectptr.i;
- UintR TnewApiIndex = regApiPtr->apiCopyRecord;
- UintR TapiFailState = regApiPtr->apiFailState;
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
- tmpApiConnectptr.p = apiConnectptr.p;
- tmpApiConnectptr.i = TapiIndex;
- c_counters.ccommitCount = TcommitCount + 1;
- apiConnectptr.i = TnewApiIndex;
- ptrCheckGuard(apiConnectptr, TapiConnectFilesize, localApiConnectRecord);
- copyApi(signal);
- if (TapiFailState != ZTRUE) {
- return;
- } else {
- jam();
- handleApiFailState(signal, tmpApiConnectptr.i);
- return;
- }//if
-}//Dbtc::sendApiCommit()
-
-/* ========================================================================= */
-/* ======= COPY_API ======= */
-/* COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT */
-/* IS PREPARED TO RECEIVE A NEW TRANSACTION. */
-/*===========================================================================*/
-void Dbtc::copyApi(Signal* signal)
-{
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p;
-
- UintR TndbapiConnect = regTmpApiPtr->ndbapiConnect;
- UintR TfirstTcConnect = regTmpApiPtr->firstTcConnect;
- UintR Ttransid1 = regTmpApiPtr->transid[0];
- UintR Ttransid2 = regTmpApiPtr->transid[1];
- UintR Tlqhkeyconfrec = regTmpApiPtr->lqhkeyconfrec;
- UintR TgcpPointer = regTmpApiPtr->gcpPointer;
- UintR TgcpFilesize = cgcpFilesize;
- UintR TcommitAckMarker = regTmpApiPtr->commitAckMarker;
- NdbNodeBitmask Tnodes = regTmpApiPtr->m_transaction_nodes;
- GcpRecord *localGcpRecord = gcpRecord;
-
- regApiPtr->ndbapiBlockref = regTmpApiPtr->ndbapiBlockref;
- regApiPtr->ndbapiConnect = TndbapiConnect;
- regApiPtr->firstTcConnect = TfirstTcConnect;
- regApiPtr->apiConnectstate = CS_COMPLETING;
- regApiPtr->transid[0] = Ttransid1;
- regApiPtr->transid[1] = Ttransid2;
- regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec;
- regApiPtr->commitAckMarker = TcommitAckMarker;
- regApiPtr->m_transaction_nodes = Tnodes;
- regApiPtr->singleUserMode = 0;
-
- gcpPtr.i = TgcpPointer;
- ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
- unlinkApiConnect(signal);
- linkApiToGcp(signal);
- setApiConTimer(tmpApiConnectptr.i, 0, __LINE__);
- regTmpApiPtr->apiConnectstate = CS_CONNECTED;
- regTmpApiPtr->commitAckMarker = RNIL;
- regTmpApiPtr->firstTcConnect = RNIL;
- regTmpApiPtr->lastTcConnect = RNIL;
- regTmpApiPtr->m_transaction_nodes.clear();
- regTmpApiPtr->singleUserMode = 0;
- releaseAllSeizedIndexOperations(regTmpApiPtr);
-}//Dbtc::copyApi()
-
-void Dbtc::unlinkApiConnect(Signal* signal)
-{
- ApiConnectRecordPtr localApiConnectptr;
- ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p;
- UintR TapiConnectFilesize = capiConnectFilesize;
- UintR TprevGcpConnect = regTmpApiPtr->prevGcpConnect;
- UintR TnextGcpConnect = regTmpApiPtr->nextGcpConnect;
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
- if (TprevGcpConnect == RNIL) {
- gcpPtr.p->firstApiConnect = TnextGcpConnect;
- jam();
- } else {
- localApiConnectptr.i = TprevGcpConnect;
- jam();
- ptrCheckGuard(localApiConnectptr,
- TapiConnectFilesize, localApiConnectRecord);
- localApiConnectptr.p->nextGcpConnect = TnextGcpConnect;
- }//if
- if (TnextGcpConnect == RNIL) {
- gcpPtr.p->lastApiConnect = TprevGcpConnect;
- jam();
- } else {
- localApiConnectptr.i = TnextGcpConnect;
- jam();
- ptrCheckGuard(localApiConnectptr,
- TapiConnectFilesize, localApiConnectRecord);
- localApiConnectptr.p->prevGcpConnect = TprevGcpConnect;
- }//if
-}//Dbtc::unlinkApiConnect()
-
-void Dbtc::complete010Lab(Signal* signal)
-{
- TcConnectRecordPtr localTcConnectptr;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- UintR TtcConnectFilesize = ctcConnectFilesize;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
-
- localTcConnectptr.p = tcConnectptr.p;
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- UintR TapiConnectptrIndex = apiConnectptr.i;
- UintR Tcount = 0;
- do {
- localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
- localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
-
- /* ************ */
- /* COMPLETE < */
- /* ************ */
- const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
- sendCompleteLqh(signal, localTcConnectptr.p);
- localTcConnectptr.i = nextTcConnect;
- if (localTcConnectptr.i != RNIL) {
- Tcount++;
- if (Tcount < 16) {
- ptrCheckGuard(localTcConnectptr,
- TtcConnectFilesize, localTcConnectRecord);
- jam();
- continue;
- } else {
- jam();
- if (ERROR_INSERTED(8013)) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
- signal->theData[1] = apiConnectptr.i;
- signal->theData[2] = localTcConnectptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- return;
- }//if
- } else {
- jam();
- regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
- return;
- }//if
- } while (1);
-}//Dbtc::complete010Lab()
-
-void Dbtc::sendCompleteLqh(Signal* signal,
- TcConnectRecord * const regTcPtr)
-{
- HostRecordPtr Thostptr;
- UintR ThostFilesize = chostFilesize;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- Thostptr.i = regTcPtr->lastLqhNodeId;
- ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
- if (Thostptr.p->noOfPackedWordsLqh > 22) {
- jam();
- sendPackedSignalLqh(signal, Thostptr.p);
- } else {
- jam();
- updatePackedList(signal, Thostptr.p, Thostptr.i);
- }//if
-
- UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
- UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
- UintR Tdata1 = regTcPtr->lastLqhCon | (ZCOMPLETE << 28);
- UintR Tdata2 = regApiPtr->transid[0];
- UintR Tdata3 = regApiPtr->transid[1];
-
- TDataPtr[0] = Tdata1;
- TDataPtr[1] = Tdata2;
- TDataPtr[2] = Tdata3;
- Thostptr.p->noOfPackedWordsLqh = Tindex + 3;
-}//Dbtc::sendCompleteLqh()
-
-void
-Dbtc::execTC_COMMIT_ACK(Signal* signal){
- jamEntry();
-
- CommitAckMarker key;
- key.transid1 = signal->theData[0];
- key.transid2 = signal->theData[1];
-
- CommitAckMarkerPtr removedMarker;
- m_commitAckMarkerHash.remove(removedMarker, key);
- if (removedMarker.i == RNIL) {
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }//if
- sendRemoveMarkers(signal, removedMarker.p);
- m_commitAckMarkerPool.release(removedMarker);
-}
-
-void
-Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker){
- jam();
- const Uint32 noOfLqhs = marker->noOfLqhs;
- const Uint32 transId1 = marker->transid1;
- const Uint32 transId2 = marker->transid2;
-
- for(Uint32 i = 0; i<noOfLqhs; i++){
- jam();
- const NodeId nodeId = marker->lqhNodeId[i];
- sendRemoveMarker(signal, nodeId, transId1, transId2);
- }
-}
-
-void
-Dbtc::sendRemoveMarker(Signal* signal,
- NodeId nodeId,
- Uint32 transid1,
- Uint32 transid2){
- /**
- * Seize host ptr
- */
- HostRecordPtr hostPtr;
- const UintR ThostFilesize = chostFilesize;
- hostPtr.i = nodeId;
- ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
-
- if (hostPtr.p->noOfPackedWordsLqh > (25 - 3)){
- jam();
- sendPackedSignalLqh(signal, hostPtr.p);
- } else {
- jam();
- updatePackedList(signal, hostPtr.p, hostPtr.i);
- }//if
-
- UintR numWord = hostPtr.p->noOfPackedWordsLqh;
- UintR* dataPtr = &hostPtr.p->packedWordsLqh[numWord];
-
- dataPtr[0] = (ZREMOVE_MARKER << 28);
- dataPtr[1] = transid1;
- dataPtr[2] = transid2;
- hostPtr.p->noOfPackedWordsLqh = numWord + 3;
-}
-
-void Dbtc::execCOMPLETED(Signal* signal)
-{
- TcConnectRecordPtr localTcConnectptr;
- ApiConnectRecordPtr localApiConnectptr;
-
- UintR TtcConnectFilesize = ctcConnectFilesize;
- UintR TapiConnectFilesize = capiConnectFilesize;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(8031)) {
- systemErrorLab(signal, __LINE__);
- }//if
- if (ERROR_INSERTED(8019)) {
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }//if
- if (ERROR_INSERTED(8027)) {
- SET_ERROR_INSERT_VALUE(8028);
- return;
- }//if
- if (ERROR_INSERTED(8043)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
- return;
- }//if
- if (ERROR_INSERTED(8044)) {
- SET_ERROR_INSERT_VALUE(8047);
- sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
- return;
- }//if
-#endif
- localTcConnectptr.i = signal->theData[0];
- jamEntry();
- ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
- bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
- localApiConnectptr.i = localTcConnectptr.p->apiConnect;
- if (Tcond1) {
- warningReport(signal, 6);
- return;
- }//if
- ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
- localApiConnectRecord);
- UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
- UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
- UintR Tcounter = localApiConnectptr.p->counter - 1;
- ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
- Tdata1 = Tdata1 | Tdata2;
- bool TcheckCondition =
- (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
- if (Tdata1 != 0) {
- warningReport(signal, 7);
- return;
- }//if
- setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
- localApiConnectptr.p->counter = Tcounter;
- localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
- localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
- if (TcheckCondition) {
- jam();
- /*-------------------------------------------------------*/
- // We have not sent all COMPLETE requests yet. We could be
- // in the state that all sent are COMPLETED but we are
- // still waiting for a CONTINUEB to send the rest of the
- // COMPLETE requests.
- /*-------------------------------------------------------*/
- return;
- }//if
- if (ERROR_INSERTED(8021)) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- apiConnectptr = localApiConnectptr;
- releaseTransResources(signal);
-}//Dbtc::execCOMPLETED()
-
-/*---------------------------------------------------------------------------*/
-/* RELEASE_TRANS_RESOURCES */
-/* RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION. */
-/*---------------------------------------------------------------------------*/
-void Dbtc::releaseTransResources(Signal* signal)
-{
- TcConnectRecordPtr localTcConnectptr;
- UintR TtcConnectFilesize = ctcConnectFilesize;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
- apiConnectptr.p->m_transaction_nodes.clear();
- localTcConnectptr.i = apiConnectptr.p->firstTcConnect;
- do {
- jam();
- ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
- UintR rtrTcConnectptrIndex = localTcConnectptr.p->nextTcConnect;
- tcConnectptr.i = localTcConnectptr.i;
- tcConnectptr.p = localTcConnectptr.p;
- localTcConnectptr.i = rtrTcConnectptrIndex;
- releaseTcCon();
- } while (localTcConnectptr.i != RNIL);
- handleGcp(signal);
- releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
- releaseAllSeizedIndexOperations(apiConnectptr.p);
- releaseApiConCopy(signal);
-}//Dbtc::releaseTransResources()
-
-/* *********************************************************************>> */
-/* MODULE: HANDLE_GCP */
-/* DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
-/* OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC */
-/* SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
-/* GLOBAL CHECKPOINT HAVE COMPLETED. */
-/* *********************************************************************>> */
-void Dbtc::handleGcp(Signal* signal)
-{
- GcpRecord *localGcpRecord = gcpRecord;
- GcpRecordPtr localGcpPtr;
- UintR TapiConnectptrIndex = apiConnectptr.i;
- UintR TgcpFilesize = cgcpFilesize;
- localGcpPtr.i = apiConnectptr.p->gcpPointer;
- tmpApiConnectptr.i = TapiConnectptrIndex;
- tmpApiConnectptr.p = apiConnectptr.p;
- ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord);
- gcpPtr.i = localGcpPtr.i;
- gcpPtr.p = localGcpPtr.p;
- unlinkApiConnect(signal);
- if (localGcpPtr.p->firstApiConnect == RNIL) {
- if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
- jam();
- tcheckGcpId = localGcpPtr.p->gcpId;
- gcpTcfinished(signal);
- unlinkGcp(signal);
- }//if
- }//if
-}//Dbtc::handleGcp()
-
-void Dbtc::releaseApiConCopy(Signal* signal)
-{
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- UintR TfirstfreeApiConnectCopyOld = cfirstfreeApiConnectCopy;
- cfirstfreeApiConnectCopy = apiConnectptr.i;
- regApiPtr->nextApiConnect = TfirstfreeApiConnectCopyOld;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- regApiPtr->apiConnectstate = CS_RESTART;
-}//Dbtc::releaseApiConCopy()
-
-/* ========================================================================= */
-/* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
-/* ========================================================================= */
-void Dbtc::releaseDirtyWrite(Signal* signal)
-{
- unlinkReadyTcCon(signal);
- releaseTcCon();
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
- if (regApiPtr->firstTcConnect == RNIL) {
- jam();
- regApiPtr->apiConnectstate = CS_CONNECTED;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- sendtckeyconf(signal, 1);
- }//if
- }//if
-}//Dbtc::releaseDirtyWrite()
-
-/*****************************************************************************
- * L Q H K E Y R E F
- * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
- * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
- * TCROLLBACKREP WILL BE SENT TO THE API.
- *
- * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
- * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
- * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
- * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
- * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
- * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
- * "REC_LQHREFUSE",
- * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
- * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
- *****************************************************************************/
-void Dbtc::execLQHKEYREF(Signal* signal)
-{
- const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
- Uint32 indexId = 0;
- jamEntry();
-
- UintR compare_transid1, compare_transid2;
- UintR TtcConnectFilesize = ctcConnectFilesize;
- /*-------------------------------------------------------------------------
- *
- * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
- * TRANSACTION PARTS ACTIVE ANYMORE.
- * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
- *-------------------------------------------------------------------------*/
- if (lqhKeyRef->connectPtr < TtcConnectFilesize) {
- /*-----------------------------------------------------------------------
- * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
- * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
- * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
- * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
- * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
- * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
- * ALREADY COMPLETED (ABORTED).
- *-----------------------------------------------------------------------*/
- tcConnectptr.i = lqhKeyRef->connectPtr;
- Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
- ptrAss(tcConnectptr, tcConnectRecord);
- TcConnectRecord * const regTcPtr = tcConnectptr.p;
- if (regTcPtr->tcConnectstate == OS_OPERATING) {
- Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
- compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- warningReport(signal, 25);
- return;
- }//if
-
- const ConnectionState state = regApiPtr->apiConnectstate;
- const Uint32 triggeringOp = regTcPtr->triggeringOperation;
- if (triggeringOp != RNIL) {
- jam();
- // This operation was created by a trigger execting operation
- TcConnectRecordPtr opPtr;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
-
- const Uint32 currentIndexId = regTcPtr->currentIndexId;
- ndbassert(currentIndexId != 0); // Only index triggers so far
-
- opPtr.i = triggeringOp;
- ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
-
- // The operation executed an index trigger
- TcIndexData* indexData = c_theIndexes.getPtr(currentIndexId);
- indexId = indexData->indexId;
- regApiPtr->errorData = indexId;
- const Uint32 opType = regTcPtr->operation;
- if (errCode == ZALREADYEXIST)
- errCode = terrorCode = ZNOTUNIQUE;
- else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
- jam();
- /**
- * "Normal path"
- */
- // fall-through
- } else {
- jam();
- /** ZDELETE && NOT_FOUND */
- if(indexData->indexState == IS_BUILDING && state != CS_ABORTING){
- jam();
- /**
- * Ignore error
- */
- regApiPtr->lqhkeyconfrec++;
-
- unlinkReadyTcCon(signal);
- releaseTcCon();
-
- opPtr.p->triggerExecutionCount--;
- if (opPtr.p->triggerExecutionCount == 0) {
- /**
- * We have completed current trigger execution
- * Continue triggering operation
- */
- jam();
- continueTriggeringOp(signal, opPtr.p);
- }
- return;
- }
- }
- }
-
- Uint32 marker = regTcPtr->commitAckMarker;
- markOperationAborted(regApiPtr, regTcPtr);
-
- if(regApiPtr->apiConnectstate == CS_ABORTING){
- /**
- * We're already aborting' so don't send an "extra" TCKEYREF
- */
- jam();
- return;
- }
-
- const Uint32 abort = regTcPtr->m_execAbortOption;
- if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
- /**
- * No error is allowed on this operation
- */
- TCKEY_abort(signal, 49);
- return;
- }//if
-
- if (marker != RNIL){
- /**
- * This was an insert/update/delete/write which failed
- * that contained the marker
- * Currently unsupported to place new marker
- */
- TCKEY_abort(signal, 49);
- return;
- }
-
- /* Only ref in certain situations */
- {
- const Uint32 opType = regTcPtr->operation;
- if ( (opType == ZDELETE && errCode != ZNOT_FOUND)
- || (opType == ZINSERT && errCode != ZALREADYEXIST)
- || (opType == ZUPDATE && errCode != ZNOT_FOUND)
- || (opType == ZWRITE && errCode != 839 && errCode != 840))
- {
- TCKEY_abort(signal, 49);
- return;
- }
- }
-
- /* *************** */
- /* TCKEYREF < */
- /* *************** */
- TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
- tcKeyRef->transId[0] = regApiPtr->transid[0];
- tcKeyRef->transId[1] = regApiPtr->transid[1];
- tcKeyRef->errorCode = terrorCode;
- bool isIndexOp = regTcPtr->isIndexOp;
- Uint32 indexOp = tcConnectptr.p->indexOp;
- Uint32 clientData = regTcPtr->clientData;
- unlinkReadyTcCon(signal); /* LINK TC CONNECT RECORD OUT OF */
- releaseTcCon(); /* RELEASE THE TC CONNECT RECORD */
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- if (isIndexOp) {
- jam();
- regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
- tcKeyRef->connectPtr = indexOp;
- tcKeyRef->errorData = indexId;
- EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
- apiConnectptr.i = save;
- apiConnectptr.p = regApiPtr;
- } else {
- jam();
- tcKeyRef->connectPtr = clientData;
- tcKeyRef->errorData = indexId;
- sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
- }//if
-
- /*---------------------------------------------------------------------
- * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
- * LQHKEYREQ THAT HAVE RETURNED.
- * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
- * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
- *---------------------------------------------------------------------*/
- regApiPtr->lqhkeyreqrec--;
- if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
- if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
- jam();
- diverify010Lab(signal);
- return;
- } else if (regApiPtr->tckeyrec > 0 || regApiPtr->m_exec_flag) {
- jam();
- sendtckeyconf(signal, 2);
- return;
- }
- }//if
- return;
-
- } else {
- warningReport(signal, 26);
- }//if
- } else {
- errorReport(signal, 6);
- }//if
- return;
-}//Dbtc::execLQHKEYREF()
-
-void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
- TcConnectRecord * const regTcPtr)
-{
- const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- if (regApiPtr->commitAckMarker == RNIL)
- ndbassert(commitAckMarker == RNIL);
- if (commitAckMarker != RNIL)
- ndbassert(regApiPtr->commitAckMarker != RNIL);
- if(commitAckMarker != RNIL){
- jam();
- m_commitAckMarkerHash.release(commitAckMarker);
- regTcPtr->commitAckMarker = RNIL;
- regApiPtr->commitAckMarker = RNIL;
- }
-}
-
-void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
- TcConnectRecord * const regTcPtr)
-{
- /*------------------------------------------------------------------------
- * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
- * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
- * ALREADY COMPLETED.
- *------------------------------------------------------------------------*/
- regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
- regTcPtr->tcConnectstate = OS_ABORTING;
- clearCommitAckMarker(regApiPtr, regTcPtr);
-}
-
-/*--------------------------------------*/
-/* EXIT AND WAIT FOR SIGNAL TCOMMITREQ */
-/* OR TCROLLBACKREQ FROM THE USER TO */
-/* CONTINUE THE TRANSACTION */
-/*--------------------------------------*/
-void Dbtc::execTC_COMMITREQ(Signal* signal)
-{
- UintR compare_transid1, compare_transid2;
-
- jamEntry();
- apiConnectptr.i = signal->theData[0];
- if (apiConnectptr.i < capiConnectFilesize) {
- ptrAss(apiConnectptr, apiConnectRecord);
- compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
- compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- jam();
- return;
- }//if
-
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
-
- const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
- const Uint32 apiBlockRef = regApiPtr->ndbapiBlockref;
- const Uint32 transId1 = regApiPtr->transid[0];
- const Uint32 transId2 = regApiPtr->transid[1];
- Uint32 errorCode = 0;
-
- regApiPtr->m_exec_flag = 1;
- switch (regApiPtr->apiConnectstate) {
- case CS_STARTED:
- tcConnectptr.i = regApiPtr->firstTcConnect;
- if (tcConnectptr.i != RNIL) {
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
- jam();
- /*******************************************************************/
- // The proper case where the application is waiting for commit or
- // abort order.
- // Start the commit order.
- /*******************************************************************/
- regApiPtr->returnsignal = RS_TC_COMMITCONF;
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- diverify010Lab(signal);
- return;
- } else {
- jam();
- /*******************************************************************/
- // The transaction is started but not all operations are completed.
- // It is not possible to commit the transaction in this state.
- // We will abort it instead.
- /*******************************************************************/
- regApiPtr->returnsignal = RS_NO_RETURN;
- errorCode = ZTRANS_STATUS_ERROR;
- abort010Lab(signal);
- }//if
- } else {
- jam();
- /**
- * No operations, accept commit
- */
- TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
- commitConf->apiConnectPtr = apiConnectPtr;
- commitConf->transId1 = transId1;
- commitConf->transId2 = transId2;
- commitConf->gci = 0;
- sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
- TcCommitConf::SignalLength, JBB);
-
- regApiPtr->returnsignal = RS_NO_RETURN;
- releaseAbortResources(signal);
- return;
- }//if
- break;
- case CS_RECEIVING:
- jam();
- /***********************************************************************/
- // A transaction is still receiving data. We cannot commit an unfinished
- // transaction. We will abort it instead.
- /***********************************************************************/
- regApiPtr->returnsignal = RS_NO_RETURN;
- errorCode = ZPREPAREINPROGRESS;
- abort010Lab(signal);
- break;
-
- case CS_START_COMMITTING:
- case CS_COMMITTING:
- case CS_COMMIT_SENT:
- case CS_COMPLETING:
- case CS_COMPLETE_SENT:
- case CS_REC_COMMITTING:
- case CS_PREPARE_TO_COMMIT:
- jam();
- /***********************************************************************/
- // The transaction is already performing a commit but it is not concluded
- // yet.
- /***********************************************************************/
- errorCode = ZCOMMITINPROGRESS;
- break;
- case CS_ABORTING:
- jam();
- errorCode = regApiPtr->returncode ?
- regApiPtr->returncode : ZABORTINPROGRESS;
- break;
- case CS_START_SCAN:
- jam();
- /***********************************************************************/
- // The transaction is a scan. Scans cannot commit
- /***********************************************************************/
- errorCode = ZSCANINPROGRESS;
- break;
- case CS_PREPARED:
- jam();
- return;
- case CS_START_PREPARING:
- jam();
- return;
- case CS_REC_PREPARING:
- jam();
- return;
- break;
- default:
- warningHandlerLab(signal, __LINE__);
- return;
- }//switch
- TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
- commitRef->apiConnectPtr = apiConnectPtr;
- commitRef->transId1 = transId1;
- commitRef->transId2 = transId2;
- commitRef->errorCode = errorCode;
- sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
- TcCommitRef::SignalLength, JBB);
- return;
- } else /** apiConnectptr.i < capiConnectFilesize */ {
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }
-}//Dbtc::execTC_COMMITREQ()
-
-/**
- * TCROLLBACKREQ
- *
- * Format is:
- *
- * thedata[0] = apiconnectptr
- * thedata[1] = transid[0]
- * thedata[2] = transid[1]
- * OPTIONAL thedata[3] = flags
- *
- * Flags:
- * 0x1 = potentiallyBad data from API (try not to assert)
- */
-void Dbtc::execTCROLLBACKREQ(Signal* signal)
-{
- bool potentiallyBad= false;
- UintR compare_transid1, compare_transid2;
-
- jamEntry();
-
- if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
- {
- ndbout_c("Trying to roll back potentially bad txn\n");
- potentiallyBad= true;
- }
-
- apiConnectptr.i = signal->theData[0];
- if (apiConnectptr.i >= capiConnectFilesize) {
- goto TC_ROLL_warning;
- }//if
- ptrAss(apiConnectptr, apiConnectRecord);
- compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
- compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- jam();
- return;
- }//if
-
- apiConnectptr.p->m_exec_flag = 1;
- switch (apiConnectptr.p->apiConnectstate) {
- case CS_STARTED:
- case CS_RECEIVING:
- jam();
- apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
- abort010Lab(signal);
- return;
- case CS_CONNECTED:
- jam();
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
- signal, 3, JBB);
- break;
- case CS_START_SCAN:
- case CS_PREPARE_TO_COMMIT:
- case CS_COMMITTING:
- case CS_COMMIT_SENT:
- case CS_COMPLETING:
- case CS_COMPLETE_SENT:
- case CS_WAIT_COMMIT_CONF:
- case CS_WAIT_COMPLETE_CONF:
- case CS_RESTART:
- case CS_DISCONNECTED:
- case CS_START_COMMITTING:
- case CS_REC_COMMITTING:
- jam();
- /* ***************< */
- /* TC_ROLLBACKREF < */
- /* ***************< */
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- signal->theData[3] = ZROLLBACKNOTALLOWED;
- signal->theData[4] = apiConnectptr.p->apiConnectstate;
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
- signal, 5, JBB);
- break;
- /* SEND A REFUSAL SIGNAL*/
- case CS_ABORTING:
- jam();
- if (apiConnectptr.p->abortState == AS_IDLE) {
- jam();
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
- signal, 3, JBB);
- } else {
- jam();
- apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
- }//if
- break;
- case CS_WAIT_ABORT_CONF:
- jam();
- apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
- break;
- case CS_START_PREPARING:
- jam();
- case CS_PREPARED:
- jam();
- case CS_REC_PREPARING:
- jam();
- default:
- goto TC_ROLL_system_error;
- break;
- }//switch
- return;
-
-TC_ROLL_warning:
- jam();
- if(likely(potentiallyBad==false))
- warningHandlerLab(signal, __LINE__);
- return;
-
-TC_ROLL_system_error:
- jam();
- if(likely(potentiallyBad==false))
- systemErrorLab(signal, __LINE__);
- return;
-}//Dbtc::execTCROLLBACKREQ()
-
-void Dbtc::execTC_HBREP(Signal* signal)
-{
- const TcHbRep * const tcHbRep =
- (TcHbRep *)signal->getDataPtr();
-
- jamEntry();
- apiConnectptr.i = tcHbRep->apiConnectPtr;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
-
- if (apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
- apiConnectptr.p->transid[1] == tcHbRep->transId2){
-
- if (getApiConTimer(apiConnectptr.i) != 0){
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- } else {
- DEBUG("TCHBREP received when timer was off apiConnectptr.i="
- << apiConnectptr.i);
- }
- }
-}//Dbtc::execTCHBREP()
-
-/*
-4.3.15 ABORT
------------
-*/
-/*****************************************************************************/
-/* A B O R T */
-/* */
-/*****************************************************************************/
-void Dbtc::warningReport(Signal* signal, int place)
-{
- switch (place) {
- case 0:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "ABORTED to not active TC record" << endl;
-#endif
- break;
- case 1:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "ABORTED to TC record active with new transaction" << endl;
-#endif
- break;
- case 2:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
-#endif
- break;
- case 3:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
- ndbout << "This is ok when aborting in node failure situations" << endl;
-#endif
- break;
- case 4:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
-#endif
- break;
- case 5:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
-#endif
- break;
- case 6:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
-#endif
- break;
- case 7:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
-#endif
- break;
- case 8:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
-#endif
- break;
- case 9:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
-#endif
- break;
- case 10:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
-#endif
- break;
- case 11:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
-#endif
- break;
- case 12:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
-#endif
- break;
- case 13:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
-#endif
- break;
- case 14:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
-#endif
- break;
- case 15:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
-#endif
- break;
- case 16:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
-#endif
- break;
- case 17:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
-#endif
- break;
- case 18:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
-#endif
- break;
- case 19:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
-#endif
- break;
- case 20:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
-#endif
- break;
- case 21:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
-#endif
- break;
- case 22:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
-#endif
- break;
- case 23:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
-#endif
- break;
- case 24:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
-#endif
- break;
- case 25:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
-#endif
- break;
- case 26:
- jam();
-#ifdef ABORT_TRACE
- ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
-#endif
- break;
- case 27:
- jam();
- // printState(signal, 27);
-#ifdef ABORT_TRACE
- ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
-#endif
- break;
- default:
- jam();
- break;
- }//switch
- return;
-}//Dbtc::warningReport()
-
-void Dbtc::errorReport(Signal* signal, int place)
-{
- switch (place) {
- case 0:
- jam();
- break;
- case 1:
- jam();
- break;
- case 2:
- jam();
- break;
- case 3:
- jam();
- break;
- case 4:
- jam();
- break;
- case 5:
- jam();
- break;
- case 6:
- jam();
- break;
- default:
- jam();
- break;
- }//switch
- systemErrorLab(signal, __LINE__);
- return;
-}//Dbtc::errorReport()
-
-/* ------------------------------------------------------------------------- */
-/* ------- ENTER ABORTED ------- */
-/* */
-/*-------------------------------------------------------------------------- */
-void Dbtc::execABORTED(Signal* signal)
-{
- UintR compare_transid1, compare_transid2;
-
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- UintR Tnodeid = signal->theData[3];
- UintR TlastLqhInd = signal->theData[4];
-
- if (ERROR_INSERTED(8040)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
- return;
- }//if
- /*------------------------------------------------------------------------
- * ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
- *------------------------------------------------------------------------*/
- if (tcConnectptr.i >= ctcConnectFilesize) {
- errorReport(signal, 0);
- return;
- }//if
- /*-------------------------------------------------------------------------
- * WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
- * TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
- * IN TC WAITING FOR ABORTED.
- *-------------------------------------------------------------------------*/
- ptrAss(tcConnectptr, tcConnectRecord);
- if (tcConnectptr.p->tcConnectstate != OS_ABORT_SENT) {
- warningReport(signal, 2);
- return;
- /*-----------------------------------------------------------------------*/
- // ABORTED reported on an operation not expecting ABORT.
- /*-----------------------------------------------------------------------*/
- }//if
- apiConnectptr.i = tcConnectptr.p->apiConnect;
- if (apiConnectptr.i >= capiConnectFilesize) {
- warningReport(signal, 0);
- return;
- }//if
- ptrAss(apiConnectptr, apiConnectRecord);
- compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
- compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- warningReport(signal, 1);
- return;
- }//if
- if (ERROR_INSERTED(8024)) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
-
- /**
- * Release marker
- */
- clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
-
- Uint32 i;
- Uint32 Tfound = 0;
- for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
- jam();
- if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
- /*---------------------------------------------------------------------
- * We have received ABORTED from one of the participants in this
- * operation in this aborted transaction.
- * Record all nodes that have completed abort.
- * If last indicator is set it means that no more replica has
- * heard of the operation and are thus also aborted.
- *---------------------------------------------------------------------*/
- jam();
- Tfound = 1;
- clearTcNodeData(signal, TlastLqhInd, i);
- }//if
- }//for
- if (Tfound == 0) {
- warningReport(signal, 3);
- return;
- }
- for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
- if (tcConnectptr.p->tcNodedata[i] != 0) {
- /*--------------------------------------------------------------------
- * There are still outstanding ABORTED's to wait for.
- *--------------------------------------------------------------------*/
- jam();
- return;
- }//if
- }//for
- tcConnectptr.p->noOfNodes = 0;
- tcConnectptr.p->tcConnectstate = OS_ABORTING;
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- apiConnectptr.p->counter--;
- if (apiConnectptr.p->counter > 0) {
- jam();
- /*----------------------------------------------------------------------
- * WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
- *----------------------------------------------------------------------*/
- return;
- }//if
- /*------------------------------------------------------------------------*/
- /* */
- /* WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED */
- /* FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL */
- /* RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
- /*------------------------------------------------------------------------*/
- releaseAbortResources(signal);
-}//Dbtc::execABORTED()
-
-void Dbtc::clearTcNodeData(Signal* signal,
- UintR TLastLqhIndicator,
- UintR Tstart)
-{
- UintR Ti;
- if (TLastLqhIndicator == ZTRUE) {
- for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
- jam();
- tcConnectptr.p->tcNodedata[Ti] = 0;
- }//for
- } else {
- jam();
- tcConnectptr.p->tcNodedata[Tstart] = 0;
- }//for
-}//clearTcNodeData()
-
-void Dbtc::abortErrorLab(Signal* signal)
-{
- ptrGuard(apiConnectptr);
- ApiConnectRecord * transP = apiConnectptr.p;
- if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
- jam();
- return;
- }
- transP->returnsignal = RS_TCROLLBACKREP;
- if(transP->returncode == 0){
- jam();
- transP->returncode = terrorCode;
- }
- abort010Lab(signal);
-}//Dbtc::abortErrorLab()
-
-void Dbtc::abort010Lab(Signal* signal)
-{
- ApiConnectRecord * transP = apiConnectptr.p;
- if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
- jam();
- return;
- }
- transP->apiConnectstate = CS_ABORTING;
- /*------------------------------------------------------------------------*/
- /* AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
- /* ALL PARTICIPANTS IN THE TRANSACTION. */
- /*------------------------------------------------------------------------*/
- transP->abortState = AS_ACTIVE;
- transP->counter = 0;
-
- if (transP->firstTcConnect == RNIL) {
- jam();
- /*--------------------------------------------------------------------*/
- /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION. */
- /*--------------------------------------------------------------------*/
- releaseAbortResources(signal);
- return;
- }//if
- tcConnectptr.i = transP->firstTcConnect;
- abort015Lab(signal);
-}//Dbtc::abort010Lab()
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP */
-/* ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE. */
-/* EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE */
-/* MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES */
-/* NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
-/* WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
-/*--------------------------------------------------------------------------*/
-void Dbtc::abort015Lab(Signal* signal)
-{
- Uint32 TloopCount = 0;
-ABORT020:
- jam();
- TloopCount++;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- switch (tcConnectptr.p->tcConnectstate) {
- case OS_WAIT_DIH:
- case OS_WAIT_KEYINFO:
- case OS_WAIT_ATTR:
- jam();
- /*----------------------------------------------------------------------*/
- /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
- /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING. */
- /*----------------------------------------------------------------------*/
- tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
- tcConnectptr.p->tcConnectstate = OS_ABORTING;
- break;
- case OS_CONNECTED:
- jam();
- /*-----------------------------------------------------------------------
- * WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
- * NEED NOT BOTHER ABOUT ANY LQH ABORTS.
- *-----------------------------------------------------------------------*/
- tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
- tcConnectptr.p->tcConnectstate = OS_ABORTING;
- break;
- case OS_PREPARED:
- jam();
- case OS_OPERATING:
- jam();
- /*----------------------------------------------------------------------
- * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
- * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
- * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
- *----------------------------------------------------------------------*/
- releaseAndAbort(signal);
- tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
- TloopCount += 127;
- break;
- case OS_ABORTING:
- jam();
- break;
- case OS_ABORT_SENT:
- jam();
- DEBUG("ABORT_SENT state in abort015Lab(), not expected");
- systemErrorLab(signal, __LINE__);
- return;
- default:
- jam();
- DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
-
- if (tcConnectptr.p->nextTcConnect != RNIL) {
- jam();
- tcConnectptr.i = tcConnectptr.p->nextTcConnect;
- if (TloopCount < 1024) {
- goto ABORT020;
- } else {
- jam();
- /*---------------------------------------------------------------------
- * Reset timer to avoid time-out in real-time break.
- * Increase counter to ensure that we don't think that all ABORTED have
- * been received before all have been sent.
- *---------------------------------------------------------------------*/
- apiConnectptr.p->counter++;
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- signal->theData[0] = TcContinueB::ZABORT_BREAK;
- signal->theData[1] = tcConnectptr.i;
- signal->theData[2] = apiConnectptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- return;
- }//if
- }//if
- if (apiConnectptr.p->counter > 0) {
- jam();
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- return;
- }//if
- /*-----------------------------------------------------------------------
- * WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
- * FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
- * RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
- *------------------------------------------------------------------------*/
- releaseAbortResources(signal);
-}//Dbtc::abort015Lab()
-
-/*--------------------------------------------------------------------------*/
-/* RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK. */
-/*--------------------------------------------------------------------------*/
-int Dbtc::releaseAndAbort(Signal* signal)
-{
- HostRecordPtr localHostptr;
- UintR TnoLoops = tcConnectptr.p->noOfNodes;
-
- apiConnectptr.p->counter++;
- bool prevAlive = false;
- for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
- localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
- ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
- if (localHostptr.p->hostStatus == HS_ALIVE) {
- jam();
- if (prevAlive) {
- // if previous is alive, its LQH forwards abort to this node
- jam();
- continue;
- }
- /* ************< */
- /* ABORT < */
- /* ************< */
- tblockref = calcLqhBlockRef(localHostptr.i);
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = apiConnectptr.p->transid[0];
- signal->theData[3] = apiConnectptr.p->transid[1];
- sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
- prevAlive = true;
- } else {
- jam();
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- signal->theData[3] = localHostptr.i;
- signal->theData[4] = ZFALSE;
- sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
- prevAlive = false;
- }//if
- }//for
- return 1;
-}//Dbtc::releaseAndAbort()
-
-/* ------------------------------------------------------------------------- */
-/* ------- ENTER TIME_SIGNAL ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dbtc::execTIME_SIGNAL(Signal* signal)
-{
-
- jamEntry();
- ctcTimer++;
- if (csystemStart != SSS_TRUE) {
- jam();
- return;
- }//if
- checkStartTimeout(signal);
- checkStartFragTimeout(signal);
-}//Dbtc::execTIME_SIGNAL()
-
-/*------------------------------------------------*/
-/* Start timeout handling if not already going on */
-/*------------------------------------------------*/
-void Dbtc::checkStartTimeout(Signal* signal)
-{
- ctimeOutCheckCounter++;
- if (ctimeOutCheckActive == TOCS_TRUE) {
- jam();
- // Check heartbeat of timeout loop
- if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
- jam();
- ctimeOutMissedHeartbeats = 0;
- }else{
- jam();
- ctimeOutMissedHeartbeats++;
- if (ctimeOutMissedHeartbeats > 100){
- jam();
- systemErrorLab(signal, __LINE__);
- }
- }
- ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
- return;
- }//if
- if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
- jam();
- /*------------------------------------------------------------------*/
- /* */
- /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
- /*------------------------------------------------------------------*/
- return;
- }//if
- ctimeOutCheckActive = TOCS_TRUE;
- ctimeOutCheckCounter = 0;
- timeOutLoopStartLab(signal, 0); // 0 is first api connect record
- return;
-}//Dbtc::execTIME_SIGNAL()
-
-/*----------------------------------------------------------------*/
-/* Start fragment (scan) timeout handling if not already going on */
-/*----------------------------------------------------------------*/
-void Dbtc::checkStartFragTimeout(Signal* signal)
-{
- ctimeOutCheckFragCounter++;
- if (ctimeOutCheckFragActive == TOCS_TRUE) {
- jam();
- return;
- }//if
- if (ctimeOutCheckFragCounter < ctimeOutCheckDelay) {
- jam();
- /*------------------------------------------------------------------*/
- /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
- /*------------------------------------------------------------------*/
- return;
- }//if
-
- // Go through the fragment records and look for timeout in a scan.
- ctimeOutCheckFragActive = TOCS_TRUE;
- ctimeOutCheckFragCounter = 0;
- timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
-}//checkStartFragTimeout()
-
-/*------------------------------------------------------------------*/
-/* IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE */
-/* BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM */
-/* SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM */
-/* THE WAITING PART OF A PROTOCOL. */
-/*
-The algorithm used here is to check 1024 transactions at a time before
-doing a real-time break.
-To avoid aborting both transactions in a deadlock detected by time-out
-we insert a random extra time-out of upto 630 ms by using the lowest
-six bits of the api connect reference.
-We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
-we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
-and otherwise we spread it out 310 ms.
-*/
-/*------------------------------------------------------------------*/
-void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
-{
- Uint32 end_ptr, time_passed, time_out_value, mask_value;
- Uint32 old_mask_value= 0;
- const Uint32 api_con_sz= capiConnectFilesize;
- const Uint32 tc_timer= ctcTimer;
- const Uint32 time_out_param= ctimeOutValue;
- const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
-
- ctimeOutCheckHeartbeat = tc_timer;
-
- if (api_con_ptr + 1024 < api_con_sz) {
- jam();
- end_ptr= api_con_ptr + 1024;
- } else {
- jam();
- end_ptr= api_con_sz;
- }
- if (time_out_param > 300) {
- jam();
- mask_value= 63;
- } else if (time_out_param < 30) {
- jam();
- mask_value= 7;
- } else {
- jam();
- mask_value= 31;
- }
- if (time_out_param != old_time_out_param &&
- getNodeState().getSingleUserMode())
- {
- // abort during single user mode, use old_mask_value as flag
- // and calculate value to be used for connections with allowed api
- if (old_time_out_param > 300) {
- jam();
- old_mask_value= 63;
- } else if (old_time_out_param < 30) {
- jam();
- old_mask_value= 7;
- } else {
- jam();
- old_mask_value= 31;
- }
- }
- for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
- Uint32 api_timer= getApiConTimer(api_con_ptr);
- jam();
- if (api_timer != 0) {
- Uint32 error= ZTIME_OUT_ERROR;
- time_out_value= time_out_param + (ndb_rand() & mask_value);
- if (unlikely(old_mask_value)) // abort during single user mode
- {
- apiConnectptr.i = api_con_ptr;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- if ((getNodeState().getSingleUserApi() ==
- refToNode(apiConnectptr.p->ndbapiBlockref)) ||
- !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
- {
- // api allowed during single user, use original timeout
- time_out_value=
- old_time_out_param + (api_con_ptr & old_mask_value);
- }
- else
- {
- error= ZCLUSTER_IN_SINGLEUSER_MODE;
- }
- }
- time_passed= tc_timer - api_timer;
- if (time_passed > time_out_value)
- {
- jam();
- timeOutFoundLab(signal, api_con_ptr, error);
- api_con_ptr++;
- break;
- }
- }
- }
- if (api_con_ptr == api_con_sz) {
- jam();
- /*------------------------------------------------------------------*/
- /* */
- /* WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
- /* STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW */
- /* READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK. */
- /*------------------------------------------------------------------*/
- ctimeOutCheckActive = TOCS_FALSE;
- } else {
- jam();
- sendContinueTimeOutControl(signal, api_con_ptr);
- }
- return;
-}//Dbtc::timeOutLoopStartLab()
-
-void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
-{
- apiConnectptr.i = TapiConPtr;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- /*------------------------------------------------------------------*/
- /* */
- /* THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
- /* FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
- /*------------------------------------------------------------------*/
- DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
- << " H'" << apiConnectptr.p->transid[1] << "] " << dec
- << "Time-out in state = " << apiConnectptr.p->apiConnectstate
- << " apiConnectptr.i = " << apiConnectptr.i
- << " - exec: " << apiConnectptr.p->m_exec_flag
- << " - place: " << c_apiConTimer_line[apiConnectptr.i]
- << " code: " << errCode);
- switch (apiConnectptr.p->apiConnectstate) {
- case CS_STARTED:
- if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
- errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
- jam();
- /*
- We are waiting for application to continue the transaction. In this
- particular state we will use the application timeout parameter rather
- than the shorter Deadlock detection timeout.
- */
- if (c_appl_timeout_value == 0 ||
- (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
- jam();
- return;
- }//if
- }
- apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
- apiConnectptr.p->returncode = errCode;
- abort010Lab(signal);
- return;
- case CS_RECEIVING:
- case CS_REC_COMMITTING:
- case CS_START_COMMITTING:
- jam();
- /*------------------------------------------------------------------*/
- /* WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS */
- /* NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO */
- /* START ABORTING THE TRANSACTION. ALSO START CHECKING THE */
- /* REMAINING TRANSACTIONS. */
- /*------------------------------------------------------------------*/
- terrorCode = errCode;
- abortErrorLab(signal);
- return;
- case CS_COMMITTING:
- jam();
- /*------------------------------------------------------------------*/
- // We are simply waiting for a signal in the job buffer. Only extreme
- // conditions should get us here. We ignore it.
- /*------------------------------------------------------------------*/
- case CS_COMPLETING:
- jam();
- /*------------------------------------------------------------------*/
- // We are simply waiting for a signal in the job buffer. Only extreme
- // conditions should get us here. We ignore it.
- /*------------------------------------------------------------------*/
- case CS_PREPARE_TO_COMMIT:
- {
- jam();
- /*------------------------------------------------------------------*/
- /* WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
- /* KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO. */
- /* IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE. */
- // To ensure against strange bugs we crash the system if we have passed
- // time-out period by a factor of 10 and it is also at least 5 seconds.
- /*------------------------------------------------------------------*/
- Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr.i);
- if (time_passed > 500 &&
- time_passed > (5 * cDbHbInterval) &&
- time_passed > (10 * ctimeOutValue))
- {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- break;
- }
- case CS_COMMIT_SENT:
- jam();
- /*------------------------------------------------------------------*/
- /* WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
- /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
- /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL */
- /* TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO */
- /* A NODE FAILURE. */
- /*------------------------------------------------------------------*/
- tabortInd = ZCOMMIT_SETUP;
- setupFailData(signal);
- toCommitHandlingLab(signal);
- return;
- case CS_COMPLETE_SENT:
- jam();
- /*--------------------------------------------------------------------*/
- /* WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
- /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
- /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL */
- /* TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO */
- /* A NODE FAILURE. */
- /*--------------------------------------------------------------------*/
- tabortInd = ZCOMMIT_SETUP;
- setupFailData(signal);
- toCompleteHandlingLab(signal);
- return;
- case CS_ABORTING:
- jam();
- /*------------------------------------------------------------------*/
- /* TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL */
- /* NODES THAT HAVE FAILED BEFORE SENDING ABORTED. */
- /*------------------------------------------------------------------*/
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- sendAbortedAfterTimeout(signal, 0);
- break;
- case CS_START_SCAN:{
- jam();
-
- /*
- We are waiting for application to continue the transaction. In this
- particular state we will use the application timeout parameter rather
- than the shorter Deadlock detection timeout.
- */
- if (c_appl_timeout_value == 0 ||
- (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
- jam();
- return;
- }//if
-
- ScanRecordPtr scanPtr;
- scanPtr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
- scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
- break;
- }
- case CS_WAIT_ABORT_CONF:
- jam();
- tcConnectptr.i = apiConnectptr.p->currentTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
- hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- /*------------------------------------------------------------------*/
- // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
- // case.
- /*------------------------------------------------------------------*/
- warningReport(signal, 20);
- apiConnectptr.p->timeOutCounter++;
- if (apiConnectptr.p->timeOutCounter > 3) {
- /*------------------------------------------------------------------*/
- // 100 time-outs are not acceptable. We will shoot down the node
- // not responding.
- /*------------------------------------------------------------------*/
- reportNodeFailed(signal, hostptr.i);
- }//if
- apiConnectptr.p->currentReplicaNo++;
- }//if
- tcurrentReplicaNo = (Uint8)Z8NIL;
- toAbortHandlingLab(signal);
- return;
- case CS_WAIT_COMMIT_CONF:
- jam();
- CRASH_INSERTION(8053);
- tcConnectptr.i = apiConnectptr.p->currentTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
- hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- /*------------------------------------------------------------------*/
- // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
- // case.
- /*------------------------------------------------------------------*/
- warningReport(signal, 21);
- apiConnectptr.p->timeOutCounter++;
- if (apiConnectptr.p->timeOutCounter > 3) {
- /*------------------------------------------------------------------*/
- // 100 time-outs are not acceptable. We will shoot down the node
- // not responding.
- /*------------------------------------------------------------------*/
- reportNodeFailed(signal, hostptr.i);
- }//if
- apiConnectptr.p->currentReplicaNo++;
- }//if
- tcurrentReplicaNo = (Uint8)Z8NIL;
- toCommitHandlingLab(signal);
- return;
- case CS_WAIT_COMPLETE_CONF:
- jam();
- tcConnectptr.i = apiConnectptr.p->currentTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
- hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- /*------------------------------------------------------------------*/
- // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
- // just in case.
- /*------------------------------------------------------------------*/
- warningReport(signal, 22);
- apiConnectptr.p->timeOutCounter++;
- if (apiConnectptr.p->timeOutCounter > 100) {
- /*------------------------------------------------------------------*/
- // 100 time-outs are not acceptable. We will shoot down the node
- // not responding.
- /*------------------------------------------------------------------*/
- reportNodeFailed(signal, hostptr.i);
- }//if
- apiConnectptr.p->currentReplicaNo++;
- }//if
- tcurrentReplicaNo = (Uint8)Z8NIL;
- toCompleteHandlingLab(signal);
- return;
- case CS_FAIL_PREPARED:
- jam();
- case CS_FAIL_COMMITTING:
- jam();
- case CS_FAIL_COMMITTED:
- jam();
- case CS_REC_PREPARING:
- jam();
- case CS_START_PREPARING:
- jam();
- case CS_PREPARED:
- jam();
- case CS_RESTART:
- jam();
- case CS_FAIL_ABORTED:
- jam();
- case CS_DISCONNECTED:
- jam();
- default:
- jam();
- /*------------------------------------------------------------------*/
- /* AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM. */
- /*------------------------------------------------------------------*/
- DEBUG("State = " << apiConnectptr.p->apiConnectstate);
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
- return;
-}//Dbtc::timeOutFoundLab()
-
-void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
-{
- ApiConnectRecord * transP = apiConnectptr.p;
- if(transP->abortState == AS_IDLE){
- jam();
- warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
- __LINE__,
- apiConnectptr.i,
- transP->apiConnectstate,
- c_apiConTimer_line[apiConnectptr.i],
- transP->firstTcConnect,
- c_apiConTimer[apiConnectptr.i]
- );
- ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
- __LINE__,
- apiConnectptr.i,
- transP->apiConnectstate,
- c_apiConTimer_line[apiConnectptr.i],
- transP->firstTcConnect,
- c_apiConTimer[apiConnectptr.i]
- );
- ndbrequire(false);
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- return;
- }
-
- bool found = false;
- OperationState tmp[16];
-
- Uint32 TloopCount = 0;
- do {
- jam();
- if (tcConnectptr.i == RNIL) {
- jam();
-
-#ifdef VM_TRACE
- ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
- found, Tcheck, apiConnectptr.p->counter);
-#endif
- if (found || apiConnectptr.p->counter)
- {
- jam();
- /**
- * We sent atleast one ABORT/ABORTED
- * or ZABORT_TIMEOUT_BREAK is in job buffer
- * wait for reception...
- */
- return;
- }
-
- if (Tcheck == 1)
- {
- jam();
- releaseAbortResources(signal);
- return;
- }
-
- if (Tcheck == 0)
- {
- jam();
- /*------------------------------------------------------------------
- * All nodes had already reported ABORTED for all tcConnect records.
- * Crash since it is an error situation that we then received a
- * time-out.
- *------------------------------------------------------------------*/
- char buf[96]; buf[0] = 0;
- char buf2[96];
- BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
- __LINE__, apiConnectptr.i,
- apiConnectptr.p->counter);
- for(Uint32 i = 0; i<TloopCount; i++)
- {
- BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
- BaseString::snprintf(buf, sizeof(buf), buf2);
- }
- warningEvent(buf);
- ndbout_c(buf);
- ndbrequire(false);
- releaseAbortResources(signal);
- return;
- }
-
- return;
- }//if
- TloopCount++;
- if (TloopCount >= 1024) {
- jam();
- /*------------------------------------------------------------------*/
- // Insert a real-time break for large transactions to avoid blowing
- // away the job buffer.
- /*------------------------------------------------------------------*/
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- apiConnectptr.p->counter++;
- signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
- signal->theData[1] = tcConnectptr.i;
- signal->theData[2] = apiConnectptr.i;
- if (ERROR_INSERTED(8050))
- {
- ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
- Tcheck, apiConnectptr.p->counter);
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
- }
- else
- {
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- }
- return;
- }//if
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- if(TloopCount < 16){
- jam();
- tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
- }
-
- if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
- jam();
- /*------------------------------------------------------------------*/
- // We have sent an ABORT signal to this node but not yet received any
- // reply. We have to send an ABORTED signal on our own in some cases.
- // If the node is declared as up and running and still do not respond
- // in time to the ABORT signal we will declare it as dead.
- /*------------------------------------------------------------------*/
- UintR Ti = 0;
- arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
- for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
- jam();
- if (tcConnectptr.p->tcNodedata[Ti] != 0) {
- TloopCount += 31;
- found = true;
- hostptr.i = tcConnectptr.p->tcNodedata[Ti];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- jam();
- /*---------------------------------------------------------------
- * A backup replica has not sent ABORTED.
- * Could be that a node before him has crashed.
- * Send an ABORT signal specifically to this node.
- * We will not send to any more nodes after this
- * to avoid race problems.
- * To also ensure that we use this message also as a heartbeat
- * we will move this node to the primary replica seat.
- * The primary replica and any failed node after it will
- * be removed from the node list. Update also number of nodes.
- * Finally break the loop to ensure we don't mess
- * things up by executing another loop.
- * We also update the timer to ensure we don't get time-out
- * too early.
- *--------------------------------------------------------------*/
- BlockReference TBRef = calcLqhBlockRef(hostptr.i);
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = apiConnectptr.p->transid[0];
- signal->theData[3] = apiConnectptr.p->transid[1];
- sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- break;
- } else {
- jam();
- /*--------------------------------------------------------------
- * The node we are waiting for is dead. We will send ABORTED to
- * ourselves vicarious for the failed node.
- *--------------------------------------------------------------*/
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- signal->theData[3] = hostptr.i;
- signal->theData[4] = ZFALSE;
- sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
- }//if
- }//if
- }//for
- }//if
- tcConnectptr.i = tcConnectptr.p->nextTcConnect;
- } while (1);
-}//Dbtc::sendAbortedAfterTimeout()
-
-void Dbtc::reportNodeFailed(Signal* signal, Uint32 nodeId)
-{
- DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
- rep->nodeId = nodeId;
- rep->err = DisconnectRep::TcReportNodeFailed;
- sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
- DisconnectRep::SignalLength, JBB);
-}//Dbtc::reportNodeFailed()
-
-/*-------------------------------------------------*/
-/* Timeout-loop for scanned fragments. */
-/*-------------------------------------------------*/
-void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
-{
- ScanFragRecPtr timeOutPtr[8];
- UintR tfragTimer[8];
- UintR texpiredTime[8];
- UintR TloopCount = 0;
- Uint32 TtcTimer = ctcTimer;
-
- while ((TscanConPtr + 8) < cscanFragrecFileSize) {
- jam();
- timeOutPtr[0].i = TscanConPtr + 0;
- timeOutPtr[1].i = TscanConPtr + 1;
- timeOutPtr[2].i = TscanConPtr + 2;
- timeOutPtr[3].i = TscanConPtr + 3;
- timeOutPtr[4].i = TscanConPtr + 4;
- timeOutPtr[5].i = TscanConPtr + 5;
- timeOutPtr[6].i = TscanConPtr + 6;
- timeOutPtr[7].i = TscanConPtr + 7;
-
- c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
- c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
- c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
- c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
- c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
- c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
- c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
- c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
-
- tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
- tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
- tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
- tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
- tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
- tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
- tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
- tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
-
- texpiredTime[0] = TtcTimer - tfragTimer[0];
- texpiredTime[1] = TtcTimer - tfragTimer[1];
- texpiredTime[2] = TtcTimer - tfragTimer[2];
- texpiredTime[3] = TtcTimer - tfragTimer[3];
- texpiredTime[4] = TtcTimer - tfragTimer[4];
- texpiredTime[5] = TtcTimer - tfragTimer[5];
- texpiredTime[6] = TtcTimer - tfragTimer[6];
- texpiredTime[7] = TtcTimer - tfragTimer[7];
-
- for (Uint32 Ti = 0; Ti < 8; Ti++) {
- jam();
- if (tfragTimer[Ti] != 0) {
-
- if (texpiredTime[Ti] > ctimeOutValue) {
- jam();
- DEBUG("Fragment timeout found:"<<
- " ctimeOutValue=" <<ctimeOutValue
- <<", texpiredTime="<<texpiredTime[Ti]<<endl
- <<" tfragTimer="<<tfragTimer[Ti]
- <<", ctcTimer="<<ctcTimer);
- timeOutFoundFragLab(signal, TscanConPtr + Ti);
- return;
- }//if
- }//if
- }//for
- TscanConPtr += 8;
- /*----------------------------------------------------------------*/
- /* We split the process up checking 1024 fragmentrecords at a time*/
- /* to maintain real time behaviour. */
- /*----------------------------------------------------------------*/
- if (TloopCount++ > 128 ) {
- jam();
- signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
- signal->theData[1] = TscanConPtr;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
- }//if
- }//while
- for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
- jam();
- timeOutPtr[0].i = TscanConPtr;
- c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
- if (timeOutPtr[0].p->scanFragTimer != 0) {
- texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
- if (texpiredTime[0] > ctimeOutValue) {
- jam();
- DEBUG("Fragment timeout found:"<<
- " ctimeOutValue=" <<ctimeOutValue
- <<", texpiredTime="<<texpiredTime[0]<<endl
- <<" tfragTimer="<<tfragTimer[0]
- <<", ctcTimer="<<ctcTimer);
- timeOutFoundFragLab(signal, TscanConPtr);
- return;
- }//if
- }//if
- }//for
- ctimeOutCheckFragActive = TOCS_FALSE;
-
- return;
-}//timeOutLoopStartFragLab()
-
-/*--------------------------------------------------------------------------*/
-/*Handle the heartbeat signal from LQH in a scan process */
-// (Set timer on fragrec.)
-/*--------------------------------------------------------------------------*/
-void Dbtc::execSCAN_HBREP(Signal* signal)
-{
- jamEntry();
-
- scanFragptr.i = signal->theData[0];
- c_scan_frag_pool.getPtr(scanFragptr);
- switch (scanFragptr.p->scanFragState){
- case ScanFragRec::LQH_ACTIVE:
- break;
- default:
- DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
- systemErrorLab(signal, __LINE__);
- break;
- }
-
- ScanRecordPtr scanptr;
- scanptr.i = scanFragptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
-
- if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
- apiConnectptr.p->transid[1] == signal->theData[2])){
- jam();
- /**
- * Send signal back to sender so that the crash occurs there
- */
- // Save original transid
- signal->theData[3] = signal->theData[0];
- signal->theData[4] = signal->theData[1];
- // Set transid to illegal values
- signal->theData[1] = RNIL;
- signal->theData[2] = RNIL;
-
- sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
- DEBUG("SCAN_HBREP with wrong transid("
- <<signal->theData[3]<<", "<<signal->theData[4]<<")");
- return;
- }//if
-
- // Update timer on ScanFragRec
- if (scanFragptr.p->scanFragTimer != 0){
- updateBuddyTimer(apiConnectptr);
- scanFragptr.p->startFragTimer(ctcTimer);
- } else {
- ndbassert(false);
- DEBUG("SCAN_HBREP when scanFragTimer was turned off");
- }
-}//execSCAN_HBREP()
-
-/*--------------------------------------------------------------------------*/
-/* Timeout has occured on a fragment which means a scan has timed out. */
-/* If this is true we have an error in LQH/ACC. */
-/*--------------------------------------------------------------------------*/
-void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
-{
- ScanFragRecPtr ptr;
- c_scan_frag_pool.getPtr(ptr, TscanConPtr);
- DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState);
-
- const Uint32 time_out_param= ctimeOutValue;
- const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
-
- if (unlikely(time_out_param != old_time_out_param &&
- getNodeState().getSingleUserMode()))
- {
- jam();
- ScanRecordPtr scanptr;
- scanptr.i = ptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- ApiConnectRecordPtr TlocalApiConnectptr;
- TlocalApiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
-
- if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
- getNodeState().getSingleUserApi())
- {
- jam();
- Uint32 val = ctcTimer - ptr.p->scanFragTimer;
- if (val <= old_time_out_param)
- {
- jam();
- goto next;
- }
- }
- }
-
- /*-------------------------------------------------------------------------*/
- // The scan fragment has expired its timeout. Check its state to decide
- // what to do.
- /*-------------------------------------------------------------------------*/
- switch (ptr.p->scanFragState) {
- case ScanFragRec::WAIT_GET_PRIMCONF:
- jam();
- ndbrequire(false);
- break;
- case ScanFragRec::LQH_ACTIVE:{
- jam();
-
- /**
- * The LQH expired it's timeout, try to close it
- */
- Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
- Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
- ScanRecordPtr scanptr;
- scanptr.i = ptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- if(connectCount != ptr.p->m_connectCount){
- jam();
- /**
- * The node has died
- */
- ptr.p->scanFragState = ScanFragRec::COMPLETED;
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
-
- run.release(ptr);
- ptr.p->stopFragTimer();
- }
-
- scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
- break;
- }
- case ScanFragRec::DELIVERED:
- jam();
- case ScanFragRec::IDLE:
- jam();
- case ScanFragRec::QUEUED_FOR_DELIVERY:
- jam();
- /*-----------------------------------------------------------------------
- * Should never occur. We will simply report set the timer to zero and
- * continue. In a debug version we should crash here but not in a release
- * version. In a release version we will simply set the time-out to zero.
- *-----------------------------------------------------------------------*/
-#ifdef VM_TRACE
- systemErrorLab(signal, __LINE__);
-#endif
- scanFragptr.p->stopFragTimer();
- break;
- default:
- jam();
- /*-----------------------------------------------------------------------
- * Non-existent state. Crash.
- *-----------------------------------------------------------------------*/
- systemErrorLab(signal, __LINE__);
- break;
- }//switch
-
-next:
- signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
- signal->theData[1] = TscanConPtr + 1;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
-}//timeOutFoundFragLab()
-
-
-/*
- 4.3.16 GCP_NOMORETRANS
- ----------------------
-*/
-/*****************************************************************************
- * G C P _ N O M O R E T R A N S
- *
- * WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
- * THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
- * SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
- * CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
- * FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
- * COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
- * THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
- * THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
- * TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
- *****************************************************************************/
-void Dbtc::execGCP_NOMORETRANS(Signal* signal)
-{
- jamEntry();
- c_gcp_ref = signal->theData[0];
- tcheckGcpId = signal->theData[1];
- if (cfirstgcp != RNIL) {
- jam();
- /* A GLOBAL CHECKPOINT IS GOING ON */
- gcpPtr.i = cfirstgcp; /* SET POINTER TO FIRST GCP IN QUEUE*/
- ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
- if (gcpPtr.p->gcpId == tcheckGcpId) {
- jam();
- if (gcpPtr.p->firstApiConnect != RNIL) {
- jam();
- gcpPtr.p->gcpNomoretransRec = ZTRUE;
- } else {
- jam();
- gcpTcfinished(signal);
- unlinkGcp(signal);
- }//if
- } else {
- jam();
- /*------------------------------------------------------------*/
- /* IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO */
- /* RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE */
- /* THE GLOBAL CHECKPOINTS IN ORDER. */
- /*------------------------------------------------------------*/
- gcpTcfinished(signal);
- }//if
- } else {
- jam();
- gcpTcfinished(signal);
- }//if
- return;
-}//Dbtc::execGCP_NOMORETRANS()
-
-/*****************************************************************************/
-/* */
-/* TAKE OVER MODULE */
-/* */
-/*****************************************************************************/
-/* */
-/* THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE */
-/* NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT */
-/* ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE */
-/* FAILED. */
-/* */
-/* AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
-/* CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
-/* COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED. */
-/* IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO */
-/* WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT. */
-/*****************************************************************************/
-void Dbtc::execNODE_FAILREP(Signal* signal)
-{
- jamEntry();
-
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
-
- cfailure_nr = nodeFail->failNo;
- const Uint32 tnoOfNodes = nodeFail->noOfNodes;
- const Uint32 tnewMasterId = nodeFail->masterNodeId;
-
- arrGuard(tnoOfNodes, MAX_NDB_NODES);
- Uint32 i;
- int index = 0;
- for (i = 1; i< MAX_NDB_NODES; i++)
- {
- if(NodeBitmask::get(nodeFail->theNodes, i))
- {
- cdata[index] = i;
- index++;
- }//if
- }//for
-
- cmasterNodeId = tnewMasterId;
-
- tcNodeFailptr.i = 0;
- ptrAss(tcNodeFailptr, tcFailRecord);
- for (i = 0; i < tnoOfNodes; i++)
- {
- jam();
- hostptr.i = cdata[i];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
-
- /*------------------------------------------------------------*/
- /* SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS */
- /* FAILED. */
- /*------------------------------------------------------------*/
- hostptr.p->hostStatus = HS_DEAD;
- hostptr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
- c_alive_nodes.clear(hostptr.i);
-
- if (tcNodeFailptr.p->failStatus == FS_LISTENING)
- {
- jam();
- /*------------------------------------------------------------*/
- /* THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE */
- /* FAILURE. */
- /*------------------------------------------------------------*/
- if (hostptr.p->lqhTransStatus == LTS_ACTIVE)
- {
- jam();
- /*------------------------------------------------------------*/
- /* WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
- /* PROTOCOL FOR TC. */
- /*------------------------------------------------------------*/
- signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
- signal->theData[1] = hostptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
- }//if
-
- if (getOwnNodeId() != tnewMasterId)
- {
- jam();
- /**
- * Only master does takeover currently
- */
- hostptr.p->m_nf_bits &= ~HostRecord::NF_TAKEOVER;
- }
- else
- {
- jam();
- signal->theData[0] = hostptr.i;
- sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
- }
-
- checkScanActiveInFailedLqh(signal, 0, hostptr.i);
- checkWaitDropTabFailedLqh(signal, hostptr.i, 0); // nodeid, tableid
- nodeFailCheckTransactions(signal, 0, hostptr.i);
- }
-}//Dbtc::execNODE_FAILREP()
-
-void
-Dbtc::checkNodeFailComplete(Signal* signal,
- Uint32 failedNodeId,
- Uint32 bit)
-{
- hostptr.i = failedNodeId;
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- hostptr.p->m_nf_bits &= ~bit;
- if (hostptr.p->m_nf_bits == 0)
- {
- NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
- nfRep->blockNo = DBTC;
- nfRep->nodeId = cownNodeid;
- nfRep->failedNodeId = hostptr.i;
- sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBB);
- }
-}
-
-void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
- Uint32 scanPtrI,
- Uint32 failedNodeId){
-
- ScanRecordPtr scanptr;
- for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
- jam();
- ptrAss(scanptr, scanRecord);
- bool found = false;
- if (scanptr.p->scanState != ScanRecord::IDLE){
- jam();
- ScanFragRecPtr ptr;
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
-
- for(run.first(ptr); !ptr.isNull(); ){
- jam();
- ScanFragRecPtr curr = ptr;
- run.next(ptr);
- if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
- refToNode(curr.p->lqhBlockref) == failedNodeId){
- jam();
-
- run.release(curr);
- curr.p->scanFragState = ScanFragRec::COMPLETED;
- curr.p->stopFragTimer();
- found = true;
- }
- }
-
- ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags);
- for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
- {
- jam();
- if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
- {
- jam();
- found = true;
- break;
- }
- }
- }
- if(found){
- jam();
- scanError(signal, scanptr, ZSCAN_LQH_ERROR);
- }
-
- // Send CONTINUEB to continue later
- signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
- signal->theData[1] = scanptr.i + 1; // Check next scanptr
- signal->theData[2] = failedNodeId;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- return;
- }//for
-
- checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
-}
-
-void
-Dbtc::nodeFailCheckTransactions(Signal* signal,
- Uint32 transPtrI,
- Uint32 failedNodeId)
-{
- jam();
- Ptr<ApiConnectRecord> transPtr;
- Uint32 TtcTimer = ctcTimer;
- Uint32 TapplTimeout = c_appl_timeout_value;
- for (transPtr.i = transPtrI; transPtr.i < capiConnectFilesize; transPtr.i++)
- {
- ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
- if (transPtr.p->m_transaction_nodes.get(failedNodeId))
- {
- jam();
-
- // Force timeout regardless of state
- c_appl_timeout_value = 1;
- setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__);
- timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
- c_appl_timeout_value = TapplTimeout;
- }
-
- // Send CONTINUEB to continue later
- signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
- signal->theData[1] = transPtr.i + 1; // Check next
- signal->theData[2] = failedNodeId;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- return;
- }
-
- checkNodeFailComplete(signal, failedNodeId,
- HostRecord::NF_CHECK_TRANSACTION);
-}
-
-
-void
-Dbtc::checkScanFragList(Signal* signal,
- Uint32 failedNodeId,
- ScanRecord * scanP,
- ScanFragList::Head & head){
-
- DEBUG("checkScanActiveInFailedLqh: scanFragError");
-}
-
-void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
-{
- jamEntry();
- tfailedNodeId = signal->theData[0];
- hostptr.i = tfailedNodeId;
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
-
- if (signal->getSendersBlockRef() != reference())
- {
- jam();
- return;
- }
-
- checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
-}//Dbtc::execTAKE_OVERTCCONF()
-
-void Dbtc::execTAKE_OVERTCREQ(Signal* signal)
-{
- jamEntry();
- tfailedNodeId = signal->theData[0];
- tcNodeFailptr.i = 0;
- ptrAss(tcNodeFailptr, tcFailRecord);
- if (tcNodeFailptr.p->failStatus != FS_IDLE) {
- jam();
- /*------------------------------------------------------------*/
- /* WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
- /*------------------------------------------------------------*/
- /* IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL */
- /* QUEUE THE TAKE OVER AND START IT AS SOON AS THE */
- /* PREVIOUS ARE COMPLETED. */
- /*------------------------------------------------------------*/
- arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
- tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = tfailedNodeId;
- tcNodeFailptr.p->queueIndex = tcNodeFailptr.p->queueIndex + 1;
- return;
- }//if
- startTakeOverLab(signal);
-}//Dbtc::execTAKE_OVERTCREQ()
-
-/*------------------------------------------------------------*/
-/* INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS */
-/* AND OPERATIONS DURING TC TAKE OVER. */
-/*------------------------------------------------------------*/
-void Dbtc::startTakeOverLab(Signal* signal)
-{
- for (tindex = 0; tindex <= 511; tindex++) {
- ctransidFailHash[tindex] = RNIL;
- }//for
- for (tindex = 0; tindex <= 1023; tindex++) {
- ctcConnectFailHash[tindex] = RNIL;
- }//for
- tcNodeFailptr.p->failStatus = FS_LISTENING;
- tcNodeFailptr.p->takeOverNode = tfailedNodeId;
- for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
- jam();
- ptrAss(hostptr, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- jam();
- tblockref = calcLqhBlockRef(hostptr.i);
- hostptr.p->lqhTransStatus = LTS_ACTIVE;
- signal->theData[0] = tcNodeFailptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = tfailedNodeId;
- sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB);
- }//if
- }//for
-}//Dbtc::startTakeOverLab()
-
-/*------------------------------------------------------------*/
-/* A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
-/*------------------------------------------------------------*/
-void Dbtc::execLQH_TRANSCONF(Signal* signal)
-{
- jamEntry();
- LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
-
- tcNodeFailptr.i = lqhTransConf->tcRef;
- ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
- tnodeid = lqhTransConf->lqhNodeId;
- ttransStatus = (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
- ttransid1 = lqhTransConf->transId1;
- ttransid2 = lqhTransConf->transId2;
- ttcOprec = lqhTransConf->oldTcOpRec;
- treqinfo = lqhTransConf->requestInfo;
- tgci = lqhTransConf->gci;
- cnodes[0] = lqhTransConf->nextNodeId1;
- cnodes[1] = lqhTransConf->nextNodeId2;
- cnodes[2] = lqhTransConf->nextNodeId3;
- const Uint32 ref = tapplRef = lqhTransConf->apiRef;
- tapplOprec = lqhTransConf->apiOpRec;
- const Uint32 tableId = lqhTransConf->tableId;
-
- if (ttransStatus == LqhTransConf::LastTransConf){
- jam();
- /*------------------------------------------------------------*/
- /* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
- /*------------------------------------------------------------*/
- nodeTakeOverCompletedLab(signal);
- return;
- }//if
- if (ttransStatus == LqhTransConf::Marker){
- jam();
- treqinfo = 0;
- LqhTransConf::setMarkerFlag(treqinfo, 1);
- } else {
- TableRecordPtr tabPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
- switch((DictTabInfo::TableType)tabPtr.p->tableType){
- case DictTabInfo::SystemTable:
- case DictTabInfo::UserTable:
- break;
- default:
- tapplRef = 0;
- tapplOprec = 0;
- }
- }
-
- findApiConnectFail(signal);
-
- if(apiConnectptr.p->ndbapiBlockref == 0 && tapplRef != 0){
- apiConnectptr.p->ndbapiBlockref = ref;
- apiConnectptr.p->ndbapiConnect = tapplOprec;
- }
-
- if (ttransStatus != LqhTransConf::Marker){
- jam();
- findTcConnectFail(signal);
- }
-}//Dbtc::execLQH_TRANSCONF()
-
-/*------------------------------------------------------------*/
-/* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
-/*------------------------------------------------------------*/
-void Dbtc::nodeTakeOverCompletedLab(Signal* signal)
-{
- Uint32 guard0;
-
- hostptr.i = tnodeid;
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- hostptr.p->lqhTransStatus = LTS_IDLE;
- for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
- jam();
- ptrAss(hostptr, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
- jam();
- /*------------------------------------------------------------*/
- /* NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE */
- /* TAKE OVER. */
- /*------------------------------------------------------------*/
- return;
- }//if
- }//if
- }//for
- /*------------------------------------------------------------*/
- /* ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
- /* OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE */
- /* ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE */
- /* TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN */
- /* UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
- /* TO THE APPLICATION IF THAT IS STILL ALIVE. */
- /*------------------------------------------------------------*/
- tcNodeFailptr.p->currentHashIndexTakeOver = 0;
- tcNodeFailptr.p->completedTakeOver = 0;
- tcNodeFailptr.p->failStatus = FS_COMPLETING;
- guard0 = cnoParallelTakeOver - 1;
- /*------------------------------------------------------------*/
- /* WE WILL COMPLETE THE TRANSACTIONS BY STARTING A */
- /* NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL */
- /* COMPLETE ONE TRANSACTION AT A TIME AND IN THAT */
- /* TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
- /* WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
- /* IS COMPLETED. */
- /*------------------------------------------------------------*/
- arrGuard(guard0, MAX_NDB_NODES);
- for (tindex = 0; tindex <= guard0; tindex++) {
- jam();
- tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
- signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
- signal->theData[1] = tcNodeFailptr.i;
- signal->theData[2] = tindex;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- }//for
-}//Dbtc::nodeTakeOverCompletedLab()
-
-/*------------------------------------------------------------*/
-/* COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF */
-/* TRANSACTIONS TO COMPLETE. */
-/*------------------------------------------------------------*/
-void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
-{
- jam();
- while (tcNodeFailptr.p->currentHashIndexTakeOver < 512){
- jam();
- apiConnectptr.i =
- ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
- if (apiConnectptr.i != RNIL) {
- jam();
- /*------------------------------------------------------------*/
- /* WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE */
- /* COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT */
- /* NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS */
- /* TRANSACTION. */
- /*------------------------------------------------------------*/
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
- apiConnectptr.p->nextApiConnect;
-
- completeTransAtTakeOverDoOne(signal, TtakeOverInd);
- // One transaction taken care of, return from this function
- // and wait for the next CONTINUEB to continue processing
- break;
-
- } else {
- if (tcNodeFailptr.p->currentHashIndexTakeOver < 511){
- jam();
- tcNodeFailptr.p->currentHashIndexTakeOver++;
- } else {
- jam();
- completeTransAtTakeOverDoLast(signal, TtakeOverInd);
- tcNodeFailptr.p->currentHashIndexTakeOver++;
- }//if
- }//if
- }//while
-}//Dbtc::completeTransAtTakeOverLab()
-
-
-
-
-void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
-{
- Uint32 guard0;
- /*------------------------------------------------------------*/
- /* THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS */
- /* ACTIVITY IS COMPLETED. */
- /*------------------------------------------------------------*/
- arrGuard(TtakeOverInd, MAX_NDB_NODES);
- if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
- tcNodeFailptr.p->completedTakeOver++;
-
- if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
- jam();
- /*------------------------------------------------------------*/
- /* WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
- /* TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL */
- /* NODES THAT ARE ALIVE. */
- /*------------------------------------------------------------*/
- NodeReceiverGroup rg(DBTC, c_alive_nodes);
- signal->theData[0] = tcNodeFailptr.p->takeOverNode;
- sendSignal(rg, GSN_TAKE_OVERTCCONF, signal, 1, JBB);
-
- if (tcNodeFailptr.p->queueIndex > 0) {
- jam();
- /*------------------------------------------------------------*/
- /* THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START */
- /* THE TAKE OVER. */
- /*------------------------------------------------------------*/
- tfailedNodeId = tcNodeFailptr.p->queueList[0];
- guard0 = tcNodeFailptr.p->queueIndex - 1;
- arrGuard(guard0 + 1, MAX_NDB_NODES);
- for (tindex = 0; tindex <= guard0; tindex++) {
- jam();
- tcNodeFailptr.p->queueList[tindex] =
- tcNodeFailptr.p->queueList[tindex + 1];
- }//for
- tcNodeFailptr.p->queueIndex--;
- startTakeOverLab(signal);
- return;
- } else {
- jam();
- tcNodeFailptr.p->failStatus = FS_IDLE;
- }//if
- }//if
- return;
-}//Dbtc::completeTransAtTakeOverDoLast()
-
-void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
-{
- apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
- apiConnectptr.p->takeOverInd = TtakeOverInd;
-
- switch (apiConnectptr.p->apiConnectstate) {
- case CS_FAIL_COMMITTED:
- jam();
- /*------------------------------------------------------------*/
- /* ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
- /* HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT */
- /* COMMITTED TO THE APPLICATION AND CONTINUE WITH THE */
- /* COMPLETE PHASE. */
- /*------------------------------------------------------------*/
- sendTCKEY_FAILCONF(signal, apiConnectptr.p);
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.p->currentTcConnect = tcConnectptr.i;
- apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
- toCompleteHandlingLab(signal);
- return;
- case CS_FAIL_COMMITTING:
- jam();
- /*------------------------------------------------------------*/
- /* AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
- /* PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
- /* THEN CONTINUE AS AFTER COMMITTED. */
- /*------------------------------------------------------------*/
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.p->currentTcConnect = tcConnectptr.i;
- apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
- toCommitHandlingLab(signal);
- return;
- case CS_FAIL_ABORTING:
- case CS_FAIL_PREPARED:
- jam();
- /*------------------------------------------------------------*/
- /* WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
- /* STATE IN THIS VERSION. IN LATER VERSIONS WE WILL */
- /* HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT */
- /* TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
- /* HAVE HEARD FROM THE TRANSACTION COORDINATOR. */
- /* */
- /* IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE */
- /* PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL */
- /* LATER VERSIONS. */
- /*------------------------------------------------------------*/
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.p->currentTcConnect = tcConnectptr.i;
- apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
- toAbortHandlingLab(signal);
- return;
- case CS_FAIL_ABORTED:
- jam();
- sendTCKEY_FAILREF(signal, apiConnectptr.p);
-
- signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
- signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
- signal->theData[2] = apiConnectptr.p->takeOverInd;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- releaseTakeOver(signal);
- break;
- case CS_FAIL_COMPLETED:
- jam();
- sendTCKEY_FAILCONF(signal, apiConnectptr.p);
-
- signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
- signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
- signal->theData[2] = apiConnectptr.p->takeOverInd;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- releaseApiConnectFail(signal);
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
-}//Dbtc::completeTransAtTakeOverDoOne()
-
-void
-Dbtc::sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord * regApiPtr){
- jam();
-
- const Uint32 ref = regApiPtr->ndbapiBlockref;
- if(ref != 0){
- signal->theData[0] = regApiPtr->ndbapiConnect;
- signal->theData[1] = regApiPtr->transid[0];
- signal->theData[2] = regApiPtr->transid[1];
-
- sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
- }
-}
-
-void
-Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
- jam();
- TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
-
- const Uint32 ref = regApiPtr->ndbapiBlockref;
- const Uint32 marker = regApiPtr->commitAckMarker;
- if(ref != 0){
- failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
- failConf->transId1 = regApiPtr->transid[0];
- failConf->transId2 = regApiPtr->transid[1];
-
- sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB);
- }
- regApiPtr->commitAckMarker = RNIL;
-}
-
-/*------------------------------------------------------------*/
-/* THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A */
-/* NODE FAILURE BEFORE THE COMMIT DECISION. */
-/*------------------------------------------------------------*/
-/* ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
-/*------------------------------------------------------------*/
-void Dbtc::execABORTCONF(Signal* signal)
-{
- UintR compare_transid1, compare_transid2;
-
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- tnodeid = signal->theData[2];
- if (ERROR_INSERTED(8045)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
- return;
- }//if
- if (tcConnectptr.i >= ctcConnectFilesize) {
- errorReport(signal, 5);
- return;
- }//if
- ptrAss(tcConnectptr, tcConnectRecord);
- if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
- warningReport(signal, 16);
- return;
- }//if
- apiConnectptr.i = tcConnectptr.p->apiConnect;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
- warningReport(signal, 17);
- return;
- }//if
- compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
- compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- warningReport(signal, 18);
- return;
- }//if
- arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
- if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
- tnodeid) {
- warningReport(signal, 19);
- return;
- }//if
- tcurrentReplicaNo = (Uint8)Z8NIL;
- tcConnectptr.p->tcConnectstate = OS_ABORTING;
- toAbortHandlingLab(signal);
-}//Dbtc::execABORTCONF()
-
-void Dbtc::toAbortHandlingLab(Signal* signal)
-{
- do {
- if (tcurrentReplicaNo != (Uint8)Z8NIL) {
- jam();
- arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
- const LqhTransConf::OperationStatus stat =
- (LqhTransConf::OperationStatus)
- tcConnectptr.p->failData[tcurrentReplicaNo];
- switch(stat){
- case LqhTransConf::InvalidStatus:
- case LqhTransConf::Aborted:
- jam();
- /*empty*/;
- break;
- case LqhTransConf::Prepared:
- jam();
- hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- jam();
- tblockref = calcLqhBlockRef(hostptr.i);
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
- apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
- apiConnectptr.p->timeOutCounter = 0;
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = apiConnectptr.p->transid[0];
- signal->theData[3] = apiConnectptr.p->transid[1];
- signal->theData[4] = apiConnectptr.p->tcBlockref;
- signal->theData[5] = tcConnectptr.p->tcOprec;
- sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
- return;
- }//if
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//switch
- }//if
- if (apiConnectptr.p->currentReplicaNo > 0) {
- jam();
- /*------------------------------------------------------------*/
- /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
- /* ABORTED. */
- /*------------------------------------------------------------*/
- apiConnectptr.p->currentReplicaNo--;
- tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
- } else {
- /*------------------------------------------------------------*/
- /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
- /*------------------------------------------------------------*/
- tcConnectptr.i = tcConnectptr.p->nextTcConnect;
- if (tcConnectptr.i == RNIL) {
- /*------------------------------------------------------------*/
- /* WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
- /* THE ABORT STATUS TO THE APPLICATION AND CONTINUE */
- /* WITH THE NEXT TRANSACTION. */
- /*------------------------------------------------------------*/
- if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
- jam();
- sendTCKEY_FAILREF(signal, apiConnectptr.p);
- const Uint32 marker = apiConnectptr.p->commitAckMarker;
- if(marker != RNIL){
- jam();
-
- CommitAckMarkerPtr tmp;
- tmp.i = marker;
- tmp.p = m_commitAckMarkerHash.getPtr(tmp.i);
-
- m_commitAckMarkerHash.release(tmp);
- apiConnectptr.p->commitAckMarker = RNIL;
- }
-
- /*------------------------------------------------------------*/
- /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
- /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
- /*------------------------------------------------------------*/
- signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
- signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
- signal->theData[2] = apiConnectptr.p->takeOverInd;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- releaseTakeOver(signal);
- } else {
- jam();
- releaseAbortResources(signal);
- }//if
- return;
- }//if
- apiConnectptr.p->currentTcConnect = tcConnectptr.i;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
- }//if
- } while (1);
-}//Dbtc::toAbortHandlingLab()
-
-/*------------------------------------------------------------*/
-/* THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A */
-/* NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE. */
-/*------------------------------------------------------------*/
-/* COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
-/*------------------------------------------------------------*/
-void Dbtc::execCOMMITCONF(Signal* signal)
-{
- UintR compare_transid1, compare_transid2;
-
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- tnodeid = signal->theData[1];
- if (ERROR_INSERTED(8046)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
- return;
- }//if
- if (tcConnectptr.i >= ctcConnectFilesize) {
- errorReport(signal, 4);
- return;
- }//if
- ptrAss(tcConnectptr, tcConnectRecord);
- if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
- warningReport(signal, 8);
- return;
- }//if
- apiConnectptr.i = tcConnectptr.p->apiConnect;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
- warningReport(signal, 9);
- return;
- }//if
- compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
- compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- warningReport(signal, 10);
- return;
- }//if
- arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
- if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
- tnodeid) {
- warningReport(signal, 11);
- return;
- }//if
- if (ERROR_INSERTED(8026)) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- tcurrentReplicaNo = (Uint8)Z8NIL;
- tcConnectptr.p->tcConnectstate = OS_COMMITTED;
- toCommitHandlingLab(signal);
-}//Dbtc::execCOMMITCONF()
-
-void Dbtc::toCommitHandlingLab(Signal* signal)
-{
- do {
- if (tcurrentReplicaNo != (Uint8)Z8NIL) {
- jam();
- arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
- switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
- case LqhTransConf::InvalidStatus:
- jam();
- /*empty*/;
- break;
- case LqhTransConf::Committed:
- jam();
- /*empty*/;
- break;
- case LqhTransConf::Prepared:
- jam();
- /*------------------------------------------------------------*/
- /* THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR */
- /* COMMIT REQUEST FROM TC. */
- /*------------------------------------------------------------*/
- hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- jam();
- tblockref = calcLqhBlockRef(hostptr.i);
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
- apiConnectptr.p->timeOutCounter = 0;
- tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = apiConnectptr.p->globalcheckpointid;
- signal->theData[3] = apiConnectptr.p->transid[0];
- signal->theData[4] = apiConnectptr.p->transid[1];
- signal->theData[5] = apiConnectptr.p->tcBlockref;
- signal->theData[6] = tcConnectptr.p->tcOprec;
- sendSignal(tblockref, GSN_COMMITREQ, signal, 7, JBB);
- return;
- }//if
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
- }//if
- if (apiConnectptr.p->currentReplicaNo > 0) {
- jam();
- /*------------------------------------------------------------*/
- /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
- /* COMMITTED. */
- /*------------------------------------------------------------*/
- apiConnectptr.p->currentReplicaNo--;
- tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
- } else {
- /*------------------------------------------------------------*/
- /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
- /*------------------------------------------------------------*/
- tcConnectptr.i = tcConnectptr.p->nextTcConnect;
- if (tcConnectptr.i == RNIL) {
- /*------------------------------------------------------------*/
- /* WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
- /* THE COMMIT STATUS TO THE APPLICATION AND CONTINUE */
- /* WITH THE COMPLETE PHASE. */
- /*------------------------------------------------------------*/
- if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
- jam();
- sendTCKEY_FAILCONF(signal, apiConnectptr.p);
- } else {
- jam();
- sendApiCommit(signal);
- }//if
- apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
- apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
- toCompleteHandlingLab(signal);
- return;
- }//if
- apiConnectptr.p->currentTcConnect = tcConnectptr.i;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
- }//if
- } while (1);
-}//Dbtc::toCommitHandlingLab()
-
-/*------------------------------------------------------------*/
-/* COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE */
-/* HAVE FAILED. */
-/*------------------------------------------------------------*/
-/* THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION */
-/*------------------------------------------------------------*/
-void Dbtc::execCOMPLETECONF(Signal* signal)
-{
- UintR compare_transid1, compare_transid2;
-
- jamEntry();
- tcConnectptr.i = signal->theData[0];
- tnodeid = signal->theData[1];
- if (ERROR_INSERTED(8047)) {
- CLEAR_ERROR_INSERT_VALUE;
- sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
- return;
- }//if
- if (tcConnectptr.i >= ctcConnectFilesize) {
- errorReport(signal, 3);
- return;
- }//if
- ptrAss(tcConnectptr, tcConnectRecord);
- if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
- warningReport(signal, 12);
- return;
- }//if
- apiConnectptr.i = tcConnectptr.p->apiConnect;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
- warningReport(signal, 13);
- return;
- }//if
- compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
- compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
- compare_transid1 = compare_transid1 | compare_transid2;
- if (compare_transid1 != 0) {
- warningReport(signal, 14);
- return;
- }//if
- arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
- if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
- tnodeid) {
- warningReport(signal, 15);
- return;
- }//if
- if (ERROR_INSERTED(8028)) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- tcConnectptr.p->tcConnectstate = OS_COMPLETED;
- tcurrentReplicaNo = (Uint8)Z8NIL;
- toCompleteHandlingLab(signal);
-}//Dbtc::execCOMPLETECONF()
-
-void Dbtc::toCompleteHandlingLab(Signal* signal)
-{
- do {
- if (tcurrentReplicaNo != (Uint8)Z8NIL) {
- jam();
- arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
- switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
- case LqhTransConf::InvalidStatus:
- jam();
- /*empty*/;
- break;
- default:
- jam();
- /*------------------------------------------------------------*/
- /* THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
- /* IT MUST HAVE FAILED. */
- /*------------------------------------------------------------*/
- /*------------------------------------------------------------*/
- /* SEND COMPLETEREQ TO THE NEXT REPLICA. */
- /*------------------------------------------------------------*/
- hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus == HS_ALIVE) {
- jam();
- tblockref = calcLqhBlockRef(hostptr.i);
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
- apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
- apiConnectptr.p->timeOutCounter = 0;
- tcConnectptr.p->apiConnect = apiConnectptr.i;
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = apiConnectptr.p->transid[0];
- signal->theData[3] = apiConnectptr.p->transid[1];
- signal->theData[4] = apiConnectptr.p->tcBlockref;
- signal->theData[5] = tcConnectptr.p->tcOprec;
- sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
- return;
- }//if
- break;
- }//switch
- }//if
- if (apiConnectptr.p->currentReplicaNo != 0) {
- jam();
- /*------------------------------------------------------------*/
- /* THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE */
- /* NEED TO CONTINUE WITH THOSE REPLICAS. */
- /*------------------------------------------------------------*/
- apiConnectptr.p->currentReplicaNo--;
- tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
- } else {
- tcConnectptr.i = tcConnectptr.p->nextTcConnect;
- if (tcConnectptr.i == RNIL) {
- /*------------------------------------------------------------*/
- /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
- /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
- /*------------------------------------------------------------*/
- if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
- jam();
- signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
- signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
- signal->theData[2] = apiConnectptr.p->takeOverInd;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- releaseTakeOver(signal);
- } else {
- jam();
- releaseTransResources(signal);
- }//if
- return;
- }//if
- /*------------------------------------------------------------*/
- /* WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
- /* COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
- /* FIRST REPLICA SINCE IT IS THE COMPLETE PHASE. */
- /*------------------------------------------------------------*/
- apiConnectptr.p->currentTcConnect = tcConnectptr.i;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
- apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
- }//if
- } while (1);
-}//Dbtc::toCompleteHandlingLab()
-
-/*------------------------------------------------------------*/
-/* */
-/* FIND THE API CONNECT RECORD FOR THIS TRANSACTION */
-/* DURING TAKE OVER FROM A FAILED TC. IF NONE EXISTS */
-/* YET THEN SEIZE A NEW API CONNECT RECORD AND LINK IT */
-/* INTO THE HASH TABLE. */
-/*------------------------------------------------------------*/
-void Dbtc::findApiConnectFail(Signal* signal)
-{
- ApiConnectRecordPtr fafPrevApiConnectptr;
- ApiConnectRecordPtr fafNextApiConnectptr;
- UintR tfafHashNumber;
-
- tfafHashNumber = ttransid1 & 511;
- fafPrevApiConnectptr.i = RNIL;
- ptrNull(fafPrevApiConnectptr);
- arrGuard(tfafHashNumber, 512);
- fafNextApiConnectptr.i = ctransidFailHash[tfafHashNumber];
- ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
-FAF_LOOP:
- jam();
- if (fafNextApiConnectptr.i == RNIL) {
- jam();
- if (cfirstfreeApiConnectFail == RNIL) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- seizeApiConnectFail(signal);
- if (fafPrevApiConnectptr.i == RNIL) {
- jam();
- ctransidFailHash[tfafHashNumber] = apiConnectptr.i;
- } else {
- jam();
- ptrGuard(fafPrevApiConnectptr);
- fafPrevApiConnectptr.p->nextApiConnect = apiConnectptr.i;
- }//if
- apiConnectptr.p->nextApiConnect = RNIL;
- initApiConnectFail(signal);
- } else {
- jam();
- fafPrevApiConnectptr.i = fafNextApiConnectptr.i;
- fafPrevApiConnectptr.p = fafNextApiConnectptr.p;
- apiConnectptr.i = fafNextApiConnectptr.i;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- fafNextApiConnectptr.i = apiConnectptr.p->nextApiConnect;
- ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
- if ((apiConnectptr.p->transid[1] != ttransid2) ||
- (apiConnectptr.p->transid[0] != ttransid1)) {
- goto FAF_LOOP;
- }//if
- updateApiStateFail(signal);
- }//if
-}//Dbtc::findApiConnectFail()
-
-/*----------------------------------------------------------*/
-/* FIND THE TC CONNECT AND IF NOT FOUND ALLOCATE A NEW */
-/*----------------------------------------------------------*/
-void Dbtc::findTcConnectFail(Signal* signal)
-{
- UintR tftfHashNumber;
-
- tftfHashNumber = (ttransid1 ^ ttcOprec) & 1023;
- tcConnectptr.i = ctcConnectFailHash[tftfHashNumber];
- do {
- if (tcConnectptr.i == RNIL) {
- jam();
- if (cfirstfreeTcConnectFail == RNIL) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- seizeTcConnectFail(signal);
- linkTcInConnectionlist(signal);
- tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[tftfHashNumber];
- ctcConnectFailHash[tftfHashNumber] = tcConnectptr.i;
- initTcConnectFail(signal);
- return;
- } else {
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- if (tcConnectptr.p->tcOprec != ttcOprec) {
- jam(); /* FRAGMENTID = TC_OPREC HERE, LOOP ANOTHER TURN */
- tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
- } else {
- updateTcStateFail(signal);
- return;
- }//if
- }//if
- } while (1);
-}//Dbtc::findTcConnectFail()
-
-/*----------------------------------------------------------*/
-/* INITIALISE AN API CONNECT FAIL RECORD */
-/*----------------------------------------------------------*/
-void Dbtc::initApiConnectFail(Signal* signal)
-{
- apiConnectptr.p->transid[0] = ttransid1;
- apiConnectptr.p->transid[1] = ttransid2;
- apiConnectptr.p->firstTcConnect = RNIL;
- apiConnectptr.p->currSavePointId = 0;
- apiConnectptr.p->lastTcConnect = RNIL;
- tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
-
- apiConnectptr.p->tcBlockref = tblockref;
- apiConnectptr.p->ndbapiBlockref = 0;
- apiConnectptr.p->ndbapiConnect = 0;
- apiConnectptr.p->buddyPtr = RNIL;
- apiConnectptr.p->m_transaction_nodes.clear();
- apiConnectptr.p->singleUserMode = 0;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- switch(ttransStatus){
- case LqhTransConf::Committed:
- jam();
- apiConnectptr.p->globalcheckpointid = tgci;
- apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
- break;
- case LqhTransConf::Prepared:
- jam();
- apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
- break;
- case LqhTransConf::Aborted:
- jam();
- apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
- break;
- case LqhTransConf::Marker:
- jam();
- apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- apiConnectptr.p->commitAckMarker = RNIL;
- if(LqhTransConf::getMarkerFlag(treqinfo)){
- jam();
- CommitAckMarkerPtr tmp;
- m_commitAckMarkerHash.seize(tmp);
-
- ndbrequire(tmp.i != RNIL);
-
- apiConnectptr.p->commitAckMarker = tmp.i;
- tmp.p->transid1 = ttransid1;
- tmp.p->transid2 = ttransid2;
- tmp.p->apiNodeId = refToNode(tapplRef);
- tmp.p->noOfLqhs = 1;
- tmp.p->lqhNodeId[0] = tnodeid;
- tmp.p->apiConnectPtr = apiConnectptr.i;
-
-#if defined VM_TRACE || defined ERROR_INSERT
- {
- CommitAckMarkerPtr check;
- ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
- }
-#endif
- m_commitAckMarkerHash.add(tmp);
- }
-}//Dbtc::initApiConnectFail()
-
-/*------------------------------------------------------------*/
-/* INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
-/* THE TC CONNECT RECORD. */
-/*------------------------------------------------------------*/
-void Dbtc::initTcConnectFail(Signal* signal)
-{
- tcConnectptr.p->apiConnect = apiConnectptr.i;
- tcConnectptr.p->tcOprec = ttcOprec;
- Uint32 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
- for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
- tcConnectptr.p->failData[i] = LqhTransConf::InvalidStatus;
- }//for
- tcConnectptr.p->tcNodedata[treplicaNo] = tnodeid;
- tcConnectptr.p->failData[treplicaNo] = ttransStatus;
- tcConnectptr.p->lastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
- tcConnectptr.p->dirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
-
-}//Dbtc::initTcConnectFail()
-
-/*----------------------------------------------------------*/
-/* INITIALISE TC NODE FAIL RECORD. */
-/*----------------------------------------------------------*/
-void Dbtc::initTcFail(Signal* signal)
-{
- tcNodeFailptr.i = 0;
- ptrAss(tcNodeFailptr, tcFailRecord);
- tcNodeFailptr.p->queueIndex = 0;
- tcNodeFailptr.p->failStatus = FS_IDLE;
-}//Dbtc::initTcFail()
-
-/*----------------------------------------------------------*/
-/* RELEASE_TAKE_OVER */
-/*----------------------------------------------------------*/
-void Dbtc::releaseTakeOver(Signal* signal)
-{
- TcConnectRecordPtr rtoNextTcConnectptr;
-
- rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
- do {
- jam();
- tcConnectptr.i = rtoNextTcConnectptr.i;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
- releaseTcConnectFail(signal);
- } while (rtoNextTcConnectptr.i != RNIL);
- releaseApiConnectFail(signal);
-}//Dbtc::releaseTakeOver()
-
-/*---------------------------------------------------------------------------*/
-/* SETUP_FAIL_DATA */
-/* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE */
-/* FAILURE SITUATIONS. */
-/*---------------------------------------------------------------------------*/
-void Dbtc::setupFailData(Signal* signal)
-{
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- do {
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- switch (tcConnectptr.p->tcConnectstate) {
- case OS_PREPARED:
- case OS_COMMITTING:
- 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 PREPARED AND WAITING FOR
- * COMMIT/ABORT DECISION.
- *------------------------------------------------------------------*/
- 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();
- /*-------------------------------------------------------------------
- * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
- * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
- * COMPLETE MESSAGE.
- *------------------------------------------------------------------*/
- 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.
- *-------------------------------------------------------------------*/
- tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
- }//for
- break;
- default:
- jam();
- sendSystemError(signal, __LINE__);
- break;
- }//switch
- if (tabortInd != ZCOMMIT_SETUP) {
- jam();
- for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
- hostptr.i = tcConnectptr.p->tcNodedata[Ti];
- ptrCheckGuard(hostptr, chostFilesize, hostRecord);
- if (hostptr.p->hostStatus != HS_ALIVE) {
- jam();
- /*-----------------------------------------------------------------
- * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
- *-----------------------------------------------------------------*/
- tabortInd = ZTRUE;
- }//if
- }//for
- }//if
- tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
- tcConnectptr.p->tcOprec = tcConnectptr.i;
- tcConnectptr.i = tcConnectptr.p->nextTcConnect;
- } while (tcConnectptr.i != RNIL);
- apiConnectptr.p->tcBlockref = cownref;
- apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
- tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
-}//Dbtc::setupFailData()
-
-/*----------------------------------------------------------*/
-/* UPDATE THE STATE OF THE API CONNECT FOR THIS PART. */
-/*----------------------------------------------------------*/
-void Dbtc::updateApiStateFail(Signal* signal)
-{
- if(LqhTransConf::getMarkerFlag(treqinfo)){
- jam();
- const Uint32 marker = apiConnectptr.p->commitAckMarker;
- if(marker == RNIL){
- jam();
-
- CommitAckMarkerPtr tmp;
- m_commitAckMarkerHash.seize(tmp);
- ndbrequire(tmp.i != RNIL);
-
- apiConnectptr.p->commitAckMarker = tmp.i;
- tmp.p->transid1 = ttransid1;
- tmp.p->transid2 = ttransid2;
- tmp.p->apiNodeId = refToNode(tapplRef);
- tmp.p->noOfLqhs = 1;
- tmp.p->lqhNodeId[0] = tnodeid;
- tmp.p->apiConnectPtr = apiConnectptr.i;
-#if defined VM_TRACE || defined ERROR_INSERT
- {
- CommitAckMarkerPtr check;
- ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
- }
-#endif
- m_commitAckMarkerHash.add(tmp);
- } else {
- jam();
-
- CommitAckMarkerPtr tmp;
- tmp.i = marker;
- tmp.p = m_commitAckMarkerHash.getPtr(marker);
-
- const Uint32 noOfLqhs = tmp.p->noOfLqhs;
- ndbrequire(noOfLqhs < MAX_REPLICAS);
- tmp.p->lqhNodeId[noOfLqhs] = tnodeid;
- tmp.p->noOfLqhs = (noOfLqhs + 1);
- }
- }
-
- switch (ttransStatus) {
- case LqhTransConf::Committed:
- jam();
- switch (apiConnectptr.p->apiConnectstate) {
- case CS_FAIL_COMMITTING:
- case CS_FAIL_COMMITTED:
- jam();
- ndbrequire(tgci == apiConnectptr.p->globalcheckpointid);
- break;
- case CS_FAIL_PREPARED:
- jam();
- apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
- apiConnectptr.p->globalcheckpointid = tgci;
- break;
- case CS_FAIL_COMPLETED:
- jam();
- apiConnectptr.p->globalcheckpointid = tgci;
- apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- break;
- }//switch
- break;
- case LqhTransConf::Prepared:
- jam();
- switch (apiConnectptr.p->apiConnectstate) {
- case CS_FAIL_COMMITTED:
- jam();
- apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
- break;
- case CS_FAIL_ABORTED:
- jam();
- apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
- break;
- case CS_FAIL_COMMITTING:
- case CS_FAIL_PREPARED:
- case CS_FAIL_ABORTING:
- jam();
- /*empty*/;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- break;
- }//switch
- break;
- case LqhTransConf::Aborted:
- jam();
- switch (apiConnectptr.p->apiConnectstate) {
- case CS_FAIL_COMMITTING:
- case CS_FAIL_COMMITTED:
- jam();
- systemErrorLab(signal, __LINE__);
- break;
- case CS_FAIL_PREPARED:
- jam();
- apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
- break;
- case CS_FAIL_ABORTING:
- case CS_FAIL_ABORTED:
- jam();
- /*empty*/;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- break;
- }//switch
- break;
- case LqhTransConf::Marker:
- jam();
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- break;
- }//switch
-}//Dbtc::updateApiStateFail()
-
-/*------------------------------------------------------------*/
-/* UPDATE_TC_STATE_FAIL */
-/* */
-/* WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
-/* WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY */
-/* BETWEEN THE DIFFERENT REPLICAS. */
-/*------------------------------------------------------------*/
-void Dbtc::updateTcStateFail(Signal* signal)
-{
- const Uint8 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
- const Uint8 tlastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
- const Uint8 tdirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
-
- TcConnectRecord * regTcPtr = tcConnectptr.p;
-
- ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
- ndbrequire(regTcPtr->failData[treplicaNo] == LqhTransConf::InvalidStatus);
- ndbrequire(regTcPtr->lastReplicaNo == tlastReplicaNo);
- ndbrequire(regTcPtr->dirtyOp == tdirtyOp);
-
- regTcPtr->tcNodedata[treplicaNo] = tnodeid;
- regTcPtr->failData[treplicaNo] = ttransStatus;
-}//Dbtc::updateTcStateFail()
-
-void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(8000);
-
- UintR Tuserpointer = signal->theData[0]; /* DBDIH POINTER */
- BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
- signal->theData[0] = Tuserpointer;
- signal->theData[1] = coperationsize;
- sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
-}//Dbtc::execTCGETOPSIZEREQ()
-
-void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
-{
- jamEntry();
- CRASH_INSERTION(8001);
-
- tuserpointer = signal->theData[0];
- tusersblkref = signal->theData[1];
- /* DBDIH BLOCK REFERENCE */
- coperationsize = 0;
- signal->theData[0] = tuserpointer;
- sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
-}//Dbtc::execTC_CLOPSIZEREQ()
-
-/* ######################################################################### */
-/* ####### ERROR MODULE ####### */
-/* ######################################################################### */
-void Dbtc::tabStateErrorLab(Signal* signal)
-{
- terrorCode = ZSTATE_ERROR;
- releaseAtErrorLab(signal);
-}//Dbtc::tabStateErrorLab()
-
-void Dbtc::wrongSchemaVersionErrorLab(Signal* signal)
-{
- const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
-
- TableRecordPtr tabPtr;
- tabPtr.i = tcKeyReq->tableId;
- const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
-
- terrorCode = tabPtr.p->getErrorCode(schemVer);
-
- abortErrorLab(signal);
-}//Dbtc::wrongSchemaVersionErrorLab()
-
-void Dbtc::noFreeConnectionErrorLab(Signal* signal)
-{
- terrorCode = ZNO_FREE_TC_CONNECTION;
- abortErrorLab(signal); /* RECORD. OTHERWISE GOTO ERRORHANDLING */
-}//Dbtc::noFreeConnectionErrorLab()
-
-void Dbtc::aiErrorLab(Signal* signal)
-{
- terrorCode = ZLENGTH_ERROR;
- abortErrorLab(signal);
-}//Dbtc::aiErrorLab()
-
-void Dbtc::seizeAttrbuferrorLab(Signal* signal)
-{
- terrorCode = ZGET_ATTRBUF_ERROR;
- abortErrorLab(signal);
-}//Dbtc::seizeAttrbuferrorLab()
-
-void Dbtc::seizeDatabuferrorLab(Signal* signal)
-{
- terrorCode = ZGET_DATAREC_ERROR;
- releaseAtErrorLab(signal);
-}//Dbtc::seizeDatabuferrorLab()
-
-void Dbtc::releaseAtErrorLab(Signal* signal)
-{
- ptrGuard(tcConnectptr);
- tcConnectptr.p->tcConnectstate = OS_ABORTING;
- /*-------------------------------------------------------------------------*
- * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
- * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
- * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
- * TO HANDLE THIS PROBLEM.
- * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
- * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
- * ANY SIGNALS.
- *-------------------------------------------------------------------------*/
- tcConnectptr.p->noOfNodes = 0;
- abortErrorLab(signal);
-}//Dbtc::releaseAtErrorLab()
-
-void Dbtc::warningHandlerLab(Signal* signal, int line)
-{
- ndbassert(false);
-}//Dbtc::warningHandlerLab()
-
-void Dbtc::systemErrorLab(Signal* signal, int line)
-{
- progError(line, NDBD_EXIT_NDBREQUIRE);
-}//Dbtc::systemErrorLab()
-
-
-/* ######################################################################### *
- * ####### SCAN MODULE ####### *
- * ######################################################################### *
-
- The application orders a scan of a table. We divide the scan into a scan on
- each fragment. The scan uses the primary replicas since the scan might be
- used for an update in a separate transaction.
-
- Scans are always done as a separate transaction. Locks from the scan
- can be overtaken by another transaction. Scans can never lock the entire
- table. Locks are released immediately after the read has been verified
- by the application. There is not even an option to leave the locks.
- The reason is that this would hurt real-time behaviour too much.
-
- -# The first step in handling a scan of a table is to receive all signals
- defining the scan. If failures occur during this step we release all
- resource and reply with SCAN_TABREF providing the error code.
- If system load is too high, the request will not be allowed.
-
- -# The second step retrieves the number of fragments that exist in the
- table. It also ensures that the table actually exist. After this,
- the scan is ready to be parallelised. The idea is that the receiving
- process (hereafter called delivery process) will start up a number
- of scan processes. Each of these scan processes will
- independently scan one fragment at a time. The delivery
- process object is the scan record and the scan process object is
- the scan fragment record plus the scan operation record.
-
- -# The third step is thus performed in parallel. In the third step each
- scan process retrieves the primary replica of the fragment it will
- scan. Then it starts the scan as soon as the load on that node permits.
-
- The LQH returns either when it retrieved the maximum number of tuples or
- when it has retrived at least one tuple and is hindered by a lock to
- retrieve the next tuple. This is to ensure that a scan process never
- can be involved in a deadlock situation.
-
- When the scan process receives a number of tuples to report to the
- application it checks the state of the delivery process. Only one delivery
- at a time is handled by the application. Thus if the delivery process
- has already sent a number of tuples to the application this set of tuples
- are queued.
-
- When the application requests the next set of tuples it is immediately
- delivered if any are queued, otherwise it waits for the next scan
- process that is ready to deliver.
-
-
- ERROR HANDLING
-
- As already mentioned it is rather easy to handle errors before the scan
- processes have started. In this case it is enough to release the resources
- and send SCAN_TAB_REF.
-
- If an error occurs in any of the scan processes then we have to stop all
- scan processes. We do however only stop the delivery process and ask
- the api to order us to close the scan. The reason is that we can easily
- enter into difficult timing problems since the application and this
- block is out of synch we will thus always start by report the error to
- the application and wait for a close request. This error report uses the
- SCAN_TABREF signal with a special error code that the api must check for.
-
-
- CLOSING AN ACTIVE SCAN
-
- The application can close a scan for several reasons before it is completed.
- One reason was mentioned above where an error in a scan process led to a
- request to close the scan. Another reason could simply be that the
- application found what it looked for and is thus not interested in the
- rest of the scan.
-
- IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
-
- When a close scan request is received, all scan processes are stopped and all
- resources belonging to those scan processes are released. Stopping the scan
- processes most often includes communication with an LQH where the local scan
- is controlled. Finally all resources belonging to the scan is released and
- the SCAN_TABCONF is sent with an indication of that the scan is closed.
-
-
- CLOSING A COMPLETED SCAN
-
- When all scan processes are completed then a report is sent to the
- application which indicates that no more tuples can be fetched.
- The application will send a close scan and the same action as when
- closing an active scan is performed.
- In this case it will of course not find any active scan processes.
- It will even find all scan processes already released.
-
- The reason for requiring the api to close the scan is the same as above.
- It is to avoid any timing problems due to that the api and this block
- is out of synch.
-
- * ######################################################################## */
-void Dbtc::execSCAN_TABREQ(Signal* signal)
-{
- const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
- const Uint32 ri = scanTabReq->requestInfo;
- const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
- const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
- const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
- const Uint32 transid1 = scanTabReq->transId1;
- const Uint32 transid2 = scanTabReq->transId2;
- const Uint32 tmpXX = scanTabReq->buddyConPtr;
- const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
- Uint32 currSavePointId = 0;
-
- Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
- Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
- Uint32 scanParallel = scanConcurrency;
- Uint32 errCode;
- ScanRecordPtr scanptr;
-
- jamEntry();
-
- SegmentedSectionPtr api_op_ptr;
- signal->getSection(api_op_ptr, 0);
- copy(&cdata[0], api_op_ptr);
- releaseSections(signal);
-
- apiConnectptr.i = scanTabReq->apiConnectPtr;
- tabptr.i = scanTabReq->tableId;
-
- if (apiConnectptr.i >= capiConnectFilesize)
- {
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }//if
-
- ptrAss(apiConnectptr, apiConnectRecord);
- ApiConnectRecord * transP = apiConnectptr.p;
-
- if (transP->apiConnectstate != CS_CONNECTED) {
- jam();
- // could be left over from TCKEYREQ rollback
- if (transP->apiConnectstate == CS_ABORTING &&
- transP->abortState == AS_IDLE) {
- jam();
- } else if(transP->apiConnectstate == CS_STARTED &&
- transP->firstTcConnect == RNIL){
- jam();
- // left over from simple/dirty read
- } else {
- jam();
- jamLine(transP->apiConnectstate);
- errCode = ZSTATE_ERROR;
- goto SCAN_TAB_error_no_state_change;
- }
- }
-
- if(tabptr.i >= ctabrecFilesize)
- {
- errCode = ZUNKNOWN_TABLE_ERROR;
- goto SCAN_TAB_error;
- }
-
- ptrAss(tabptr, tableRecord);
- if ((aiLength == 0) ||
- (!tabptr.p->checkTable(schemaVersion)) ||
- (scanConcurrency == 0) ||
- (cfirstfreeTcConnect == RNIL) ||
- (cfirstfreeScanrec == RNIL)) {
- goto SCAN_error_check;
- }
- if (buddyPtr != RNIL) {
- jam();
- ApiConnectRecordPtr buddyApiPtr;
- buddyApiPtr.i = buddyPtr;
- ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
- if ((transid1 == buddyApiPtr.p->transid[0]) &&
- (transid2 == buddyApiPtr.p->transid[1])) {
- jam();
-
- if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
- // transaction has been aborted
- jam();
- errCode = buddyApiPtr.p->returncode;
- goto SCAN_TAB_error;
- }//if
- currSavePointId = buddyApiPtr.p->currSavePointId;
- buddyApiPtr.p->currSavePointId++;
- }
- }
-
- if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
- getNodeState().getSingleUserApi() !=
- refToNode(apiConnectptr.p->ndbapiBlockref))
- {
- errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
- goto SCAN_TAB_error;
- }
-
- seizeTcConnect(signal);
- tcConnectptr.p->apiConnect = apiConnectptr.i;
- tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
- apiConnectptr.p->lastTcConnect = tcConnectptr.i;
-
- 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);
- ndbrequire(scanptr.p->scanApiRec == RNIL);
-
- initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag);
-
- transP->apiScanRec = scanptr.i;
- transP->returncode = 0;
- transP->transid[0] = transid1;
- transP->transid[1] = transid2;
- transP->buddyPtr = buddyPtr;
-
- // The scan is started
- transP->apiConnectstate = CS_START_SCAN;
- transP->currSavePointId = currSavePointId;
-
- /**********************************************************
- * We start the timer on scanRec to be able to discover a
- * timeout in the API the API now is in charge!
- ***********************************************************/
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- updateBuddyTimer(apiConnectptr);
-
- /***********************************************************
- * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
- * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
- * IF ANY TO RECEIVE.
- **********************************************************/
- scanptr.p->scanState = ScanRecord::WAIT_AI;
-
- if (ERROR_INSERTED(8038))
- {
- /**
- * Force API_FAILREQ
- */
- DisconnectRep * const rep = (DisconnectRep *)signal->getDataPtrSend();
- rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
- rep->err = 8038;
-
- EXECUTE_DIRECT(CMVMI, GSN_DISCONNECT_REP, signal, 2);
- CLEAR_ERROR_INSERT_VALUE;
- }
-
- return;
-
- SCAN_error_check:
- if (aiLength == 0) {
- jam()
- errCode = ZSCAN_AI_LEN_ERROR;
- goto SCAN_TAB_error;
- }//if
- if (!tabptr.p->checkTable(schemaVersion)){
- jam();
- errCode = tabptr.p->getErrorCode(schemaVersion);
- goto SCAN_TAB_error;
- }//if
- if (scanConcurrency == 0) {
- jam();
- errCode = ZNO_CONCURRENCY_ERROR;
- goto SCAN_TAB_error;
- }//if
- if (cfirstfreeTcConnect == RNIL) {
- jam();
- errCode = ZNO_FREE_TC_CONNECTION;
- goto SCAN_TAB_error;
- }//if
- ndbrequire(cfirstfreeScanrec == RNIL);
- jam();
- errCode = ZNO_SCANREC_ERROR;
- goto SCAN_TAB_error;
-
-SCAN_TAB_error:
- jam();
- /**
- * Prepare for up coming ATTRINFO/KEYINFO
- */
- transP->apiConnectstate = CS_ABORTING;
- transP->abortState = AS_IDLE;
- transP->transid[0] = transid1;
- transP->transid[1] = transid2;
-
-SCAN_TAB_error_no_state_change:
-
- ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
- ref->apiConnectPtr = transP->ndbapiConnect;
- ref->transId1 = transid1;
- ref->transId2 = transid2;
- ref->errorCode = errCode;
- ref->closeNeeded = 0;
- sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
- signal, ScanTabRef::SignalLength, JBB);
- return;
-}//Dbtc::execSCAN_TABREQ()
-
-void Dbtc::initScanrec(ScanRecordPtr scanptr,
- const ScanTabReq * scanTabReq,
- 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;
- scanptr.p->scanKeyLen = scanTabReq->attrLenKeyLen >> 16;
- scanptr.p->scanTableref = tabptr.i;
- scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
- scanptr.p->scanParallel = scanParallel;
- scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
- scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
- scanptr.p->batch_size_rows = noOprecPerFrag;
-
- Uint32 tmp = 0;
- 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);
- ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
-
- scanptr.p->scanRequestInfo = tmp;
- scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
- scanptr.p->scanState = ScanRecord::RUNNING;
- scanptr.p->m_queued_count = 0;
-
- ScanFragList list(c_scan_frag_pool,
- scanptr.p->m_running_scan_frags);
- for (Uint32 i = 0; i < scanParallel; i++) {
- jam();
- ScanFragRecPtr ptr;
- ndbrequire(list.seize(ptr));
- ptr.p->scanFragState = ScanFragRec::IDLE;
- ptr.p->scanRec = scanptr.i;
- ptr.p->scanFragId = 0;
- ptr.p->m_apiPtr = cdata[i];
- }//for
-
- (* (ScanTabReq::getRangeScanFlag(ri) ?
- &c_counters.c_range_scan_count :
- &c_counters.c_scan_count))++;
-}//Dbtc::initScanrec()
-
-void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
-{
- ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
- ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
- ref->transId1 = apiConnectptr.p->transid[0];
- ref->transId2 = apiConnectptr.p->transid[1];
- ref->errorCode = errCode;
- ref->closeNeeded = 0;
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
- signal, ScanTabRef::SignalLength, JBB);
-}//Dbtc::scanTabRefLab()
-
-/*---------------------------------------------------------------------------*/
-/* */
-/* RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST. */
-/*---------------------------------------------------------------------------*/
-void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
-{
- ScanRecordPtr scanptr;
- scanptr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- cachePtr.i = apiConnectptr.p->cachePtr;
- ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
- CacheRecord * const regCachePtr = cachePtr.p;
- ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
-
- regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
- if (regCachePtr->currReclenAi < scanptr.p->scanAiLength) {
- if (cfirstfreeAttrbuf == RNIL) {
- goto scanAttrinfo_attrbuf_error;
- }//if
- saveAttrbuf(signal);
- } else {
- if (regCachePtr->currReclenAi > scanptr.p->scanAiLength) {
- goto scanAttrinfo_len_error;
- } else {
- /* CURR_RECLEN_AI = SCAN_AI_LENGTH */
- if (cfirstfreeAttrbuf == RNIL) {
- goto scanAttrinfo_attrbuf2_error;
- }//if
- saveAttrbuf(signal);
- /**************************************************
- * WE HAVE NOW RECEIVED ALL INFORMATION CONCERNING
- * THIS SCAN. WE ARE READY TO START THE ACTUAL
- * EXECUTION OF THE SCAN QUERY
- **************************************************/
- diFcountReqLab(signal, scanptr);
- return;
- }//if
- }//if
- return;
-
-scanAttrinfo_attrbuf_error:
- jam();
- abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
- return;
-
-scanAttrinfo_attrbuf2_error:
- jam();
- abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
- return;
-
-scanAttrinfo_len_error:
- jam();
- abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
- return;
-}//Dbtc::scanAttrinfoLab()
-
-void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
-{
- /**
- * Check so that the table is not being dropped
- */
- TableRecordPtr tabPtr;
- tabPtr.i = scanptr.p->scanTableref;
- tabPtr.p = &tableRecord[tabPtr.i];
- if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
- ;
- } else {
- abortScanLab(signal, scanptr,
- tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
- true);
- return;
- }
-
- scanptr.p->scanNextFragId = 0;
- scanptr.p->m_booked_fragments_count= 0;
- scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
-
- if(!cachePtr.p->distributionKeyIndicator)
- {
- jam();
- /*************************************************
- * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
- * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
- ***************************************************/
- DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
- req->m_connectionData = tcConnectptr.p->dihConnectptr;
- req->m_tableRef = scanptr.p->scanTableref;
- sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal,
- DihFragCountReq::SignalLength, 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) {
- DihFragCountRef * const ref = (DihFragCountRef*)signal->getDataPtr();
- ref->m_connectionData = tcConnectptr.i;
- ref->m_error = signal->theData[1];
- execDI_FCOUNTREF(signal);
- return;
- }
-
- UintR Tdata1 = signal->theData[1];
- scanptr.p->scanNextFragId = Tdata1;
- DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
- conf->m_connectionData = tcConnectptr.i;
- conf->m_fragmentCount = 1; // Frag count
- execDI_FCOUNTCONF(signal);
- }
- return;
-}//Dbtc::diFcountReqLab()
-
-/********************************************************************
- * execDI_FCOUNTCONF
- *
- * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
- * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
- * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS
- * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION
- * CLOSES THE SCAN.
- ********************************************************************/
-void Dbtc::execDI_FCOUNTCONF(Signal* signal)
-{
- jamEntry();
- DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
- tcConnectptr.i = conf->m_connectionData;
- Uint32 tfragCount = conf->m_fragmentCount;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.i = tcConnectptr.p->apiConnect;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- ScanRecordPtr scanptr;
- scanptr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
- if (apiConnectptr.p->apiFailState == ZTRUE) {
- jam();
- releaseScanResources(scanptr, true);
- handleApiFailState(signal, apiConnectptr.i);
- return;
- }//if
- if (tfragCount == 0) {
- jam();
- abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
- return;
- }//if
-
- /**
- * Check so that the table is not being dropped
- */
- TableRecordPtr tabPtr;
- tabPtr.i = scanptr.p->scanTableref;
- tabPtr.p = &tableRecord[tabPtr.i];
- if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
- ;
- } else {
- abortScanLab(signal, scanptr,
- tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
- true);
- return;
- }
-
- scanptr.p->scanParallel = tfragCount;
- scanptr.p->scanNoFrag = tfragCount;
- 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() && tfragCount;
- list.next(ptr), tfragCount--){
- jam();
-
- ptr.p->lqhBlockref = 0;
- ptr.p->startFragTimer(ctcTimer);
- ptr.p->scanFragId = scanptr.p->scanNextFragId++;
- ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
- ptr.p->startFragTimer(ctcTimer);
-
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = ptr.i;
- signal->theData[2] = scanptr.p->scanTableref;
- signal->theData[3] = ptr.p->scanFragId;
- sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
- }//for
-
- 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()
-
-/******************************************************
- * execDI_FCOUNTREF
- ******************************************************/
-void Dbtc::execDI_FCOUNTREF(Signal* signal)
-{
- jamEntry();
- DihFragCountRef * const ref = (DihFragCountRef*)signal->getDataPtr();
- tcConnectptr.i = ref->m_connectionData;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- const Uint32 errCode = ref->m_error;
- apiConnectptr.i = tcConnectptr.p->apiConnect;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- ScanRecordPtr scanptr;
- scanptr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
- if (apiConnectptr.p->apiFailState == ZTRUE) {
- jam();
- releaseScanResources(scanptr, true);
- handleApiFailState(signal, apiConnectptr.i);
- return;
- }//if
- abortScanLab(signal, scanptr, errCode, true);
-}//Dbtc::execDI_FCOUNTREF()
-
-void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
- bool not_started)
-{
- scanTabRefLab(signal, errCode);
- releaseScanResources(scanptr, not_started);
-}//Dbtc::abortScanLab()
-
-void Dbtc::releaseScanResources(ScanRecordPtr scanPtr,
- bool not_started)
-{
- if (apiConnectptr.p->cachePtr != RNIL) {
- cachePtr.i = apiConnectptr.p->cachePtr;
- ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
- releaseKeys();
- releaseAttrinfo();
- }//if
- tcConnectptr.i = scanPtr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- releaseTcCon();
-
- if (not_started)
- {
- jam();
- ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
- ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
- run.release();
- queue.release();
- }
-
- ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
- ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
- ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
-
- ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
- ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
-
- // link into free list
- scanPtr.p->nextScan = cfirstfreeScanrec;
- scanPtr.p->scanState = ScanRecord::IDLE;
- scanPtr.p->scanTcrec = RNIL;
- scanPtr.p->scanApiRec = RNIL;
- cfirstfreeScanrec = scanPtr.i;
-
- apiConnectptr.p->apiScanRec = RNIL;
- apiConnectptr.p->apiConnectstate = CS_CONNECTED;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
-}//Dbtc::releaseScanResources()
-
-
-/****************************************************************
- * execDIGETPRIMCONF
- *
- * WE HAVE RECEIVED THE PRIMARY NODE OF THIS FRAGMENT.
- * WE ARE NOW READY TO ASK FOR PERMISSION TO LOAD THIS
- * SPECIFIC NODE WITH A SCAN OPERATION.
- ****************************************************************/
-void Dbtc::execDIGETPRIMCONF(Signal* signal)
-{
- jamEntry();
- // tcConnectptr.i in theData[0] is not used
- scanFragptr.i = signal->theData[1];
- c_scan_frag_pool.getPtr(scanFragptr);
-
- tnodeid = signal->theData[2];
- arrGuard(tnodeid, MAX_NDB_NODES);
-
- ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
- scanFragptr.p->stopFragTimer();
-
- ScanRecordPtr scanptr;
- scanptr.i = scanFragptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- /**
- * This must be false as select count(*) otherwise
- * can "pass" committing on backup fragments and
- * get incorrect row count
- */
- if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
- {
- jam();
- Uint32 max = 3+signal->theData[6];
- Uint32 nodeid = getOwnNodeId();
- for(Uint32 i = 3; i<max; i++)
- if(signal->theData[i] == nodeid)
- {
- jam();
- tnodeid = nodeid;
- break;
- }
- }
-
- {
- /**
- * Check table
- */
- TableRecordPtr tabPtr;
- tabPtr.i = scanptr.p->scanTableref;
- ptrAss(tabPtr, tableRecord);
- Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
- if(tabPtr.p->checkTable(schemaVersion) == false){
- jam();
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
-
- run.release(scanFragptr);
- scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion));
- return;
- }
- }
-
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- cachePtr.i = apiConnectptr.p->cachePtr;
- ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
- switch (scanptr.p->scanState) {
- case ScanRecord::CLOSING_SCAN:
- jam();
- updateBuddyTimer(apiConnectptr);
- {
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
-
- run.release(scanFragptr);
- }
- close_scan_req_send_conf(signal, scanptr);
- return;
- default:
- jam();
- /*empty*/;
- break;
- }//switch
- Uint32 ref = calcLqhBlockRef(tnodeid);
- scanFragptr.p->lqhBlockref = ref;
- scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
- sendScanFragReq(signal, scanptr.p, scanFragptr.p);
- if(ERROR_INSERTED(8035))
- globalTransporterRegistry.performSend();
- attrbufptr.i = cachePtr.p->firstAttrbuf;
- while (attrbufptr.i != RNIL) {
- jam();
- ptrCheckGuard(attrbufptr, cattrbufFilesize, attrbufRecord);
- sendAttrinfo(signal,
- scanFragptr.i,
- attrbufptr.p,
- ref);
- attrbufptr.i = attrbufptr.p->attrbuf[ZINBUF_NEXT];
- if(ERROR_INSERTED(8035))
- globalTransporterRegistry.performSend();
- }//while
- scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
- scanFragptr.p->startFragTimer(ctcTimer);
- updateBuddyTimer(apiConnectptr);
- /*********************************************
- * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
- * WAIT FOR THE FIRST SCANNED RECORDS
- *********************************************/
-}//Dbtc::execDIGETPRIMCONF
-
-/***************************************************
- * execDIGETPRIMREF
- *
- * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR
- * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH
- * FINDING A PRIMARY REPLICA OF A CERTAIN FRAGMENT.
- ***************************************************/
-void Dbtc::execDIGETPRIMREF(Signal* signal)
-{
- jamEntry();
- // tcConnectptr.i in theData[0] is not used.
- scanFragptr.i = signal->theData[1];
- const Uint32 errCode = signal->theData[2];
- c_scan_frag_pool.getPtr(scanFragptr);
- ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
-
- ScanRecordPtr scanptr;
- scanptr.i = scanFragptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
-
- run.release(scanFragptr);
-
- scanError(signal, scanptr, errCode);
-}//Dbtc::execDIGETPRIMREF()
-
-/**
- * Dbtc::execSCAN_FRAGREF
- * Our attempt to scan a fragment was refused
- * set error code and close all other fragment
- * scan's belonging to this scan
- */
-void Dbtc::execSCAN_FRAGREF(Signal* signal)
-{
- const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
-
- jamEntry();
- const Uint32 errCode = ref->errorCode;
-
- scanFragptr.i = ref->senderData;
- c_scan_frag_pool.getPtr(scanFragptr);
-
- ScanRecordPtr scanptr;
- scanptr.i = scanFragptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
-
- Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
- Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
- transid1 = transid1 | transid2;
- if (transid1 != 0) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
-
- /**
- * Set errorcode, close connection to this lqh fragment,
- * stop fragment timer and call scanFragError to start
- * close of the other fragment scans
- */
- ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
- {
- scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
-
- run.release(scanFragptr);
- scanFragptr.p->stopFragTimer();
- }
- scanError(signal, scanptr, errCode);
-}//Dbtc::execSCAN_FRAGREF()
-
-/**
- * Dbtc::scanError
- *
- * Called when an error occurs during
- */
-void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
-{
- jam();
- ScanRecord* scanP = scanptr.p;
-
- DEBUG("scanError, errorCode = "<< errorCode <<
- ", scanState = " << scanptr.p->scanState);
-
- apiConnectptr.i = scanP->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
-
- if(scanP->scanState == ScanRecord::CLOSING_SCAN){
- jam();
- close_scan_req_send_conf(signal, scanptr);
- return;
- }
-
- ndbrequire(scanP->scanState == ScanRecord::RUNNING);
-
- /**
- * Close scan wo/ having received an order to do so
- */
- close_scan_req(signal, scanptr, false);
-
- const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
- if(apiFail){
- jam();
- return;
- }
-
- ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
- ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
- ref->transId1 = apiConnectptr.p->transid[0];
- ref->transId2 = apiConnectptr.p->transid[1];
- ref->errorCode = errorCode;
- ref->closeNeeded = 1;
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
- signal, ScanTabRef::SignalLength, JBB);
-}//Dbtc::scanError()
-
-/************************************************************
- * execSCAN_FRAGCONF
- *
- * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
- * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
- ************************************************************/
-void Dbtc::execSCAN_FRAGCONF(Signal* signal)
-{
- Uint32 transid1, transid2, total_len;
- jamEntry();
-
- const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
- const Uint32 noCompletedOps = conf->completedOps;
- const Uint32 status = conf->fragmentCompleted;
-
- scanFragptr.i = conf->senderData;
- c_scan_frag_pool.getPtr(scanFragptr);
-
- ScanRecordPtr scanptr;
- scanptr.i = scanFragptr.p->scanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-
- apiConnectptr.i = scanptr.p->scanApiRec;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
-
- transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
- transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
- total_len= conf->total_len;
- transid1 = transid1 | transid2;
- if (transid1 != 0) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
-
- ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
-
- if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
- jam();
- if(status == 0){
- /**
- * We have started closing = we sent a close -> ignore this
- */
- return;
- } else {
- jam();
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
-
- run.release(scanFragptr);
- scanFragptr.p->stopFragTimer();
- scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
- }
- close_scan_req_send_conf(signal, scanptr);
- return;
- }
-
- if(noCompletedOps == 0 && status != 0 &&
- scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
- /**
- * Start on next fragment
- */
- scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
- scanFragptr.p->startFragTimer(ctcTimer);
-
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = scanFragptr.i;
- signal->theData[2] = scanptr.p->scanTableref;
- signal->theData[3] = scanFragptr.p->scanFragId;
- sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
- return;
- }
- /*
- Uint32 totalLen = 0;
- for(Uint32 i = 0; i<noCompletedOps; i++){
- Uint32 tmp = conf->opReturnDataLen[i];
- totalLen += tmp;
- }
- */
- {
- ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
- ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
-
- run.remove(scanFragptr);
- queued.add(scanFragptr);
- scanptr.p->m_queued_count++;
- }
-
- scanFragptr.p->m_scan_frag_conf_status = status;
- scanFragptr.p->m_ops = noCompletedOps;
- scanFragptr.p->m_totalLen = total_len;
- scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
- scanFragptr.p->stopFragTimer();
-
- if(scanptr.p->m_queued_count > /** Min */ 0){
- jam();
- sendScanTabConf(signal, scanptr);
- }
-}//Dbtc::execSCAN_FRAGCONF()
-
-/****************************************************************************
- * execSCAN_NEXTREQ
- *
- * THE APPLICATION HAVE PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
- * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
- ****************************************************************************/
-void Dbtc::execSCAN_NEXTREQ(Signal* signal)
-{
- const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
- const UintR transid1 = req->transId1;
- const UintR transid2 = req->transId2;
- const UintR stopScan = req->stopScan;
-
- jamEntry();
-
- apiConnectptr.i = req->apiConnectPtr;
- if (apiConnectptr.i >= capiConnectFilesize) {
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }//if
- ptrAss(apiConnectptr, apiConnectRecord);
-
- /**
- * Check transid
- */
- const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
- const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
- if ((ctransid1 | ctransid2) != 0){
- ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
- ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
- ref->transId1 = transid1;
- ref->transId2 = transid2;
- ref->errorCode = ZSTATE_ERROR;
- ref->closeNeeded = 0;
- sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
- signal, ScanTabRef::SignalLength, JBB);
- DEBUG("Wrong transid");
- return;
- }
-
- /**
- * Check state of API connection
- */
- if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
- jam();
- if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
- jam();
- /*********************************************************************
- * The application sends a SCAN_NEXTREQ after experiencing a time-out.
- * We will send a SCAN_TABREF to indicate a time-out occurred.
- *********************************************************************/
- DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
- ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
- ndbrequire(false); //B2 indication of strange things going on
- scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
- return;
- }
- DEBUG("scanTabRefLab: ZSTATE_ERROR");
- DEBUG(" apiConnectstate="<<apiConnectptr.p->apiConnectstate);
- ndbrequire(false); //B2 indication of strange things going on
- scanTabRefLab(signal, ZSTATE_ERROR);
- return;
- }//if
-
- /*******************************************************
- * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
- ********************************************************/
- // Stop the timer that is used to check for timeout in the API
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- ScanRecordPtr scanptr;
- scanptr.i = apiConnectptr.p->apiScanRec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- ScanRecord* scanP = scanptr.p;
-
- const Uint32 len = signal->getLength() - 4;
-
- if (stopScan == ZTRUE) {
- jam();
- /*********************************************************************
- * APPLICATION IS CLOSING THE SCAN.
- **********************************************************************/
- close_scan_req(signal, scanptr, true);
- return;
- }//if
-
- if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
- jam();
- /**
- * The scan is closing (typically due to error)
- * but the API hasn't understood it yet
- *
- * Wait for API close request
- */
- return;
- }
-
- // Copy op ptrs so I dont overwrite them when sending...
- memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len);
-
- ScanFragNextReq tmp;
- tmp.closeFlag = ZFALSE;
- tmp.transId1 = apiConnectptr.p->transid[0];
- tmp.transId2 = apiConnectptr.p->transid[1];
- tmp.batch_size_rows = scanP->batch_size_rows;
- tmp.batch_size_bytes = scanP->batch_byte_size;
-
- ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
- ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
- for(Uint32 i = 0 ; i<len; i++){
- jam();
- scanFragptr.i = signal->theData[i+25];
- c_scan_frag_pool.getPtr(scanFragptr);
- ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
-
- scanFragptr.p->startFragTimer(ctcTimer);
- scanFragptr.p->m_ops = 0;
-
- if(scanFragptr.p->m_scan_frag_conf_status)
- {
- /**
- * last scan was complete
- */
- 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;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = scanFragptr.i;
- signal->theData[2] = scanptr.p->scanTableref;
- signal->theData[3] = scanFragptr.p->scanFragId;
- sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
- }
- else
- {
- jam();
- scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
- ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
- * req = tmp;
- req->senderData = scanFragptr.i;
- sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- }
- delivered.remove(scanFragptr);
- running.add(scanFragptr);
- }//for
-
-}//Dbtc::execSCAN_NEXTREQ()
-
-void
-Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
-
- ScanRecord* scanP = scanPtr.p;
- ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
- ScanRecord::ScanState old = scanPtr.p->scanState;
- scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
- scanPtr.p->m_close_scan_req = req_received;
-
- if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
- {
- jam();
- scanPtr.p->scanState = old;
- return; // Will continue on execDI_FCOUNTCONF
- }
-
- /**
- * Queue : Action
- * ============= : =================
- * completed : -
- * running : close -> LQH
- * delivered w/ : close -> LQH
- * delivered wo/ : move to completed
- * queued w/ : close -> LQH
- * queued wo/ : move to completed
- */
-
- ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
- nextReq->closeFlag = ZTRUE;
- nextReq->transId1 = apiConnectptr.p->transid[0];
- nextReq->transId2 = apiConnectptr.p->transid[1];
-
- {
- ScanFragRecPtr ptr;
- ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
- ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
- ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
-
- // Close running
- for(running.first(ptr); !ptr.isNull(); ){
- ScanFragRecPtr curr = ptr; // Remove while iterating...
- running.next(ptr);
-
- switch(curr.p->scanFragState){
- case ScanFragRec::IDLE:
- jam(); // real early abort
- ndbrequire(old == ScanRecord::WAIT_AI);
- running.release(curr);
- continue;
- case ScanFragRec::WAIT_GET_PRIMCONF:
- jam();
- continue;
- case ScanFragRec::LQH_ACTIVE:
- jam();
- break;
- default:
- jamLine(curr.p->scanFragState);
- ndbrequire(false);
- }
-
- curr.p->startFragTimer(ctcTimer);
- curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
- nextReq->senderData = curr.i;
- sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- }
-
- // Close delivered
- for(delivered.first(ptr); !ptr.isNull(); ){
- jam();
- ScanFragRecPtr curr = ptr; // Remove while iterating...
- delivered.next(ptr);
-
- ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
- delivered.remove(curr);
-
- if(curr.p->m_ops > 0 && curr.p->m_scan_frag_conf_status == 0){
- jam();
- running.add(curr);
- curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
- curr.p->startFragTimer(ctcTimer);
- nextReq->senderData = curr.i;
- sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
-
- } else {
- jam();
- c_scan_frag_pool.release(curr);
- curr.p->scanFragState = ScanFragRec::COMPLETED;
- curr.p->stopFragTimer();
- }
- }//for
-
- /**
- * All queued with data should be closed
- */
- for(queued.first(ptr); !ptr.isNull(); ){
- jam();
- ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
- ScanFragRecPtr curr = ptr; // Remove while iterating...
- queued.next(ptr);
-
- queued.remove(curr);
- scanP->m_queued_count--;
-
- if(curr.p->m_ops > 0){
- jam();
- running.add(curr);
- curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
- curr.p->startFragTimer(ctcTimer);
- nextReq->senderData = curr.i;
- sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
- } else {
- jam();
- c_scan_frag_pool.release(curr);
- curr.p->scanFragState = ScanFragRec::COMPLETED;
- curr.p->stopFragTimer();
- }
- }
- }
- close_scan_req_send_conf(signal, scanPtr);
-}
-
-void
-Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
-
- jam();
-
- ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
- ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
- //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
-
-#if 0
- {
- ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
- ScanFragRecPtr ptr;
- for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
- ndbrequire(ptr.p->scanFragTimer == 0);
- ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
- }
- }
-#endif
-
- if(!scanPtr.p->m_running_scan_frags.isEmpty()){
- jam();
- return;
- }
-
- const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
-
- if(!scanPtr.p->m_close_scan_req){
- jam();
- /**
- * The API hasn't order closing yet
- */
- return;
- }
-
- Uint32 ref = apiConnectptr.p->ndbapiBlockref;
- if(!apiFail && ref){
- jam();
- ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
- conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
- conf->requestInfo = ScanTabConf::EndOfData;
- conf->transId1 = apiConnectptr.p->transid[0];
- conf->transId2 = apiConnectptr.p->transid[1];
- sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
- }
-
- releaseScanResources(scanPtr);
-
- if(apiFail){
- jam();
- /**
- * API has failed
- */
- handleApiFailState(signal, apiConnectptr.i);
- }
-}
-
-Dbtc::ScanRecordPtr
-Dbtc::seizeScanrec(Signal* signal) {
- ScanRecordPtr scanptr;
- scanptr.i = cfirstfreeScanrec;
- ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
- cfirstfreeScanrec = scanptr.p->nextScan;
- scanptr.p->nextScan = RNIL;
- ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
- return scanptr;
-}//Dbtc::seizeScanrec()
-
-void Dbtc::sendScanFragReq(Signal* signal,
- ScanRecord* scanP,
- ScanFragRec* scanFragP)
-{
- ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
- Uint32 requestInfo = scanP->scanRequestInfo;
- ScanFragReq::setScanPrio(requestInfo, 1);
- apiConnectptr.i = scanP->scanApiRec;
- req->tableId = scanP->scanTableref;
- req->schemaVersion = scanP->scanSchemaVersion;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- req->senderData = scanFragptr.i;
- req->requestInfo = requestInfo;
- req->fragmentNoKeyLen = scanFragP->scanFragId | (scanP->scanKeyLen << 16);
- req->resultRef = apiConnectptr.p->ndbapiBlockref;
- req->savePointId = apiConnectptr.p->currSavePointId;
- req->transId1 = apiConnectptr.p->transid[0];
- req->transId2 = apiConnectptr.p->transid[1];
- req->clientOpPtr = scanFragP->m_apiPtr;
- req->batch_size_rows= scanP->batch_size_rows;
- req->batch_size_bytes= scanP->batch_byte_size;
- sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
- ScanFragReq::SignalLength, JBB);
- if(scanP->scanKeyLen > 0)
- {
- tcConnectptr.i = scanFragptr.i;
- packKeyData000Lab(signal, scanFragP->lqhBlockref, scanP->scanKeyLen);
- }
- updateBuddyTimer(apiConnectptr);
- scanFragP->startFragTimer(ctcTimer);
-}//Dbtc::sendScanFragReq()
-
-
-void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
- jam();
- Uint32* ops = signal->getDataPtrSend()+4;
- Uint32 op_count = scanPtr.p->m_queued_count;
- if(4 + 3 * op_count > 25){
- jam();
- ops += 21;
- }
-
- 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;
- conf->requestInfo = op_count;
- conf->transId1 = apiConnectptr.p->transid[0];
- conf->transId2 = apiConnectptr.p->transid[1];
- ScanFragRecPtr ptr;
- {
- ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
- ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
- for(queued.first(ptr); !ptr.isNull(); ){
- ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
- ScanFragRecPtr curr = ptr; // Remove while iterating...
- queued.next(ptr);
-
- 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;
-
- queued.remove(curr);
- if(!done){
- delivered.add(curr);
- curr.p->scanFragState = ScanFragRec::DELIVERED;
- curr.p->stopFragTimer();
- } else {
- c_scan_frag_pool.release(curr);
- curr.p->scanFragState = ScanFragRec::COMPLETED;
- curr.p->stopFragTimer();
- }
- }
- }
-
- scanPtr.p->m_booked_fragments_count = booked;
- if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
- scanPtr.p->m_running_scan_frags.isEmpty())
- {
- conf->requestInfo = op_count | ScanTabConf::EndOfData;
- releaseScanResources(scanPtr);
- }
- else
- {
- if (scanPtr.p->m_running_scan_frags.isEmpty())
- {
- jam();
- /**
- * All scan frags delivered...waiting for API
- */
- setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
- }
- }
-
- if(4 + 3 * op_count > 25){
- jam();
- LinearSectionPtr ptr[3];
- ptr[0].p = signal->getDataPtrSend()+25;
- ptr[0].sz = 3 * op_count;
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
- ScanTabConf::SignalLength, JBB, ptr, 1);
- } else {
- jam();
- sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
- ScanTabConf::SignalLength + 3 * op_count, JBB);
- }
- scanPtr.p->m_queued_count = 0;
-}//Dbtc::sendScanTabConf()
-
-
-void Dbtc::gcpTcfinished(Signal* signal)
-{
- signal->theData[0] = c_gcp_ref;
- signal->theData[1] = tcheckGcpId;
- sendSignal(cdihblockref, GSN_GCP_TCFINISHED, signal, 2, JBB);
-}//Dbtc::gcpTcfinished()
-
-void Dbtc::initApiConnect(Signal* signal)
-{
- Uint32 tiacTmp;
- Uint32 guard4;
-
- tiacTmp = capiConnectFilesize / 3;
- ndbrequire(tiacTmp > 0);
- guard4 = tiacTmp + 1;
- for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
- refresh_watch_dog();
- ptrAss(cachePtr, cacheRecord);
- cachePtr.p->firstAttrbuf = RNIL;
- cachePtr.p->lastAttrbuf = RNIL;
- cachePtr.p->firstKeybuf = RNIL;
- cachePtr.p->lastKeybuf = RNIL;
- cachePtr.p->nextCacheRec = cachePtr.i + 1;
- }//for
- cachePtr.i = tiacTmp;
- ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
- cachePtr.p->nextCacheRec = RNIL;
- cfirstfreeCacheRec = 0;
-
- guard4 = tiacTmp - 1;
- for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
- refresh_watch_dog();
- jam();
- ptrAss(apiConnectptr, apiConnectRecord);
- apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
- apiConnectptr.p->apiFailState = ZFALSE;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
- apiConnectptr.p->cachePtr = RNIL;
- apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
- apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
- apiConnectptr.p->commitAckMarker = RNIL;
- apiConnectptr.p->firstTcConnect = RNIL;
- apiConnectptr.p->lastTcConnect = RNIL;
- apiConnectptr.p->triggerPending = false;
- apiConnectptr.p->isIndexOp = false;
- apiConnectptr.p->accumulatingIndexOp = RNIL;
- apiConnectptr.p->executingIndexOp = RNIL;
- apiConnectptr.p->buddyPtr = RNIL;
- apiConnectptr.p->currSavePointId = 0;
- apiConnectptr.p->m_transaction_nodes.clear();
- apiConnectptr.p->singleUserMode = 0;
- }//for
- apiConnectptr.i = tiacTmp - 1;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- apiConnectptr.p->nextApiConnect = RNIL;
- cfirstfreeApiConnect = 0;
- guard4 = (2 * tiacTmp) - 1;
- for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
- {
- refresh_watch_dog();
- jam();
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- apiConnectptr.p->apiConnectstate = CS_RESTART;
- apiConnectptr.p->apiFailState = ZFALSE;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
- apiConnectptr.p->cachePtr = RNIL;
- apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
- apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
- apiConnectptr.p->commitAckMarker = RNIL;
- apiConnectptr.p->firstTcConnect = RNIL;
- apiConnectptr.p->lastTcConnect = RNIL;
- apiConnectptr.p->triggerPending = false;
- apiConnectptr.p->isIndexOp = false;
- apiConnectptr.p->accumulatingIndexOp = RNIL;
- apiConnectptr.p->executingIndexOp = RNIL;
- apiConnectptr.p->buddyPtr = RNIL;
- apiConnectptr.p->currSavePointId = 0;
- apiConnectptr.p->m_transaction_nodes.clear();
- apiConnectptr.p->singleUserMode = 0;
- }//for
- apiConnectptr.i = (2 * tiacTmp) - 1;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- apiConnectptr.p->nextApiConnect = RNIL;
- cfirstfreeApiConnectCopy = tiacTmp;
- guard4 = (3 * tiacTmp) - 1;
- for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
- apiConnectptr.i++) {
- refresh_watch_dog();
- jam();
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- apiConnectptr.p->apiFailState = ZFALSE;
- apiConnectptr.p->apiConnectstate = CS_RESTART;
- apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
- apiConnectptr.p->cachePtr = RNIL;
- apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
- apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
- apiConnectptr.p->commitAckMarker = RNIL;
- apiConnectptr.p->firstTcConnect = RNIL;
- apiConnectptr.p->lastTcConnect = RNIL;
- apiConnectptr.p->triggerPending = false;
- apiConnectptr.p->isIndexOp = false;
- apiConnectptr.p->accumulatingIndexOp = RNIL;
- apiConnectptr.p->executingIndexOp = RNIL;
- apiConnectptr.p->buddyPtr = RNIL;
- apiConnectptr.p->currSavePointId = 0;
- apiConnectptr.p->m_transaction_nodes.clear();
- apiConnectptr.p->singleUserMode = 0;
- }//for
- apiConnectptr.i = (3 * tiacTmp) - 1;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- apiConnectptr.p->nextApiConnect = RNIL;
- cfirstfreeApiConnectFail = 2 * tiacTmp;
-}//Dbtc::initApiConnect()
-
-void Dbtc::initattrbuf(Signal* signal)
-{
- ndbrequire(cattrbufFilesize > 0);
- for (attrbufptr.i = 0; attrbufptr.i < cattrbufFilesize; attrbufptr.i++) {
- refresh_watch_dog();
- jam();
- ptrAss(attrbufptr, attrbufRecord);
- attrbufptr.p->attrbuf[ZINBUF_NEXT] = attrbufptr.i + 1; /* NEXT ATTRBUF */
- }//for
- attrbufptr.i = cattrbufFilesize - 1;
- ptrAss(attrbufptr, attrbufRecord);
- attrbufptr.p->attrbuf[ZINBUF_NEXT] = RNIL; /* NEXT ATTRBUF */
- cfirstfreeAttrbuf = 0;
-}//Dbtc::initattrbuf()
-
-void Dbtc::initdatabuf(Signal* signal)
-{
- ndbrequire(cdatabufFilesize > 0);
- for (databufptr.i = 0; databufptr.i < cdatabufFilesize; databufptr.i++) {
- refresh_watch_dog();
- ptrAss(databufptr, databufRecord);
- databufptr.p->nextDatabuf = databufptr.i + 1;
- }//for
- databufptr.i = cdatabufFilesize - 1;
- ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
- databufptr.p->nextDatabuf = RNIL;
- cfirstfreeDatabuf = 0;
-}//Dbtc::initdatabuf()
-
-void Dbtc::initgcp(Signal* signal)
-{
- ndbrequire(cgcpFilesize > 0);
- for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
- ptrAss(gcpPtr, gcpRecord);
- gcpPtr.p->nextGcp = gcpPtr.i + 1;
- }//for
- gcpPtr.i = cgcpFilesize - 1;
- ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
- gcpPtr.p->nextGcp = RNIL;
- cfirstfreeGcp = 0;
- cfirstgcp = RNIL;
- clastgcp = RNIL;
-}//Dbtc::initgcp()
-
-void Dbtc::inithost(Signal* signal)
-{
- cpackedListIndex = 0;
- ndbrequire(chostFilesize > 0);
- for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
- jam();
- ptrAss(hostptr, hostRecord);
- hostptr.p->hostStatus = HS_DEAD;
- hostptr.p->inPackedList = false;
- hostptr.p->lqhTransStatus = LTS_IDLE;
- hostptr.p->noOfWordsTCKEYCONF = 0;
- hostptr.p->noOfWordsTCINDXCONF = 0;
- hostptr.p->noOfPackedWordsLqh = 0;
- hostptr.p->hostLqhBlockRef = calcLqhBlockRef(hostptr.i);
- hostptr.p->m_nf_bits = 0;
- }//for
- c_alive_nodes.clear();
-}//Dbtc::inithost()
-
-void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
- Uint32 retRef, Uint32 retData)
-{
- switch (Tdata0) {
- case 0:
- jam();
- initApiConnect(signal);
- break;
- case 1:
- jam();
- initattrbuf(signal);
- break;
- case 2:
- jam();
- initdatabuf(signal);
- break;
- case 3:
- jam();
- initgcp(signal);
- break;
- case 4:
- jam();
- inithost(signal);
- break;
- case 5:
- jam();
- // UNUSED Free to initialise something
- break;
- case 6:
- jam();
- initTable(signal);
- break;
- case 7:
- jam();
- initialiseScanrec(signal);
- break;
- case 8:
- jam();
- initialiseScanOprec(signal);
- break;
- case 9:
- jam();
- initialiseScanFragrec(signal);
- break;
- case 10:
- jam();
- initialiseTcConnect(signal);
- break;
- case 11:
- jam();
- initTcFail(signal);
-
- {
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = retData;
- sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
- }
- return;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
-
- signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
- signal->theData[1] = Tdata0 + 1;
- signal->theData[2] = 0;
- signal->theData[3] = retRef;
- signal->theData[4] = retData;
- sendSignal(DBTC_REF, GSN_CONTINUEB, signal, 5, JBB);
-}
-
-/* ========================================================================= */
-/* ======= INITIALISE_SCANREC ======= */
-/* */
-/* ========================================================================= */
-void Dbtc::initialiseScanrec(Signal* signal)
-{
- ScanRecordPtr scanptr;
- ndbrequire(cscanrecFileSize > 0);
- for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
- refresh_watch_dog();
- jam();
- ptrAss(scanptr, scanRecord);
- new (scanptr.p) ScanRecord();
- scanptr.p->scanState = ScanRecord::IDLE;
- scanptr.p->scanApiRec = RNIL;
- scanptr.p->nextScan = scanptr.i + 1;
- }//for
- scanptr.i = cscanrecFileSize - 1;
- ptrAss(scanptr, scanRecord);
- scanptr.p->nextScan = RNIL;
- cfirstfreeScanrec = 0;
-}//Dbtc::initialiseScanrec()
-
-void Dbtc::initialiseScanFragrec(Signal* signal)
-{
-}//Dbtc::initialiseScanFragrec()
-
-void Dbtc::initialiseScanOprec(Signal* signal)
-{
-}//Dbtc::initialiseScanOprec()
-
-void Dbtc::initTable(Signal* signal)
-{
-
- ndbrequire(ctabrecFilesize > 0);
- for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
- refresh_watch_dog();
- ptrAss(tabptr, tableRecord);
- tabptr.p->currentSchemaVersion = 0;
- tabptr.p->m_flags = 0;
- tabptr.p->set_storedTable(true);
- tabptr.p->tableType = 0;
- tabptr.p->set_enabled(false);
- tabptr.p->set_dropping(false);
- tabptr.p->noOfKeyAttr = 0;
- tabptr.p->hasCharAttr = 0;
- tabptr.p->noOfDistrKeys = 0;
- tabptr.p->hasVarKeys = 0;
- }//for
-}//Dbtc::initTable()
-
-void Dbtc::initialiseTcConnect(Signal* signal)
-{
- ndbrequire(ctcConnectFilesize >= 2);
-
- // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
- Uint32 titcTmp = ctcConnectFilesize / 2;
- for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
- refresh_watch_dog();
- jam();
- ptrAss(tcConnectptr, tcConnectRecord);
- tcConnectptr.p->tcConnectstate = OS_RESTART;
- tcConnectptr.p->apiConnect = RNIL;
- tcConnectptr.p->noOfNodes = 0;
- tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
- }//for
- tcConnectptr.i = titcTmp - 1;
- ptrAss(tcConnectptr, tcConnectRecord);
- tcConnectptr.p->nextTcConnect = RNIL;
- cfirstfreeTcConnectFail = 0;
-
- // Place other half in cfirstfreeTcConnect list
- for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
- tcConnectptr.i++) {
- refresh_watch_dog();
- jam();
- ptrAss(tcConnectptr, tcConnectRecord);
- tcConnectptr.p->tcConnectstate = OS_RESTART;
- tcConnectptr.p->apiConnect = RNIL;
- tcConnectptr.p->noOfNodes = 0;
- tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
- }//for
- tcConnectptr.i = ctcConnectFilesize - 1;
- ptrAss(tcConnectptr, tcConnectRecord);
- tcConnectptr.p->nextTcConnect = RNIL;
- cfirstfreeTcConnect = titcTmp;
- c_counters.cconcurrentOp = 0;
-}//Dbtc::initialiseTcConnect()
-
-/* ------------------------------------------------------------------------- */
-/* ---- LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS */
-/* WAITING FOR COMPLETION. */
-/* ------------------------------------------------------------------------- */
-void Dbtc::linkGciInGcilist(Signal* signal)
-{
- GcpRecordPtr tmpGcpPointer;
- if (cfirstgcp == RNIL) {
- jam();
- cfirstgcp = gcpPtr.i;
- } else {
- jam();
- tmpGcpPointer.i = clastgcp;
- ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
- tmpGcpPointer.p->nextGcp = gcpPtr.i;
- }//if
- clastgcp = gcpPtr.i;
-}//Dbtc::linkGciInGcilist()
-
-/* ------------------------------------------------------------------------- */
-/* ------- LINK SECONDARY KEY BUFFER IN OPERATION RECORD ------- */
-/* ------------------------------------------------------------------------- */
-void Dbtc::linkKeybuf(Signal* signal)
-{
- seizeDatabuf(signal);
- tmpDatabufptr.i = cachePtr.p->lastKeybuf;
- cachePtr.p->lastKeybuf = databufptr.i;
- if (tmpDatabufptr.i == RNIL) {
- jam();
- cachePtr.p->firstKeybuf = databufptr.i;
- } else {
- jam();
- ptrCheckGuard(tmpDatabufptr, cdatabufFilesize, databufRecord);
- tmpDatabufptr.p->nextDatabuf = databufptr.i;
- }//if
-}//Dbtc::linkKeybuf()
-
-/* ------------------------------------------------------------------------- */
-/* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS --- */
-/* ------------------------------------------------------------------------- */
-void Dbtc::linkTcInConnectionlist(Signal* signal)
-{
- /* POINTER FOR THE CONNECT_RECORD */
- TcConnectRecordPtr ltcTcConnectptr;
-
- tcConnectptr.p->nextTcConnect = RNIL;
- ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
- ptrCheck(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
- apiConnectptr.p->lastTcConnect = tcConnectptr.i;
- if (ltcTcConnectptr.i == RNIL) {
- jam();
- apiConnectptr.p->firstTcConnect = tcConnectptr.i;
- } else {
- jam();
- ptrGuard(ltcTcConnectptr);
- ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
- }//if
-}//Dbtc::linkTcInConnectionlist()
-
-/*---------------------------------------------------------------------------*/
-/* RELEASE_ABORT_RESOURCES */
-/* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
-/* SENDS THE ABORT DECISION TO THE APPLICATION. */
-/*---------------------------------------------------------------------------*/
-void Dbtc::releaseAbortResources(Signal* signal)
-{
- TcConnectRecordPtr rarTcConnectptr;
-
- c_counters.cabortCount++;
- if (apiConnectptr.p->cachePtr != RNIL) {
- cachePtr.i = apiConnectptr.p->cachePtr;
- ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
- releaseAttrinfo();
- releaseKeys();
- }//if
- tcConnectptr.i = apiConnectptr.p->firstTcConnect;
- while (tcConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- // Clear any markers that were set in CS_RECEIVING state
- clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
- rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
- releaseTcCon();
- tcConnectptr.i = rarTcConnectptr.i;
- }//while
- apiConnectptr.p->firstTcConnect = RNIL;
- apiConnectptr.p->lastTcConnect = RNIL;
- apiConnectptr.p->m_transaction_nodes.clear();
- apiConnectptr.p->singleUserMode = 0;
-
- // MASV let state be CS_ABORTING until all
- // signals in the "air" have been received. Reset to CS_CONNECTED
- // will be done when a TCKEYREQ with start flag is recieved
- // or releaseApiCon is called
- // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
- apiConnectptr.p->apiConnectstate = CS_ABORTING;
- apiConnectptr.p->abortState = AS_IDLE;
- releaseAllSeizedIndexOperations(apiConnectptr.p);
- if(apiConnectptr.p->m_exec_flag || apiConnectptr.p->apiFailState == ZTRUE){
- jam();
- bool ok = false;
- Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
- ReturnSignal ret = apiConnectptr.p->returnsignal;
- apiConnectptr.p->returnsignal = RS_NO_RETURN;
- apiConnectptr.p->m_exec_flag = 0;
- switch(ret){
- case RS_TCROLLBACKCONF:
- jam();
- ok = true;
- signal->theData[0] = apiConnectptr.p->ndbapiConnect;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
- break;
- case RS_TCROLLBACKREP:{
- jam();
- ok = true;
- TcRollbackRep * const tcRollbackRep =
- (TcRollbackRep *) signal->getDataPtr();
-
- tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
- tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
- tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
- tcRollbackRep->returnCode = apiConnectptr.p->returncode;
- tcRollbackRep->errorData = apiConnectptr.p->errorData;
- sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
- TcRollbackRep::SignalLength, JBB);
- }
- break;
- case RS_NO_RETURN:
- jam();
- ok = true;
- break;
- case RS_TCKEYCONF:
- case RS_TC_COMMITCONF:
- break;
- }
- if(!ok){
- jam();
- ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
- sendSystemError(signal, __LINE__);
- }//if
-
- }
- setApiConTimer(apiConnectptr.i, 0,
- 100000+c_apiConTimer_line[apiConnectptr.i]);
- if (apiConnectptr.p->apiFailState == ZTRUE) {
- jam();
- handleApiFailState(signal, apiConnectptr.i);
- return;
- }//if
-}//Dbtc::releaseAbortResources()
-
-void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
-{
- ApiConnectRecordPtr TlocalApiConnectptr;
-
- TlocalApiConnectptr.i = TapiConnectPtr;
- ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
- TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
- cfirstfreeApiConnect = TlocalApiConnectptr.i;
- setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
- TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
- ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
- ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
- TlocalApiConnectptr.p->ndbapiBlockref = 0;
-}//Dbtc::releaseApiCon()
-
-void Dbtc::releaseApiConnectFail(Signal* signal)
-{
- apiConnectptr.p->apiConnectstate = CS_RESTART;
- apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
- cfirstfreeApiConnectFail = apiConnectptr.i;
-}//Dbtc::releaseApiConnectFail()
-
-void Dbtc::releaseGcp(Signal* signal)
-{
- ptrGuard(gcpPtr);
- gcpPtr.p->nextGcp = cfirstfreeGcp;
- cfirstfreeGcp = gcpPtr.i;
-}//Dbtc::releaseGcp()
-
-void Dbtc::releaseKeys()
-{
- UintR Tmp;
- databufptr.i = cachePtr.p->firstKeybuf;
- while (databufptr.i != RNIL) {
- jam();
- ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
- Tmp = databufptr.p->nextDatabuf;
- databufptr.p->nextDatabuf = cfirstfreeDatabuf;
- cfirstfreeDatabuf = databufptr.i;
- databufptr.i = Tmp;
- }//while
- cachePtr.p->firstKeybuf = RNIL;
- cachePtr.p->lastKeybuf = RNIL;
-}//Dbtc::releaseKeys()
-
-void Dbtc::releaseTcConnectFail(Signal* signal)
-{
- ptrGuard(tcConnectptr);
- tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
- cfirstfreeTcConnectFail = tcConnectptr.i;
-}//Dbtc::releaseTcConnectFail()
-
-void Dbtc::seizeApiConnect(Signal* signal)
-{
- if (cfirstfreeApiConnect != RNIL) {
- jam();
- terrorCode = ZOK;
- apiConnectptr.i = cfirstfreeApiConnect; /* ASSIGN A FREE RECORD FROM */
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
- apiConnectptr.p->nextApiConnect = RNIL;
- setApiConTimer(apiConnectptr.i, 0, __LINE__);
- apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
- apiConnectptr.p->triggerPending = false;
- apiConnectptr.p->isIndexOp = false;
- } else {
- jam();
- terrorCode = ZNO_FREE_API_CONNECTION;
- }//if
-}//Dbtc::seizeApiConnect()
-
-void Dbtc::seizeApiConnectFail(Signal* signal)
-{
- apiConnectptr.i = cfirstfreeApiConnectFail;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
-}//Dbtc::seizeApiConnectFail()
-
-void Dbtc::seizeDatabuf(Signal* signal)
-{
- databufptr.i = cfirstfreeDatabuf;
- ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
- cfirstfreeDatabuf = databufptr.p->nextDatabuf;
- databufptr.p->nextDatabuf = RNIL;
-}//Dbtc::seizeDatabuf()
-
-void Dbtc::seizeTcConnect(Signal* signal)
-{
- tcConnectptr.i = cfirstfreeTcConnect;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
- c_counters.cconcurrentOp++;
- tcConnectptr.p->isIndexOp = false;
-}//Dbtc::seizeTcConnect()
-
-void Dbtc::seizeTcConnectFail(Signal* signal)
-{
- tcConnectptr.i = cfirstfreeTcConnectFail;
- ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
-}//Dbtc::seizeTcConnectFail()
-
-void Dbtc::sendAttrinfo(Signal* signal,
- UintR TattrinfoPtr,
- AttrbufRecord * const regAttrPtr,
- UintR TBref)
-{
- UintR TdataPos;
- UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6, sig7;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- TdataPos = regAttrPtr->attrbuf[ZINBUF_DATA_LEN];
- sig0 = TattrinfoPtr;
- sig1 = regApiPtr->transid[0];
- sig2 = regApiPtr->transid[1];
-
- signal->theData[0] = sig0;
- signal->theData[1] = sig1;
- signal->theData[2] = sig2;
-
- sig0 = regAttrPtr->attrbuf[0];
- sig1 = regAttrPtr->attrbuf[1];
- sig2 = regAttrPtr->attrbuf[2];
- sig3 = regAttrPtr->attrbuf[3];
- sig4 = regAttrPtr->attrbuf[4];
- sig5 = regAttrPtr->attrbuf[5];
- sig6 = regAttrPtr->attrbuf[6];
- sig7 = regAttrPtr->attrbuf[7];
-
- signal->theData[3] = sig0;
- signal->theData[4] = sig1;
- signal->theData[5] = sig2;
- signal->theData[6] = sig3;
- signal->theData[7] = sig4;
- signal->theData[8] = sig5;
- signal->theData[9] = sig6;
- signal->theData[10] = sig7;
-
- if (TdataPos > 8) {
- sig0 = regAttrPtr->attrbuf[8];
- sig1 = regAttrPtr->attrbuf[9];
- sig2 = regAttrPtr->attrbuf[10];
- sig3 = regAttrPtr->attrbuf[11];
- sig4 = regAttrPtr->attrbuf[12];
- sig5 = regAttrPtr->attrbuf[13];
- sig6 = regAttrPtr->attrbuf[14];
-
- jam();
- signal->theData[11] = sig0;
- signal->theData[12] = sig1;
- signal->theData[13] = sig2;
- signal->theData[14] = sig3;
- signal->theData[15] = sig4;
- signal->theData[16] = sig5;
- signal->theData[17] = sig6;
-
- if (TdataPos > 15) {
-
- sig0 = regAttrPtr->attrbuf[15];
- sig1 = regAttrPtr->attrbuf[16];
- sig2 = regAttrPtr->attrbuf[17];
- sig3 = regAttrPtr->attrbuf[18];
- sig4 = regAttrPtr->attrbuf[19];
- sig5 = regAttrPtr->attrbuf[20];
- sig6 = regAttrPtr->attrbuf[21];
-
- jam();
- signal->theData[18] = sig0;
- signal->theData[19] = sig1;
- signal->theData[20] = sig2;
- signal->theData[21] = sig3;
- signal->theData[22] = sig4;
- signal->theData[23] = sig5;
- signal->theData[24] = sig6;
- }//if
- }//if
- sendSignal(TBref, GSN_ATTRINFO, signal, TdataPos + 3, JBB);
-}//Dbtc::sendAttrinfo()
-
-void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
-{
- signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
- signal->theData[1] = TapiConPtr;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
-}//Dbtc::sendContinueTimeOutControl()
-
-void Dbtc::sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len)
-{
- signal->theData[0] = tcConnectptr.i;
- signal->theData[1] = apiConnectptr.p->transid[0];
- signal->theData[2] = apiConnectptr.p->transid[1];
- signal->theData[3] = cdata[0];
- signal->theData[4] = cdata[1];
- signal->theData[5] = cdata[2];
- signal->theData[6] = cdata[3];
- signal->theData[7] = cdata[4];
- signal->theData[8] = cdata[5];
- signal->theData[9] = cdata[6];
- signal->theData[10] = cdata[7];
- signal->theData[11] = cdata[8];
- signal->theData[12] = cdata[9];
- signal->theData[13] = cdata[10];
- signal->theData[14] = cdata[11];
- signal->theData[15] = cdata[12];
- signal->theData[16] = cdata[13];
- signal->theData[17] = cdata[14];
- signal->theData[18] = cdata[15];
- signal->theData[19] = cdata[16];
- signal->theData[20] = cdata[17];
- signal->theData[21] = cdata[18];
- signal->theData[22] = cdata[19];
- sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
-}//Dbtc::sendKeyinfo()
-
-void Dbtc::sendSystemError(Signal* signal, int line)
-{
- progError(line, NDBD_EXIT_NDBREQUIRE);
-}//Dbtc::sendSystemError()
-
-/* ========================================================================= */
-/* ------- LINK ACTUAL GCP OUT OF LIST ------- */
-/* ------------------------------------------------------------------------- */
-void Dbtc::unlinkGcp(Signal* signal)
-{
- if (cfirstgcp == gcpPtr.i) {
- jam();
- cfirstgcp = gcpPtr.p->nextGcp;
- if (gcpPtr.i == clastgcp) {
- jam();
- clastgcp = RNIL;
- }//if
- } else {
- jam();
- /* --------------------------------------------------------------------
- * WE ARE TRYING TO REMOVE A GLOBAL CHECKPOINT WHICH WAS NOT THE OLDEST.
- * THIS IS A SYSTEM ERROR.
- * ------------------------------------------------------------------- */
- sendSystemError(signal, __LINE__);
- }//if
- gcpPtr.p->nextGcp = cfirstfreeGcp;
- cfirstfreeGcp = gcpPtr.i;
-}//Dbtc::unlinkGcp()
-
-void
-Dbtc::execDUMP_STATE_ORD(Signal* signal)
-{
- DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
- if(signal->theData[0] == DumpStateOrd::CommitAckMarkersSize){
- infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
- m_commitAckMarkerPool.getNoOfFree(),
- m_commitAckMarkerPool.getSize());
- }
- if(signal->theData[0] == DumpStateOrd::CommitAckMarkersDump){
- infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
- m_commitAckMarkerPool.getNoOfFree(),
- m_commitAckMarkerPool.getSize());
-
- CommitAckMarkerIterator iter;
- for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
- m_commitAckMarkerHash.next(iter)){
- infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
- " Api: %d Lghs(%d): %d %d %d %d bucket = %d",
- iter.curr.i,
- iter.curr.p->transid1,
- iter.curr.p->transid2,
- iter.curr.p->apiNodeId,
- iter.curr.p->noOfLqhs,
- iter.curr.p->lqhNodeId[0],
- iter.curr.p->lqhNodeId[1],
- iter.curr.p->lqhNodeId[2],
- iter.curr.p->lqhNodeId[3],
- iter.bucket);
- }
- }
- // Dump all ScanFragRecs
- if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
- Uint32 recordNo = 0;
- if (signal->getLength() == 1)
- infoEvent("TC: Dump all ScanFragRec - size: %d",
- cscanFragrecFileSize);
- else if (signal->getLength() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
-
- if (recordNo < cscanFragrecFileSize-1){
- dumpState->args[0] = DumpStateOrd::TcDumpAllScanFragRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- }
-
- // Dump one ScanFragRec
- if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
- Uint32 recordNo = RNIL;
- if (signal->getLength() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- if (recordNo >= cscanFragrecFileSize)
- return;
-
- ScanFragRecPtr sfp;
- sfp.i = recordNo;
- c_scan_frag_pool.getPtr(sfp);
- infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
- sfp.i,
- sfp.p->scanFragState,
- sfp.p->scanFragId);
- infoEvent(" nodeid=%d, timer=%d",
- refToNode(sfp.p->lqhBlockref),
- sfp.p->scanFragTimer);
- }
-
- // Dump all ScanRecords
- if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanRec){
- Uint32 recordNo = 0;
- if (signal->getLength() == 1)
- infoEvent("TC: Dump all ScanRecord - size: %d",
- cscanrecFileSize);
- else if (signal->getLength() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
-
- if (recordNo < cscanrecFileSize-1){
- dumpState->args[0] = DumpStateOrd::TcDumpAllScanRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- }
-
- // Dump all active ScanRecords
- if (dumpState->args[0] == DumpStateOrd::TcDumpAllActiveScanRec){
- Uint32 recordNo = 0;
- if (signal->getLength() == 1)
- infoEvent("TC: Dump active ScanRecord - size: %d",
- cscanrecFileSize);
- else if (signal->getLength() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- ScanRecordPtr sp;
- sp.i = recordNo;
- ptrAss(sp, scanRecord);
- if (sp.p->scanState != ScanRecord::IDLE){
- dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
- }
-
- if (recordNo < cscanrecFileSize-1){
- dumpState->args[0] = DumpStateOrd::TcDumpAllActiveScanRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- }
-
- // Dump one ScanRecord
- // and associated ScanFragRec and ApiConnectRecord
- if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
- Uint32 recordNo = RNIL;
- if (signal->getLength() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- if (recordNo >= cscanrecFileSize)
- return;
-
- ScanRecordPtr sp;
- sp.i = recordNo;
- ptrAss(sp, scanRecord);
- infoEvent("Dbtc::ScanRecord[%d]: state=%d"
- "nextfrag=%d, nofrag=%d",
- sp.i,
- sp.p->scanState,
- sp.p->scanNextFragId,
- sp.p->scanNoFrag);
- infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
- sp.p->scanAiLength,
- sp.p->scanParallel,
- sp.p->scanReceivedOperations,
- sp.p->batch_size_rows);
- infoEvent(" schv=%d, tab=%d, sproc=%d",
- sp.p->scanSchemaVersion,
- sp.p->scanTableref,
- sp.p->scanStoredProcId);
- infoEvent(" apiRec=%d, next=%d",
- sp.p->scanApiRec, sp.p->nextScan);
-
- if (sp.p->scanState != ScanRecord::IDLE){
- // Request dump of ScanFragRec
- ScanFragRecPtr sfptr;
-#define DUMP_SFR(x){\
- ScanFragList list(c_scan_frag_pool, x);\
- for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
- dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
- dumpState->args[1] = sfptr.i;\
- execDUMP_STATE_ORD(signal);\
- }}
-
- DUMP_SFR(sp.p->m_running_scan_frags);
- DUMP_SFR(sp.p->m_queued_scan_frags);
- DUMP_SFR(sp.p->m_delivered_scan_frags);
-
- // Request dump of ApiConnectRecord
- dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
- dumpState->args[1] = sp.p->scanApiRec;
- execDUMP_STATE_ORD(signal);
- }
-
- }
-
- // Dump all ApiConnectRecord(s)
- if (dumpState->args[0] == DumpStateOrd::TcDumpAllApiConnectRec){
- Uint32 recordNo = 0;
- if (signal->getLength() == 1)
- infoEvent("TC: Dump all ApiConnectRecord - size: %d",
- capiConnectFilesize);
- else if (signal->getLength() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
- dumpState->args[1] = recordNo;
- execDUMP_STATE_ORD(signal);
-
- if (recordNo < capiConnectFilesize-1){
- dumpState->args[0] = DumpStateOrd::TcDumpAllApiConnectRec;
- dumpState->args[1] = recordNo+1;
- sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
- }
- }
-
- // Dump one ApiConnectRecord
- if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
- Uint32 recordNo = RNIL;
- if (signal->getLength() == 2)
- recordNo = dumpState->args[1];
- else
- return;
-
- if (recordNo >= capiConnectFilesize)
- return;
-
- ApiConnectRecordPtr ap;
- ap.i = recordNo;
- ptrAss(ap, apiConnectRecord);
- infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
- "apiFailState=%d",
- ap.i,
- ap.p->apiConnectstate,
- ap.p->abortState,
- ap.p->apiFailState);
- infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
- ap.p->transid[0],
- ap.p->transid[1],
- ap.p->ndbapiBlockref,
- ap.p->apiScanRec);
- infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
- "retsig=%d",
- ctcTimer, getApiConTimer(ap.i),
- ap.p->counter,
- ap.p->returncode,
- ap.p->returnsignal);
- infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
- "tckeyrec=%d",
- ap.p->lqhkeyconfrec,
- ap.p->lqhkeyreqrec,
- ap.p->tckeyrec);
- infoEvent(" next=%d ",
- ap.p->nextApiConnect);
- }
-
- if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
- jam();
- if(signal->getLength() > 1){
- set_timeout_value(signal->theData[1]);
- }
- }
-
- if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
- jam();
- if(signal->getLength() > 1){
- set_appl_timeout_value(signal->theData[1]);
- }
- }
-
- if (dumpState->args[0] == DumpStateOrd::StartTcTimer){
- c_counters.c_trans_status = TransCounters::Started;
- c_counters.reset();
- }
-
- if (dumpState->args[0] == DumpStateOrd::StopTcTimer){
- c_counters.c_trans_status = TransCounters::Off;
- Uint32 len = c_counters.report(signal);
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
- c_counters.reset();
- }
-
- if (dumpState->args[0] == DumpStateOrd::StartPeriodicTcTimer){
- c_counters.c_trans_status = TransCounters::Timer;
- c_counters.reset();
- signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
- }
-
- if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
- {
- static int frequency = 1;
- if (signal->getLength() > 1)
- frequency = signal->theData[1];
- else
- if (refToBlock(signal->getSendersBlockRef()) != DBTC)
- frequency = 1;
-
- if (frequency)
- {
- dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
- execDUMP_STATE_ORD(signal);
- dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
-
- Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
- sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
- }
- }
-
- if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
- {
- infoEvent("IndexOpCount: pool: %d free: %d",
- c_theIndexOperationPool.getSize(),
- c_theIndexOperationPool.getNoOfFree());
- }
-
- if (dumpState->args[0] == 2514)
- {
- if (signal->getLength() == 2)
- {
- dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
- execDUMP_STATE_ORD(signal);
- }
-
- NodeReceiverGroup rg(CMVMI, c_alive_nodes);
- dumpState->args[0] = 15;
- sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
-
- signal->theData[0] = 2515;
- sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, 1000, 1);
- return;
- }
-
- if (dumpState->args[0] == 2515)
- {
- NdbNodeBitmask mask = c_alive_nodes;
- mask.clear(getOwnNodeId());
- NodeReceiverGroup rg(NDBCNTR, mask);
-
- sendSignal(rg, GSN_SYSTEM_ERROR, signal, 1, JBB);
- sendSignalWithDelay(cownref, GSN_SYSTEM_ERROR, signal, 300, 1);
- return;
- }
-}//Dbtc::execDUMP_STATE_ORD()
-
-void Dbtc::execABORT_ALL_REQ(Signal* signal)
-{
- jamEntry();
- AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
- AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
-
- const Uint32 senderData = req->senderData;
- const BlockReference senderRef = req->senderRef;
-
- if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
- jam();
-
- ref->senderData = senderData;
- ref->errorCode = AbortAllRef::InvalidState;
- sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
- AbortAllRef::SignalLength, JBB);
- return;
- }
-
- if(c_abortRec.clientRef != 0){
- jam();
-
- ref->senderData = senderData;
- ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
- sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
- AbortAllRef::SignalLength, JBB);
- return;
- }
-
- if(refToNode(senderRef) != getOwnNodeId()){
- jam();
-
- ref->senderData = senderData;
- ref->errorCode = AbortAllRef::FunctionNotImplemented;
- sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
- AbortAllRef::SignalLength, JBB);
- return;
- }
-
- c_abortRec.clientRef = senderRef;
- c_abortRec.clientData = senderData;
- c_abortRec.oldTimeOutValue = ctimeOutValue;
-
- ctimeOutValue = 0;
- const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
-
- checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
-}
-
-void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
-{
-
- ndbrequire(c_abortRec.clientRef != 0);
-
- if(sleepTime > 0){
- jam();
-
- sleepTime -= 1;
- signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
- signal->theData[1] = sleepTime;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
- return;
- }
-
- AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
- conf->senderData = c_abortRec.clientData;
- sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
- AbortAllConf::SignalLength, JBB);
-
- ctimeOutValue = c_abortRec.oldTimeOutValue;
- c_abortRec.clientRef = 0;
-}
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-void Dbtc::execCREATE_TRIG_REQ(Signal* signal)
-{
- jamEntry();
- CreateTrigReq * const createTrigReq =
- (CreateTrigReq *)&signal->theData[0];
- TcDefinedTriggerData* triggerData;
- DefinedTriggerPtr triggerPtr;
- BlockReference sender = signal->senderBlockRef();
-
- releaseSections(signal);
-
- triggerPtr.i = createTrigReq->getTriggerId();
- if (ERROR_INSERTED(8033) ||
- !c_theDefinedTriggers.seizeId(triggerPtr,
- createTrigReq->getTriggerId())) {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- // Failed to allocate trigger record
- CreateTrigRef * const createTrigRef =
- (CreateTrigRef *)&signal->theData[0];
-
- createTrigRef->setConnectionPtr(createTrigReq->getConnectionPtr());
- createTrigRef->setErrorCode(CreateTrigRef::TooManyTriggers);
- sendSignal(sender, GSN_CREATE_TRIG_REF,
- signal, CreateTrigRef::SignalLength, JBB);
- return;
- }
-
- triggerData = triggerPtr.p;
- triggerData->triggerId = createTrigReq->getTriggerId();
- triggerData->triggerType = createTrigReq->getTriggerType();
- triggerData->triggerEvent = createTrigReq->getTriggerEvent();
- triggerData->attributeMask = createTrigReq->getAttributeMask();
- if (triggerData->triggerType == TriggerType::SECONDARY_INDEX)
- triggerData->indexId = createTrigReq->getIndexId();
- CreateTrigConf * const createTrigConf =
- (CreateTrigConf *)&signal->theData[0];
-
- createTrigConf->setConnectionPtr(createTrigReq->getConnectionPtr());
- sendSignal(sender, GSN_CREATE_TRIG_CONF,
- signal, CreateTrigConf::SignalLength, JBB);
-}
-
-
-void Dbtc::execDROP_TRIG_REQ(Signal* signal)
-{
- jamEntry();
- DropTrigReq * const dropTrigReq = (DropTrigReq *)&signal->theData[0];
- BlockReference sender = signal->senderBlockRef();
-
- if (ERROR_INSERTED(8035) ||
- (c_theDefinedTriggers.getPtr(dropTrigReq->getTriggerId())) == NULL) {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- // Failed to find find trigger record
- DropTrigRef * const dropTrigRef = (DropTrigRef *)&signal->theData[0];
-
- dropTrigRef->setConnectionPtr(dropTrigReq->getConnectionPtr());
- dropTrigRef->setErrorCode(DropTrigRef::TriggerNotFound);
- sendSignal(sender, GSN_DROP_TRIG_REF,
- signal, DropTrigRef::SignalLength, JBB);
- return;
- }
-
- // Release trigger record
- c_theDefinedTriggers.release(dropTrigReq->getTriggerId());
-
- DropTrigConf * const dropTrigConf = (DropTrigConf *)&signal->theData[0];
-
- dropTrigConf->setConnectionPtr(dropTrigReq->getConnectionPtr());
- sendSignal(sender, GSN_DROP_TRIG_CONF,
- signal, DropTrigConf::SignalLength, JBB);
-}
-
-void Dbtc::execCREATE_INDX_REQ(Signal* signal)
-{
- jamEntry();
- CreateIndxReq * const createIndxReq =
- (CreateIndxReq *)signal->getDataPtr();
- TcIndexData* indexData;
- TcIndexDataPtr indexPtr;
- BlockReference sender = signal->senderBlockRef();
-
- if (ERROR_INSERTED(8034) ||
- !c_theIndexes.seizeId(indexPtr, createIndxReq->getIndexId())) {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- // Failed to allocate index record
- CreateIndxRef * const createIndxRef =
- (CreateIndxRef *)&signal->theData[0];
-
- createIndxRef->setConnectionPtr(createIndxReq->getConnectionPtr());
- createIndxRef->setErrorCode(CreateIndxRef::TooManyIndexes);
- releaseSections(signal);
- sendSignal(sender, GSN_CREATE_INDX_REF,
- signal, CreateIndxRef::SignalLength, JBB);
- return;
- }
- indexData = indexPtr.p;
- // Indexes always start in state IS_BUILDING
- // Will become IS_ONLINE in execALTER_INDX_REQ
- indexData->indexState = IS_BUILDING;
- indexData->indexId = indexPtr.i;
- indexData->primaryTableId = createIndxReq->getTableId();
-
- // So far need only attribute count
- SegmentedSectionPtr ssPtr;
- signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
- r0.reset(); // undo implicit first()
- if (!r0.getWord(&indexData->attributeList.sz) ||
- !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
- ndbrequire(false);
- }
- indexData->primaryKeyPos = indexData->attributeList.sz;
-
- releaseSections(signal);
-
- CreateIndxConf * const createIndxConf =
- (CreateIndxConf *)&signal->theData[0];
-
- createIndxConf->setConnectionPtr(createIndxReq->getConnectionPtr());
- createIndxConf->setTableId(createIndxReq->getTableId());
- createIndxConf->setIndexId(createIndxReq->getIndexId());
- sendSignal(sender, GSN_CREATE_INDX_CONF,
- signal, CreateIndxConf::SignalLength, JBB);
-}
-
-void Dbtc::execALTER_INDX_REQ(Signal* signal)
-{
- jamEntry();
- AlterIndxReq * const alterIndxReq = (AlterIndxReq *)signal->getDataPtr();
- TcIndexData* indexData;
- //BlockReference sender = signal->senderBlockRef();
- BlockReference sender = (BlockReference) alterIndxReq->getUserRef();
- Uint32 connectionPtr = alterIndxReq->getConnectionPtr();
- AlterIndxReq::RequestType requestType = alterIndxReq->getRequestType();
- Uint32 tableId = alterIndxReq->getTableId();
- Uint32 indexId = alterIndxReq->getIndexId();
- bool online = (alterIndxReq->getOnline() == 1) ? true : false;
-
- if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
- jam();
- // Failed to find index record
- AlterIndxRef * const alterIndxRef =
- (AlterIndxRef *)signal->getDataPtrSend();
-
- alterIndxRef->setUserRef(reference());
- alterIndxRef->setConnectionPtr(connectionPtr);
- alterIndxRef->setRequestType(requestType);
- alterIndxRef->setTableId(tableId);
- alterIndxRef->setIndexId(indexId);
- alterIndxRef->setErrorCode(AlterIndxRef::IndexNotFound);
- alterIndxRef->setErrorLine(__LINE__);
- alterIndxRef->setErrorNode(getOwnNodeId());
- sendSignal(sender, GSN_ALTER_INDX_REF,
- signal, AlterIndxRef::SignalLength, JBB);
- return;
- }
- // Found index record, alter it's state
- if (online) {
- jam();
- indexData->indexState = IS_ONLINE;
- } else {
- jam();
- indexData->indexState = IS_BUILDING;
- }//if
- AlterIndxConf * const alterIndxConf =
- (AlterIndxConf *)signal->getDataPtrSend();
-
- alterIndxConf->setUserRef(reference());
- alterIndxConf->setConnectionPtr(connectionPtr);
- alterIndxConf->setRequestType(requestType);
- alterIndxConf->setTableId(tableId);
- alterIndxConf->setIndexId(indexId);
- sendSignal(sender, GSN_ALTER_INDX_CONF,
- signal, AlterIndxConf::SignalLength, JBB);
-}
-
-void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
-{
- jamEntry();
- FireTrigOrd * const fireOrd = (FireTrigOrd *)signal->getDataPtr();
- ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
- ApiConnectRecordPtr transPtr;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
- TcConnectRecordPtr opPtr;
- /**
- * TODO
- * Check transid,
- * Fix overload i.e invalid word count
- */
- TcFiredTriggerData key;
- key.fireingOperation = fireOrd->getConnectionPtr();
- key.nodeId = refToNode(signal->getSendersBlockRef());
- FiredTriggerPtr trigPtr;
- if(c_firedTriggerHash.find(trigPtr, key)){
-
- c_firedTriggerHash.remove(trigPtr);
-
- trigPtr.p->fragId= fireOrd->fragId;
- bool ok = trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
- ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
- ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
- if(ok){
- opPtr.i = key.fireingOperation;
- ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
- transPtr.i = opPtr.p->apiConnect;
- transPtr.p = &localApiConnectRecord[transPtr.i];
-
- opPtr.p->noReceivedTriggers++;
- opPtr.p->triggerExecutionCount++;
-
- // Insert fired trigger in execution queue
- transPtr.p->theFiredTriggers.add(trigPtr);
- if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
- executeTriggers(signal, &transPtr);
- }
- return;
- }
- jam();
- c_theFiredTriggerPool.release(trigPtr);
- }
- jam();
- /**
- * Failed to find record or invalid word counts
- */
- ndbrequire(false);
-}
-
-void Dbtc::execTRIG_ATTRINFO(Signal* signal)
-{
- jamEntry();
- TrigAttrInfo * const trigAttrInfo = (TrigAttrInfo *)signal->getDataPtr();
- Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
- const Uint32 *src = trigAttrInfo->getData();
- FiredTriggerPtr firedTrigPtr;
-
- TcFiredTriggerData key;
- key.fireingOperation = trigAttrInfo->getConnectionPtr();
- key.nodeId = refToNode(signal->getSendersBlockRef());
- if(!c_firedTriggerHash.find(firedTrigPtr, key)){
- jam();
- if(!c_firedTriggerHash.seize(firedTrigPtr)){
- jam();
- /**
- * Will be handled when FIRE_TRIG_ORD arrives
- */
- ndbout_c("op: %d node: %d failed to seize",
- key.fireingOperation, key.nodeId);
- return;
- }
- ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
- firedTrigPtr.p->beforeValues.getSize() == 0 &&
- firedTrigPtr.p->afterValues.getSize() == 0);
-
- firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
- firedTrigPtr.p->fireingOperation = key.fireingOperation;
- firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
- c_firedTriggerHash.add(firedTrigPtr);
- }
-
- AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
- switch (trigAttrInfo->getAttrInfoType()) {
- case(TrigAttrInfo::PRIMARY_KEY):
- jam();
- {
- LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
- buf.append(src, attrInfoLength);
- }
- break;
- case(TrigAttrInfo::BEFORE_VALUES):
- jam();
- {
- LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
- buf.append(src, attrInfoLength);
- }
- break;
- case(TrigAttrInfo::AFTER_VALUES):
- jam();
- {
- LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
- buf.append(src, attrInfoLength);
- }
- break;
- default:
- ndbrequire(false);
- }
-}
-
-void Dbtc::execDROP_INDX_REQ(Signal* signal)
-{
- jamEntry();
- DropIndxReq * const dropIndxReq = (DropIndxReq *)signal->getDataPtr();
- TcIndexData* indexData;
- BlockReference sender = signal->senderBlockRef();
-
- if (ERROR_INSERTED(8036) ||
- (indexData = c_theIndexes.getPtr(dropIndxReq->getIndexId())) == NULL) {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- // Failed to find index record
- DropIndxRef * const dropIndxRef =
- (DropIndxRef *)signal->getDataPtrSend();
-
- dropIndxRef->setConnectionPtr(dropIndxReq->getConnectionPtr());
- dropIndxRef->setErrorCode(DropIndxRef::IndexNotFound);
- sendSignal(sender, GSN_DROP_INDX_REF,
- signal, DropIndxRef::SignalLength, JBB);
- return;
- }
- // Release index record
- c_theIndexes.release(dropIndxReq->getIndexId());
-
- DropIndxConf * const dropIndxConf =
- (DropIndxConf *)signal->getDataPtrSend();
-
- dropIndxConf->setConnectionPtr(dropIndxReq->getConnectionPtr());
- sendSignal(sender, GSN_DROP_INDX_CONF,
- signal, DropIndxConf::SignalLength, JBB);
-}
-
-void Dbtc::execTCINDXREQ(Signal* signal)
-{
- jamEntry();
-
- TcKeyReq * const tcIndxReq = (TcKeyReq *)signal->getDataPtr();
- const UintR TapiIndex = tcIndxReq->apiConnectPtr;
- Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
- Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
- Uint32 * dataPtr = &tcIndxReq->scanInfo;
- Uint32 indexBufSize = 8; // Maximum for index in TCINDXREQ
- Uint32 attrBufSize = 5; // Maximum for attrInfo in TCINDXREQ
- ApiConnectRecordPtr transPtr;
- transPtr.i = TapiIndex;
- if (transPtr.i >= capiConnectFilesize) {
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }//if
- ptrAss(transPtr, apiConnectRecord);
- ApiConnectRecord * const regApiPtr = transPtr.p;
- // Seize index operation
- TcIndexOperationPtr indexOpPtr;
- if ((startFlag == 1) &&
- (regApiPtr->apiConnectstate == CS_CONNECTED ||
- (regApiPtr->apiConnectstate == CS_STARTED &&
- regApiPtr->firstTcConnect == RNIL)) ||
- (regApiPtr->apiConnectstate == CS_ABORTING &&
- regApiPtr->abortState == AS_IDLE)) {
- jam();
- // This is a newly started transaction, clean-up
- releaseAllSeizedIndexOperations(regApiPtr);
-
- regApiPtr->apiConnectstate = CS_STARTED;
- regApiPtr->transid[0] = tcIndxReq->transId1;
- regApiPtr->transid[1] = tcIndxReq->transId2;
- }//if
-
- if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
- getNodeState().getSingleUserApi() !=
- refToNode(regApiPtr->ndbapiBlockref))
- {
- terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
- regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
- apiConnectptr = transPtr;
- abortErrorLab(signal);
- return;
- }
-
- if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
- jam();
- // Failed to allocate index operation
- terrorCode = 288;
- regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
- apiConnectptr = transPtr;
- abortErrorLab(signal);
- return;
- }
- TcIndexOperation* indexOp = indexOpPtr.p;
- indexOp->indexOpId = indexOpPtr.i;
-
- // Save original signal
- indexOp->tcIndxReq = *tcIndxReq;
- indexOp->connectionIndex = TapiIndex;
- regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
-
- // If operation is readTupleExclusive or updateTuple then read index
- // table with exclusive lock
- Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
- Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
- indexOp->expectedKeyInfo = indexLength;
- Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
- indexOp->expectedAttrInfo = attrLength;
- Uint32 includedAttrLength = MIN(attrLength, attrBufSize);
-
- int ret;
- if ((ret = saveINDXKEYINFO(signal,
- indexOp,
- dataPtr,
- includedIndexLength)) == 0)
- {
- jam();
- // We have received all we need
- readIndexTable(signal, regApiPtr, indexOp);
- return;
- }
- else if (ret == -1)
- {
- jam();
- return;
- }
-
- dataPtr += includedIndexLength;
- if (saveINDXATTRINFO(signal,
- indexOp,
- dataPtr,
- includedAttrLength) == 0) {
- jam();
- // We have received all we need
- readIndexTable(signal, regApiPtr, indexOp);
- return;
- }
-}
-
-
-void Dbtc::sendTcIndxConf(Signal* signal, UintR TcommitFlag)
-{
- HostRecordPtr localHostptr;
- ApiConnectRecord * const regApiPtr = apiConnectptr.p;
- const UintR TopWords = (UintR)regApiPtr->tcindxrec;
- localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
- const Uint32 type = getNodeInfo(localHostptr.i).m_type;
- const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
- const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
- const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL ? 0 : 1);
- ptrAss(localHostptr, hostRecord);
- UintR TcurrLen = localHostptr.p->noOfWordsTCINDXCONF;
- UintR confInfo = 0;
- TcIndxConf::setNoOfOperations(confInfo, (TopWords >> 1));
- TcIndxConf::setCommitFlag(confInfo, TcommitFlag == 1);
- TcIndxConf::setMarkerFlag(confInfo, Tmarker);
- const UintR TpacketLen = 6 + TopWords;
- regApiPtr->tcindxrec = 0;
-
- if(TcommitFlag || (regApiPtr->lqhkeyreqrec == regApiPtr->lqhkeyconfrec)){
- jam();
- regApiPtr->m_exec_flag = 0;
- }
-
- if ((TpacketLen > 25) || !is_api){
- TcIndxConf * const tcIndxConf = (TcIndxConf *)signal->getDataPtrSend();
-
- jam();
- tcIndxConf->apiConnectPtr = regApiPtr->ndbapiConnect;
- tcIndxConf->gci = regApiPtr->globalcheckpointid;;
- tcIndxConf->confInfo = confInfo;
- tcIndxConf->transId1 = regApiPtr->transid[0];
- tcIndxConf->transId2 = regApiPtr->transid[1];
- copyFromToLen(&regApiPtr->tcIndxSendArray[0],
- (UintR*)&tcIndxConf->operations,
- (UintR)ZTCOPCONF_SIZE);
- sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCINDXCONF, signal, (TpacketLen - 1), JBB);
- return;
- } else if (((TcurrLen + TpacketLen) > 25) && (TcurrLen > 0)) {
- jam();
- sendPackedTCINDXCONF(signal, localHostptr.p, localHostptr.i);
- TcurrLen = 0;
- } else {
- jam();
- updatePackedList(signal, localHostptr.p, localHostptr.i);
- }//if
-// -------------------------------------------------------------------------
-// The header contains the block reference of receiver plus the real signal
-// length - 3, since we have the real signal length plus one additional word
-// for the header we have to do - 4.
-// -------------------------------------------------------------------------
- UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
- UintR Tpack1 = regApiPtr->ndbapiConnect;
- UintR Tpack2 = regApiPtr->globalcheckpointid;
- UintR Tpack3 = confInfo;
- UintR Tpack4 = regApiPtr->transid[0];
- UintR Tpack5 = regApiPtr->transid[1];
-
- localHostptr.p->noOfWordsTCINDXCONF = TcurrLen + TpacketLen;
-
- localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 0] = Tpack0;
- localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 1] = Tpack1;
- localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 2] = Tpack2;
- localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 3] = Tpack3;
- localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 4] = Tpack4;
- localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 5] = Tpack5;
-
- UintR Ti;
- for (Ti = 6; Ti < TpacketLen; Ti++) {
- localHostptr.p->packedWordsTCINDXCONF[TcurrLen + Ti] =
- regApiPtr->tcIndxSendArray[Ti - 6];
- }//for
-}//Dbtc::sendTcIndxConf()
-
-void Dbtc::execINDXKEYINFO(Signal* signal)
-{
- jamEntry();
- Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
- IndxKeyInfo * const indxKeyInfo = (IndxKeyInfo *)signal->getDataPtr();
- const Uint32 *src = indxKeyInfo->getData();
- const UintR TconnectIndex = indxKeyInfo->connectPtr;
- ApiConnectRecordPtr transPtr;
- transPtr.i = TconnectIndex;
- if (transPtr.i >= capiConnectFilesize) {
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }//if
- ptrAss(transPtr, apiConnectRecord);
- ApiConnectRecord * const regApiPtr = transPtr.p;
- TcIndexOperationPtr indexOpPtr;
- TcIndexOperation* indexOp;
-
- if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
- {
- TCKEY_abort(signal, 19);
- return;
- }
-
- if (regApiPtr->apiConnectstate == CS_ABORTING)
- {
- jam();
- return;
- }
-
- if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
- {
- indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
- if (saveINDXKEYINFO(signal,
- indexOp,
- src,
- keyInfoLength) == 0) {
- jam();
- // We have received all we need
- readIndexTable(signal, regApiPtr, indexOp);
- }
- }
-}
-
-void Dbtc::execINDXATTRINFO(Signal* signal)
-{
- jamEntry();
- Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
- IndxAttrInfo * const indxAttrInfo = (IndxAttrInfo *)signal->getDataPtr();
- const Uint32 *src = indxAttrInfo->getData();
- const UintR TconnectIndex = indxAttrInfo->connectPtr;
- ApiConnectRecordPtr transPtr;
- transPtr.i = TconnectIndex;
- if (transPtr.i >= capiConnectFilesize) {
- jam();
- warningHandlerLab(signal, __LINE__);
- return;
- }//if
- ptrAss(transPtr, apiConnectRecord);
- ApiConnectRecord * const regApiPtr = transPtr.p;
- TcIndexOperationPtr indexOpPtr;
- TcIndexOperation* indexOp;
-
- if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
- {
- TCKEY_abort(signal, 19);
- return;
- }
-
- if (regApiPtr->apiConnectstate == CS_ABORTING)
- {
- jam();
- return;
- }
-
- if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
- {
- indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
- if (saveINDXATTRINFO(signal,
- indexOp,
- src,
- attrInfoLength) == 0) {
- jam();
- // We have received all we need
- readIndexTable(signal, regApiPtr, indexOp);
- return;
- }
- return;
- }
-}
-
-/**
- * Save signal INDXKEYINFO
- * Return true if we have received all needed data
- */
-int
-Dbtc::saveINDXKEYINFO(Signal* signal,
- TcIndexOperation* indexOp,
- const Uint32 *src,
- Uint32 len)
-{
- if (ERROR_INSERTED(8052) || !indexOp->keyInfo.append(src, len)) {
- jam();
- // Failed to seize keyInfo, abort transaction
-#ifdef VM_TRACE
- ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize keyinfo\n");
-#endif
- // Abort transaction
- apiConnectptr.i = indexOp->connectionIndex;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- releaseIndexOperation(apiConnectptr.p, indexOp);
- terrorCode = 289;
- if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
- apiConnectptr.p->m_exec_flag= 1;
- abortErrorLab(signal);
- return -1;
- }
- if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
- jam();
- return 0;
- }
- return 1;
-}
-
-bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
-{
- return (indexOp->keyInfo.getSize() == indexOp->expectedKeyInfo);
-}
-
-/**
- * Save signal INDXATTRINFO
- * Return true if we have received all needed data
- */
-int
-Dbtc::saveINDXATTRINFO(Signal* signal,
- TcIndexOperation* indexOp,
- const Uint32 *src,
- Uint32 len)
-{
- if (ERROR_INSERTED(8051) || !indexOp->attrInfo.append(src, len)) {
- jam();
-#ifdef VM_TRACE
- ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize attrInfo\n");
-#endif
- apiConnectptr.i = indexOp->connectionIndex;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- releaseIndexOperation(apiConnectptr.p, indexOp);
- terrorCode = 289;
- if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
- apiConnectptr.p->m_exec_flag= 1;
- abortErrorLab(signal);
- return -1;
- }
- if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
- jam();
- return 0;
- }
- return 1;
-}
-
-bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
-{
- return (indexOp->attrInfo.getSize() == indexOp->expectedAttrInfo);
-}
-
-bool Dbtc::saveTRANSID_AI(Signal* signal,
- TcIndexOperation* indexOp,
- const Uint32 *src,
- Uint32 len)
-{
- Uint32 currentTransIdAILength = indexOp->transIdAI.getSize();
-
- if (currentTransIdAILength == 0) {
- jam();
- // Read first AttributeHeader to get expected size
- // of the single key attribute expected
- AttributeHeader* head = (AttributeHeader *) src;
- indexOp->expectedTransIdAI = head->getHeaderSize() + head->getDataSize();
- }
- if (!indexOp->transIdAI.append(src, len)) {
- jam();
-#ifdef VM_TRACE
- ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize transIdAI\n");
-#endif
- apiConnectptr.i = indexOp->connectionIndex;
- ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
- releaseIndexOperation(apiConnectptr.p, indexOp);
- terrorCode = 4000;
- abortErrorLab(signal);
- return false;
- }
- return true;
-}
-
-bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
-{
- return (indexOp->transIdAI.getSize() == indexOp->expectedTransIdAI);
-}
-
-/**
- * Receive signal TCINDXCONF
- * This can be either the return of reading an index table
- * or performing an index operation
- */
-void Dbtc::execTCKEYCONF(Signal* signal)
-{
- TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtr();
- TcIndexOperationPtr indexOpPtr;
-
- jamEntry();
- indexOpPtr.i = tcKeyConf->apiConnectPtr;
- TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
- Uint32 confInfo = tcKeyConf->confInfo;
-
- /**
- * Check on TCKEYCONF wheater the the transaction was committed
- */
- Uint32 Tcommit = TcKeyConf::getCommitFlag(confInfo);
-
- indexOpPtr.p = indexOp;
- if (!indexOp) {
- jam();
- // Missing index operation
- return;
- }
- const UintR TconnectIndex = indexOp->connectionIndex;
- ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
- apiConnectptr.p = regApiPtr;
- apiConnectptr.i = TconnectIndex;
- switch(indexOp->indexOpState) {
- case(IOS_NOOP): {
- jam();
- // Should never happen, abort
- 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;
- tcIndxRef->errorData = 0;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- return;
- }
- case(IOS_INDEX_ACCESS): {
- jam();
- // Wait for TRANSID_AI
- indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
- break;
- }
- case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
- jam();
- // Double TCKEYCONF, should never happen, abort
- 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;
- tcIndxRef->errorData = 0;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- return;
- }
- case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
- jam();
- // Continue with index operation
- executeIndexOperation(signal, regApiPtr, indexOp);
- break;
- }
- case(IOS_INDEX_OPERATION): {
- // We are done, send TCINDXCONF
- jam();
- Uint32 Ttcindxrec = regApiPtr->tcindxrec;
- // Copy reply from TcKeyConf
-
- ndbassert(regApiPtr->noIndexOp);
- regApiPtr->noIndexOp--; // Decrease count
- regApiPtr->tcIndxSendArray[Ttcindxrec] = indexOp->tcIndxReq.senderData;
- regApiPtr->tcIndxSendArray[Ttcindxrec + 1] =
- tcKeyConf->operations[0].attrInfoLen;
- regApiPtr->tcindxrec = Ttcindxrec + 2;
- if (regApiPtr->noIndexOp == 0) {
- jam();
- sendTcIndxConf(signal, Tcommit);
- } else if (regApiPtr->tcindxrec == ZTCOPCONF_SIZE) {
- jam();
- sendTcIndxConf(signal, 0);
- }
- releaseIndexOperation(regApiPtr, indexOp);
- break;
- }
- }
-}
-
-void Dbtc::execTCKEYREF(Signal* signal)
-{
- TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
- TcIndexOperationPtr indexOpPtr;
-
- jamEntry();
- indexOpPtr.i = tcKeyRef->connectPtr;
- TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
- indexOpPtr.p = indexOp;
- if (!indexOp) {
- jam();
- // Missing index operation
- return;
- }
- const UintR TconnectIndex = indexOp->connectionIndex;
- ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
-
- switch(indexOp->indexOpState) {
- case(IOS_NOOP): {
- jam();
- // Should never happen, abort
- break;
- }
- case(IOS_INDEX_ACCESS):
- case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
- case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
- jam();
- /**
- * Increase count as it will be decreased below...
- * (and the code is written to handle failing lookup on "real" table
- * not lookup on index table)
- */
- regApiPtr->noIndexOp++;
- // else continue
- }
- case(IOS_INDEX_OPERATION): {
- // Send TCINDXREF
-
- jam();
- TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
- TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
-
- ndbassert(regApiPtr->noIndexOp);
- regApiPtr->noIndexOp--; // Decrease count
- tcIndxRef->connectPtr = tcIndxReq->senderData;
- tcIndxRef->transId[0] = tcKeyRef->transId[0];
- tcIndxRef->transId[1] = tcKeyRef->transId[1];
- tcIndxRef->errorCode = tcKeyRef->errorCode;
- tcIndxRef->errorData = 0;
-
- releaseIndexOperation(regApiPtr, indexOp);
-
- sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
- return;
- }
- }
-}
-
-void Dbtc::execTRANSID_AI_R(Signal* signal){
- TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
- Uint32 sigLen = signal->length();
- Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
- Uint32 recBlockref = transIdAI->attrData[dataLen];
-
- jamEntry();
-
- /**
- * Forward signal to final destination
- * Truncate last word since that was used to hold the final dest.
- */
- sendSignal(recBlockref, GSN_TRANSID_AI,
- signal, sigLen - 1, JBB);
-}
-
-void Dbtc::execKEYINFO20_R(Signal* signal){
- KeyInfo20 * const keyInfo = (KeyInfo20 *)signal->getDataPtr();
- Uint32 sigLen = signal->length();
- Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
- Uint32 recBlockref = keyInfo->keyData[dataLen];
-
- jamEntry();
-
- /**
- * Forward signal to final destination
- * Truncate last word since that was used to hold the final dest.
- */
- sendSignal(recBlockref, GSN_KEYINFO20,
- signal, sigLen - 1, JBB);
-}
-
-
-void Dbtc::execTRANSID_AI(Signal* signal)
-{
- TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
-
- jamEntry();
- TcIndexOperationPtr indexOpPtr;
- indexOpPtr.i = transIdAI->connectPtr;
- TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
- indexOpPtr.p = indexOp;
- if (!indexOp) {
- jam();
- // Missing index operation
- }
- const UintR TconnectIndex = indexOp->connectionIndex;
- // ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
- ApiConnectRecordPtr transPtr;
-
- transPtr.i = TconnectIndex;
- ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
- ApiConnectRecord * const regApiPtr = transPtr.p;
-
- // Acccumulate attribute data
- if (!saveTRANSID_AI(signal,
- indexOp,
- transIdAI->getData(),
- signal->getLength() - TransIdAI::HeaderLength)) {
- jam();
- // Failed to allocate space for TransIdAI
- 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;
- tcIndxRef->errorData = 0;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- return;
- }
-
- switch(indexOp->indexOpState) {
- case(IOS_NOOP): {
- jam();
- // Should never happen, abort
- 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;
- tcIndxRef->errorData = 0;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- return;
- break;
- }
- case(IOS_INDEX_ACCESS): {
- jam();
- // Check if all TRANSID_AI have been received
- if (receivedAllTRANSID_AI(indexOp)) {
- jam();
- // Wait for TRANSID_AI
- indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
- }
- break;
- }
- case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
- jam();
-#ifdef VM_TRACE
- ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
-#endif
- /*
- // Too many TRANSID_AI
- 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;
- tcIndxRef->errorData = 0;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- */
- break;
- }
- case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
- jam();
- // Check if all TRANSID_AI have been received
- if (receivedAllTRANSID_AI(indexOp)) {
- jam();
- // Continue with index operation
- executeIndexOperation(signal, regApiPtr, indexOp);
- }
- // else continue waiting for more TRANSID_AI
- break;
- }
- case(IOS_INDEX_OPERATION): {
- // Should never receive TRANSID_AI in this state!!
- jam();
- 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;
- tcIndxRef->errorData = regApiPtr->errorData;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- return;
- }
- }
-}
-
-void Dbtc::execTCROLLBACKREP(Signal* signal)
-{
- TcRollbackRep* tcRollbackRep = (TcRollbackRep *)signal->getDataPtr();
- jamEntry();
- TcIndexOperationPtr indexOpPtr;
- indexOpPtr.i = tcRollbackRep->connectPtr;
- TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
- indexOpPtr.p = indexOp;
- tcRollbackRep = (TcRollbackRep *)signal->getDataPtrSend();
- tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
- sendSignal(apiConnectptr.p->ndbapiBlockref,
- GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
-}
-
-/**
- * Read index table with the index attributes as PK
- */
-void Dbtc::readIndexTable(Signal* signal,
- ApiConnectRecord* regApiPtr,
- TcIndexOperation* indexOp)
-{
- Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
- Uint32 dataPos = 0;
- TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
- Uint32 * dataPtr = &tcKeyReq->scanInfo;
- Uint32 tcKeyLength = TcKeyReq::StaticLength;
- Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
- AttributeBuffer::DataBufferIterator keyIter;
- Uint32 keyLength = TcKeyReq::getKeyLength(tcKeyRequestInfo);
- TcIndexData* indexData;
- Uint32 transId1 = indexOp->tcIndxReq.transId1;
- Uint32 transId2 = indexOp->tcIndxReq.transId2;
-
- const Operation_t opType =
- (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
-
- // Find index table
- if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
- jam();
- // Failed to find index record
- 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;
- // tcIndxRef->errorData = ??; Where to find indexId
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- return;
- }
- tcKeyReq->transId1 = transId1;
- tcKeyReq->transId2 = transId2;
- tcKeyReq->tableId = indexData->indexId;
- tcKeyLength += MIN(keyLength, keyBufSize);
- tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
- TcKeyReq::setOperationType(tcKeyRequestInfo,
- opType == ZREAD ? ZREAD : ZREAD_EX);
- TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
- TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
- tcKeyReq->senderData = indexOp->indexOpId;
- indexOp->indexOpState = IOS_INDEX_ACCESS;
- regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
- regApiPtr->accumulatingIndexOp = RNIL;
- regApiPtr->isIndexOp = 2;
-
- if (ERROR_INSERTED(8037))
- {
- ndbout_c("shifting index version");
- tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
- }
-
- Uint32 remainingKey = indexOp->keyInfo.getSize();
- bool moreKeyData = indexOp->keyInfo.first(keyIter);
- // *********** KEYINFO in TCKEYREQ ***********
- while((dataPos < keyBufSize) &&
- (remainingKey-- != 0)) {
- *dataPtr++ = *keyIter.data;
- dataPos++;
- moreKeyData = indexOp->keyInfo.next(keyIter);
- }
- // *********** ATTRINFO in TCKEYREQ ***********
- tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
- AttributeHeader::init(dataPtr, indexData->primaryKeyPos, 0);
- tcKeyLength++;
- tcKeyReq->requestInfo = tcKeyRequestInfo;
-
- ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
- ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
- EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
- jamEntry();
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- goto err;
- }
-
- // *********** KEYINFO ***********
- if (moreKeyData) {
- jam();
- // Send KEYINFO sequence
- KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
-
- keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
- keyInfo->transId[0] = transId1;
- keyInfo->transId[1] = transId2;
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- while(remainingKey-- != 0) {// If we have not read complete key
- *dataPtr++ = *keyIter.data;
- dataPos++;
- if (dataPos == KeyInfo::DataLength) {
- // Flush KEYINFO
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength);
- jamEntry();
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- goto err;
- }
- dataPos = 0;
- dataPtr = (Uint32 *) &keyInfo->keyData;
- }
- moreKeyData = indexOp->keyInfo.next(keyIter);
- }
- if (dataPos != 0) {
- // Flush last KEYINFO
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + dataPos);
- jamEntry();
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- goto err;
- }
- }
- }
-
- /**
- * "Fool" TC not to start commiting transaction since it always will
- * have one outstanding lqhkeyreq
- * This is later decreased when the index read is complete
- */
- regApiPtr->lqhkeyreqrec++;
-
- /**
- * Remember ptr to index read operation
- * (used to set correct save point id on index operation later)
- */
- indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
-
-done:
- return;
-
-err:
- jam();
- goto done;
-}
-
-/**
- * Execute the index operation with the result from
- * the index table read as PK
- */
-void Dbtc::executeIndexOperation(Signal* signal,
- ApiConnectRecord* regApiPtr,
- TcIndexOperation* indexOp) {
-
- Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
- Uint32 attrBufSize = 5;
- Uint32 dataPos = 0;
- TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
- TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
- /*
- Data points to distrGroupHashValue since scanInfo is used to send
- fragment id of receiving fragment
- */
- Uint32 * dataPtr = &tcKeyReq->distrGroupHashValue;
- Uint32 tcKeyLength = TcKeyReq::StaticLength;
- Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
- TcIndexData* indexData;
- AttributeBuffer::DataBufferIterator attrIter;
- AttributeBuffer::DataBufferIterator aiIter;
- bool moreKeyData = indexOp->transIdAI.first(aiIter);
-
- // Find index table
- if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
- jam();
- // Failed to find index record
- 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;
- tcIndxRef->errorData = 0;
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcKeyRef::SignalLength, JBB);
- return;
- }
- // Find schema version of primary table
- TableRecordPtr tabPtr;
- tabPtr.i = indexData->primaryTableId;
- ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
-
- tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
- tcKeyReq->attrLen = tcIndxReq->attrLen;
- tcKeyReq->tableId = indexData->primaryTableId;
- tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
- tcKeyReq->transId1 = regApiPtr->transid[0];
- tcKeyReq->transId2 = regApiPtr->transid[1];
- tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
- indexOp->indexOpState = IOS_INDEX_OPERATION;
- regApiPtr->isIndexOp = 1;
- regApiPtr->executingIndexOp = indexOp->indexOpId;;
- regApiPtr->noIndexOp++; // Increase count
-
- /*
- Filter out AttributeHeader:s since this should not be in key.
- Also filter out fragment id from primary key and handle that
- separately by setting it as Distribution Key and set indicator.
- */
-
- AttributeHeader* attrHeader = (AttributeHeader *) aiIter.data;
-
- Uint32 headerSize = attrHeader->getHeaderSize();
- Uint32 keySize = attrHeader->getDataSize() - 1;
- TcKeyReq::setKeyLength(tcKeyRequestInfo, keySize);
- // Skip header
- if (headerSize == 1) {
- jam();
- moreKeyData = indexOp->transIdAI.next(aiIter);
- } else {
- jam();
- moreKeyData = indexOp->transIdAI.next(aiIter, headerSize - 1);
- }//if
- tcKeyReq->scanInfo = *aiIter.data; //Fragment Id
- moreKeyData = indexOp->transIdAI.next(aiIter);
- TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
- while(// If we have not read complete key
- (keySize != 0) &&
- (dataPos < keyBufSize)) {
- *dataPtr++ = *aiIter.data;
- dataPos++;
- keySize--;
- moreKeyData = indexOp->transIdAI.next(aiIter);
- }
- tcKeyLength += dataPos;
-
- Uint32 attributesLength = indexOp->attrInfo.getSize();
- if (attributesLength <= attrBufSize) {
- jam();
- // ATTRINFO fits in TCKEYREQ
- // Pack ATTRINFO IN TCKEYREQ
- TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, indexOp->attrInfo.getSize());
- // Insert IndxAttrInfo
- for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
- moreAttrData;
- moreAttrData = indexOp->attrInfo.next(attrIter)) {
- *dataPtr++ = *attrIter.data;
- }
- tcKeyLength += attributesLength;
- } else {
- jam();
- // No ATTRINFO in TCKEYREQ
- TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
- }
-
- TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
- TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
- TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
- tcKeyReq->requestInfo = tcKeyRequestInfo;
-
- ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
- ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
-
- /**
- * Decrease lqhkeyreqrec to compensate for addition
- * during read of index table
- * I.e. let TC start committing when other operations has completed
- */
- regApiPtr->lqhkeyreqrec--;
-
- /**
- * Fix savepoint id -
- * fix so that index operation has the same savepoint id
- * as the read of the index table (TCINDXREQ)
- */
- TcConnectRecordPtr tmp;
- tmp.i = indexOp->indexReadTcConnect;
- ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
- const Uint32 currSavePointId = regApiPtr->currSavePointId;
- regApiPtr->currSavePointId = tmp.p->savePointId;
- EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
- jamEntry();
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- regApiPtr->currSavePointId = currSavePointId;
-
- // *********** KEYINFO ***********
- if (moreKeyData) {
- jam();
- // Send KEYINFO sequence
- KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
-
- keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
- keyInfo->transId[0] = regApiPtr->transid[0];
- keyInfo->transId[1] = regApiPtr->transid[1];
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- // Pack any part of a key attribute that did no fit TCKEYREQ
- while(keySize-- != 0) {// If we have not read complete key
- *dataPtr++ = *aiIter.data;
- dataPos++;
- if (dataPos == KeyInfo::DataLength) {
- // Flush KEYINFO
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength);
- jamEntry();
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- dataPos = 0;
- dataPtr = (Uint32 *) &keyInfo->keyData;
- }
- moreKeyData = indexOp->transIdAI.next(aiIter);
- }
- if (dataPos != 0) {
- // Flush last KEYINFO
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + dataPos);
- jamEntry();
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
- }
- }
-
- // *********** ATTRINFO ***********
- if (attributesLength > attrBufSize) {
- jam();
- // No ATTRINFO in TcKeyReq
- TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
- // Send ATTRINFO sequence
- AttrInfo * const attrInfo = (AttrInfo *)signal->getDataPtrSend();
- Uint32 attrInfoPos = 0;
-
- attrInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
- attrInfo->transId[0] = regApiPtr->transid[0];
- attrInfo->transId[1] = regApiPtr->transid[1];
- dataPtr = (Uint32 *) &attrInfo->attrData;
-
-
- // Insert attribute values (insert key values of primary table)
- for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
- moreAttrData;
- moreAttrData = indexOp->attrInfo.next(attrIter)) {
- *dataPtr++ = *attrIter.data;
- attrInfoPos++;
- if (attrInfoPos == AttrInfo::DataLength) {
- // Flush ATTRINFO
- EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + AttrInfo::DataLength);
- jamEntry();
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- attrInfoPos = 0;
- dataPtr = (Uint32 *) &attrInfo->attrData;
- }
- }
- if (attrInfoPos != 0) {
- // Send last ATTRINFO
- EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + attrInfoPos);
- jamEntry();
- }
- }
-}
-
-bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
- TcIndexOperationPtr& indexOpPtr)
-{
- if (regApiPtr->theSeizedIndexOperations.seize(indexOpPtr))
- {
- ndbassert(indexOpPtr.p->expectedKeyInfo == 0);
- ndbassert(indexOpPtr.p->keyInfo.getSize() == 0);
- ndbassert(indexOpPtr.p->expectedAttrInfo == 0);
- ndbassert(indexOpPtr.p->attrInfo.getSize() == 0);
- ndbassert(indexOpPtr.p->expectedTransIdAI == 0);
- ndbassert(indexOpPtr.p->transIdAI.getSize() == 0);
- return true;
- }
-
- return false;
-}
-
-void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
- TcIndexOperation* indexOp)
-{
- indexOp->indexOpState = IOS_NOOP;
- indexOp->expectedKeyInfo = 0;
- indexOp->keyInfo.release();
- indexOp->expectedAttrInfo = 0;
- indexOp->attrInfo.release();
- indexOp->expectedTransIdAI = 0;
- indexOp->transIdAI.release();
- regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
-}
-
-void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
-{
- TcIndexOperationPtr seizedIndexOpPtr;
-
- regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
- while(seizedIndexOpPtr.i != RNIL) {
- jam();
- TcIndexOperation* indexOp = seizedIndexOpPtr.p;
-
- indexOp->indexOpState = IOS_NOOP;
- indexOp->expectedKeyInfo = 0;
- indexOp->keyInfo.release();
- indexOp->expectedAttrInfo = 0;
- indexOp->attrInfo.release();
- indexOp->expectedTransIdAI = 0;
- indexOp->transIdAI.release();
- regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
- }
- regApiPtr->theSeizedIndexOperations.release();
-}
-
-void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
-{
- LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
- copyFromToLen((UintR*)lqhKeyConf,
- &trigOp->savedState[0],
- LqhKeyConf::SignalLength);
-}
-
-void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
-{
- LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
- copyFromToLen(&trigOp->savedState[0],
- (UintR*)lqhKeyConf,
- LqhKeyConf::SignalLength);
-
- lqhKeyConf->noFiredTriggers = 0;
- trigOp->noReceivedTriggers = 0;
-
- // All triggers executed successfully, continue operation
- execLQHKEYCONF(signal);
-}
-
-void Dbtc::scheduleFiredTrigger(ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr)
-{
- // Set initial values for trigger fireing operation
- opPtr->p->triggerExecutionCount++;
-
- // Insert fired trigger in execution queue
- transPtr->p->theFiredTriggers.add(opPtr->p->accumulatingTriggerData);
- opPtr->p->accumulatingTriggerData.i = RNIL;
- opPtr->p->accumulatingTriggerData.p = NULL;
-}
-
-void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
-{
- ApiConnectRecord* regApiPtr = transPtr->p;
- TcConnectRecord *localTcConnectRecord = tcConnectRecord;
- TcConnectRecordPtr opPtr;
- FiredTriggerPtr trigPtr;
-
- if (!regApiPtr->theFiredTriggers.isEmpty()) {
- jam();
- if ((regApiPtr->apiConnectstate == CS_STARTED) ||
- (regApiPtr->apiConnectstate == CS_START_COMMITTING)) {
- jam();
- regApiPtr->theFiredTriggers.first(trigPtr);
- while (trigPtr.i != RNIL) {
- jam();
- // Execute all ready triggers in parallel
- opPtr.i = trigPtr.p->fireingOperation;
- ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
- FiredTriggerPtr nextTrigPtr = trigPtr;
- regApiPtr->theFiredTriggers.next(nextTrigPtr);
- if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
- jam();
- // Fireing operation is ready to have a trigger executing
- executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
- // Should allow for interleaving here by sending a CONTINUEB and
- // return
- // Release trigger records
- AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
- LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
- tmp1.release();
- LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
- tmp2.release();
- LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
- tmp3.release();
- regApiPtr->theFiredTriggers.release(trigPtr);
- }
- trigPtr = nextTrigPtr;
- }
- return;
- // No more triggers, continue transaction after last executed trigger has
- // reurned (in execLQHKEYCONF or execLQHKEYREF)
- } else {
- // Wait until transaction is ready to execute a trigger
- jam();
- if (!regApiPtr->triggerPending) {
- jam();
- regApiPtr->triggerPending = true;
- signal->theData[0] = TcContinueB::TRIGGER_PENDING;
- signal->theData[1] = transPtr->i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- }
- // else
- // We are already waiting for a pending trigger (CONTINUEB)
- }
- }
-}
-
-void Dbtc::executeTrigger(Signal* signal,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr)
-{
- TcDefinedTriggerData* definedTriggerData;
-
- if ((definedTriggerData =
- c_theDefinedTriggers.getPtr(firedTriggerData->triggerId))
- != NULL) {
- switch(definedTriggerData->triggerType) {
- case(TriggerType::SECONDARY_INDEX):
- jam();
- executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
- transPtr, opPtr);
- break;
- default:
- ndbrequire(false);
- }
- }
-}
-
-void Dbtc::executeIndexTrigger(Signal* signal,
- TcDefinedTriggerData* definedTriggerData,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr)
-{
- TcIndexData* indexData;
-
- indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
- ndbassert(indexData != NULL);
-
- switch (definedTriggerData->triggerEvent) {
- case(TriggerEvent::TE_INSERT): {
- jam();
- insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
- break;
- }
- case(TriggerEvent::TE_DELETE): {
- jam();
- deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
- break;
- }
- case(TriggerEvent::TE_UPDATE): {
- jam();
- deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr,
- indexData, true); // Hold the triggering operation
- insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
- break;
- }
- default:
- ndbrequire(false);
- }
-}
-
-void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
-{
- FiredTriggerPtr trigPtr;
-
- triggers->first(trigPtr);
- while (trigPtr.i != RNIL) {
- jam();
- // Release trigger records
-
- AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
- LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
- tmp1.release();
- LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
- tmp2.release();
- LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
- tmp3.release();
-
- triggers->next(trigPtr);
- }
- triggers->release();
-}
-
-void Dbtc::insertIntoIndexTable(Signal* signal,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr,
- TcIndexData* indexData,
- bool holdOperation)
-{
- ApiConnectRecord* regApiPtr = transPtr->p;
- TcConnectRecord* opRecord = opPtr->p;
- TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
- Uint32 tcKeyRequestInfo = 0;
- Uint32 tcKeyLength = TcKeyReq::StaticLength;
- TableRecordPtr indexTabPtr;
- AttributeBuffer::DataBufferIterator iter;
- Uint32 attrId = 0;
- Uint32 keyLength = 0;
- Uint32 totalPrimaryKeyLength = 1; // fragment length
- Uint32 hops;
-
- indexTabPtr.i = indexData->indexId;
- ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
- tcKeyReq->apiConnectPtr = transPtr->i;
- tcKeyReq->senderData = opPtr->i;
- if (holdOperation) {
- jam();
- opRecord->triggerExecutionCount++;
- }//if
- // Calculate key length and renumber attribute id:s
- AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
- LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
- bool skipNull = false;
- for(bool moreKeyAttrs = afterValues.first(iter); moreKeyAttrs; attrId++) {
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- // Filter out NULL valued attributes
- if (attrHeader->isNULL()) {
- skipNull = true;
- break;
- }
- attrHeader->setAttributeId(attrId);
- keyLength += attrHeader->getDataSize();
- hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
- moreKeyAttrs = afterValues.next(iter, hops);
- }
- if (skipNull) {
- jam();
- opRecord->triggerExecutionCount--;
- if (opRecord->triggerExecutionCount == 0) {
- /*
- We have completed current trigger execution
- Continue triggering operation
- */
- jam();
- continueTriggeringOp(signal, opRecord);
- }//if
- return;
- }//if
-
- // Calculate total length of primary key to be stored in index table
- LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
- for(bool moreAttrData = keyValues.first(iter); moreAttrData; ) {
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- totalPrimaryKeyLength += attrHeader->getDataSize();
- hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
- moreAttrData = keyValues.next(iter, hops);
- }
- AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength << 2);
- Uint32 attributesLength = afterValues.getSize() +
- pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
-
- TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
- tcKeyReq->attrLen = attributesLength;
- tcKeyReq->tableId = indexData->indexId;
- TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
- TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
- tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
- tcKeyReq->transId1 = regApiPtr->transid[0];
- tcKeyReq->transId2 = regApiPtr->transid[1];
- Uint32 * dataPtr = &tcKeyReq->scanInfo;
- // Write first part of key in TCKEYREQ
- Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
- Uint32 attrBufSize = 5; // Maximum for key in TCKEYREQ
- Uint32 dataPos = 0;
- // Filter out AttributeHeader:s since this should no be in key
- bool moreKeyData = afterValues.first(iter);
- Uint32 headerSize = 0, keyAttrSize = 0, dataSize = 0, headAndData = 0;
-
- while (moreKeyData && (dataPos < keyBufSize)) {
- /*
- * If we have not read complete key
- * and it fits in the signal
- */
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- headerSize = attrHeader->getHeaderSize();
- keyAttrSize = attrHeader->getDataSize();
- headAndData = headerSize + attrHeader->getDataSize();
- // Skip header
- if (headerSize == 1) {
- jam();
- moreKeyData = afterValues.next(iter);
- } else {
- jam();
- moreKeyData = afterValues.next(iter, headerSize - 1);
- }//if
- while((keyAttrSize != 0) && (dataPos < keyBufSize)) {
- // If we have not read complete key
- jam();
- *dataPtr++ = *iter.data;
- dataPos++;
- keyAttrSize--;
- moreKeyData = afterValues.next(iter);
- }
- if (keyAttrSize != 0) {
- jam();
- break;
- }//if
- }
-
- tcKeyLength += dataPos;
- /*
- Size of attrinfo is unique index attributes one by one, header for each
- of them (all contained in the afterValues data structure), plus a header,
- the primary key (compacted) and the fragment id before the primary key
- */
- if (attributesLength <= attrBufSize) {
- jam();
- // ATTRINFO fits in TCKEYREQ
- // Pack ATTRINFO IN TCKEYREQ as one attribute
- TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, attributesLength);
- bool moreAttrData;
- // Insert primary key attributes (insert after values of primary table)
- for(moreAttrData = afterValues.first(iter);
- moreAttrData;
- moreAttrData = afterValues.next(iter)) {
- *dataPtr++ = *iter.data;
- }
- // Insert attribute values (insert key values of primary table)
- // as one attribute
- pkAttrHeader.insertHeader(dataPtr);
- dataPtr += pkAttrHeader.getHeaderSize();
- /*
- Insert fragment id before primary key as part of reference to tuple
- */
- *dataPtr++ = firedTriggerData->fragId;
- moreAttrData = keyValues.first(iter);
- while(moreAttrData) {
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- headerSize = attrHeader->getHeaderSize();
- dataSize = attrHeader->getDataSize();
- // Skip header
- if (headerSize == 1) {
- jam();
- moreAttrData = keyValues.next(iter);
- } else {
- jam();
- moreAttrData = keyValues.next(iter, headerSize - 1);
- }//if
- // Copy attribute data
- while(dataSize-- != 0) {
- *dataPtr++ = *iter.data;
- moreAttrData = keyValues.next(iter);
- }
- }
- tcKeyLength += attributesLength;
- } else {
- jam();
- // No ATTRINFO in TCKEYREQ
- TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
- }
- tcKeyReq->requestInfo = tcKeyRequestInfo;
-
- /**
- * Fix savepoint id -
- * fix so that insert has same savepoint id as triggering operation
- */
- const Uint32 currSavePointId = regApiPtr->currSavePointId;
- regApiPtr->currSavePointId = opRecord->savePointId;
- EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
- jamEntry();
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- regApiPtr->currSavePointId = currSavePointId;
- tcConnectptr.p->currentIndexId = indexData->indexId;
-
- // *********** KEYINFO ***********
- if (moreKeyData) {
- jam();
- // Send KEYINFO sequence
- KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
-
- keyInfo->connectPtr = transPtr->i;
- keyInfo->transId[0] = regApiPtr->transid[0];
- keyInfo->transId[1] = regApiPtr->transid[1];
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- // Pack any part of a key attribute that did no fit TCKEYREQ
- while((keyAttrSize != 0) && (dataPos < KeyInfo::DataLength)) {
- // If we have not read complete key
- *dataPtr++ = *iter.data;
- dataPos++;
- keyAttrSize--;
- if (dataPos == KeyInfo::DataLength) {
- jam();
- // Flush KEYINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength);
- jamEntry();
-#endif
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- }
- moreKeyData = afterValues.next(iter);
- }
-
- while(moreKeyData) {
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- headerSize = attrHeader->getHeaderSize();
- keyAttrSize = attrHeader->getDataSize();
- headAndData = headerSize + attrHeader->getDataSize();
- // Skip header
- if (headerSize == 1) {
- jam();
- moreKeyData = afterValues.next(iter);
- } else {
- jam();
- moreKeyData = afterValues.next(iter, headerSize - 1);
- }//if
- while (keyAttrSize-- != 0) {
- *dataPtr++ = *iter.data;
- dataPos++;
- if (dataPos == KeyInfo::DataLength) {
- jam();
- // Flush KEYINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength);
- jamEntry();
-#endif
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- }
- moreKeyData = afterValues.next(iter);
- }
- }
- if (dataPos != 0) {
- jam();
- // Flush last KEYINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + dataPos, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + dataPos);
- jamEntry();
-#endif
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
- }
- }
-
- // *********** ATTRINFO ***********
- if (attributesLength > attrBufSize) {
- jam();
- // No ATTRINFO in TcKeyReq
- TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
- // Send ATTRINFO sequence
- AttrInfo * const attrInfo = (AttrInfo *)signal->getDataPtrSend();
- Uint32 attrInfoPos = 0;
-
- attrInfo->connectPtr = transPtr->i;
- attrInfo->transId[0] = regApiPtr->transid[0];
- attrInfo->transId[1] = regApiPtr->transid[1];
- dataPtr = (Uint32 *) &attrInfo->attrData;
-
- bool moreAttrData;
- // Insert primary key attributes (insert after values of primary table)
- for(moreAttrData = afterValues.first(iter);
- moreAttrData;
- moreAttrData = afterValues.next(iter)) {
- *dataPtr++ = *iter.data;
- attrInfoPos++;
- if (attrInfoPos == AttrInfo::DataLength) {
- jam();
- // Flush ATTRINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + AttrInfo::DataLength);
- jamEntry();
-#endif
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- dataPtr = (Uint32 *) &attrInfo->attrData;
- attrInfoPos = 0;
- }
- }
- // Insert attribute values (insert key values of primary table)
- // as one attribute
- pkAttrHeader.insertHeader(dataPtr);
- dataPtr += pkAttrHeader.getHeaderSize();
- attrInfoPos += pkAttrHeader.getHeaderSize();
- /*
- Add fragment id before primary key
- TODO: This code really needs to be made into a long signal
- to remove this messy code.
- */
- if (attrInfoPos == AttrInfo::DataLength)
- {
- jam();
- // Flush ATTRINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + AttrInfo::DataLength);
- jamEntry();
-#endif
- dataPtr = (Uint32 *) &attrInfo->attrData;
- attrInfoPos = 0;
- }
- attrInfoPos++;
- *dataPtr++ = firedTriggerData->fragId;
-
- moreAttrData = keyValues.first(iter);
- while(moreAttrData) {
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- headerSize = attrHeader->getHeaderSize();
- dataSize = attrHeader->getDataSize();
- // Skip header
- if (headerSize == 1) {
- jam();
- moreAttrData = keyValues.next(iter);
- } else {
- jam();
- moreAttrData = keyValues.next(iter, headerSize - 1);
- }//if
- while(dataSize-- != 0) { // If we have not read complete key
- if (attrInfoPos == AttrInfo::DataLength) {
- jam();
- // Flush ATTRINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + AttrInfo::DataLength);
- jamEntry();
-#endif
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- dataPtr = (Uint32 *) &attrInfo->attrData;
- attrInfoPos = 0;
- }
- *dataPtr++ = *iter.data;
- attrInfoPos++;
- moreAttrData = keyValues.next(iter);
- }
- }
- if (attrInfoPos != 0) {
- jam();
- // Flush last ATTRINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + attrInfoPos, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + attrInfoPos);
- jamEntry();
-#endif
- }
- }
-}
-
-void Dbtc::deleteFromIndexTable(Signal* signal,
- TcFiredTriggerData* firedTriggerData,
- ApiConnectRecordPtr* transPtr,
- TcConnectRecordPtr* opPtr,
- TcIndexData* indexData,
- bool holdOperation)
-{
- ApiConnectRecord* regApiPtr = transPtr->p;
- TcConnectRecord* opRecord = opPtr->p;
- TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
- Uint32 tcKeyRequestInfo = 0;
- Uint32 tcKeyLength = 12; // Static length
- TableRecordPtr indexTabPtr;
- AttributeBuffer::DataBufferIterator iter;
- Uint32 attrId = 0;
- Uint32 keyLength = 0;
- Uint32 hops;
-
- indexTabPtr.i = indexData->indexId;
- ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
- tcKeyReq->apiConnectPtr = transPtr->i;
- tcKeyReq->senderData = opPtr->i;
- if (holdOperation) {
- jam();
- opRecord->triggerExecutionCount++;
- }//if
- // Calculate key length and renumber attribute id:s
- AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
- LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
- bool skipNull = false;
- for(bool moreKeyAttrs = beforeValues.first(iter);
- (moreKeyAttrs);
- attrId++) {
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- // Filter out NULL valued attributes
- if (attrHeader->isNULL()) {
- skipNull = true;
- break;
- }
- attrHeader->setAttributeId(attrId);
- keyLength += attrHeader->getDataSize();
- hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
- moreKeyAttrs = beforeValues.next(iter, hops);
- }
-
- if (skipNull) {
- jam();
- opRecord->triggerExecutionCount--;
- if (opRecord->triggerExecutionCount == 0) {
- /*
- We have completed current trigger execution
- Continue triggering operation
- */
- jam();
- continueTriggeringOp(signal, opRecord);
- }//if
- return;
- }//if
-
- TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
- tcKeyReq->attrLen = 0;
- tcKeyReq->tableId = indexData->indexId;
- TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
- TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
- tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
- tcKeyReq->transId1 = regApiPtr->transid[0];
- tcKeyReq->transId2 = regApiPtr->transid[1];
- Uint32 * dataPtr = &tcKeyReq->scanInfo;
- // Write first part of key in TCKEYREQ
- Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
- Uint32 dataPos = 0;
- // Filter out AttributeHeader:s since this should no be in key
- bool moreKeyData = beforeValues.first(iter);
- Uint32 headerSize = 0, keyAttrSize = 0, headAndData = 0;
-
- while (moreKeyData &&
- (dataPos < keyBufSize)) {
- /*
- If we have not read complete key
- and it fits in the signal
- */
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- headerSize = attrHeader->getHeaderSize();
- keyAttrSize = attrHeader->getDataSize();
- headAndData = headerSize + attrHeader->getDataSize();
- // Skip header
- if (headerSize == 1) {
- jam();
- moreKeyData = beforeValues.next(iter);
- } else {
- jam();
- moreKeyData = beforeValues.next(iter, headerSize - 1);
- }//if
- while((keyAttrSize != 0) &&
- (dataPos < keyBufSize)) {
- // If we have not read complete key
- jam();
- *dataPtr++ = *iter.data;
- dataPos++;
- keyAttrSize--;
- moreKeyData = beforeValues.next(iter);
- }
- if (keyAttrSize != 0) {
- jam();
- break;
- }//if
- }
-
- tcKeyLength += dataPos;
- tcKeyReq->requestInfo = tcKeyRequestInfo;
-
- /**
- * Fix savepoint id -
- * fix so that delete has same savepoint id as triggering operation
- */
- const Uint32 currSavePointId = regApiPtr->currSavePointId;
- regApiPtr->currSavePointId = opRecord->savePointId;
- EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
- jamEntry();
-
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- regApiPtr->currSavePointId = currSavePointId;
- tcConnectptr.p->currentIndexId = indexData->indexId;
-
- // *********** KEYINFO ***********
- if (moreKeyData) {
- jam();
- // Send KEYINFO sequence
- KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
-
- keyInfo->connectPtr = transPtr->i;
- keyInfo->transId[0] = regApiPtr->transid[0];
- keyInfo->transId[1] = regApiPtr->transid[1];
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- // Pack any part of a key attribute that did no fit TCKEYREQ
- while((keyAttrSize != 0) &&
- (dataPos < KeyInfo::DataLength)) {
- // If we have not read complete key
- *dataPtr++ = *iter.data;
- dataPos++;
- keyAttrSize--;
- if (dataPos == KeyInfo::DataLength) {
- jam();
- // Flush KEYINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength);
- jamEntry();
-#endif
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- }
- moreKeyData = beforeValues.next(iter);
- }
-
- while(moreKeyData) {
- jam();
- AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-
- headerSize = attrHeader->getHeaderSize();
- keyAttrSize = attrHeader->getDataSize();
- headAndData = headerSize + attrHeader->getDataSize();
- // Skip header
- if (headerSize == 1) {
- jam();
- moreKeyData = beforeValues.next(iter);
- } else {
- jam();
- moreKeyData = beforeValues.next(iter,
- headerSize - 1);
- }//if
- while (keyAttrSize-- != 0) {
- *dataPtr++ = *iter.data;
- dataPos++;
- if (dataPos == KeyInfo::DataLength) {
- jam();
- // Flush KEYINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + KeyInfo::DataLength);
- jamEntry();
-#endif
- if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
- {
- jam();
- return;
- }
-
- dataPtr = (Uint32 *) &keyInfo->keyData;
- dataPos = 0;
- }
- moreKeyData = beforeValues.next(iter);
- }
- }
- if (dataPos != 0) {
- jam();
- // Flush last KEYINFO
-#if INTERNAL_TRIGGER_TCKEYREQ_JBA
- sendSignal(reference(), GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + dataPos, JBA);
-#else
- EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + dataPos);
- jamEntry();
-#endif
- }
- }
-}
-
-Uint32
-Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
- if(!get_enabled())
- return ZNO_SUCH_TABLE;
- if(get_dropping())
- return ZDROP_TABLE_IN_PROGRESS;
- if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
- return ZWRONG_SCHEMA_VERSION_ERROR;
- ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
- __FILE__, __LINE__);
- return 0;
-}
-
-void
-Dbtc::execROUTE_ORD(Signal* signal)
-{
- jamEntry();
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
- Uint32 dstRef = ord->dstRef;
- Uint32 srcRef = ord->srcRef;
- Uint32 gsn = ord->gsn;
-
- if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
- {
- jam();
- Uint32 secCount = signal->getNoOfSections();
- SegmentedSectionPtr ptr[3];
- ndbrequire(secCount >= 1 && secCount <= 3);
-
- jamLine(secCount);
- for (Uint32 i = 0; i<secCount; i++)
- signal->getSection(ptr[i], i);
-
- /**
- * Put section 0 in signal->theData
- */
- ndbrequire(ptr[0].sz <= 25);
- copy(signal->theData, ptr[0]);
-
- signal->header.m_noOfSections = 0;
-
- /**
- * Shift rest of sections
- */
- for(Uint32 i = 1; i<secCount; i++)
- {
- signal->setSection(ptr[i], i - 1);
- }
-
- sendSignal(dstRef, gsn, signal, ptr[0].sz, JBB);
-
- signal->header.m_noOfSections = 0;
- signal->setSection(ptr[0], 0);
- releaseSections(signal);
- return ;
- }
-
- warningEvent("Unable to route GSN: %d from %x to %x",
- gsn, srcRef, dstRef);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp b/storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp
deleted file mode 100644
index 12be23851c8..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef ATTRIBUTE_OFFSET_HPP
-#define ATTRIBUTE_OFFSET_HPP
-
-class AttributeOffset {
- friend class Dbtup;
-
-private:
- static void setOffset(Uint32 & desc, Uint32 offset);
- static void setCharsetPos(Uint32 & desc, Uint32 offset);
- static void setNullFlagPos(Uint32 & desc, Uint32 offset);
-
- static Uint32 getOffset(const Uint32 &);
- static bool getCharsetFlag(const Uint32 &);
- static Uint32 getCharsetPos(const Uint32 &);
- static Uint32 getNullFlagPos(const Uint32 &);
- static Uint32 getNullFlagOffset(const Uint32 &);
- static Uint32 getNullFlagBitOffset(const Uint32 &);
-
- Uint32 m_data;
-
- friend class NdbOut& operator<<(class NdbOut&, const AttributeOffset&);
-};
-
-/**
- * Allow for 4096 attributes, all nullable, and for 128 different
- * character sets.
- *
- * a = Attribute offset - 11 bits 0-10 ( addr word in 8 kb )
- * c = Has charset flag 1 bits 11-11
- * s = Charset pointer position - 7 bits 12-18 ( in table descriptor )
- * f = Null flag offset in word - 5 bits 20-24 ( address 32 bits )
- * w = Null word offset - 7 bits 25-32 ( f+w addr 4096 attrs )
- *
- * 1111111111222222222233
- * 01234567890123456789012345678901
- * aaaaaaaaaaacsssssss fffffwwwwwww
- */
-
-#define AO_ATTRIBUTE_OFFSET_SHIFT 0
-#define AO_ATTRIBUTE_OFFSET_MASK 0x7ff
-
-#define AO_CHARSET_FLAG_SHIFT 11
-#define AO_CHARSET_POS_SHIFT 12
-#define AO_CHARSET_POS_MASK 127
-
-#define AO_NULL_FLAG_POS_MASK 0xfff // f+w
-#define AO_NULL_FLAG_POS_SHIFT 20
-
-#define AO_NULL_FLAG_WORD_MASK 31 // f
-#define AO_NULL_FLAG_OFFSET_SHIFT 5
-
-inline
-void
-AttributeOffset::setOffset(Uint32 & desc, Uint32 offset){
- ASSERT_MAX(offset, AO_ATTRIBUTE_OFFSET_MASK, "AttributeOffset::setOffset");
- desc &= ~(Uint32)(AO_ATTRIBUTE_OFFSET_MASK << AO_ATTRIBUTE_OFFSET_SHIFT);
- desc |= (offset << AO_ATTRIBUTE_OFFSET_SHIFT);
-}
-
-inline
-void
-AttributeOffset::setCharsetPos(Uint32 & desc, Uint32 offset) {
- ASSERT_MAX(offset, AO_CHARSET_POS_MASK, "AttributeOffset::setCharsetPos");
- desc |= (1 << AO_CHARSET_FLAG_SHIFT);
- desc |= (offset << AO_CHARSET_POS_SHIFT);
-}
-
-inline
-void
-AttributeOffset::setNullFlagPos(Uint32 & desc, Uint32 pos){
- ASSERT_MAX(pos, AO_NULL_FLAG_POS_MASK, "AttributeOffset::setNullFlagPos");
- desc |= (pos << AO_NULL_FLAG_POS_SHIFT);
-}
-
-inline
-Uint32
-AttributeOffset::getOffset(const Uint32 & desc)
-{
- return (desc >> AO_ATTRIBUTE_OFFSET_SHIFT) & AO_ATTRIBUTE_OFFSET_MASK;
-}
-
-inline
-bool
-AttributeOffset::getCharsetFlag(const Uint32 & desc)
-{
- return (desc >> AO_CHARSET_FLAG_SHIFT) & 1;
-}
-
-inline
-Uint32
-AttributeOffset::getCharsetPos(const Uint32 & desc)
-{
- return (desc >> AO_CHARSET_POS_SHIFT) & AO_CHARSET_POS_MASK;
-}
-
-inline
-Uint32
-AttributeOffset::getNullFlagPos(const Uint32 & desc)
-{
- return ((desc >> AO_NULL_FLAG_POS_SHIFT) & AO_NULL_FLAG_POS_MASK);
-}
-
-inline
-Uint32
-AttributeOffset::getNullFlagOffset(const Uint32 & desc)
-{
- return (getNullFlagPos(desc) >> AO_NULL_FLAG_OFFSET_SHIFT);
-}
-
-inline
-Uint32
-AttributeOffset::getNullFlagBitOffset(const Uint32 & desc)
-{
- return (getNullFlagPos(desc) & AO_NULL_FLAG_WORD_MASK);
-}
-
-class NdbOut&
-operator<<(class NdbOut&, const AttributeOffset&);
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
deleted file mode 100644
index a963fe9b708..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ /dev/null
@@ -1,3070 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBTUP_H
-#define DBTUP_H
-
-#include <pc.hpp>
-#include <SimulatedBlock.hpp>
-#include <ndb_limits.h>
-#include <trigger_definitions.h>
-#include <AttributeHeader.hpp>
-#include <Bitmask.hpp>
-#include <signaldata/TupKey.hpp>
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/DropTrig.hpp>
-#include <signaldata/TrigAttrInfo.hpp>
-#include <signaldata/BuildIndx.hpp>
-#include "Undo_buffer.hpp"
-#include "tuppage.hpp"
-#include <../pgman.hpp>
-#include <../tsman.hpp>
-
-// jams
-#undef jam
-#undef jamEntry
-#ifdef DBTUP_BUFFER_CPP
-#define jam() jamLine(10000 + __LINE__)
-#define jamEntry() jamEntryLine(10000 + __LINE__)
-#endif
-#ifdef DBTUP_ROUTINES_CPP
-#define jam() jamLine(15000 + __LINE__)
-#define jamEntry() jamEntryLine(15000 + __LINE__)
-#endif
-#ifdef DBTUP_COMMIT_CPP
-#define jam() jamLine(20000 + __LINE__)
-#define jamEntry() jamEntryLine(20000 + __LINE__)
-#endif
-#ifdef DBTUP_FIXALLOC_CPP
-#define jam() jamLine(25000 + __LINE__)
-#define jamEntry() jamEntryLine(25000 + __LINE__)
-#endif
-#ifdef DBTUP_TRIGGER_CPP
-#define jam() jamLine(30000 + __LINE__)
-#define jamEntry() jamEntryLine(30000 + __LINE__)
-#endif
-#ifdef DBTUP_ABORT_CPP
-#define jam() jamLine(35000 + __LINE__)
-#define jamEntry() jamEntryLine(35000 + __LINE__)
-#endif
-#ifdef DBTUP_PAGE_MAP_CPP
-#define jam() jamLine(40000 + __LINE__)
-#define jamEntry() jamEntryLine(40000 + __LINE__)
-#endif
-#ifdef DBTUP_PAG_MAN_CPP
-#define jam() jamLine(45000 + __LINE__)
-#define jamEntry() jamEntryLine(45000 + __LINE__)
-#endif
-#ifdef DBTUP_STORE_PROC_DEF_CPP
-#define jam() jamLine(50000 + __LINE__)
-#define jamEntry() jamEntryLine(50000 + __LINE__)
-#endif
-#ifdef DBTUP_META_CPP
-#define jam() jamLine(55000 + __LINE__)
-#define jamEntry() jamEntryLine(55000 + __LINE__)
-#endif
-#ifdef DBTUP_TAB_DES_MAN_CPP
-#define jam() jamLine(60000 + __LINE__)
-#define jamEntry() jamEntryLine(60000 + __LINE__)
-#endif
-#ifdef DBTUP_GEN_CPP
-#define jam() jamLine(65000 + __LINE__)
-#define jamEntry() jamEntryLine(65000 + __LINE__)
-#endif
-#ifdef DBTUP_INDEX_CPP
-#define jam() jamLine(70000 + __LINE__)
-#define jamEntry() jamEntryLine(70000 + __LINE__)
-#endif
-#ifdef DBTUP_DEBUG_CPP
-#define jam() jamLine(75000 + __LINE__)
-#define jamEntry() jamEntryLine(75000 + __LINE__)
-#endif
-#ifdef DBTUP_VAR_ALLOC_CPP
-#define jam() jamLine(80000 + __LINE__)
-#define jamEntry() jamEntryLine(80000 + __LINE__)
-#endif
-#ifdef DBTUP_SCAN_CPP
-#define jam() jamLine(85000 + __LINE__)
-#define jamEntry() jamEntryLine(85000 + __LINE__)
-#endif
-#ifdef DBTUP_DISK_ALLOC_CPP
-#define jam() jamLine(90000 + __LINE__)
-#define jamEntry() jamEntryLine(90000 + __LINE__)
-#endif
-#ifndef jam
-#define jam() jamLine(__LINE__)
-#define jamEntry() jamEntryLine(__LINE__)
-#endif
-
-#ifdef VM_TRACE
-inline const char* dbgmask(const Bitmask<MAXNROFATTRIBUTESINWORDS>& bm) {
- static int i=0; static char buf[5][200];
- bm.getText(buf[i%5]); return buf[i++%5]; }
-inline const char* dbgmask(const Uint32 bm[2]) {
- static int i=0; static char buf[5][200];
- sprintf(buf[i%5],"%08x%08x",bm[1],bm[0]); return buf[i++%5]; }
-#endif
-
-#define ZWORDS_ON_PAGE 8192 /* NUMBER OF WORDS ON A PAGE. */
-#define ZATTRBUF_SIZE 32 /* SIZE OF ATTRIBUTE RECORD BUFFER */
-#define ZMIN_PAGE_LIMIT_TUPKEYREQ 5
-#define ZTUP_VERSION_BITS 15
-#define ZTUP_VERSION_MASK ((1 << ZTUP_VERSION_BITS) - 1)
-#define MAX_FREE_LIST 4
-
-inline Uint32* ALIGN_WORD(void * ptr)
-{
- return (Uint32*)(((UintPtr(ptr) + 3) >> 2) << 2);
-}
-
-inline const Uint32* ALIGN_WORD(const void* ptr)
-{
- return (Uint32*)(((UintPtr(ptr) + 3) >> 2) << 2);
-}
-
-#ifdef DBTUP_C
-//------------------------------------------------------------------
-// Jam Handling:
-//
-// When DBTUP reports lines through jam in the trace files it has to
-// be interpreted. 4024 means as an example line 24 in DbtupCommit.cpp
-// Thus 4000 is added to the line number beacuse it is located in the
-// file DbtupCommit.cpp. The following is the exhaustive list of the
-// added value in the various files. ndbrequire, ptrCheckGuard still
-// only reports the line number in the file it currently is located in.
-//
-// DbtupExecQuery.cpp 0
-// DbtupBuffer.cpp 10000
-// DbtupRoutines.cpp 15000
-// DbtupCommit.cpp 20000
-// DbtupFixAlloc.cpp 25000
-// DbtupTrigger.cpp 30000
-// DbtupAbort.cpp 35000
-// DbtupPageMap.cpp 40000
-// DbtupPagMan.cpp 45000
-// DbtupStoredProcDef.cpp 50000
-// DbtupMeta.cpp 55000
-// DbtupTabDesMan.cpp 60000
-// DbtupGen.cpp 65000
-// DbtupIndex.cpp 70000
-// DbtupDebug.cpp 75000
-// DbtupVarAlloc.cpp 80000
-// DbtupScan.cpp 85000
-// DbtupDiskAlloc.cpp 90000
-//------------------------------------------------------------------
-
-/*
-2.2 LOCAL SYMBOLS
------------------
-*/
-/* ---------------------------------------------------------------- */
-/* S I Z E O F R E C O R D S */
-/* ---------------------------------------------------------------- */
-#define ZNO_OF_ATTRBUFREC 10000 /* SIZE OF ATTRIBUTE INFO FILE */
-#define ZNO_OF_CONCURRENT_OPEN_OP 40 /* NUMBER OF CONCURRENT OPENS */
-#define ZNO_OF_CONCURRENT_WRITE_OP 80 /* NUMBER OF CONCURRENT DISK WRITES*/
-#define ZNO_OF_FRAGOPREC 20 /* NUMBER OF CONCURRENT ADD FRAG. */
-#define TOT_PAGE_RECORD_SPACE 262144 /* SIZE OF PAGE RECORD FILE. */
-#define ZNO_OF_PAGE TOT_PAGE_RECORD_SPACE/ZWORDS_ON_PAGE
-#define ZNO_OF_PAGE_RANGE_REC 128 /* SIZE OF PAGE RANGE FILE */
-// Trigger constants
-#define ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE 16
-
-/* ---------------------------------------------------------------- */
-/* A ATTRIBUTE MAY BE NULL, DYNAMIC OR NORMAL. A NORMAL ATTRIBUTE */
-/* IS A ATTRIBUTE THAT IS NOT NULL OR DYNAMIC. A NULL ATTRIBUTE */
-/* MAY HAVE NO VALUE. A DYNAMIC ATTRIBUTE IS A NULL ATTRIBUTE THAT */
-/* DOES NOT HAVE TO BE A MEMBER OF EVERY TUPLE I A CERTAIN TABLE. */
-/* ---------------------------------------------------------------- */
-/**
- * #defines moved into include/kernel/Interpreter.hpp
- */
-#define ZINSERT_DELETE 0
-#define ZUPDATE_ALL 8
-/* ---------------------------------------------------------------- */
-/* THE MINIMUM SIZE OF AN 'EMPTY' TUPLE HEADER IN R-WORDS */
-/* ---------------------------------------------------------------- */
- /* THE TUPLE HEADER FIELD 'SIZE OF NULL ATTR. FIELD' SPECIFYES */
- /* THE SIZE OF THE TUPLE HEADER FIELD 'NULL ATTR. FIELD'. */
- /* THE TUPLE HEADER FIELD 'TYPE' SPECIFYES THE TYPE OF THE TUPLE */
- /* HEADER. */
- /* TUPLE ATTRIBUTE INDEX CLUSTERS, ATTRIBUTE */
- /* CLUSTERS AND A DYNAMIC ATTRIBUTE HEADER. */
- /* IT MAY ALSO CONTAIN SHORT ATTRIBUTES AND */
- /* POINTERS TO LONG ATTRIBUTE HEADERS. */
- /* TUPLE ATTRIBUTE INDEX CLUSTERS, ATTRIBUTE */
- /* CLUSTERS AND A DYNAMIC ATTRIBUTE HEADER. */
-
- /* DATA STRUCTURE TYPES */
- /* WHEN ATTRIBUTE INFO IS SENT WITH A ATTRINFO-SIGNAL THE */
- /* VARIABLE TYPE IS SPECIFYED. THIS MUST BE DONE TO BE ABLE TO */
- /* NOW HOW MUCH DATA OF A ATTRIBUTE TO READ FROM ATTRINFO. */
-
- /* WHEN A REQUEST CAN NOT BE EXECUTED BECAUSE OF A ERROR THE */
- /* ERROR MUST BE IDENTIFYED BY MEANS OF A ERROR CODE AND SENT TO */
- /* THE REQUESTER. */
-#define ZGET_OPREC_ERROR 804 // TUP_SEIZEREF
-
-#define ZEXIST_FRAG_ERROR 816 // Add fragment
-#define ZFULL_FRAGRECORD_ERROR 817 // Add fragment
-#define ZNO_FREE_PAGE_RANGE_ERROR 818 // Add fragment
-#define ZNOFREE_FRAGOP_ERROR 830 // Add fragment
-#define ZTOO_LARGE_TUPLE_ERROR 851 // Add fragment
-#define ZNO_FREE_TAB_ENTRY_ERROR 852 // Add fragment
-#define ZNO_PAGES_ALLOCATED_ERROR 881 // Add fragment
-
-#define ZGET_REALPID_ERROR 809
-#define ZNOT_IMPLEMENTED_ERROR 812
-#define ZSEIZE_ATTRINBUFREC_ERROR 805
-#define ZTOO_MUCH_ATTRINFO_ERROR 823
-#define ZMEM_NOTABDESCR_ERROR 826
-#define ZMEM_NOMEM_ERROR 827
-#define ZAI_INCONSISTENCY_ERROR 829
-#define ZNO_ILLEGAL_NULL_ATTR 839
-#define ZNOT_NULL_ATTR 840
-#define ZNO_INSTRUCTION_ERROR 871
-#define ZOUTSIDE_OF_PROGRAM_ERROR 876
-#define ZSTORED_PROC_ID_ERROR 877
-#define ZREGISTER_INIT_ERROR 878
-#define ZATTRIBUTE_ID_ERROR 879
-#define ZTRY_TO_READ_TOO_MUCH_ERROR 880
-#define ZTOTAL_LEN_ERROR 882
-#define ZATTR_INTERPRETER_ERROR 883
-#define ZSTACK_OVERFLOW_ERROR 884
-#define ZSTACK_UNDERFLOW_ERROR 885
-#define ZTOO_MANY_INSTRUCTIONS_ERROR 886
-#define ZTRY_TO_UPDATE_ERROR 888
-#define ZCALL_ERROR 890
-#define ZTEMPORARY_RESOURCE_FAILURE 891
-#define ZUNSUPPORTED_BRANCH 892
-
-#define ZSTORED_SEIZE_ATTRINBUFREC_ERROR 873 // Part of Scan
-#define ZSTORED_TOO_MUCH_ATTRINFO_ERROR 874
-
-#define ZREAD_ONLY_CONSTRAINT_VIOLATION 893
-#define ZVAR_SIZED_NOT_SUPPORTED 894
-#define ZINCONSISTENT_NULL_ATTRIBUTE_COUNT 895
-#define ZTUPLE_CORRUPTED_ERROR 896
-#define ZTRY_UPDATE_PRIMARY_KEY 897
-#define ZMUST_BE_ABORTED_ERROR 898
-#define ZTUPLE_DELETED_ERROR 626
-#define ZINSERT_ERROR 630
-
-#define ZINVALID_CHAR_FORMAT 744
-#define ZROWID_ALLOCATED 899
-
- /* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */
-
-#define ZFREE_COMMON 1 /* PAGE STATE, PAGE IN COMMON AREA */
-#define ZEMPTY_MM 2 /* PAGE STATE, PAGE IN EMPTY LIST */
-#define ZTH_MM_FREE 3 /* PAGE STATE, TUPLE HEADER PAGE WITH FREE AREA */
-#define ZTH_MM_FULL 4 /* PAGE STATE, TUPLE HEADER PAGE WHICH IS FULL */
-
-#define ZTD_HEADER 0 /* HEADER POSITION */
-#define ZTD_DATASIZE 1 /* SIZE OF THE DATA IN THIS CHUNK */
-#define ZTD_SIZE 2 /* TOTAL SIZE OF TABLE DESCRIPTOR */
-
- /* TRAILER POSITIONS FROM END OF TABLE DESCRIPTOR RECORD */
-#define ZTD_TR_SIZE 1 /* SIZE DESCRIPTOR POS FROM END+1 */
-#define ZTD_TR_TYPE 2
-#define ZTD_TRAILER_SIZE 2 /* TOTAL SIZE OF TABLE TRAILER */
-#define ZAD_SIZE 2 /* TOTAL SIZE OF ATTR DESCRIPTOR */
-#define ZAD_LOG_SIZE 1 /* TWO LOG OF TOTAL SIZE OF ATTR DESCRIPTOR */
-
- /* CONSTANTS USED TO HANDLE TABLE DESCRIPTOR AS A FREELIST */
-#define ZTD_FL_HEADER 0 /* HEADER POSITION */
-#define ZTD_FL_SIZE 1 /* TOTAL SIZE OF THIS FREELIST ENTRY */
-#define ZTD_FL_PREV 2 /* PREVIOUS RECORD IN FREELIST */
-#define ZTD_FL_NEXT 3 /* NEXT RECORD IN FREELIST */
-#define ZTD_FREE_SIZE 16 /* SIZE NEEDED TO HOLD ONE FL ENTRY */
-
- /* CONSTANTS USED IN LSB OF TABLE DESCRIPTOR HEADER DESCRIBING USAGE */
-#define ZTD_TYPE_FREE 0 /* RECORD LINKED INTO FREELIST */
-#define ZTD_TYPE_NORMAL 1 /* RECORD USED AS TABLE DESCRIPTOR */
- /* ATTRIBUTE OPERATION CONSTANTS */
-#define ZLEAF 1
-#define ZNON_LEAF 2
-
- /* ATTRINBUFREC VARIABLE POSITIONS. */
-#define ZBUF_PREV 29 /* POSITION OF 'PREV'-VARIABLE (USED BY INTERPRETED EXEC) */
-#define ZBUF_DATA_LEN 30 /* POSITION OF 'DATA LENGTH'-VARIABLE. */
-#define ZBUF_NEXT 31 /* POSITION OF 'NEXT'-VARIABLE. */
-#define ZSAVE_BUF_NEXT 28
-#define ZSAVE_BUF_DATA_LEN 27
-
- /* RETURN POINTS. */
- /* RESTART PHASES */
-#define ZSTARTPHASE1 1
-#define ZSTARTPHASE2 2
-#define ZSTARTPHASE3 3
-#define ZSTARTPHASE4 4
-#define ZSTARTPHASE6 6
-
-#define ZADDFRAG 0
-
-//------------------------------------------------------------
-// TUP_CONTINUEB codes
-//------------------------------------------------------------
-#define ZINITIALISE_RECORDS 6
-#define ZREL_FRAG 7
-#define ZREPORT_MEMORY_USAGE 8
-#define ZBUILD_INDEX 9
-#define ZTUP_SCAN 10
-#define ZFREE_EXTENT 11
-#define ZUNMAP_PAGES 12
-#define ZFREE_VAR_PAGES 13
-
-#define ZSCAN_PROCEDURE 0
-#define ZCOPY_PROCEDURE 2
-#define ZSTORED_PROCEDURE_DELETE 3
-#define ZSTORED_PROCEDURE_FREE 0xffff
-#define ZMIN_PAGE_LIMIT_TUP_COMMITREQ 2
-
-#define ZSKIP_TUX_TRIGGERS 0x1 // flag for TUP_ABORTREQ
-
-#endif
-
-class Dbtup: public SimulatedBlock {
-friend class Suma;
-public:
-struct KeyReqStruct;
-friend struct KeyReqStruct; // CC
-typedef bool (Dbtup::* ReadFunction)(Uint32*,
- KeyReqStruct*,
- AttributeHeader*,
- Uint32);
-typedef bool (Dbtup::* UpdateFunction)(Uint32*,
- KeyReqStruct*,
- Uint32);
-private:
-
- typedef Tup_fixsize_page Fix_page;
- typedef Tup_varsize_page Var_page;
-
-public:
- class Dblqh *c_lqh;
- Tsman* c_tsman;
- Lgman* c_lgman;
- Page_cache_client m_pgman;
-
-// State values
-enum ChangeMaskState {
- DELETE_CHANGES = 0,
- SET_ALL_MASK = 1,
- USE_SAVED_CHANGE_MASK = 2,
- RECALCULATE_CHANGE_MASK = 3
-};
-
-enum TransState {
- TRANS_IDLE = 0,
- TRANS_STARTED = 1,
- TRANS_WAIT_STORED_PROCEDURE_ATTR_INFO = 2,
- TRANS_ERROR_WAIT_STORED_PROCREQ = 3,
- TRANS_ERROR_WAIT_TUPKEYREQ = 4,
- TRANS_TOO_MUCH_AI = 5,
- TRANS_DISCONNECTED = 6
-};
-
-enum TupleState {
- TUPLE_PREPARED = 1,
- TUPLE_ALREADY_ABORTED = 2,
- TUPLE_TO_BE_COMMITTED = 3
-};
-
-enum State {
- NOT_INITIALIZED = 0,
- IDLE = 17,
- ACTIVE = 18,
- SYSTEM_RESTART = 19,
- DEFINED = 34,
- NOT_DEFINED = 37,
- NORMAL_PAGE = 40,
- DEFINING = 65,
- DROPPING = 68
-};
-
-// Records
-/* ************** ATTRIBUTE INFO BUFFER RECORD ****************** */
-/* THIS RECORD IS USED AS A BUFFER FOR INCOMING AND OUTGOING DATA */
-/* ************************************************************** */
-struct Attrbufrec {
- Uint32 attrbuf[ZATTRBUF_SIZE];
-}; /* p2c: size = 128 bytes */
-
-typedef Ptr<Attrbufrec> AttrbufrecPtr;
-
-
-
-struct Fragoperrec {
- Uint64 minRows;
- Uint64 maxRows;
- Uint32 nextFragoprec;
- Uint32 lqhPtrFrag;
- Uint32 fragidFrag;
- Uint32 tableidFrag;
- Uint32 fragPointer;
- Uint32 attributeCount;
- Uint32 charsetIndex;
- Uint32 m_null_bits[2];
- Uint32 m_fix_attributes_size[2]; // In words
- Uint32 m_var_attributes_size[2]; // In bytes
- BlockReference lqhBlockrefFrag;
- bool inUse;
- bool definingFragment;
-};
-typedef Ptr<Fragoperrec> FragoperrecPtr;
-
-
- typedef Tup_page Page;
- typedef Ptr<Page> PagePtr;
-
- // Scan position
- struct ScanPos {
- enum Get {
- Get_undef = 0,
- Get_next_page,
- Get_page,
- Get_next_page_mm,
- Get_page_mm,
- Get_next_page_dd,
- Get_page_dd,
- Get_next_tuple,
- Get_tuple,
- Get_next_tuple_fs,
- Get_tuple_fs
- };
- Get m_get; // entry point in scanNext
- Local_key m_key; // scan position pointer MM or DD
- Page* m_page; // scanned MM or DD (cache) page
- Local_key m_key_mm; // MM local key returned
- Uint32 m_realpid_mm; // MM real page id
- Uint32 m_extent_info_ptr_i;
- };
-
- // Scan Lock
- struct ScanLock {
- Uint32 m_accLockOp;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- typedef Ptr<ScanLock> ScanLockPtr;
- ArrayPool<ScanLock> c_scanLockPool;
-
- // Tup scan, similar to Tux scan. Later some of this could
- // be moved to common superclass.
- struct ScanOp {
- ScanOp() :
- m_state(Undef),
- m_bits(0),
- m_userPtr(RNIL),
- m_userRef(RNIL),
- m_tableId(RNIL),
- m_fragId(~(Uint32)0),
- m_fragPtrI(RNIL),
- m_transId1(0),
- m_transId2(0),
- m_savePointId(0),
- m_accLockOp(RNIL)
- {}
-
- enum State {
- Undef = 0,
- First = 1, // before first entry
- Current = 2, // at current before locking
- Blocked = 3, // at current waiting for ACC lock
- Locked = 4, // at current and locked or no lock needed
- Next = 5, // looking for next extry
- Last = 6, // after last entry
- Aborting = 7, // lock wait at scan close
- Invalid = 9 // cannot return REF to LQH currently
- };
- Uint16 m_state;
-
- enum Bits {
- SCAN_DD = 0x01, // scan disk pages
- SCAN_VS = 0x02, // page format is var size
- SCAN_LCP = 0x04, // LCP mem page scan
- SCAN_LOCK_SH = 0x10, // lock mode shared
- SCAN_LOCK_EX = 0x20, // lock mode exclusive
- SCAN_LOCK_WAIT = 0x40, // lock wait
- // any lock mode
- SCAN_LOCK = SCAN_LOCK_SH | SCAN_LOCK_EX,
- SCAN_NR = 0x80 // Node recovery scan
- };
- Uint16 m_bits;
-
- Uint32 m_userPtr; // scanptr.i in LQH
- Uint32 m_userRef;
- Uint32 m_tableId;
- Uint32 m_fragId;
- Uint32 m_fragPtrI;
- Uint32 m_transId1;
- Uint32 m_transId2;
- union {
- Uint32 m_savePointId;
- Uint32 m_scanGCI;
- };
- Uint32 m_endPage;
- // lock waited for or obtained and not yet passed to LQH
- Uint32 m_accLockOp;
-
- ScanPos m_scanPos;
-
- DLFifoList<ScanLock>::Head m_accLockOps;
-
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- typedef Ptr<ScanOp> ScanOpPtr;
- ArrayPool<ScanOp> c_scanOpPool;
-
- void scanReply(Signal*, ScanOpPtr scanPtr);
- void scanFirst(Signal*, ScanOpPtr scanPtr);
- bool scanNext(Signal*, ScanOpPtr scanPtr);
- void scanCont(Signal*, ScanOpPtr scanPtr);
- void disk_page_tup_scan_callback(Signal*, Uint32 scanPtrI, Uint32 page_i);
- void scanClose(Signal*, ScanOpPtr scanPtr);
- void addAccLockOp(ScanOp& scan, Uint32 accLockOp);
- void removeAccLockOp(ScanOp& scan, Uint32 accLockOp);
- void releaseScanOp(ScanOpPtr& scanPtr);
-
- // for md5 of key (could maybe reuse existing temp buffer)
- Uint64 c_dataBuffer[ZWORDS_ON_PAGE/2 + 1];
-
- struct Page_request
- {
- Local_key m_key;
- Uint32 m_frag_ptr_i;
- Uint32 m_extent_info_ptr;
- Uint16 m_estimated_free_space; // in bytes/records
- Uint16 m_list_index; // in Disk_alloc_info.m_page_requests
- Uint16 m_ref_count; // Waiters for page
- Uint16 m_uncommitted_used_space;
- Uint32 nextList;
- Uint32 prevList;
- Uint32 m_magic;
- }; // 32 bytes
-
- typedef RecordPool<Page_request, WOPool> Page_request_pool;
- typedef DLFifoListImpl<Page_request_pool, Page_request> Page_request_list;
- typedef LocalDLFifoListImpl<Page_request_pool, Page_request> Local_page_request_list;
-
- STATIC_CONST( EXTENT_SEARCH_MATRIX_COLS = 4 ); // Guarantee size
- STATIC_CONST( EXTENT_SEARCH_MATRIX_ROWS = 5 ); // Total size
- STATIC_CONST( EXTENT_SEARCH_MATRIX_SIZE = 20 );
-
- struct Extent_list_t
- {
- Uint32 nextList;
- };
-
- struct Extent_info : public Extent_list_t
- {
- Uint32 m_magic;
- Uint32 m_first_page_no;
- Local_key m_key;
- Uint32 m_free_space;
- Uint32 m_free_matrix_pos;
- Uint16 m_free_page_count[EXTENT_SEARCH_MATRIX_COLS];
- union {
- Uint32 nextList;
- Uint32 nextPool;
- };
- Uint32 prevList;
- Uint32 nextHash, prevHash;
-
- Uint32 hashValue() const {
- return (m_key.m_file_no << 16) ^ m_key.m_page_idx;
- }
-
- Extent_info() {}
- bool equal(const Extent_info & rec) const {
- return m_key.m_file_no == rec.m_key.m_file_no &&
- m_key.m_page_idx == rec.m_key.m_page_idx;
- }
- }; // 40 bytes
-
- typedef RecordPool<Extent_info, RWPool> Extent_info_pool;
- typedef DLListImpl<Extent_info_pool, Extent_info> Extent_info_list;
- typedef LocalDLListImpl<Extent_info_pool, Extent_info> Local_extent_info_list;
- typedef DLHashTableImpl<Extent_info_pool, Extent_info> Extent_info_hash;
- typedef SLListImpl<Extent_info_pool, Extent_info, Extent_list_t> Fragment_extent_list;
- typedef LocalSLListImpl<Extent_info_pool, Extent_info, Extent_list_t> Local_fragment_extent_list;
- struct Tablerec;
- struct Disk_alloc_info
- {
- Disk_alloc_info() {}
- Disk_alloc_info(const Tablerec* tabPtrP,
- Uint32 extent_size_in_pages);
- Uint32 m_extent_size;
-
- /**
- * Disk allocation
- *
- * 1) Allocate space on pages that already are dirty
- * (4 free lists for different requests)
- * 2) Allocate space on pages waiting to maped that will be dirty
- * (4 free lists for different requests)
- * 3) Check if "current" extent can accommodate request
- * If so, allocate page from there
- * Else put "current" into free matrix
- * 4) Search free matrix for extent with greatest amount of free space
- * while still accommodating current request
- * (20 free lists for different requests)
- */
-
- /**
- * Free list of pages in different size
- * that are dirty
- */
- DLList<Page>::Head m_dirty_pages[MAX_FREE_LIST]; // In real page id's
-
- /**
- * Requests (for update) that have sufficient space left after request
- * these are currently being "mapped"
- */
- Page_request_list::Head m_page_requests[MAX_FREE_LIST];
-
- DLList<Page>::Head m_unmap_pages;
-
- /**
- * Current extent
- */
- Uint32 m_curr_extent_info_ptr_i;
-
- /**
- *
- */
- STATIC_CONST( SZ = EXTENT_SEARCH_MATRIX_SIZE );
- Extent_info_list::Head m_free_extents[SZ];
- Uint32 m_total_extent_free_space_thresholds[EXTENT_SEARCH_MATRIX_ROWS];
- Uint32 m_page_free_bits_map[EXTENT_SEARCH_MATRIX_COLS];
-
- Uint32 find_extent(Uint32 sz) const;
- Uint32 calc_extent_pos(const Extent_info*) const;
-
- /**
- * Compute minimum free space on page given bits
- */
- Uint32 calc_page_free_space(Uint32 bits) const {
- return m_page_free_bits_map[bits];
- }
-
- /**
- * Compute page free bits, given free space
- */
- Uint32 calc_page_free_bits(Uint32 free) const {
- for(Uint32 i = 0; i<EXTENT_SEARCH_MATRIX_COLS-1; i++)
- if(free >= m_page_free_bits_map[i])
- return i;
- return EXTENT_SEARCH_MATRIX_COLS - 1;
- }
-
- Fragment_extent_list::Head m_extent_list;
- };
-
- void dump_disk_alloc(Disk_alloc_info&);
-
-struct Fragrecord {
- Uint32 nextStartRange;
- Uint32 currentPageRange;
- Uint32 rootPageRange;
- Uint32 noOfPages;
- Uint32 noOfVarPages;
- Uint32 noOfPagesToGrow;
-
- DLList<Page>::Head emptyPrimPage; // allocated pages (not init)
- DLFifoList<Page>::Head thFreeFirst; // pages with atleast 1 free record
- SLList<Page>::Head m_empty_pages; // Empty pages not in logical/physical map
-
- Uint32 m_lcp_scan_op;
- Uint32 m_lcp_keep_list;
-
- State fragStatus;
- Uint32 fragTableId;
- Uint32 fragmentId;
- Uint32 nextfreefrag;
- DLList<Page>::Head free_var_page_array[MAX_FREE_LIST];
-
- DLList<ScanOp>::Head m_scanList;
-
- enum { UC_LCP = 1, UC_CREATE = 2, UC_SET_LCP = 3 };
- Uint32 m_restore_lcp_id;
- Uint32 m_undo_complete;
- Uint32 m_tablespace_id;
- Uint32 m_logfile_group_id;
- Disk_alloc_info m_disk_alloc_info;
- Uint32 m_var_page_chunks;
-};
-typedef Ptr<Fragrecord> FragrecordPtr;
-
-
-struct Operationrec {
- /*
- * To handle Attrinfo signals and buffer them up we need to
- * a simple list with first and last and we also need to keep track
- * of how much we received for security check.
- * Will most likely disappear with introduction of long signals.
- * These variables are used before TUPKEYREQ is received and not
- * thereafter and is disposed with after calling copyAttrinfo
- * which is called before putting the operation into its lists.
- * Thus we can use union declarations for these variables.
- */
-
- /*
- * Used by scans to find the Attrinfo buffers.
- * This is only until returning from copyAttrinfo and
- * can thus reuse the same memory as needed by the
- * active operation list variables.
- */
-
- /*
- * Doubly linked list with anchor on tuple.
- * This is to handle multiple updates on the same tuple
- * by the same transaction.
- */
- union {
- Uint32 prevActiveOp;
- Uint32 storedProcedureId; //Used until copyAttrinfo
- };
- union {
- Uint32 nextActiveOp;
- Uint32 currentAttrinbufLen; //Used until copyAttrinfo
- };
-
- Operationrec() {}
- bool is_first_operation() const { return prevActiveOp == RNIL;}
- bool is_last_operation() const { return nextActiveOp == RNIL;}
-
- Uint32 m_undo_buffer_space; // In words
- union {
- Uint32 firstAttrinbufrec; //Used until copyAttrinfo
- };
- Uint32 m_any_value;
- union {
- Uint32 lastAttrinbufrec; //Used until copyAttrinfo
- Uint32 nextPool;
- };
- Uint32 attrinbufLen; //only used during STORED_PROCDEF phase
- Uint32 storedProcPtr; //only used during STORED_PROCDEF phase
-
- /*
- * From fragment i-value we can find fragment and table record
- */
- Uint32 fragmentPtr;
-
- /*
- * We need references to both the original tuple and the copy tuple.
- * We keep the page's real i-value and its index and from there we
- * can find out about the fragment page id and the page offset.
- */
- Local_key m_tuple_location;
- Local_key m_copy_tuple_location;
-
- /*
- * We keep the record linked to the operation record in LQH.
- * This is needed due to writing of REDO log must be performed
- * in correct order, which is the same order as the writes
- * occurred. LQH can receive the records in different order.
- */
- Uint32 userpointer;
-
- /*
- * When responding to queries in the same transaction they will see
- * a result from the save point id the query was started. Again
- * functionality for multi-updates of the same record in one
- * transaction.
- */
- union {
- Uint32 savepointId;
- Uint32 m_commit_disk_callback_page;
- };
-
- /*
- * We use 64 bits to save change mask for the most common cases.
- */
- Uint32 saved_change_mask[2];
-
- /*
- * State variables on connection.
- * State variable on tuple after multi-updates
- * Is operation undo logged or not
- * Is operation in fragment list
- * Is operation in multi-update list
- * Operation type (READ, UPDATE, etc)
- * Is record primary replica
- * Is delete or insert performed
- */
- struct OpBitFields {
- unsigned int trans_state : 3;
- unsigned int tuple_state : 2;
- unsigned int in_active_list : 1;
-
- unsigned int op_type : 3;
- unsigned int delete_insert_flag : 1;
- unsigned int primary_replica : 1;
- unsigned int change_mask_state : 2;
- unsigned int m_disk_preallocated : 1;
- unsigned int m_load_diskpage_on_commit : 1;
- unsigned int m_wait_log_buffer : 1;
- };
- union {
- OpBitFields op_struct;
- Uint16 op_bit_fields;
- };
-
- /*
- * TUX needs to know the tuple version of the tuple since it
- * keeps an entry for both the committed and all versions in
- * a transaction currently. So each update will create a new
- * version even if in the same transaction.
- */
- Uint16 tupVersion;
-};
-typedef Ptr<Operationrec> OperationrecPtr;
-
- /* ****************************** PAGE RANGE RECORD ************************** */
- /* PAGE RANGES AND BASE PAGE ID. EACH RANGE HAS A CORRESPONDING BASE PAGE ID */
- /* THAT IS USED TO CALCULATE REAL PAGE ID FROM A FRAGMENT PAGE ID AND A TABLE */
- /* REFERENCE. */
- /* THE PAGE RANGES ARE ORGANISED IN A B-TREE FASHION WHERE THE VARIABLE TYPE */
- /* SPECIFIES IF A LEAF NODE HAS BEEN REACHED. IF A LEAF NODE HAS BEEN REACHED */
- /* THEN BASE_PAGE_ID IS THE BASE_PAGE_ID OF THE SET OF PAGES THAT WAS */
- /* ALLOCATED IN THAT RANGE. OTHERWISE BASE_PAGE_ID IS THE POINTER TO THE NEXT */
- /* PAGE_RANGE RECORD. */
- /* *************************************************************************** */
-struct PageRange {
- Uint32 startRange[4]; /* START OF RANGE */
- Uint32 endRange[4]; /* END OF THIS RANGE */
- Uint32 basePageId[4]; /* BASE PAGE ID. */
-/*---- VARIABLE BASE_PAGE_ID2 (4) 8 DS NEEDED WHEN SUPPORTING 40 BIT PAGE ID -------*/
- Uint8 type[4]; /* TYPE OF BASE PAGE ID */
- Uint32 nextFree; /* NEXT FREE PAGE RANGE RECORD */
- Uint32 parentPtr; /* THE PARENT TO THE PAGE RANGE REC IN THE B-TREE */
- Uint8 currentIndexPos;
-};
-typedef Ptr<PageRange> PageRangePtr;
-
-
- /* ************* TRIGGER DATA ************* */
- /* THIS RECORD FORMS LISTS OF ACTIVE */
- /* TRIGGERS FOR EACH TABLE. */
- /* THE RECORDS ARE MANAGED BY A TRIGGER */
- /* POOL wHERE A TRIGGER RECORD IS SEIZED */
- /* WHEN A TRIGGER IS ACTIVATED AND RELEASED */
- /* WHEN THE TRIGGER IS DEACTIVATED. */
- /* **************************************** */
-struct TupTriggerData {
- TupTriggerData() {}
-
- /**
- * Trigger id, used by DICT/TRIX to identify the trigger
- *
- * trigger Ids are unique per block for SUBSCRIPTION triggers.
- * This is so that BACKUP can use TUP triggers directly and delete them
- * properly.
- */
- Uint32 triggerId;
-
- /**
- * Index id is needed for ordered index.
- */
- Uint32 indexId;
-
- /**
- * Trigger type etc, defines what the trigger is used for
- */
- TriggerType::Value triggerType;
- TriggerActionTime::Value triggerActionTime;
- TriggerEvent::Value triggerEvent;
- /**
- * Receiver block
- */
- Uint32 m_receiverBlock;
-
- /**
- * Monitor all replicas, i.e. trigger will fire on all nodes where tuples
- * are stored
- */
- bool monitorReplicas;
-
- /**
- * Monitor all attributes, the trigger monitors all changes to attributes
- * in the table
- */
- bool monitorAllAttributes;
-
- /**
- * Send only changed attributes at trigger firing time.
- */
- bool sendOnlyChangedAttributes;
-
- /**
- * Send also before values at trigger firing time.
- */
- bool sendBeforeValues;
-
- /**
- * Attribute mask, defines what attributes are to be monitored
- * Can be seen as a compact representation of SQL column name list
- */
- Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
-
- /**
- * Next ptr (used in pool/list)
- */
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
-
- /**
- * Prev pointer (used in list)
- */
- Uint32 prevList;
-
- inline void print(NdbOut & s) const { s << "[TriggerData = " << triggerId << "]"; };
-};
-
-typedef Ptr<TupTriggerData> TriggerPtr;
-
-/**
- * Pool of trigger data record
- */
-ArrayPool<TupTriggerData> c_triggerPool;
-
- /* ************ TABLE RECORD ************ */
- /* THIS RECORD FORMS A LIST OF TABLE */
- /* REFERENCE INFORMATION. ONE RECORD */
- /* PER TABLE REFERENCE. */
- /* ************************************** */
- STATIC_CONST( MM = 0 );
- STATIC_CONST( DD = 1 );
-
- struct Tablerec {
- Tablerec(ArrayPool<TupTriggerData> & triggerPool) :
- afterInsertTriggers(triggerPool),
- afterDeleteTriggers(triggerPool),
- afterUpdateTriggers(triggerPool),
- subscriptionInsertTriggers(triggerPool),
- subscriptionDeleteTriggers(triggerPool),
- subscriptionUpdateTriggers(triggerPool),
- constraintUpdateTriggers(triggerPool),
- tuxCustomTriggers(triggerPool)
- {}
-
- Bitmask<MAXNROFATTRIBUTESINWORDS> notNullAttributeMask;
- Bitmask<MAXNROFATTRIBUTESINWORDS> blobAttributeMask;
-
- ReadFunction* readFunctionArray;
- UpdateFunction* updateFunctionArray;
- CHARSET_INFO** charsetArray;
-
- Uint32 readKeyArray;
- Uint32 tabDescriptor;
- Uint32 m_real_order_descriptor;
-
- enum Bits
- {
- TR_Checksum = 0x1, // Need to be 1
- TR_RowGCI = 0x2,
- TR_ForceVarPart = 0x4
- };
- Uint16 m_bits;
- Uint16 total_rec_size; // Max total size for entire tuple in words
-
- /**
- * Aggregates
- */
- Uint16 m_no_of_attributes;
- Uint16 m_no_of_disk_attributes;
- Uint16 noOfKeyAttr;
- Uint16 noOfCharsets;
-
- bool need_expand() const {
- return m_no_of_attributes > m_attributes[MM].m_no_of_fixsize;
- }
-
- bool need_expand(bool disk) const {
- return m_attributes[MM].m_no_of_varsize > 0 ||
- (disk && m_no_of_disk_attributes > 0);
- }
-
- bool need_shrink() const {
- return
- m_attributes[MM].m_no_of_varsize > 0 ||
- m_attributes[DD].m_no_of_varsize > 0;
- }
-
- bool need_shrink(bool disk) const {
- return
- m_attributes[MM].m_no_of_varsize > 0 ||
- (disk && m_attributes[DD].m_no_of_varsize > 0);
- }
-
- /**
- * Descriptors for MM and DD part
- */
- struct Tuple_offsets {
- Uint8 m_null_words;
- Uint8 m_null_offset;
- Uint16 m_disk_ref_offset; // In words relative m_data
- Uint16 m_fix_header_size; // For fix size tuples= total rec size(part)
- Uint16 m_max_var_offset; // In bytes relative m_var_data.m_data_ptr
- } m_offsets[2];
-
- Uint32 get_check_offset(Uint32 mm) const {
- return m_offsets[mm].m_fix_header_size;
- }
-
- struct {
- Uint16 m_no_of_fixsize;
- Uint16 m_no_of_varsize;
- } m_attributes[2];
-
- // Lists of trigger data for active triggers
- DLList<TupTriggerData> afterInsertTriggers;
- DLList<TupTriggerData> afterDeleteTriggers;
- DLList<TupTriggerData> afterUpdateTriggers;
- DLList<TupTriggerData> subscriptionInsertTriggers;
- DLList<TupTriggerData> subscriptionDeleteTriggers;
- DLList<TupTriggerData> subscriptionUpdateTriggers;
- DLList<TupTriggerData> constraintUpdateTriggers;
-
- // List of ordered indexes
- DLList<TupTriggerData> tuxCustomTriggers;
-
- Uint32 fragid[MAX_FRAG_PER_NODE];
- Uint32 fragrec[MAX_FRAG_PER_NODE];
-
- struct {
- Uint32 tabUserPtr;
- Uint32 tabUserRef;
- Uint32 m_lcpno;
- Uint32 m_fragPtrI;
- } m_dropTable;
- State tableStatus;
- };
-
- struct Disk_undo
- {
- enum
- {
- UNDO_ALLOC = File_formats::Undofile::UNDO_TUP_ALLOC
- ,UNDO_UPDATE = File_formats::Undofile::UNDO_TUP_UPDATE
- ,UNDO_FREE = File_formats::Undofile::UNDO_TUP_FREE
- ,UNDO_CREATE = File_formats::Undofile::UNDO_TUP_CREATE
- ,UNDO_DROP = File_formats::Undofile::UNDO_TUP_DROP
- ,UNDO_ALLOC_EXTENT = File_formats::Undofile::UNDO_TUP_ALLOC_EXTENT
- ,UNDO_FREE_EXTENT = File_formats::Undofile::UNDO_TUP_FREE_EXTENT
- };
-
- struct Alloc
- {
- Uint32 m_file_no_page_idx; // 16 bit file_no, 16 bit page_idx
- Uint32 m_page_no;
- Uint32 m_type_length; // 16 bit type, 16 bit length
- };
-
- struct Update
- {
- Uint32 m_file_no_page_idx; // 16 bit file_no, 16 bit page_idx
- Uint32 m_page_no;
- Uint32 m_gci;
- Uint32 m_data[1];
- Uint32 m_type_length; // 16 bit type, 16 bit length
- };
-
- struct Free
- {
- Uint32 m_file_no_page_idx; // 16 bit file_no, 16 bit page_idx
- Uint32 m_page_no;
- Uint32 m_gci;
- Uint32 m_data[1];
- Uint32 m_type_length; // 16 bit type, 16 bit length
- };
-
- struct Create
- {
- Uint32 m_table;
- Uint32 m_type_length; // 16 bit type, 16 bit length
- };
-
- struct Drop
- {
- Uint32 m_table;
- Uint32 m_type_length; // 16 bit type, 16 bit length
- };
-
- struct AllocExtent
- {
- Uint32 m_table;
- Uint32 m_fragment;
- Uint32 m_page_no;
- Uint32 m_file_no;
- Uint32 m_type_length;
- };
-
- struct FreeExtent
- {
- Uint32 m_table;
- Uint32 m_fragment;
- Uint32 m_page_no;
- Uint32 m_file_no;
- Uint32 m_type_length;
- };
- };
-
- Extent_info_pool c_extent_pool;
- Extent_info_hash c_extent_hash;
- Page_request_pool c_page_request_pool;
-
- typedef Ptr<Tablerec> TablerecPtr;
-
- struct storedProc {
- Uint32 storedLinkFirst;
- Uint32 storedLinkLast;
- Uint32 storedCounter;
- Uint32 nextPool;
- Uint16 storedCode;
- Uint16 storedProcLength;
-};
-
-typedef Ptr<storedProc> StoredProcPtr;
-
-ArrayPool<storedProc> c_storedProcPool;
-
-/* **************************** TABLE_DESCRIPTOR RECORD ******************************** */
-/* THIS VARIABLE IS USED TO STORE TABLE DESCRIPTIONS. A TABLE DESCRIPTION IS STORED AS A */
-/* CONTIGUOS ARRAY IN THIS VARIABLE. WHEN A NEW TABLE IS ADDED A CHUNK IS ALLOCATED IN */
-/* THIS RECORD. WHEN ATTRIBUTES ARE ADDED TO THE TABLE, A NEW CHUNK OF PROPER SIZE IS */
-/* ALLOCATED AND ALL DATA IS COPIED TO THIS NEW CHUNK AND THEN THE OLD CHUNK IS PUT IN */
-/* THE FREE LIST. EACH TABLE IS DESCRIBED BY A NUMBER OF TABLE DESCRIPTIVE ATTRIBUTES */
-/* AND A NUMBER OF ATTRIBUTE DESCRIPTORS AS SHOWN IN FIGURE BELOW */
-/* */
-/* WHEN ALLOCATING A TABLE DESCRIPTOR THE SIZE IS ALWAYS A MULTIPLE OF 16 WORDS. */
-/* */
-/* ---------------------------------------------- */
-/* | TRAILER USED FOR ALLOC/DEALLOC | */
-/* ---------------------------------------------- */
-/* | TABLE DESCRIPTIVE ATTRIBUTES | */
-/* ---------------------------------------------- */
-/* | ATTRIBUTE DESCRIPTION 1 | */
-/* ---------------------------------------------- */
-/* | ATTRIBUTE DESCRIPTION 2 | */
-/* ---------------------------------------------- */
-/* | | */
-/* | | */
-/* | | */
-/* ---------------------------------------------- */
-/* | ATTRIBUTE DESCRIPTION N | */
-/* ---------------------------------------------- */
-/* */
-/* THE TABLE DESCRIPTIVE ATTRIBUTES CONTAINS THE FOLLOWING ATTRIBUTES: */
-/* */
-/* ---------------------------------------------- */
-/* | HEADER (TYPE OF INFO) | */
-/* ---------------------------------------------- */
-/* | SIZE OF WHOLE CHUNK (INCL. TRAILER) | */
-/* ---------------------------------------------- */
-/* | TABLE IDENTITY | */
-/* ---------------------------------------------- */
-/* | FRAGMENT IDENTITY | */
-/* ---------------------------------------------- */
-/* | NUMBER OF ATTRIBUTES | */
-/* ---------------------------------------------- */
-/* | SIZE OF FIXED ATTRIBUTES | */
-/* ---------------------------------------------- */
-/* | NUMBER OF NULL FIELDS | */
-/* ---------------------------------------------- */
-/* | NOT USED | */
-/* ---------------------------------------------- */
-/* */
-/* THESE ATTRIBUTES ARE ALL ONE R-VARIABLE IN THE RECORD. */
-/* NORMALLY ONLY ONE TABLE DESCRIPTOR IS USED. DURING SCHEMA CHANGES THERE COULD */
-/* HOWEVER EXIST MORE THAN ONE TABLE DESCRIPTION SINCE THE SCHEMA CHANGE OF VARIOUS */
-/* FRAGMENTS ARE NOT SYNCHRONISED. THIS MEANS THAT ALTHOUGH THE SCHEMA HAS CHANGED */
-/* IN ALL FRAGMENTS, BUT THE FRAGMENTS HAVE NOT REMOVED THE ATTRIBUTES IN THE SAME */
-/* TIME-FRAME. THEREBY SOME ATTRIBUTE INFORMATION MIGHT DIFFER BETWEEN FRAGMENTS. */
-/* EXAMPLES OF ATTRIBUTES THAT MIGHT DIFFER ARE SIZE OF FIXED ATTRIBUTES, NUMBER OF */
-/* ATTRIBUTES, FIELD START WORD, START BIT. */
-/* */
-/* AN ATTRIBUTE DESCRIPTION CONTAINS THE FOLLOWING ATTRIBUTES: */
-/* */
-/* ---------------------------------------------- */
-/* | Field Type, 4 bits (LSB Bits) | */
-/* ---------------------------------------------- */
-/* | Attribute Size, 4 bits | */
-/* ---------------------------------------------- */
-/* | NULL indicator 1 bit | */
-/* ---------------------------------------------- */
-/* | Indicator if TUP stores attr. 1 bit | */
-/* ---------------------------------------------- */
-/* | Not used 6 bits | */
-/* ---------------------------------------------- */
-/* | No. of elements in fixed array 16 bits | */
-/* ---------------------------------------------- */
-/* ---------------------------------------------- */
-/* | Field Start Word, 21 bits (LSB Bits) | */
-/* ---------------------------------------------- */
-/* | NULL Bit, 11 bits | */
-/* ---------------------------------------------- */
-/* */
-/* THE ATTRIBUTE SIZE CAN BE 1,2,4,8,16,32,64 AND 128 BITS. */
-/* */
-/* THE UNUSED PARTS OF THE RECORDS ARE PUT IN A LINKED LIST OF FREE PARTS. EACH OF */
-/* THOSE FREE PARTS HAVE THREE RECORDS ASSIGNED AS SHOWN IN THIS STRUCTURE */
-/* ALL FREE PARTS ARE SET INTO A CHUNK LIST WHERE EACH CHUNK IS AT LEAST 16 WORDS */
-/* */
-/* ---------------------------------------------- */
-/* | HEADER = RNIL | */
-/* ---------------------------------------------- */
-/* | SIZE OF FREE AREA | */
-/* ---------------------------------------------- */
-/* | POINTER TO PREVIOUS FREE AREA | */
-/* ---------------------------------------------- */
-/* | POINTER TO NEXT FREE AREA | */
-/* ---------------------------------------------- */
-/* */
-/* IF THE POINTER TO THE NEXT AREA IS RNIL THEN THIS IS THE LAST FREE AREA. */
-/* */
-/*****************************************************************************************/
-struct TableDescriptor {
- Uint32 tabDescr;
-};
-typedef Ptr<TableDescriptor> TableDescriptorPtr;
-
-struct HostBuffer {
- bool inPackedList;
- Uint32 packetLenTA;
- Uint32 noOfPacketsTA;
- Uint32 packetBufferTA[30];
-};
-typedef Ptr<HostBuffer> HostBufferPtr;
-
- /*
- * Build index operation record.
- */
- struct BuildIndexRec {
- // request cannot use signal class due to extra members
- Uint32 m_request[BuildIndxReq::SignalLength];
- Uint8 m_build_vs; // varsize pages
- Uint32 m_indexId; // the index
- Uint32 m_fragNo; // fragment number under Tablerec
- Uint32 m_pageId; // logical fragment page id
- Uint32 m_tupleNo; // tuple number on page
- Uint32 m_buildRef; // Where to send tuples
- BuildIndxRef::ErrorCode m_errorCode;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- typedef Ptr<BuildIndexRec> BuildIndexPtr;
- ArrayPool<BuildIndexRec> c_buildIndexPool;
- DLList<BuildIndexRec> c_buildIndexList;
- Uint32 c_noOfBuildIndexRec;
-
- /**
- * Reference to variable part when a tuple is chained
- */
- struct Var_part_ref
- {
-#ifdef NDB_32BIT_VAR_REF
- /*
- In versions prior to ndb 6.1.6, 6.2.1 and mysql 5.1.17
- Running this code limits DataMemory to 16G, also online
- upgrade not possible between versions
- */
- Uint32 m_ref;
- STATIC_CONST( SZ32 = 1 );
-
- void copyout(Local_key* dst) const {
- dst->m_page_no = m_ref >> MAX_TUPLES_BITS;
- dst->m_page_idx = m_ref & MAX_TUPLES_PER_PAGE;
- }
-
- void assign(const Local_key* src) {
- m_ref = (src->m_page_no << MAX_TUPLES_BITS) | src->m_page_idx;
- }
-#else
- Uint32 m_page_no;
- Uint32 m_page_idx;
- STATIC_CONST( SZ32 = 2 );
-
- void copyout(Local_key* dst) const {
- dst->m_page_no = m_page_no;
- dst->m_page_idx = m_page_idx;
- }
-
- void assign(const Local_key* src) {
- m_page_no = src->m_page_no;
- m_page_idx = src->m_page_idx;
- }
-#endif
- };
-
- struct Disk_part_ref
- {
- STATIC_CONST( SZ32 = 2 );
- };
-
- struct Tuple_header
- {
- union {
- /**
- * List of prepared operations for this tuple.
- * Points to most recent/last operation, ie. to walk the list must follow
- * regOperPtr->prevActiveOp links.
- */
- Uint32 m_operation_ptr_i; // OperationPtrI
- Uint32 m_base_record_ref; // For disk tuple, ref to MM tuple
- };
- Uint32 m_header_bits; // Header word
- union {
- Uint32 m_checksum;
- Uint32 m_data[1];
- Uint32 m_null_bits[1];
- };
-
- STATIC_CONST( HeaderSize = 2 );
-
- /**
- * header bits
- */
- STATIC_CONST( TUP_VERSION_MASK = 0xFFFF );
- STATIC_CONST( CHAINED_ROW = 0x00010000 ); // Is var part on different page
- STATIC_CONST( DISK_PART = 0x00020000 ); // Is there a disk part
- STATIC_CONST( DISK_ALLOC = 0x00040000 ); // Is disk part allocated
- STATIC_CONST( DISK_INLINE = 0x00080000 ); // Is disk inline
- STATIC_CONST( ALLOC = 0x00100000 ); // Is record allocated now
- STATIC_CONST( MM_SHRINK = 0x00200000 ); // Has MM part shrunk
- STATIC_CONST( MM_GROWN = 0x00400000 ); // Has MM part grown
- STATIC_CONST( FREED = 0x00800000 ); // Is freed
- STATIC_CONST( LCP_SKIP = 0x01000000 ); // Should not be returned in LCP
- STATIC_CONST( LCP_KEEP = 0x02000000 ); // Should be returned in LCP
- STATIC_CONST( FREE = 0x02800000 ); // Is free
-
- Tuple_header() {}
- Uint32 get_tuple_version() const {
- return m_header_bits & TUP_VERSION_MASK;
- }
- void set_tuple_version(Uint32 version) {
- m_header_bits=
- (m_header_bits & ~(Uint32)TUP_VERSION_MASK) |
- (version & TUP_VERSION_MASK);
- }
-
- Uint32* get_null_bits(const Tablerec* tabPtrP) {
- return m_null_bits+tabPtrP->m_offsets[MM].m_null_offset;
- }
-
- Uint32* get_null_bits(const Tablerec* tabPtrP, Uint32 mm) {
- return m_null_bits+tabPtrP->m_offsets[mm].m_null_offset;
- }
-
- Var_part_ref* get_var_part_ref_ptr(const Tablerec* tabPtrP) {
- return (Var_part_ref*)(get_disk_ref_ptr(tabPtrP) + Disk_part_ref::SZ32);
- }
-
- const Var_part_ref* get_var_part_ref_ptr(const Tablerec* tabPtrP) const {
- return (Var_part_ref*)(get_disk_ref_ptr(tabPtrP) + Disk_part_ref::SZ32);
- }
-
- Uint32* get_end_of_fix_part_ptr(const Tablerec* tabPtrP) {
- return m_data + tabPtrP->m_offsets[MM].m_fix_header_size -
- Tuple_header::HeaderSize;
- }
-
- const Uint32* get_end_of_fix_part_ptr(const Tablerec* tabPtrP) const {
- return m_data + tabPtrP->m_offsets[MM].m_fix_header_size -
- Tuple_header::HeaderSize;
- }
-
- Uint32* get_disk_ref_ptr(const Tablerec* tabPtrP) {
- return m_data + tabPtrP->m_offsets[MM].m_disk_ref_offset;
- }
-
- const Uint32* get_disk_ref_ptr(const Tablerec* tabPtrP) const {
- return m_data + tabPtrP->m_offsets[MM].m_disk_ref_offset;
- }
-
- Uint32 *get_mm_gci(const Tablerec* tabPtrP){
- assert(tabPtrP->m_bits & Tablerec::TR_RowGCI);
- return m_data + (tabPtrP->m_bits & Tablerec::TR_Checksum);
- }
-
- Uint32 *get_dd_gci(const Tablerec* tabPtrP, Uint32 mm){
- assert(tabPtrP->m_bits & Tablerec::TR_RowGCI);
- return m_data;
- }
- };
-
-struct KeyReqStruct {
-/**
- * These variables are used as temporary storage during execution of the
- * TUPKEYREQ signal.
- * The first set of variables defines a number of variables needed for
- * the fix part of the tuple.
- *
- * The second part defines a number of commonly used meta data variables.
- *
- * The third set of variables defines a set of variables needed for the
- * variable part.
- *
- * The fourth part is variables needed only for updates and inserts.
- *
- * The fifth part is a long array of real lengths which is is put last
- * for cache memory reasons. This is part of the variable part and
- * contains the real allocated lengths whereas the tuple contains
- * the length of attribute stored.
- */
- Tuple_header *m_tuple_ptr;
-
- Uint32 check_offset[2];
-
- TableDescriptor *attr_descr;
- Uint32 max_read;
- Uint32 out_buf_index;
- Uint32 in_buf_index;
- Uint32 in_buf_len;
- Uint32 attr_descriptor;
- bool xfrm_flag;
-
- struct Var_data {
- char *m_data_ptr;
- Uint16 *m_offset_array_ptr;
- Uint16 m_var_len_offset;
- Uint16 m_max_var_offset;
- } m_var_data[2];
-
- Tuple_header *m_disk_ptr;
- PagePtr m_page_ptr;
- PagePtr m_varpart_page_ptr; // could be same as m_page_ptr_p
- PagePtr m_disk_page_ptr; //
- Local_key m_row_id;
-
- bool dirty_op;
- bool interpreted_exec;
- bool last_row;
- bool m_use_rowid;
-
- Signal* signal;
- Uint32 no_fired_triggers;
- Uint32 frag_page_id;
- Uint32 hash_value;
- Uint32 gci;
- Uint32 log_size;
- Uint32 read_length;
- Uint32 attrinfo_len;
- Uint32 tc_operation_ptr;
- Uint32 trans_id1;
- Uint32 trans_id2;
- Uint32 TC_index;
- // next 2 apply only to attrids >= 64 (zero otherwise)
- Uint32 max_attr_id_updated;
- Uint32 no_changed_attrs;
- BlockReference TC_ref;
- BlockReference rec_blockref;
- bool change_mask_calculated;
- /*
- * A bit mask where a bit set means that the update or insert
- * was updating this record.
- */
- Bitmask<MAXNROFATTRIBUTESINWORDS> changeMask;
- Uint16 var_pos_array[2*MAX_ATTRIBUTES_IN_TABLE + 1];
- OperationrecPtr prevOpPtr;
-};
-
- friend class Undo_buffer;
- Undo_buffer c_undo_buffer;
-
-/*
- No longer used:
- Implemented by shift instructions in subroutines instead
-
-struct TupHeadInfo {
- struct BitPart {
- unsigned int disk_indicator : 1;
- unsigned int var_part_loc_ind : 1;
- unsigned int initialised : 1;
- unsigned int not_used_yet : 5;
- unsigned int no_var_sized : 8;
- unsigned int tuple_version : 16;
- };
- union {
- Uint32 all;
- BitPart bit_part;
- };
-};
-*/
-
-// updateAttributes module
- Uint32 terrorCode;
-
-public:
- Dbtup(Block_context&, Pgman*);
- virtual ~Dbtup();
-
- /*
- * TUX uses logical tuple address when talking to ACC and LQH.
- */
- void tuxGetTupAddr(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32& tupAddr);
-
- /*
- * TUX index in TUP has single Uint32 array attribute which stores an
- * index node. TUX reads and writes the node directly via pointer.
- */
- int tuxAllocNode(Signal* signal, Uint32 fragPtrI, Uint32& pageId, Uint32& pageOffset, Uint32*& node);
- void tuxFreeNode(Signal* signal, Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* node);
- void tuxGetNode(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32*& node);
-
- /*
- * TUX reads primary table attributes for index keys. Tuple is
- * specified by location of original tuple and version number. Input
- * is attribute ids in AttributeHeader format. Output is attribute
- * data with headers. Uses readAttributes with xfrm option set.
- * Returns number of words or negative (-terrorCode) on error.
- */
- int tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, const Uint32* attrIds, Uint32 numAttrs, Uint32* dataOut);
-
- /*
- * TUX reads primary key without headers into an array of words. Used
- * 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, 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.
- */
- bool tuxQueryTh(Uint32 fragPtrI, Uint32 pageId, Uint32 pageIndex, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, bool dirty, Uint32 savepointId);
-
- int load_diskpage(Signal*, Uint32 opRec, Uint32 fragPtrI,
- Uint32 local_key, Uint32 flags);
-
- int load_diskpage_scan(Signal*, Uint32 opRec, Uint32 fragPtrI,
- Uint32 local_key, Uint32 flags);
-
- int alloc_page(Tablerec*, Fragrecord*, PagePtr*,Uint32 page_no);
-
- void start_restore_lcp(Uint32 tableId, Uint32 fragmentId);
- void complete_restore_lcp(Uint32 tableId, Uint32 fragmentId);
-
- int nr_read_pk(Uint32 fragPtr, const Local_key*, Uint32* dataOut, bool&copy);
- int nr_update_gci(Uint32 fragPtr, const Local_key*, Uint32 gci);
- int nr_delete(Signal*, Uint32, Uint32 fragPtr, const Local_key*, Uint32 gci);
-
- void nr_delete_page_callback(Signal*, Uint32 op, Uint32 page);
- void nr_delete_log_buffer_callback(Signal*, Uint32 op, Uint32 page);
-
- bool get_frag_info(Uint32 tableId, Uint32 fragId, Uint32* maxPage);
-private:
- BLOCK_DEFINES(Dbtup);
-
- // Transit signals
- void execDEBUG_SIG(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- // Received signals
- void execLCP_FRAG_ORD(Signal*signal);
- void execDUMP_STATE_ORD(Signal* signal);
- void execSEND_PACKED(Signal* signal);
- void execSTTOR(Signal* signal);
- void execTUP_LCPREQ(Signal* signal);
- void execEND_LCPREQ(Signal* signal);
- void execSTART_RECREQ(Signal* signal);
- void execMEMCHECKREQ(Signal* signal);
- void execTUPSEIZEREQ(Signal* signal);
- void execTUPRELEASEREQ(Signal* signal);
- void execSTORED_PROCREQ(Signal* signal);
- void execTUPFRAGREQ(Signal* signal);
- void execTUP_ADD_ATTRREQ(Signal* signal);
- void execTUP_COMMITREQ(Signal* signal);
- void execTUP_ABORTREQ(Signal* signal);
- void execNDB_STTOR(Signal* signal);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execDROP_TAB_REQ(Signal* signal);
- void execALTER_TAB_REQ(Signal* signal);
- void execTUP_DEALLOCREQ(Signal* signal);
- void execTUP_WRITELOG_REQ(Signal* signal);
-
- // Ordered index related
- void execBUILDINDXREQ(Signal* signal);
- 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);
- void execACCKEYCONF(Signal* signal);
- void execACCKEYREF(Signal* signal);
- void execACC_ABORTCONF(Signal* signal);
-
-
- // Drop table
- void execFSREMOVEREF(Signal*);
- void execFSREMOVECONF(Signal*);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
-// Methods to handle execution of TUPKEYREQ + ATTRINFO.
-//
-// Module Execution Manager
-//
-// The TUPKEYREQ signal is central to this block. This signal is used
-// by everybody that needs to read data residing in DBTUP. The data is
-// read using an interpreter approach.
-//
-// Operations only needing to read execute a simplified version of the
-// interpreter where the only instruction is read Attribute to send.
-// Operations only needing to update the record (insert or update)
-// execute a simplified version of the interpreter where the only
-// instruction is write Attribute.
-//
-// Currently TUPKEYREQ is used in the following situations.
-// 1) Normal transaction execution. Can be any of the types described
-// below.
-// 2) Execution of fragment redo log during system restart.
-// In this situation there will only be normal updates, inserts
-// and deletes performed.
-// 3) A special type of normal transaction execution is to write the
-// records arriving from the primary replica in the node restart
-// processing. This will always be normal write operations which
-// are translated to inserts or updates before arriving to TUP.
-// 4) Scan processing. The scan processing will use normal reads or
-// interpreted reads in their execution. There will be one TUPKEYREQ
-// signal for each record processed.
-// 5) Copy fragment processing. This is a special type of scan used in the
-// primary replica at system restart. It reads the entire reads and
-// converts those to writes to the starting node. In this special case
-// LQH acts as an API node and receives also the ATTRINFO sent in the
-// TRANSID_AI signals.
-//
-// Signal Diagram:
-//
-// In Signals:
-// -----------
-//
-// Logically there is one request TUPKEYREQ which requests to read/write data
-// of one tuple in the database. Since the definition of what to read and write
-// can be bigger than the maximum signal size we segment the signal. The definition
-// of what to read/write/interpreted program is sent before the TUPKEYREQ signal.
-//
-// ---> ATTRINFO
-// ...
-// ---> ATTRINFO
-// ---> TUPKEYREQ
-// The number of ATTRINFO signals can be anything between 0 and upwards.
-// The total size of the ATTRINFO is not allowed to be more than 16384 words.
-// There is always one and only one TUPKEYREQ.
-//
-// Response Signals (successful case):
-//
-// Simple/Dirty Read Operation
-// ---------------------------
-//
-// <---- TRANSID_AI (to API)
-// ...
-// <---- TRANSID_AI (to API)
-// <---- READCONF (to API)
-// <---- TUPKEYCONF (to LQH)
-// There is always exactly one READCONF25 sent last. The number of
-// TRANSID_AI is dependent on how much that was read. The maximum size
-// of the ATTRINFO sent back is 16384 words. The signals are sent
-// directly to the application with an address provided by the
-// TUPKEYREQ signal.
-// A positive response signal is also sent to LQH.
-//
-// Normal Read Operation
-// ---------------------
-//
-// <---- TRANSID_AI (to API)
-// ...
-// <---- TRANSID_AI (to API)
-// <---- TUPKEYCONF (to LQH)
-// The number of TRANSID_AI is dependent on how much that was read.
-// The maximum size of the ATTRINFO sent back is 16384 words. The
-// signals are sent directly to the application with an address
-// provided by the TUPKEYREQ signal.
-// A positive response signal is also sent to LQH.
-//
-// Normal update/insert/delete operation
-// -------------------------------------
-//
-// <---- TUPKEYCONF
-// After successful updating of the tuple LQH is informed of this.
-//
-// Delete with read
-// ----------------
-//
-// Will behave as a normal read although it also prepares the
-// deletion of the tuple.
-//
-// Interpreted Update
-// ------------------
-//
-// <---- TRANSID_AI (to API)
-// ...
-// <---- TRANSID_AI (to API)
-// <---- TUP_ATTRINFO (to LQH)
-// ...
-// <---- TUP_ATTRINFO (to LQH)
-// <---- TUPKEYCONF (to LQH)
-//
-// The interpreted Update contains five sections:
-// The first section performs read Attribute operations
-// that send results back to the API.
-//
-// The second section executes the interpreted program
-// where data from attributes can be updated and it
-// can also read attribute values into the registers.
-//
-// The third section performs unconditional updates of
-// attributes.
-//
-// The fourth section can read the attributes to be sent to the
-// API after updating the record.
-//
-// The fifth section contains subroutines used by the interpreter
-// in the second section.
-//
-// All types of interpreted programs contains the same five sections.
-// The only difference is that only interpreted updates can update
-// attributes. Interpreted inserts are not allowed.
-//
-// Interpreted Updates have to send back the information about the
-// attributes they have updated. This information will be shipped to
-// the log and also to any other replicas. Thus interpreted updates
-// are only performed in the primary replica. The fragment redo log
-// in LQH will contain information so that normal update/inserts/deletes
-// can be performed using TUPKEYREQ.
-//
-// Interpreted Read
-// ----------------
-//
-// From a signalling point of view the Interpreted Read behaves as
-// as a Normal Read. The interpreted Read is often used by Scan's.
-//
-// Interpreted Delete
-// ------------------
-//
-// <---- TUPKEYCONF
-// After successful prepartion to delete the tuple LQH is informed
-// of this.
-//
-// Interpreted Delete with Read
-// ----------------------------
-//
-// From a signalling point of view an interpreted delete with read
-// behaves as a normal read.
-//
-// Continuation after successful case:
-//
-// After a read of any kind the operation record is ready to be used
-// again by a new operation.
-//
-// Any updates, inserts or deletes waits for either of two messages.
-// A commit specifying that the operation is to be performed for real
-// or an abort specifying that the operation is to be rolled back and
-// the record to be restored in its original format.
-//
-// This is handled by the module Transaction Manager.
-//
-// Response Signals (unsuccessful case):
-//
-// <---- TUPKEYREF (to LQH)
-// A signal is sent back to LQH informing about the unsuccessful
-// operation. In this case TUP waits for an abort signal to arrive
-// before the operation record is ready for the next operation.
-// This is handled by the Transaction Manager.
-//------------------------------------------------------------------
-//------------------------------------------------------------------
-
-// *****************************************************************
-// Signal Reception methods.
-// *****************************************************************
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void execTUPKEYREQ(Signal* signal);
- void disk_page_load_callback(Signal*, Uint32 op, Uint32 page);
- void disk_page_load_scan_callback(Signal*, Uint32 op, Uint32 page);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void execATTRINFO(Signal* signal);
-public:
- void receive_attrinfo(Signal*, Uint32 op, const Uint32* data, Uint32 len);
-private:
-
-// Trigger signals
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void execCREATE_TRIG_REQ(Signal* signal);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void execDROP_TRIG_REQ(Signal* signal);
-
-// *****************************************************************
-// Support methods for ATTRINFO.
-// *****************************************************************
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void handleATTRINFOforTUPKEYREQ(Signal* signal,
- const Uint32* data,
- Uint32 length,
- Operationrec * regOperPtr);
-
-// *****************************************************************
-// Setting up the environment for reads, inserts, updates and deletes.
-// *****************************************************************
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int handleReadReq(Signal* signal,
- Operationrec* regOperPtr,
- Tablerec* regTabPtr,
- KeyReqStruct* req_struct);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int handleUpdateReq(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- KeyReqStruct* req_struct,
- bool disk);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int handleInsertReq(Signal* signal,
- Ptr<Operationrec> regOperPtr,
- Ptr<Fragrecord>,
- Tablerec* regTabPtr,
- KeyReqStruct* req_struct);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int handleDeleteReq(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- KeyReqStruct* req_struct,
- bool disk);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int updateStartLab(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- KeyReqStruct* req_struct);
-
-// *****************************************************************
-// Interpreter Handling methods.
-// *****************************************************************
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int interpreterStartLab(Signal* signal,
- KeyReqStruct *req_struct);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int interpreterNextLab(Signal* signal,
- KeyReqStruct *req_struct,
- Uint32* logMemory,
- Uint32* mainProgram,
- Uint32 TmainProgLen,
- Uint32* subroutineProg,
- Uint32 TsubroutineLen,
- Uint32 * tmpArea,
- Uint32 tmpAreaSz);
-
-// *****************************************************************
-// Signal Sending methods.
-// *****************************************************************
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void sendReadAttrinfo(Signal* signal,
- KeyReqStruct *req_struct,
- Uint32 TnoOfData,
- const Operationrec * regOperPtr);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void sendLogAttrinfo(Signal* signal,
- Uint32 TlogSize,
- Operationrec * regOperPtr);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void sendTUPKEYCONF(Signal* signal,
- KeyReqStruct *req_struct,
- Operationrec * regOperPtr);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
-// *****************************************************************
-// The methods that perform the actual read and update of attributes
-// in the tuple.
-// *****************************************************************
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int readAttributes(KeyReqStruct* req_struct,
- const Uint32* inBuffer,
- Uint32 inBufLen,
- Uint32* outBuffer,
- Uint32 TmaxRead,
- bool xfrmFlag);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int updateAttributes(KeyReqStruct *req_struct,
- Uint32* inBuffer,
- Uint32 inBufLen);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readFixedSizeTHOneWordNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateFixedSizeTHOneWordNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readFixedSizeTHTwoWordNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateFixedSizeTHTwoWordNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readFixedSizeTHOneWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateFixedSizeTHOneWordNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readFixedSizeTHTwoWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateFixedSizeTHTwoWordNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readFixedSizeTHManyWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readFixedSizeTHZeroWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateFixedSizeTHManyWordNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readVarSizeNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateVarSizeNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readVarSizeNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateVarSizeNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readDynFixedSize(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateDynFixedSize(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readDynVarSize(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateDynVarSize(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2);
-
- bool readCharNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
- bool readCharNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
- bool readBitsNULLable(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);
- bool updateBitsNULLable(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
- bool readBitsNotNULL(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);
- bool updateBitsNotNULL(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
-
- bool updateFixedNULLable(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
- bool updateFixedNotNull(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
-
- bool updateVarNULLable(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
- bool updateVarNotNull(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
-
-
- bool readDiskFixedSizeNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
-
- bool readDiskFixedSizeNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2);
- bool readDiskVarSizeNULLable(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);
- bool readDiskVarSizeNotNULL(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);
-
- bool updateDiskFixedSizeNULLable(Uint32*, KeyReqStruct*, Uint32);
- bool updateDiskFixedSizeNotNULL(Uint32*, KeyReqStruct*, Uint32);
-
- bool updateDiskVarSizeNULLable(Uint32*, KeyReqStruct *, Uint32);
- bool updateDiskVarSizeNotNULL(Uint32*, KeyReqStruct *, Uint32);
-
- bool readDiskBitsNULLable(Uint32*, KeyReqStruct*, AttributeHeader*, Uint32);
- bool readDiskBitsNotNULL(Uint32*, KeyReqStruct*, AttributeHeader*, Uint32);
- bool updateDiskBitsNULLable(Uint32*, KeyReqStruct*, Uint32);
- bool updateDiskBitsNotNULL(Uint32*, KeyReqStruct*, Uint32);
-
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2);
- bool disk_nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2);
- Uint32 read_pseudo(Uint32 attrId,
- KeyReqStruct *req_struct,
- Uint32* outBuffer);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void setUpQueryRoutines(Tablerec* regTabPtr);
-
-// *****************************************************************
-// Service methods.
-// *****************************************************************
- TransState get_trans_state(Operationrec * const);
- void set_trans_state(Operationrec * const, TransState);
- TupleState get_tuple_state(Operationrec * const);
- void set_tuple_state(Operationrec * const, TupleState);
- Uint32 get_frag_page_id(Uint32 real_page_id);
- Uint32 get_fix_page_offset(Uint32 page_index, Uint32 tuple_size);
-
- Uint32 decr_tup_version(Uint32 tuple_version);
- void set_change_mask_state(Operationrec * const, ChangeMaskState);
- ChangeMaskState get_change_mask_state(Operationrec * const);
- void update_change_mask_info(KeyReqStruct * const, Operationrec * const);
- void set_change_mask_info(KeyReqStruct * const, Operationrec * const);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void copyAttrinfo(Operationrec * regOperPtr, Uint32* inBuffer);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void initOpConnection(Operationrec* regOperPtr);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void initOperationrec(Signal* signal);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int initStoredOperationrec(Operationrec* regOperPtr,
- KeyReqStruct* req_struct,
- Uint32 storedId);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool insertActiveOpList(OperationrecPtr, KeyReqStruct* req_struct);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void bufferTRANSID_AI(Signal* signal, BlockReference aRef, Uint32 Tlen);
-
-//------------------------------------------------------------------
-// Trigger handling routines
-//------------------------------------------------------------------
- DLList<TupTriggerData>*
- findTriggerList(Tablerec* table,
- TriggerType::Value ttype,
- TriggerActionTime::Value ttime,
- TriggerEvent::Value tevent);
-
- bool createTrigger(Tablerec* table, const CreateTrigReq* req);
-
- Uint32 dropTrigger(Tablerec* table,
- const DropTrigReq* req,
- BlockNumber sender);
-
- void
- checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* tablePtr,
- bool disk);
-
- void
- checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* tablePtr,
- bool disk);
-
- void
- checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* tablePtr,
- bool disk);
-
-#if 0
- void checkDeferredTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Tablerec* regTablePtr);
-#endif
- void checkDetachedTriggers(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* regTablePtr,
- bool disk);
-
- void fireImmediateTriggers(KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* regOperPtr,
- bool disk);
-
- void fireDeferredTriggers(KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* regOperPtr);
-
- void fireDetachedTriggers(KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* regOperPtr,
- bool disk);
-
- void executeTriggers(KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* regOperPtr,
- bool disk);
-
- void executeTrigger(KeyReqStruct *req_struct,
- TupTriggerData* trigPtr,
- Operationrec* regOperPtr,
- bool disk);
-
- bool readTriggerInfo(TupTriggerData* trigPtr,
- Operationrec* regOperPtr,
- KeyReqStruct * req_struct,
- Fragrecord* regFragPtr,
- Uint32* keyBuffer,
- Uint32& noPrimKey,
- Uint32* afterBuffer,
- Uint32& noAfterWords,
- Uint32* beforeBuffer,
- Uint32& noBeforeWords,
- bool disk);
-
- void sendTrigAttrInfo(Signal* signal,
- Uint32* data,
- Uint32 dataLen,
- bool executeDirect,
- BlockReference receiverReference);
-
- Uint32 setAttrIds(Bitmask<MAXNROFATTRIBUTESINWORDS>& attributeMask,
- Uint32 noOfAttributes,
- Uint32* inBuffer);
-
- void sendFireTrigOrd(Signal* signal,
- KeyReqStruct *req_struct,
- Operationrec * regOperPtr,
- TupTriggerData* trigPtr,
- Uint32 fragmentId,
- Uint32 noPrimKeySignals,
- Uint32 noBeforeSignals,
- Uint32 noAfterSignals);
-
- bool primaryKey(Tablerec* const, Uint32);
-
- // these set terrorCode and return non-zero on error
-
- int executeTuxInsertTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr);
-
- int executeTuxUpdateTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr);
-
- int executeTuxDeleteTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr);
-
- int addTuxEntries(Signal* signal,
- Operationrec* regOperPtr,
- Tablerec* regTabPtr);
-
- // these crash the node on error
-
- void executeTuxCommitTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr);
-
- void executeTuxAbortTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr);
-
- void removeTuxEntries(Signal* signal,
- Tablerec* regTabPtr);
-
-// *****************************************************************
-// Error Handling routines.
-// *****************************************************************
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int TUPKEY_abort(Signal* signal, int error_type);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- void tupkeyErrorLab(Signal* signal);
- void do_tup_abortreq(Signal*, Uint32 flags);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
-// Methods to handle execution of TUP_COMMITREQ + TUP_ABORTREQ.
-//
-// Module Transaction Manager
-//
-// The Transaction Manager module is responsible for the commit
-// and abort of operations started by the Execution Manager.
-//
-// Commit Operation:
-// ----------------
-//
-// Failures in commit processing is not allowed since that would
-// leave the database in an unreliable state. Thus the only way
-// to handle failures in commit processing is to crash the node.
-//
-// TUP_COMMITREQ can only be received in the wait state after a
-// successful TUPKEYREQ which was not a read operation.
-//
-// Commit of Delete:
-// -----------------
-//
-// This will actually perform the deletion of the record unless
-// other operations also are connected to the record. In this case
-// we will set the delete state on the record that becomes the ownerd
-// of the record.
-//
-// Commit of Update:
-// ----------------
-//
-// We will release the copy record where the original record was kept.
-// Also here we will take special care if more operations are updating
-// the record simultaneously.
-//
-// Commit of Insert:
-// -----------------
-//
-// Will simply reset the state of the operation record.
-//
-// Signal Diagram:
-// ---> TUP_COMMITREQ (from LQH)
-// <---- TUP_COMMITCONF (to LQH)
-//
-//
-// Abort Operation:
-// ----------------
-//
-// Signal Diagram:
-// ---> TUP_ABORTREQ (from LQH)
-// <---- TUP_ABORTCONF (to LQH)
-//
-// Failures in abort processing is not allowed since that would
-// leave the database in an unreliable state. Thus the only way
-// to handle failures in abort processing is to crash the node.
-//
-// Abort messages can arrive at any time. It can arrive even before
-// anything at all have arrived of the operation. It can arrive after
-// receiving a number of ATTRINFO but before TUPKEYREQ has been received.
-// It must arrive after that we sent TUPKEYREF in response to TUPKEYREQ
-// and finally it can arrive after successfully performing the TUPKEYREQ
-// in all cases including the read case.
-//------------------------------------------------------------------
-//------------------------------------------------------------------
-
-#if 0
- void checkPages(Fragrecord* regFragPtr);
-#endif
- Uint32 convert_byte_to_word_size(Uint32 byte_size)
- {
- return ((byte_size + 3) >> 2);
- }
- Uint32 convert_bit_to_word_size(Uint32 bit_size)
- {
- return ((bit_size + 31) >> 5);
- }
-
- void prepare_initial_insert(KeyReqStruct*, Operationrec*, Tablerec*);
- void fix_disk_insert_no_mem_insert(KeyReqStruct*, Operationrec*, Tablerec*);
- void setup_fixed_part(KeyReqStruct* req_struct,
- Operationrec* regOperPtr,
- Tablerec* regTabPtr);
-
- void send_TUPKEYREF(Signal* signal,
- Operationrec* regOperPtr);
- void early_tupkey_error(Signal* signal);
-
- void printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit);
-
- bool checkUpdateOfPrimaryKey(KeyReqStruct *req_struct,
- Uint32* updateBuffer,
- Tablerec* regTabPtr);
-
- void setNullBits(Uint32*, Tablerec* regTabPtr);
- bool checkNullAttributes(KeyReqStruct * const, Tablerec* const);
- bool find_savepoint(OperationrecPtr& loopOpPtr, Uint32 savepointId);
- bool setup_read(KeyReqStruct* req_struct,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- bool disk);
-
- Uint32 calculateChecksum(Tuple_header*, Tablerec* regTabPtr);
- void setChecksum(Tuple_header*, Tablerec* regTabPtr);
-
- void complexTrigger(Signal* signal,
- KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr);
-
- void setTupleStatesSetOpType(Operationrec* regOperPtr,
- KeyReqStruct *req_struct,
- Page* pagePtr,
- Uint32& opType,
- OperationrecPtr& firstOpPtr);
-
- void findBeforeValueOperation(OperationrecPtr& befOpPtr,
- OperationrecPtr firstOpPtr);
-
- void calculateChangeMask(Page* PagePtr,
- Tablerec* regTabPtr,
- KeyReqStruct * req_struct);
-
- void updateGcpId(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr);
-
- void setTupleStateOnPreviousOps(Uint32 prevOpIndex);
- void copyMem(Signal* signal, Uint32 sourceIndex, Uint32 destIndex);
-
- void freeAllAttrBuffers(Operationrec* const regOperPtr);
- void freeAttrinbufrec(Uint32 anAttrBufRec);
- void removeActiveOpList(Operationrec* const regOperPtr, Tuple_header*);
-
- void updatePackedList(Signal* signal, Uint16 ahostIndex);
-
- void setUpDescriptorReferences(Uint32 descriptorReference,
- Tablerec* regTabPtr,
- const Uint32* offset);
- void setUpKeyArray(Tablerec* regTabPtr);
- bool addfragtotab(Tablerec* regTabPtr, Uint32 fragId, Uint32 fragIndex);
- void deleteFragTab(Tablerec* regTabPtr, Uint32 fragId);
- void abortAddFragOp(Signal* signal);
- void releaseTabDescr(Tablerec* regTabPtr);
- void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* regTabPtr);
-
- void initialiseRecordsLab(Signal* signal, Uint32 switchData, Uint32, Uint32);
- void initializeAttrbufrec();
- void initializeCheckpointInfoRec();
- void initializeDiskBufferSegmentRecord();
- void initializeFragoperrec();
- void initializeFragrecord();
- void initializeHostBuffer();
- void initializeLocalLogInfo();
- void initializeOperationrec();
- void initializePendingFileOpenInfoRecord();
- void initializeRestartInfoRec();
- void initializeTablerec();
- void initializeTabDescr();
- void initializeUndoPage();
-
- void initTab(Tablerec* regTabPtr);
-
- void startphase3Lab(Signal* signal, Uint32 config1, Uint32 config2);
-
- void fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr);
- void fragrefuse1Lab(Signal* signal, FragoperrecPtr fragOperPtr);
- void fragrefuse2Lab(Signal* signal, FragoperrecPtr fragOperPtr, FragrecordPtr regFragPtr);
- void fragrefuse3Lab(Signal* signal,
- FragoperrecPtr fragOperPtr,
- FragrecordPtr regFragPtr,
- Tablerec* regTabPtr,
- Uint32 fragId);
- void fragrefuse4Lab(Signal* signal,
- FragoperrecPtr fragOperPtr,
- FragrecordPtr regFragPtr,
- Tablerec* regTabPtr,
- Uint32 fragId);
- void addattrrefuseLab(Signal* signal,
- FragrecordPtr regFragPtr,
- FragoperrecPtr fragOperPtr,
- Tablerec* regTabPtr,
- Uint32 fragId);
-
-
- void releaseFragment(Signal* signal, Uint32 tableId, Uint32);
- void drop_fragment_free_var_pages(Signal*);
- void drop_fragment_free_extent(Signal*, TablerecPtr, FragrecordPtr, Uint32);
- void drop_fragment_free_extent_log_buffer_callback(Signal*, Uint32, Uint32);
- void drop_fragment_unmap_pages(Signal*, TablerecPtr, FragrecordPtr, Uint32);
- void drop_fragment_unmap_page_callback(Signal* signal, Uint32, Uint32);
- void drop_fragment_fsremove(Signal*, TablerecPtr, FragrecordPtr);
- void drop_fragment_fsremove_done(Signal*, TablerecPtr, FragrecordPtr);
-
- // Initialisation
- void initData();
- void initRecords();
-
- void deleteScanProcedure(Signal* signal, Operationrec* regOperPtr);
- void copyProcedure(Signal* signal,
- TablerecPtr regTabPtr,
- Operationrec* regOperPtr);
- void scanProcedure(Signal* signal,
- Operationrec* regOperPtr,
- Uint32 lenAttrInfo);
- void storedSeizeAttrinbufrecErrorLab(Signal* signal,
- Operationrec* regOperPtr,
- Uint32 errorCode);
- bool storedProcedureAttrInfo(Signal* signal,
- Operationrec* regOperPtr,
- const Uint32* data,
- Uint32 length,
- bool copyProc);
-
-//-----------------------------------------------------------------------------
-// Table Descriptor Memory Manager
-//-----------------------------------------------------------------------------
-
-// Public methods
- Uint32 getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset);
- Uint32 allocTabDescr(const Tablerec* regTabPtr, Uint32* offset);
- void freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal = true);
- Uint32 getTabDescrWord(Uint32 index);
- void setTabDescrWord(Uint32 index, Uint32 word);
-
-// Private methods
- Uint32 sizeOfReadFunction();
- void removeTdArea(Uint32 tabDesRef, Uint32 list);
- void insertTdArea(Uint32 tabDesRef, Uint32 list);
- void itdaMergeTabDescr(Uint32& retRef, Uint32& retNo, bool normal);
-#ifdef VM_TRACE
- void verifytabdes();
-#endif
-
- void seizeOpRec(OperationrecPtr& regOperPtr);
- void seizeFragrecord(FragrecordPtr& regFragPtr);
- void seizeFragoperrec(FragoperrecPtr& fragOperPtr);
- void releaseFragoperrec(FragoperrecPtr fragOperPtr);
- void releaseFragrec(FragrecordPtr);
-//----------------------------------------------------------------------------
-// Page Memory Manager
-//----------------------------------------------------------------------------
-
-// Public methods
- void allocConsPages(Uint32 noOfPagesToAllocate,
- Uint32& noOfPagesAllocated,
- Uint32& allocPageRef);
- void returnCommonArea(Uint32 retPageRef, Uint32 retNo);
- void initializePage();
-
-// Private methods
- void removeCommonArea(Uint32 remPageRef, Uint32 list);
- void insertCommonArea(Uint32 insPageRef, Uint32 list);
- void findFreeLeftNeighbours(Uint32& allocPageRef, Uint32& noPagesAllocated, Uint32 noPagesToAllocate);
- void findFreeRightNeighbours(Uint32& allocPageRef, Uint32& noPagesAllocated, Uint32 noPagesToAllocate);
- Uint32 nextHigherTwoLog(Uint32 input);
-
-// Private data
- Uint32 cfreepageList[16];
-
-//------------------------------------------------------------------------------------------------------
-// Page Mapper, convert logical page id's to physical page id's
-// The page mapper also handles the pages allocated to the fragment.
-//------------------------------------------------------------------------------------------------------
-//
-// Public methods
- Uint32 getRealpid(Fragrecord* regFragPtr, Uint32 logicalPageId);
- Uint32 getNoOfPages(Fragrecord* regFragPtr);
- void initPageRangeSize(Uint32 size);
- bool insertPageRangeTab(Fragrecord* regFragPtr,
- Uint32 startPageId,
- Uint32 noPages);
- void releaseFragPages(Fragrecord* regFragPtr);
- void initFragRange(Fragrecord* regFragPtr);
- void initializePageRange();
- Uint32 getEmptyPage(Fragrecord* regFragPtr);
- Uint32 allocFragPages(Fragrecord* regFragPtr, Uint32 noOfPagesAllocated);
- Uint32 get_empty_var_page(Fragrecord* frag_ptr);
-
-// Private methods
- Uint32 leafPageRangeFull(Fragrecord* regFragPtr, PageRangePtr currPageRangePtr);
- void releasePagerange(PageRangePtr regPRPtr);
- void seizePagerange(PageRangePtr& regPageRangePtr);
- void errorHandler(Uint32 errorCode);
- void allocMoreFragPages(Fragrecord* regFragPtr);
-
-// Private data
- Uint32 cfirstfreerange;
- PageRange *pageRange;
- Uint32 c_noOfFreePageRanges;
- Uint32 cnoOfPageRangeRec;
-
-//---------------------------------------------------------------
-// Variable Allocator
-// Allocates and deallocates tuples of fixed size on a fragment.
-//---------------------------------------------------------------
-//
-// Public methods
-
- void init_list_sizes(void);
-
-// Private methods
-
- Uint32 get_alloc_page(Fragrecord* const, Uint32);
- void update_free_page_list(Fragrecord* const, Ptr<Page>);
-
-#if 0
- Uint32 calc_free_list(const Tablerec* regTabPtr, Uint32 sz) const {
- return regTabPtr->m_disk_alloc_info.calc_page_free_bits(sz);
- }
-#endif
-
- Uint32 calculate_free_list_impl(Uint32) const ;
- void remove_free_page(Fragrecord*, Var_page*, Uint32);
- void insert_free_page(Fragrecord*, Var_page*, Uint32);
-
-//---------------------------------------------------------------
-// Fixed Allocator
-// Allocates and deallocates tuples of fixed size on a fragment.
-//---------------------------------------------------------------
-//
-// Public methods
- Uint32* alloc_var_rec(Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*);
- void free_var_rec(Fragrecord*, Tablerec*, Local_key*, Ptr<Page>);
- Uint32* alloc_var_part(Fragrecord*, Tablerec*, Uint32, Local_key*);
- int realloc_var_part(Fragrecord*, Tablerec*,
- PagePtr, Var_part_ref*, Uint32, Uint32);
-
- void validate_page(Tablerec*, Var_page* page);
-
- Uint32* alloc_fix_rec(Fragrecord*const, Tablerec*const, Local_key*,
- Uint32*);
- void free_fix_rec(Fragrecord*, Tablerec*, Local_key*, Fix_page*);
-
- Uint32* alloc_fix_rowid(Fragrecord*, Tablerec*, Local_key*, Uint32 *);
- Uint32* alloc_var_rowid(Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*);
-// Private methods
- void convertThPage(Fix_page* regPagePtr,
- Tablerec*,
- Uint32 mm);
-
- /**
- * Return offset
- */
- Uint32 alloc_tuple_from_page(Fragrecord* regFragPtr,
- Fix_page* regPagePtr);
-
-//---------------------------------------------------------------
-// Temporary variables used for storing commonly used variables
-// in certain modules
-//---------------------------------------------------------------
-
- Uint32 c_lcp_scan_op;
- FragrecordPtr fragptr;
- OperationrecPtr operPtr;
- TablerecPtr tabptr;
-
-// readAttributes and updateAttributes module
-//------------------------------------------------------------------------------------------------------
-// Common stored variables. Variables that have a valid value always.
-//------------------------------------------------------------------------------------------------------
- Attrbufrec *attrbufrec;
- Uint32 cfirstfreeAttrbufrec;
- Uint32 cnoOfAttrbufrec;
- Uint32 cnoFreeAttrbufrec;
-
- Fragoperrec *fragoperrec;
- Uint32 cfirstfreeFragopr;
- Uint32 cnoOfFragoprec;
-
- Fragrecord *fragrecord;
- Uint32 cfirstfreefrag;
- Uint32 cnoOfFragrec;
-
- HostBuffer *hostBuffer;
-
- ArrayPool<Operationrec> c_operation_pool;
-
- ArrayPool<Page> c_page_pool;
- Uint32 cnoOfAllocatedPages;
- Uint32 m_max_allocate_pages;
-
- /* read ahead in pages during disk order scan */
- Uint32 m_max_page_read_ahead;
-
- Tablerec *tablerec;
- Uint32 cnoOfTablerec;
-
- TableDescriptor *tableDescriptor;
- Uint32 cnoOfTabDescrRec;
-
- Uint32 cdata[32];
- Uint32 cdataPages[16];
- Uint32 cpackedListIndex;
- Uint32 cpackedList[MAX_NODES];
- Uint32 cfreeTdList[16];
- Uint32 clastBitMask;
- Uint32 clblPageCounter;
- Uint32 clblPagesPerTick;
- Uint32 clblPagesPerTickAfterSr;
- BlockReference clqhBlockref;
- Uint32 clqhUserpointer;
- Uint32 cminusOne;
- BlockReference cndbcntrRef;
- BlockReference cownref;
- Uint32 cownNodeId;
- Uint32 czero;
-
- // A little bit bigger to cover overwrites in copy algorithms (16384 real size).
-#define ZATTR_BUFFER_SIZE 16384
- Uint32 clogMemBuffer[ZATTR_BUFFER_SIZE + 16];
- Uint32 coutBuffer[ZATTR_BUFFER_SIZE + 16];
- Uint32 cinBuffer[ZATTR_BUFFER_SIZE + 16];
- Uint32 ctemp_page[ZWORDS_ON_PAGE];
- Uint32 ctemp_var_record[ZWORDS_ON_PAGE];
- Uint32 totNoOfPagesAllocated;
-
- // Trigger variables
- Uint32 c_maxTriggersPerTable;
- Uint32 c_memusage_report_frequency;
-
- Uint32 c_errorInsert4000TableId;
- Uint32 c_min_list_size[MAX_FREE_LIST + 1];
- Uint32 c_max_list_size[MAX_FREE_LIST + 1];
-
- void initGlobalTemporaryVars();
- void reportMemoryUsage(Signal* signal, int incDec);
-
-
-#ifdef VM_TRACE
- struct Th {
- Uint32 data[1];
- };
- friend class NdbOut& operator<<(NdbOut&, const Operationrec&);
- friend class NdbOut& operator<<(NdbOut&, const Th&);
-#endif
-
- void expand_tuple(KeyReqStruct*, Uint32 sizes[4], Tuple_header*org,
- const Tablerec*, bool disk);
- void shrink_tuple(KeyReqStruct*, Uint32 sizes[2], const Tablerec*,
- bool disk);
-
- Uint32* get_ptr(Var_part_ref);
- Uint32* get_ptr(PagePtr*, Var_part_ref);
- Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*);
- Uint32* get_dd_ptr(PagePtr*, const Local_key*, const Tablerec*);
-
- /**
- * prealloc space from disk
- * key.m_file_no contains file no
- * key.m_page_no contains disk page
- * key.m_page_idx contains byte preallocated
- */
- int disk_page_prealloc(Signal*, Ptr<Fragrecord>, Local_key*, Uint32);
- void disk_page_prealloc_dirty_page(Disk_alloc_info&,
- Ptr<Page>, Uint32, Uint32);
- void disk_page_prealloc_transit_page(Disk_alloc_info&,
- Ptr<Page_request>, Uint32, Uint32);
-
- void disk_page_abort_prealloc(Signal*, Fragrecord*,Local_key*, Uint32);
- void disk_page_abort_prealloc_callback(Signal*, Uint32, Uint32);
- void disk_page_abort_prealloc_callback_1(Signal*, Fragrecord*,
- PagePtr, Uint32);
-
- void disk_page_prealloc_callback(Signal*, Uint32, Uint32);
- void disk_page_prealloc_initial_callback(Signal*, Uint32, Uint32);
- void disk_page_prealloc_callback_common(Signal*,
- Ptr<Page_request>,
- Ptr<Fragrecord>,
- Ptr<Page>);
-
- void disk_page_alloc(Signal*,
- Tablerec*, Fragrecord*, Local_key*, PagePtr, Uint32);
- void disk_page_free(Signal*,
- Tablerec*, Fragrecord*, Local_key*, PagePtr, Uint32);
-
- void disk_page_commit_callback(Signal*, Uint32 opPtrI, Uint32 page_id);
-
- void disk_page_log_buffer_callback(Signal*, Uint32 opPtrI, Uint32);
-
- void disk_page_alloc_extent_log_buffer_callback(Signal*, Uint32, Uint32);
- void disk_page_free_extent_log_buffer_callback(Signal*, Uint32, Uint32);
-
- Uint64 disk_page_undo_alloc(Page*, const Local_key*,
- Uint32 sz, Uint32 gci, Uint32 logfile_group_id);
-
- Uint64 disk_page_undo_update(Page*, const Local_key*,
- const Uint32*, Uint32,
- Uint32 gci, Uint32 logfile_group_id);
-
- Uint64 disk_page_undo_free(Page*, const Local_key*,
- const Uint32*, Uint32 sz,
- Uint32 gci, Uint32 logfile_group_id);
-
- void undo_createtable_callback(Signal* signal, Uint32 opPtrI, Uint32 unused);
- void undo_createtable_logsync_callback(Signal* signal, Uint32, Uint32);
-
- void drop_table_log_buffer_callback(Signal*, Uint32, Uint32);
- void drop_table_logsync_callback(Signal*, Uint32, Uint32);
-
- void disk_page_set_dirty(Ptr<Page>);
- void restart_setup_page(Disk_alloc_info&, Ptr<Page>);
- void update_extent_pos(Disk_alloc_info&, Ptr<Extent_info>);
-
- /**
- * Disk restart code
- */
-public:
- int disk_page_load_hook(Uint32 page_id);
-
- void disk_page_unmap_callback(Uint32 when, Uint32 page, Uint32 dirty_count);
-
- int disk_restart_alloc_extent(Uint32 tableId, Uint32 fragId,
- const Local_key* key, Uint32 pages);
- void disk_restart_page_bits(Uint32 tableId, Uint32 fragId,
- const Local_key*, Uint32 bits);
- void disk_restart_undo(Signal* signal, Uint64 lsn,
- Uint32 type, const Uint32 * ptr, Uint32 len);
-
- struct Apply_undo
- {
- Uint32 m_type, m_len;
- const Uint32* m_ptr;
- Uint64 m_lsn;
- Ptr<Tablerec> m_table_ptr;
- Ptr<Fragrecord> m_fragment_ptr;
- Ptr<Page> m_page_ptr;
- Ptr<Extent_info> m_extent_ptr;
- Local_key m_key;
- };
-
- void disk_restart_lcp_id(Uint32 table, Uint32 frag, Uint32 lcpId);
-
-private:
- void disk_restart_undo_next(Signal*);
- void disk_restart_undo_lcp(Uint32, Uint32, Uint32 flag, Uint32 lcpId);
- void disk_restart_undo_callback(Signal* signal, Uint32, Uint32);
- void disk_restart_undo_alloc(Apply_undo*);
- void disk_restart_undo_update(Apply_undo*);
- void disk_restart_undo_free(Apply_undo*);
- void disk_restart_undo_page_bits(Signal*, Apply_undo*);
-
-#ifdef VM_TRACE
- void verify_page_lists(Disk_alloc_info&);
-#else
- void verify_page_lists(Disk_alloc_info&) {}
-#endif
-
- void findFirstOp(OperationrecPtr&);
- void commit_operation(Signal*, Uint32, Tuple_header*, PagePtr,
- Operationrec*, Fragrecord*, Tablerec*);
-
- void dealloc_tuple(Signal* signal, Uint32, Page*, Tuple_header*,
- Operationrec*, Fragrecord*, Tablerec*);
-
- int handle_size_change_after_update(KeyReqStruct* req_struct,
- Tuple_header* org,
- Operationrec*,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- Uint32 sizes[4]);
-
- /**
- * Setup all pointer on keyreqstruct to prepare for read
- * req_struct->m_tuple_ptr is set to tuple to read
- */
- void prepare_read(KeyReqStruct*, Tablerec* const, bool disk);
-};
-
-#if 0
-inline
-Uint32
-Dbtup::get_frag_page_id(Uint32 real_page_id)
-{
- PagePtr real_page_ptr;
- real_page_ptr.i= real_page_id;
- ptrCheckGuard(real_page_ptr, cnoOfPage, cpage);
- return real_page_ptr.p->frag_page_id;
-}
-#endif
-
-inline
-Dbtup::TransState
-Dbtup::get_trans_state(Operationrec * regOperPtr)
-{
- return (Dbtup::TransState)regOperPtr->op_struct.trans_state;
-}
-
-inline
-void
-Dbtup::set_trans_state(Operationrec* regOperPtr,
- Dbtup::TransState trans_state)
-{
- regOperPtr->op_struct.trans_state= (Uint32)trans_state;
-}
-
-inline
-Dbtup::TupleState
-Dbtup::get_tuple_state(Operationrec * regOperPtr)
-{
- return (Dbtup::TupleState)regOperPtr->op_struct.tuple_state;
-}
-
-inline
-void
-Dbtup::set_tuple_state(Operationrec* regOperPtr,
- Dbtup::TupleState tuple_state)
-{
- regOperPtr->op_struct.tuple_state= (Uint32)tuple_state;
-}
-
-
-inline
-Uint32
-Dbtup::decr_tup_version(Uint32 tup_version)
-{
- return (tup_version - 1) & ZTUP_VERSION_MASK;
-}
-
-inline
-Dbtup::ChangeMaskState
-Dbtup::get_change_mask_state(Operationrec * regOperPtr)
-{
- return (Dbtup::ChangeMaskState)regOperPtr->op_struct.change_mask_state;
-}
-
-inline
-void
-Dbtup::set_change_mask_state(Operationrec * regOperPtr,
- ChangeMaskState new_state)
-{
- regOperPtr->op_struct.change_mask_state= (Uint32)new_state;
-}
-
-inline
-void
-Dbtup::update_change_mask_info(KeyReqStruct * req_struct,
- Operationrec * regOperPtr)
-{
- if (req_struct->max_attr_id_updated == 0) {
- if (get_change_mask_state(regOperPtr) == USE_SAVED_CHANGE_MASK) {
- // add new changes
- regOperPtr->saved_change_mask[0] |= req_struct->changeMask.getWord(0);
- regOperPtr->saved_change_mask[1] |= req_struct->changeMask.getWord(1);
- }
- } else {
- if (req_struct->no_changed_attrs < 16) {
- set_change_mask_state(regOperPtr, RECALCULATE_CHANGE_MASK);
- } else {
- set_change_mask_state(regOperPtr, SET_ALL_MASK);
- }
- }
-}
-
-inline
-Uint32*
-Dbtup::get_ptr(Var_part_ref ref)
-{
- Ptr<Page> tmp;
- return get_ptr(&tmp, ref);
-}
-
-inline
-Uint32*
-Dbtup::get_ptr(Ptr<Page>* pagePtr, Var_part_ref ref)
-{
- PagePtr tmp;
- Local_key key;
- ref.copyout(&key);
- tmp.i = key.m_page_no;
-
- c_page_pool.getPtr(tmp);
- memcpy(pagePtr, &tmp, sizeof(tmp));
- return ((Var_page*)tmp.p)->get_ptr(key.m_page_idx);
-}
-
-inline
-Uint32*
-Dbtup::get_ptr(PagePtr* pagePtr,
- const Local_key* key, const Tablerec* regTabPtr)
-{
- PagePtr tmp;
- tmp.i= key->m_page_no;
- c_page_pool.getPtr(tmp);
- memcpy(pagePtr, &tmp, sizeof(tmp));
-
- return ((Fix_page*)tmp.p)->
- get_ptr(key->m_page_idx, regTabPtr->m_offsets[MM].m_fix_header_size);
-}
-
-inline
-Uint32*
-Dbtup::get_dd_ptr(PagePtr* pagePtr,
- const Local_key* key, const Tablerec* regTabPtr)
-{
- PagePtr tmp;
- tmp.i= key->m_page_no;
- tmp.p= (Page*)m_global_page_pool.getPtr(tmp.i);
- memcpy(pagePtr, &tmp, sizeof(tmp));
-
- if(regTabPtr->m_attributes[DD].m_no_of_varsize)
- return ((Var_page*)tmp.p)->get_ptr(key->m_page_idx);
- else
- return ((Fix_page*)tmp.p)->
- get_ptr(key->m_page_idx, regTabPtr->m_offsets[DD].m_fix_header_size);
-}
-
-NdbOut&
-operator<<(NdbOut&, const Dbtup::Tablerec&);
-
-inline
-bool Dbtup::find_savepoint(OperationrecPtr& loopOpPtr, Uint32 savepointId)
-{
- while (true) {
- if (savepointId > loopOpPtr.p->savepointId) {
- jam();
- return true;
- }
- loopOpPtr.i = loopOpPtr.p->prevActiveOp;
- if (loopOpPtr.i == RNIL) {
- break;
- }
- c_operation_pool.getPtr(loopOpPtr);
- }
- return false;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
deleted file mode 100644
index 7a000eb5042..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_ABORT_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-
-void Dbtup::freeAllAttrBuffers(Operationrec* const regOperPtr)
-{
- if (regOperPtr->storedProcedureId == RNIL) {
- jam();
- freeAttrinbufrec(regOperPtr->firstAttrinbufrec);
- } else {
- jam();
- StoredProcPtr storedPtr;
- c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->storedProcedureId);
- ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
- storedPtr.p->storedCounter--;
- regOperPtr->storedProcedureId = ZNIL;
- }//if
- regOperPtr->firstAttrinbufrec = RNIL;
- regOperPtr->lastAttrinbufrec = RNIL;
- regOperPtr->m_any_value = 0;
-}//Dbtup::freeAllAttrBuffers()
-
-void Dbtup::freeAttrinbufrec(Uint32 anAttrBuf)
-{
- Uint32 Ttemp;
- AttrbufrecPtr localAttrBufPtr;
- Uint32 RnoFree = cnoFreeAttrbufrec;
- localAttrBufPtr.i = anAttrBuf;
- while (localAttrBufPtr.i != RNIL) {
- jam();
- ptrCheckGuard(localAttrBufPtr, cnoOfAttrbufrec, attrbufrec);
- Ttemp = localAttrBufPtr.p->attrbuf[ZBUF_NEXT];
- localAttrBufPtr.p->attrbuf[ZBUF_NEXT] = cfirstfreeAttrbufrec;
- cfirstfreeAttrbufrec = localAttrBufPtr.i;
- localAttrBufPtr.i = Ttemp;
- RnoFree++;
- }//if
- cnoFreeAttrbufrec = RnoFree;
-}//Dbtup::freeAttrinbufrec()
-
-/**
- * Abort abort this operation and all after (nextActiveOp's)
- */
-void Dbtup::execTUP_ABORTREQ(Signal* signal)
-{
- jamEntry();
- do_tup_abortreq(signal, 0);
-}
-
-void Dbtup::do_tup_abortreq(Signal* signal, Uint32 flags)
-{
- OperationrecPtr regOperPtr;
- FragrecordPtr regFragPtr;
- TablerecPtr regTabPtr;
-
- regOperPtr.i = signal->theData[0];
- c_operation_pool.getPtr(regOperPtr);
- TransState trans_state= get_trans_state(regOperPtr.p);
- ndbrequire((trans_state == TRANS_STARTED) ||
- (trans_state == TRANS_TOO_MUCH_AI) ||
- (trans_state == TRANS_ERROR_WAIT_TUPKEYREQ) ||
- (trans_state == TRANS_IDLE));
- if (regOperPtr.p->op_struct.op_type == ZREAD) {
- jam();
- freeAllAttrBuffers(regOperPtr.p);
- initOpConnection(regOperPtr.p);
- return;
- }//if
-
- regFragPtr.i = regOperPtr.p->fragmentPtr;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
-
- regTabPtr.i = regFragPtr.p->fragTableId;
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
- if (get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
- {
- jam();
- if (!regTabPtr.p->tuxCustomTriggers.isEmpty() &&
- (flags & ZSKIP_TUX_TRIGGERS) == 0)
- executeTuxAbortTriggers(signal,
- regOperPtr.p,
- regFragPtr.p,
- regTabPtr.p);
-
- OperationrecPtr loopOpPtr;
- loopOpPtr.i = regOperPtr.p->nextActiveOp;
- while (loopOpPtr.i != RNIL) {
- jam();
- c_operation_pool.getPtr(loopOpPtr);
- if (get_tuple_state(loopOpPtr.p) != TUPLE_ALREADY_ABORTED &&
- !regTabPtr.p->tuxCustomTriggers.isEmpty() &&
- (flags & ZSKIP_TUX_TRIGGERS) == 0) {
- jam();
- executeTuxAbortTriggers(signal,
- loopOpPtr.p,
- regFragPtr.p,
- regTabPtr.p);
- }
- set_tuple_state(loopOpPtr.p, TUPLE_ALREADY_ABORTED);
- loopOpPtr.i = loopOpPtr.p->nextActiveOp;
- }
- }
-
- PagePtr page;
- Tuple_header *tuple_ptr= (Tuple_header*)
- get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
-
- Uint32 bits= tuple_ptr->m_header_bits;
- if(regOperPtr.p->op_struct.op_type != ZDELETE)
- {
- Tuple_header *copy= (Tuple_header*)
- c_undo_buffer.get_ptr(&regOperPtr.p->m_copy_tuple_location);
-
- if(regOperPtr.p->op_struct.m_disk_preallocated)
- {
- jam();
- Local_key key;
- memcpy(&key, copy->get_disk_ref_ptr(regTabPtr.p), sizeof(key));
- disk_page_abort_prealloc(signal, regFragPtr.p, &key, key.m_page_idx);
- }
-
-
- Uint32 copy_bits= copy->m_header_bits;
- if(! (bits & Tuple_header::ALLOC))
- {
- if(copy_bits & Tuple_header::MM_GROWN)
- {
- if (0) ndbout_c("abort grow");
- Ptr<Page> vpage;
- Uint32 idx= regOperPtr.p->m_tuple_location.m_page_idx;
- Uint32 mm_vars= regTabPtr.p->m_attributes[MM].m_no_of_varsize;
- Uint32 *var_part;
-
- ndbassert(tuple_ptr->m_header_bits & Tuple_header::CHAINED_ROW);
-
- Var_part_ref *ref = tuple_ptr->get_var_part_ref_ptr(regTabPtr.p);
-
- Local_key tmp;
- ref->copyout(&tmp);
-
- idx= tmp.m_page_idx;
- var_part= get_ptr(&vpage, *ref);
- Var_page* pageP = (Var_page*)vpage.p;
- Uint32 len= pageP->get_entry_len(idx) & ~Var_page::CHAIN;
- Uint32 sz = ((((mm_vars + 1) << 1) + (((Uint16*)var_part)[mm_vars]) + 3)>> 2);
- ndbassert(sz <= len);
- pageP->shrink_entry(idx, sz);
- update_free_page_list(regFragPtr.p, vpage);
- }
- else if(bits & Tuple_header::MM_SHRINK)
- {
- if (0) ndbout_c("abort shrink");
- }
- }
- else if (regOperPtr.p->is_first_operation() &&
- regOperPtr.p->is_last_operation())
- {
- /**
- * Aborting last operation that performed ALLOC
- */
- tuple_ptr->m_header_bits &= ~(Uint32)Tuple_header::ALLOC;
- tuple_ptr->m_header_bits |= Tuple_header::FREED;
- }
- }
- else if (regOperPtr.p->is_first_operation() &&
- regOperPtr.p->is_last_operation())
- {
- if (bits & Tuple_header::ALLOC)
- {
- tuple_ptr->m_header_bits &= ~(Uint32)Tuple_header::ALLOC;
- tuple_ptr->m_header_bits |= Tuple_header::FREED;
- }
- }
-
- if(regOperPtr.p->is_first_operation() && regOperPtr.p->is_last_operation())
- {
- if (regOperPtr.p->m_undo_buffer_space)
- c_lgman->free_log_space(regFragPtr.p->m_logfile_group_id,
- regOperPtr.p->m_undo_buffer_space);
- }
-
- removeActiveOpList(regOperPtr.p, tuple_ptr);
- initOpConnection(regOperPtr.p);
-}
-
-/* **************************************************************** */
-/* ********************** TRANSACTION ERROR MODULE **************** */
-/* **************************************************************** */
-int Dbtup::TUPKEY_abort(Signal* signal, int error_type)
-{
- switch(error_type) {
- case 1:
-//tmupdate_alloc_error:
- terrorCode= ZMEM_NOMEM_ERROR;
- jam();
- break;
-
- case 15:
- jam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
- case 16:
- jam();
- terrorCode = ZTRY_TO_UPDATE_ERROR;
- break;
-
- case 17:
- jam();
- terrorCode = ZNO_ILLEGAL_NULL_ATTR;
- break;
-
- case 19:
- jam();
- terrorCode = ZTRY_TO_UPDATE_ERROR;
- break;
-
- case 20:
- jam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
- case 22:
- jam();
- terrorCode = ZTOTAL_LEN_ERROR;
- break;
-
- case 23:
- jam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
- case 24:
- jam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
- case 26:
- jam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
- case 27:
- jam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
- case 28:
- jam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
- case 29:
- jam();
- break;
-
- case 30:
- jam();
- terrorCode = ZCALL_ERROR;
- break;
-
- case 31:
- jam();
- terrorCode = ZSTACK_OVERFLOW_ERROR;
- break;
-
- case 32:
- jam();
- terrorCode = ZSTACK_UNDERFLOW_ERROR;
- break;
-
- case 33:
- jam();
- terrorCode = ZNO_INSTRUCTION_ERROR;
- break;
-
- case 34:
- jam();
- terrorCode = ZOUTSIDE_OF_PROGRAM_ERROR;
- break;
-
- case 35:
- jam();
- terrorCode = ZTOO_MANY_INSTRUCTIONS_ERROR;
- break;
-
- case 38:
- jam();
- terrorCode = ZTEMPORARY_RESOURCE_FAILURE;
- break;
-
- case 39:
- if (get_trans_state(operPtr.p) == TRANS_TOO_MUCH_AI) {
- jam();
- terrorCode = ZTOO_MUCH_ATTRINFO_ERROR;
- } else if (get_trans_state(operPtr.p) == TRANS_ERROR_WAIT_TUPKEYREQ) {
- jam();
- terrorCode = ZSEIZE_ATTRINBUFREC_ERROR;
- } else {
- ndbrequire(false);
- }//if
- break;
- case 40:
- jam();
- terrorCode = ZUNSUPPORTED_BRANCH;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- tupkeyErrorLab(signal);
- return -1;
-}
-
-void Dbtup::early_tupkey_error(Signal* signal)
-{
- Operationrec * const regOperPtr = operPtr.p;
- ndbrequire(!regOperPtr->op_struct.in_active_list);
- set_trans_state(regOperPtr, TRANS_IDLE);
- set_tuple_state(regOperPtr, TUPLE_PREPARED);
- initOpConnection(regOperPtr);
- send_TUPKEYREF(signal, regOperPtr);
-}
-
-void Dbtup::tupkeyErrorLab(Signal* signal)
-{
- Operationrec * const regOperPtr = operPtr.p;
- set_trans_state(regOperPtr, TRANS_IDLE);
- set_tuple_state(regOperPtr, TUPLE_PREPARED);
-
- FragrecordPtr fragPtr;
- fragPtr.i= regOperPtr->fragmentPtr;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- TablerecPtr tabPtr;
- tabPtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- if (regOperPtr->m_undo_buffer_space &&
- (regOperPtr->is_first_operation() && regOperPtr->is_last_operation()))
- {
- c_lgman->free_log_space(fragPtr.p->m_logfile_group_id,
- regOperPtr->m_undo_buffer_space);
- }
-
- Uint32 *ptr = 0;
- if (!regOperPtr->m_tuple_location.isNull())
- {
- PagePtr tmp;
- ptr= get_ptr(&tmp, &regOperPtr->m_tuple_location, tabPtr.p);
- }
-
-
- removeActiveOpList(regOperPtr, (Tuple_header*)ptr);
- initOpConnection(regOperPtr);
- send_TUPKEYREF(signal, regOperPtr);
-}
-
-void Dbtup::send_TUPKEYREF(Signal* signal,
- Operationrec* const regOperPtr)
-{
- TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtrSend();
- tupKeyRef->userRef = regOperPtr->userpointer;
- tupKeyRef->errorCode = terrorCode;
- sendSignal(DBLQH_REF, GSN_TUPKEYREF, signal,
- TupKeyRef::SignalLength, JBB);
-}
-
-/**
- * Unlink one operation from the m_operation_ptr_i list in the tuple.
- */
-void Dbtup::removeActiveOpList(Operationrec* const regOperPtr,
- Tuple_header *tuple_ptr)
-{
- OperationrecPtr raoOperPtr;
-
- if(!regOperPtr->m_copy_tuple_location.isNull())
- {
- jam();
- c_undo_buffer.free_copy_tuple(&regOperPtr->m_copy_tuple_location);
- }
-
- if (regOperPtr->op_struct.in_active_list) {
- regOperPtr->op_struct.in_active_list= false;
- if (regOperPtr->nextActiveOp != RNIL) {
- jam();
- raoOperPtr.i= regOperPtr->nextActiveOp;
- c_operation_pool.getPtr(raoOperPtr);
- raoOperPtr.p->prevActiveOp= regOperPtr->prevActiveOp;
- } else {
- jam();
- tuple_ptr->m_operation_ptr_i = regOperPtr->prevActiveOp;
- }
- if (regOperPtr->prevActiveOp != RNIL) {
- jam();
- raoOperPtr.i= regOperPtr->prevActiveOp;
- c_operation_pool.getPtr(raoOperPtr);
- raoOperPtr.p->nextActiveOp= regOperPtr->nextActiveOp;
- }
- regOperPtr->prevActiveOp= RNIL;
- regOperPtr->nextActiveOp= RNIL;
- }
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
deleted file mode 100644
index 2f8151acca1..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_BUFFER_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <signaldata/TransIdAI.hpp>
-
-void Dbtup::execSEND_PACKED(Signal* signal)
-{
- Uint16 hostId;
- Uint32 i;
- Uint32 TpackedListIndex= cpackedListIndex;
- jamEntry();
- for (i= 0; i < TpackedListIndex; i++) {
- jam();
- hostId= cpackedList[i];
- ndbrequire((hostId - 1) < (MAX_NODES - 1)); // Also check not zero
- Uint32 TpacketTA= hostBuffer[hostId].noOfPacketsTA;
- if (TpacketTA != 0) {
- jam();
- BlockReference TBref= numberToRef(API_PACKED, hostId);
- Uint32 TpacketLen= hostBuffer[hostId].packetLenTA;
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &hostBuffer[hostId].packetBufferTA[0],
- TpacketLen);
- sendSignal(TBref, GSN_TRANSID_AI, signal, TpacketLen, JBB);
- hostBuffer[hostId].noOfPacketsTA= 0;
- hostBuffer[hostId].packetLenTA= 0;
- }
- hostBuffer[hostId].inPackedList= false;
- }//for
- cpackedListIndex= 0;
-}
-
-void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
- Uint32 Tlen)
-{
- if (Tlen == 3)
- return;
-
- Uint32 hostId= refToNode(aRef);
- Uint32 Theader= ((refToBlock(aRef) << 16)+(Tlen-3));
-
- ndbrequire(hostId < MAX_NODES);
- Uint32 TpacketLen= hostBuffer[hostId].packetLenTA;
- Uint32 TnoOfPackets= hostBuffer[hostId].noOfPacketsTA;
- Uint32 sig0= signal->theData[0];
- Uint32 sig1= signal->theData[1];
- Uint32 sig2= signal->theData[2];
-
- BlockReference TBref= numberToRef(API_PACKED, hostId);
-
- if ((Tlen + TpacketLen + 1) <= 25) {
-// ----------------------------------------------------------------
-// There is still space in the buffer. We will copy it into the
-// buffer.
-// ----------------------------------------------------------------
- jam();
- updatePackedList(signal, hostId);
- } else if (false && TnoOfPackets == 1) {
-// ----------------------------------------------------------------
-// The buffer is full and there was only one packet buffered. We
-// will send this as a normal signal.
-// ----------------------------------------------------------------
- Uint32 TnewRef= numberToRef((hostBuffer[hostId].packetBufferTA[0] >> 16),
- hostId);
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &hostBuffer[hostId].packetBufferTA[1],
- TpacketLen - 1);
- sendSignal(TnewRef, GSN_TRANSID_AI, signal, (TpacketLen - 1), JBB);
- TpacketLen= 0;
- TnoOfPackets= 0;
- } else {
-// ----------------------------------------------------------------
-// The buffer is full but at least two packets. Send those in
-// packed form.
-// ----------------------------------------------------------------
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &hostBuffer[hostId].packetBufferTA[0],
- TpacketLen);
- sendSignal(TBref, GSN_TRANSID_AI, signal, TpacketLen, JBB);
- TpacketLen= 0;
- TnoOfPackets= 0;
- }
-// ----------------------------------------------------------------
-// Copy the signal into the buffer
-// ----------------------------------------------------------------
- hostBuffer[hostId].packetBufferTA[TpacketLen + 0]= Theader;
- hostBuffer[hostId].packetBufferTA[TpacketLen + 1]= sig0;
- hostBuffer[hostId].packetBufferTA[TpacketLen + 2]= sig1;
- hostBuffer[hostId].packetBufferTA[TpacketLen + 3]= sig2;
- hostBuffer[hostId].noOfPacketsTA= TnoOfPackets + 1;
- hostBuffer[hostId].packetLenTA= Tlen + TpacketLen + 1;
- MEMCOPY_NO_WORDS(&hostBuffer[hostId].packetBufferTA[TpacketLen + 4],
- &signal->theData[25],
- Tlen - 3);
-}
-
-void Dbtup::updatePackedList(Signal* signal, Uint16 hostId)
-{
- if (hostBuffer[hostId].inPackedList == false) {
- Uint32 TpackedListIndex= cpackedListIndex;
- jam();
- hostBuffer[hostId].inPackedList= true;
- cpackedList[TpackedListIndex]= hostId;
- cpackedListIndex= TpackedListIndex + 1;
- }
-}
-
-/* ---------------------------------------------------------------- */
-/* ----------------------- SEND READ ATTRINFO --------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::sendReadAttrinfo(Signal* signal,
- KeyReqStruct *req_struct,
- Uint32 ToutBufIndex,
- const Operationrec *regOperPtr)
-{
- if(ToutBufIndex == 0)
- return;
-
- const BlockReference recBlockref= req_struct->rec_blockref;
- const Uint32 block= refToBlock(recBlockref);
- const Uint32 nodeId= refToNode(recBlockref);
-
- bool connectedToNode= getNodeInfo(nodeId).m_connected;
- const Uint32 type= getNodeInfo(nodeId).m_type;
- bool is_api= (type >= NodeInfo::API && type <= NodeInfo::MGM);
- bool old_dest= (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
- Uint32 TpacketLen= hostBuffer[nodeId].packetLenTA;
- Uint32 TpacketTA= hostBuffer[nodeId].noOfPacketsTA;
-
- if (ERROR_INSERTED(4006) && (nodeId != getOwnNodeId())){
- // Use error insert to turn routing on
- jam();
- connectedToNode= false;
- }
-
- Uint32 sig0= req_struct->tc_operation_ptr;
- Uint32 sig1= req_struct->trans_id1;
- Uint32 sig2= req_struct->trans_id2;
-
- TransIdAI * transIdAI= (TransIdAI *)signal->getDataPtrSend();
- transIdAI->connectPtr= sig0;
- transIdAI->transId[0]= sig1;
- transIdAI->transId[1]= sig2;
-
- if (connectedToNode){
- /**
- * Own node -> execute direct
- */
- if(nodeId != getOwnNodeId()){
- jam();
-
- /**
- * Send long sig
- */
- if (ToutBufIndex >= 22 && is_api && !old_dest) {
- jam();
- /**
- * Flush buffer so that order is maintained
- */
- if (TpacketTA != 0) {
- jam();
- BlockReference TBref = numberToRef(API_PACKED, nodeId);
- MEMCOPY_NO_WORDS(&signal->theData[0],
- &hostBuffer[nodeId].packetBufferTA[0],
- TpacketLen);
- sendSignal(TBref, GSN_TRANSID_AI, signal, TpacketLen, JBB);
- hostBuffer[nodeId].noOfPacketsTA = 0;
- hostBuffer[nodeId].packetLenTA = 0;
- transIdAI->connectPtr = sig0;
- transIdAI->transId[0] = sig1;
- transIdAI->transId[1] = sig2;
- }//if
- LinearSectionPtr ptr[3];
- ptr[0].p= &signal->theData[25];
- ptr[0].sz= ToutBufIndex;
- sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3, JBB, ptr, 1);
- return;
- }
-
- /**
- * short sig + api -> buffer
- */
-#ifndef NDB_NO_DROPPED_SIGNAL
- if (ToutBufIndex < 22 && is_api){
- jam();
- bufferTRANSID_AI(signal, recBlockref, 3+ToutBufIndex);
- return;
- }
-#endif
-
- /**
- * rest -> old send sig
- */
- Uint32 * src= signal->theData+25;
- if (ToutBufIndex >= 22){
- do {
- jam();
- MEMCOPY_NO_WORDS(&signal->theData[3], src, 22);
- sendSignal(recBlockref, GSN_TRANSID_AI, signal, 25, JBB);
- ToutBufIndex -= 22;
- src += 22;
- } while(ToutBufIndex >= 22);
- }
-
- if (ToutBufIndex > 0){
- jam();
- MEMCOPY_NO_WORDS(&signal->theData[3], src, ToutBufIndex);
- sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3+ToutBufIndex, JBB);
- }
- return;
- }
- EXECUTE_DIRECT(block, GSN_TRANSID_AI, signal, 3 + ToutBufIndex);
- jamEntry();
- return;
- }
-
- /**
- * If this node does not have a direct connection
- * to the receiving node we want to send the signals
- * routed via the node that controls this read
- */
- Uint32 routeBlockref= req_struct->TC_ref;
-
- if (true){ // TODO is_api && !old_dest){
- jam();
- transIdAI->attrData[0]= recBlockref;
- LinearSectionPtr ptr[3];
- ptr[0].p= &signal->theData[25];
- ptr[0].sz= ToutBufIndex;
- sendSignal(routeBlockref, GSN_TRANSID_AI_R, signal, 4, JBB, ptr, 1);
- return;
- }
-
- /**
- * Fill in a TRANSID_AI signal, use last word to store
- * final destination and send it to route node
- * as signal TRANSID_AI_R (R as in Routed)
- */
- Uint32 tot= ToutBufIndex;
- Uint32 sent= 0;
- Uint32 maxLen= TransIdAI::DataLength - 1;
- while (sent < tot) {
- jam();
- Uint32 dataLen= (tot - sent > maxLen) ? maxLen : tot - sent;
- Uint32 sigLen= dataLen + TransIdAI::HeaderLength + 1;
- MEMCOPY_NO_WORDS(&transIdAI->attrData,
- &signal->theData[25+sent],
- dataLen);
- // Set final destination in last word
- transIdAI->attrData[dataLen]= recBlockref;
-
- sendSignal(routeBlockref, GSN_TRANSID_AI_R,
- signal, sigLen, JBB);
- sent += dataLen;
- }
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
deleted file mode 100644
index d65ebf26eee..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
+++ /dev/null
@@ -1,749 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_COMMIT_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <signaldata/TupCommit.hpp>
-#include "../dblqh/Dblqh.hpp"
-
-void Dbtup::execTUP_DEALLOCREQ(Signal* signal)
-{
- TablerecPtr regTabPtr;
- FragrecordPtr regFragPtr;
- Uint32 frag_page_id, frag_id;
-
- jamEntry();
-
- frag_id= signal->theData[0];
- regTabPtr.i= signal->theData[1];
- frag_page_id= signal->theData[2];
- Uint32 page_index= signal->theData[3];
-
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
- getFragmentrec(regFragPtr, frag_id, regTabPtr.p);
- ndbassert(regFragPtr.p != NULL);
-
- if (! (((frag_page_id << MAX_TUPLES_BITS) + page_index) == ~ (Uint32) 0))
- {
- Local_key tmp;
- tmp.m_page_no= getRealpid(regFragPtr.p, frag_page_id);
- tmp.m_page_idx= page_index;
-
- PagePtr pagePtr;
- Tuple_header* ptr= (Tuple_header*)get_ptr(&pagePtr, &tmp, regTabPtr.p);
-
- ndbassert(ptr->m_header_bits & Tuple_header::FREE);
-
- if (ptr->m_header_bits & Tuple_header::LCP_KEEP)
- {
- ndbassert(! (ptr->m_header_bits & Tuple_header::FREED));
- ptr->m_header_bits |= Tuple_header::FREED;
- return;
- }
-
- if (regTabPtr.p->m_attributes[MM].m_no_of_varsize)
- {
- jam();
- free_var_rec(regFragPtr.p, regTabPtr.p, &tmp, pagePtr);
- } else {
- free_fix_rec(regFragPtr.p, regTabPtr.p, &tmp, (Fix_page*)pagePtr.p);
- }
- }
-}
-
-void Dbtup::execTUP_WRITELOG_REQ(Signal* signal)
-{
- jamEntry();
- OperationrecPtr loopOpPtr;
- loopOpPtr.i= signal->theData[0];
- Uint32 gci= signal->theData[1];
- c_operation_pool.getPtr(loopOpPtr);
- while (loopOpPtr.p->prevActiveOp != RNIL) {
- jam();
- loopOpPtr.i= loopOpPtr.p->prevActiveOp;
- c_operation_pool.getPtr(loopOpPtr);
- }
- do {
- ndbrequire(get_trans_state(loopOpPtr.p) == TRANS_STARTED);
- signal->theData[0]= loopOpPtr.p->userpointer;
- signal->theData[1]= gci;
- if (loopOpPtr.p->nextActiveOp == RNIL) {
- jam();
- EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 2);
- return;
- }
- jam();
- EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 2);
- jamEntry();
- loopOpPtr.i= loopOpPtr.p->nextActiveOp;
- c_operation_pool.getPtr(loopOpPtr);
- } while (true);
-}
-
-/* ---------------------------------------------------------------- */
-/* INITIALIZATION OF ONE CONNECTION RECORD TO PREPARE FOR NEXT OP. */
-/* ---------------------------------------------------------------- */
-void Dbtup::initOpConnection(Operationrec* regOperPtr)
-{
- set_tuple_state(regOperPtr, TUPLE_ALREADY_ABORTED);
- set_trans_state(regOperPtr, TRANS_IDLE);
- regOperPtr->currentAttrinbufLen= 0;
- regOperPtr->op_struct.op_type= ZREAD;
- regOperPtr->op_struct.m_disk_preallocated= 0;
- regOperPtr->op_struct.m_load_diskpage_on_commit= 0;
- regOperPtr->op_struct.m_wait_log_buffer= 0;
- regOperPtr->op_struct.in_active_list = false;
- regOperPtr->m_undo_buffer_space= 0;
-}
-
-static
-inline
-bool
-operator>(const Local_key& key1, const Local_key& key2)
-{
- return key1.m_page_no > key2.m_page_no ||
- (key1.m_page_no == key2.m_page_no && key1.m_page_idx > key2.m_page_idx);
-}
-
-void
-Dbtup::dealloc_tuple(Signal* signal,
- Uint32 gci,
- Page* page,
- Tuple_header* ptr,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr)
-{
- Uint32 lcpScan_ptr_i= regFragPtr->m_lcp_scan_op;
- Uint32 lcp_keep_list = regFragPtr->m_lcp_keep_list;
-
- Uint32 bits = ptr->m_header_bits;
- Uint32 extra_bits = Tuple_header::FREED;
- if (bits & Tuple_header::DISK_PART)
- {
- jam();
- Local_key disk;
- memcpy(&disk, ptr->get_disk_ref_ptr(regTabPtr), sizeof(disk));
- PagePtr tmpptr;
- tmpptr.i = m_pgman.m_ptr.i;
- tmpptr.p = reinterpret_cast<Page*>(m_pgman.m_ptr.p);
- disk_page_free(signal, regTabPtr, regFragPtr,
- &disk, tmpptr, gci);
- }
-
- if (! (bits & (Tuple_header::LCP_SKIP | Tuple_header::ALLOC)) &&
- lcpScan_ptr_i != RNIL)
- {
- jam();
- ScanOpPtr scanOp;
- c_scanOpPool.getPtr(scanOp, lcpScan_ptr_i);
- Local_key rowid = regOperPtr->m_tuple_location;
- Local_key scanpos = scanOp.p->m_scanPos.m_key;
- rowid.m_page_no = page->frag_page_id;
- if (rowid > scanpos)
- {
- jam();
- extra_bits = Tuple_header::LCP_KEEP; // Note REMOVE FREE
- ptr->m_operation_ptr_i = lcp_keep_list;
- regFragPtr->m_lcp_keep_list = rowid.ref();
- }
- }
-
- ptr->m_header_bits = bits | extra_bits;
-
- if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
- {
- jam();
- * ptr->get_mm_gci(regTabPtr) = gci;
- }
-}
-
-void
-Dbtup::commit_operation(Signal* signal,
- Uint32 gci,
- Tuple_header* tuple_ptr,
- PagePtr pagePtr,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr)
-{
- ndbassert(regOperPtr->op_struct.op_type != ZDELETE);
-
- Uint32 lcpScan_ptr_i= regFragPtr->m_lcp_scan_op;
- Uint32 save= tuple_ptr->m_operation_ptr_i;
- Uint32 bits= tuple_ptr->m_header_bits;
-
- Tuple_header *disk_ptr= 0;
- Tuple_header *copy= (Tuple_header*)
- c_undo_buffer.get_ptr(&regOperPtr->m_copy_tuple_location);
-
- Uint32 copy_bits= copy->m_header_bits;
-
- Uint32 fixsize= regTabPtr->m_offsets[MM].m_fix_header_size;
- Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
- if(mm_vars == 0)
- {
- jam();
- memcpy(tuple_ptr, copy, 4*fixsize);
- disk_ptr= (Tuple_header*)(((Uint32*)copy)+fixsize);
- }
- else
- {
- jam();
- /**
- * Var_part_ref is only stored in *allocated* tuple
- * so memcpy from copy, will over write it...
- * hence subtle copyout/assign...
- */
- Local_key tmp;
- Var_part_ref *ref= tuple_ptr->get_var_part_ref_ptr(regTabPtr);
- ref->copyout(&tmp);
-
- memcpy(tuple_ptr, copy, 4*fixsize);
- ref->assign(&tmp);
-
- PagePtr vpagePtr;
- Uint32 *dst= get_ptr(&vpagePtr, *ref);
- Var_page* vpagePtrP = (Var_page*)vpagePtr.p;
- Uint32 *src= copy->get_end_of_fix_part_ptr(regTabPtr);
- Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)src)[mm_vars]);
- ndbassert(4*vpagePtrP->get_entry_len(tmp.m_page_idx) >= sz);
- memcpy(dst, src, sz);
-
- copy_bits |= Tuple_header::CHAINED_ROW;
-
- if(copy_bits & Tuple_header::MM_SHRINK)
- {
- jam();
- vpagePtrP->shrink_entry(tmp.m_page_idx, (sz + 3) >> 2);
- update_free_page_list(regFragPtr, vpagePtr);
- }
-
- disk_ptr = (Tuple_header*)(((Uint32*)copy)+fixsize+((sz + 3) >> 2));
- }
-
- if (regTabPtr->m_no_of_disk_attributes &&
- (copy_bits & Tuple_header::DISK_INLINE))
- {
- jam();
- Local_key key;
- memcpy(&key, copy->get_disk_ref_ptr(regTabPtr), sizeof(Local_key));
- Uint32 logfile_group_id= regFragPtr->m_logfile_group_id;
-
- PagePtr diskPagePtr = *(PagePtr*)&m_pgman.m_ptr;
- ndbassert(diskPagePtr.p->m_page_no == key.m_page_no);
- ndbassert(diskPagePtr.p->m_file_no == key.m_file_no);
- Uint32 sz, *dst;
- if(copy_bits & Tuple_header::DISK_ALLOC)
- {
- jam();
- disk_page_alloc(signal, regTabPtr, regFragPtr, &key, diskPagePtr, gci);
- }
-
- if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0)
- {
- jam();
- sz= regTabPtr->m_offsets[DD].m_fix_header_size;
- dst= ((Fix_page*)diskPagePtr.p)->get_ptr(key.m_page_idx, sz);
- }
- else
- {
- jam();
- dst= ((Var_page*)diskPagePtr.p)->get_ptr(key.m_page_idx);
- sz= ((Var_page*)diskPagePtr.p)->get_entry_len(key.m_page_idx);
- }
-
- if(! (copy_bits & Tuple_header::DISK_ALLOC))
- {
- jam();
- disk_page_undo_update(diskPagePtr.p,
- &key, dst, sz, gci, logfile_group_id);
- }
-
- memcpy(dst, disk_ptr, 4*sz);
- memcpy(tuple_ptr->get_disk_ref_ptr(regTabPtr), &key, sizeof(Local_key));
-
- ndbassert(! (disk_ptr->m_header_bits & Tuple_header::FREE));
- copy_bits |= Tuple_header::DISK_PART;
- }
-
- if(lcpScan_ptr_i != RNIL && (bits & Tuple_header::ALLOC))
- {
- jam();
- ScanOpPtr scanOp;
- c_scanOpPool.getPtr(scanOp, lcpScan_ptr_i);
- Local_key rowid = regOperPtr->m_tuple_location;
- Local_key scanpos = scanOp.p->m_scanPos.m_key;
- rowid.m_page_no = pagePtr.p->frag_page_id;
- if(rowid > scanpos)
- {
- jam();
- copy_bits |= Tuple_header::LCP_SKIP;
- }
- }
-
- Uint32 clear=
- Tuple_header::ALLOC | Tuple_header::FREE |
- Tuple_header::DISK_ALLOC | Tuple_header::DISK_INLINE |
- Tuple_header::MM_SHRINK | Tuple_header::MM_GROWN;
- copy_bits &= ~(Uint32)clear;
-
- tuple_ptr->m_header_bits= copy_bits;
- tuple_ptr->m_operation_ptr_i= save;
-
- if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
- {
- jam();
- * tuple_ptr->get_mm_gci(regTabPtr) = gci;
- }
-
- if (regTabPtr->m_bits & Tablerec::TR_Checksum) {
- jam();
- setChecksum(tuple_ptr, regTabPtr);
- }
-}
-
-void
-Dbtup::disk_page_commit_callback(Signal* signal,
- Uint32 opPtrI, Uint32 page_id)
-{
- Uint32 hash_value;
- Uint32 gci;
- OperationrecPtr regOperPtr;
-
- jamEntry();
-
- c_operation_pool.getPtr(regOperPtr, opPtrI);
- c_lqh->get_op_info(regOperPtr.p->userpointer, &hash_value, &gci);
-
- TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
-
- tupCommitReq->opPtr= opPtrI;
- tupCommitReq->hashValue= hash_value;
- tupCommitReq->gci= gci;
- tupCommitReq->diskpage = page_id;
-
- regOperPtr.p->op_struct.m_load_diskpage_on_commit= 0;
- regOperPtr.p->m_commit_disk_callback_page= page_id;
- m_global_page_pool.getPtr(m_pgman.m_ptr, page_id);
-
- {
- PagePtr tmp;
- tmp.i = m_pgman.m_ptr.i;
- tmp.p = reinterpret_cast<Page*>(m_pgman.m_ptr.p);
- disk_page_set_dirty(tmp);
- }
-
- execTUP_COMMITREQ(signal);
- if(signal->theData[0] == 0)
- {
- jam();
- c_lqh->tupcommit_conf_callback(signal, regOperPtr.p->userpointer);
- }
-}
-
-void
-Dbtup::disk_page_log_buffer_callback(Signal* signal,
- Uint32 opPtrI,
- Uint32 unused)
-{
- Uint32 hash_value;
- Uint32 gci;
- OperationrecPtr regOperPtr;
-
- jamEntry();
-
- c_operation_pool.getPtr(regOperPtr, opPtrI);
- c_lqh->get_op_info(regOperPtr.p->userpointer, &hash_value, &gci);
- Uint32 page= regOperPtr.p->m_commit_disk_callback_page;
-
- TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
-
- tupCommitReq->opPtr= opPtrI;
- tupCommitReq->hashValue= hash_value;
- tupCommitReq->gci= gci;
- tupCommitReq->diskpage = page;
-
- ndbassert(regOperPtr.p->op_struct.m_load_diskpage_on_commit == 0);
- regOperPtr.p->op_struct.m_wait_log_buffer= 0;
- m_global_page_pool.getPtr(m_pgman.m_ptr, page);
-
- execTUP_COMMITREQ(signal);
- ndbassert(signal->theData[0] == 0);
-
- c_lqh->tupcommit_conf_callback(signal, regOperPtr.p->userpointer);
-}
-
-/**
- * Move to the first operation performed on this tuple
- */
-void
-Dbtup::findFirstOp(OperationrecPtr & firstPtr)
-{
- jam();
- printf("Detect out-of-order commit(%u) -> ", firstPtr.i);
- ndbassert(!firstPtr.p->is_first_operation());
- while(firstPtr.p->prevActiveOp != RNIL)
- {
- firstPtr.i = firstPtr.p->prevActiveOp;
- c_operation_pool.getPtr(firstPtr);
- }
- ndbout_c("%u", firstPtr.i);
-}
-
-/* ----------------------------------------------------------------- */
-/* --------------- COMMIT THIS PART OF A TRANSACTION --------------- */
-/* ----------------------------------------------------------------- */
-void Dbtup::execTUP_COMMITREQ(Signal* signal)
-{
- FragrecordPtr regFragPtr;
- OperationrecPtr regOperPtr;
- TablerecPtr regTabPtr;
- KeyReqStruct req_struct;
- TransState trans_state;
- Uint32 no_of_fragrec, no_of_tablerec;
-
- TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
-
- regOperPtr.i= tupCommitReq->opPtr;
- Uint32 hash_value= tupCommitReq->hashValue;
- Uint32 gci = tupCommitReq->gci;
-
- jamEntry();
-
- c_operation_pool.getPtr(regOperPtr);
-
- regFragPtr.i= regOperPtr.p->fragmentPtr;
- trans_state= get_trans_state(regOperPtr.p);
-
- no_of_fragrec= cnoOfFragrec;
-
- ndbrequire(trans_state == TRANS_STARTED);
- ptrCheckGuard(regFragPtr, no_of_fragrec, fragrecord);
-
- no_of_tablerec= cnoOfTablerec;
- regTabPtr.i= regFragPtr.p->fragTableId;
- hash_value= tupCommitReq->hashValue;
- gci= tupCommitReq->gci;
-
- req_struct.signal= signal;
- req_struct.hash_value= hash_value;
- req_struct.gci= gci;
- regOperPtr.p->m_commit_disk_callback_page = tupCommitReq->diskpage;
-
-#ifdef VM_TRACE
- if (tupCommitReq->diskpage == RNIL)
- {
- m_pgman.m_ptr.i = RNIL;
- m_pgman.m_ptr.p = 0;
- req_struct.m_disk_page_ptr.i = RNIL;
- req_struct.m_disk_page_ptr.p = 0;
- }
-#endif
-
- ptrCheckGuard(regTabPtr, no_of_tablerec, tablerec);
-
- PagePtr page;
- Tuple_header* tuple_ptr= (Tuple_header*)
- get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
-
- /**
- * NOTE: This has to be run before potential time-slice when
- * waiting for disk, as otherwise the "other-ops" in a multi-op
- * commit might run while we're waiting for disk
- *
- */
- if (!regTabPtr.p->tuxCustomTriggers.isEmpty())
- {
- if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
- {
- jam();
-
- OperationrecPtr loopPtr = regOperPtr;
- if (unlikely(!regOperPtr.p->is_first_operation()))
- {
- findFirstOp(loopPtr);
- }
-
- /**
- * Execute all tux triggers at first commit
- * since previous tuple is otherwise removed...
- */
- jam();
- goto first;
- while(loopPtr.i != RNIL)
- {
- c_operation_pool.getPtr(loopPtr);
- first:
- executeTuxCommitTriggers(signal,
- loopPtr.p,
- regFragPtr.p,
- regTabPtr.p);
- set_tuple_state(loopPtr.p, TUPLE_TO_BE_COMMITTED);
- loopPtr.i = loopPtr.p->nextActiveOp;
- }
- }
- }
-
- bool get_page = false;
- if(regOperPtr.p->op_struct.m_load_diskpage_on_commit)
- {
- jam();
- Page_cache_client::Request req;
-
- /**
- * Only last op on tuple needs "real" commit,
- * hence only this one should have m_load_diskpage_on_commit
- */
- ndbassert(tuple_ptr->m_operation_ptr_i == regOperPtr.i);
-
- /**
- * Check for page
- */
- if(!regOperPtr.p->m_copy_tuple_location.isNull())
- {
- jam();
- Tuple_header* tmp= (Tuple_header*)
- c_undo_buffer.get_ptr(&regOperPtr.p->m_copy_tuple_location);
-
- memcpy(&req.m_page,
- tmp->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key));
-
- if (unlikely(regOperPtr.p->op_struct.op_type == ZDELETE &&
- tmp->m_header_bits & Tuple_header::DISK_ALLOC))
- {
- jam();
- /**
- * Insert+Delete
- */
- regOperPtr.p->op_struct.m_load_diskpage_on_commit = 0;
- regOperPtr.p->op_struct.m_wait_log_buffer = 0;
- disk_page_abort_prealloc(signal, regFragPtr.p,
- &req.m_page, req.m_page.m_page_idx);
-
- c_lgman->free_log_space(regFragPtr.p->m_logfile_group_id,
- regOperPtr.p->m_undo_buffer_space);
- goto skip_disk;
- if (0) ndbout_c("insert+delete");
- jamEntry();
- goto skip_disk;
- }
- }
- else
- {
- jam();
- // initial delete
- ndbassert(regOperPtr.p->op_struct.op_type == ZDELETE);
- memcpy(&req.m_page,
- tuple_ptr->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key));
-
- ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
- }
- req.m_callback.m_callbackData= regOperPtr.i;
- req.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::disk_page_commit_callback);
-
- /*
- * Consider commit to be correlated. Otherwise pk op + commit makes
- * the page hot. XXX move to TUP which knows better.
- */
- int flags= regOperPtr.p->op_struct.op_type |
- Page_cache_client::COMMIT_REQ | Page_cache_client::CORR_REQ;
- int res= m_pgman.get_page(signal, req, flags);
- switch(res){
- case 0:
- /**
- * Timeslice
- */
- jam();
- signal->theData[0] = 1;
- return;
- case -1:
- ndbrequire("NOT YET IMPLEMENTED" == 0);
- break;
- default:
- jam();
- }
- get_page = true;
-
- {
- PagePtr tmpptr;
- tmpptr.i = m_pgman.m_ptr.i;
- tmpptr.p = reinterpret_cast<Page*>(m_pgman.m_ptr.p);
- disk_page_set_dirty(tmpptr);
- }
-
- regOperPtr.p->m_commit_disk_callback_page= res;
- regOperPtr.p->op_struct.m_load_diskpage_on_commit= 0;
- }
-
- if(regOperPtr.p->op_struct.m_wait_log_buffer)
- {
- jam();
- /**
- * Only last op on tuple needs "real" commit,
- * hence only this one should have m_wait_log_buffer
- */
- ndbassert(tuple_ptr->m_operation_ptr_i == regOperPtr.i);
-
- Callback cb;
- cb.m_callbackData= regOperPtr.i;
- cb.m_callbackFunction =
- safe_cast(&Dbtup::disk_page_log_buffer_callback);
- Uint32 sz= regOperPtr.p->m_undo_buffer_space;
-
- Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id);
- int res= lgman.get_log_buffer(signal, sz, &cb);
- jamEntry();
- switch(res){
- case 0:
- jam();
- signal->theData[0] = 1;
- return;
- case -1:
- ndbrequire("NOT YET IMPLEMENTED" == 0);
- break;
- default:
- jam();
- }
- }
-
- assert(tuple_ptr);
-skip_disk:
- req_struct.m_tuple_ptr = tuple_ptr;
-
- Uint32 nextOp = regOperPtr.p->nextActiveOp;
- Uint32 prevOp = regOperPtr.p->prevActiveOp;
- /**
- * The trigger code (which is shared between detached/imediate)
- * check op-list to check were to read before values from
- * detached triggers should always read from original tuple value
- * from before transaction start, not from any intermediate update
- *
- * Setting the op-list has this effect
- */
- regOperPtr.p->nextActiveOp = RNIL;
- regOperPtr.p->prevActiveOp = RNIL;
- if(tuple_ptr->m_operation_ptr_i == regOperPtr.i)
- {
- jam();
- /**
- * Perform "real" commit
- */
- Uint32 disk = regOperPtr.p->m_commit_disk_callback_page;
- set_change_mask_info(&req_struct, regOperPtr.p);
- checkDetachedTriggers(&req_struct, regOperPtr.p, regTabPtr.p,
- disk != RNIL);
-
- tuple_ptr->m_operation_ptr_i = RNIL;
-
- if(regOperPtr.p->op_struct.op_type != ZDELETE)
- {
- jam();
- commit_operation(signal, gci, tuple_ptr, page,
- regOperPtr.p, regFragPtr.p, regTabPtr.p);
- }
- else
- {
- jam();
- if (get_page)
- ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
- dealloc_tuple(signal, gci, page.p, tuple_ptr,
- regOperPtr.p, regFragPtr.p, regTabPtr.p);
- }
- }
-
- if (nextOp != RNIL)
- {
- c_operation_pool.getPtr(nextOp)->prevActiveOp = prevOp;
- }
-
- if (prevOp != RNIL)
- {
- c_operation_pool.getPtr(prevOp)->nextActiveOp = nextOp;
- }
-
- if(!regOperPtr.p->m_copy_tuple_location.isNull())
- {
- jam();
- c_undo_buffer.free_copy_tuple(&regOperPtr.p->m_copy_tuple_location);
- }
-
- initOpConnection(regOperPtr.p);
- signal->theData[0] = 0;
-}
-
-void
-Dbtup::set_change_mask_info(KeyReqStruct * const req_struct,
- Operationrec * const regOperPtr)
-{
- ChangeMaskState state = get_change_mask_state(regOperPtr);
- if (state == USE_SAVED_CHANGE_MASK) {
- jam();
- req_struct->changeMask.setWord(0, regOperPtr->saved_change_mask[0]);
- req_struct->changeMask.setWord(1, regOperPtr->saved_change_mask[1]);
- } else if (state == RECALCULATE_CHANGE_MASK) {
- jam();
- // Recompute change mask, for now set all bits
- req_struct->changeMask.set();
- } else if (state == SET_ALL_MASK) {
- jam();
- req_struct->changeMask.set();
- } else {
- jam();
- ndbrequire(state == DELETE_CHANGES);
- req_struct->changeMask.set();
- }
-}
-
-void
-Dbtup::calculateChangeMask(Page* const pagePtr,
- Tablerec* const regTabPtr,
- KeyReqStruct * const req_struct)
-{
- OperationrecPtr loopOpPtr;
- Uint32 saved_word1= 0;
- Uint32 saved_word2= 0;
- loopOpPtr.i= req_struct->m_tuple_ptr->m_operation_ptr_i;
- do {
- c_operation_pool.getPtr(loopOpPtr);
- ndbrequire(loopOpPtr.p->op_struct.op_type == ZUPDATE);
- ChangeMaskState change_mask= get_change_mask_state(loopOpPtr.p);
- if (change_mask == USE_SAVED_CHANGE_MASK) {
- jam();
- saved_word1|= loopOpPtr.p->saved_change_mask[0];
- saved_word2|= loopOpPtr.p->saved_change_mask[1];
- } else if (change_mask == RECALCULATE_CHANGE_MASK) {
- jam();
- //Recompute change mask, for now set all bits
- req_struct->changeMask.set();
- return;
- } else {
- ndbrequire(change_mask == SET_ALL_MASK);
- jam();
- req_struct->changeMask.set();
- return;
- }
- loopOpPtr.i= loopOpPtr.p->prevActiveOp;
- } while (loopOpPtr.i != RNIL);
- req_struct->changeMask.setWord(0, saved_word1);
- req_struct->changeMask.setWord(1, saved_word2);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
deleted file mode 100644
index 7d88587cb35..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_DEBUG_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/EventReport.hpp>
-#include <Vector.hpp>
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* ------------------------ DEBUG MODULE -------------------------- */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-void Dbtup::execDEBUG_SIG(Signal* signal)
-{
- PagePtr regPagePtr;
- jamEntry();
- regPagePtr.i = signal->theData[0];
- c_page_pool.getPtr(regPagePtr);
-}//Dbtup::execDEBUG_SIG()
-
-#ifdef TEST_MR
-#include <time.h>
-
-void startTimer(struct timespec *tp)
-{
- clock_gettime(CLOCK_REALTIME, tp);
-}//startTimer()
-
-int stopTimer(struct timespec *tp)
-{
- double timer_count;
- struct timespec theStopTime;
- clock_gettime(CLOCK_REALTIME, &theStopTime);
- timer_count = (double)(1000000*((double)theStopTime.tv_sec - (double)tp->tv_sec)) +
- (double)((double)((double)theStopTime.tv_nsec - (double)tp->tv_nsec)/(double)1000);
- return (int)timer_count;
-}//stopTimer()
-
-#endif // end TEST_MR
-
-struct Chunk {
- Uint32 pageId;
- Uint32 pageCount;
-};
-
-void
-Dbtup::reportMemoryUsage(Signal* signal, int incDec){
- signal->theData[0] = NDB_LE_MemoryUsage;
- signal->theData[1] = incDec;
- signal->theData[2] = sizeof(Page);
- signal->theData[3] = cnoOfAllocatedPages;
- signal->theData[4] = c_page_pool.getSize();
- signal->theData[5] = DBTUP;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB);
-}
-
-#ifdef VM_TRACE
-extern Uint32 fc_left, fc_right, fc_remove;
-#endif
-
-void
-Dbtup::execDUMP_STATE_ORD(Signal* signal)
-{
- Uint32 type = signal->theData[0];
- if(type == DumpStateOrd::DumpPageMemory && signal->getLength() == 1){
- reportMemoryUsage(signal, 0);
- return;
- }
- DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
-
-#if 0
- if (type == 100) {
- RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
- req->primaryTableId = 2;
- req->secondaryTableId = RNIL;
- req->userPtr = 2;
- req->userRef = DBDICT_REF;
- sendSignal(cownref, GSN_REL_TABMEMREQ, signal,
- RelTabMemReq::SignalLength, JBB);
- return;
- }//if
- if (type == 101) {
- RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
- req->primaryTableId = 4;
- req->secondaryTableId = 5;
- req->userPtr = 4;
- req->userRef = DBDICT_REF;
- sendSignal(cownref, GSN_REL_TABMEMREQ, signal,
- RelTabMemReq::SignalLength, JBB);
- return;
- }//if
- if (type == 102) {
- RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
- req->primaryTableId = 6;
- req->secondaryTableId = 8;
- req->userPtr = 6;
- req->userRef = DBDICT_REF;
- sendSignal(cownref, GSN_REL_TABMEMREQ, signal,
- RelTabMemReq::SignalLength, JBB);
- return;
- }//if
- if (type == 103) {
- DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
- req->primaryTableId = 2;
- req->secondaryTableId = RNIL;
- req->userPtr = 2;
- req->userRef = DBDICT_REF;
- sendSignal(cownref, GSN_DROP_TABFILEREQ, signal,
- DropTabFileReq::SignalLength, JBB);
- return;
- }//if
- if (type == 104) {
- DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
- req->primaryTableId = 4;
- req->secondaryTableId = 5;
- req->userPtr = 4;
- req->userRef = DBDICT_REF;
- sendSignal(cownref, GSN_DROP_TABFILEREQ, signal,
- DropTabFileReq::SignalLength, JBB);
- return;
- }//if
- if (type == 105) {
- DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
- req->primaryTableId = 6;
- req->secondaryTableId = 8;
- req->userPtr = 6;
- req->userRef = DBDICT_REF;
- sendSignal(cownref, GSN_DROP_TABFILEREQ, signal,
- DropTabFileReq::SignalLength, JBB);
- return;
- }//if
-#endif
-#ifdef ERROR_INSERT
- if (type == DumpStateOrd::EnableUndoDelayDataWrite) {
- ndbout << "Dbtup:: delay write of datapages for table = "
- << dumpState->args[1]<< endl;
- c_errorInsert4000TableId = dumpState->args[1];
- SET_ERROR_INSERT_VALUE(4000);
- return;
- }//if
-#endif
-#if defined VM_TRACE
- if (type == 1211 || type == 1212 || type == 1213){
- Uint32 seed = time(0);
- if (signal->getLength() > 1)
- seed = signal->theData[1];
- ndbout_c("Startar modul test av Page Manager (seed: 0x%x)", seed);
- srand(seed);
-
- Vector<Chunk> chunks;
- const Uint32 LOOPS = 1000;
- Uint32 sum_req = 0;
- Uint32 sum_conf = 0;
- Uint32 sum_loop = 0;
- Uint32 max_loop = 0;
- for(Uint32 i = 0; i<LOOPS; i++){
-
- // Case
- Uint32 c = (rand() % 3);
- const Uint32 free = c_page_pool.getSize() - cnoOfAllocatedPages;
-
- Uint32 alloc = 0;
- if(free <= 1){
- c = 0;
- alloc = 1;
- } else
- alloc = 1 + (rand() % (free - 1));
-
- if(chunks.size() == 0 && c == 0){
- c = 1 + rand() % 2;
- }
-
- if (type == 1211)
- ndbout_c("loop=%d case=%d free=%d alloc=%d", i, c, free, alloc);
-
- if (type == 1213)
- {
- c = 1;
- alloc = 2 + (sum_conf >> 3) + (sum_conf >> 4);
- }
- switch(c){
- case 0:{ // Release
- const int ch = rand() % chunks.size();
- Chunk chunk = chunks[ch];
- chunks.erase(ch);
- returnCommonArea(chunk.pageId, chunk.pageCount);
- }
- break;
- case 2: { // Seize(n) - fail
- alloc += free;
- // Fall through
- sum_req += free;
- goto doalloc;
- }
- case 1: { // Seize(n) (success)
- sum_req += alloc;
- doalloc:
- Chunk chunk;
- allocConsPages(alloc, chunk.pageCount, chunk.pageId);
- ndbrequire(chunk.pageCount <= alloc);
- if(chunk.pageCount != 0){
- chunks.push_back(chunk);
- if(chunk.pageCount != alloc) {
- if (type == 1211)
- ndbout_c(" Tried to allocate %d - only allocated %d - free: %d",
- alloc, chunk.pageCount, free);
- }
- } else {
- ndbout_c(" Failed to alloc %d pages with %d pages free",
- alloc, free);
- }
-
- sum_conf += chunk.pageCount;
- Uint32 tot = fc_left + fc_right + fc_remove;
- sum_loop += tot;
- if (tot > max_loop)
- max_loop = tot;
-
- for(Uint32 i = 0; i<chunk.pageCount; i++){
- PagePtr pagePtr;
- pagePtr.i = chunk.pageId + i;
- c_page_pool.getPtr(pagePtr);
- pagePtr.p->page_state = ~ZFREE_COMMON;
- }
-
- if(alloc == 1 && free > 0)
- ndbrequire(chunk.pageCount == alloc);
- }
- break;
- }
- }
- while(chunks.size() > 0){
- Chunk chunk = chunks.back();
- returnCommonArea(chunk.pageId, chunk.pageCount);
- chunks.erase(chunks.size() - 1);
- }
-
- ndbout_c("Got %u%% of requested allocs, loops : %u 100*avg: %u max: %u",
- (100 * sum_conf) / sum_req, sum_loop, 100*sum_loop / LOOPS,
- max_loop);
- }
-#endif
-}//Dbtup::execDUMP_STATE_ORD()
-
-/* ---------------------------------------------------------------- */
-/* --------- MEMORY CHECK ----------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::execMEMCHECKREQ(Signal* signal)
-{
- TablerecPtr regTabPtr;
- regTabPtr.i = 2;
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
- if(tablerec && regTabPtr.p->tableStatus == DEFINED)
- validate_page(regTabPtr.p, 0);
-
-#if 0
- const Dbtup::Tablerec& tab = *tup->tabptr.p;
-
- PagePtr regPagePtr;
- Uint32* data = &signal->theData[0];
-
- jamEntry();
- BlockReference blockref = signal->theData[0];
- Uint32 i;
- for (i = 0; i < 25; i++) {
- jam();
- data[i] = 0;
- }//for
- for (i = 0; i < 16; i++) {
- regPagePtr.i = cfreepageList[i];
- jam();
- while (regPagePtr.i != RNIL) {
- jam();
- ptrCheckGuard(regPagePtr, cnoOfPage, cpage);
- regPagePtr.i = regPagePtr.p->next_page;
- data[0]++;
- }//while
- }//for
- sendSignal(blockref, GSN_MEMCHECKCONF, signal, 25, JBB);
-#endif
-}//Dbtup::memCheck()
-
-// ------------------------------------------------------------------------
-// Help function to be used when debugging. Prints out a tuple page.
-// printLimit is the number of bytes that is printed out from the page. A
-// page is of size 32768 bytes as of March 2003.
-// ------------------------------------------------------------------------
-void Dbtup::printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit)
-{
- PagePtr tmpPageP;
- FragrecordPtr tmpFragP;
- TablerecPtr tmpTableP;
-
- c_page_pool.getPtr(tmpPageP, pageid);
-
- tmpFragP.i = fragid;
- ptrCheckGuard(tmpFragP, cnoOfFragrec, fragrecord);
-
- tmpTableP.i = tmpFragP.p->fragTableId;
- ptrCheckGuard(tmpTableP, cnoOfTablerec, tablerec);
-
- ndbout << "Fragid: " << fragid << " Pageid: " << pageid << endl
- << "----------------------------------------" << endl;
-
- ndbout << "PageHead : ";
- ndbout << endl;
-}//Dbtup::printoutTuplePage
-
-#ifdef VM_TRACE
-NdbOut&
-operator<<(NdbOut& out, const Dbtup::Operationrec& op)
-{
- out << "[Operationrec " << hex << &op;
- // table
- out << " [fragmentPtr " << hex << op.fragmentPtr << "]";
- // type
- out << " [op_type " << dec << op.op_struct.op_type << "]";
- out << " [delete_insert_flag " << dec;
- out << op.op_struct.delete_insert_flag << "]";
- // state
- out << " [tuple_state " << dec << op.op_struct.tuple_state << "]";
- out << " [trans_state " << dec << op.op_struct.trans_state << "]";
- out << " [in_active_list " << dec << op.op_struct.in_active_list << "]";
- // links
- out << " [prevActiveOp " << hex << op.prevActiveOp << "]";
- out << " [nextActiveOp " << hex << op.nextActiveOp << "]";
- // tuples
- out << " [tupVersion " << hex << op.tupVersion << "]";
- out << " [m_tuple_location " << op.m_tuple_location << "]";
- out << " [m_copy_tuple_location " << op.m_copy_tuple_location << "]";
- out << "]";
- return out;
-}
-
-// uses global tabptr
-NdbOut&
-operator<<(NdbOut& out, const Dbtup::Th& th)
-{
- // ugly
- Dbtup* tup = (Dbtup*)globalData.getBlock(DBTUP);
- const Dbtup::Tablerec& tab = *tup->tabptr.p;
- unsigned i = 0;
- out << "[Th " << hex << &th;
- out << " [op " << hex << th.data[i++] << "]";
- out << " [version " << hex << (Uint16)th.data[i++] << "]";
- if (tab.m_bits & Dbtup::Tablerec::TR_Checksum)
- out << " [checksum " << hex << th.data[i++] << "]";
- out << " [nullbits";
- for (unsigned j = 0; j < tab.m_offsets[Dbtup::MM].m_null_words; j++)
- out << " " << hex << th.data[i++];
- out << "]";
- out << " [data";
- while (i < tab.m_offsets[Dbtup::MM].m_fix_header_size)
- out << " " << hex << th.data[i++];
- out << "]";
- out << "]";
- return out;
-}
-#endif
-
-#ifdef VM_TRACE
-template class Vector<Chunk>;
-#endif
-// uses global tabptr
-
-NdbOut&
-operator<<(NdbOut& out, const Local_key & key)
-{
- out << "[ m_page_no: " << dec << key.m_page_no
- << " m_file_no: " << dec << key.m_file_no
- << " m_page_idx: " << dec << key.m_page_idx << "]";
- return out;
-}
-
-static
-NdbOut&
-operator<<(NdbOut& out, const Dbtup::Tablerec::Tuple_offsets& off)
-{
- out << "[ null_words: " << (Uint32)off.m_null_words
- << " null off: " << (Uint32)off.m_null_offset
- << " disk_off: " << off.m_disk_ref_offset
- << " fixheadsz: " << off.m_fix_header_size
- << " max_var_off: " << off.m_max_var_offset
- << " ]";
-
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtup::Tablerec& tab)
-{
- out << "[ total_rec_size: " << tab.total_rec_size
- << " checksum: " << !!(tab.m_bits & Dbtup::Tablerec::TR_Checksum)
- << " attr: " << tab.m_no_of_attributes
- << " disk: " << tab.m_no_of_disk_attributes
- << " mm: " << tab.m_offsets[Dbtup::MM]
- << " [ fix: " << tab.m_attributes[Dbtup::MM].m_no_of_fixsize
- << " var: " << tab.m_attributes[Dbtup::MM].m_no_of_varsize << "]"
-
- << " dd: " << tab.m_offsets[Dbtup::DD]
- << " [ fix: " << tab.m_attributes[Dbtup::DD].m_no_of_fixsize
- << " var: " << tab.m_attributes[Dbtup::DD].m_no_of_varsize << "]"
- << " ]" << endl;
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const AttributeDescriptor& off)
-{
- Uint32 word;
- memcpy(&word, &off, 4);
- return out;
-}
-
-#include "AttributeOffset.hpp"
-
-NdbOut&
-operator<<(NdbOut& out, const AttributeOffset& off)
-{
- Uint32 word;
- memcpy(&word, &off, 4);
- out << "[ offset: " << AttributeOffset::getOffset(word)
- << " nullpos: " << AttributeOffset::getNullFlagPos(word);
- if(AttributeOffset::getCharsetFlag(word))
- out << " charset: %d" << AttributeOffset::getCharsetPos(word);
- out << " ]";
- return out;
-}
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp
deleted file mode 100644
index e426213162a..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp
+++ /dev/null
@@ -1,1893 +0,0 @@
-/* Copyright (c) 2004-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_DISK_ALLOC_CPP
-#include "Dbtup.hpp"
-
-static bool f_undo_done = true;
-
-static
-NdbOut&
-operator<<(NdbOut& out, const Ptr<Dbtup::Page> & ptr)
-{
- out << "[ Page: ptr.i: " << ptr.i
- << " [ m_file_no: " << ptr.p->m_file_no
- << " m_page_no: " << ptr.p->m_page_no << "]"
- << " list_index: " << ptr.p->list_index
- << " free_space: " << ptr.p->free_space
- << " uncommitted_used_space: " << ptr.p->uncommitted_used_space
- << " ]";
- return out;
-}
-
-static
-NdbOut&
-operator<<(NdbOut& out, const Ptr<Dbtup::Page_request> & ptr)
-{
- out << "[ Page_request: ptr.i: " << ptr.i
- << " " << ptr.p->m_key
- << " m_estimated_free_space: " << ptr.p->m_estimated_free_space
- << " m_list_index: " << ptr.p->m_list_index
- << " m_frag_ptr_i: " << ptr.p->m_frag_ptr_i
- << " m_extent_info_ptr: " << ptr.p->m_extent_info_ptr
- << " m_ref_count: " << ptr.p->m_ref_count
- << " m_uncommitted_used_space: " << ptr.p->m_uncommitted_used_space
- << " ]";
-
- return out;
-}
-
-static
-NdbOut&
-operator<<(NdbOut& out, const Ptr<Dbtup::Extent_info> & ptr)
-{
- out << "[ Extent_info: ptr.i " << ptr.i
- << " " << ptr.p->m_key
- << " m_first_page_no: " << ptr.p->m_first_page_no
- << " m_free_space: " << ptr.p->m_free_space
- << " m_free_matrix_pos: " << ptr.p->m_free_matrix_pos
- << " m_free_page_count: [";
-
- for(Uint32 i = 0; i<Dbtup::EXTENT_SEARCH_MATRIX_COLS; i++)
- out << " " << ptr.p->m_free_page_count[i];
- out << " ] ]";
-
- return out;
-}
-
-#if NOT_YET_FREE_EXTENT
-static
-inline
-bool
-check_free(const Dbtup::Extent_info* extP)
-{
- Uint32 res = 0;
- for (Uint32 i = 1; i<MAX_FREE_LIST; i++)
- res += extP->m_free_page_count[i];
- return res;
-}
-#error "Code for deallocting extents when they get empty"
-#error "This code is not yet complete"
-#endif
-
-#if NOT_YET_UNDO_ALLOC_EXTENT
-#error "This is needed for deallocting extents when they get empty"
-#error "This code is not complete yet"
-#endif
-
-void
-Dbtup::dump_disk_alloc(Dbtup::Disk_alloc_info & alloc)
-{
- ndbout_c("dirty pages");
- for(Uint32 i = 0; i<MAX_FREE_LIST; i++)
- {
- printf(" %d : ", i);
- PagePtr ptr;
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
- LocalDLList<Page> list(*pool, alloc.m_dirty_pages[i]);
- for(list.first(ptr); !ptr.isNull(); list.next(ptr))
- {
- ndbout << ptr << " ";
- }
- ndbout_c(" ");
- }
- ndbout_c("page requests");
- for(Uint32 i = 0; i<MAX_FREE_LIST; i++)
- {
- printf(" %d : ", i);
- Ptr<Page_request> ptr;
- Local_page_request_list list(c_page_request_pool,
- alloc.m_page_requests[i]);
- for(list.first(ptr); !ptr.isNull(); list.next(ptr))
- {
- ndbout << ptr << " ";
- }
- ndbout_c(" ");
- }
-
- ndbout_c("Extent matrix");
- for(Uint32 i = 0; i<alloc.SZ; i++)
- {
- printf(" %d : ", i);
- Ptr<Extent_info> ptr;
- Local_extent_info_list list(c_extent_pool, alloc.m_free_extents[i]);
- for(list.first(ptr); !ptr.isNull(); list.next(ptr))
- {
- ndbout << ptr << " ";
- }
- ndbout_c(" ");
- }
-
- if (alloc.m_curr_extent_info_ptr_i != RNIL)
- {
- Ptr<Extent_info> ptr;
- c_extent_pool.getPtr(ptr, alloc.m_curr_extent_info_ptr_i);
- ndbout << "current extent: " << ptr << endl;
- }
-}
-
-#if defined VM_TRACE || true
-#define ddassert(x) do { if(unlikely(!(x))) { dump_disk_alloc(alloc); ndbrequire(false); } } while(0)
-#else
-#define ddassert(x)
-#endif
-
-Dbtup::Disk_alloc_info::Disk_alloc_info(const Tablerec* tabPtrP,
- Uint32 extent_size)
-{
- m_extent_size = extent_size;
- m_curr_extent_info_ptr_i = RNIL;
- if (tabPtrP->m_no_of_disk_attributes == 0)
- return;
-
- Uint32 min_size= 4*tabPtrP->m_offsets[DD].m_fix_header_size;
-
- if (tabPtrP->m_attributes[DD].m_no_of_varsize == 0)
- {
- Uint32 recs_per_page= (4*Tup_fixsize_page::DATA_WORDS)/min_size;
- m_page_free_bits_map[0] = recs_per_page; // 100% free
- m_page_free_bits_map[1] = 1;
- m_page_free_bits_map[2] = 0;
- m_page_free_bits_map[3] = 0;
-
- Uint32 max= recs_per_page * extent_size;
- for(Uint32 i = 0; i<EXTENT_SEARCH_MATRIX_ROWS; i++)
- {
- m_total_extent_free_space_thresholds[i] =
- (EXTENT_SEARCH_MATRIX_ROWS - i - 1)*max/EXTENT_SEARCH_MATRIX_ROWS;
- }
- }
- else
- {
- abort();
- }
-}
-
-Uint32
-Dbtup::Disk_alloc_info::find_extent(Uint32 sz) const
-{
- /**
- * Find an extent with sufficient space for sz
- * Find the biggest available (with most free space)
- * Return position in matrix
- */
- Uint32 col = calc_page_free_bits(sz);
- Uint32 mask= EXTENT_SEARCH_MATRIX_COLS - 1;
- for(Uint32 i= 0; i<EXTENT_SEARCH_MATRIX_SIZE; i++)
- {
- // Check that it can cater for request
- if (!m_free_extents[i].isEmpty())
- {
- return i;
- }
-
- if ((i & mask) >= col)
- {
- i = (i & ~mask) + mask;
- }
- }
-
- return RNIL;
-}
-
-Uint32
-Dbtup::Disk_alloc_info::calc_extent_pos(const Extent_info* extP) const
-{
- Uint32 free= extP->m_free_space;
- Uint32 mask= EXTENT_SEARCH_MATRIX_COLS - 1;
-
- Uint32 col= 0, row=0;
-
- /**
- * Find correct row based on total free space
- * if zero (or very small free space) put
- * absolutly last
- */
- {
- const Uint32 *arr= m_total_extent_free_space_thresholds;
- for(; free < * arr++; row++)
- assert(row < EXTENT_SEARCH_MATRIX_ROWS);
- }
-
- /**
- * Find correct col based on largest available chunk
- */
- {
- const Uint16 *arr= extP->m_free_page_count;
- for(; col < EXTENT_SEARCH_MATRIX_COLS && * arr++ == 0; col++);
- }
-
- /**
- * NOTE
- *
- * If free space on extent is small or zero,
- * col will be = EXTENT_SEARCH_MATRIX_COLS
- * row will be = EXTENT_SEARCH_MATRIX_ROWS
- * in that case pos will be col * row = max pos
- * (as fixed by + 1 in declaration)
- */
- Uint32 pos= (row * (mask + 1)) + (col & mask);
-
- assert(pos < EXTENT_SEARCH_MATRIX_SIZE);
- return pos;
-}
-
-void
-Dbtup::update_extent_pos(Disk_alloc_info& alloc,
- Ptr<Extent_info> extentPtr)
-{
-#ifdef VM_TRACE
- Uint32 min_free = 0;
- for(Uint32 i = 0; i<MAX_FREE_LIST; i++)
- {
- Uint32 sum = alloc.calc_page_free_space(i);
- min_free += sum * extentPtr.p->m_free_page_count[i];
- }
- ddassert(extentPtr.p->m_free_space >= min_free);
-#endif
-
- Uint32 old = extentPtr.p->m_free_matrix_pos;
- if (old != RNIL)
- {
- Uint32 pos = alloc.calc_extent_pos(extentPtr.p);
- if (old != pos)
- {
- jam();
- Local_extent_info_list old_list(c_extent_pool, alloc.m_free_extents[old]);
- Local_extent_info_list new_list(c_extent_pool, alloc.m_free_extents[pos]);
- old_list.remove(extentPtr);
- new_list.add(extentPtr);
- extentPtr.p->m_free_matrix_pos= pos;
- }
- }
- else
- {
- ddassert(alloc.m_curr_extent_info_ptr_i == extentPtr.i);
- }
-}
-
-void
-Dbtup::restart_setup_page(Disk_alloc_info& alloc, PagePtr pagePtr)
-{
- jam();
- /**
- * Link to extent, clear uncommitted_used_space
- */
- pagePtr.p->uncommitted_used_space = 0;
- pagePtr.p->m_restart_seq = globalData.m_restart_seq;
-
- Extent_info key;
- key.m_key.m_file_no = pagePtr.p->m_file_no;
- key.m_key.m_page_idx = pagePtr.p->m_extent_no;
- Ptr<Extent_info> extentPtr;
- ndbrequire(c_extent_hash.find(extentPtr, key));
- pagePtr.p->m_extent_info_ptr = extentPtr.i;
-
- Uint32 idx = pagePtr.p->list_index & ~0x8000;
- Uint32 estimated = alloc.calc_page_free_space(idx);
- Uint32 real_free = pagePtr.p->free_space;
-
- ddassert(real_free >= estimated);
- if (real_free != estimated)
- {
- jam();
- extentPtr.p->m_free_space += (real_free - estimated);
- update_extent_pos(alloc, extentPtr);
- }
-
-#ifdef VM_TRACE
- {
- Local_key page;
- page.m_file_no = pagePtr.p->m_file_no;
- page.m_page_no = pagePtr.p->m_page_no;
-
- Tablespace_client tsman(0, c_tsman,
- 0, 0, 0);
- unsigned uncommitted, committed;
- uncommitted = committed = ~(unsigned)0;
- (void) tsman.get_page_free_bits(&page, &uncommitted, &committed);
- jamEntry();
-
- idx = alloc.calc_page_free_bits(real_free);
- ddassert(idx == committed);
- }
-#endif
-}
-
-/**
- * - Page free bits -
- * 0 = 00 - free - 100% free
- * 1 = 01 - atleast 70% free, 70= pct_free + 2 * (100 - pct_free) / 3
- * 2 = 10 - atleast 40% free, 40= pct_free + (100 - pct_free) / 3
- * 3 = 11 - full - less than pct_free% free, pct_free=10%
- *
- */
-
-#define DBG_DISK 0
-
-int
-Dbtup::disk_page_prealloc(Signal* signal,
- Ptr<Fragrecord> fragPtr,
- Local_key* key, Uint32 sz)
-{
- int err;
- Uint32 i, ptrI;
- Ptr<Page_request> req;
- Fragrecord* fragPtrP = fragPtr.p;
- Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info;
- Uint32 idx= alloc.calc_page_free_bits(sz);
- Tablespace_client tsman(signal, c_tsman,
- fragPtrP->fragTableId,
- fragPtrP->fragmentId,
- fragPtrP->m_tablespace_id);
-
- if (DBG_DISK)
- ndbout << "disk_page_prealloc";
-
- /**
- * 1) search current dirty pages
- */
- for(i= 0; i <= idx; i++)
- {
- if (!alloc.m_dirty_pages[i].isEmpty())
- {
- ptrI= alloc.m_dirty_pages[i].firstItem;
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, ptrI);
-
- PagePtr tmp;
- tmp.i = gpage.i;
- tmp.p = reinterpret_cast<Page*>(gpage.p);
- disk_page_prealloc_dirty_page(alloc, tmp, i, sz);
- key->m_page_no= tmp.p->m_page_no;
- key->m_file_no= tmp.p->m_file_no;
- if (DBG_DISK)
- ndbout << " found dirty page " << *key << endl;
- jam();
- return 0; // Page in memory
- }
- }
-
- /**
- * Search outanding page requests
- * callback does not need to access page request again
- * as it's not the first request to this page
- */
- for(i= 0; i <= idx; i++)
- {
- if (!alloc.m_page_requests[i].isEmpty())
- {
- ptrI= alloc.m_page_requests[i].firstItem;
- Ptr<Page_request> req;
- c_page_request_pool.getPtr(req, ptrI);
-
- disk_page_prealloc_transit_page(alloc, req, i, sz);
- * key = req.p->m_key;
- if (DBG_DISK)
- ndbout << " found transit page " << *key << endl;
- jam();
- return 0;
- }
- }
-
- /**
- * We need to request a page...
- */
- if (!c_page_request_pool.seize(req))
- {
- jam();
- err= 1;
- //XXX set error code
- ndbout_c("no free request");
- return -err;
- }
-
- req.p->m_ref_count= 1;
- req.p->m_frag_ptr_i= fragPtr.i;
- req.p->m_uncommitted_used_space= sz;
-
- int pageBits; // received
- Ptr<Extent_info> ext;
- const Uint32 bits= alloc.calc_page_free_bits(sz); // required
- bool found= false;
-
- /**
- * Do we have a current extent
- */
- if ((ext.i= alloc.m_curr_extent_info_ptr_i) != RNIL)
- {
- jam();
- c_extent_pool.getPtr(ext);
- if ((pageBits= tsman.alloc_page_from_extent(&ext.p->m_key, bits)) >= 0)
- {
- jamEntry();
- found= true;
- }
- else
- {
- jamEntry();
- /**
- * The current extent is not in a free list
- * and since it couldn't accomadate the request
- * we put it on the free list
- */
- alloc.m_curr_extent_info_ptr_i = RNIL;
- Uint32 pos= alloc.calc_extent_pos(ext.p);
- ext.p->m_free_matrix_pos = pos;
- Local_extent_info_list list(c_extent_pool, alloc.m_free_extents[pos]);
- list.add(ext);
- }
- }
-
- if (!found)
- {
- Uint32 pos;
- if ((pos= alloc.find_extent(sz)) != RNIL)
- {
- jam();
- Local_extent_info_list list(c_extent_pool, alloc.m_free_extents[pos]);
- list.first(ext);
- list.remove(ext);
- }
- else
- {
- jam();
- /**
- * We need to alloc an extent
- */
-#if NOT_YET_UNDO_ALLOC_EXTENT
- Uint32 logfile_group_id = fragPtr.p->m_logfile_group_id;
-
- err = c_lgman->alloc_log_space(logfile_group_id,
- sizeof(Disk_undo::AllocExtent)>>2);
- jamEntry();
- if(unlikely(err))
- {
- return -err;
- }
-#endif
-
- if (!c_extent_pool.seize(ext))
- {
- jam();
- //XXX
- err= 2;
-#if NOT_YET_UNDO_ALLOC_EXTENT
- c_lgman->free_log_space(logfile_group_id,
- sizeof(Disk_undo::AllocExtent)>>2);
-#endif
- c_page_request_pool.release(req);
- ndbout_c("no free extent info");
- return -err;
- }
-
- if ((err= tsman.alloc_extent(&ext.p->m_key)) < 0)
- {
- jamEntry();
-#if NOT_YET_UNDO_ALLOC_EXTENT
- c_lgman->free_log_space(logfile_group_id,
- sizeof(Disk_undo::AllocExtent)>>2);
-#endif
- c_extent_pool.release(ext);
- c_page_request_pool.release(req);
- return err;
- }
-
- int pages= err;
-#if NOT_YET_UNDO_ALLOC_EXTENT
- {
- /**
- * Do something here
- */
- {
- Callback cb;
- cb.m_callbackData= ext.i;
- cb.m_callbackFunction =
- safe_cast(&Dbtup::disk_page_alloc_extent_log_buffer_callback);
- Uint32 sz= sizeof(Disk_undo::AllocExtent)>>2;
-
- Logfile_client lgman(this, c_lgman, logfile_group_id);
- int res= lgman.get_log_buffer(signal, sz, &cb);
- switch(res){
- case 0:
- break;
- case -1:
- ndbrequire("NOT YET IMPLEMENTED" == 0);
- break;
- default:
- execute(signal, cb, res);
- }
- }
- }
-#endif
-
- ndbout << "allocated " << pages << " pages: " << ext.p->m_key << endl;
- ext.p->m_first_page_no = ext.p->m_key.m_page_no;
- bzero(ext.p->m_free_page_count, sizeof(ext.p->m_free_page_count));
- ext.p->m_free_space= alloc.m_page_free_bits_map[0] * pages;
- ext.p->m_free_page_count[0]= pages; // All pages are "free"-est
- c_extent_hash.add(ext);
-
- Local_fragment_extent_list list1(c_extent_pool, alloc.m_extent_list);
- list1.add(ext);
- }
-
- alloc.m_curr_extent_info_ptr_i= ext.i;
- ext.p->m_free_matrix_pos= RNIL;
- pageBits= tsman.alloc_page_from_extent(&ext.p->m_key, bits);
- jamEntry();
- ddassert(pageBits >= 0);
- }
-
- /**
- * We have a page from an extent
- */
- *key= req.p->m_key= ext.p->m_key;
-
- if (DBG_DISK)
- ndbout << " allocated page " << *key << endl;
-
- /**
- * We don't know exact free space of page
- * but we know what page free bits it has.
- * compute free space based on them
- */
- Uint32 size= alloc.calc_page_free_space((Uint32)pageBits);
-
- ddassert(size >= sz);
- Uint32 new_size = size - sz; // Subtract alloc rec
- req.p->m_estimated_free_space= new_size; // Store on page request
-
- Uint32 newPageBits= alloc.calc_page_free_bits(new_size);
- if (newPageBits != (Uint32)pageBits)
- {
- jam();
- ddassert(ext.p->m_free_page_count[pageBits] > 0);
- ext.p->m_free_page_count[pageBits]--;
- ext.p->m_free_page_count[newPageBits]++;
- }
- ddassert(ext.p->m_free_space >= sz);
- ext.p->m_free_space -= sz;
-
- // And put page request in correct free list
- idx= alloc.calc_page_free_bits(new_size);
- {
- Local_page_request_list list(c_page_request_pool,
- alloc.m_page_requests[idx]);
-
- list.add(req);
- }
- req.p->m_list_index= idx;
- req.p->m_extent_info_ptr= ext.i;
-
- Page_cache_client::Request preq;
- preq.m_page = *key;
- preq.m_callback.m_callbackData= req.i;
- preq.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::disk_page_prealloc_callback);
-
- int flags= Page_cache_client::ALLOC_REQ;
- if (pageBits == 0)
- {
- jam();
- //XXX empty page -> fast to map
- flags |= Page_cache_client::EMPTY_PAGE;
- preq.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::disk_page_prealloc_initial_callback);
- }
-
- int res= m_pgman.get_page(signal, preq, flags);
- jamEntry();
- switch(res)
- {
- case 0:
- jam();
- break;
- case -1:
- ndbassert(false);
- break;
- default:
- jam();
- execute(signal, preq.m_callback, res); // run callback
- }
-
- return res;
-}
-
-void
-Dbtup::disk_page_prealloc_dirty_page(Disk_alloc_info & alloc,
- PagePtr pagePtr,
- Uint32 old_idx, Uint32 sz)
-{
- jam();
- ddassert(pagePtr.p->list_index == old_idx);
-
- Uint32 free= pagePtr.p->free_space;
- Uint32 used= pagePtr.p->uncommitted_used_space + sz;
- Uint32 ext= pagePtr.p->m_extent_info_ptr;
-
- ddassert(free >= used);
- Ptr<Extent_info> extentPtr;
- c_extent_pool.getPtr(extentPtr, ext);
-
- Uint32 new_idx= alloc.calc_page_free_bits(free - used);
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
-
- if (old_idx != new_idx)
- {
- jam();
- LocalDLList<Page> old_list(*pool, alloc.m_dirty_pages[old_idx]);
- LocalDLList<Page> new_list(*pool, alloc.m_dirty_pages[new_idx]);
- old_list.remove(pagePtr);
- new_list.add(pagePtr);
-
- ddassert(extentPtr.p->m_free_page_count[old_idx]);
- extentPtr.p->m_free_page_count[old_idx]--;
- extentPtr.p->m_free_page_count[new_idx]++;
- pagePtr.p->list_index= new_idx;
- }
-
- pagePtr.p->uncommitted_used_space = used;
- ddassert(extentPtr.p->m_free_space >= sz);
- extentPtr.p->m_free_space -= sz;
- update_extent_pos(alloc, extentPtr);
-}
-
-
-void
-Dbtup::disk_page_prealloc_transit_page(Disk_alloc_info& alloc,
- Ptr<Page_request> req,
- Uint32 old_idx, Uint32 sz)
-{
- jam();
- ddassert(req.p->m_list_index == old_idx);
-
- Uint32 free= req.p->m_estimated_free_space;
- Uint32 used= req.p->m_uncommitted_used_space + sz;
- Uint32 ext= req.p->m_extent_info_ptr;
-
- Ptr<Extent_info> extentPtr;
- c_extent_pool.getPtr(extentPtr, ext);
-
- ddassert(free >= sz);
- Uint32 new_idx= alloc.calc_page_free_bits(free - sz);
-
- if (old_idx != new_idx)
- {
- jam();
- Page_request_list::Head *lists = alloc.m_page_requests;
- Local_page_request_list old_list(c_page_request_pool, lists[old_idx]);
- Local_page_request_list new_list(c_page_request_pool, lists[new_idx]);
- old_list.remove(req);
- new_list.add(req);
-
- ddassert(extentPtr.p->m_free_page_count[old_idx]);
- extentPtr.p->m_free_page_count[old_idx]--;
- extentPtr.p->m_free_page_count[new_idx]++;
- req.p->m_list_index= new_idx;
- }
-
- req.p->m_uncommitted_used_space = used;
- req.p->m_estimated_free_space = free - sz;
- ddassert(extentPtr.p->m_free_space >= sz);
- extentPtr.p->m_free_space -= sz;
- update_extent_pos(alloc, extentPtr);
-}
-
-
-void
-Dbtup::disk_page_prealloc_callback(Signal* signal,
- Uint32 page_request, Uint32 page_id)
-{
- jamEntry();
- //ndbout_c("disk_alloc_page_callback id: %d", page_id);
-
- Ptr<Page_request> req;
- c_page_request_pool.getPtr(req, page_request);
-
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, page_id);
-
- Ptr<Fragrecord> fragPtr;
- fragPtr.i= req.p->m_frag_ptr_i;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- PagePtr pagePtr;
- pagePtr.i = gpage.i;
- pagePtr.p = reinterpret_cast<Page*>(gpage.p);
-
- if (unlikely(pagePtr.p->m_restart_seq != globalData.m_restart_seq))
- {
- restart_setup_page(fragPtr.p->m_disk_alloc_info, pagePtr);
- }
-
- disk_page_prealloc_callback_common(signal, req, fragPtr, pagePtr);
-}
-
-void
-Dbtup::disk_page_prealloc_initial_callback(Signal*signal,
- Uint32 page_request,
- Uint32 page_id)
-{
- jamEntry();
- //ndbout_c("disk_alloc_page_callback_initial id: %d", page_id);
- /**
- * 1) lookup page request
- * 2) lookup page
- * 3) lookup table
- * 4) init page (according to page type)
- * 5) call ordinary callback
- */
- Ptr<Page_request> req;
- c_page_request_pool.getPtr(req, page_request);
-
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, page_id);
- PagePtr pagePtr;
- pagePtr.i = gpage.i;
- pagePtr.p = reinterpret_cast<Page*>(gpage.p);
-
- Ptr<Fragrecord> fragPtr;
- fragPtr.i= req.p->m_frag_ptr_i;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- Ptr<Tablerec> tabPtr;
- tabPtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- Ptr<Extent_info> extentPtr;
- c_extent_pool.getPtr(extentPtr, req.p->m_extent_info_ptr);
-
- pagePtr.p->m_page_no= req.p->m_key.m_page_no;
- pagePtr.p->m_file_no= req.p->m_key.m_file_no;
- pagePtr.p->m_table_id= fragPtr.p->fragTableId;
- pagePtr.p->m_fragment_id = fragPtr.p->fragmentId;
- pagePtr.p->m_extent_no = extentPtr.p->m_key.m_page_idx; // logical extent no
- pagePtr.p->m_extent_info_ptr= req.p->m_extent_info_ptr;
- pagePtr.p->m_restart_seq = globalData.m_restart_seq;
- pagePtr.p->list_index = 0x8000;
- pagePtr.p->uncommitted_used_space = 0;
- pagePtr.p->nextList = pagePtr.p->prevList = RNIL;
-
- if (tabPtr.p->m_attributes[DD].m_no_of_varsize == 0)
- {
- convertThPage((Fix_page*)pagePtr.p, tabPtr.p, DD);
- }
- else
- {
- abort();
- }
- disk_page_prealloc_callback_common(signal, req, fragPtr, pagePtr);
-}
-
-void
-Dbtup::disk_page_prealloc_callback_common(Signal* signal,
- Ptr<Page_request> req,
- Ptr<Fragrecord> fragPtr,
- PagePtr pagePtr)
-{
- /**
- * 1) remove page request from Disk_alloc_info.m_page_requests
- * 2) Add page to Disk_alloc_info.m_dirty_pages
- * 3) register callback in pgman (unmap callback)
- * 4) inform pgman about current users
- */
- Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
- ddassert((pagePtr.p->list_index & 0x8000) == 0x8000);
- ddassert(pagePtr.p->m_extent_info_ptr == req.p->m_extent_info_ptr);
- ddassert(pagePtr.p->m_page_no == req.p->m_key.m_page_no);
- ddassert(pagePtr.p->m_file_no == req.p->m_key.m_file_no);
-
- Uint32 old_idx = req.p->m_list_index;
- Uint32 free= req.p->m_estimated_free_space;
- Uint32 ext = req.p->m_extent_info_ptr;
- Uint32 used= req.p->m_uncommitted_used_space;
- Uint32 real_free = pagePtr.p->free_space;
- Uint32 real_used = used + pagePtr.p->uncommitted_used_space;
-
- ddassert(real_free >= free);
- ddassert(real_free >= real_used);
- ddassert(alloc.calc_page_free_bits(free) == old_idx);
- Uint32 new_idx= alloc.calc_page_free_bits(real_free - real_used);
-
- /**
- * Add to dirty pages
- */
- ArrayPool<Page> *cheat_pool= (ArrayPool<Page>*)&m_global_page_pool;
- LocalDLList<Page> list(* cheat_pool, alloc.m_dirty_pages[new_idx]);
- list.add(pagePtr);
- pagePtr.p->uncommitted_used_space = real_used;
- pagePtr.p->list_index = new_idx;
-
- if (old_idx != new_idx || free != real_free)
- {
- jam();
- Ptr<Extent_info> extentPtr;
- c_extent_pool.getPtr(extentPtr, ext);
-
- extentPtr.p->m_free_space += (real_free - free);
-
- if (old_idx != new_idx)
- {
- jam();
- ddassert(extentPtr.p->m_free_page_count[old_idx]);
- extentPtr.p->m_free_page_count[old_idx]--;
- extentPtr.p->m_free_page_count[new_idx]++;
- }
-
- update_extent_pos(alloc, extentPtr);
- }
-
- {
- Local_page_request_list list(c_page_request_pool,
- alloc.m_page_requests[old_idx]);
- list.release(req);
- }
-}
-
-void
-Dbtup::disk_page_set_dirty(PagePtr pagePtr)
-{
- jam();
- Uint32 idx = pagePtr.p->list_index;
- if ((idx & 0x8000) == 0)
- {
- jam();
- /**
- * Already in dirty list
- */
- return ;
- }
-
- Local_key key;
- key.m_page_no = pagePtr.p->m_page_no;
- key.m_file_no = pagePtr.p->m_file_no;
-
- pagePtr.p->nextList = pagePtr.p->prevList = RNIL;
-
- if (DBG_DISK)
- ndbout << " disk_page_set_dirty " << key << endl;
-
- Ptr<Tablerec> tabPtr;
- tabPtr.i= pagePtr.p->m_table_id;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- Ptr<Fragrecord> fragPtr;
- getFragmentrec(fragPtr, pagePtr.p->m_fragment_id, tabPtr.p);
-
- Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
-
- Uint32 free = pagePtr.p->free_space;
- Uint32 used = pagePtr.p->uncommitted_used_space;
- if (unlikely(pagePtr.p->m_restart_seq != globalData.m_restart_seq))
- {
- restart_setup_page(alloc, pagePtr);
- idx = alloc.calc_page_free_bits(free);
- used = 0;
- }
- else
- {
- idx &= ~0x8000;
- ddassert(idx == alloc.calc_page_free_bits(free - used));
- }
-
- ddassert(free >= used);
-
- Tablespace_client tsman(0, c_tsman,
- fragPtr.p->fragTableId,
- fragPtr.p->fragmentId,
- fragPtr.p->m_tablespace_id);
-
- pagePtr.p->list_index = idx;
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
- LocalDLList<Page> list(*pool, alloc.m_dirty_pages[idx]);
- list.add(pagePtr);
-
- // Make sure no one will allocate it...
- tsman.unmap_page(&key, MAX_FREE_LIST - 1);
- jamEntry();
-}
-
-void
-Dbtup::disk_page_unmap_callback(Uint32 when,
- Uint32 page_id, Uint32 dirty_count)
-{
- jamEntry();
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, page_id);
- PagePtr pagePtr;
- pagePtr.i = gpage.i;
- pagePtr.p = reinterpret_cast<Page*>(gpage.p);
-
- Uint32 type = pagePtr.p->m_page_header.m_page_type;
- if (unlikely((type != File_formats::PT_Tup_fixsize_page &&
- type != File_formats::PT_Tup_varsize_page) ||
- f_undo_done == false))
- {
- jam();
- return ;
- }
-
- Uint32 idx = pagePtr.p->list_index;
-
- Ptr<Tablerec> tabPtr;
- tabPtr.i= pagePtr.p->m_table_id;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- Ptr<Fragrecord> fragPtr;
- getFragmentrec(fragPtr, pagePtr.p->m_fragment_id, tabPtr.p);
-
- Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
-
- if (when == 0)
- {
- /**
- * Before pageout
- */
- jam();
-
- if (DBG_DISK)
- {
- Local_key key;
- key.m_page_no = pagePtr.p->m_page_no;
- key.m_file_no = pagePtr.p->m_file_no;
- ndbout << "disk_page_unmap_callback(before) " << key
- << " cnt: " << dirty_count << " " << (idx & ~0x8000) << endl;
- }
-
- ndbassert((idx & 0x8000) == 0);
-
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
- LocalDLList<Page> list(*pool, alloc.m_dirty_pages[idx]);
- LocalDLList<Page> list2(*pool, alloc.m_unmap_pages);
- list.remove(pagePtr);
- list2.add(pagePtr);
-
- if (dirty_count == 0)
- {
- jam();
- pagePtr.p->list_index = idx | 0x8000;
-
- Local_key key;
- key.m_page_no = pagePtr.p->m_page_no;
- key.m_file_no = pagePtr.p->m_file_no;
-
- Uint32 free = pagePtr.p->free_space;
- Uint32 used = pagePtr.p->uncommitted_used_space;
- ddassert(free >= used);
- ddassert(alloc.calc_page_free_bits(free - used) == idx);
-
- Tablespace_client tsman(0, c_tsman,
- fragPtr.p->fragTableId,
- fragPtr.p->fragmentId,
- fragPtr.p->m_tablespace_id);
-
- tsman.unmap_page(&key, idx);
- jamEntry();
- }
- }
- else if (when == 1)
- {
- /**
- * After page out
- */
- jam();
-
- Local_key key;
- key.m_page_no = pagePtr.p->m_page_no;
- key.m_file_no = pagePtr.p->m_file_no;
- Uint32 real_free = pagePtr.p->free_space;
-
- if (DBG_DISK)
- {
- ndbout << "disk_page_unmap_callback(after) " << key
- << " cnt: " << dirty_count << " " << (idx & ~0x8000) << endl;
- }
-
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
- LocalDLList<Page> list(*pool, alloc.m_unmap_pages);
- list.remove(pagePtr);
-
- Tablespace_client tsman(0, c_tsman,
- fragPtr.p->fragTableId,
- fragPtr.p->fragmentId,
- fragPtr.p->m_tablespace_id);
-
- if (DBG_DISK && alloc.calc_page_free_bits(real_free) != (idx & ~0x8000))
- {
- ndbout << key
- << " calc: " << alloc.calc_page_free_bits(real_free)
- << " idx: " << (idx & ~0x8000)
- << endl;
- }
- tsman.update_page_free_bits(&key, alloc.calc_page_free_bits(real_free));
- jamEntry();
- }
-}
-
-void
-Dbtup::disk_page_alloc(Signal* signal,
- Tablerec* tabPtrP, Fragrecord* fragPtrP,
- Local_key* key, PagePtr pagePtr, Uint32 gci)
-{
- jam();
- Uint32 logfile_group_id= fragPtrP->m_logfile_group_id;
- Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info;
-
- Uint64 lsn;
- if (tabPtrP->m_attributes[DD].m_no_of_varsize == 0)
- {
- ddassert(pagePtr.p->uncommitted_used_space > 0);
- pagePtr.p->uncommitted_used_space--;
- key->m_page_idx= ((Fix_page*)pagePtr.p)->alloc_record();
- lsn= disk_page_undo_alloc(pagePtr.p, key, 1, gci, logfile_group_id);
- }
- else
- {
- Uint32 sz= key->m_page_idx;
- ddassert(pagePtr.p->uncommitted_used_space >= sz);
- pagePtr.p->uncommitted_used_space -= sz;
- key->m_page_idx= ((Var_page*)pagePtr.p)->
- alloc_record(sz, (Var_page*)ctemp_page, 0);
-
- lsn= disk_page_undo_alloc(pagePtr.p, key, sz, gci, logfile_group_id);
- }
-}
-
-void
-Dbtup::disk_page_free(Signal *signal,
- Tablerec *tabPtrP, Fragrecord * fragPtrP,
- Local_key* key, PagePtr pagePtr, Uint32 gci)
-{
- jam();
- if (DBG_DISK)
- ndbout << " disk_page_free " << *key << endl;
-
- Uint32 page_idx= key->m_page_idx;
- Uint32 logfile_group_id= fragPtrP->m_logfile_group_id;
- Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info;
- Uint32 old_free= pagePtr.p->free_space;
-
- Uint32 sz;
- Uint64 lsn;
- if (tabPtrP->m_attributes[DD].m_no_of_varsize == 0)
- {
- sz = 1;
- const Uint32 *src= ((Fix_page*)pagePtr.p)->get_ptr(page_idx, 0);
- ndbassert(* (src + 1) != Tup_fixsize_page::FREE_RECORD);
- lsn= disk_page_undo_free(pagePtr.p, key,
- src, tabPtrP->m_offsets[DD].m_fix_header_size,
- gci, logfile_group_id);
-
- ((Fix_page*)pagePtr.p)->free_record(page_idx);
- }
- else
- {
- const Uint32 *src= ((Var_page*)pagePtr.p)->get_ptr(page_idx);
- sz= ((Var_page*)pagePtr.p)->get_entry_len(page_idx);
- lsn= disk_page_undo_free(pagePtr.p, key,
- src, sz,
- gci, logfile_group_id);
-
- ((Var_page*)pagePtr.p)->free_record(page_idx, 0);
- }
-
- Uint32 new_free = pagePtr.p->free_space;
-
- Uint32 ext = pagePtr.p->m_extent_info_ptr;
- Uint32 used = pagePtr.p->uncommitted_used_space;
- Uint32 old_idx = pagePtr.p->list_index;
- ddassert(old_free >= used);
- ddassert(new_free >= used);
- ddassert(new_free >= old_free);
- ddassert((old_idx & 0x8000) == 0);
-
- Uint32 new_idx = alloc.calc_page_free_bits(new_free - used);
- ddassert(alloc.calc_page_free_bits(old_free - used) == old_idx);
-
- Ptr<Extent_info> extentPtr;
- c_extent_pool.getPtr(extentPtr, ext);
-
- if (old_idx != new_idx)
- {
- jam();
- ddassert(extentPtr.p->m_free_page_count[old_idx]);
- extentPtr.p->m_free_page_count[old_idx]--;
- extentPtr.p->m_free_page_count[new_idx]++;
-
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
- LocalDLList<Page> new_list(*pool, alloc.m_dirty_pages[new_idx]);
- LocalDLList<Page> old_list(*pool, alloc.m_dirty_pages[old_idx]);
- old_list.remove(pagePtr);
- new_list.add(pagePtr);
- pagePtr.p->list_index = new_idx;
- }
-
- extentPtr.p->m_free_space += sz;
- update_extent_pos(alloc, extentPtr);
-#if NOT_YET_FREE_EXTENT
- if (check_free(extentPtr.p) == 0)
- {
- ndbout_c("free: extent is free");
- }
-#endif
-}
-
-void
-Dbtup::disk_page_abort_prealloc(Signal *signal, Fragrecord* fragPtrP,
- Local_key* key, Uint32 sz)
-{
- jam();
- Page_cache_client::Request req;
- req.m_callback.m_callbackData= sz;
- req.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::disk_page_abort_prealloc_callback);
-
- int flags= Page_cache_client::DIRTY_REQ;
- memcpy(&req.m_page, key, sizeof(Local_key));
-
- int res= m_pgman.get_page(signal, req, flags);
- jamEntry();
- switch(res)
- {
- case 0:
- jam();
- break;
- case -1:
- ndbrequire(false);
- break;
- default:
- jam();
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, (Uint32)res);
- PagePtr pagePtr;
- pagePtr.i = gpage.i;
- pagePtr.p = reinterpret_cast<Page*>(gpage.p);
-
- disk_page_abort_prealloc_callback_1(signal, fragPtrP, pagePtr, sz);
- }
-}
-
-void
-Dbtup::disk_page_abort_prealloc_callback(Signal* signal,
- Uint32 sz, Uint32 page_id)
-{
- //ndbout_c("disk_alloc_page_callback id: %d", page_id);
- jamEntry();
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, page_id);
-
- PagePtr pagePtr;
- pagePtr.i = gpage.i;
- pagePtr.p = reinterpret_cast<Page*>(gpage.p);
-
- Ptr<Tablerec> tabPtr;
- tabPtr.i= pagePtr.p->m_table_id;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- Ptr<Fragrecord> fragPtr;
- getFragmentrec(fragPtr, pagePtr.p->m_fragment_id, tabPtr.p);
-
- disk_page_abort_prealloc_callback_1(signal, fragPtr.p, pagePtr, sz);
-}
-
-void
-Dbtup::disk_page_abort_prealloc_callback_1(Signal* signal,
- Fragrecord* fragPtrP,
- PagePtr pagePtr,
- Uint32 sz)
-{
- jam();
- disk_page_set_dirty(pagePtr);
-
- Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info;
- Uint32 page_idx = pagePtr.p->list_index;
- Uint32 used = pagePtr.p->uncommitted_used_space;
- Uint32 free = pagePtr.p->free_space;
- Uint32 ext = pagePtr.p->m_extent_info_ptr;
-
- Uint32 old_idx = page_idx & 0x7FFF;
- ddassert(free >= used);
- ddassert(used >= sz);
- ddassert(alloc.calc_page_free_bits(free - used) == old_idx);
- Uint32 new_idx = alloc.calc_page_free_bits(free - used + sz);
-
- Ptr<Extent_info> extentPtr;
- c_extent_pool.getPtr(extentPtr, ext);
- if (old_idx != new_idx)
- {
- jam();
- ddassert(extentPtr.p->m_free_page_count[old_idx]);
- extentPtr.p->m_free_page_count[old_idx]--;
- extentPtr.p->m_free_page_count[new_idx]++;
-
- if (old_idx == page_idx)
- {
- jam();
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
- LocalDLList<Page> old_list(*pool, alloc.m_dirty_pages[old_idx]);
- LocalDLList<Page> new_list(*pool, alloc.m_dirty_pages[new_idx]);
- old_list.remove(pagePtr);
- new_list.add(pagePtr);
- pagePtr.p->list_index = new_idx;
- }
- else
- {
- jam();
- pagePtr.p->list_index = new_idx | 0x8000;
- }
- }
-
- pagePtr.p->uncommitted_used_space = used - sz;
-
- extentPtr.p->m_free_space += sz;
- update_extent_pos(alloc, extentPtr);
-#if NOT_YET_FREE_EXTENT
- if (check_free(extentPtr.p) == 0)
- {
- ndbout_c("abort: extent is free");
- }
-#endif
-}
-
-#if NOT_YET_UNDO_ALLOC_EXTENT
-void
-Dbtup::disk_page_alloc_extent_log_buffer_callback(Signal* signal,
- Uint32 extentPtrI,
- Uint32 unused)
-{
- Ptr<Extent_info> extentPtr;
- c_extent_pool.getPtr(extentPtr, extentPtrI);
-
- Local_key key = extentPtr.p->m_key;
- Tablespace_client2 tsman(signal, c_tsman, &key);
-
- Ptr<Tablerec> tabPtr;
- tabPtr.i= tsman.m_table_id;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- Ptr<Fragrecord> fragPtr;
- getFragmentrec(fragPtr, tsman.m_fragment_id, tabPtr.p);
-
- Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
-
- Disk_undo::AllocExtent alloc;
- alloc.m_table = tabPtr.i;
- alloc.m_fragment = tsman.m_fragment_id;
- alloc.m_page_no = key.m_page_no;
- alloc.m_file_no = key.m_file_no;
- alloc.m_type_length = (Disk_undo::UNDO_ALLOC_EXTENT<<16)|(sizeof(alloc)>> 2);
-
- Logfile_client::Change c[1] = {{ &alloc, sizeof(alloc) >> 2 } };
-
- Uint64 lsn= lgman.add_entry(c, 1);
-
- tsman.update_lsn(&key, lsn);
- jamEntry();
-}
-#endif
-
-Uint64
-Dbtup::disk_page_undo_alloc(Page* page, const Local_key* key,
- Uint32 sz, Uint32 gci, Uint32 logfile_group_id)
-{
- jam();
- Logfile_client lgman(this, c_lgman, logfile_group_id);
-
- Disk_undo::Alloc alloc;
- alloc.m_type_length= (Disk_undo::UNDO_ALLOC << 16) | (sizeof(alloc) >> 2);
- alloc.m_page_no = key->m_page_no;
- alloc.m_file_no_page_idx= key->m_file_no << 16 | key->m_page_idx;
-
- Logfile_client::Change c[1] = {{ &alloc, sizeof(alloc) >> 2 } };
-
- Uint64 lsn= lgman.add_entry(c, 1);
- m_pgman.update_lsn(* key, lsn);
- jamEntry();
-
- return lsn;
-}
-
-Uint64
-Dbtup::disk_page_undo_update(Page* page, const Local_key* key,
- const Uint32* src, Uint32 sz,
- Uint32 gci, Uint32 logfile_group_id)
-{
- jam();
- Logfile_client lgman(this, c_lgman, logfile_group_id);
-
- Disk_undo::Update update;
- update.m_page_no = key->m_page_no;
- update.m_file_no_page_idx= key->m_file_no << 16 | key->m_page_idx;
- update.m_gci= gci;
-
- update.m_type_length=
- (Disk_undo::UNDO_UPDATE << 16) | (sz + (sizeof(update) >> 2) - 1);
-
- Logfile_client::Change c[3] = {
- { &update, 3 },
- { src, sz },
- { &update.m_type_length, 1 }
- };
-
- ndbassert(4*(3 + sz + 1) == (sizeof(update) + 4*sz - 4));
-
- Uint64 lsn= lgman.add_entry(c, 3);
- m_pgman.update_lsn(* key, lsn);
- jamEntry();
-
- return lsn;
-}
-
-Uint64
-Dbtup::disk_page_undo_free(Page* page, const Local_key* key,
- const Uint32* src, Uint32 sz,
- Uint32 gci, Uint32 logfile_group_id)
-{
- jam();
- Logfile_client lgman(this, c_lgman, logfile_group_id);
-
- Disk_undo::Free free;
- free.m_page_no = key->m_page_no;
- free.m_file_no_page_idx= key->m_file_no << 16 | key->m_page_idx;
- free.m_gci= gci;
-
- free.m_type_length=
- (Disk_undo::UNDO_FREE << 16) | (sz + (sizeof(free) >> 2) - 1);
-
- Logfile_client::Change c[3] = {
- { &free, 3 },
- { src, sz },
- { &free.m_type_length, 1 }
- };
-
- ndbassert(4*(3 + sz + 1) == (sizeof(free) + 4*sz - 4));
-
- Uint64 lsn= lgman.add_entry(c, 3);
- m_pgman.update_lsn(* key, lsn);
- jamEntry();
-
- return lsn;
-}
-
-#include <signaldata/LgmanContinueB.hpp>
-
-static Dbtup::Apply_undo f_undo;
-
-#define DBG_UNDO 0
-
-void
-Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn,
- Uint32 type, const Uint32 * ptr, Uint32 len)
-{
- f_undo_done = false;
- f_undo.m_lsn= lsn;
- f_undo.m_ptr= ptr;
- f_undo.m_len= len;
- f_undo.m_type = type;
-
- Page_cache_client::Request preq;
- switch(f_undo.m_type){
- case File_formats::Undofile::UNDO_LCP_FIRST:
- case File_formats::Undofile::UNDO_LCP:
- {
- jam();
- ndbrequire(len == 3);
- Uint32 lcp = ptr[0];
- Uint32 tableId = ptr[1] >> 16;
- Uint32 fragId = ptr[1] & 0xFFFF;
- disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_LCP, lcp);
- disk_restart_undo_next(signal);
-
- if (DBG_UNDO)
- {
- ndbout_c("UNDO LCP %u (%u, %u)", lcp, tableId, fragId);
- }
- return;
- }
- case File_formats::Undofile::UNDO_TUP_ALLOC:
- {
- jam();
- Disk_undo::Alloc* rec= (Disk_undo::Alloc*)ptr;
- preq.m_page.m_page_no = rec->m_page_no;
- preq.m_page.m_file_no = rec->m_file_no_page_idx >> 16;
- preq.m_page.m_page_idx = rec->m_file_no_page_idx & 0xFFFF;
- break;
- }
- case File_formats::Undofile::UNDO_TUP_UPDATE:
- {
- jam();
- Disk_undo::Update* rec= (Disk_undo::Update*)ptr;
- preq.m_page.m_page_no = rec->m_page_no;
- preq.m_page.m_file_no = rec->m_file_no_page_idx >> 16;
- preq.m_page.m_page_idx = rec->m_file_no_page_idx & 0xFFFF;
- break;
- }
- case File_formats::Undofile::UNDO_TUP_FREE:
- {
- jam();
- Disk_undo::Free* rec= (Disk_undo::Free*)ptr;
- preq.m_page.m_page_no = rec->m_page_no;
- preq.m_page.m_file_no = rec->m_file_no_page_idx >> 16;
- preq.m_page.m_page_idx = rec->m_file_no_page_idx & 0xFFFF;
- break;
- }
- case File_formats::Undofile::UNDO_TUP_CREATE:
- /**
- *
- */
- {
- jam();
- Disk_undo::Create* rec= (Disk_undo::Create*)ptr;
- Ptr<Tablerec> tabPtr;
- tabPtr.i= rec->m_table;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
- for(Uint32 i = 0; i<MAX_FRAG_PER_NODE; i++)
- if (tabPtr.p->fragrec[i] != RNIL)
- disk_restart_undo_lcp(tabPtr.i, tabPtr.p->fragid[i],
- Fragrecord::UC_CREATE, 0);
- disk_restart_undo_next(signal);
-
- if (DBG_UNDO)
- {
- ndbout_c("UNDO CREATE (%u)", tabPtr.i);
- }
- return;
- }
- case File_formats::Undofile::UNDO_TUP_DROP:
- {
- jam();
- Disk_undo::Drop* rec = (Disk_undo::Drop*)ptr;
- Ptr<Tablerec> tabPtr;
- tabPtr.i= rec->m_table;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
- for(Uint32 i = 0; i<MAX_FRAG_PER_NODE; i++)
- if (tabPtr.p->fragrec[i] != RNIL)
- disk_restart_undo_lcp(tabPtr.i, tabPtr.p->fragid[i],
- Fragrecord::UC_CREATE, 0);
- disk_restart_undo_next(signal);
-
- if (DBG_UNDO)
- {
- ndbout_c("UNDO DROP (%u)", tabPtr.i);
- }
- return;
- }
- case File_formats::Undofile::UNDO_TUP_ALLOC_EXTENT:
- jam();
- case File_formats::Undofile::UNDO_TUP_FREE_EXTENT:
- jam();
- disk_restart_undo_next(signal);
- return;
-
- case File_formats::Undofile::UNDO_END:
- jam();
- f_undo_done = true;
- return;
- default:
- ndbrequire(false);
- }
-
- f_undo.m_key = preq.m_page;
- preq.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::disk_restart_undo_callback);
-
- int flags = 0;
- int res= m_pgman.get_page(signal, preq, flags);
- jamEntry();
- switch(res)
- {
- case 0:
- break; // Wait for callback
- case -1:
- ndbrequire(false);
- break;
- default:
- execute(signal, preq.m_callback, res); // run callback
- }
-}
-
-void
-Dbtup::disk_restart_undo_next(Signal* signal)
-{
- signal->theData[0] = LgmanContinueB::EXECUTE_UNDO_RECORD;
- sendSignal(LGMAN_REF, GSN_CONTINUEB, signal, 1, JBB);
-}
-
-void
-Dbtup::disk_restart_lcp_id(Uint32 tableId, Uint32 fragId, Uint32 lcpId)
-{
- jamEntry();
-
- if (lcpId == RNIL)
- {
- disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_CREATE, 0);
- if (DBG_UNDO)
- {
- ndbout_c("mark_no_lcp (%u, %u)", tableId, fragId);
- }
- }
- else
- {
- disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_SET_LCP, lcpId);
- if (DBG_UNDO)
- {
- ndbout_c("mark_no_lcp (%u, %u)", tableId, fragId);
- }
-
- }
-}
-
-void
-Dbtup::disk_restart_undo_lcp(Uint32 tableId, Uint32 fragId, Uint32 flag,
- Uint32 lcpId)
-{
- Ptr<Tablerec> tabPtr;
- tabPtr.i= tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- if (tabPtr.p->tableStatus == DEFINED)
- {
- jam();
- FragrecordPtr fragPtr;
- getFragmentrec(fragPtr, fragId, tabPtr.p);
- if (!fragPtr.isNull())
- {
- jam();
- switch(flag){
- case Fragrecord::UC_CREATE:
- jam();
- fragPtr.p->m_undo_complete |= flag;
- return;
- case Fragrecord::UC_LCP:
- jam();
- if (fragPtr.p->m_undo_complete == 0 &&
- fragPtr.p->m_restore_lcp_id == lcpId)
- {
- jam();
- fragPtr.p->m_undo_complete |= flag;
- if (DBG_UNDO)
- ndbout_c("table: %u fragment: %u lcp: %u -> done",
- tableId, fragId, lcpId);
- }
- return;
- case Fragrecord::UC_SET_LCP:
- {
- jam();
- if (DBG_UNDO)
- ndbout_c("table: %u fragment: %u restore to lcp: %u",
- tableId, fragId, lcpId);
- ndbrequire(fragPtr.p->m_undo_complete == 0);
- ndbrequire(fragPtr.p->m_restore_lcp_id == RNIL);
- fragPtr.p->m_restore_lcp_id = lcpId;
- return;
- }
- }
- jamLine(flag);
- ndbrequire(false);
- }
- }
-}
-
-void
-Dbtup::disk_restart_undo_callback(Signal* signal,
- Uint32 id,
- Uint32 page_id)
-{
- jamEntry();
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, page_id);
- PagePtr pagePtr;
- pagePtr.i = gpage.i;
- pagePtr.p = reinterpret_cast<Page*>(gpage.p);
-
- Apply_undo* undo = &f_undo;
-
- bool update = false;
- if (! (pagePtr.p->list_index & 0x8000) ||
- pagePtr.p->nextList != RNIL ||
- pagePtr.p->prevList != RNIL)
- {
- jam();
- update = true;
- pagePtr.p->list_index |= 0x8000;
- pagePtr.p->nextList = pagePtr.p->prevList = RNIL;
- }
-
- Uint32 tableId= pagePtr.p->m_table_id;
- Uint32 fragId = pagePtr.p->m_fragment_id;
-
- if (tableId >= cnoOfTablerec)
- {
- jam();
- if (DBG_UNDO)
- ndbout_c("UNDO table> %u", tableId);
- disk_restart_undo_next(signal);
- return;
- }
- undo->m_table_ptr.i = tableId;
- ptrCheckGuard(undo->m_table_ptr, cnoOfTablerec, tablerec);
-
- if (undo->m_table_ptr.p->tableStatus != DEFINED)
- {
- jam();
- if (DBG_UNDO)
- ndbout_c("UNDO !defined (%u) ", tableId);
- disk_restart_undo_next(signal);
- return;
- }
-
- getFragmentrec(undo->m_fragment_ptr, fragId, undo->m_table_ptr.p);
- if(undo->m_fragment_ptr.isNull())
- {
- jam();
- if (DBG_UNDO)
- ndbout_c("UNDO fragment null %u/%u", tableId, fragId);
- disk_restart_undo_next(signal);
- return;
- }
-
- if (undo->m_fragment_ptr.p->m_undo_complete)
- {
- jam();
- if (DBG_UNDO)
- ndbout_c("UNDO undo complete %u/%u", tableId, fragId);
- disk_restart_undo_next(signal);
- return;
- }
-
- Local_key key = undo->m_key;
-// key.m_page_no = pagePtr.p->m_page_no;
-// key.m_file_no = pagePtr.p->m_file_no;
-
- Uint64 lsn = 0;
- lsn += pagePtr.p->m_page_header.m_page_lsn_hi; lsn <<= 32;
- lsn += pagePtr.p->m_page_header.m_page_lsn_lo;
-
- undo->m_page_ptr = pagePtr;
-
- if (undo->m_lsn <= lsn)
- {
- jam();
- if (DBG_UNDO)
- {
- ndbout << "apply: " << undo->m_lsn << "(" << lsn << " )"
- << key << " type: " << undo->m_type << endl;
- }
-
- update = true;
- if (DBG_UNDO)
- ndbout_c("applying %lld", undo->m_lsn);
- /**
- * Apply undo record
- */
- switch(undo->m_type){
- case File_formats::Undofile::UNDO_TUP_ALLOC:
- jam();
- disk_restart_undo_alloc(undo);
- break;
- case File_formats::Undofile::UNDO_TUP_UPDATE:
- jam();
- disk_restart_undo_update(undo);
- break;
- case File_formats::Undofile::UNDO_TUP_FREE:
- jam();
- disk_restart_undo_free(undo);
- break;
- default:
- ndbrequire(false);
- }
-
- if (DBG_UNDO)
- ndbout << "disk_restart_undo: " << undo->m_type << " "
- << undo->m_key << endl;
-
- lsn = undo->m_lsn - 1; // make sure undo isn't run again...
-
- m_pgman.update_lsn(undo->m_key, lsn);
- jamEntry();
-
- disk_restart_undo_page_bits(signal, undo);
- }
- else if (DBG_UNDO)
- {
- jam();
- ndbout << "ignore: " << undo->m_lsn << "(" << lsn << " )"
- << key << " type: " << undo->m_type
- << " tab: " << tableId << endl;
- }
-
- disk_restart_undo_next(signal);
-}
-
-void
-Dbtup::disk_restart_undo_alloc(Apply_undo* undo)
-{
- ndbassert(undo->m_page_ptr.p->m_file_no == undo->m_key.m_file_no);
- ndbassert(undo->m_page_ptr.p->m_page_no == undo->m_key.m_page_no);
- if (undo->m_table_ptr.p->m_attributes[DD].m_no_of_varsize == 0)
- {
- ((Fix_page*)undo->m_page_ptr.p)->free_record(undo->m_key.m_page_idx);
- }
- else
- ((Var_page*)undo->m_page_ptr.p)->free_record(undo->m_key.m_page_idx, 0);
-}
-
-void
-Dbtup::disk_restart_undo_update(Apply_undo* undo)
-{
- Uint32* ptr;
- Uint32 len= undo->m_len - 4;
- if (undo->m_table_ptr.p->m_attributes[DD].m_no_of_varsize == 0)
- {
- ptr= ((Fix_page*)undo->m_page_ptr.p)->get_ptr(undo->m_key.m_page_idx, len);
- ndbrequire(len == undo->m_table_ptr.p->m_offsets[DD].m_fix_header_size);
- }
- else
- {
- ptr= ((Var_page*)undo->m_page_ptr.p)->get_ptr(undo->m_key.m_page_idx);
- abort();
- }
-
- const Disk_undo::Update *update = (const Disk_undo::Update*)undo->m_ptr;
- const Uint32* src= update->m_data;
- memcpy(ptr, src, 4 * len);
-}
-
-void
-Dbtup::disk_restart_undo_free(Apply_undo* undo)
-{
- Uint32* ptr, idx = undo->m_key.m_page_idx;
- Uint32 len= undo->m_len - 4;
- if (undo->m_table_ptr.p->m_attributes[DD].m_no_of_varsize == 0)
- {
- ndbrequire(len == undo->m_table_ptr.p->m_offsets[DD].m_fix_header_size);
- idx= ((Fix_page*)undo->m_page_ptr.p)->alloc_record(idx);
- ptr= ((Fix_page*)undo->m_page_ptr.p)->get_ptr(idx, len);
- }
- else
- {
- abort();
- }
-
- ndbrequire(idx == undo->m_key.m_page_idx);
- const Disk_undo::Free *free = (const Disk_undo::Free*)undo->m_ptr;
- const Uint32* src= free->m_data;
- memcpy(ptr, src, 4 * len);
-}
-
-void
-Dbtup::disk_restart_undo_page_bits(Signal* signal, Apply_undo* undo)
-{
- Fragrecord* fragPtrP = undo->m_fragment_ptr.p;
- Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info;
-
- /**
- * Set alloc.m_curr_extent_info_ptr_i to
- * current this extent (and move old extend into free matrix)
- */
- Page* pageP = undo->m_page_ptr.p;
- Uint32 free = pageP->free_space;
- Uint32 new_bits = alloc.calc_page_free_bits(free);
- pageP->list_index = 0x8000 | new_bits;
-
- Tablespace_client tsman(signal, c_tsman,
- fragPtrP->fragTableId,
- fragPtrP->fragmentId,
- fragPtrP->m_tablespace_id);
-
- tsman.restart_undo_page_free_bits(&undo->m_key, new_bits);
- jamEntry();
-}
-
-int
-Dbtup::disk_restart_alloc_extent(Uint32 tableId, Uint32 fragId,
- const Local_key* key, Uint32 pages)
-{
- TablerecPtr tabPtr;
- FragrecordPtr fragPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
- if (tabPtr.p->tableStatus == DEFINED)
- {
- getFragmentrec(fragPtr, fragId, tabPtr.p);
- if (fragPtr.p->m_undo_complete & Fragrecord::UC_CREATE)
- {
- jam();
- return -1;
- }
-
- if (!fragPtr.isNull())
- {
- Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
-
- Ptr<Extent_info> ext;
- ndbrequire(c_extent_pool.seize(ext));
-
- ndbout << "allocated " << pages << " pages: " << *key << endl;
-
- ext.p->m_key = *key;
- ext.p->m_first_page_no = ext.p->m_key.m_page_no;
- ext.p->m_free_space= 0;
- bzero(ext.p->m_free_page_count, sizeof(ext.p->m_free_page_count));
-
- if (alloc.m_curr_extent_info_ptr_i != RNIL)
- {
- jam();
- Ptr<Extent_info> old;
- c_extent_pool.getPtr(old, alloc.m_curr_extent_info_ptr_i);
- ndbassert(old.p->m_free_matrix_pos == RNIL);
- Uint32 pos= alloc.calc_extent_pos(old.p);
- Local_extent_info_list new_list(c_extent_pool, alloc.m_free_extents[pos]);
- new_list.add(old);
- old.p->m_free_matrix_pos= pos;
- }
-
- alloc.m_curr_extent_info_ptr_i = ext.i;
- ext.p->m_free_matrix_pos = RNIL;
- c_extent_hash.add(ext);
-
- Local_fragment_extent_list list1(c_extent_pool, alloc.m_extent_list);
- list1.add(ext);
- return 0;
- }
- }
-
- return -1;
-}
-
-void
-Dbtup::disk_restart_page_bits(Uint32 tableId, Uint32 fragId,
- const Local_key*, Uint32 bits)
-{
- jam();
- TablerecPtr tabPtr;
- FragrecordPtr fragPtr;
- tabPtr.i = tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
- getFragmentrec(fragPtr, fragId, tabPtr.p);
- Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
-
- Ptr<Extent_info> ext;
- c_extent_pool.getPtr(ext, alloc.m_curr_extent_info_ptr_i);
-
- Uint32 size= alloc.calc_page_free_space(bits);
-
- ext.p->m_free_space += size;
- ext.p->m_free_page_count[bits]++;
- ndbassert(ext.p->m_free_matrix_pos == RNIL);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
deleted file mode 100644
index d7d7f20bbc7..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ /dev/null
@@ -1,3205 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#include <Dblqh.hpp>
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <AttributeDescriptor.hpp>
-#include "AttributeOffset.hpp"
-#include <AttributeHeader.hpp>
-#include <Interpreter.hpp>
-#include <signaldata/TupKey.hpp>
-#include <signaldata/AttrInfo.hpp>
-#include <NdbSqlUtil.hpp>
-
-/* ----------------------------------------------------------------- */
-/* ----------- INIT_STORED_OPERATIONREC -------------- */
-/* ----------------------------------------------------------------- */
-int Dbtup::initStoredOperationrec(Operationrec* regOperPtr,
- KeyReqStruct* req_struct,
- Uint32 storedId)
-{
- jam();
- StoredProcPtr storedPtr;
- c_storedProcPool.getPtr(storedPtr, storedId);
- if (storedPtr.i != RNIL) {
- if (storedPtr.p->storedCode == ZSCAN_PROCEDURE) {
- storedPtr.p->storedCounter++;
- regOperPtr->firstAttrinbufrec= storedPtr.p->storedLinkFirst;
- regOperPtr->lastAttrinbufrec= storedPtr.p->storedLinkLast;
- regOperPtr->currentAttrinbufLen= storedPtr.p->storedProcLength;
- req_struct->attrinfo_len= storedPtr.p->storedProcLength;
- return ZOK;
- }
- }
- terrorCode= ZSTORED_PROC_ID_ERROR;
- return terrorCode;
-}
-
-void Dbtup::copyAttrinfo(Operationrec * regOperPtr,
- Uint32* inBuffer)
-{
- AttrbufrecPtr copyAttrBufPtr;
- Uint32 RnoOfAttrBufrec= cnoOfAttrbufrec;
- int RbufLen;
- Uint32 RinBufIndex= 0;
- Uint32 Rnext;
- Uint32 Rfirst;
- Uint32 TstoredProcedure= (regOperPtr->storedProcedureId != ZNIL);
- Uint32 RnoFree= cnoFreeAttrbufrec;
-
-//-------------------------------------------------------------------------
-// As a prelude to the execution of the TUPKEYREQ we will copy the program
-// into the inBuffer to enable easy execution without any complex jumping
-// between the buffers. In particular this will make the interpreter less
-// complex. Hopefully it does also improve performance.
-//-------------------------------------------------------------------------
- copyAttrBufPtr.i= regOperPtr->firstAttrinbufrec;
- while (copyAttrBufPtr.i != RNIL) {
- jam();
- ndbrequire(copyAttrBufPtr.i < RnoOfAttrBufrec);
- ptrAss(copyAttrBufPtr, attrbufrec);
- RbufLen = copyAttrBufPtr.p->attrbuf[ZBUF_DATA_LEN];
- Rnext = copyAttrBufPtr.p->attrbuf[ZBUF_NEXT];
- Rfirst = cfirstfreeAttrbufrec;
- /*
- * ATTRINFO comes from 2 mutually exclusive places:
- * 1) TUPKEYREQ (also interpreted part)
- * 2) STORED_PROCREQ before scan start
- * Assert here that both have a check for overflow.
- * The "<" instead of "<=" is intentional.
- */
- ndbrequire(RinBufIndex + RbufLen < ZATTR_BUFFER_SIZE);
- MEMCOPY_NO_WORDS(&inBuffer[RinBufIndex],
- &copyAttrBufPtr.p->attrbuf[0],
- RbufLen);
- RinBufIndex += RbufLen;
- if (!TstoredProcedure) {
- copyAttrBufPtr.p->attrbuf[ZBUF_NEXT]= Rfirst;
- cfirstfreeAttrbufrec= copyAttrBufPtr.i;
- RnoFree++;
- }
- copyAttrBufPtr.i= Rnext;
- }
- cnoFreeAttrbufrec= RnoFree;
- if (TstoredProcedure) {
- jam();
- StoredProcPtr storedPtr;
- c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->storedProcedureId);
- ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
- storedPtr.p->storedCounter--;
- }
- // Release the ATTRINFO buffers
- regOperPtr->storedProcedureId= RNIL;
- regOperPtr->firstAttrinbufrec= RNIL;
- regOperPtr->lastAttrinbufrec= RNIL;
- regOperPtr->m_any_value= 0;
-}
-
-void Dbtup::handleATTRINFOforTUPKEYREQ(Signal* signal,
- const Uint32 *data,
- Uint32 len,
- Operationrec * regOperPtr)
-{
- while(len)
- {
- Uint32 length = len > AttrInfo::DataLength ? AttrInfo::DataLength : len;
-
- AttrbufrecPtr TAttrinbufptr;
- TAttrinbufptr.i= cfirstfreeAttrbufrec;
- if ((cfirstfreeAttrbufrec < cnoOfAttrbufrec) &&
- (cnoFreeAttrbufrec > MIN_ATTRBUF)) {
- ptrAss(TAttrinbufptr, attrbufrec);
- MEMCOPY_NO_WORDS(&TAttrinbufptr.p->attrbuf[0],
- data,
- length);
- Uint32 RnoFree= cnoFreeAttrbufrec;
- Uint32 Rnext= TAttrinbufptr.p->attrbuf[ZBUF_NEXT];
- TAttrinbufptr.p->attrbuf[ZBUF_DATA_LEN]= length;
- TAttrinbufptr.p->attrbuf[ZBUF_NEXT]= RNIL;
-
- AttrbufrecPtr locAttrinbufptr;
- Uint32 RnewLen= regOperPtr->currentAttrinbufLen;
-
- locAttrinbufptr.i= regOperPtr->lastAttrinbufrec;
- cfirstfreeAttrbufrec= Rnext;
- cnoFreeAttrbufrec= RnoFree - 1;
- RnewLen += length;
- regOperPtr->lastAttrinbufrec= TAttrinbufptr.i;
- regOperPtr->currentAttrinbufLen= RnewLen;
- if (locAttrinbufptr.i == RNIL) {
- regOperPtr->firstAttrinbufrec= TAttrinbufptr.i;
- } else {
- jam();
- ptrCheckGuard(locAttrinbufptr, cnoOfAttrbufrec, attrbufrec);
- locAttrinbufptr.p->attrbuf[ZBUF_NEXT]= TAttrinbufptr.i;
- }
- if (RnewLen < ZATTR_BUFFER_SIZE) {
- } else {
- jam();
- set_trans_state(regOperPtr, TRANS_TOO_MUCH_AI);
- return;
- }
- } else if (cnoFreeAttrbufrec <= MIN_ATTRBUF) {
- jam();
- set_trans_state(regOperPtr, TRANS_ERROR_WAIT_TUPKEYREQ);
- } else {
- ndbrequire(false);
- }
-
- len -= length;
- data += length;
- }
-}
-
-void Dbtup::execATTRINFO(Signal* signal)
-{
- Uint32 Rsig0= signal->theData[0];
- Uint32 Rlen= signal->length();
- jamEntry();
-
- receive_attrinfo(signal, Rsig0, signal->theData+3, Rlen-3);
-}
-
-void
-Dbtup::receive_attrinfo(Signal* signal, Uint32 op,
- const Uint32* data, Uint32 Rlen)
-{
- OperationrecPtr regOpPtr;
- regOpPtr.i= op;
- c_operation_pool.getPtr(regOpPtr, op);
- TransState trans_state= get_trans_state(regOpPtr.p);
- if (trans_state == TRANS_IDLE) {
- handleATTRINFOforTUPKEYREQ(signal, data, Rlen, regOpPtr.p);
- return;
- } else if (trans_state == TRANS_WAIT_STORED_PROCEDURE_ATTR_INFO) {
- storedProcedureAttrInfo(signal, regOpPtr.p, data, Rlen, false);
- return;
- }
- switch (trans_state) {
- case TRANS_ERROR_WAIT_STORED_PROCREQ:
- jam();
- case TRANS_TOO_MUCH_AI:
- jam();
- case TRANS_ERROR_WAIT_TUPKEYREQ:
- jam();
- return; /* IGNORE ATTRINFO IN THOSE STATES, WAITING FOR ABORT SIGNAL */
- case TRANS_DISCONNECTED:
- jam();
- case TRANS_STARTED:
- jam();
- default:
- ndbrequire(false);
- }
-}
-
-void
-Dbtup::setChecksum(Tuple_header* tuple_ptr,
- Tablerec* regTabPtr)
-{
- tuple_ptr->m_checksum= 0;
- tuple_ptr->m_checksum= calculateChecksum(tuple_ptr, regTabPtr);
-}
-
-Uint32
-Dbtup::calculateChecksum(Tuple_header* tuple_ptr,
- Tablerec* regTabPtr)
-{
- Uint32 checksum;
- Uint32 i, rec_size, *tuple_header;
- rec_size= regTabPtr->m_offsets[MM].m_fix_header_size;
- tuple_header= tuple_ptr->m_data;
- checksum= 0;
- // includes tupVersion
- //printf("%p - ", tuple_ptr);
-
- for (i= 0; i < rec_size-Tuple_header::HeaderSize; i++) {
- checksum ^= tuple_header[i];
- //printf("%.8x ", tuple_header[i]);
- }
-
- //printf("-> %.8x\n", checksum);
-
-#if 0
- if (var_sized) {
- /*
- if (! req_struct->fix_var_together) {
- jam();
- checksum ^= tuple_header[rec_size];
- }
- */
- jam();
- var_data_part= req_struct->var_data_start;
- vsize_words= calculate_total_var_size(req_struct->var_len_array,
- regTabPtr->no_var_attr);
- ndbassert(req_struct->var_data_end >= &var_data_part[vsize_words]);
- for (i= 0; i < vsize_words; i++) {
- checksum ^= var_data_part[i];
- }
- }
-#endif
- return checksum;
-}
-
-/* ----------------------------------------------------------------- */
-/* ----------- INSERT_ACTIVE_OP_LIST -------------- */
-/* ----------------------------------------------------------------- */
-bool
-Dbtup::insertActiveOpList(OperationrecPtr regOperPtr,
- KeyReqStruct* req_struct)
-{
- OperationrecPtr prevOpPtr;
- ndbrequire(!regOperPtr.p->op_struct.in_active_list);
- regOperPtr.p->op_struct.in_active_list= true;
- req_struct->prevOpPtr.i=
- prevOpPtr.i= req_struct->m_tuple_ptr->m_operation_ptr_i;
- regOperPtr.p->prevActiveOp= prevOpPtr.i;
- regOperPtr.p->nextActiveOp= RNIL;
- regOperPtr.p->m_undo_buffer_space= 0;
- req_struct->m_tuple_ptr->m_operation_ptr_i= regOperPtr.i;
- if (prevOpPtr.i == RNIL) {
- set_change_mask_state(regOperPtr.p, USE_SAVED_CHANGE_MASK);
- regOperPtr.p->saved_change_mask[0] = 0;
- regOperPtr.p->saved_change_mask[1] = 0;
- return true;
- } else {
- req_struct->prevOpPtr.p= prevOpPtr.p= c_operation_pool.getPtr(prevOpPtr.i);
- prevOpPtr.p->nextActiveOp= regOperPtr.i;
-
- regOperPtr.p->op_struct.m_wait_log_buffer=
- prevOpPtr.p->op_struct.m_wait_log_buffer;
- regOperPtr.p->op_struct.m_load_diskpage_on_commit=
- prevOpPtr.p->op_struct.m_load_diskpage_on_commit;
- regOperPtr.p->m_undo_buffer_space= prevOpPtr.p->m_undo_buffer_space;
- // start with prev mask (matters only for UPD o UPD)
- set_change_mask_state(regOperPtr.p, get_change_mask_state(prevOpPtr.p));
- regOperPtr.p->saved_change_mask[0] = prevOpPtr.p->saved_change_mask[0];
- regOperPtr.p->saved_change_mask[1] = prevOpPtr.p->saved_change_mask[1];
-
- regOperPtr.p->m_any_value = prevOpPtr.p->m_any_value;
-
- prevOpPtr.p->op_struct.m_wait_log_buffer= 0;
- prevOpPtr.p->op_struct.m_load_diskpage_on_commit= 0;
-
- if(prevOpPtr.p->op_struct.tuple_state == TUPLE_PREPARED)
- {
- Uint32 op= regOperPtr.p->op_struct.op_type;
- Uint32 prevOp= prevOpPtr.p->op_struct.op_type;
- if (prevOp == ZDELETE)
- {
- if(op == ZINSERT)
- {
- // mark both
- prevOpPtr.p->op_struct.delete_insert_flag= true;
- regOperPtr.p->op_struct.delete_insert_flag= true;
- return true;
- } else {
- terrorCode= ZTUPLE_DELETED_ERROR;
- return false;
- }
- }
- else if(op == ZINSERT && prevOp != ZDELETE)
- {
- terrorCode= ZINSERT_ERROR;
- return false;
- }
- return true;
- }
- else
- {
- terrorCode= ZMUST_BE_ABORTED_ERROR;
- return false;
- }
- }
-}
-
-bool
-Dbtup::setup_read(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- bool disk)
-{
- OperationrecPtr currOpPtr;
- currOpPtr.i= req_struct->m_tuple_ptr->m_operation_ptr_i;
- if (currOpPtr.i == RNIL)
- {
- if (regTabPtr->need_expand(disk))
- prepare_read(req_struct, regTabPtr, disk);
- return true;
- }
-
- do {
- Uint32 savepointId= regOperPtr->savepointId;
- bool dirty= req_struct->dirty_op;
-
- c_operation_pool.getPtr(currOpPtr);
- bool sameTrans= c_lqh->is_same_trans(currOpPtr.p->userpointer,
- req_struct->trans_id1,
- req_struct->trans_id2);
- /**
- * Read committed in same trans reads latest copy
- */
- if(dirty && !sameTrans)
- {
- savepointId= 0;
- }
- else if(sameTrans)
- {
- // Use savepoint even in read committed mode
- dirty= false;
- }
-
- bool found= find_savepoint(currOpPtr, savepointId);
-
- Uint32 currOp= currOpPtr.p->op_struct.op_type;
-
- if((found && currOp == ZDELETE) ||
- ((dirty || !found) && currOp == ZINSERT))
- {
- terrorCode= ZTUPLE_DELETED_ERROR;
- break;
- }
-
- if(dirty || !found)
- {
-
- }
- else
- {
- req_struct->m_tuple_ptr= (Tuple_header*)
- c_undo_buffer.get_ptr(&currOpPtr.p->m_copy_tuple_location);
- }
-
- if (regTabPtr->need_expand(disk))
- prepare_read(req_struct, regTabPtr, disk);
-
-#if 0
- ndbout_c("reading copy");
- Uint32 *var_ptr = fixed_ptr+regTabPtr->var_offset;
- req_struct->m_tuple_ptr= fixed_ptr;
- req_struct->fix_var_together= true;
- req_struct->var_len_array= (Uint16*)var_ptr;
- req_struct->var_data_start= var_ptr+regTabPtr->var_array_wsize;
- Uint32 var_sz32= init_var_pos_array((Uint16*)var_ptr,
- req_struct->var_pos_array,
- regTabPtr->no_var_attr);
- req_struct->var_data_end= var_ptr+regTabPtr->var_array_wsize + var_sz32;
-#endif
- return true;
- } while(0);
-
- return false;
-}
-
-int
-Dbtup::load_diskpage(Signal* signal,
- Uint32 opRec, Uint32 fragPtrI,
- Uint32 local_key, Uint32 flags)
-{
- c_operation_pool.getPtr(operPtr, opRec);
- fragptr.i= fragPtrI;
- ptrCheckGuard(fragptr, cnoOfFragrec, fragrecord);
-
- Operationrec * regOperPtr= operPtr.p;
- Fragrecord * regFragPtr= fragptr.p;
-
- tabptr.i = regFragPtr->fragTableId;
- ptrCheckGuard(tabptr, cnoOfTablerec, tablerec);
- Tablerec* regTabPtr = tabptr.p;
-
- if(local_key == ~(Uint32)0)
- {
- jam();
- regOperPtr->op_struct.m_wait_log_buffer= 1;
- regOperPtr->op_struct.m_load_diskpage_on_commit= 1;
- return 1;
- }
-
- jam();
- Uint32 page_idx= local_key & MAX_TUPLES_PER_PAGE;
- Uint32 frag_page_id= local_key >> MAX_TUPLES_BITS;
- regOperPtr->m_tuple_location.m_page_no= getRealpid(regFragPtr,
- frag_page_id);
- regOperPtr->m_tuple_location.m_page_idx= page_idx;
-
- PagePtr page_ptr;
- Uint32* tmp= get_ptr(&page_ptr, &regOperPtr->m_tuple_location, regTabPtr);
- Tuple_header* ptr= (Tuple_header*)tmp;
-
- int res= 1;
- if(ptr->m_header_bits & Tuple_header::DISK_PART)
- {
- Page_cache_client::Request req;
- memcpy(&req.m_page, ptr->get_disk_ref_ptr(regTabPtr), sizeof(Local_key));
- req.m_callback.m_callbackData= opRec;
- req.m_callback.m_callbackFunction=
- safe_cast(&Dbtup::disk_page_load_callback);
-
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(4022))
- {
- flags |= Page_cache_client::DELAY_REQ;
- req.m_delay_until_time = NdbTick_CurrentMillisecond()+(Uint64)3000;
- }
-#endif
-
- if((res= m_pgman.get_page(signal, req, flags)) > 0)
- {
- //ndbout_c("in cache");
- // In cache
- }
- else if(res == 0)
- {
- //ndbout_c("waiting for callback");
- // set state
- }
- else
- {
- // Error
- }
- }
-
- switch(flags & 7)
- {
- case ZREAD:
- case ZREAD_EX:
- break;
- case ZDELETE:
- case ZUPDATE:
- case ZINSERT:
- case ZWRITE:
- regOperPtr->op_struct.m_wait_log_buffer= 1;
- regOperPtr->op_struct.m_load_diskpage_on_commit= 1;
- }
- return res;
-}
-
-void
-Dbtup::disk_page_load_callback(Signal* signal, Uint32 opRec, Uint32 page_id)
-{
- c_operation_pool.getPtr(operPtr, opRec);
- c_lqh->acckeyconf_load_diskpage_callback(signal,
- operPtr.p->userpointer, page_id);
-}
-
-int
-Dbtup::load_diskpage_scan(Signal* signal,
- Uint32 opRec, Uint32 fragPtrI,
- Uint32 local_key, Uint32 flags)
-{
- c_operation_pool.getPtr(operPtr, opRec);
- fragptr.i= fragPtrI;
- ptrCheckGuard(fragptr, cnoOfFragrec, fragrecord);
-
- Operationrec * regOperPtr= operPtr.p;
- Fragrecord * regFragPtr= fragptr.p;
-
- tabptr.i = regFragPtr->fragTableId;
- ptrCheckGuard(tabptr, cnoOfTablerec, tablerec);
- Tablerec* regTabPtr = tabptr.p;
-
- jam();
- Uint32 page_idx= local_key & MAX_TUPLES_PER_PAGE;
- Uint32 frag_page_id= local_key >> MAX_TUPLES_BITS;
- regOperPtr->m_tuple_location.m_page_no= getRealpid(regFragPtr,
- frag_page_id);
- regOperPtr->m_tuple_location.m_page_idx= page_idx;
- regOperPtr->op_struct.m_load_diskpage_on_commit= 0;
-
- PagePtr page_ptr;
- Uint32* tmp= get_ptr(&page_ptr, &regOperPtr->m_tuple_location, regTabPtr);
- Tuple_header* ptr= (Tuple_header*)tmp;
-
- int res= 1;
- if(ptr->m_header_bits & Tuple_header::DISK_PART)
- {
- Page_cache_client::Request req;
- memcpy(&req.m_page, ptr->get_disk_ref_ptr(regTabPtr), sizeof(Local_key));
- req.m_callback.m_callbackData= opRec;
- req.m_callback.m_callbackFunction=
- safe_cast(&Dbtup::disk_page_load_scan_callback);
-
- if((res= m_pgman.get_page(signal, req, flags)) > 0)
- {
- // ndbout_c("in cache");
- // In cache
- }
- else if(res == 0)
- {
- //ndbout_c("waiting for callback");
- // set state
- }
- else
- {
- // Error
- }
- }
- return res;
-}
-
-void
-Dbtup::disk_page_load_scan_callback(Signal* signal,
- Uint32 opRec, Uint32 page_id)
-{
- c_operation_pool.getPtr(operPtr, opRec);
- c_lqh->next_scanconf_load_diskpage_callback(signal,
- operPtr.p->userpointer, page_id);
-}
-
-void Dbtup::execTUPKEYREQ(Signal* signal)
-{
- TupKeyReq * tupKeyReq= (TupKeyReq *)signal->getDataPtr();
- KeyReqStruct req_struct;
- Uint32 sig1, sig2, sig3, sig4;
-
- Uint32 RoperPtr= tupKeyReq->connectPtr;
- Uint32 Rfragptr= tupKeyReq->fragPtr;
-
- Uint32 RnoOfFragrec= cnoOfFragrec;
- Uint32 RnoOfTablerec= cnoOfTablerec;
-
- jamEntry();
- fragptr.i= Rfragptr;
-
- ndbrequire(Rfragptr < RnoOfFragrec);
-
- c_operation_pool.getPtr(operPtr, RoperPtr);
- ptrAss(fragptr, fragrecord);
-
- Uint32 TrequestInfo= tupKeyReq->request;
-
- Operationrec * regOperPtr= operPtr.p;
- Fragrecord * regFragPtr= fragptr.p;
-
- tabptr.i = regFragPtr->fragTableId;
- ptrCheckGuard(tabptr, RnoOfTablerec, tablerec);
- Tablerec* regTabPtr = tabptr.p;
-
- req_struct.signal= signal;
- req_struct.dirty_op= TrequestInfo & 1;
- req_struct.interpreted_exec= (TrequestInfo >> 10) & 1;
- req_struct.no_fired_triggers= 0;
- req_struct.read_length= 0;
- req_struct.max_attr_id_updated= 0;
- req_struct.no_changed_attrs= 0;
- req_struct.last_row= false;
- req_struct.changeMask.clear();
-
- if (unlikely(get_trans_state(regOperPtr) != TRANS_IDLE))
- {
- TUPKEY_abort(signal, 39);
- return;
- }
-
- /* ----------------------------------------------------------------- */
- // Operation is ZREAD when we arrive here so no need to worry about the
- // abort process.
- /* ----------------------------------------------------------------- */
- /* ----------- INITIATE THE OPERATION RECORD -------------- */
- /* ----------------------------------------------------------------- */
- Uint32 Rstoredid= tupKeyReq->storedProcedure;
-
- regOperPtr->fragmentPtr= Rfragptr;
- regOperPtr->op_struct.op_type= (TrequestInfo >> 6) & 0xf;
- regOperPtr->op_struct.delete_insert_flag = false;
- regOperPtr->storedProcedureId= Rstoredid;
-
- regOperPtr->m_copy_tuple_location.setNull();
- regOperPtr->tupVersion= ZNIL;
-
- sig1= tupKeyReq->savePointId;
- sig2= tupKeyReq->primaryReplica;
- sig3= tupKeyReq->keyRef2;
-
- regOperPtr->savepointId= sig1;
- regOperPtr->op_struct.primary_replica= sig2;
- Uint32 pageidx = regOperPtr->m_tuple_location.m_page_idx= sig3;
-
- sig1= tupKeyReq->opRef;
- sig2= tupKeyReq->tcOpIndex;
- sig3= tupKeyReq->coordinatorTC;
- sig4= tupKeyReq->keyRef1;
-
- req_struct.tc_operation_ptr= sig1;
- req_struct.TC_index= sig2;
- req_struct.TC_ref= sig3;
- Uint32 pageid = req_struct.frag_page_id= sig4;
- req_struct.m_use_rowid = (TrequestInfo >> 11) & 1;
-
- sig1= tupKeyReq->attrBufLen;
- sig2= tupKeyReq->applRef;
- sig3= tupKeyReq->transId1;
- sig4= tupKeyReq->transId2;
-
- Uint32 disk_page= tupKeyReq->disk_page;
-
- req_struct.log_size= sig1;
- req_struct.attrinfo_len= sig1;
- req_struct.rec_blockref= sig2;
- req_struct.trans_id1= sig3;
- req_struct.trans_id2= sig4;
- req_struct.m_disk_page_ptr.i= disk_page;
-
- sig1 = tupKeyReq->m_row_id_page_no;
- sig2 = tupKeyReq->m_row_id_page_idx;
-
- req_struct.m_row_id.m_page_no = sig1;
- req_struct.m_row_id.m_page_idx = sig2;
-
- Uint32 Roptype = regOperPtr->op_struct.op_type;
-
- if (Rstoredid != ZNIL) {
- ndbrequire(initStoredOperationrec(regOperPtr,
- &req_struct,
- Rstoredid) == ZOK);
- }
-
- copyAttrinfo(regOperPtr, &cinBuffer[0]);
-
- Uint32 localkey = (pageid << MAX_TUPLES_BITS) + pageidx;
- if (Roptype == ZINSERT && localkey == ~ (Uint32) 0)
- {
- // No tuple allocatated yet
- goto do_insert;
- }
-
- /**
- * Get pointer to tuple
- */
- regOperPtr->m_tuple_location.m_page_no= getRealpid(regFragPtr,
- req_struct.frag_page_id);
-
- setup_fixed_part(&req_struct, regOperPtr, regTabPtr);
-
- /**
- * Check operation
- */
- if (Roptype == ZREAD) {
- jam();
-
- if (setup_read(&req_struct, regOperPtr, regFragPtr, regTabPtr,
- disk_page != RNIL))
- {
- if(handleReadReq(signal, regOperPtr, regTabPtr, &req_struct) != -1)
- {
- req_struct.log_size= 0;
- sendTUPKEYCONF(signal, &req_struct, regOperPtr);
- /* ---------------------------------------------------------------- */
- // Read Operations need not to be taken out of any lists.
- // We also do not need to wait for commit since there is no changes
- // to commit. Thus we
- // prepare the operation record already now for the next operation.
- // Write operations have set the state to STARTED above indicating
- // that they are waiting for the Commit or Abort decision.
- /* ---------------------------------------------------------------- */
- set_trans_state(regOperPtr, TRANS_IDLE);
- regOperPtr->currentAttrinbufLen= 0;
- }
- return;
- }
- tupkeyErrorLab(signal);
- return;
- }
-
- if(insertActiveOpList(operPtr, &req_struct))
- {
- if(Roptype == ZINSERT)
- {
- jam();
- do_insert:
- if (handleInsertReq(signal, operPtr,
- fragptr, regTabPtr, &req_struct) == -1)
- {
- return;
- }
- if (!regTabPtr->tuxCustomTriggers.isEmpty())
- {
- jam();
- if (executeTuxInsertTriggers(signal,
- regOperPtr,
- regFragPtr,
- regTabPtr) != 0) {
- jam();
- /*
- * TUP insert succeeded but add of TUX entries failed. All
- * TUX changes have been rolled back at this point.
- *
- * We will abort via tupkeyErrorLab() as usual. This routine
- * however resets the operation to ZREAD. The TUP_ABORTREQ
- * arriving later cannot then undo the insert.
- *
- * Therefore we call TUP_ABORTREQ already now. Diskdata etc
- * should be in memory and timeslicing cannot occur. We must
- * skip TUX abort triggers since TUX is already aborted.
- */
- signal->theData[0] = operPtr.i;
- do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS);
- tupkeyErrorLab(signal);
- return;
- }
- }
- checkImmediateTriggersAfterInsert(&req_struct,
- regOperPtr,
- regTabPtr,
- disk_page != RNIL);
- set_change_mask_state(regOperPtr, SET_ALL_MASK);
- sendTUPKEYCONF(signal, &req_struct, regOperPtr);
- return;
- }
-
- if (Roptype == ZUPDATE) {
- jam();
- if (handleUpdateReq(signal, regOperPtr,
- regFragPtr, regTabPtr, &req_struct, disk_page != RNIL) == -1) {
- return;
- }
- // If update operation is done on primary,
- // check any after op triggers
- terrorCode= 0;
- if (!regTabPtr->tuxCustomTriggers.isEmpty()) {
- jam();
- if (executeTuxUpdateTriggers(signal,
- regOperPtr,
- regFragPtr,
- regTabPtr) != 0) {
- jam();
- /*
- * See insert case.
- */
- signal->theData[0] = operPtr.i;
- do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS);
- tupkeyErrorLab(signal);
- return;
- }
- }
- checkImmediateTriggersAfterUpdate(&req_struct,
- regOperPtr,
- regTabPtr,
- disk_page != RNIL);
- // XXX use terrorCode for now since all methods are void
- if (terrorCode != 0)
- {
- tupkeyErrorLab(signal);
- return;
- }
- update_change_mask_info(&req_struct, regOperPtr);
- sendTUPKEYCONF(signal, &req_struct, regOperPtr);
- return;
- }
- else if(Roptype == ZDELETE)
- {
- jam();
- req_struct.log_size= 0;
- if (handleDeleteReq(signal, regOperPtr,
- regFragPtr, regTabPtr,
- &req_struct,
- disk_page != RNIL) == -1) {
- return;
- }
- /*
- * TUX doesn't need to check for triggers at delete since entries in
- * the index are kept until commit time.
- */
-
- /*
- * Secondary index triggers fire on the primary after a delete.
- */
- checkImmediateTriggersAfterDelete(&req_struct,
- regOperPtr,
- regTabPtr,
- disk_page != RNIL);
- set_change_mask_state(regOperPtr, DELETE_CHANGES);
- sendTUPKEYCONF(signal, &req_struct, regOperPtr);
- return;
- }
- else
- {
- ndbrequire(false); // Invalid op type
- }
- }
-
- tupkeyErrorLab(signal);
- }
-
-void
-Dbtup::setup_fixed_part(KeyReqStruct* req_struct,
- Operationrec* regOperPtr,
- Tablerec* regTabPtr)
-{
- PagePtr page_ptr;
- Uint32* ptr= get_ptr(&page_ptr, &regOperPtr->m_tuple_location, regTabPtr);
- req_struct->m_page_ptr = page_ptr;
- req_struct->m_tuple_ptr = (Tuple_header*)ptr;
-
- ndbassert(regOperPtr->op_struct.op_type == ZINSERT || (! (req_struct->m_tuple_ptr->m_header_bits & Tuple_header::FREE)));
-
- req_struct->check_offset[MM]= regTabPtr->get_check_offset(MM);
- req_struct->check_offset[DD]= regTabPtr->get_check_offset(DD);
-
- Uint32 num_attr= regTabPtr->m_no_of_attributes;
- Uint32 descr_start= regTabPtr->tabDescriptor;
- TableDescriptor *tab_descr= &tableDescriptor[descr_start];
- ndbrequire(descr_start + (num_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
- req_struct->attr_descr= tab_descr;
-}
-
- /* ---------------------------------------------------------------- */
- /* ------------------------ CONFIRM REQUEST ----------------------- */
- /* ---------------------------------------------------------------- */
- void Dbtup::sendTUPKEYCONF(Signal* signal,
- KeyReqStruct *req_struct,
- Operationrec * regOperPtr)
-{
- TupKeyConf * tupKeyConf= (TupKeyConf *)signal->getDataPtrSend();
-
- Uint32 Rcreate_rowid = req_struct->m_use_rowid;
- Uint32 RuserPointer= regOperPtr->userpointer;
- Uint32 RnoFiredTriggers= req_struct->no_fired_triggers;
- Uint32 log_size= req_struct->log_size;
- Uint32 read_length= req_struct->read_length;
- Uint32 last_row= req_struct->last_row;
-
- set_trans_state(regOperPtr, TRANS_STARTED);
- set_tuple_state(regOperPtr, TUPLE_PREPARED);
- tupKeyConf->userPtr= RuserPointer;
- tupKeyConf->readLength= read_length;
- tupKeyConf->writeLength= log_size;
- tupKeyConf->noFiredTriggers= RnoFiredTriggers;
- tupKeyConf->lastRow= last_row;
- tupKeyConf->rowid = Rcreate_rowid;
-
- EXECUTE_DIRECT(DBLQH, GSN_TUPKEYCONF, signal,
- TupKeyConf::SignalLength);
-
-}
-
-
-#define MAX_READ (sizeof(signal->theData) > MAX_MESSAGE_SIZE ? MAX_MESSAGE_SIZE : sizeof(signal->theData))
-
-/* ---------------------------------------------------------------- */
-/* ----------------------------- READ ---------------------------- */
-/* ---------------------------------------------------------------- */
-int Dbtup::handleReadReq(Signal* signal,
- Operationrec* regOperPtr,
- Tablerec* regTabPtr,
- KeyReqStruct* req_struct)
-{
- Uint32 *dst;
- Uint32 dstLen, start_index;
- const BlockReference sendBref= req_struct->rec_blockref;
- if ((regTabPtr->m_bits & Tablerec::TR_Checksum) &&
- (calculateChecksum(req_struct->m_tuple_ptr, regTabPtr) != 0)) {
- jam();
- ndbout_c("here2");
- terrorCode= ZTUPLE_CORRUPTED_ERROR;
- tupkeyErrorLab(signal);
- return -1;
- }
-
- const Uint32 node = refToNode(sendBref);
- if(node != 0 && node != getOwnNodeId()) {
- start_index= 25;
- } else {
- jam();
- /**
- * execute direct
- */
- start_index= 3;
- }
- dst= &signal->theData[start_index];
- dstLen= (MAX_READ / 4) - start_index;
- if (!req_struct->interpreted_exec) {
- jam();
- int ret = readAttributes(req_struct,
- &cinBuffer[0],
- req_struct->attrinfo_len,
- dst,
- dstLen,
- false);
- if (likely(ret != -1)) {
-/* ------------------------------------------------------------------------- */
-// We have read all data into coutBuffer. Now send it to the API.
-/* ------------------------------------------------------------------------- */
- jam();
- Uint32 TnoOfDataRead= (Uint32) ret;
- req_struct->read_length= TnoOfDataRead;
- sendReadAttrinfo(signal, req_struct, TnoOfDataRead, regOperPtr);
- return 0;
- }
- } else {
- jam();
- if (likely(interpreterStartLab(signal, req_struct) != -1)) {
- return 0;
- }
- return -1;
- }
-
- jam();
- tupkeyErrorLab(signal);
- return -1;
-}
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------- UPDATE ---------------------------- */
-/* ---------------------------------------------------------------- */
-int Dbtup::handleUpdateReq(Signal* signal,
- Operationrec* operPtrP,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- KeyReqStruct* req_struct,
- bool disk)
-{
- Uint32 *dst;
- Tuple_header *base= req_struct->m_tuple_ptr, *org;
- if ((dst= c_undo_buffer.alloc_copy_tuple(&operPtrP->m_copy_tuple_location,
- regTabPtr->total_rec_size)) == 0)
- {
- terrorCode= ZMEM_NOMEM_ERROR;
- goto error;
- }
-
- Uint32 tup_version;
- if(operPtrP->is_first_operation())
- {
- org= req_struct->m_tuple_ptr;
- tup_version= org->get_tuple_version();
- }
- else
- {
- Operationrec* prevOp= req_struct->prevOpPtr.p;
- tup_version= prevOp->tupVersion;
- org= (Tuple_header*)c_undo_buffer.get_ptr(&prevOp->m_copy_tuple_location);
- }
-
- /**
- * Check consistency before update/delete
- */
- req_struct->m_tuple_ptr= org;
- if ((regTabPtr->m_bits & Tablerec::TR_Checksum) &&
- (calculateChecksum(req_struct->m_tuple_ptr, regTabPtr) != 0))
- {
- terrorCode= ZTUPLE_CORRUPTED_ERROR;
- goto error;
- }
-
- req_struct->m_tuple_ptr= (Tuple_header*)dst;
-
- union {
- Uint32 sizes[4];
- Uint64 cmp[2];
- };
-
- disk = disk || (org->m_header_bits & Tuple_header::DISK_INLINE);
- if (regTabPtr->need_expand(disk))
- {
- expand_tuple(req_struct, sizes, org, regTabPtr, disk);
- if(disk && operPtrP->m_undo_buffer_space == 0)
- {
- operPtrP->op_struct.m_wait_log_buffer = 1;
- operPtrP->op_struct.m_load_diskpage_on_commit = 1;
- Uint32 sz= operPtrP->m_undo_buffer_space=
- (sizeof(Dbtup::Disk_undo::Update) >> 2) + sizes[DD] - 1;
-
- terrorCode= c_lgman->alloc_log_space(regFragPtr->m_logfile_group_id,
- sz);
- if(unlikely(terrorCode))
- {
- operPtrP->m_undo_buffer_space= 0;
- goto error;
- }
- }
- }
- else
- {
- memcpy(dst, org, 4*regTabPtr->m_offsets[MM].m_fix_header_size);
- }
-
- tup_version= (tup_version + 1) & ZTUP_VERSION_MASK;
- operPtrP->tupVersion= tup_version;
-
- if (!req_struct->interpreted_exec) {
- jam();
- int retValue = updateAttributes(req_struct,
- &cinBuffer[0],
- req_struct->attrinfo_len);
- if (unlikely(retValue == -1))
- goto error;
- } else {
- jam();
- if (unlikely(interpreterStartLab(signal, req_struct) == -1))
- return -1;
- }
-
- if (regTabPtr->need_shrink())
- {
- shrink_tuple(req_struct, sizes+2, regTabPtr, disk);
- if (cmp[0] != cmp[1] && handle_size_change_after_update(req_struct,
- base,
- operPtrP,
- regFragPtr,
- regTabPtr,
- sizes)) {
- goto error;
- }
- }
-
- req_struct->m_tuple_ptr->set_tuple_version(tup_version);
- if (regTabPtr->m_bits & Tablerec::TR_Checksum) {
- jam();
- setChecksum(req_struct->m_tuple_ptr, regTabPtr);
- }
- return 0;
-
-error:
- tupkeyErrorLab(signal);
- return -1;
-}
-
-/* ---------------------------------------------------------------- */
-/* ----------------------------- INSERT --------------------------- */
-/* ---------------------------------------------------------------- */
-void
-Dbtup::prepare_initial_insert(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* regTabPtr)
-{
- Uint32 disk_undo = regTabPtr->m_no_of_disk_attributes ?
- sizeof(Dbtup::Disk_undo::Alloc) >> 2 : 0;
- regOperPtr->nextActiveOp= RNIL;
- regOperPtr->prevActiveOp= RNIL;
- regOperPtr->op_struct.in_active_list= true;
- regOperPtr->m_undo_buffer_space= disk_undo;
-
- req_struct->check_offset[MM]= regTabPtr->get_check_offset(MM);
- req_struct->check_offset[DD]= regTabPtr->get_check_offset(DD);
-
- Uint32 num_attr= regTabPtr->m_no_of_attributes;
- Uint32 descr_start= regTabPtr->tabDescriptor;
- Uint32 order_desc= regTabPtr->m_real_order_descriptor;
- TableDescriptor *tab_descr= &tableDescriptor[descr_start];
- ndbrequire(descr_start + (num_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
- req_struct->attr_descr= tab_descr;
- Uint16* order= (Uint16*)&tableDescriptor[order_desc];
-
- const Uint32 cnt1= regTabPtr->m_attributes[MM].m_no_of_varsize;
- const Uint32 cnt2= regTabPtr->m_attributes[DD].m_no_of_varsize;
- Uint32 *ptr= req_struct->m_tuple_ptr->get_end_of_fix_part_ptr(regTabPtr);
- Var_part_ref* ref = req_struct->m_tuple_ptr->get_var_part_ref_ptr(regTabPtr);
-
- if (regTabPtr->m_bits & Tablerec::TR_ForceVarPart)
- {
- ref->m_page_no = RNIL;
- ref->m_page_idx = Tup_varsize_page::END_OF_FREE_LIST;
- }
-
- if(cnt1)
- {
- KeyReqStruct::Var_data* dst= &req_struct->m_var_data[MM];
- dst->m_data_ptr= (char*)(((Uint16*)ptr)+cnt1+1);
- dst->m_offset_array_ptr= req_struct->var_pos_array;
- dst->m_var_len_offset= cnt1;
- dst->m_max_var_offset= regTabPtr->m_offsets[MM].m_max_var_offset;
- // Disk part is 32-bit aligned
- ptr= ALIGN_WORD(dst->m_data_ptr+regTabPtr->m_offsets[MM].m_max_var_offset);
- order += regTabPtr->m_attributes[MM].m_no_of_fixsize;
- Uint32 pos= 0;
- Uint16 *pos_ptr = req_struct->var_pos_array;
- Uint16 *len_ptr = pos_ptr + cnt1;
- for(Uint32 i= 0; i<cnt1; i++)
- {
- * pos_ptr++ = pos;
- * len_ptr++ = pos;
- pos += AttributeDescriptor::getSizeInBytes(tab_descr[*order++].tabDescr);
- }
- }
-
- req_struct->m_disk_ptr= (Tuple_header*)ptr;
-
- ndbrequire(cnt2 == 0);
-
- // Set all null bits
- memset(req_struct->m_tuple_ptr->m_null_bits+
- regTabPtr->m_offsets[MM].m_null_offset, 0xFF,
- 4*regTabPtr->m_offsets[MM].m_null_words);
- memset(req_struct->m_disk_ptr->m_null_bits+
- regTabPtr->m_offsets[DD].m_null_offset, 0xFF,
- 4*regTabPtr->m_offsets[DD].m_null_words);
- req_struct->m_tuple_ptr->m_header_bits=
- disk_undo ? (Tuple_header::DISK_ALLOC | Tuple_header::DISK_INLINE) : 0;
-}
-
-int Dbtup::handleInsertReq(Signal* signal,
- Ptr<Operationrec> regOperPtr,
- Ptr<Fragrecord> fragPtr,
- Tablerec* regTabPtr,
- KeyReqStruct *req_struct)
-{
- Uint32 tup_version = 1;
- Fragrecord* regFragPtr = fragPtr.p;
- Uint32 *dst, *ptr= 0;
- Tuple_header *base= req_struct->m_tuple_ptr, *org= base;
- Tuple_header *tuple_ptr;
-
- bool disk = regTabPtr->m_no_of_disk_attributes > 0;
- bool mem_insert = regOperPtr.p->is_first_operation();
- bool disk_insert = mem_insert && disk;
- bool varsize = regTabPtr->m_attributes[MM].m_no_of_varsize;
- bool rowid = req_struct->m_use_rowid;
- Uint32 real_page_id = regOperPtr.p->m_tuple_location.m_page_no;
- Uint32 frag_page_id = req_struct->frag_page_id;
-
- union {
- Uint32 sizes[4];
- Uint64 cmp[2];
- };
-
- if (ERROR_INSERTED(4014))
- {
- dst = 0;
- goto undo_buffer_error;
- }
-
- dst= c_undo_buffer.alloc_copy_tuple(&regOperPtr.p->m_copy_tuple_location,
- regTabPtr->total_rec_size);
- if (unlikely(dst == 0))
- {
- goto undo_buffer_error;
- }
- tuple_ptr= req_struct->m_tuple_ptr= (Tuple_header*)dst;
-
- if(mem_insert)
- {
- jam();
- prepare_initial_insert(req_struct, regOperPtr.p, regTabPtr);
- }
- else
- {
- Operationrec* prevOp= req_struct->prevOpPtr.p;
- ndbassert(prevOp->op_struct.op_type == ZDELETE);
- tup_version= prevOp->tupVersion + 1;
-
- if(!prevOp->is_first_operation())
- org= (Tuple_header*)c_undo_buffer.get_ptr(&prevOp->m_copy_tuple_location);
- if (regTabPtr->need_expand())
- {
- expand_tuple(req_struct, sizes, org, regTabPtr, !disk_insert);
- memset(req_struct->m_disk_ptr->m_null_bits+
- regTabPtr->m_offsets[DD].m_null_offset, 0xFF,
- 4*regTabPtr->m_offsets[DD].m_null_words);
- }
- else
- {
- memcpy(dst, org, 4*regTabPtr->m_offsets[MM].m_fix_header_size);
- }
- memset(tuple_ptr->m_null_bits+
- regTabPtr->m_offsets[MM].m_null_offset, 0xFF,
- 4*regTabPtr->m_offsets[MM].m_null_words);
- }
-
- if (disk_insert)
- {
- int res;
-
- if (ERROR_INSERTED(4015))
- {
- terrorCode = 1501;
- goto log_space_error;
- }
-
- res= c_lgman->alloc_log_space(regFragPtr->m_logfile_group_id,
- regOperPtr.p->m_undo_buffer_space);
- if(unlikely(res))
- {
- terrorCode= res;
- goto log_space_error;
- }
- }
-
- regOperPtr.p->tupVersion= tup_version & ZTUP_VERSION_MASK;
- tuple_ptr->set_tuple_version(tup_version);
-
- if (ERROR_INSERTED(4016))
- {
- terrorCode = ZAI_INCONSISTENCY_ERROR;
- goto update_error;
- }
-
- if(unlikely(updateAttributes(req_struct, &cinBuffer[0],
- req_struct->attrinfo_len) == -1))
- {
- goto update_error;
- }
-
- if (ERROR_INSERTED(4017))
- {
- goto null_check_error;
- }
- if (unlikely(checkNullAttributes(req_struct, regTabPtr) == false))
- {
- goto null_check_error;
- }
-
- if (regTabPtr->need_shrink())
- {
- shrink_tuple(req_struct, sizes+2, regTabPtr, true);
- }
-
- if (ERROR_INSERTED(4025))
- {
- goto mem_error;
- }
-
- if (ERROR_INSERTED(4026))
- {
- CLEAR_ERROR_INSERT_VALUE;
- goto mem_error;
- }
-
- if (ERROR_INSERTED(4027) && (rand() % 100) > 25)
- {
- goto mem_error;
- }
-
- if (ERROR_INSERTED(4028) && (rand() % 100) > 25)
- {
- CLEAR_ERROR_INSERT_VALUE;
- goto mem_error;
- }
-
- /**
- * Alloc memory
- */
- if(mem_insert)
- {
- if (!rowid)
- {
- if (ERROR_INSERTED(4018))
- {
- goto mem_error;
- }
-
- if (!varsize)
- {
- jam();
- ptr= alloc_fix_rec(regFragPtr,
- regTabPtr,
- &regOperPtr.p->m_tuple_location,
- &frag_page_id);
- }
- else
- {
- jam();
- regOperPtr.p->m_tuple_location.m_file_no= sizes[2+MM];
- ptr= alloc_var_rec(regFragPtr, regTabPtr,
- sizes[2+MM],
- &regOperPtr.p->m_tuple_location,
- &frag_page_id);
- }
- if (unlikely(ptr == 0))
- {
- goto mem_error;
- }
- req_struct->m_use_rowid = true;
- }
- else
- {
- regOperPtr.p->m_tuple_location = req_struct->m_row_id;
- if (ERROR_INSERTED(4019))
- {
- terrorCode = ZROWID_ALLOCATED;
- goto alloc_rowid_error;
- }
-
- if (!varsize)
- {
- jam();
- ptr= alloc_fix_rowid(regFragPtr,
- regTabPtr,
- &regOperPtr.p->m_tuple_location,
- &frag_page_id);
- }
- else
- {
- jam();
- regOperPtr.p->m_tuple_location.m_file_no= sizes[2+MM];
- ptr= alloc_var_rowid(regFragPtr, regTabPtr,
- sizes[2+MM],
- &regOperPtr.p->m_tuple_location,
- &frag_page_id);
- }
- if (unlikely(ptr == 0))
- {
- jam();
- goto alloc_rowid_error;
- }
- }
- real_page_id = regOperPtr.p->m_tuple_location.m_page_no;
- regOperPtr.p->m_tuple_location.m_page_no= frag_page_id;
- c_lqh->accminupdate(signal,
- regOperPtr.p->userpointer,
- &regOperPtr.p->m_tuple_location);
-
- base = (Tuple_header*)ptr;
- base->m_operation_ptr_i= regOperPtr.i;
- base->m_header_bits= Tuple_header::ALLOC |
- (varsize ? Tuple_header::CHAINED_ROW : 0);
- regOperPtr.p->m_tuple_location.m_page_no = real_page_id;
- }
- else
- {
- int ret;
- if (ERROR_INSERTED(4020))
- {
- goto size_change_error;
- }
-
- if (regTabPtr->need_shrink() && cmp[0] != cmp[1] &&
- unlikely(ret = handle_size_change_after_update(req_struct,
- base,
- regOperPtr.p,
- regFragPtr,
- regTabPtr,
- sizes)))
- {
- goto size_change_error;
- }
- req_struct->m_use_rowid = false;
- base->m_header_bits &= ~(Uint32)Tuple_header::FREE;
- }
-
- base->m_header_bits |= Tuple_header::ALLOC &
- (regOperPtr.p->is_first_operation() ? ~0 : 1);
-
- if (disk_insert)
- {
- Local_key tmp;
- Uint32 size= regTabPtr->m_attributes[DD].m_no_of_varsize == 0 ?
- 1 : sizes[2+DD];
-
- if (ERROR_INSERTED(4021))
- {
- terrorCode = 1601;
- goto disk_prealloc_error;
- }
-
- int ret= disk_page_prealloc(signal, fragPtr, &tmp, size);
- if (unlikely(ret < 0))
- {
- terrorCode = -ret;
- goto disk_prealloc_error;
- }
-
- regOperPtr.p->op_struct.m_disk_preallocated= 1;
- tmp.m_page_idx= size;
- memcpy(tuple_ptr->get_disk_ref_ptr(regTabPtr), &tmp, sizeof(tmp));
-
- /**
- * Set ref from disk to mm
- */
- Local_key ref = regOperPtr.p->m_tuple_location;
- ref.m_page_no = frag_page_id;
-
- Tuple_header* disk_ptr= req_struct->m_disk_ptr;
- disk_ptr->m_header_bits = 0;
- disk_ptr->m_base_record_ref= ref.ref();
- }
-
- if (regTabPtr->m_bits & Tablerec::TR_Checksum)
- {
- jam();
- setChecksum(req_struct->m_tuple_ptr, regTabPtr);
- }
- return 0;
-
-size_change_error:
- jam();
- terrorCode = ZMEM_NOMEM_ERROR;
- goto exit_error;
-
-undo_buffer_error:
- jam();
- terrorCode= ZMEM_NOMEM_ERROR;
- regOperPtr.p->m_undo_buffer_space = 0;
- if (mem_insert)
- regOperPtr.p->m_tuple_location.setNull();
- regOperPtr.p->m_copy_tuple_location.setNull();
- tupkeyErrorLab(signal);
- return -1;
-
-null_check_error:
- jam();
- terrorCode= ZNO_ILLEGAL_NULL_ATTR;
- goto update_error;
-
-mem_error:
- jam();
- terrorCode= ZMEM_NOMEM_ERROR;
- goto update_error;
-
-log_space_error:
- jam();
- regOperPtr.p->m_undo_buffer_space = 0;
-alloc_rowid_error:
- jam();
-update_error:
- jam();
- if (mem_insert)
- {
- regOperPtr.p->op_struct.in_active_list = false;
- regOperPtr.p->m_tuple_location.setNull();
- }
-exit_error:
- tupkeyErrorLab(signal);
- return -1;
-
-disk_prealloc_error:
- base->m_header_bits |= Tuple_header::FREED;
- goto exit_error;
-}
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------- DELETE ---------------------------- */
-/* ---------------------------------------------------------------- */
-int Dbtup::handleDeleteReq(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- KeyReqStruct *req_struct,
- bool disk)
-{
- // delete must set but not increment tupVersion
- if (!regOperPtr->is_first_operation())
- {
- Operationrec* prevOp= req_struct->prevOpPtr.p;
- regOperPtr->tupVersion= prevOp->tupVersion;
- // make copy since previous op is committed before this one
- const Uint32* org = c_undo_buffer.get_ptr(&prevOp->m_copy_tuple_location);
- Uint32* dst = c_undo_buffer.alloc_copy_tuple(
- &regOperPtr->m_copy_tuple_location, regTabPtr->total_rec_size);
- if (dst == 0) {
- terrorCode = ZMEM_NOMEM_ERROR;
- goto error;
- }
- memcpy(dst, org, regTabPtr->total_rec_size << 2);
- req_struct->m_tuple_ptr = (Tuple_header*)dst;
- }
- else
- {
- regOperPtr->tupVersion= req_struct->m_tuple_ptr->get_tuple_version();
- }
-
- if(disk && regOperPtr->m_undo_buffer_space == 0)
- {
- regOperPtr->op_struct.m_wait_log_buffer = 1;
- regOperPtr->op_struct.m_load_diskpage_on_commit = 1;
- Uint32 sz= regOperPtr->m_undo_buffer_space=
- (sizeof(Dbtup::Disk_undo::Free) >> 2) +
- regTabPtr->m_offsets[DD].m_fix_header_size - 1;
-
- terrorCode= c_lgman->alloc_log_space(regFragPtr->m_logfile_group_id,
- sz);
- if(unlikely(terrorCode))
- {
- regOperPtr->m_undo_buffer_space= 0;
- goto error;
- }
- }
- if (req_struct->attrinfo_len == 0)
- {
- return 0;
- }
-
- if (regTabPtr->need_expand(disk))
- {
- prepare_read(req_struct, regTabPtr, disk);
- }
-
- {
- Uint32 RlogSize;
- int ret= handleReadReq(signal, regOperPtr, regTabPtr, req_struct);
- if (ret == 0 && (RlogSize= req_struct->log_size))
- {
- jam();
- sendLogAttrinfo(signal, RlogSize, regOperPtr);
- }
- return ret;
- }
-
-error:
- tupkeyErrorLab(signal);
- return -1;
-}
-
-bool
-Dbtup::checkNullAttributes(KeyReqStruct * req_struct,
- Tablerec* regTabPtr)
-{
-// Implement checking of updating all not null attributes in an insert here.
- Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
- /*
- * The idea here is maybe that changeMask is not-null attributes
- * and must contain notNullAttributeMask. But:
- *
- * 1. changeMask has all bits set on insert
- * 2. not-null is checked in each UpdateFunction
- * 3. the code below does not work except trivially due to 1.
- *
- * XXX remove or fix
- */
- attributeMask.clear();
- attributeMask.bitOR(req_struct->changeMask);
- attributeMask.bitAND(regTabPtr->notNullAttributeMask);
- attributeMask.bitXOR(regTabPtr->notNullAttributeMask);
- if (!attributeMask.isclear()) {
- return false;
- }
- return true;
-}
-
-/* ---------------------------------------------------------------- */
-/* THIS IS THE START OF THE INTERPRETED EXECUTION OF UPDATES. WE */
-/* START BY LINKING ALL ATTRINFO'S IN A DOUBLY LINKED LIST (THEY ARE*/
-/* ALREADY IN A LINKED LIST). WE ALLOCATE A REGISTER MEMORY (EQUAL */
-/* TO AN ATTRINFO RECORD). THE INTERPRETER GOES THROUGH FOUR PHASES*/
-/* DURING THE FIRST PHASE IT IS ONLY ALLOWED TO READ ATTRIBUTES THAT*/
-/* ARE SENT TO THE CLIENT APPLICATION. DURING THE SECOND PHASE IT IS*/
-/* ALLOWED TO READ FROM ATTRIBUTES INTO REGISTERS, TO UPDATE */
-/* ATTRIBUTES BASED ON EITHER A CONSTANT VALUE OR A REGISTER VALUE, */
-/* A DIVERSE SET OF OPERATIONS ON REGISTERS ARE AVAILABLE AS WELL. */
-/* IT IS ALSO POSSIBLE TO PERFORM JUMPS WITHIN THE INSTRUCTIONS THAT*/
-/* BELONGS TO THE SECOND PHASE. ALSO SUBROUTINES CAN BE CALLED IN */
-/* THIS PHASE. THE THIRD PHASE IS TO AGAIN READ ATTRIBUTES AND */
-/* FINALLY THE FOURTH PHASE READS SELECTED REGISTERS AND SEND THEM */
-/* TO THE CLIENT APPLICATION. */
-/* THERE IS A FIFTH REGION WHICH CONTAINS SUBROUTINES CALLABLE FROM */
-/* THE INTERPRETER EXECUTION REGION. */
-/* THE FIRST FIVE WORDS WILL GIVE THE LENGTH OF THE FIVEE REGIONS */
-/* */
-/* THIS MEANS THAT FROM THE APPLICATIONS POINT OF VIEW THE DATABASE */
-/* CAN HANDLE SUBROUTINE CALLS WHERE THE CODE IS SENT IN THE REQUEST*/
-/* THE RETURN PARAMETERS ARE FIXED AND CAN EITHER BE GENERATED */
-/* BEFORE THE EXECUTION OF THE ROUTINE OR AFTER. */
-/* */
-/* IN LATER VERSIONS WE WILL ADD MORE THINGS LIKE THE POSSIBILITY */
-/* TO ALLOCATE MEMORY AND USE THIS AS LOCAL STORAGE. IT IS ALSO */
-/* IMAGINABLE TO HAVE SPECIAL ROUTINES THAT CAN PERFORM CERTAIN */
-/* OPERATIONS ON BLOB'S DEPENDENT ON WHAT THE BLOB REPRESENTS. */
-/* */
-/* */
-/* ----------------------------------------- */
-/* + INITIAL READ REGION + */
-/* ----------------------------------------- */
-/* + INTERPRETED EXECUTE REGION + */
-/* ----------------------------------------- */
-/* + FINAL UPDATE REGION + */
-/* ----------------------------------------- */
-/* + FINAL READ REGION + */
-/* ----------------------------------------- */
-/* + SUBROUTINE REGION + */
-/* ----------------------------------------- */
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-/* ----------------- INTERPRETED EXECUTION ----------------------- */
-/* ---------------------------------------------------------------- */
-int Dbtup::interpreterStartLab(Signal* signal,
- KeyReqStruct *req_struct)
-{
- Operationrec * const regOperPtr= operPtr.p;
- int TnoDataRW;
- Uint32 RtotalLen, start_index, dstLen;
- Uint32 *dst;
-
- Uint32 RinitReadLen= cinBuffer[0];
- Uint32 RexecRegionLen= cinBuffer[1];
- Uint32 RfinalUpdateLen= cinBuffer[2];
- Uint32 RfinalRLen= cinBuffer[3];
- Uint32 RsubLen= cinBuffer[4];
-
- Uint32 RattrinbufLen= req_struct->attrinfo_len;
- const BlockReference sendBref= req_struct->rec_blockref;
-
- const Uint32 node = refToNode(sendBref);
- if(node != 0 && node != getOwnNodeId()) {
- start_index= 25;
- } else {
- jam();
- /**
- * execute direct
- */
- start_index= 3;
- }
- dst= &signal->theData[start_index];
- dstLen= (MAX_READ / 4) - start_index;
-
- RtotalLen= RinitReadLen;
- RtotalLen += RexecRegionLen;
- RtotalLen += RfinalUpdateLen;
- RtotalLen += RfinalRLen;
- RtotalLen += RsubLen;
-
- Uint32 RattroutCounter= 0;
- Uint32 RinstructionCounter= 5;
- Uint32 RlogSize= 0;
- if (((RtotalLen + 5) == RattrinbufLen) &&
- (RattrinbufLen >= 5) &&
- (RattrinbufLen < ZATTR_BUFFER_SIZE)) {
- /* ---------------------------------------------------------------- */
- // We start by checking consistency. We must have the first five
- // words of the ATTRINFO to give us the length of the regions. The
- // size of these regions must be the same as the total ATTRINFO
- // length and finally the total length must be within the limits.
- /* ---------------------------------------------------------------- */
-
- if (RinitReadLen > 0) {
- jam();
- /* ---------------------------------------------------------------- */
- // The first step that can be taken in the interpreter is to read
- // data of the tuple before any updates have been applied.
- /* ---------------------------------------------------------------- */
- TnoDataRW= readAttributes(req_struct,
- &cinBuffer[5],
- RinitReadLen,
- &dst[0],
- dstLen,
- false);
- if (TnoDataRW != -1) {
- RattroutCounter= TnoDataRW;
- RinstructionCounter += RinitReadLen;
- } else {
- jam();
- tupkeyErrorLab(signal);
- return -1;
- }
- }
- if (RexecRegionLen > 0) {
- jam();
- /* ---------------------------------------------------------------- */
- // The next step is the actual interpreted execution. This executes
- // a register-based virtual machine which can read and write attributes
- // to and from registers.
- /* ---------------------------------------------------------------- */
- Uint32 RsubPC= RinstructionCounter + RfinalUpdateLen + RfinalRLen;
- TnoDataRW= interpreterNextLab(signal,
- req_struct,
- &clogMemBuffer[0],
- &cinBuffer[RinstructionCounter],
- RexecRegionLen,
- &cinBuffer[RsubPC],
- RsubLen,
- &coutBuffer[0],
- sizeof(coutBuffer) / 4);
- if (TnoDataRW != -1) {
- RinstructionCounter += RexecRegionLen;
- RlogSize= TnoDataRW;
- } else {
- jam();
- /**
- * TUPKEY REF is sent from within interpreter
- */
- return -1;
- }
- }
- if (RfinalUpdateLen > 0) {
- jam();
- /* ---------------------------------------------------------------- */
- // We can also apply a set of updates without any conditions as part
- // of the interpreted execution.
- /* ---------------------------------------------------------------- */
- if (regOperPtr->op_struct.op_type == ZUPDATE) {
- TnoDataRW= updateAttributes(req_struct,
- &cinBuffer[RinstructionCounter],
- RfinalUpdateLen);
- if (TnoDataRW != -1) {
- MEMCOPY_NO_WORDS(&clogMemBuffer[RlogSize],
- &cinBuffer[RinstructionCounter],
- RfinalUpdateLen);
- RinstructionCounter += RfinalUpdateLen;
- RlogSize += RfinalUpdateLen;
- } else {
- jam();
- tupkeyErrorLab(signal);
- return -1;
- }
- } else {
- return TUPKEY_abort(signal, 19);
- }
- }
- if (RfinalRLen > 0) {
- jam();
- /* ---------------------------------------------------------------- */
- // The final action is that we can also read the tuple after it has
- // been updated.
- /* ---------------------------------------------------------------- */
- TnoDataRW= readAttributes(req_struct,
- &cinBuffer[RinstructionCounter],
- RfinalRLen,
- &dst[RattroutCounter],
- (dstLen - RattroutCounter),
- false);
- if (TnoDataRW != -1) {
- RattroutCounter += TnoDataRW;
- } else {
- jam();
- tupkeyErrorLab(signal);
- return -1;
- }
- }
- req_struct->log_size= RlogSize;
- req_struct->read_length= RattroutCounter;
- sendReadAttrinfo(signal, req_struct, RattroutCounter, regOperPtr);
- if (RlogSize > 0) {
- sendLogAttrinfo(signal, RlogSize, regOperPtr);
- }
- return 0;
- } else {
- return TUPKEY_abort(signal, 22);
- }
-}
-
-/* ---------------------------------------------------------------- */
-/* WHEN EXECUTION IS INTERPRETED WE NEED TO SEND SOME ATTRINFO*/
-/* BACK TO LQH FOR LOGGING AND SENDING TO BACKUP AND STANDBY */
-/* NODES. */
-/* INPUT: LOG_ATTRINFOPTR WHERE TO FETCH DATA FROM */
-/* TLOG_START FIRST INDEX TO LOG */
-/* TLOG_END LAST INDEX + 1 TO LOG */
-/* ---------------------------------------------------------------- */
-void Dbtup::sendLogAttrinfo(Signal* signal,
- Uint32 TlogSize,
- Operationrec * const regOperPtr)
-
-{
- Uint32 TbufferIndex= 0;
- signal->theData[0]= regOperPtr->userpointer;
- while (TlogSize > 22) {
- MEMCOPY_NO_WORDS(&signal->theData[3],
- &clogMemBuffer[TbufferIndex],
- 22);
- EXECUTE_DIRECT(DBLQH, GSN_TUP_ATTRINFO, signal, 25);
- TbufferIndex += 22;
- TlogSize -= 22;
- }
- MEMCOPY_NO_WORDS(&signal->theData[3],
- &clogMemBuffer[TbufferIndex],
- TlogSize);
- EXECUTE_DIRECT(DBLQH, GSN_TUP_ATTRINFO, signal, 3 + TlogSize);
-}
-
-inline
-Uint32
-brancher(Uint32 TheInstruction, Uint32 TprogramCounter)
-{
- Uint32 TbranchDirection= TheInstruction >> 31;
- Uint32 TbranchLength= (TheInstruction >> 16) & 0x7fff;
- TprogramCounter--;
- if (TbranchDirection == 1) {
- jam();
- /* ---------------------------------------------------------------- */
- /* WE JUMP BACKWARDS. */
- /* ---------------------------------------------------------------- */
- return (TprogramCounter - TbranchLength);
- } else {
- jam();
- /* ---------------------------------------------------------------- */
- /* WE JUMP FORWARD. */
- /* ---------------------------------------------------------------- */
- return (TprogramCounter + TbranchLength);
- }
-}
-
-int Dbtup::interpreterNextLab(Signal* signal,
- KeyReqStruct* req_struct,
- Uint32* logMemory,
- Uint32* mainProgram,
- Uint32 TmainProgLen,
- Uint32* subroutineProg,
- Uint32 TsubroutineLen,
- Uint32 * tmpArea,
- Uint32 tmpAreaSz)
-{
- register Uint32* TcurrentProgram= mainProgram;
- register Uint32 TcurrentSize= TmainProgLen;
- register Uint32 RnoOfInstructions= 0;
- register Uint32 TprogramCounter= 0;
- register Uint32 theInstruction;
- register Uint32 theRegister;
- Uint32 TdataWritten= 0;
- Uint32 RstackPtr= 0;
- union {
- Uint32 TregMemBuffer[32];
- Uint64 align[16];
- };
- Uint32 TstackMemBuffer[32];
-
- /* ---------------------------------------------------------------- */
- // Initialise all 8 registers to contain the NULL value.
- // In this version we can handle 32 and 64 bit unsigned integers.
- // They are handled as 64 bit values. Thus the 32 most significant
- // bits are zeroed for 32 bit values.
- /* ---------------------------------------------------------------- */
- TregMemBuffer[0]= 0;
- TregMemBuffer[4]= 0;
- TregMemBuffer[8]= 0;
- TregMemBuffer[12]= 0;
- TregMemBuffer[16]= 0;
- TregMemBuffer[20]= 0;
- TregMemBuffer[24]= 0;
- TregMemBuffer[28]= 0;
- Uint32 tmpHabitant= ~0;
-
- while (RnoOfInstructions < 8000) {
- /* ---------------------------------------------------------------- */
- /* EXECUTE THE NEXT INTERPRETER INSTRUCTION. */
- /* ---------------------------------------------------------------- */
- RnoOfInstructions++;
- theInstruction= TcurrentProgram[TprogramCounter];
- theRegister= Interpreter::getReg1(theInstruction) << 2;
- if (TprogramCounter < TcurrentSize) {
- TprogramCounter++;
- switch (Interpreter::getOpCode(theInstruction)) {
- case Interpreter::READ_ATTR_INTO_REG:
- jam();
- /* ---------------------------------------------------------------- */
- // Read an attribute from the tuple into a register.
- // While reading an attribute we allow the attribute to be an array
- // as long as it fits in the 64 bits of the register.
- /* ---------------------------------------------------------------- */
- {
- Uint32 theAttrinfo= theInstruction;
- int TnoDataRW= readAttributes(req_struct,
- &theAttrinfo,
- (Uint32)1,
- &TregMemBuffer[theRegister],
- (Uint32)3,
- false);
- if (TnoDataRW == 2) {
- /* ------------------------------------------------------------- */
- // Two words read means that we get the instruction plus one 32
- // word read. Thus we set the register to be a 32 bit register.
- /* ------------------------------------------------------------- */
- TregMemBuffer[theRegister]= 0x50;
- // arithmetic conversion if big-endian
- * (Int64*)(TregMemBuffer+theRegister+2)= TregMemBuffer[theRegister+1];
- } else if (TnoDataRW == 3) {
- /* ------------------------------------------------------------- */
- // Three words read means that we get the instruction plus two
- // 32 words read. Thus we set the register to be a 64 bit register.
- /* ------------------------------------------------------------- */
- TregMemBuffer[theRegister]= 0x60;
- TregMemBuffer[theRegister+3]= TregMemBuffer[theRegister+2];
- TregMemBuffer[theRegister+2]= TregMemBuffer[theRegister+1];
- } else if (TnoDataRW == 1) {
- /* ------------------------------------------------------------- */
- // One word read means that we must have read a NULL value. We set
- // the register to indicate a NULL value.
- /* ------------------------------------------------------------- */
- TregMemBuffer[theRegister]= 0;
- TregMemBuffer[theRegister + 2]= 0;
- TregMemBuffer[theRegister + 3]= 0;
- } else if (TnoDataRW == -1) {
- jam();
- tupkeyErrorLab(signal);
- return -1;
- } else {
- /* ------------------------------------------------------------- */
- // Any other return value from the read attribute here is not
- // allowed and will lead to a system crash.
- /* ------------------------------------------------------------- */
- ndbrequire(false);
- }
- break;
- }
-
- case Interpreter::WRITE_ATTR_FROM_REG:
- jam();
- {
- Uint32 TattrId= theInstruction >> 16;
- Uint32 TattrDescrIndex= tabptr.p->tabDescriptor +
- (TattrId << ZAD_LOG_SIZE);
- Uint32 TattrDesc1= tableDescriptor[TattrDescrIndex].tabDescr;
- Uint32 TregType= TregMemBuffer[theRegister];
-
- /* --------------------------------------------------------------- */
- // Calculate the number of words of this attribute.
- // We allow writes into arrays as long as they fit into the 64 bit
- // register size.
- /* --------------------------------------------------------------- */
- Uint32 TattrNoOfWords = AttributeDescriptor::getSizeInWords(TattrDesc1);
- Uint32 Toptype = operPtr.p->op_struct.op_type;
- Uint32 TdataForUpdate[3];
- Uint32 Tlen;
-
- AttributeHeader ah(TattrId, TattrNoOfWords << 2);
- TdataForUpdate[0]= ah.m_value;
- TdataForUpdate[1]= TregMemBuffer[theRegister + 2];
- TdataForUpdate[2]= TregMemBuffer[theRegister + 3];
- Tlen= TattrNoOfWords + 1;
- if (Toptype == ZUPDATE) {
- if (TattrNoOfWords <= 2) {
- if (TattrNoOfWords == 1) {
- // arithmetic conversion if big-endian
- TdataForUpdate[1] = *(Int64*)&TregMemBuffer[theRegister + 2];
- TdataForUpdate[2] = 0;
- }
- if (TregType == 0) {
- /* --------------------------------------------------------- */
- // Write a NULL value into the attribute
- /* --------------------------------------------------------- */
- ah.setNULL();
- TdataForUpdate[0]= ah.m_value;
- Tlen= 1;
- }
- int TnoDataRW= updateAttributes(req_struct,
- &TdataForUpdate[0],
- Tlen);
- if (TnoDataRW != -1) {
- /* --------------------------------------------------------- */
- // Write the written data also into the log buffer so that it
- // will be logged.
- /* --------------------------------------------------------- */
- logMemory[TdataWritten + 0]= TdataForUpdate[0];
- logMemory[TdataWritten + 1]= TdataForUpdate[1];
- logMemory[TdataWritten + 2]= TdataForUpdate[2];
- TdataWritten += Tlen;
- } else {
- tupkeyErrorLab(signal);
- return -1;
- }
- } else {
- return TUPKEY_abort(signal, 15);
- }
- } else {
- return TUPKEY_abort(signal, 16);
- }
- break;
- }
-
- case Interpreter::LOAD_CONST_NULL:
- jam();
- TregMemBuffer[theRegister]= 0; /* NULL INDICATOR */
- break;
-
- case Interpreter::LOAD_CONST16:
- jam();
- TregMemBuffer[theRegister]= 0x50; /* 32 BIT UNSIGNED CONSTANT */
- * (Int64*)(TregMemBuffer+theRegister+2)= theInstruction >> 16;
- break;
-
- case Interpreter::LOAD_CONST32:
- jam();
- TregMemBuffer[theRegister]= 0x50; /* 32 BIT UNSIGNED CONSTANT */
- * (Int64*)(TregMemBuffer+theRegister+2)= *
- (TcurrentProgram+TprogramCounter);
- TprogramCounter++;
- break;
-
- case Interpreter::LOAD_CONST64:
- jam();
- TregMemBuffer[theRegister]= 0x60; /* 64 BIT UNSIGNED CONSTANT */
- TregMemBuffer[theRegister + 2 ]= * (TcurrentProgram +
- TprogramCounter++);
- TregMemBuffer[theRegister + 3 ]= * (TcurrentProgram +
- TprogramCounter++);
- break;
-
- case Interpreter::ADD_REG_REG:
- jam();
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TdestRegister= Interpreter::getReg3(theInstruction) << 2;
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
-
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
-
- if ((TleftType | TrightType) != 0) {
- Uint64 Tdest0= Tleft0 + Tright0;
- * (Int64*)(TregMemBuffer+TdestRegister+2)= Tdest0;
- TregMemBuffer[TdestRegister]= 0x60;
- } else {
- return TUPKEY_abort(signal, 20);
- }
- break;
- }
-
- case Interpreter::SUB_REG_REG:
- jam();
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TdestRegister= Interpreter::getReg3(theInstruction) << 2;
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
-
- if ((TleftType | TrightType) != 0) {
- Int64 Tdest0= Tleft0 - Tright0;
- * (Int64*)(TregMemBuffer+TdestRegister+2)= Tdest0;
- TregMemBuffer[TdestRegister]= 0x60;
- } else {
- return TUPKEY_abort(signal, 20);
- }
- break;
- }
-
- case Interpreter::BRANCH:
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- break;
-
- case Interpreter::BRANCH_REG_EQ_NULL:
- if (TregMemBuffer[theRegister] != 0) {
- jam();
- continue;
- } else {
- jam();
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- break;
-
- case Interpreter::BRANCH_REG_NE_NULL:
- if (TregMemBuffer[theRegister] == 0) {
- jam();
- continue;
- } else {
- jam();
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- break;
-
-
- case Interpreter::BRANCH_EQ_REG_REG:
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Uint32 Tleft0= TregMemBuffer[theRegister + 2];
- Uint32 Tleft1= TregMemBuffer[theRegister + 3];
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Uint32 Tright0= TregMemBuffer[TrightRegister + 2];
- Uint32 Tright1= TregMemBuffer[TrightRegister + 3];
- if ((TrightType | TleftType) != 0) {
- jam();
- if ((Tleft0 == Tright0) && (Tleft1 == Tright1)) {
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- } else {
- return TUPKEY_abort(signal, 23);
- }
- break;
- }
-
- case Interpreter::BRANCH_NE_REG_REG:
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Uint32 Tleft0= TregMemBuffer[theRegister + 2];
- Uint32 Tleft1= TregMemBuffer[theRegister + 3];
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Uint32 Tright0= TregMemBuffer[TrightRegister + 2];
- Uint32 Tright1= TregMemBuffer[TrightRegister + 3];
- if ((TrightType | TleftType) != 0) {
- jam();
- if ((Tleft0 != Tright0) || (Tleft1 != Tright1)) {
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- } else {
- return TUPKEY_abort(signal, 24);
- }
- break;
- }
-
- case Interpreter::BRANCH_LT_REG_REG:
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
-
-
- if ((TrightType | TleftType) != 0) {
- jam();
- if (Tleft0 < Tright0) {
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- } else {
- return TUPKEY_abort(signal, 24);
- }
- break;
- }
-
- case Interpreter::BRANCH_LE_REG_REG:
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
-
-
- if ((TrightType | TleftType) != 0) {
- jam();
- if (Tleft0 <= Tright0) {
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- } else {
- return TUPKEY_abort(signal, 26);
- }
- break;
- }
-
- case Interpreter::BRANCH_GT_REG_REG:
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
-
-
- if ((TrightType | TleftType) != 0) {
- jam();
- if (Tleft0 > Tright0){
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- } else {
- return TUPKEY_abort(signal, 27);
- }
- break;
- }
-
- case Interpreter::BRANCH_GE_REG_REG:
- {
- Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
-
- Uint32 TrightType= TregMemBuffer[TrightRegister];
- Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
-
- Uint32 TleftType= TregMemBuffer[theRegister];
- Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
-
-
- if ((TrightType | TleftType) != 0) {
- jam();
- if (Tleft0 >= Tright0){
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- } else {
- return TUPKEY_abort(signal, 28);
- }
- break;
- }
-
- case Interpreter::BRANCH_ATTR_OP_ARG:{
- jam();
- Uint32 cond = Interpreter::getBinaryCondition(theInstruction);
- Uint32 ins2 = TcurrentProgram[TprogramCounter];
- Uint32 attrId = Interpreter::getBranchCol_AttrId(ins2) << 16;
- Uint32 argLen = Interpreter::getBranchCol_Len(ins2);
-
- if(tmpHabitant != attrId){
- Int32 TnoDataR = readAttributes(req_struct,
- &attrId, 1,
- tmpArea, tmpAreaSz,
- false);
-
- if (TnoDataR == -1) {
- jam();
- tupkeyErrorLab(signal);
- return -1;
- }
- tmpHabitant= attrId;
- }
-
- // 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);
- const void * cs = 0;
- if(AttributeOffset::getCharsetFlag(TattrDesc2))
- {
- Uint32 pos = AttributeOffset::getCharsetPos(TattrDesc2);
- cs = (void*) 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];
- // 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 {
- jam();
- if (unlikely(sqlType.m_cmp == 0))
- {
- return TUPKEY_abort(signal, 40);
- }
- res1 = (*sqlType.m_cmp)(cs, s1, attrLen, s2, argLen, true);
- }
- } else {
- if (r1_null || r2_null) {
- // NULL like NULL is true (has no practical use)
- res1 = r1_null && r2_null ? 0 : -1;
- } else {
- jam();
- if (unlikely(sqlType.m_like == 0))
- {
- return TUPKEY_abort(signal, 40);
- }
- res1 = (*sqlType.m_like)(cs, s1, attrLen, s2, argLen);
- }
- }
-
- int res = 0;
- switch ((Interpreter::BinaryCondition)cond) {
- case Interpreter::EQ:
- res = (res1 == 0);
- break;
- case Interpreter::NE:
- res = (res1 != 0);
- break;
- // note the condition is backwards
- case Interpreter::LT:
- res = (res1 > 0);
- break;
- case Interpreter::LE:
- res = (res1 >= 0);
- break;
- case Interpreter::GT:
- res = (res1 < 0);
- break;
- case Interpreter::GE:
- res = (res1 <= 0);
- break;
- case Interpreter::LIKE:
- res = (res1 == 0);
- break;
- case Interpreter::NOT_LIKE:
- res = (res1 == 1);
- break;
- // XXX handle invalid value
- }
-#ifdef TRACE_INTERPRETER
- 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 = ((argLen + 3) >> 2) + 1;
- TprogramCounter += tmp;
- }
- break;
- }
-
- case Interpreter::BRANCH_ATTR_EQ_NULL:{
- jam();
- Uint32 ins2= TcurrentProgram[TprogramCounter];
- Uint32 attrId= Interpreter::getBranchCol_AttrId(ins2) << 16;
-
- if (tmpHabitant != attrId){
- Int32 TnoDataR= readAttributes(req_struct,
- &attrId, 1,
- tmpArea, tmpAreaSz,
- false);
-
- if (TnoDataR == -1) {
- jam();
- tupkeyErrorLab(signal);
- return -1;
- }
- tmpHabitant= attrId;
- }
-
- AttributeHeader ah(tmpArea[0]);
- if (ah.isNULL()){
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- } else {
- TprogramCounter ++;
- }
- break;
- }
-
- case Interpreter::BRANCH_ATTR_NE_NULL:{
- jam();
- Uint32 ins2= TcurrentProgram[TprogramCounter];
- Uint32 attrId= Interpreter::getBranchCol_AttrId(ins2) << 16;
-
- if (tmpHabitant != attrId){
- Int32 TnoDataR= readAttributes(req_struct,
- &attrId, 1,
- tmpArea, tmpAreaSz,
- false);
-
- if (TnoDataR == -1) {
- jam();
- tupkeyErrorLab(signal);
- return -1;
- }
- tmpHabitant= attrId;
- }
-
- AttributeHeader ah(tmpArea[0]);
- if (ah.isNULL()){
- TprogramCounter ++;
- } else {
- TprogramCounter= brancher(theInstruction, TprogramCounter);
- }
- break;
- }
-
- case Interpreter::EXIT_OK:
- jam();
-#ifdef TRACE_INTERPRETER
- ndbout_c(" - exit_ok");
-#endif
- return TdataWritten;
-
- case Interpreter::EXIT_OK_LAST:
- jam();
-#ifdef TRACE_INTERPRETER
- ndbout_c(" - exit_ok_last");
-#endif
- req_struct->last_row= true;
- return TdataWritten;
-
- case Interpreter::EXIT_REFUSE:
- jam();
-#ifdef TRACE_INTERPRETER
- ndbout_c(" - exit_nok");
-#endif
- terrorCode= theInstruction >> 16;
- return TUPKEY_abort(signal, 29);
-
- case Interpreter::CALL:
- jam();
- RstackPtr++;
- if (RstackPtr < 32) {
- TstackMemBuffer[RstackPtr]= TprogramCounter + 1;
- TprogramCounter= theInstruction >> 16;
- if (TprogramCounter < TsubroutineLen) {
- TcurrentProgram= subroutineProg;
- TcurrentSize= TsubroutineLen;
- } else {
- return TUPKEY_abort(signal, 30);
- }
- } else {
- return TUPKEY_abort(signal, 31);
- }
- break;
-
- case Interpreter::RETURN:
- jam();
- if (RstackPtr > 0) {
- TprogramCounter= TstackMemBuffer[RstackPtr];
- RstackPtr--;
- if (RstackPtr == 0) {
- jam();
- /* ------------------------------------------------------------- */
- // We are back to the main program.
- /* ------------------------------------------------------------- */
- TcurrentProgram= mainProgram;
- TcurrentSize= TmainProgLen;
- }
- } else {
- return TUPKEY_abort(signal, 32);
- }
- break;
-
- default:
- return TUPKEY_abort(signal, 33);
- }
- } else {
- return TUPKEY_abort(signal, 34);
- }
- }
- return TUPKEY_abort(signal, 35);
-}
-
-/**
- * expand_var_part - copy packed variable attributes to fully expanded size
- *
- * dst: where to start writing attribute data
- * dst_off_ptr where to write attribute offsets
- * src pointer to packed attributes
- * tabDesc array of attribute descriptors (used for getting max size)
- * no_of_attr no of atributes to expand
- */
-Uint32*
-expand_var_part(Dbtup::KeyReqStruct::Var_data *dst,
- const Uint32* src,
- const Uint32 * tabDesc,
- const Uint16* order)
-{
- char* dst_ptr= dst->m_data_ptr;
- Uint32 no_attr= dst->m_var_len_offset;
- Uint16* dst_off_ptr= dst->m_offset_array_ptr;
- Uint16* dst_len_ptr= dst_off_ptr + no_attr;
- const Uint16* src_off_ptr= (const Uint16*)src;
- const char* src_ptr= (const char*)(src_off_ptr + no_attr + 1);
-
- Uint16 tmp= *src_off_ptr++, next_pos, len, max_len, dst_off= 0;
- for(Uint32 i = 0; i<no_attr; i++)
- {
- next_pos= *src_off_ptr++;
- len= next_pos - tmp;
-
- *dst_off_ptr++ = dst_off;
- *dst_len_ptr++ = dst_off + len;
- memcpy(dst_ptr, src_ptr, len);
- src_ptr += len;
-
- max_len= AttributeDescriptor::getSizeInBytes(tabDesc[* order++]);
- dst_ptr += max_len; // Max size
- dst_off += max_len;
-
- tmp= next_pos;
- }
-
- return ALIGN_WORD(dst_ptr);
-}
-
-void
-Dbtup::expand_tuple(KeyReqStruct* req_struct,
- Uint32 sizes[2],
- Tuple_header* src,
- const Tablerec* tabPtrP,
- bool disk)
-{
- Uint32 bits= src->m_header_bits;
- Tuple_header* ptr= req_struct->m_tuple_ptr;
-
- Uint16 dd_tot= tabPtrP->m_no_of_disk_attributes;
- Uint16 mm_vars= tabPtrP->m_attributes[MM].m_no_of_varsize;
- Uint32 fix_size= tabPtrP->m_offsets[MM].m_fix_header_size;
- Uint32 order_desc= tabPtrP->m_real_order_descriptor;
-
- Uint32 *dst_ptr= ptr->get_end_of_fix_part_ptr(tabPtrP);
- const Uint32 *disk_ref= src->get_disk_ref_ptr(tabPtrP);
- const Uint32 *src_ptr= src->get_end_of_fix_part_ptr(tabPtrP);
- const Var_part_ref* var_ref = src->get_var_part_ref_ptr(tabPtrP);
- const Uint32 *desc= (Uint32*)req_struct->attr_descr;
- const Uint16 *order = (Uint16*)(&tableDescriptor[order_desc]);
- order += tabPtrP->m_attributes[MM].m_no_of_fixsize;
-
- if(mm_vars)
- {
-
- Uint32 step; // in bytes
- const Uint32 *src_data= src_ptr;
- KeyReqStruct::Var_data* dst= &req_struct->m_var_data[MM];
- if(bits & Tuple_header::CHAINED_ROW)
- {
- Ptr<Page> var_page;
- src_data= get_ptr(&var_page, *var_ref);
- step= 4;
- sizes[MM]= (2 + (mm_vars << 1) + ((Uint16*)src_data)[mm_vars] + 3) >> 2;
- req_struct->m_varpart_page_ptr = var_page;
- }
- else
- {
- step= (2 + (mm_vars << 1) + ((Uint16*)src_ptr)[mm_vars]);
- sizes[MM]= (step + 3) >> 2;
- req_struct->m_varpart_page_ptr = req_struct->m_page_ptr;
- }
- dst->m_data_ptr= (char*)(((Uint16*)dst_ptr)+mm_vars+1);
- dst->m_offset_array_ptr= req_struct->var_pos_array;
- dst->m_var_len_offset= mm_vars;
- dst->m_max_var_offset= tabPtrP->m_offsets[MM].m_max_var_offset;
-
- dst_ptr= expand_var_part(dst, src_data, desc, order);
- ndbassert(dst_ptr == ALIGN_WORD(dst->m_data_ptr + dst->m_max_var_offset));
- ndbassert((UintPtr(src_ptr) & 3) == 0);
- src_ptr = ALIGN_WORD(((char*)src_ptr)+step);
-
- sizes[MM] += fix_size;
- memcpy(ptr, src, 4*fix_size);
- }
- else
- {
- sizes[MM]= 1;
- memcpy(ptr, src, 4*fix_size);
- }
-
- src->m_header_bits= bits &
- ~(Uint32)(Tuple_header::MM_SHRINK | Tuple_header::MM_GROWN);
-
- sizes[DD]= 0;
- if(disk && dd_tot)
- {
- const Uint16 dd_vars= tabPtrP->m_attributes[DD].m_no_of_varsize;
- order += mm_vars;
-
- if(bits & Tuple_header::DISK_INLINE)
- {
- // Only on copy tuple
- ndbassert((bits & Tuple_header::CHAINED_ROW) == 0);
- }
- else
- {
- Local_key key;
- memcpy(&key, disk_ref, sizeof(key));
- key.m_page_no= req_struct->m_disk_page_ptr.i;
- src_ptr= get_dd_ptr(&req_struct->m_disk_page_ptr, &key, tabPtrP);
- }
- bits |= Tuple_header::DISK_INLINE;
-
- // Fix diskpart
- req_struct->m_disk_ptr= (Tuple_header*)dst_ptr;
- memcpy(dst_ptr, src_ptr, 4*tabPtrP->m_offsets[DD].m_fix_header_size);
- sizes[DD] = tabPtrP->m_offsets[DD].m_fix_header_size;
-
- ndbassert(! (req_struct->m_disk_ptr->m_header_bits & Tuple_header::FREE));
-
- ndbrequire(dd_vars == 0);
- }
-
- ptr->m_header_bits= (bits & ~(Uint32)(Tuple_header::CHAINED_ROW));
-}
-
-void
-Dbtup::prepare_read(KeyReqStruct* req_struct,
- Tablerec* tabPtrP, bool disk)
-{
- Tuple_header* ptr= req_struct->m_tuple_ptr;
-
- Uint32 bits= ptr->m_header_bits;
- Uint16 dd_tot= tabPtrP->m_no_of_disk_attributes;
- Uint16 mm_vars= tabPtrP->m_attributes[MM].m_no_of_varsize;
-
- const Uint32 *src_ptr= ptr->get_end_of_fix_part_ptr(tabPtrP);
- const Uint32 *disk_ref= ptr->get_disk_ref_ptr(tabPtrP);
- const Var_part_ref* var_ref = ptr->get_var_part_ref_ptr(tabPtrP);
- if(mm_vars)
- {
- const Uint32 *src_data= src_ptr;
- KeyReqStruct::Var_data* dst= &req_struct->m_var_data[MM];
- if(bits & Tuple_header::CHAINED_ROW)
- {
-#if VM_TRACE
-
-#endif
- src_data= get_ptr(* var_ref);
- }
- dst->m_data_ptr= (char*)(((Uint16*)src_data)+mm_vars+1);
- dst->m_offset_array_ptr= (Uint16*)src_data;
- dst->m_var_len_offset= 1;
- dst->m_max_var_offset= ((Uint16*)src_data)[mm_vars];
-
- // disk part start after varsize (aligned)
- src_ptr = ALIGN_WORD(dst->m_data_ptr + dst->m_max_var_offset);
- }
-
- if(disk && dd_tot)
- {
- const Uint16 dd_vars= tabPtrP->m_attributes[DD].m_no_of_varsize;
-
- if(bits & Tuple_header::DISK_INLINE)
- {
- // Only on copy tuple
- ndbassert((bits & Tuple_header::CHAINED_ROW) == 0);
- }
- else
- {
- // XXX
- Local_key key;
- memcpy(&key, disk_ref, sizeof(key));
- key.m_page_no= req_struct->m_disk_page_ptr.i;
- src_ptr= get_dd_ptr(&req_struct->m_disk_page_ptr, &key, tabPtrP);
- }
- // Fix diskpart
- req_struct->m_disk_ptr= (Tuple_header*)src_ptr;
- ndbassert(! (req_struct->m_disk_ptr->m_header_bits & Tuple_header::FREE));
- ndbrequire(dd_vars == 0);
- }
-}
-
-void
-Dbtup::shrink_tuple(KeyReqStruct* req_struct, Uint32 sizes[2],
- const Tablerec* tabPtrP, bool disk)
-{
- ndbassert(tabPtrP->need_shrink());
- Tuple_header* ptr= req_struct->m_tuple_ptr;
-
- Uint16 dd_tot= tabPtrP->m_no_of_disk_attributes;
- Uint16 mm_vars= tabPtrP->m_attributes[MM].m_no_of_varsize;
- Uint16 dd_vars= tabPtrP->m_attributes[DD].m_no_of_varsize;
-
- Uint32 *dst_ptr= ptr->get_end_of_fix_part_ptr(tabPtrP);
- Uint16* src_off_ptr= req_struct->var_pos_array;
-
- sizes[MM] = 1;
- sizes[DD] = 0;
- if(mm_vars)
- {
- Uint16* dst_off_ptr= (Uint16*)dst_ptr;
- char* dst_data_ptr= (char*)(dst_off_ptr + mm_vars + 1);
- char* src_data_ptr= dst_data_ptr;
- Uint32 off= 0;
- for(Uint32 i= 0; i<mm_vars; i++)
- {
- const char* data_ptr= src_data_ptr + *src_off_ptr;
- Uint32 len= src_off_ptr[mm_vars] - *src_off_ptr;
- * dst_off_ptr++= off;
- memmove(dst_data_ptr, data_ptr, len);
- off += len;
- src_off_ptr++;
- dst_data_ptr += len;
- }
- *dst_off_ptr= off;
- ndbassert(dst_data_ptr <= ((char*)ptr) + 8192);
- ndbassert((UintPtr(ptr) & 3) == 0);
- sizes[MM]= (dst_data_ptr + 3 - ((char*)ptr)) >> 2;
-
- dst_ptr = ALIGN_WORD(dst_data_ptr);
- }
-
- if(disk && dd_tot)
- {
- Uint32 * src_ptr = (Uint32*)req_struct->m_disk_ptr;
- req_struct->m_disk_ptr = (Tuple_header*)dst_ptr;
- ndbrequire(dd_vars == 0);
- sizes[DD] = tabPtrP->m_offsets[DD].m_fix_header_size;
- memmove(dst_ptr, src_ptr, 4*tabPtrP->m_offsets[DD].m_fix_header_size);
- }
-}
-
-void
-Dbtup::validate_page(Tablerec* regTabPtr, Var_page* p)
-{
- Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
- Uint32 fix_sz= regTabPtr->m_offsets[MM].m_fix_header_size +
- Tuple_header::HeaderSize;
-
- if(mm_vars == 0)
- return;
-
- for(Uint32 F= 0; F<MAX_FRAG_PER_NODE; F++)
- {
- FragrecordPtr fragPtr;
-
- if((fragPtr.i = regTabPtr->fragrec[F]) == RNIL)
- continue;
-
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- for(Uint32 P= 0; P<fragPtr.p->noOfPages; P++)
- {
- Uint32 real= getRealpid(fragPtr.p, P);
- Var_page* page= (Var_page*)c_page_pool.getPtr(real);
-
- for(Uint32 i=1; i<page->high_index; i++)
- {
- Uint32 idx= page->get_index_word(i);
- Uint32 len = (idx & Var_page::LEN_MASK) >> Var_page::LEN_SHIFT;
- if(!(idx & Var_page::FREE) && !(idx & Var_page::CHAIN))
- {
- Tuple_header *ptr= (Tuple_header*)page->get_ptr(i);
- Uint32 *part= ptr->get_end_of_fix_part_ptr(regTabPtr);
- if(ptr->m_header_bits & Tuple_header::CHAINED_ROW)
- {
- ndbassert(len == fix_sz + 1);
- Local_key tmp; tmp.assref(*part);
- Ptr<Page> tmpPage;
- part= get_ptr(&tmpPage, *(Var_part_ref*)part);
- len= ((Var_page*)tmpPage.p)->get_entry_len(tmp.m_page_idx);
- Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)part)[mm_vars]);
- ndbassert(len >= ((sz + 3) >> 2));
- }
- else
- {
- Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)part)[mm_vars]);
- ndbassert(len >= ((sz+3)>>2)+fix_sz);
- }
- if(ptr->m_operation_ptr_i != RNIL)
- {
- c_operation_pool.getPtr(ptr->m_operation_ptr_i);
- }
- }
- else if(!(idx & Var_page::FREE))
- {
- /**
- * Chain
- */
- Uint32 *part= page->get_ptr(i);
- Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)part)[mm_vars]);
- ndbassert(len >= ((sz + 3) >> 2));
- }
- else
- {
-
- }
- }
- if(p == 0 && page->high_index > 1)
- page->reorg((Var_page*)ctemp_page);
- }
- }
-
- if(p == 0)
- {
- validate_page(regTabPtr, (Var_page*)1);
- }
-}
-
-int
-Dbtup::handle_size_change_after_update(KeyReqStruct* req_struct,
- Tuple_header* org,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- Uint32 sizes[4])
-{
- ndbrequire(sizes[1] == sizes[3]);
- //ndbout_c("%d %d %d %d", sizes[0], sizes[1], sizes[2], sizes[3]);
- if(0)
- printf("%p %d %d - handle_size_change_after_update ",
- req_struct->m_tuple_ptr,
- regOperPtr->m_tuple_location.m_page_no,
- regOperPtr->m_tuple_location.m_page_idx);
-
- Uint32 bits= org->m_header_bits;
- Uint32 copy_bits= req_struct->m_tuple_ptr->m_header_bits;
- Uint32 fix_sz = regTabPtr->m_offsets[MM].m_fix_header_size;
-
- if(sizes[MM] == sizes[2+MM])
- ;
- else if(sizes[MM] > sizes[2+MM])
- {
- if(0) ndbout_c("shrink");
- copy_bits |= Tuple_header::MM_SHRINK;
- }
- else
- {
- if(0) printf("grow - ");
- Ptr<Page> pagePtr = req_struct->m_varpart_page_ptr;
- Var_page* pageP= (Var_page*)pagePtr.p;
- Uint32 idx, alloc, needed;
- Var_part_ref *refptr = org->get_var_part_ref_ptr(regTabPtr);
- ndbassert(bits & Tuple_header::CHAINED_ROW);
-
- Local_key ref;
- refptr->copyout(&ref);
- idx= ref.m_page_idx;
- if (! (copy_bits & Tuple_header::CHAINED_ROW))
- {
- c_page_pool.getPtr(pagePtr, ref.m_page_no);
- pageP = (Var_page*)pagePtr.p;
- }
- alloc= pageP->get_entry_len(idx);
-#ifdef VM_TRACE
- if(!pageP->get_entry_chain(idx))
- ndbout << *pageP << endl;
-#endif
- ndbassert(pageP->get_entry_chain(idx));
- needed= sizes[2+MM] - fix_sz;
-
- if(needed <= alloc)
- {
- //ndbassert(!regOperPtr->is_first_operation());
- if (0) ndbout_c(" no grow");
- return 0;
- }
- copy_bits |= Tuple_header::MM_GROWN;
- if (unlikely(realloc_var_part(regFragPtr, regTabPtr, pagePtr,
- refptr, alloc, needed)))
- return -1;
-
- if (regTabPtr->m_bits & Tablerec::TR_Checksum)
- {
- jam();
- setChecksum(org, regTabPtr);
- }
- }
- req_struct->m_tuple_ptr->m_header_bits = copy_bits;
- return 0;
-}
-
-int
-Dbtup::nr_update_gci(Uint32 fragPtrI, const Local_key* key, Uint32 gci)
-{
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- if (tablePtr.p->m_bits & Tablerec::TR_RowGCI)
- {
- Local_key tmp = *key;
- PagePtr page_ptr;
-
- int ret = alloc_page(tablePtr.p, fragPtr.p, &page_ptr, tmp.m_page_no);
-
- if (ret)
- return -1;
-
- Tuple_header* ptr = (Tuple_header*)
- ((Fix_page*)page_ptr.p)->get_ptr(tmp.m_page_idx, 0);
-
- ndbrequire(ptr->m_header_bits & Tuple_header::FREE);
- *ptr->get_mm_gci(tablePtr.p) = gci;
- }
- return 0;
-}
-
-int
-Dbtup::nr_read_pk(Uint32 fragPtrI,
- const Local_key* key, Uint32* dst, bool& copy)
-{
-
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- Local_key tmp = *key;
-
-
- PagePtr page_ptr;
- int ret = alloc_page(tablePtr.p, fragPtr.p, &page_ptr, tmp.m_page_no);
- if (ret)
- return -1;
-
- KeyReqStruct req_struct;
- Uint32* ptr= ((Fix_page*)page_ptr.p)->get_ptr(key->m_page_idx, 0);
-
- req_struct.m_page_ptr = page_ptr;
- req_struct.m_tuple_ptr = (Tuple_header*)ptr;
- Uint32 bits = req_struct.m_tuple_ptr->m_header_bits;
-
- ret = 0;
- copy = false;
- if (! (bits & Tuple_header::FREE))
- {
- if (bits & Tuple_header::ALLOC)
- {
- Uint32 opPtrI= req_struct.m_tuple_ptr->m_operation_ptr_i;
- Operationrec* opPtrP= c_operation_pool.getPtr(opPtrI);
- ndbassert(!opPtrP->m_copy_tuple_location.isNull());
- req_struct.m_tuple_ptr= (Tuple_header*)
- c_undo_buffer.get_ptr(&opPtrP->m_copy_tuple_location);
- copy = true;
- }
- req_struct.check_offset[MM]= tablePtr.p->get_check_offset(MM);
- req_struct.check_offset[DD]= tablePtr.p->get_check_offset(DD);
-
- Uint32 num_attr= tablePtr.p->m_no_of_attributes;
- Uint32 descr_start= tablePtr.p->tabDescriptor;
- TableDescriptor *tab_descr= &tableDescriptor[descr_start];
- ndbrequire(descr_start + (num_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
- req_struct.attr_descr= tab_descr;
-
- if (tablePtr.p->need_expand())
- prepare_read(&req_struct, tablePtr.p, false);
-
- const Uint32* attrIds= &tableDescriptor[tablePtr.p->readKeyArray].tabDescr;
- const Uint32 numAttrs= tablePtr.p->noOfKeyAttr;
- // read pk attributes from original tuple
-
- // new globals
- tabptr= tablePtr;
- fragptr= fragPtr;
- operPtr.i= RNIL;
- operPtr.p= NULL;
-
- // do it
- ret = readAttributes(&req_struct,
- attrIds,
- numAttrs,
- dst,
- ZNIL, false);
-
- // done
- if (likely(ret != -1)) {
- // remove headers
- Uint32 n= 0;
- Uint32 i= 0;
- while (n < numAttrs) {
- const AttributeHeader ah(dst[i]);
- Uint32 size= ah.getDataSize();
- ndbrequire(size != 0);
- for (Uint32 j= 0; j < size; j++) {
- dst[i + j - n]= dst[i + j + 1];
- }
- n+= 1;
- i+= 1 + size;
- }
- ndbrequire((int)i == ret);
- ret -= numAttrs;
- } else {
- return terrorCode ? (-(int)terrorCode) : -1;
- }
- }
-
- if (tablePtr.p->m_bits & Tablerec::TR_RowGCI)
- {
- dst[ret] = *req_struct.m_tuple_ptr->get_mm_gci(tablePtr.p);
- }
- else
- {
- dst[ret] = 0;
- }
- return ret;
-}
-
-#include <signaldata/TuxMaint.hpp>
-
-int
-Dbtup::nr_delete(Signal* signal, Uint32 senderData,
- Uint32 fragPtrI, const Local_key* key, Uint32 gci)
-{
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- Local_key tmp = * key;
- tmp.m_page_no= getRealpid(fragPtr.p, tmp.m_page_no);
-
- PagePtr pagePtr;
- Tuple_header* ptr= (Tuple_header*)get_ptr(&pagePtr, &tmp, tablePtr.p);
-
- if (!tablePtr.p->tuxCustomTriggers.isEmpty())
- {
- jam();
- TuxMaintReq* req = (TuxMaintReq*)signal->getDataPtrSend();
- req->tableId = fragPtr.p->fragTableId;
- req->fragId = fragPtr.p->fragmentId;
- req->pageId = tmp.m_page_no;
- req->pageIndex = tmp.m_page_idx;
- req->tupVersion = ptr->get_tuple_version();
- req->opInfo = TuxMaintReq::OpRemove;
- removeTuxEntries(signal, tablePtr.p);
- }
-
- Local_key disk;
- memcpy(&disk, ptr->get_disk_ref_ptr(tablePtr.p), sizeof(disk));
-
- if (tablePtr.p->m_attributes[MM].m_no_of_varsize)
- {
- jam();
- free_var_rec(fragPtr.p, tablePtr.p, &tmp, pagePtr);
- } else {
- jam();
- free_fix_rec(fragPtr.p, tablePtr.p, &tmp, (Fix_page*)pagePtr.p);
- }
-
- if (tablePtr.p->m_no_of_disk_attributes)
- {
- jam();
-
- Uint32 sz = (sizeof(Dbtup::Disk_undo::Free) >> 2) +
- tablePtr.p->m_offsets[DD].m_fix_header_size - 1;
-
- int res = c_lgman->alloc_log_space(fragPtr.p->m_logfile_group_id, sz);
- ndbrequire(res == 0);
-
- /**
- * 1) alloc log buffer
- * 2) get page
- * 3) get log buffer
- * 4) delete tuple
- */
- Page_cache_client::Request preq;
- preq.m_page = disk;
- preq.m_callback.m_callbackData = senderData;
- preq.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::nr_delete_page_callback);
- int flags = Page_cache_client::COMMIT_REQ;
-
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(4023) || ERROR_INSERTED(4024))
- {
- int rnd = rand() % 100;
- int slp = 0;
- if (ERROR_INSERTED(4024))
- {
- slp = 3000;
- }
- else if (rnd > 90)
- {
- slp = 3000;
- }
- else if (rnd > 70)
- {
- slp = 100;
- }
-
- ndbout_c("rnd: %d slp: %d", rnd, slp);
-
- if (slp)
- {
- flags |= Page_cache_client::DELAY_REQ;
- preq.m_delay_until_time = NdbTick_CurrentMillisecond()+(Uint64)slp;
- }
- }
-#endif
-
- res = m_pgman.get_page(signal, preq, flags);
- if (res == 0)
- {
- goto timeslice;
- }
- else if (unlikely(res == -1))
- {
- return -1;
- }
-
- PagePtr disk_page = *(PagePtr*)&m_pgman.m_ptr;
- disk_page_set_dirty(disk_page);
-
- preq.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::nr_delete_log_buffer_callback);
- Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
- res= lgman.get_log_buffer(signal, sz, &preq.m_callback);
- switch(res){
- case 0:
- signal->theData[2] = disk_page.i;
- goto timeslice;
- case -1:
- ndbrequire("NOT YET IMPLEMENTED" == 0);
- break;
- }
-
- if (0) ndbout << "DIRECT DISK DELETE: " << disk << endl;
- disk_page_free(signal, tablePtr.p, fragPtr.p,
- &disk, *(PagePtr*)&disk_page, gci);
- return 0;
- }
-
- return 0;
-
-timeslice:
- memcpy(signal->theData, &disk, sizeof(disk));
- return 1;
-}
-
-void
-Dbtup::nr_delete_page_callback(Signal* signal,
- Uint32 userpointer, Uint32 page_id)
-{
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, page_id);
- PagePtr pagePtr= *(PagePtr*)&gpage;
- disk_page_set_dirty(pagePtr);
- Dblqh::Nr_op_info op;
- op.m_ptr_i = userpointer;
- op.m_disk_ref.m_page_no = pagePtr.p->m_page_no;
- op.m_disk_ref.m_file_no = pagePtr.p->m_file_no;
- c_lqh->get_nr_op_info(&op, page_id);
-
- Ptr<Fragrecord> fragPtr;
- fragPtr.i= op.m_tup_frag_ptr_i;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- Ptr<Tablerec> tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- Uint32 sz = (sizeof(Dbtup::Disk_undo::Free) >> 2) +
- tablePtr.p->m_offsets[DD].m_fix_header_size - 1;
-
- Callback cb;
- cb.m_callbackData = userpointer;
- cb.m_callbackFunction =
- safe_cast(&Dbtup::nr_delete_log_buffer_callback);
- Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
- int res= lgman.get_log_buffer(signal, sz, &cb);
- switch(res){
- case 0:
- return;
- case -1:
- ndbrequire("NOT YET IMPLEMENTED" == 0);
- break;
- }
-
- if (0) ndbout << "PAGE CALLBACK DISK DELETE: " << op.m_disk_ref << endl;
- disk_page_free(signal, tablePtr.p, fragPtr.p,
- &op.m_disk_ref, pagePtr, op.m_gci);
-
- c_lqh->nr_delete_complete(signal, &op);
- return;
-}
-
-void
-Dbtup::nr_delete_log_buffer_callback(Signal* signal,
- Uint32 userpointer,
- Uint32 unused)
-{
- Dblqh::Nr_op_info op;
- op.m_ptr_i = userpointer;
- c_lqh->get_nr_op_info(&op, RNIL);
-
- Ptr<Fragrecord> fragPtr;
- fragPtr.i= op.m_tup_frag_ptr_i;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- Ptr<Tablerec> tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- Ptr<GlobalPage> gpage;
- m_global_page_pool.getPtr(gpage, op.m_page_id);
- PagePtr pagePtr= *(PagePtr*)&gpage;
-
- /**
- * reset page no
- */
- if (0) ndbout << "LOGBUFFER CALLBACK DISK DELETE: " << op.m_disk_ref << endl;
-
- disk_page_free(signal, tablePtr.p, fragPtr.p,
- &op.m_disk_ref, pagePtr, op.m_gci);
-
- c_lqh->nr_delete_complete(signal, &op);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp
deleted file mode 100644
index 6822deb8b19..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_FIXALLOC_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-
-//
-// Fixed Allocator
-// This module is used to allocate and free fixed size tuples from the
-// set of pages attached to a fragment. The fixed size is preset per
-// fragment and their can only be one such value per fragment in the
-// current implementation.
-//
-// Public methods
-// bool
-// alloc_fix_rec(Fragrecord* const regFragPtr, # In
-// Tablerec* const regTabPtr, # In
-// Uint32 pageType, # In
-// Signal* signal, # In
-// Uint32& pageOffset, # Out
-// PagePtr& pagePtr) # In/Out
-// This method allocates a fixed size and the pagePtr is a reference
-// to the page and pageOffset is the offset in the page of the tuple.
-//
-// freeTh()
-// This method is used to free a tuple header in normal transaction
-// handling.
-//
-// getThAtPageSr()
-// This method is used to allocate a tuple on a set page as part of
-// undo log execution.
-//
-//
-// Private methods
-// getThAtPage()
-// This method gets a tuple from a page with free tuples.
-//
-// convertThPage()
-// Convert an empty page into a page of free tuples in a linked list.
-//
-// getEmptyPageTh()
-// A page recently taken from the set of empty pages on the fragment is
-// is made part of the set of free pages with fixed size tuples in the
-// fragment.
-//
-Uint32*
-Dbtup::alloc_fix_rec(Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr,
- Local_key* key,
- Uint32 * out_frag_page_id)
-{
-/* ---------------------------------------------------------------- */
-/* EITHER NORMAL PAGE REQUESTED OR ALLOCATION FROM COPY PAGE */
-/* FAILED. TRY ALLOCATING FROM NORMAL PAGE. */
-/* ---------------------------------------------------------------- */
- PagePtr pagePtr;
- pagePtr.i = regFragPtr->thFreeFirst.firstItem;
- if (pagePtr.i == RNIL) {
-/* ---------------------------------------------------------------- */
-// No prepared tuple header page with free entries exists.
-/* ---------------------------------------------------------------- */
- pagePtr.i = getEmptyPage(regFragPtr);
- if (pagePtr.i != RNIL) {
- jam();
-/* ---------------------------------------------------------------- */
-// We found empty pages on the fragment. Allocate an empty page and
-// convert it into a tuple header page and put it in thFreeFirst-list.
-/* ---------------------------------------------------------------- */
- c_page_pool.getPtr(pagePtr);
-
- ndbassert(pagePtr.p->page_state == ZEMPTY_MM);
-
- convertThPage((Fix_page*)pagePtr.p, regTabPtr, MM);
-
- pagePtr.p->page_state = ZTH_MM_FREE;
-
- LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
- free_pages.addFirst(pagePtr);
- } else {
- jam();
-/* ---------------------------------------------------------------- */
-/* THERE ARE NO EMPTY PAGES. MEMORY CAN NOT BE ALLOCATED. */
-/* ---------------------------------------------------------------- */
- return 0;
- }
- } else {
- jam();
-/* ---------------------------------------------------------------- */
-/* THIS SHOULD BE THE COMMON PATH THROUGH THE CODE, FREE */
-/* COPY PAGE EXISTED. */
-/* ---------------------------------------------------------------- */
- c_page_pool.getPtr(pagePtr);
- }
-
- Uint32 page_offset= alloc_tuple_from_page(regFragPtr, (Fix_page*)pagePtr.p);
-
- *out_frag_page_id= pagePtr.p->frag_page_id;
- key->m_page_no = pagePtr.i;
- key->m_page_idx = page_offset;
- return pagePtr.p->m_data + page_offset;
-}
-
-void Dbtup::convertThPage(Fix_page* regPagePtr,
- Tablerec* regTabPtr,
- Uint32 mm)
-{
- Uint32 nextTuple = regTabPtr->m_offsets[mm].m_fix_header_size;
- /*
- ASSUMES AT LEAST ONE TUPLE HEADER FITS AND THEREFORE NO HANDLING
- OF ZERO AS EXTREME CASE
- */
- Uint32 cnt= 0;
- Uint32 pos= 0;
- Uint32 prev = 0xFFFF;
-#ifdef VM_TRACE
- memset(regPagePtr->m_data, 0xF1, 4*Fix_page::DATA_WORDS);
-#endif
- Uint32 gci_pos = 2;
- Uint32 gci_val = 0xF1F1F1F1;
- if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
- {
- Tuple_header* ptr = 0;
- gci_pos = ptr->get_mm_gci(regTabPtr) - (Uint32*)ptr;
- gci_val = 0;
- }
- while (pos + nextTuple <= Fix_page::DATA_WORDS)
- {
- regPagePtr->m_data[pos] = (prev << 16) | (pos + nextTuple);
- regPagePtr->m_data[pos + 1] = Fix_page::FREE_RECORD;
- regPagePtr->m_data[pos + gci_pos] = gci_val;
- prev = pos;
- pos += nextTuple;
- cnt ++;
- }
-
- regPagePtr->m_data[prev] |= 0xFFFF;
- regPagePtr->next_free_index= 0;
- regPagePtr->free_space= cnt;
- regPagePtr->m_page_header.m_page_type = File_formats::PT_Tup_fixsize_page;
-}//Dbtup::convertThPage()
-
-Uint32
-Dbtup::alloc_tuple_from_page(Fragrecord* const regFragPtr,
- Fix_page* const regPagePtr)
-{
- ndbassert(regPagePtr->free_space);
- Uint32 idx= regPagePtr->alloc_record();
- if(regPagePtr->free_space == 0)
- {
- jam();
-/* ---------------------------------------------------------------- */
-/* THIS WAS THE LAST TUPLE HEADER IN THIS PAGE. REMOVE IT FROM*/
-/* THE TUPLE HEADER FREE LIST OR TH COPY FREE LIST. ALSO SET */
-/* A PROPER PAGE STATE. */
-/* */
-/* WE ALSO HAVE TO INSERT AN UNDO LOG ENTRY TO ENSURE PAGE */
-/* ARE MAINTAINED EVEN AFTER A SYSTEM CRASH. */
-/* ---------------------------------------------------------------- */
- ndbrequire(regPagePtr->page_state == ZTH_MM_FREE);
- LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
- free_pages.remove((Page*)regPagePtr);
- regPagePtr->page_state = ZTH_MM_FULL;
- }
-
- return idx;
-}//Dbtup::getThAtPage()
-
-
-void Dbtup::free_fix_rec(Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- Local_key* key,
- Fix_page* regPagePtr)
-{
- Uint32 free= regPagePtr->free_record(key->m_page_idx);
-
- if(free == 1)
- {
- jam();
- PagePtr pagePtr = { (Page*)regPagePtr, key->m_page_no };
- LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
- ndbrequire(regPagePtr->page_state == ZTH_MM_FULL);
- regPagePtr->page_state = ZTH_MM_FREE;
- free_pages.addLast(pagePtr);
- }
-}//Dbtup::freeTh()
-
-
-int
-Dbtup::alloc_page(Tablerec* tabPtrP, Fragrecord* fragPtrP,
- PagePtr * ret, Uint32 page_no)
-{
- Uint32 pages = fragPtrP->noOfPages;
-
- if (page_no >= pages)
- {
- Uint32 start = pages;
- while(page_no >= pages)
- pages += (pages >> 3) + (pages >> 4) + 2;
- allocFragPages(fragPtrP, pages - start);
- if (page_no >= (pages = fragPtrP->noOfPages))
- {
- terrorCode = ZMEM_NOMEM_ERROR;
- return 1;
- }
- }
-
- PagePtr pagePtr;
- c_page_pool.getPtr(pagePtr, getRealpid(fragPtrP, page_no));
-
- LocalDLList<Page> alloc_pages(c_page_pool, fragPtrP->emptyPrimPage);
- LocalDLFifoList<Page> free_pages(c_page_pool, fragPtrP->thFreeFirst);
- if (pagePtr.p->page_state == ZEMPTY_MM)
- {
- convertThPage((Fix_page*)pagePtr.p, tabPtrP, MM);
- pagePtr.p->page_state = ZTH_MM_FREE;
- alloc_pages.remove(pagePtr);
- free_pages.addFirst(pagePtr);
- }
-
- *ret = pagePtr;
- return 0;
-}
-
-Uint32*
-Dbtup::alloc_fix_rowid(Fragrecord* regFragPtr,
- Tablerec* regTabPtr,
- Local_key* key,
- Uint32 * out_frag_page_id)
-{
- Uint32 page_no = key->m_page_no;
- Uint32 idx= key->m_page_idx;
-
- PagePtr pagePtr;
- if (alloc_page(regTabPtr, regFragPtr, &pagePtr, page_no))
- {
- terrorCode = ZMEM_NOMEM_ERROR;
- return 0;
- }
-
- Uint32 state = pagePtr.p->page_state;
- LocalDLFifoList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
- switch(state){
- case ZTH_MM_FREE:
- if (((Fix_page*)pagePtr.p)->alloc_record(idx) != idx)
- {
- terrorCode = ZROWID_ALLOCATED;
- return 0;
- }
-
- if(pagePtr.p->free_space == 0)
- {
- jam();
- pagePtr.p->page_state = ZTH_MM_FULL;
- free_pages.remove(pagePtr);
- }
-
- *out_frag_page_id= page_no;
- key->m_page_no = pagePtr.i;
- key->m_page_idx = idx;
- return pagePtr.p->m_data + idx;
- case ZTH_MM_FULL:
- terrorCode = ZROWID_ALLOCATED;
- return 0;
- case ZEMPTY_MM:
- ndbrequire(false);
- }
- return 0; /* purify: deadcode */
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
deleted file mode 100644
index 262701b3d87..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
+++ /dev/null
@@ -1,749 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_GEN_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <AttributeDescriptor.hpp>
-#include "AttributeOffset.hpp"
-#include <AttributeHeader.hpp>
-#include <Interpreter.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsRemoveReq.hpp>
-#include <signaldata/TupCommit.hpp>
-#include <signaldata/TupKey.hpp>
-
-#include <signaldata/DropTab.hpp>
-#include <SLList.hpp>
-
-#define DEBUG(x) { ndbout << "TUP::" << x << endl; }
-
-void Dbtup::initData()
-{
- cnoOfAttrbufrec = ZNO_OF_ATTRBUFREC;
- cnoOfFragrec = MAX_FRAG_PER_NODE;
- cnoOfFragoprec = MAX_FRAG_PER_NODE;
- cnoOfPageRangeRec = ZNO_OF_PAGE_RANGE_REC;
- c_maxTriggersPerTable = ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE;
- c_noOfBuildIndexRec = 32;
-
- // Records with constant sizes
- init_list_sizes();
-}//Dbtup::initData()
-
-Dbtup::Dbtup(Block_context& ctx, Pgman* pgman)
- : SimulatedBlock(DBTUP, ctx),
- c_lqh(0),
- m_pgman(this, pgman),
- c_extent_hash(c_extent_pool),
- c_storedProcPool(),
- c_buildIndexList(c_buildIndexPool),
- c_undo_buffer(this)
-{
- BLOCK_CONSTRUCTOR(Dbtup);
-
- addRecSignal(GSN_DEBUG_SIG, &Dbtup::execDEBUG_SIG);
- addRecSignal(GSN_CONTINUEB, &Dbtup::execCONTINUEB);
- addRecSignal(GSN_LCP_FRAG_ORD, &Dbtup::execLCP_FRAG_ORD);
-
- addRecSignal(GSN_DUMP_STATE_ORD, &Dbtup::execDUMP_STATE_ORD);
- addRecSignal(GSN_SEND_PACKED, &Dbtup::execSEND_PACKED);
- addRecSignal(GSN_ATTRINFO, &Dbtup::execATTRINFO);
- addRecSignal(GSN_STTOR, &Dbtup::execSTTOR);
- addRecSignal(GSN_MEMCHECKREQ, &Dbtup::execMEMCHECKREQ);
- addRecSignal(GSN_TUPKEYREQ, &Dbtup::execTUPKEYREQ);
- addRecSignal(GSN_TUPSEIZEREQ, &Dbtup::execTUPSEIZEREQ);
- addRecSignal(GSN_TUPRELEASEREQ, &Dbtup::execTUPRELEASEREQ);
- addRecSignal(GSN_STORED_PROCREQ, &Dbtup::execSTORED_PROCREQ);
- addRecSignal(GSN_TUPFRAGREQ, &Dbtup::execTUPFRAGREQ);
- addRecSignal(GSN_TUP_ADD_ATTRREQ, &Dbtup::execTUP_ADD_ATTRREQ);
- addRecSignal(GSN_TUP_COMMITREQ, &Dbtup::execTUP_COMMITREQ);
- addRecSignal(GSN_TUP_ABORTREQ, &Dbtup::execTUP_ABORTREQ);
- addRecSignal(GSN_NDB_STTOR, &Dbtup::execNDB_STTOR);
- addRecSignal(GSN_READ_CONFIG_REQ, &Dbtup::execREAD_CONFIG_REQ, true);
-
- // Trigger Signals
- addRecSignal(GSN_CREATE_TRIG_REQ, &Dbtup::execCREATE_TRIG_REQ);
- addRecSignal(GSN_DROP_TRIG_REQ, &Dbtup::execDROP_TRIG_REQ);
-
- addRecSignal(GSN_DROP_TAB_REQ, &Dbtup::execDROP_TAB_REQ);
-
- addRecSignal(GSN_TUP_DEALLOCREQ, &Dbtup::execTUP_DEALLOCREQ);
- addRecSignal(GSN_TUP_WRITELOG_REQ, &Dbtup::execTUP_WRITELOG_REQ);
-
- // 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);
- addRecSignal(GSN_ACCKEYCONF, &Dbtup::execACCKEYCONF);
- addRecSignal(GSN_ACCKEYREF, &Dbtup::execACCKEYREF);
- addRecSignal(GSN_ACC_ABORTCONF, &Dbtup::execACC_ABORTCONF);
-
- // Drop table
- addRecSignal(GSN_FSREMOVEREF, &Dbtup::execFSREMOVEREF, true);
- addRecSignal(GSN_FSREMOVECONF, &Dbtup::execFSREMOVECONF, true);
-
- attrbufrec = 0;
- fragoperrec = 0;
- fragrecord = 0;
- hostBuffer = 0;
- pageRange = 0;
- tablerec = 0;
- tableDescriptor = 0;
- totNoOfPagesAllocated = 0;
- cnoOfAllocatedPages = 0;
-
- initData();
- CLEAR_ERROR_INSERT_VALUE;
-}//Dbtup::Dbtup()
-
-Dbtup::~Dbtup()
-{
- // Records with dynamic sizes
- deallocRecord((void **)&attrbufrec,"Attrbufrec",
- sizeof(Attrbufrec),
- cnoOfAttrbufrec);
-
- deallocRecord((void **)&fragoperrec,"Fragoperrec",
- sizeof(Fragoperrec),
- cnoOfFragoprec);
-
- deallocRecord((void **)&fragrecord,"Fragrecord",
- sizeof(Fragrecord),
- cnoOfFragrec);
-
- deallocRecord((void **)&hostBuffer,"HostBuffer",
- sizeof(HostBuffer),
- MAX_NODES);
-
- deallocRecord((void **)&pageRange,"PageRange",
- sizeof(PageRange),
- cnoOfPageRangeRec);
-
- deallocRecord((void **)&tablerec,"Tablerec",
- sizeof(Tablerec),
- cnoOfTablerec);
-
- deallocRecord((void **)&tableDescriptor, "TableDescriptor",
- sizeof(TableDescriptor),
- cnoOfTabDescrRec);
-
-}//Dbtup::~Dbtup()
-
-BLOCK_FUNCTIONS(Dbtup)
-
-void Dbtup::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- Uint32 actionType = signal->theData[0];
- Uint32 dataPtr = signal->theData[1];
- switch (actionType) {
- case ZINITIALISE_RECORDS:
- jam();
- initialiseRecordsLab(signal, dataPtr,
- signal->theData[2], signal->theData[3]);
- break;
- case ZREL_FRAG:
- jam();
- releaseFragment(signal, dataPtr, signal->theData[2]);
- break;
- case ZREPORT_MEMORY_USAGE:{
- jam();
- static int c_currentMemUsed = 0;
- Uint32 cnt = signal->theData[1];
- Uint32 tmp = c_page_pool.getSize();
- int now = tmp ? (cnoOfAllocatedPages * 100)/tmp : 0;
- const int thresholds[] = { 100, 90, 80, 0 };
-
- Uint32 i = 0;
- const Uint32 sz = sizeof(thresholds)/sizeof(thresholds[0]);
- for(i = 0; i<sz; i++){
- if(now >= thresholds[i]){
- now = thresholds[i];
- break;
- }
- }
-
- if(now != c_currentMemUsed ||
- (c_memusage_report_frequency && cnt + 1 == c_memusage_report_frequency))
- {
- reportMemoryUsage(signal,
- now > c_currentMemUsed ? 1 :
- now < c_currentMemUsed ? -1 : 0);
- cnt = 0;
- c_currentMemUsed = now;
- }
- else
- {
- cnt++;
- }
- signal->theData[0] = ZREPORT_MEMORY_USAGE;
- signal->theData[1] = cnt;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 2);
- return;
- }
- case ZBUILD_INDEX:
- jam();
- buildIndex(signal, dataPtr);
- break;
- case ZTUP_SCAN:
- jam();
- {
- ScanOpPtr scanPtr;
- c_scanOpPool.getPtr(scanPtr, dataPtr);
- scanCont(signal, scanPtr);
- }
- return;
- case ZFREE_EXTENT:
- {
- jam();
-
- TablerecPtr tabPtr;
- tabPtr.i= dataPtr;
- FragrecordPtr fragPtr;
- fragPtr.i= signal->theData[2];
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- drop_fragment_free_extent(signal, tabPtr, fragPtr, signal->theData[3]);
- return;
- }
- case ZUNMAP_PAGES:
- {
- jam();
-
- TablerecPtr tabPtr;
- tabPtr.i= dataPtr;
- FragrecordPtr fragPtr;
- fragPtr.i= signal->theData[2];
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- drop_fragment_unmap_pages(signal, tabPtr, fragPtr, signal->theData[3]);
- return;
- }
- case ZFREE_VAR_PAGES:
- {
- jam();
- drop_fragment_free_var_pages(signal);
- return;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
-}//Dbtup::execTUP_CONTINUEB()
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* ------------------- SYSTEM RESTART MODULE ---------------------- */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-void Dbtup::execSTTOR(Signal* signal)
-{
- jamEntry();
- Uint32 startPhase = signal->theData[1];
- Uint32 sigKey = signal->theData[6];
- switch (startPhase) {
- case ZSTARTPHASE1:
- jam();
- ndbrequire((c_lqh= (Dblqh*)globalData.getBlock(DBLQH)) != 0);
- ndbrequire((c_tsman= (Tsman*)globalData.getBlock(TSMAN)) != 0);
- ndbrequire((c_lgman= (Lgman*)globalData.getBlock(LGMAN)) != 0);
- cownref = calcTupBlockRef(0);
- break;
- default:
- jam();
- break;
- }//switch
- signal->theData[0] = sigKey;
- signal->theData[1] = 3;
- signal->theData[2] = 2;
- signal->theData[3] = ZSTARTPHASE1;
- signal->theData[4] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
- return;
-}//Dbtup::execSTTOR()
-
-/************************************************************************************************/
-// SIZE_ALTREP INITIALIZE DATA STRUCTURES, FILES AND DS VARIABLES, GET READY FOR EXTERNAL
-// CONNECTIONS.
-/************************************************************************************************/
-void Dbtup::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_FRAG, &cnoOfFragrec));
-
- Uint32 noOfTriggers= 0;
-
- Uint32 tmp= 0;
-
- if (ndb_mgm_get_int_parameter(p, CFG_DB_MAX_ALLOCATE, &tmp))
- tmp = 32 * 1024 * 1024;
- m_max_allocate_pages = (tmp + GLOBAL_PAGE_SIZE - 1) / GLOBAL_PAGE_SIZE;
-
- tmp = 0;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE_RANGE, &tmp));
- initPageRangeSize(tmp);
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_TABLE, &cnoOfTablerec));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_TABLE_DESC,
- &cnoOfTabDescrRec));
- Uint32 noOfStoredProc;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_STORED_PROC,
- &noOfStoredProc));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
- &noOfTriggers));
-
- cnoOfTabDescrRec = (cnoOfTabDescrRec & 0xFFFFFFF0) + 16;
-
- initRecords();
-
- c_storedProcPool.setSize(noOfStoredProc);
- c_buildIndexPool.setSize(c_noOfBuildIndexRec);
- c_triggerPool.setSize(noOfTriggers, false, true, true, CFG_DB_NO_TRIGGERS);
-
- c_extent_hash.setSize(1024); // 4k
-
- Pool_context pc;
- pc.m_block = this;
- c_page_request_pool.wo_pool_init(RT_DBTUP_PAGE_REQUEST, pc);
- c_extent_pool.init(RT_DBTUP_EXTENT_INFO, pc);
-
- Uint32 nScanOp; // use TUX config for now
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
- c_scanOpPool.setSize(nScanOp + 1);
- Uint32 nScanBatch;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_BATCH_SIZE, &nScanBatch));
- c_scanLockPool.setSize(nScanOp * nScanBatch);
-
-
- /* read ahead for disk scan can not be more that disk page buffer */
- {
- Uint64 tmp = 64*1024*1024;
- ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY, &tmp);
- m_max_page_read_ahead = (tmp + GLOBAL_PAGE_SIZE - 1) / GLOBAL_PAGE_SIZE; // in pages
- // never read ahead more than 32 pages
- if (m_max_page_read_ahead > 32)
- m_max_page_read_ahead = 32;
- }
-
-
- ScanOpPtr lcp;
- ndbrequire(c_scanOpPool.seize(lcp));
- new (lcp.p) ScanOp();
- c_lcp_scan_op= lcp.i;
-
- czero = 0;
- cminusOne = czero - 1;
- clastBitMask = 1;
- clastBitMask = clastBitMask << 31;
-
- c_memusage_report_frequency = 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_MEMREPORT_FREQUENCY,
- &c_memusage_report_frequency);
-
- initialiseRecordsLab(signal, 0, ref, senderData);
-}//Dbtup::execSIZEALT_REP()
-
-void Dbtup::initRecords()
-{
- unsigned i;
- Uint32 tmp;
- Uint32 tmp1 = 0;
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE, &tmp));
-
- // Records with dynamic sizes
- Page* ptr =(Page*)allocRecord("Page", sizeof(Page), tmp, false, CFG_DB_DATA_MEM);
- c_page_pool.set(ptr, tmp);
-
- attrbufrec = (Attrbufrec*)allocRecord("Attrbufrec",
- sizeof(Attrbufrec),
- cnoOfAttrbufrec);
-
- fragoperrec = (Fragoperrec*)allocRecord("Fragoperrec",
- sizeof(Fragoperrec),
- cnoOfFragoprec);
-
- fragrecord = (Fragrecord*)allocRecord("Fragrecord",
- sizeof(Fragrecord),
- cnoOfFragrec);
-
- hostBuffer = (HostBuffer*)allocRecord("HostBuffer",
- sizeof(HostBuffer),
- MAX_NODES);
-
- tableDescriptor = (TableDescriptor*)allocRecord("TableDescriptor",
- sizeof(TableDescriptor),
- cnoOfTabDescrRec);
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &tmp));
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_LOCAL_OPS, &tmp1);
- c_operation_pool.setSize(tmp, false, true, true,
- tmp1 == 0 ? CFG_DB_NO_OPS : CFG_DB_NO_LOCAL_OPS);
-
- pageRange = (PageRange*)allocRecord("PageRange",
- sizeof(PageRange),
- cnoOfPageRangeRec);
-
- tablerec = (Tablerec*)allocRecord("Tablerec",
- sizeof(Tablerec),
- cnoOfTablerec);
-
- for (i = 0; i<cnoOfTablerec; i++) {
- void * p = &tablerec[i];
- new (p) Tablerec(c_triggerPool);
- }
-}//Dbtup::initRecords()
-
-void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
- Uint32 retRef, Uint32 retData)
-{
- switch (switchData) {
- case 0:
- jam();
- initializeHostBuffer();
- break;
- case 1:
- jam();
- initializeOperationrec();
- break;
- case 2:
- jam();
- initializePage();
- break;
- case 3:
- jam();
- break;
- case 4:
- jam();
- initializeTablerec();
- break;
- case 5:
- jam();
- break;
- case 6:
- jam();
- initializeFragrecord();
- break;
- case 7:
- jam();
- initializeFragoperrec();
- break;
- case 8:
- jam();
- initializePageRange();
- break;
- case 9:
- jam();
- initializeTabDescr();
- break;
- case 10:
- jam();
- break;
- case 11:
- jam();
- break;
- case 12:
- jam();
- initializeAttrbufrec();
- break;
- case 13:
- jam();
- break;
- case 14:
- jam();
-
- {
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = retData;
- sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
- }
- return;
- default:
- ndbrequire(false);
- break;
- }//switch
- signal->theData[0] = ZINITIALISE_RECORDS;
- signal->theData[1] = switchData + 1;
- signal->theData[2] = retRef;
- signal->theData[3] = retData;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
- return;
-}//Dbtup::initialiseRecordsLab()
-
-void Dbtup::execNDB_STTOR(Signal* signal)
-{
- jamEntry();
- cndbcntrRef = signal->theData[0];
- Uint32 ownNodeId = signal->theData[1];
- Uint32 startPhase = signal->theData[2];
- switch (startPhase) {
- case ZSTARTPHASE1:
- jam();
- cownNodeId = ownNodeId;
- cownref = calcTupBlockRef(ownNodeId);
- break;
- case ZSTARTPHASE2:
- jam();
- break;
- case ZSTARTPHASE3:
- jam();
- startphase3Lab(signal, ~0, ~0);
- break;
- case ZSTARTPHASE4:
- jam();
- break;
- case ZSTARTPHASE6:
- jam();
-/*****************************************/
-/* NOW SET THE DISK WRITE SPEED TO */
-/* PAGES PER TICK AFTER SYSTEM */
-/* RESTART. */
-/*****************************************/
- signal->theData[0] = ZREPORT_MEMORY_USAGE;
- signal->theData[1] = 0;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 2);
- break;
- default:
- jam();
- break;
- }//switch
- signal->theData[0] = cownref;
- sendSignal(cndbcntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
-}//Dbtup::execNDB_STTOR()
-
-void Dbtup::startphase3Lab(Signal* signal, Uint32 config1, Uint32 config2)
-{
-}//Dbtup::startphase3Lab()
-
-void Dbtup::initializeAttrbufrec()
-{
- AttrbufrecPtr attrBufPtr;
- for (attrBufPtr.i = 0;
- attrBufPtr.i < cnoOfAttrbufrec; attrBufPtr.i++) {
- refresh_watch_dog();
- ptrAss(attrBufPtr, attrbufrec);
- attrBufPtr.p->attrbuf[ZBUF_NEXT] = attrBufPtr.i + 1;
- }//for
- attrBufPtr.i = cnoOfAttrbufrec - 1;
- ptrAss(attrBufPtr, attrbufrec);
- attrBufPtr.p->attrbuf[ZBUF_NEXT] = RNIL;
- cfirstfreeAttrbufrec = 0;
- cnoFreeAttrbufrec = cnoOfAttrbufrec;
-}//Dbtup::initializeAttrbufrec()
-
-void Dbtup::initializeFragoperrec()
-{
- FragoperrecPtr fragoperPtr;
- for (fragoperPtr.i = 0; fragoperPtr.i < cnoOfFragoprec; fragoperPtr.i++) {
- ptrAss(fragoperPtr, fragoperrec);
- fragoperPtr.p->nextFragoprec = fragoperPtr.i + 1;
- }//for
- fragoperPtr.i = cnoOfFragoprec - 1;
- ptrAss(fragoperPtr, fragoperrec);
- fragoperPtr.p->nextFragoprec = RNIL;
- cfirstfreeFragopr = 0;
-}//Dbtup::initializeFragoperrec()
-
-void Dbtup::initializeFragrecord()
-{
- FragrecordPtr regFragPtr;
- for (regFragPtr.i = 0; regFragPtr.i < cnoOfFragrec; regFragPtr.i++) {
- refresh_watch_dog();
- ptrAss(regFragPtr, fragrecord);
- new (regFragPtr.p) Fragrecord();
- regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
- regFragPtr.p->fragStatus = IDLE;
- }//for
- regFragPtr.i = cnoOfFragrec - 1;
- ptrAss(regFragPtr, fragrecord);
- regFragPtr.p->nextfreefrag = RNIL;
- cfirstfreefrag = 0;
-}//Dbtup::initializeFragrecord()
-
-void Dbtup::initializeHostBuffer()
-{
- Uint32 hostId;
- cpackedListIndex = 0;
- for (hostId = 0; hostId < MAX_NODES; hostId++) {
- hostBuffer[hostId].inPackedList = false;
- hostBuffer[hostId].noOfPacketsTA = 0;
- hostBuffer[hostId].packetLenTA = 0;
- }//for
-}//Dbtup::initializeHostBuffer()
-
-
-void Dbtup::initializeOperationrec()
-{
- refresh_watch_dog();
-}//Dbtup::initializeOperationrec()
-
-void Dbtup::initializeTablerec()
-{
- TablerecPtr regTabPtr;
- for (regTabPtr.i = 0; regTabPtr.i < cnoOfTablerec; regTabPtr.i++) {
- jam();
- refresh_watch_dog();
- ptrAss(regTabPtr, tablerec);
- initTab(regTabPtr.p);
- }//for
-}//Dbtup::initializeTablerec()
-
-void
-Dbtup::initTab(Tablerec* const regTabPtr)
-{
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- regTabPtr->fragid[i] = RNIL;
- regTabPtr->fragrec[i] = RNIL;
- }//for
- regTabPtr->readFunctionArray = NULL;
- regTabPtr->updateFunctionArray = NULL;
- regTabPtr->charsetArray = NULL;
-
- regTabPtr->tabDescriptor = RNIL;
- regTabPtr->readKeyArray = RNIL;
-
- regTabPtr->m_bits = 0;
-
- regTabPtr->m_no_of_attributes = 0;
- regTabPtr->noOfKeyAttr = 0;
-
- regTabPtr->m_dropTable.tabUserPtr = RNIL;
- regTabPtr->m_dropTable.tabUserRef = 0;
- regTabPtr->tableStatus = NOT_DEFINED;
-
- // Clear trigger data
- if (!regTabPtr->afterInsertTriggers.isEmpty())
- regTabPtr->afterInsertTriggers.release();
- if (!regTabPtr->afterDeleteTriggers.isEmpty())
- regTabPtr->afterDeleteTriggers.release();
- if (!regTabPtr->afterUpdateTriggers.isEmpty())
- regTabPtr->afterUpdateTriggers.release();
- if (!regTabPtr->subscriptionInsertTriggers.isEmpty())
- regTabPtr->subscriptionInsertTriggers.release();
- if (!regTabPtr->subscriptionDeleteTriggers.isEmpty())
- regTabPtr->subscriptionDeleteTriggers.release();
- if (!regTabPtr->subscriptionUpdateTriggers.isEmpty())
- regTabPtr->subscriptionUpdateTriggers.release();
- if (!regTabPtr->constraintUpdateTriggers.isEmpty())
- regTabPtr->constraintUpdateTriggers.release();
- if (!regTabPtr->tuxCustomTriggers.isEmpty())
- regTabPtr->tuxCustomTriggers.release();
-}//Dbtup::initTab()
-
-void Dbtup::initializeTabDescr()
-{
- TableDescriptorPtr regTabDesPtr;
- for (Uint32 i = 0; i < 16; i++) {
- cfreeTdList[i] = RNIL;
- }//for
- for (regTabDesPtr.i = 0; regTabDesPtr.i < cnoOfTabDescrRec; regTabDesPtr.i++) {
- refresh_watch_dog();
- ptrAss(regTabDesPtr, tableDescriptor);
- regTabDesPtr.p->tabDescr = RNIL;
- }//for
- freeTabDescr(0, cnoOfTabDescrRec);
-}//Dbtup::initializeTabDescr()
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-/* --------------- CONNECT/DISCONNECT MODULE ---------------------- */
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::execTUPSEIZEREQ(Signal* signal)
-{
- OperationrecPtr regOperPtr;
- jamEntry();
- Uint32 userPtr = signal->theData[0];
- BlockReference userRef = signal->theData[1];
- if (!c_operation_pool.seize(regOperPtr))
- {
- jam();
- signal->theData[0] = userPtr;
- signal->theData[1] = ZGET_OPREC_ERROR;
- sendSignal(userRef, GSN_TUPSEIZEREF, signal, 2, JBB);
- return;
- }//if
-
- new (regOperPtr.p) Operationrec();
- regOperPtr.p->firstAttrinbufrec = RNIL;
- regOperPtr.p->lastAttrinbufrec = RNIL;
- regOperPtr.p->m_any_value = 0;
- regOperPtr.p->op_struct.op_type = ZREAD;
- regOperPtr.p->op_struct.in_active_list = false;
- set_trans_state(regOperPtr.p, TRANS_DISCONNECTED);
- regOperPtr.p->storedProcedureId = ZNIL;
- regOperPtr.p->prevActiveOp = RNIL;
- regOperPtr.p->nextActiveOp = RNIL;
- regOperPtr.p->tupVersion = ZNIL;
- regOperPtr.p->op_struct.delete_insert_flag = false;
-
- initOpConnection(regOperPtr.p);
- regOperPtr.p->userpointer = userPtr;
- signal->theData[0] = regOperPtr.p->userpointer;
- signal->theData[1] = regOperPtr.i;
- sendSignal(userRef, GSN_TUPSEIZECONF, signal, 2, JBB);
- return;
-}//Dbtup::execTUPSEIZEREQ()
-
-#define printFragment(t){ for(Uint32 i = 0; i < MAX_FRAG_PER_NODE;i++){\
- ndbout_c("table = %d fragid[%d] = %d fragrec[%d] = %d", \
- t.i, t.p->fragid[i], i, t.p->fragrec[i]); }}
-
-void Dbtup::execTUPRELEASEREQ(Signal* signal)
-{
- OperationrecPtr regOperPtr;
- jamEntry();
- regOperPtr.i = signal->theData[0];
- c_operation_pool.getPtr(regOperPtr);
- set_trans_state(regOperPtr.p, TRANS_DISCONNECTED);
- c_operation_pool.release(regOperPtr);
-
- signal->theData[0] = regOperPtr.p->userpointer;
- sendSignal(DBLQH_REF, GSN_TUPRELEASECONF, signal, 1, JBB);
- return;
-}//Dbtup::execTUPRELEASEREQ()
-
-void Dbtup::releaseFragrec(FragrecordPtr regFragPtr)
-{
- regFragPtr.p->nextfreefrag = cfirstfreefrag;
- cfirstfreefrag = regFragPtr.i;
-}//Dbtup::releaseFragrec()
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
deleted file mode 100644
index 51235a30939..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ /dev/null
@@ -1,737 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_INDEX_CPP
-#include <Dblqh.hpp>
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <AttributeDescriptor.hpp>
-#include "AttributeOffset.hpp"
-#include <AttributeHeader.hpp>
-#include <signaldata/TuxMaint.hpp>
-
-// methods used by ordered index
-
-void
-Dbtup::tuxGetTupAddr(Uint32 fragPtrI,
- Uint32 pageId,
- Uint32 pageIndex,
- Uint32& tupAddr)
-{
- jamEntry();
- PagePtr pagePtr;
- c_page_pool.getPtr(pagePtr, pageId);
- Uint32 fragPageId= pagePtr.p->frag_page_id;
- tupAddr= (fragPageId << MAX_TUPLES_BITS) | pageIndex;
-}
-
-int
-Dbtup::tuxAllocNode(Signal* signal,
- Uint32 fragPtrI,
- Uint32& pageId,
- Uint32& pageOffset,
- Uint32*& node)
-{
- jamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- terrorCode= 0;
-
- Local_key key;
- Uint32* ptr, frag_page_id;
- if ((ptr= alloc_fix_rec(fragPtr.p, tablePtr.p, &key, &frag_page_id)) == 0)
- {
- jam();
- terrorCode = ZMEM_NOMEM_ERROR; // caller sets error
- return terrorCode;
- }
- pageId= key.m_page_no;
- pageOffset= key.m_page_idx;
- Uint32 attrDescIndex= tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset= AttributeOffset::getOffset(
- tableDescriptor[attrDescIndex + 1].tabDescr);
- node= ptr + attrDataOffset;
- return 0;
-}
-
-#if 0
-void
-Dbtup::tuxFreeNode(Signal* signal,
- Uint32 fragPtrI,
- Uint32 pageId,
- Uint32 pageOffset,
- Uint32* node)
-{
- jamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i= pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, cpage);
- Uint32 attrDescIndex= tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset= AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
- ndbrequire(node == &pagePtr.p->pageWord[pageOffset] + attrDataOffset);
- freeTh(fragPtr.p, tablePtr.p, signal, pagePtr.p, pageOffset);
-}
-#endif
-
-void
-Dbtup::tuxGetNode(Uint32 fragPtrI,
- Uint32 pageId,
- Uint32 pageOffset,
- Uint32*& node)
-{
- jamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- c_page_pool.getPtr(pagePtr, pageId);
- Uint32 attrDescIndex= tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset= AttributeOffset::getOffset(
- tableDescriptor[attrDescIndex + 1].tabDescr);
- node= ((Fix_page*)pagePtr.p)->
- get_ptr(pageOffset, tablePtr.p->m_offsets[MM].m_fix_header_size) +
- attrDataOffset;
-}
-int
-Dbtup::tuxReadAttrs(Uint32 fragPtrI,
- Uint32 pageId,
- Uint32 pageIndex,
- Uint32 tupVersion,
- const Uint32* attrIds,
- Uint32 numAttrs,
- Uint32* dataOut)
-{
- jamEntry();
- // use own variables instead of globals
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- // search for tuple version if not original
-
- Operationrec tmpOp;
- KeyReqStruct req_struct;
- tmpOp.m_tuple_location.m_page_no= pageId;
- tmpOp.m_tuple_location.m_page_idx= pageIndex;
-
- setup_fixed_part(&req_struct, &tmpOp, tablePtr.p);
- Tuple_header *tuple_ptr= req_struct.m_tuple_ptr;
- if (tuple_ptr->get_tuple_version() != tupVersion)
- {
- jam();
- OperationrecPtr opPtr;
- opPtr.i= tuple_ptr->m_operation_ptr_i;
- Uint32 loopGuard= 0;
- while (opPtr.i != RNIL) {
- c_operation_pool.getPtr(opPtr);
- if (opPtr.p->tupVersion == tupVersion) {
- jam();
- if (!opPtr.p->m_copy_tuple_location.isNull()) {
- req_struct.m_tuple_ptr= (Tuple_header*)
- c_undo_buffer.get_ptr(&opPtr.p->m_copy_tuple_location);
- }
- break;
- }
- jam();
- opPtr.i= opPtr.p->prevActiveOp;
- ndbrequire(++loopGuard < (1 << ZTUP_VERSION_BITS));
- }
- }
- // read key attributes from found tuple version
- // save globals
- TablerecPtr tabptr_old= tabptr;
- FragrecordPtr fragptr_old= fragptr;
- OperationrecPtr operPtr_old= operPtr;
- // new globals
- tabptr= tablePtr;
- fragptr= fragPtr;
- operPtr.i= RNIL;
- operPtr.p= NULL;
- prepare_read(&req_struct, tablePtr.p, false);
-
- // do it
- int ret = readAttributes(&req_struct,
- attrIds,
- numAttrs,
- dataOut,
- ZNIL,
- true);
-
- // restore globals
- tabptr= tabptr_old;
- fragptr= fragptr_old;
- operPtr= operPtr_old;
- // done
- if (ret == -1) {
- ret = terrorCode ? (-(int)terrorCode) : -1;
- }
- return ret;
-}
-int
-Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag)
-{
- jamEntry();
- // use own variables instead of globals
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- Operationrec tmpOp;
- tmpOp.m_tuple_location.m_page_no= pageId;
- tmpOp.m_tuple_location.m_page_idx= pageIndex;
-
- KeyReqStruct req_struct;
-
- PagePtr page_ptr;
- Uint32* ptr= get_ptr(&page_ptr, &tmpOp.m_tuple_location, tablePtr.p);
- req_struct.m_page_ptr = page_ptr;
- req_struct.m_tuple_ptr = (Tuple_header*)ptr;
-
- int ret = 0;
- if (! (req_struct.m_tuple_ptr->m_header_bits & Tuple_header::FREE))
- {
- req_struct.check_offset[MM]= tablePtr.p->get_check_offset(MM);
- req_struct.check_offset[DD]= tablePtr.p->get_check_offset(DD);
-
- Uint32 num_attr= tablePtr.p->m_no_of_attributes;
- Uint32 descr_start= tablePtr.p->tabDescriptor;
- TableDescriptor *tab_descr= &tableDescriptor[descr_start];
- ndbrequire(descr_start + (num_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
- req_struct.attr_descr= tab_descr;
-
- if(req_struct.m_tuple_ptr->m_header_bits & Tuple_header::ALLOC)
- {
- Uint32 opPtrI= req_struct.m_tuple_ptr->m_operation_ptr_i;
- Operationrec* opPtrP= c_operation_pool.getPtr(opPtrI);
- ndbassert(!opPtrP->m_copy_tuple_location.isNull());
- req_struct.m_tuple_ptr= (Tuple_header*)
- c_undo_buffer.get_ptr(&opPtrP->m_copy_tuple_location);
- }
- prepare_read(&req_struct, tablePtr.p, false);
-
- const Uint32* attrIds= &tableDescriptor[tablePtr.p->readKeyArray].tabDescr;
- const Uint32 numAttrs= tablePtr.p->noOfKeyAttr;
- // read pk attributes from original tuple
-
- // save globals
- TablerecPtr tabptr_old= tabptr;
- FragrecordPtr fragptr_old= fragptr;
- OperationrecPtr operPtr_old= operPtr;
-
- // new globals
- tabptr= tablePtr;
- fragptr= fragPtr;
- operPtr.i= RNIL;
- operPtr.p= NULL;
-
- // do it
- ret = readAttributes(&req_struct,
- attrIds,
- numAttrs,
- dataOut,
- ZNIL,
- xfrmFlag);
- // restore globals
- tabptr= tabptr_old;
- fragptr= fragptr_old;
- operPtr= operPtr_old;
- // done
- if (ret != -1) {
- // remove headers
- Uint32 n= 0;
- Uint32 i= 0;
- while (n < numAttrs) {
- const AttributeHeader ah(dataOut[i]);
- Uint32 size= ah.getDataSize();
- ndbrequire(size != 0);
- for (Uint32 j= 0; j < size; j++) {
- dataOut[i + j - n]= dataOut[i + j + 1];
- }
- n+= 1;
- i+= 1 + size;
- }
- ndbrequire((int)i == ret);
- ret -= numAttrs;
- } else {
- ret= terrorCode ? (-(int)terrorCode) : -1;
- }
- }
- if (tablePtr.p->m_bits & Tablerec::TR_RowGCI)
- {
- dataOut[ret] = *req_struct.m_tuple_ptr->get_mm_gci(tablePtr.p);
- }
- else
- {
- dataOut[ret] = 0;
- }
- return ret;
-}
-
-int
-Dbtup::accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag)
-{
- jamEntry();
- // 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
-
- Uint32 pageId = getRealpid(fragPtr.p, fragPageId);
- // use TUX routine - optimize later
- int ret = tuxReadPk(fragPtr.i, pageId, pageIndex, dataOut, xfrmFlag);
- return ret;
-}
-
-/*
- * TUX index contains all tuple versions. A scan in TUX has scanned
- * one of them and asks if it can be returned as scan result. This
- * depends on trans id, dirty read flag, and savepoint within trans.
- *
- * Previously this faked a ZREAD operation and used getPage().
- * In TUP getPage() is run after ACC locking, but TUX comes here
- * before ACC access. Instead of modifying getPage() it is more
- * clear to do the full check here.
- */
-bool
-Dbtup::tuxQueryTh(Uint32 fragPtrI,
- Uint32 pageId,
- Uint32 pageIndex,
- Uint32 tupVersion,
- Uint32 transId1,
- Uint32 transId2,
- bool dirty,
- Uint32 savepointId)
-{
- jamEntry();
- FragrecordPtr fragPtr;
- fragPtr.i= fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- TablerecPtr tablePtr;
- tablePtr.i= fragPtr.p->fragTableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- c_page_pool.getPtr(pagePtr);
-
- KeyReqStruct req_struct;
-
- {
- Operationrec tmpOp;
- tmpOp.m_tuple_location.m_page_no = pageId;
- tmpOp.m_tuple_location.m_page_idx = pageIndex;
- setup_fixed_part(&req_struct, &tmpOp, tablePtr.p);
- }
-
- Tuple_header* tuple_ptr = req_struct.m_tuple_ptr;
-
- OperationrecPtr currOpPtr;
- currOpPtr.i = tuple_ptr->m_operation_ptr_i;
- if (currOpPtr.i == RNIL) {
- jam();
- // tuple has no operation, any scan can see it
- return true;
- }
- c_operation_pool.getPtr(currOpPtr);
-
- const bool sameTrans =
- c_lqh->is_same_trans(currOpPtr.p->userpointer, transId1, transId2);
-
- bool res = false;
- OperationrecPtr loopOpPtr = currOpPtr;
-
- if (!sameTrans) {
- jam();
- if (!dirty) {
- jam();
- if (currOpPtr.p->nextActiveOp == RNIL) {
- jam();
- // last op - TUX makes ACC lock request in same timeslice
- res = true;
- }
- }
- else {
- // loop to first op (returns false)
- find_savepoint(loopOpPtr, 0);
- const Uint32 op_type = loopOpPtr.p->op_struct.op_type;
-
- if (op_type != ZINSERT) {
- jam();
- // read committed version
- const Uint32 origVersion = tuple_ptr->get_tuple_version();
- if (origVersion == tupVersion) {
- jam();
- res = true;
- }
- }
- }
- }
- else {
- jam();
- // for own trans, ignore dirty flag
-
- if (find_savepoint(loopOpPtr, savepointId)) {
- jam();
- const Uint32 op_type = loopOpPtr.p->op_struct.op_type;
-
- if (op_type != ZDELETE) {
- jam();
- // check if this op has produced the scanned version
- Uint32 loopVersion = loopOpPtr.p->tupVersion;
- if (loopVersion == tupVersion) {
- jam();
- res = true;
- }
- }
- }
- }
-
- return res;
-}
-
-// ordered index build
-
-//#define TIME_MEASUREMENT
-#ifdef TIME_MEASUREMENT
- static Uint32 time_events;
- NDB_TICKS tot_time_passed;
- Uint32 number_events;
-#endif
-void
-Dbtup::execBUILDINDXREQ(Signal* signal)
-{
- jamEntry();
-#ifdef TIME_MEASUREMENT
- time_events= 0;
- tot_time_passed= 0;
- number_events= 1;
-#endif
- // get new operation
- BuildIndexPtr buildPtr;
- if (! c_buildIndexList.seize(buildPtr)) {
- jam();
- BuildIndexRec buildRec;
- memcpy(buildRec.m_request, signal->theData, sizeof(buildRec.m_request));
- buildRec.m_errorCode= BuildIndxRef::Busy;
- buildIndexReply(signal, &buildRec);
- return;
- }
- memcpy(buildPtr.p->m_request,
- signal->theData,
- sizeof(buildPtr.p->m_request));
- // check
- buildPtr.p->m_errorCode= BuildIndxRef::NoError;
- do {
- const BuildIndxReq* buildReq= (const BuildIndxReq*)buildPtr.p->m_request;
- if (buildReq->getTableId() >= cnoOfTablerec) {
- jam();
- buildPtr.p->m_errorCode= BuildIndxRef::InvalidPrimaryTable;
- break;
- }
- TablerecPtr tablePtr;
- tablePtr.i= buildReq->getTableId();
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- if (tablePtr.p->tableStatus != DEFINED) {
- jam();
- buildPtr.p->m_errorCode= BuildIndxRef::InvalidPrimaryTable;
- break;
- }
- // memory page format
- buildPtr.p->m_build_vs =
- tablePtr.p->m_attributes[MM].m_no_of_varsize > 0;
- if (DictTabInfo::isOrderedIndex(buildReq->getIndexType())) {
- jam();
- const DLList<TupTriggerData>& triggerList =
- tablePtr.p->tuxCustomTriggers;
-
- TriggerPtr triggerPtr;
- triggerList.first(triggerPtr);
- while (triggerPtr.i != RNIL) {
- if (triggerPtr.p->indexId == buildReq->getIndexId()) {
- jam();
- break;
- }
- triggerList.next(triggerPtr);
- }
- if (triggerPtr.i == RNIL) {
- jam();
- // trigger was not created
- buildPtr.p->m_errorCode = BuildIndxRef::InternalError;
- break;
- }
- buildPtr.p->m_indexId = buildReq->getIndexId();
- buildPtr.p->m_buildRef = DBTUX;
- } else if(buildReq->getIndexId() == RNIL) {
- jam();
- // REBUILD of acc
- buildPtr.p->m_indexId = RNIL;
- buildPtr.p->m_buildRef = DBACC;
- } else {
- jam();
- buildPtr.p->m_errorCode = BuildIndxRef::InvalidIndexType;
- break;
- }
-
- // set to first tuple position
- const Uint32 firstTupleNo = 0;
- buildPtr.p->m_fragNo= 0;
- buildPtr.p->m_pageId= 0;
- buildPtr.p->m_tupleNo= firstTupleNo;
- // start build
- buildIndex(signal, buildPtr.i);
- return;
- } while (0);
- // check failed
- buildIndexReply(signal, buildPtr.p);
- c_buildIndexList.release(buildPtr);
-}
-
-void
-Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
-{
- // get build record
- BuildIndexPtr buildPtr;
- buildPtr.i= buildPtrI;
- c_buildIndexList.getPtr(buildPtr);
- const BuildIndxReq* buildReq= (const BuildIndxReq*)buildPtr.p->m_request;
- // get table
- TablerecPtr tablePtr;
- tablePtr.i= buildReq->getTableId();
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- const Uint32 firstTupleNo = 0;
- const Uint32 tupheadsize = tablePtr.p->m_offsets[MM].m_fix_header_size;
-
-#ifdef TIME_MEASUREMENT
- MicroSecondTimer start;
- MicroSecondTimer stop;
- NDB_TICKS time_passed;
-#endif
- do {
- // get fragment
- FragrecordPtr fragPtr;
- if (buildPtr.p->m_fragNo == MAX_FRAG_PER_NODE) {
- jam();
- // build ready
- buildIndexReply(signal, buildPtr.p);
- c_buildIndexList.release(buildPtr);
- return;
- }
- ndbrequire(buildPtr.p->m_fragNo < MAX_FRAG_PER_NODE);
- fragPtr.i= tablePtr.p->fragrec[buildPtr.p->m_fragNo];
- if (fragPtr.i == RNIL) {
- jam();
- buildPtr.p->m_fragNo++;
- buildPtr.p->m_pageId= 0;
- buildPtr.p->m_tupleNo= firstTupleNo;
- break;
- }
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- // get page
- PagePtr pagePtr;
- if (buildPtr.p->m_pageId >= fragPtr.p->noOfPages) {
- jam();
- buildPtr.p->m_fragNo++;
- buildPtr.p->m_pageId= 0;
- buildPtr.p->m_tupleNo= firstTupleNo;
- break;
- }
- Uint32 realPageId= getRealpid(fragPtr.p, buildPtr.p->m_pageId);
- c_page_pool.getPtr(pagePtr, realPageId);
- Uint32 pageState= pagePtr.p->page_state;
- // skip empty page
- if (pageState == ZEMPTY_MM) {
- jam();
- buildPtr.p->m_pageId++;
- buildPtr.p->m_tupleNo= firstTupleNo;
- break;
- }
- // get tuple
- Uint32 pageIndex = ~0;
- const Tuple_header* tuple_ptr = 0;
- pageIndex = buildPtr.p->m_tupleNo * tupheadsize;
- if (pageIndex + tupheadsize > Fix_page::DATA_WORDS) {
- jam();
- buildPtr.p->m_pageId++;
- buildPtr.p->m_tupleNo= firstTupleNo;
- break;
- }
- tuple_ptr = (Tuple_header*)&pagePtr.p->m_data[pageIndex];
- // skip over free tuple
- if (tuple_ptr->m_header_bits & Tuple_header::FREE) {
- jam();
- buildPtr.p->m_tupleNo++;
- break;
- }
- Uint32 tupVersion= tuple_ptr->get_tuple_version();
- OperationrecPtr pageOperPtr;
- pageOperPtr.i= tuple_ptr->m_operation_ptr_i;
-#ifdef TIME_MEASUREMENT
- NdbTick_getMicroTimer(&start);
-#endif
- // add to index
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- req->errorCode = RNIL;
- req->tableId = tablePtr.i;
- req->indexId = buildPtr.p->m_indexId;
- req->fragId = tablePtr.p->fragid[buildPtr.p->m_fragNo];
- req->pageId = realPageId;
- req->tupVersion = tupVersion;
- req->opInfo = TuxMaintReq::OpAdd;
- req->tupFragPtrI = fragPtr.i;
- req->fragPageId = buildPtr.p->m_pageId;
- req->pageIndex = pageIndex;
-
- if (pageOperPtr.i == RNIL)
- {
- EXECUTE_DIRECT(buildPtr.p->m_buildRef, GSN_TUX_MAINT_REQ,
- signal, TuxMaintReq::SignalLength+2);
- }
- else
- {
- /*
- If there is an ongoing operation on the tuple then it is either a
- copy tuple or an original tuple with an ongoing transaction. In
- both cases realPageId and pageOffset refer to the original tuple.
- The tuple address stored in TUX will always be the original tuple
- but with the tuple version of the tuple we found.
-
- This is necessary to avoid having to update TUX at abort of
- update. If an update aborts then the copy tuple is copied to
- the original tuple. The build will however have found that
- tuple as a copy tuple. The original tuple is stable and is thus
- preferrable to store in TUX.
- */
- jam();
-
- /**
- * Since copy tuples now can't be found on real pages.
- * we will here build all copies of the tuple
- *
- * Note only "real" tupVersion's should be added
- * i.e delete's shouldnt be added
- * (unless it's the first op, when "original" should be added)
- */
- do
- {
- c_operation_pool.getPtr(pageOperPtr);
- if(pageOperPtr.p->op_struct.op_type != ZDELETE ||
- pageOperPtr.p->is_first_operation())
- {
- req->errorCode = RNIL;
- req->tupVersion= pageOperPtr.p->tupVersion;
- EXECUTE_DIRECT(buildPtr.p->m_buildRef, GSN_TUX_MAINT_REQ,
- signal, TuxMaintReq::SignalLength+2);
- }
- else
- {
- req->errorCode= 0;
- }
- pageOperPtr.i= pageOperPtr.p->prevActiveOp;
- } while(req->errorCode == 0 && pageOperPtr.i != RNIL);
- }
-
- jamEntry();
- if (req->errorCode != 0) {
- switch (req->errorCode) {
- case TuxMaintReq::NoMemError:
- jam();
- buildPtr.p->m_errorCode= BuildIndxRef::AllocationFailure;
- break;
- default:
- ndbrequire(false);
- break;
- }
- buildIndexReply(signal, buildPtr.p);
- c_buildIndexList.release(buildPtr);
- return;
- }
-#ifdef TIME_MEASUREMENT
- NdbTick_getMicroTimer(&stop);
- time_passed= NdbTick_getMicrosPassed(start, stop);
- if (time_passed < 1000) {
- time_events++;
- tot_time_passed += time_passed;
- if (time_events == number_events) {
- NDB_TICKS mean_time_passed= tot_time_passed /
- (NDB_TICKS)number_events;
- ndbout << "Number of events= " << number_events;
- ndbout << " Mean time passed= " << mean_time_passed << endl;
- number_events <<= 1;
- tot_time_passed= (NDB_TICKS)0;
- time_events= 0;
- }
- }
-#endif
- // next tuple
- buildPtr.p->m_tupleNo++;
- break;
- } while (0);
- signal->theData[0]= ZBUILD_INDEX;
- signal->theData[1]= buildPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Dbtup::buildIndexReply(Signal* signal, const BuildIndexRec* buildPtrP)
-{
- const BuildIndxReq* const buildReq=
- (const BuildIndxReq*)buildPtrP->m_request;
- // conf is subset of ref
- BuildIndxRef* rep= (BuildIndxRef*)signal->getDataPtr();
- rep->setUserRef(buildReq->getUserRef());
- rep->setConnectionPtr(buildReq->getConnectionPtr());
- rep->setRequestType(buildReq->getRequestType());
- rep->setTableId(buildReq->getTableId());
- rep->setIndexType(buildReq->getIndexType());
- rep->setIndexId(buildReq->getIndexId());
- // conf
- if (buildPtrP->m_errorCode == BuildIndxRef::NoError) {
- jam();
- sendSignal(rep->getUserRef(), GSN_BUILDINDXCONF,
- signal, BuildIndxConf::SignalLength, JBB);
- return;
- }
- // ref
- rep->setErrorCode(buildPtrP->m_errorCode);
- sendSignal(rep->getUserRef(), GSN_BUILDINDXREF,
- signal, BuildIndxRef::SignalLength, JBB);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
deleted file mode 100644
index dffc966f875..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
+++ /dev/null
@@ -1,1486 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_META_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <signaldata/TupFrag.hpp>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRemoveReq.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/AlterTab.hpp>
-#include <signaldata/CreateFilegroupImpl.hpp>
-#include <AttributeDescriptor.hpp>
-#include "AttributeOffset.hpp"
-#include <my_sys.h>
-
-void Dbtup::execTUPFRAGREQ(Signal* signal)
-{
- jamEntry();
-
- TupFragReq* tupFragReq = (TupFragReq*)signal->getDataPtr();
- if (tupFragReq->userPtr == (Uint32)-1) {
- jam();
- abortAddFragOp(signal);
- return;
- }
-
- FragoperrecPtr fragOperPtr;
- FragrecordPtr regFragPtr;
- TablerecPtr regTabPtr;
-
- 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 schemaVersion = tupFragReq->schemaVersion;*/
- Uint32 noOfKeyAttr = tupFragReq->noOfKeyAttr;
- Uint32 noOfCharsets = tupFragReq->noOfCharsets;
-
- Uint32 checksumIndicator = tupFragReq->checksumIndicator;
- Uint32 gcpIndicator = tupFragReq->globalCheckpointIdIndicator;
- Uint32 tablespace_id= tupFragReq->tablespaceid;
- Uint32 forceVarPart = tupFragReq->forceVarPartFlag;
-
- 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) {
- jam();
- tupFragReq->userPtr = userptr;
- tupFragReq->userRef = 800;
- sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
- return;
- }
-#endif
-
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
- if (cfirstfreeFragopr == RNIL) {
- jam();
- tupFragReq->userPtr = userptr;
- tupFragReq->userRef = ZNOFREE_FRAGOP_ERROR;
- sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
- return;
- }
- seizeFragoperrec(fragOperPtr);
-
- fragOperPtr.p->nextFragoprec = RNIL;
- fragOperPtr.p->lqhBlockrefFrag = userblockref;
- fragOperPtr.p->lqhPtrFrag = userptr;
- fragOperPtr.p->fragidFrag = fragId;
- fragOperPtr.p->tableidFrag = regTabPtr.i;
- fragOperPtr.p->attributeCount = noOfAttributes;
-
- memset(fragOperPtr.p->m_null_bits, 0, sizeof(fragOperPtr.p->m_null_bits));
- memset(fragOperPtr.p->m_fix_attributes_size, 0,
- sizeof(fragOperPtr.p->m_fix_attributes_size));
- memset(fragOperPtr.p->m_var_attributes_size, 0,
- sizeof(fragOperPtr.p->m_var_attributes_size));
-
- fragOperPtr.p->charsetIndex = 0;
- fragOperPtr.p->minRows = minRows;
- fragOperPtr.p->maxRows = maxRows;
-
- ndbrequire(reqinfo == ZADDFRAG);
-
- getFragmentrec(regFragPtr, fragId, regTabPtr.p);
- if (regFragPtr.i != RNIL) {
- jam();
- terrorCode= ZEXIST_FRAG_ERROR;
- fragrefuse1Lab(signal, fragOperPtr);
- return;
- }
- if (cfirstfreefrag != RNIL) {
- jam();
- seizeFragrecord(regFragPtr);
- } else {
- jam();
- terrorCode= ZFULL_FRAGRECORD_ERROR;
- fragrefuse1Lab(signal, fragOperPtr);
- return;
- }
- initFragRange(regFragPtr.p);
- if (!addfragtotab(regTabPtr.p, fragId, regFragPtr.i)) {
- jam();
- terrorCode= ZNO_FREE_TAB_ENTRY_ERROR;
- fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
- return;
- }
- if (cfirstfreerange == RNIL) {
- jam();
- terrorCode= ZNO_FREE_PAGE_RANGE_ERROR;
- fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
- return;
- }
-
- regFragPtr.p->fragTableId= regTabPtr.i;
- regFragPtr.p->fragmentId= fragId;
- regFragPtr.p->m_tablespace_id= tablespace_id;
- regFragPtr.p->m_undo_complete= false;
- regFragPtr.p->m_lcp_scan_op = RNIL;
- regFragPtr.p->m_lcp_keep_list = RNIL;
- regFragPtr.p->m_var_page_chunks = RNIL;
- regFragPtr.p->m_restore_lcp_id = RNIL;
-
- if (ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId ||
- ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) {
- jam();
- terrorCode = 1;
- fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }
-
- if (regTabPtr.p->tableStatus == NOT_DEFINED) {
- jam();
-//-----------------------------------------------------------------------------
-// We are setting up references to the header of the tuple.
-// Active operation This word contains a reference to the operation active
-// on the tuple at the moment. RNIL means no one active at
-// all. Not optional.
-// Tuple version Uses only low 16 bits. Not optional.
-// Checksum The third header word is optional and contains a checksum
-// of the tuple header.
-// Null-bits A number of words to contain null bits for all
-// non-dynamic attributes. Each word contains upto 32 null
-// bits. Each time a new word is needed we allocate the
-// complete word. Zero nullable attributes means that there
-// is no word at all
-//-----------------------------------------------------------------------------
- fragOperPtr.p->definingFragment= true;
- regTabPtr.p->tableStatus= DEFINING;
- regTabPtr.p->m_bits = 0;
- regTabPtr.p->m_bits |= (checksumIndicator ? Tablerec::TR_Checksum : 0);
- regTabPtr.p->m_bits |= (gcpIndicator ? Tablerec::TR_RowGCI : 0);
- regTabPtr.p->m_bits |= (forceVarPart ? Tablerec::TR_ForceVarPart : 0);
-
- regTabPtr.p->m_offsets[MM].m_disk_ref_offset= 0;
- regTabPtr.p->m_offsets[MM].m_null_words= 0;
- regTabPtr.p->m_offsets[MM].m_fix_header_size= 0;
- regTabPtr.p->m_offsets[MM].m_max_var_offset= 0;
-
- regTabPtr.p->m_offsets[DD].m_disk_ref_offset= 0;
- regTabPtr.p->m_offsets[DD].m_null_words= 0;
- regTabPtr.p->m_offsets[DD].m_fix_header_size= 0;
- regTabPtr.p->m_offsets[DD].m_max_var_offset= 0;
-
- regTabPtr.p->m_attributes[MM].m_no_of_fixsize= 0;
- regTabPtr.p->m_attributes[MM].m_no_of_varsize= 0;
- regTabPtr.p->m_attributes[DD].m_no_of_fixsize= 0;
- regTabPtr.p->m_attributes[DD].m_no_of_varsize= 0;
-
- regTabPtr.p->noOfKeyAttr= noOfKeyAttr;
- regTabPtr.p->noOfCharsets= noOfCharsets;
- regTabPtr.p->m_no_of_attributes= noOfAttributes;
-
- regTabPtr.p->notNullAttributeMask.clear();
- regTabPtr.p->blobAttributeMask.clear();
-
- Uint32 offset[10];
- Uint32 tableDescriptorRef= allocTabDescr(regTabPtr.p, offset);
- if (tableDescriptorRef == RNIL) {
- jam();
- fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
- return;
- }
- setUpDescriptorReferences(tableDescriptorRef, regTabPtr.p, offset);
- } else {
- jam();
- fragOperPtr.p->definingFragment= false;
- }
- signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
- signal->theData[1]= fragOperPtr.i;
- signal->theData[2]= regFragPtr.i;
- signal->theData[3]= fragId;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUPFRAGCONF, signal, 4, JBB);
- return;
-}
-
-bool Dbtup::addfragtotab(Tablerec* const regTabPtr,
- Uint32 fragId,
- Uint32 fragIndex)
-{
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (regTabPtr->fragid[i] == RNIL) {
- jam();
- regTabPtr->fragid[i]= fragId;
- regTabPtr->fragrec[i]= fragIndex;
- return true;
- }
- }
- return false;
-}
-
-void Dbtup::getFragmentrec(FragrecordPtr& regFragPtr,
- Uint32 fragId,
- Tablerec* const regTabPtr)
-{
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (regTabPtr->fragid[i] == fragId) {
- jam();
- regFragPtr.i= regTabPtr->fragrec[i];
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- return;
- }
- }
- regFragPtr.i= RNIL;
- ptrNull(regFragPtr);
-}
-
-void Dbtup::seizeFragrecord(FragrecordPtr& regFragPtr)
-{
- regFragPtr.i= cfirstfreefrag;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- cfirstfreefrag= regFragPtr.p->nextfreefrag;
- regFragPtr.p->nextfreefrag= RNIL;
-}
-
-void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr)
-{
- fragOperPtr.i= cfirstfreeFragopr;
- ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
- cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
- fragOperPtr.p->nextFragoprec = RNIL;
- fragOperPtr.p->inUse = true;
-}//Dbtup::seizeFragoperrec()
-
-/* **************************************************************** */
-/* ************** TUP_ADD_ATTRREQ ****************** */
-/* **************************************************************** */
-void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
-{
- FragrecordPtr regFragPtr;
- FragoperrecPtr fragOperPtr;
- TablerecPtr regTabPtr;
-
- jamEntry();
- fragOperPtr.i= signal->theData[0];
- ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
- Uint32 attrId = signal->theData[2];
- Uint32 attrDescriptor = signal->theData[3];
- Uint32 extType = AttributeDescriptor::getType(attrDescriptor);
- // DICT sends charset number in upper half
- Uint32 csNumber = (signal->theData[4] >> 16);
-
- regTabPtr.i= fragOperPtr.p->tableidFrag;
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
- Uint32 fragId= fragOperPtr.p->fragidFrag;
-
- getFragmentrec(regFragPtr, fragId, regTabPtr.p);
- ndbrequire(regFragPtr.i != RNIL);
-
- ndbrequire(fragOperPtr.p->attributeCount > 0);
- fragOperPtr.p->attributeCount--;
- const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
-
- if (regTabPtr.p->tableStatus != DEFINING)
- {
- ndbrequire(regTabPtr.p->tableStatus == DEFINED);
- signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- signal->theData[1] = lastAttr;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF,
- signal, 2, JBB);
-
- if(lastAttr)
- {
- jam();
- /**
- * Init Disk_alloc_info
- */
- CreateFilegroupImplReq rep;
- if(regTabPtr.p->m_no_of_disk_attributes)
- {
- Tablespace_client tsman(0, c_tsman, 0, 0,
- regFragPtr.p->m_tablespace_id);
- ndbrequire(tsman.get_tablespace_info(&rep) == 0);
- regFragPtr.p->m_logfile_group_id= rep.tablespace.logfile_group_id;
- }
- else
- {
- jam();
- regFragPtr.p->m_logfile_group_id = RNIL;
- }
- new (&regFragPtr.p->m_disk_alloc_info)
- Disk_alloc_info(regTabPtr.p, rep.tablespace.extent_size);
- releaseFragoperrec(fragOperPtr);
- }
- return;
- }
-
- Uint32 firstTabDesIndex= regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
- setTabDescrWord(firstTabDesIndex, attrDescriptor);
- Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
-
- Uint32 attrDes2= 0;
- if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
- jam();
- Uint32 pos= 0, null_pos;
- Uint32 bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
- Uint32 words= (bytes + 3) / 4;
- Uint32 ind= AttributeDescriptor::getDiskBased(attrDescriptor);
- ndbrequire(ind <= 1);
- null_pos= fragOperPtr.p->m_null_bits[ind];
-
- if (AttributeDescriptor::getNullable(attrDescriptor))
- {
- jam();
- fragOperPtr.p->m_null_bits[ind]++;
- }
- else
- {
- regTabPtr.p->notNullAttributeMask.set(attrId);
- }
-
- if (extType == NDB_TYPE_BLOB || extType == NDB_TYPE_TEXT) {
- regTabPtr.p->blobAttributeMask.set(attrId);
- }
-
- switch (AttributeDescriptor::getArrayType(attrDescriptor)) {
- case NDB_ARRAYTYPE_FIXED:
- {
- jam();
- regTabPtr.p->m_attributes[ind].m_no_of_fixsize++;
- if(attrLen != 0)
- {
- jam();
- pos= fragOperPtr.p->m_fix_attributes_size[ind];
- fragOperPtr.p->m_fix_attributes_size[ind] += words;
- }
- else
- {
- jam();
- Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
- fragOperPtr.p->m_null_bits[ind] += bitCount;
- }
- break;
- }
- default:
- {
- jam();
- fragOperPtr.p->m_var_attributes_size[ind] += bytes;
- pos= regTabPtr.p->m_attributes[ind].m_no_of_varsize++;
- break;
- }
- }//switch
-
- AttributeOffset::setOffset(attrDes2, pos);
- AttributeOffset::setNullFlagPos(attrDes2, null_pos);
- } else {
- ndbrequire(false);
- }
- if (csNumber != 0) {
- CHARSET_INFO* cs = all_charsets[csNumber];
- ndbrequire(cs != NULL);
- Uint32 i = 0;
- while (i < fragOperPtr.p->charsetIndex) {
- jam();
- if (regTabPtr.p->charsetArray[i] == cs)
- break;
- i++;
- }
- if (i == fragOperPtr.p->charsetIndex) {
- jam();
- fragOperPtr.p->charsetIndex++;
- }
- ndbrequire(i < regTabPtr.p->noOfCharsets);
- regTabPtr.p->charsetArray[i]= cs;
- AttributeOffset::setCharsetPos(attrDes2, i);
- }
- setTabDescrWord(firstTabDesIndex + 1, attrDes2);
-
- if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId && attrId == 0||
- ERROR_INSERTED(4010) && regTabPtr.p->fragid[0] == fragId && lastAttr ||
- ERROR_INSERTED(4011) && regTabPtr.p->fragid[1] == fragId && attrId == 0||
- ERROR_INSERTED(4012) && regTabPtr.p->fragid[1] == fragId && lastAttr) {
- jam();
- terrorCode = 1;
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- CLEAR_ERROR_INSERT_VALUE;
- return;
- }
-
-/* **************************************************************** */
-/* ************** TUP_ADD_ATTCONF ****************** */
-/* **************************************************************** */
- if (! lastAttr) {
- jam();
- signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- signal->theData[1] = lastAttr;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF,
- signal, 2, JBB);
- return;
- }
-
- ndbrequire(regTabPtr.p->tableStatus == DEFINING);
- regTabPtr.p->tableStatus= DEFINED;
- regFragPtr.p->fragStatus= ACTIVE;
-
-#define BTW(x) ((x+31) >> 5)
- regTabPtr.p->m_offsets[MM].m_null_words= BTW(fragOperPtr.p->m_null_bits[MM]);
- regTabPtr.p->m_offsets[DD].m_null_words= BTW(fragOperPtr.p->m_null_bits[DD]);
-
- /**
- * Fix offsets
- */
- Uint32 pos[2] = { 0, 0 };
- if (regTabPtr.p->m_bits & Tablerec::TR_Checksum)
- {
- pos[0]= 1;
- }
-
- if (regTabPtr.p->m_bits & Tablerec::TR_RowGCI)
- {
- pos[MM]++;
- pos[DD]++;
- }
-
- regTabPtr.p->m_no_of_disk_attributes=
- regTabPtr.p->m_attributes[DD].m_no_of_fixsize +
- regTabPtr.p->m_attributes[DD].m_no_of_varsize;
-
- if(regTabPtr.p->m_no_of_disk_attributes > 0)
- {
- regTabPtr.p->m_offsets[MM].m_disk_ref_offset= pos[MM];
- pos[MM] += Disk_part_ref::SZ32; // 8 bytes
- }
- else
- {
- /**
- * var part ref is stored at m_disk_ref_offset + Disk_part_ref::SZ32
- */
- regTabPtr.p->m_offsets[MM].m_disk_ref_offset= pos[MM]-Disk_part_ref::SZ32;
- }
-
- if (regTabPtr.p->m_attributes[MM].m_no_of_varsize)
- {
- pos[MM] += Var_part_ref::SZ32;
- regTabPtr.p->m_bits &= ~(Uint32)Tablerec::TR_ForceVarPart;
- }
- else if (regTabPtr.p->m_bits & Tablerec::TR_ForceVarPart)
- {
- pos[MM] += Var_part_ref::SZ32;
- }
-
- regTabPtr.p->m_offsets[MM].m_null_offset= pos[MM];
- regTabPtr.p->m_offsets[DD].m_null_offset= pos[DD];
-
- pos[MM]+= regTabPtr.p->m_offsets[MM].m_null_words;
- pos[DD]+= regTabPtr.p->m_offsets[DD].m_null_words;
-
- Uint32 *tabDesc = (Uint32*)(tableDescriptor+regTabPtr.p->tabDescriptor);
- for(Uint32 i= 0; i<regTabPtr.p->m_no_of_attributes; i++)
- {
- Uint32 ind= AttributeDescriptor::getDiskBased(* tabDesc);
- Uint32 arr= AttributeDescriptor::getArrayType(* tabDesc++);
-
- if(arr == NDB_ARRAYTYPE_FIXED)
- {
- Uint32 desc= * tabDesc;
- Uint32 off= AttributeOffset::getOffset(desc) + pos[ind];
- AttributeOffset::setOffset(desc, off);
- * tabDesc= desc;
- }
- tabDesc++;
- }
-
- regTabPtr.p->m_offsets[MM].m_fix_header_size=
- Tuple_header::HeaderSize +
- fragOperPtr.p->m_fix_attributes_size[MM] +
- pos[MM];
-
- regTabPtr.p->m_offsets[DD].m_fix_header_size=
- fragOperPtr.p->m_fix_attributes_size[DD] +
- pos[DD];
-
- if(regTabPtr.p->m_attributes[DD].m_no_of_varsize == 0 &&
- regTabPtr.p->m_attributes[DD].m_no_of_fixsize > 0)
- regTabPtr.p->m_offsets[DD].m_fix_header_size += Tuple_header::HeaderSize;
-
- regTabPtr.p->m_offsets[MM].m_max_var_offset=
- fragOperPtr.p->m_var_attributes_size[MM];
-
- regTabPtr.p->m_offsets[DD].m_max_var_offset=
- fragOperPtr.p->m_var_attributes_size[DD];
-
- regTabPtr.p->total_rec_size=
- pos[MM] + fragOperPtr.p->m_fix_attributes_size[MM] +
- pos[DD] + fragOperPtr.p->m_fix_attributes_size[DD] +
- ((fragOperPtr.p->m_var_attributes_size[MM] + 3) >> 2) +
- ((fragOperPtr.p->m_var_attributes_size[DD] + 3) >> 2) +
- (regTabPtr.p->m_attributes[MM].m_no_of_varsize ?
- (regTabPtr.p->m_attributes[MM].m_no_of_varsize + 2) >> 1 : 0) +
- (regTabPtr.p->m_attributes[DD].m_no_of_varsize ?
- (regTabPtr.p->m_attributes[DD].m_no_of_varsize + 2) >> 1 : 0) +
- Tuple_header::HeaderSize +
- (regTabPtr.p->m_no_of_disk_attributes ? Tuple_header::HeaderSize : 0);
-
- setUpQueryRoutines(regTabPtr.p);
- setUpKeyArray(regTabPtr.p);
-
-#if 0
- ndbout << *regTabPtr.p << endl;
- Uint32 idx= regTabPtr.p->tabDescriptor;
- for(Uint32 i = 0; i<regTabPtr.p->m_no_of_attributes; i++)
- {
- ndbout << i << ": " << endl;
- ndbout << *(AttributeDescriptor*)(tableDescriptor+idx) << endl;
- ndbout << *(AttributeOffset*)(tableDescriptor+idx+1) << endl;
- idx += 2;
- }
-#endif
-
- {
- Uint32 fix_tupheader = regTabPtr.p->m_offsets[MM].m_fix_header_size;
- ndbassert(fix_tupheader > 0);
- Uint32 noRowsPerPage = ZWORDS_ON_PAGE / fix_tupheader;
- 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) {
- jam();
- terrorCode = ZNO_PAGES_ALLOCATED_ERROR;
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- return;
- }//if
- }
-
- CreateFilegroupImplReq rep;
- if(regTabPtr.p->m_no_of_disk_attributes)
- {
- jam();
- Tablespace_client tsman(0, c_tsman, 0, 0,
- regFragPtr.p->m_tablespace_id);
- ndbrequire(tsman.get_tablespace_info(&rep) == 0);
- regFragPtr.p->m_logfile_group_id= rep.tablespace.logfile_group_id;
- }
- else
- {
- jam();
- regFragPtr.p->m_logfile_group_id = RNIL;
- }
-
- new (&regFragPtr.p->m_disk_alloc_info)
- Disk_alloc_info(regTabPtr.p, rep.tablespace.extent_size);
-
- if (regTabPtr.p->m_no_of_disk_attributes)
- {
- jam();
- if(!(getNodeState().startLevel == NodeState::SL_STARTING &&
- getNodeState().starting.startPhase <= 4))
- {
- Callback cb;
- jam();
-
- cb.m_callbackData= fragOperPtr.i;
- cb.m_callbackFunction =
- safe_cast(&Dbtup::undo_createtable_callback);
- Uint32 sz= sizeof(Disk_undo::Create) >> 2;
-
- Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id);
- if((terrorCode =
- c_lgman->alloc_log_space(regFragPtr.p->m_logfile_group_id, sz)))
- {
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- return;
- }
-
- int res= lgman.get_log_buffer(signal, sz, &cb);
- switch(res){
- case 0:
- jam();
- signal->theData[0] = 1;
- return;
- case -1:
- ndbrequire("NOT YET IMPLEMENTED" == 0);
- break;
- }
- execute(signal, cb, regFragPtr.p->m_logfile_group_id);
- return;
- }
- }
-
- signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- signal->theData[1] = lastAttr;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF,
- signal, 2, JBB);
-
- releaseFragoperrec(fragOperPtr);
-
- return;
-}
-
-void
-Dbtup::undo_createtable_callback(Signal* signal, Uint32 opPtrI, Uint32 unused)
-{
- FragrecordPtr regFragPtr;
- FragoperrecPtr fragOperPtr;
- TablerecPtr regTabPtr;
-
- fragOperPtr.i= opPtrI;
- ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
-
- regTabPtr.i= fragOperPtr.p->tableidFrag;
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
- getFragmentrec(regFragPtr, fragOperPtr.p->fragidFrag, regTabPtr.p);
- ndbrequire(regFragPtr.i != RNIL);
-
- Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id);
-
- Disk_undo::Create create;
- create.m_type_length= Disk_undo::UNDO_CREATE << 16 | (sizeof(create) >> 2);
- create.m_table = regTabPtr.i;
-
- Logfile_client::Change c[1] = {{ &create, sizeof(create) >> 2 } };
-
- Uint64 lsn= lgman.add_entry(c, 1);
-
- Logfile_client::Request req;
- req.m_callback.m_callbackData= fragOperPtr.i;
- req.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::undo_createtable_logsync_callback);
-
- int ret = lgman.sync_lsn(signal, lsn, &req, 0);
- switch(ret){
- case 0:
- return;
- case -1:
- warningEvent("Failed to sync log for create of table: %u", regTabPtr.i);
- default:
- execute(signal, req.m_callback, regFragPtr.p->m_logfile_group_id);
- }
-}
-
-void
-Dbtup::undo_createtable_logsync_callback(Signal* signal, Uint32 ptrI,
- Uint32 res)
-{
- jamEntry();
- FragoperrecPtr fragOperPtr;
- fragOperPtr.i= ptrI;
- ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
-
- signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- signal->theData[1] = 1;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF,
- signal, 2, JBB);
-
- releaseFragoperrec(fragOperPtr);
-}
-
-/*
- * Descriptor has these parts:
- *
- * 0 readFunctionArray ( one for each attribute )
- * 1 updateFunctionArray ( ditto )
- * 2 charsetArray ( pointers to distinct CHARSET_INFO )
- * 3 readKeyArray ( attribute ids of keys )
- * 5 tabDescriptor ( attribute descriptors, each ZAD_SIZE )
- */
-void Dbtup::setUpDescriptorReferences(Uint32 descriptorReference,
- Tablerec* const regTabPtr,
- const Uint32* offset)
-{
- Uint32* desc= &tableDescriptor[descriptorReference].tabDescr;
- regTabPtr->readFunctionArray= (ReadFunction*)(desc + offset[0]);
- regTabPtr->updateFunctionArray= (UpdateFunction*)(desc + offset[1]);
- regTabPtr->charsetArray= (CHARSET_INFO**)(desc + offset[2]);
- regTabPtr->readKeyArray= descriptorReference + offset[3];
- regTabPtr->tabDescriptor= descriptorReference + offset[4];
- regTabPtr->m_real_order_descriptor = descriptorReference + offset[5];
-}
-
-Uint32
-Dbtup::sizeOfReadFunction()
-{
- ReadFunction* tmp= (ReadFunction*)&tableDescriptor[0];
- TableDescriptor* start= &tableDescriptor[0];
- TableDescriptor * end= (TableDescriptor*)(tmp + 1);
- return (Uint32)(end - start);
-}
-
-void Dbtup::setUpKeyArray(Tablerec* const regTabPtr)
-{
- ndbrequire((regTabPtr->readKeyArray + regTabPtr->noOfKeyAttr) <
- cnoOfTabDescrRec);
- Uint32* keyArray= &tableDescriptor[regTabPtr->readKeyArray].tabDescr;
- Uint32 countKeyAttr= 0;
- for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++) {
- jam();
- Uint32 refAttr= regTabPtr->tabDescriptor + (i * ZAD_SIZE);
- Uint32 attrDescriptor= getTabDescrWord(refAttr);
- if (AttributeDescriptor::getPrimaryKey(attrDescriptor)) {
- jam();
- AttributeHeader::init(&keyArray[countKeyAttr], i, 0);
- countKeyAttr++;
- }
- }
- ndbrequire(countKeyAttr == regTabPtr->noOfKeyAttr);
-
- /**
- * Setup real order array (16 bit per column)
- */
- const Uint32 off= regTabPtr->m_real_order_descriptor;
- const Uint32 sz= (regTabPtr->m_no_of_attributes + 1) >> 1;
- ndbrequire((off + sz) < cnoOfTabDescrRec);
-
- Uint32 cnt= 0;
- Uint16* order= (Uint16*)&tableDescriptor[off].tabDescr;
- for (Uint32 type = 0; type < 4; type++)
- {
- for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++)
- {
- jam();
- Uint32 refAttr= regTabPtr->tabDescriptor + (i * ZAD_SIZE);
- Uint32 desc = getTabDescrWord(refAttr);
- Uint32 t = 0;
-
- if (AttributeDescriptor::getArrayType(desc) != NDB_ARRAYTYPE_FIXED)
- {
- t += 1;
- }
- if (AttributeDescriptor::getDiskBased(desc))
- {
- t += 2;
- }
- ndbrequire(t < 4);
- if(t == type)
- {
- * order++ = i << ZAD_LOG_SIZE;
- cnt++;
- }
- }
- }
- ndbrequire(cnt == regTabPtr->m_no_of_attributes);
-}
-
-void Dbtup::addattrrefuseLab(Signal* signal,
- FragrecordPtr regFragPtr,
- FragoperrecPtr fragOperPtr,
- Tablerec* const regTabPtr,
- Uint32 fragId)
-{
- releaseFragPages(regFragPtr.p);
- deleteFragTab(regTabPtr, fragId);
- releaseFragrec(regFragPtr);
- releaseTabDescr(regTabPtr);
- initTab(regTabPtr);
-
- signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
- signal->theData[1]= terrorCode;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag,
- GSN_TUP_ADD_ATTRREF, signal, 2, JBB);
- releaseFragoperrec(fragOperPtr);
-}
-
-void Dbtup::fragrefuse4Lab(Signal* signal,
- FragoperrecPtr fragOperPtr,
- FragrecordPtr regFragPtr,
- Tablerec* const regTabPtr,
- Uint32 fragId)
-{
- releaseFragPages(regFragPtr.p);
- fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr, fragId);
- initTab(regTabPtr);
-}
-
-void Dbtup::fragrefuse3Lab(Signal* signal,
- FragoperrecPtr fragOperPtr,
- FragrecordPtr regFragPtr,
- Tablerec* const regTabPtr,
- Uint32 fragId)
-{
- fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
- deleteFragTab(regTabPtr, fragId);
-}
-
-void Dbtup::fragrefuse2Lab(Signal* signal,
- FragoperrecPtr fragOperPtr,
- FragrecordPtr regFragPtr)
-{
- fragrefuse1Lab(signal, fragOperPtr);
- releaseFragrec(regFragPtr);
-}
-
-void Dbtup::fragrefuse1Lab(Signal* signal, FragoperrecPtr fragOperPtr)
-{
- fragrefuseLab(signal, fragOperPtr);
- releaseFragoperrec(fragOperPtr);
-}
-
-void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr)
-{
- signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
- signal->theData[1]= terrorCode;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUPFRAGREF, signal, 2, JBB);
-}
-
-void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr)
-{
- fragOperPtr.p->inUse = false;
- fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
- cfirstfreeFragopr = fragOperPtr.i;
-}//Dbtup::releaseFragoperrec()
-
-void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
-{
- for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (regTabPtr->fragid[i] == fragId) {
- jam();
- regTabPtr->fragid[i]= RNIL;
- regTabPtr->fragrec[i]= RNIL;
- return;
- }
- }
- ndbrequire(false);
-}
-
-/*
- * LQH aborts on-going create table operation. The table is later
- * dropped by DICT.
- */
-void Dbtup::abortAddFragOp(Signal* signal)
-{
- FragoperrecPtr fragOperPtr;
-
- fragOperPtr.i = signal->theData[1];
- ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
- ndbrequire(fragOperPtr.p->inUse);
- releaseFragoperrec(fragOperPtr);
-}
-
-void
-Dbtup::execDROP_TAB_REQ(Signal* signal)
-{
- jamEntry();
- if (ERROR_INSERTED(4013)) {
-#ifdef VM_TRACE
- verifytabdes();
-#endif
- }
- DropTabReq* req= (DropTabReq*)signal->getDataPtr();
-
- TablerecPtr tabPtr;
- tabPtr.i= req->tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- tabPtr.p->m_dropTable.tabUserRef = req->senderRef;
- tabPtr.p->m_dropTable.tabUserPtr = req->senderData;
- tabPtr.p->tableStatus = DROPPING;
-
- signal->theData[0]= ZREL_FRAG;
- signal->theData[1]= tabPtr.i;
- signal->theData[2]= RNIL;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
-}
-
-void Dbtup::releaseTabDescr(Tablerec* const regTabPtr)
-{
- Uint32 descriptor= regTabPtr->readKeyArray;
- if (descriptor != RNIL) {
- jam();
- Uint32 offset[10];
- getTabDescrOffsets(regTabPtr, offset);
-
- regTabPtr->tabDescriptor= RNIL;
- regTabPtr->readKeyArray= RNIL;
- regTabPtr->readFunctionArray= NULL;
- regTabPtr->updateFunctionArray= NULL;
- regTabPtr->charsetArray= NULL;
-
- // move to start of descriptor
- descriptor -= offset[3];
- Uint32 retNo= getTabDescrWord(descriptor + ZTD_DATASIZE);
- ndbrequire(getTabDescrWord(descriptor + ZTD_HEADER) == ZTD_TYPE_NORMAL);
- ndbrequire(retNo == getTabDescrWord((descriptor + retNo) - ZTD_TR_SIZE));
- ndbrequire(ZTD_TYPE_NORMAL ==
- getTabDescrWord((descriptor + retNo) - ZTD_TR_TYPE));
- freeTabDescr(descriptor, retNo);
- }
-}
-
-void Dbtup::releaseFragment(Signal* signal, Uint32 tableId,
- Uint32 logfile_group_id)
-{
- TablerecPtr tabPtr;
- tabPtr.i= tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
- Uint32 fragIndex = RNIL;
- Uint32 fragId = RNIL;
- Uint32 i = 0;
- for (i = 0; i < MAX_FRAG_PER_NODE; i++) {
- jam();
- if (tabPtr.p->fragid[i] != RNIL) {
- jam();
- fragIndex= tabPtr.p->fragrec[i];
- fragId= tabPtr.p->fragid[i];
- break;
- }
- }
- if (fragIndex != RNIL) {
- jam();
-
- signal->theData[0] = ZUNMAP_PAGES;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragIndex;
- signal->theData[3] = 0;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- return;
- }
-
- if (logfile_group_id != RNIL)
- {
- Callback cb;
- cb.m_callbackData= tabPtr.i;
- cb.m_callbackFunction =
- safe_cast(&Dbtup::drop_table_log_buffer_callback);
- Uint32 sz= sizeof(Disk_undo::Drop) >> 2;
- int r0 = c_lgman->alloc_log_space(logfile_group_id, sz);
- if (r0)
- {
- jam();
- warningEvent("Failed to alloc log space for drop table: %u",
- tabPtr.i);
- goto done;
- }
-
- Logfile_client lgman(this, c_lgman, logfile_group_id);
- int res= lgman.get_log_buffer(signal, sz, &cb);
- switch(res){
- case 0:
- jam();
- return;
- case -1:
- warningEvent("Failed to get log buffer for drop table: %u",
- tabPtr.i);
- c_lgman->free_log_space(logfile_group_id, sz);
- goto done;
- break;
- default:
- execute(signal, cb, logfile_group_id);
- return;
- }
- }
-
-done:
- drop_table_logsync_callback(signal, tabPtr.i, RNIL);
-}
-
-void
-Dbtup::drop_fragment_unmap_pages(Signal *signal,
- TablerecPtr tabPtr,
- FragrecordPtr fragPtr,
- Uint32 pos)
-{
- if (tabPtr.p->m_no_of_disk_attributes)
- {
- jam();
- Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
-
- if (!alloc_info.m_unmap_pages.isEmpty())
- {
- jam();
- ndbout_c("waiting for unmape pages");
- signal->theData[0] = ZUNMAP_PAGES;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragPtr.i;
- signal->theData[3] = pos;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- return;
- }
- while(alloc_info.m_dirty_pages[pos].isEmpty() && pos < MAX_FREE_LIST)
- pos++;
-
- if (pos == MAX_FREE_LIST)
- {
- if(alloc_info.m_curr_extent_info_ptr_i != RNIL)
- {
- Local_extent_info_list
- list(c_extent_pool, alloc_info.m_free_extents[0]);
- Ptr<Extent_info> ext_ptr;
- c_extent_pool.getPtr(ext_ptr, alloc_info.m_curr_extent_info_ptr_i);
- list.add(ext_ptr);
- alloc_info.m_curr_extent_info_ptr_i= RNIL;
- }
-
- drop_fragment_free_extent(signal, tabPtr, fragPtr, 0);
- return;
- }
-
- Ptr<Page> pagePtr;
- ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
- {
- LocalDLList<Page> list(*pool, alloc_info.m_dirty_pages[pos]);
- list.first(pagePtr);
- list.remove(pagePtr);
- }
-
- Page_cache_client::Request req;
- req.m_page.m_page_no = pagePtr.p->m_page_no;
- req.m_page.m_file_no = pagePtr.p->m_file_no;
-
- req.m_callback.m_callbackData= pos;
- req.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::drop_fragment_unmap_page_callback);
-
- int flags= Page_cache_client::COMMIT_REQ;
- int res= m_pgman.get_page(signal, req, flags);
- switch(res)
- {
- case 0:
- case -1:
- break;
- default:
- ndbrequire((Uint32)res == pagePtr.i);
- drop_fragment_unmap_page_callback(signal, pos, res);
- }
- return;
- }
- drop_fragment_free_extent(signal, tabPtr, fragPtr, 0);
-}
-
-void
-Dbtup::drop_fragment_unmap_page_callback(Signal* signal,
- Uint32 pos, Uint32 page_id)
-{
- Ptr<GlobalPage> page;
- m_global_page_pool.getPtr(page, page_id);
-
- Local_key key;
- key.m_page_no = ((Page*)page.p)->m_page_no;
- key.m_file_no = ((Page*)page.p)->m_file_no;
-
- Uint32 fragId = ((Page*)page.p)->m_fragment_id;
- Uint32 tableId = ((Page*)page.p)->m_table_id;
- m_pgman.drop_page(key, page_id);
-
- TablerecPtr tabPtr;
- tabPtr.i= tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- FragrecordPtr fragPtr;
- getFragmentrec(fragPtr, fragId, tabPtr.p);
-
- signal->theData[0] = ZUNMAP_PAGES;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragPtr.i;
- signal->theData[3] = pos;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
-}
-
-void
-Dbtup::drop_fragment_free_extent(Signal *signal,
- TablerecPtr tabPtr,
- FragrecordPtr fragPtr,
- Uint32 pos)
-{
- if (tabPtr.p->m_no_of_disk_attributes)
- {
- Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
- for(; pos<EXTENT_SEARCH_MATRIX_SIZE; pos++)
- {
- if(!alloc_info.m_free_extents[pos].isEmpty())
- {
- jam();
- Callback cb;
- cb.m_callbackData= fragPtr.i;
- cb.m_callbackFunction =
- safe_cast(&Dbtup::drop_fragment_free_extent_log_buffer_callback);
-#if NOT_YET_UNDO_FREE_EXTENT
- Uint32 sz= sizeof(Disk_undo::FreeExtent) >> 2;
- (void) c_lgman->alloc_log_space(fragPtr.p->m_logfile_group_id, sz);
-
- Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
-
- int res= lgman.get_log_buffer(signal, sz, &cb);
- switch(res){
- case 0:
- jam();
- return;
- case -1:
- ndbrequire("NOT YET IMPLEMENTED" == 0);
- break;
- default:
- execute(signal, cb, fragPtr.p->m_logfile_group_id);
- return;
- }
-#else
- execute(signal, cb, fragPtr.p->m_logfile_group_id);
- return;
-#endif
- }
- }
-
- ArrayPool<Page> *cheat_pool= (ArrayPool<Page>*)&m_global_page_pool;
- for(pos= 0; pos<MAX_FREE_LIST; pos++)
- {
- ndbrequire(alloc_info.m_page_requests[pos].isEmpty());
- LocalDLList<Page> list(* cheat_pool, alloc_info.m_dirty_pages[pos]);
- list.remove();
- }
- }
-
- signal->theData[0] = ZFREE_VAR_PAGES;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-}
-
-void
-Dbtup::drop_table_log_buffer_callback(Signal* signal, Uint32 tablePtrI,
- Uint32 logfile_group_id)
-{
- TablerecPtr tabPtr;
- tabPtr.i = tablePtrI;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- ndbrequire(tabPtr.p->m_no_of_disk_attributes);
-
- Disk_undo::Drop drop;
- drop.m_table = tabPtr.i;
- drop.m_type_length =
- (Disk_undo::UNDO_DROP << 16) | (sizeof(drop) >> 2);
- Logfile_client lgman(this, c_lgman, logfile_group_id);
-
- Logfile_client::Change c[1] = {{ &drop, sizeof(drop) >> 2 } };
- Uint64 lsn = lgman.add_entry(c, 1);
-
- Logfile_client::Request req;
- req.m_callback.m_callbackData= tablePtrI;
- req.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::drop_table_logsync_callback);
-
- int ret = lgman.sync_lsn(signal, lsn, &req, 0);
- switch(ret){
- case 0:
- return;
- case -1:
- warningEvent("Failed to syn log for drop of table: %u", tablePtrI);
- default:
- execute(signal, req.m_callback, logfile_group_id);
- }
-}
-
-void
-Dbtup::drop_table_logsync_callback(Signal* signal,
- Uint32 tabPtrI,
- Uint32 logfile_group_id)
-{
- TablerecPtr tabPtr;
- tabPtr.i = tabPtrI;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- DropTabConf * const dropConf= (DropTabConf *)signal->getDataPtrSend();
- dropConf->senderRef= reference();
- dropConf->senderData= tabPtr.p->m_dropTable.tabUserPtr;
- dropConf->tableId= tabPtr.i;
- sendSignal(tabPtr.p->m_dropTable.tabUserRef, GSN_DROP_TAB_CONF,
- signal, DropTabConf::SignalLength, JBB);
-
- releaseTabDescr(tabPtr.p);
- initTab(tabPtr.p);
-}
-
-void
-Dbtup::drop_fragment_free_extent_log_buffer_callback(Signal* signal,
- Uint32 fragPtrI,
- Uint32 unused)
-{
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- TablerecPtr tabPtr;
- tabPtr.i = fragPtr.p->fragTableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- ndbrequire(tabPtr.p->m_no_of_disk_attributes);
- Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
-
- for(Uint32 pos = 0; pos<EXTENT_SEARCH_MATRIX_SIZE; pos++)
- {
- if(!alloc_info.m_free_extents[pos].isEmpty())
- {
- jam();
- Local_extent_info_list
- list(c_extent_pool, alloc_info.m_free_extents[pos]);
- Ptr<Extent_info> ext_ptr;
- list.first(ext_ptr);
-
-#if NOT_YET_UNDO_FREE_EXTENT
-#error "This code is complete"
-#error "but not needed until we do dealloc of empty extents"
- Disk_undo::FreeExtent free;
- free.m_table = tabPtr.i;
- free.m_fragment = fragPtr.p->fragmentId;
- free.m_file_no = ext_ptr.p->m_key.m_file_no;
- free.m_page_no = ext_ptr.p->m_key.m_page_no;
- free.m_type_length =
- (Disk_undo::UNDO_FREE_EXTENT << 16) | (sizeof(free) >> 2);
- Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
-
- Logfile_client::Change c[1] = {{ &free, sizeof(free) >> 2 } };
- Uint64 lsn = lgman.add_entry(c, 1);
-#else
- Uint64 lsn = 0;
-#endif
-
- Tablespace_client tsman(signal, c_tsman, tabPtr.i,
- fragPtr.p->fragmentId,
- fragPtr.p->m_tablespace_id);
-
- tsman.free_extent(&ext_ptr.p->m_key, lsn);
- c_extent_hash.remove(ext_ptr);
- list.release(ext_ptr);
-
- signal->theData[0] = ZFREE_EXTENT;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragPtr.i;
- signal->theData[3] = pos;
- sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
- return;
- }
- }
- ndbrequire(false);
-}
-
-void
-Dbtup::drop_fragment_free_var_pages(Signal* signal)
-{
- jam();
- Uint32 tableId = signal->theData[1];
- Uint32 fragPtrI = signal->theData[2];
-
- TablerecPtr tabPtr;
- tabPtr.i= tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- PagePtr pagePtr;
- if ((pagePtr.i = fragPtr.p->m_var_page_chunks) != RNIL)
- {
- c_page_pool.getPtr(pagePtr);
- Var_page* page = (Var_page*)pagePtr.p;
- fragPtr.p->m_var_page_chunks = page->next_chunk;
-
- Uint32 sz = page->chunk_size;
- returnCommonArea(pagePtr.i, sz);
-
- signal->theData[0] = ZFREE_VAR_PAGES;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = fragPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- return;
- }
-
- /**
- * Remove LCP's for fragment
- */
- tabPtr.p->m_dropTable.m_lcpno = 0;
- tabPtr.p->m_dropTable.m_fragPtrI = fragPtr.i;
- drop_fragment_fsremove(signal, tabPtr, fragPtr);
-}
-
-void
-Dbtup::drop_fragment_fsremove_done(Signal* signal,
- TablerecPtr tabPtr,
- FragrecordPtr fragPtr)
-{
- /**
- * LCP's removed...
- * now continue with "next"
- */
- Uint32 logfile_group_id = fragPtr.p->m_logfile_group_id ;
- releaseFragPages(fragPtr.p);
- Uint32 i;
- for(i= 0; i<MAX_FRAG_PER_NODE; i++)
- if(tabPtr.p->fragrec[i] == fragPtr.i)
- break;
-
- ndbrequire(i != MAX_FRAG_PER_NODE);
- tabPtr.p->fragid[i]= RNIL;
- tabPtr.p->fragrec[i]= RNIL;
- releaseFragrec(fragPtr);
-
- signal->theData[0]= ZREL_FRAG;
- signal->theData[1]= tabPtr.i;
- signal->theData[2]= logfile_group_id;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- return;
-}
-
-// Remove LCP
-
-void
-Dbtup::drop_fragment_fsremove(Signal* signal,
- TablerecPtr tabPtr,
- FragrecordPtr fragPtr)
-{
- FsRemoveReq* req = (FsRemoveReq*)signal->getDataPtrSend();
- req->userReference = reference();
- req->userPointer = tabPtr.i;
- req->directory = 0;
- req->ownDirectory = 0;
-
- Uint32 lcpno = tabPtr.p->m_dropTable.m_lcpno;
- Uint32 fragId = fragPtr.p->fragmentId;
- Uint32 tableId = fragPtr.p->fragTableId;
-
- FsOpenReq::setVersion(req->fileNumber, 5);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
- FsOpenReq::v5_setLcpNo(req->fileNumber, lcpno);
- FsOpenReq::v5_setTableId(req->fileNumber, tableId);
- FsOpenReq::v5_setFragmentId(req->fileNumber, fragId);
- sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
- FsRemoveReq::SignalLength, JBB);
-}
-
-void
-Dbtup::execFSREMOVEREF(Signal* signal)
-{
- jamEntry();
- FsRef* ref = (FsRef*)signal->getDataPtr();
- Uint32 userPointer = ref->userPointer;
- FsConf* conf = (FsConf*)signal->getDataPtrSend();
- conf->userPointer = userPointer;
- execFSREMOVECONF(signal);
-}
-
-void
-Dbtup::execFSREMOVECONF(Signal* signal)
-{
- jamEntry();
- FsConf* conf = (FsConf*)signal->getDataPtrSend();
-
- TablerecPtr tabPtr;
- FragrecordPtr fragPtr;
-
- tabPtr.i = conf->userPointer;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- ndbrequire(tabPtr.p->tableStatus == DROPPING);
-
- fragPtr.i = tabPtr.p->m_dropTable.m_fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- tabPtr.p->m_dropTable.m_lcpno++;
- if (tabPtr.p->m_dropTable.m_lcpno < 3)
- {
- jam();
- drop_fragment_fsremove(signal, tabPtr, fragPtr);
- }
- else
- {
- jam();
- drop_fragment_fsremove_done(signal, tabPtr, fragPtr);
- }
-}
-// End remove LCP
-
-void
-Dbtup::start_restore_lcp(Uint32 tableId, Uint32 fragId)
-{
- TablerecPtr tabPtr;
- tabPtr.i= tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- tabPtr.p->m_dropTable.tabUserPtr= tabPtr.p->m_attributes[DD].m_no_of_fixsize;
- tabPtr.p->m_dropTable.tabUserRef= tabPtr.p->m_attributes[DD].m_no_of_varsize;
-
- Uint32 *tabDesc = (Uint32*)(tableDescriptor+tabPtr.p->tabDescriptor);
- for(Uint32 i= 0; i<tabPtr.p->m_no_of_attributes; i++)
- {
- Uint32 disk= AttributeDescriptor::getDiskBased(* tabDesc);
- Uint32 null= AttributeDescriptor::getNullable(* tabDesc);
-
- ndbrequire(tabPtr.p->notNullAttributeMask.get(i) != null);
- if(disk)
- tabPtr.p->notNullAttributeMask.clear(i);
- tabDesc += 2;
- }
-
- tabPtr.p->m_no_of_disk_attributes = 0;
- tabPtr.p->m_attributes[DD].m_no_of_fixsize = 0;
- tabPtr.p->m_attributes[DD].m_no_of_varsize = 0;
-}
-void
-Dbtup::complete_restore_lcp(Uint32 tableId, Uint32 fragId)
-{
- TablerecPtr tabPtr;
- tabPtr.i= tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- tabPtr.p->m_attributes[DD].m_no_of_fixsize= tabPtr.p->m_dropTable.tabUserPtr;
- tabPtr.p->m_attributes[DD].m_no_of_varsize= tabPtr.p->m_dropTable.tabUserRef;
-
- tabPtr.p->m_no_of_disk_attributes =
- tabPtr.p->m_attributes[DD].m_no_of_fixsize +
- tabPtr.p->m_attributes[DD].m_no_of_varsize;
-
- Uint32 *tabDesc = (Uint32*)(tableDescriptor+tabPtr.p->tabDescriptor);
- for(Uint32 i= 0; i<tabPtr.p->m_no_of_attributes; i++)
- {
- Uint32 disk= AttributeDescriptor::getDiskBased(* tabDesc);
- Uint32 null= AttributeDescriptor::getNullable(* tabDesc);
-
- if(disk && !null)
- tabPtr.p->notNullAttributeMask.set(i);
-
- tabDesc += 2;
- }
-}
-
-bool
-Dbtup::get_frag_info(Uint32 tableId, Uint32 fragId, Uint32* maxPage)
-{
- jamEntry();
- TablerecPtr tabPtr;
- tabPtr.i= tableId;
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- FragrecordPtr fragPtr;
- getFragmentrec(fragPtr, fragId, tabPtr.p);
-
- if (maxPage)
- {
- * maxPage = fragPtr.p->noOfPages;
- }
-
- return true;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
deleted file mode 100644
index 47447bc3755..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_PAG_MAN_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-
-/* ---------------------------------------------------------------- */
-// 4) Page Memory Manager (buddy algorithm)
-//
-// The following data structures in Dbtup is used by the Page Memory
-// Manager.
-//
-// cfreepageList[16]
-// Pages with a header
-//
-// The cfreepageList is 16 free lists. Free list 0 contains chunks of
-// pages with 2^0 (=1) pages in each chunk. Free list 1 chunks of 2^1
-// (=2) pages in each chunk and so forth upto free list 15 which
-// contains chunks of 2^15 (=32768) pages in each chunk.
-// The cfreepageList array contains the pointer to the first chunk
-// in each of those lists. The lists are doubly linked where the
-// first page in each chunk contains the next and previous references
-// in position ZPAGE_NEXT_CLUST_POS and ZPAGE_PREV_CLUST_POS in the
-// page header.
-// In addition the leading page and the last page in each chunk is marked
-// with a state (=ZFREE_COMMON) in position ZPAGE_STATE_POS in page
-// header. This state indicates that the page is the leading or last page
-// in a chunk of free pages. Furthermore the leading and last page is
-// also marked with a reference to the leading (=ZPAGE_FIRST_CLUST_POS)
-// and the last page (=ZPAGE_LAST_CLUST_POS) in the chunk.
-//
-// The aim of these data structures is to enable a free area handling of
-// free pages based on a buddy algorithm. When allocating pages it is
-// performed in chunks of pages and the algorithm tries to make the
-// chunks as large as possible.
-// This manager is invoked when fragments lack internal page space to
-// accomodate all the data they are requested to store. It is also
-// invoked when fragments deallocate page space back to the free area.
-//
-// The following routines are part of the external interface:
-// void
-// allocConsPages(Uint32 noOfPagesToAllocate, #In
-// Uint32& noOfPagesAllocated, #Out
-// Uint32& retPageRef) #Out
-// void
-// returnCommonArea(Uint32 retPageRef, #In
-// Uint32 retNoPages) #In
-//
-// allocConsPages tries to allocate noOfPagesToAllocate pages in one chunk.
-// If this fails it delivers a chunk as large as possible. It returns the
-// i-value of the first page in the chunk delivered, if zero pages returned
-// this i-value is undefined. It also returns the size of the chunk actually
-// delivered.
-//
-// returnCommonArea is used when somebody is returning pages to the free area.
-// It is used both from internal routines and external routines.
-//
-// The following routines are private routines used to support the
-// above external interface:
-// removeCommonArea()
-// insertCommonArea()
-// findFreeLeftNeighbours()
-// findFreeRightNeighbours()
-// Uint32
-// nextHigherTwoLog(Uint32 input)
-//
-// nextHigherTwoLog is a support routine which is a mathematical function with
-// an integer as input and an integer as output. It calculates the 2-log of
-// (input + 1). If the 2-log of (input + 1) is larger than 15 then the routine
-// will return 15. It is part of the external interface since it is also used
-// by other similar memory management algorithms.
-//
-// External dependencies:
-// None.
-//
-// Side Effects:
-// Apart from the above mentioned data structures there are no more
-// side effects other than through the subroutine parameters in the
-// external interface.
-//
-/* ---------------------------------------------------------------- */
-
-/* ---------------------------------------------------------------- */
-/* CALCULATE THE 2-LOG + 1 OF TMP AND PUT RESULT INTO TBITS */
-/* ---------------------------------------------------------------- */
-Uint32 Dbtup::nextHigherTwoLog(Uint32 input)
-{
- input = input | (input >> 8);
- input = input | (input >> 4);
- input = input | (input >> 2);
- input = input | (input >> 1);
- Uint32 output = (input & 0x5555) + ((input >> 1) & 0x5555);
- output = (output & 0x3333) + ((output >> 2) & 0x3333);
- output = output + (output >> 4);
- output = (output & 0xf) + ((output >> 8) & 0xf);
- return output;
-}//nextHigherTwoLog()
-
-void Dbtup::initializePage()
-{
- for (Uint32 i = 0; i < 16; i++) {
- cfreepageList[i] = RNIL;
- }//for
- PagePtr pagePtr;
- for (pagePtr.i = 0; pagePtr.i < c_page_pool.getSize(); pagePtr.i++) {
- jam();
- refresh_watch_dog();
- c_page_pool.getPtr(pagePtr);
- pagePtr.p->physical_page_id= RNIL;
- pagePtr.p->next_page = pagePtr.i + 1;
- pagePtr.p->first_cluster_page = RNIL;
- pagePtr.p->next_cluster_page = RNIL;
- pagePtr.p->last_cluster_page = RNIL;
- pagePtr.p->prev_page = RNIL;
- pagePtr.p->page_state = ZFREE_COMMON;
- }//for
- pagePtr.p->next_page = RNIL;
-
- /**
- * Page 0 cant be part of buddy as
- * it will scan left right when searching for bigger blocks,
- * if 0 is part of arrat, it can search to -1...which is not good
- */
- pagePtr.i = 0;
- c_page_pool.getPtr(pagePtr);
- pagePtr.p->page_state = ~ZFREE_COMMON;
-
- Uint32 tmp = 1;
- returnCommonArea(tmp, c_page_pool.getSize() - tmp);
- cnoOfAllocatedPages = tmp; // Is updated by returnCommonArea
-}//Dbtup::initializePage()
-
-#ifdef VM_TRACE
-Uint32 fc_left, fc_right, fc_remove;
-#endif
-
-void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate,
- Uint32& noOfPagesAllocated,
- Uint32& allocPageRef)
-{
-#ifdef VM_TRACE
- fc_left = fc_right = fc_remove = 0;
-#endif
- if (noOfPagesToAllocate == 0){
- jam();
- noOfPagesAllocated = 0;
- return;
- }//if
-
- Uint32 firstListToCheck = nextHigherTwoLog(noOfPagesToAllocate - 1);
- for (Uint32 i = firstListToCheck; i < 16; i++) {
- jam();
- if (cfreepageList[i] != RNIL) {
- jam();
-/* ---------------------------------------------------------------- */
-/* PROPER AMOUNT OF PAGES WERE FOUND. NOW SPLIT THE FOUND */
-/* AREA AND RETURN THE PART NOT NEEDED. */
-/* ---------------------------------------------------------------- */
- noOfPagesAllocated = noOfPagesToAllocate;
- allocPageRef = cfreepageList[i];
- removeCommonArea(allocPageRef, i);
- Uint32 retNo = (1 << i) - noOfPagesToAllocate;
- Uint32 retPageRef = allocPageRef + noOfPagesToAllocate;
- returnCommonArea(retPageRef, retNo);
- return;
- }//if
- }//for
-/* ---------------------------------------------------------------- */
-/* PROPER AMOUNT OF PAGES WERE NOT FOUND. FIND AS MUCH AS */
-/* POSSIBLE. */
-/* ---------------------------------------------------------------- */
- if (firstListToCheck)
- {
- jam();
- for (Uint32 j = firstListToCheck - 1; (Uint32)~j; j--) {
- jam();
- if (cfreepageList[j] != RNIL) {
- jam();
-/* ---------------------------------------------------------------- */
-/* SOME AREA WAS FOUND, ALLOCATE ALL OF IT. */
-/* ---------------------------------------------------------------- */
- allocPageRef = cfreepageList[j];
- removeCommonArea(allocPageRef, j);
- noOfPagesAllocated = 1 << j;
- findFreeLeftNeighbours(allocPageRef, noOfPagesAllocated,
- noOfPagesToAllocate);
- findFreeRightNeighbours(allocPageRef, noOfPagesAllocated,
- noOfPagesToAllocate);
-
- return;
- }//if
- }//for
- }
-/* ---------------------------------------------------------------- */
-/* NO FREE AREA AT ALL EXISTED. RETURN ZERO PAGES */
-/* ---------------------------------------------------------------- */
- noOfPagesAllocated = 0;
- return;
-}//allocConsPages()
-
-void Dbtup::returnCommonArea(Uint32 retPageRef, Uint32 retNo)
-{
- do {
- jam();
- if (retNo == 0) {
- jam();
- return;
- }//if
- Uint32 list = nextHigherTwoLog(retNo) - 1;
- retNo -= (1 << list);
- insertCommonArea(retPageRef, list);
- retPageRef += (1 << list);
- } while (1);
-}//Dbtup::returnCommonArea()
-
-void Dbtup::findFreeLeftNeighbours(Uint32& allocPageRef,
- Uint32& noPagesAllocated,
- Uint32 noOfPagesToAllocate)
-{
- PagePtr pageFirstPtr, pageLastPtr;
- Uint32 remainAllocate = noOfPagesToAllocate - noPagesAllocated;
- Uint32 loop = 0;
- while (allocPageRef > 0 &&
- ++loop < 16)
- {
- jam();
- pageLastPtr.i = allocPageRef - 1;
- c_page_pool.getPtr(pageLastPtr);
- if (pageLastPtr.p->page_state != ZFREE_COMMON) {
- jam();
- return;
- } else {
- jam();
- pageFirstPtr.i = pageLastPtr.p->first_cluster_page;
- ndbrequire(pageFirstPtr.i != RNIL);
- Uint32 list = nextHigherTwoLog(pageLastPtr.i - pageFirstPtr.i);
- removeCommonArea(pageFirstPtr.i, list);
- Uint32 listSize = 1 << list;
- if (listSize > remainAllocate) {
- jam();
- Uint32 retNo = listSize - remainAllocate;
- returnCommonArea(pageFirstPtr.i, retNo);
- allocPageRef = pageFirstPtr.i + retNo;
- noPagesAllocated = noOfPagesToAllocate;
- return;
- } else {
- jam();
- allocPageRef = pageFirstPtr.i;
- noPagesAllocated += listSize;
- remainAllocate -= listSize;
- }//if
- }//if
-#ifdef VM_TRACE
- fc_left++;
-#endif
- }//while
-}//Dbtup::findFreeLeftNeighbours()
-
-void Dbtup::findFreeRightNeighbours(Uint32& allocPageRef,
- Uint32& noPagesAllocated,
- Uint32 noOfPagesToAllocate)
-{
- PagePtr pageFirstPtr, pageLastPtr;
- Uint32 remainAllocate = noOfPagesToAllocate - noPagesAllocated;
- if (remainAllocate == 0) {
- jam();
- return;
- }//if
- Uint32 loop = 0;
- while ((allocPageRef + noPagesAllocated) < c_page_pool.getSize() &&
- ++loop < 16)
- {
- jam();
- pageFirstPtr.i = allocPageRef + noPagesAllocated;
- c_page_pool.getPtr(pageFirstPtr);
- if (pageFirstPtr.p->page_state != ZFREE_COMMON) {
- jam();
- return;
- } else {
- jam();
- pageLastPtr.i = pageFirstPtr.p->last_cluster_page;
- ndbrequire(pageLastPtr.i != RNIL);
- Uint32 list = nextHigherTwoLog(pageLastPtr.i - pageFirstPtr.i);
- removeCommonArea(pageFirstPtr.i, list);
- Uint32 listSize = 1 << list;
- if (listSize > remainAllocate) {
- jam();
- Uint32 retPageRef = pageFirstPtr.i + remainAllocate;
- Uint32 retNo = listSize - remainAllocate;
- returnCommonArea(retPageRef, retNo);
- noPagesAllocated += remainAllocate;
- return;
- } else {
- jam();
- noPagesAllocated += listSize;
- remainAllocate -= listSize;
- }//if
- }//if
-#ifdef VM_TRACE
- fc_right++;
-#endif
- }//while
-}//Dbtup::findFreeRightNeighbours()
-
-void Dbtup::insertCommonArea(Uint32 insPageRef, Uint32 insList)
-{
- cnoOfAllocatedPages -= (1 << insList);
- PagePtr pageLastPtr, pageInsPtr, pageHeadPtr;
-
- pageHeadPtr.i = cfreepageList[insList];
- c_page_pool.getPtr(pageInsPtr, insPageRef);
- ndbrequire(insList < 16);
- pageLastPtr.i = (pageInsPtr.i + (1 << insList)) - 1;
-
- pageInsPtr.p->page_state = ZFREE_COMMON;
- pageInsPtr.p->next_cluster_page = pageHeadPtr.i;
- pageInsPtr.p->prev_cluster_page = RNIL;
- pageInsPtr.p->last_cluster_page = pageLastPtr.i;
- cfreepageList[insList] = pageInsPtr.i;
-
- if (pageHeadPtr.i != RNIL)
- {
- jam();
- c_page_pool.getPtr(pageHeadPtr);
- pageHeadPtr.p->prev_cluster_page = pageInsPtr.i;
- }
-
- c_page_pool.getPtr(pageLastPtr);
- pageLastPtr.p->page_state = ZFREE_COMMON;
- pageLastPtr.p->first_cluster_page = pageInsPtr.i;
- pageLastPtr.p->next_page = RNIL;
-}//Dbtup::insertCommonArea()
-
-void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list)
-{
- cnoOfAllocatedPages += (1 << list);
- PagePtr pagePrevPtr, pageNextPtr, pageLastPtr, remPagePtr;
-
- c_page_pool.getPtr(remPagePtr, remPageRef);
- ndbrequire(list < 16);
- if (cfreepageList[list] == remPagePtr.i) {
- jam();
- ndbassert(remPagePtr.p->prev_cluster_page == RNIL);
- cfreepageList[list] = remPagePtr.p->next_cluster_page;
- pageNextPtr.i = cfreepageList[list];
- if (pageNextPtr.i != RNIL) {
- jam();
- c_page_pool.getPtr(pageNextPtr);
- pageNextPtr.p->prev_cluster_page = RNIL;
- }//if
- } else {
- pagePrevPtr.i = remPagePtr.p->prev_cluster_page;
- pageNextPtr.i = remPagePtr.p->next_cluster_page;
- c_page_pool.getPtr(pagePrevPtr);
- pagePrevPtr.p->next_cluster_page = pageNextPtr.i;
- if (pageNextPtr.i != RNIL)
- {
- jam();
- c_page_pool.getPtr(pageNextPtr);
- pageNextPtr.p->prev_cluster_page = pagePrevPtr.i;
- }
- }//if
- remPagePtr.p->next_cluster_page= RNIL;
- remPagePtr.p->last_cluster_page= RNIL;
- remPagePtr.p->prev_cluster_page= RNIL;
- remPagePtr.p->page_state = ~ZFREE_COMMON;
-
- pageLastPtr.i = (remPagePtr.i + (1 << list)) - 1;
- c_page_pool.getPtr(pageLastPtr);
- pageLastPtr.p->first_cluster_page= RNIL;
- pageLastPtr.p->page_state = ~ZFREE_COMMON;
-
-}//Dbtup::removeCommonArea()
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
deleted file mode 100644
index bf079627990..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
+++ /dev/null
@@ -1,602 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_PAGE_MAP_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-
-//
-// PageMap is a service used by Dbtup to map logical page id's to physical
-// page id's. The mapping is needs the fragment and the logical page id to
-// provide the physical id.
-//
-// This is a part of Dbtup which is the exclusive user of a certain set of
-// variables on the fragment record and it is the exclusive user of the
-// struct for page ranges.
-//
-//
-// The following methods operate on the data handled by the page map class.
-//
-// Public methods
-// insertPageRange(Uint32 startPageId, # In
-// Uint32 noPages) # In
-// Inserts a range of pages into the mapping structure.
-//
-// void releaseFragPages()
-// Releases all pages and their mappings belonging to a fragment.
-//
-// Uint32 allocFragPages(Uint32 tafpNoAllocRequested)
-// Allocate a set of pages to the fragment from the page manager
-//
-// Uint32 getEmptyPage()
-// Get an empty page from the pool of empty pages on the fragment.
-// It returns the physical page id of the empty page.
-// Returns RNIL if no empty page is available.
-//
-// Uint32 getRealpid(Uint32 logicalPageId)
-// Return the physical page id provided the logical page id
-//
-// void initializePageRange()
-// Initialise free list of page ranges and initialise the page raneg records.
-//
-// void initFragRange()
-// Initialise the fragment variables when allocating a fragment to a table.
-//
-// void initPageRangeSize(Uint32 size)
-// Initialise the number of page ranges.
-//
-// Uint32 getNoOfPages()
-// Get the number of pages on the fragment currently.
-//
-//
-// Private methods
-// Uint32 leafPageRangeFull(PageRangePtr currPageRangePtr)
-//
-// void errorHandler()
-// Method to crash NDB kernel in case of weird data set-up
-//
-// void allocMoreFragPages()
-// When no more empty pages are attached to the fragment and we need more
-// we allocate more pages from the page manager using this method.
-//
-// Private data
-// On the fragment record
-// currentPageRange # The current page range where to insert the next range
-// rootPageRange # The root of the page ranges owned
-// nextStartRange # The next page id to assign when expanding the
-// # page map
-// noOfPages # The number of pages in the fragment
-// emptyPrimPage # The first page of the empty pages in the fragment
-//
-// The full page range struct
-
-Uint32 Dbtup::getEmptyPage(Fragrecord* regFragPtr)
-{
- Uint32 pageId = regFragPtr->emptyPrimPage.firstItem;
- if (pageId == RNIL) {
- jam();
- allocMoreFragPages(regFragPtr);
- pageId = regFragPtr->emptyPrimPage.firstItem;
- if (pageId == RNIL) {
- jam();
- return RNIL;
- }//if
- }//if
- PagePtr pagePtr;
- LocalDLList<Page> alloc_pages(c_page_pool, regFragPtr->emptyPrimPage);
- alloc_pages.getPtr(pagePtr, pageId);
- alloc_pages.remove(pagePtr);
- return pageId;
-}//Dbtup::getEmptyPage()
-
-Uint32 Dbtup::getRealpid(Fragrecord* regFragPtr, Uint32 logicalPageId)
-{
- PageRangePtr grpPageRangePtr;
- Uint32 loopLimit;
- Uint32 loopCount = 0;
- Uint32 pageRangeLimit = cnoOfPageRangeRec;
- ndbassert(logicalPageId < getNoOfPages(regFragPtr));
- grpPageRangePtr.i = regFragPtr->rootPageRange;
- while (true) {
- ndbassert(loopCount++ < 100);
- ndbrequire(grpPageRangePtr.i < pageRangeLimit);
- ptrAss(grpPageRangePtr, pageRange);
- loopLimit = grpPageRangePtr.p->currentIndexPos;
- ndbrequire(loopLimit <= 3);
- for (Uint32 i = 0; i <= loopLimit; i++) {
- jam();
- if (grpPageRangePtr.p->startRange[i] <= logicalPageId) {
- if (grpPageRangePtr.p->endRange[i] >= logicalPageId) {
- if (grpPageRangePtr.p->type[i] == ZLEAF) {
- jam();
- Uint32 realPageId = (logicalPageId - grpPageRangePtr.p->startRange[i]) +
- grpPageRangePtr.p->basePageId[i];
- return realPageId;
- } else {
- ndbrequire(grpPageRangePtr.p->type[i] == ZNON_LEAF);
- grpPageRangePtr.i = grpPageRangePtr.p->basePageId[i];
- }//if
- }//if
- }//if
- }//for
- }//while
- return 0;
-}//Dbtup::getRealpid()
-
-Uint32 Dbtup::getNoOfPages(Fragrecord* const regFragPtr)
-{
- return regFragPtr->noOfPages;
-}//Dbtup::getNoOfPages()
-
-void Dbtup::initPageRangeSize(Uint32 size)
-{
- cnoOfPageRangeRec = size;
-}//Dbtup::initPageRangeSize()
-
-/* ---------------------------------------------------------------- */
-/* ----------------------- INSERT_PAGE_RANGE_TAB ------------------ */
-/* ---------------------------------------------------------------- */
-/* INSERT A PAGE RANGE INTO THE FRAGMENT */
-/* */
-/* NOTE: THE METHOD IS ATOMIC. EITHER THE ACTION IS */
-/* PERFORMED FULLY OR NO ACTION IS PERFORMED AT ALL. */
-/* TO SUPPORT THIS THE CODE HAS A CLEANUP PART AFTER */
-/* ERRORS. */
-/* ---------------------------------------------------------------- */
-bool Dbtup::insertPageRangeTab(Fragrecord* const regFragPtr,
- Uint32 startPageId,
- Uint32 noPages)
-{
- PageRangePtr currPageRangePtr;
- if (cfirstfreerange == RNIL) {
- jam();
- return false;
- }//if
- currPageRangePtr.i = regFragPtr->currentPageRange;
- if (currPageRangePtr.i == RNIL) {
- jam();
-/* ---------------------------------------------------------------- */
-/* THE FIRST PAGE RANGE IS HANDLED WITH SPECIAL CODE */
-/* ---------------------------------------------------------------- */
- seizePagerange(currPageRangePtr);
- regFragPtr->rootPageRange = currPageRangePtr.i;
- currPageRangePtr.p->currentIndexPos = 0;
- currPageRangePtr.p->parentPtr = RNIL;
- } else {
- jam();
- ptrCheckGuard(currPageRangePtr, cnoOfPageRangeRec, pageRange);
- if (currPageRangePtr.p->currentIndexPos < 3) {
- jam();
-/* ---------------------------------------------------------------- */
-/* THE SIMPLE CASE WHEN IT IS ONLY NECESSARY TO FILL IN THE */
-/* NEXT EMPTY POSITION IN THE PAGE RANGE RECORD IS TREATED */
-/* BY COMMON CODE AT THE END OF THE SUBROUTINE. */
-/* ---------------------------------------------------------------- */
- currPageRangePtr.p->currentIndexPos++;
- } else {
- jam();
- ndbrequire(currPageRangePtr.p->currentIndexPos == 3);
- currPageRangePtr.i = leafPageRangeFull(regFragPtr, currPageRangePtr);
- if (currPageRangePtr.i == RNIL) {
- return false;
- }//if
- ptrCheckGuard(currPageRangePtr, cnoOfPageRangeRec, pageRange);
- }//if
- }//if
- currPageRangePtr.p->startRange[currPageRangePtr.p->currentIndexPos] = regFragPtr->nextStartRange;
-/* ---------------------------------------------------------------- */
-/* NOW SET THE LEAF LEVEL PAGE RANGE RECORD PROPERLY */
-/* PAGE_RANGE_PTR REFERS TO LEAF RECORD WHEN ARRIVING HERE */
-/* ---------------------------------------------------------------- */
- currPageRangePtr.p->endRange[currPageRangePtr.p->currentIndexPos] =
- (regFragPtr->nextStartRange + noPages) - 1;
- currPageRangePtr.p->basePageId[currPageRangePtr.p->currentIndexPos] = startPageId;
- currPageRangePtr.p->type[currPageRangePtr.p->currentIndexPos] = ZLEAF;
-/* ---------------------------------------------------------------- */
-/* WE NEED TO UPDATE THE CURRENT PAGE RANGE IN CASE IT HAS */
-/* CHANGED. WE ALSO NEED TO UPDATE THE NEXT START RANGE */
-/* ---------------------------------------------------------------- */
- regFragPtr->currentPageRange = currPageRangePtr.i;
- regFragPtr->nextStartRange += noPages;
-/* ---------------------------------------------------------------- */
-/* WE NEED TO UPDATE THE END RANGE IN ALL PAGE RANGE RECORDS */
-/* UP TO THE ROOT. */
-/* ---------------------------------------------------------------- */
- PageRangePtr loopPageRangePtr;
- loopPageRangePtr = currPageRangePtr;
- while (true) {
- jam();
- loopPageRangePtr.i = loopPageRangePtr.p->parentPtr;
- if (loopPageRangePtr.i != RNIL) {
- jam();
- ptrCheckGuard(loopPageRangePtr, cnoOfPageRangeRec, pageRange);
- ndbrequire(loopPageRangePtr.p->currentIndexPos < 4);
- loopPageRangePtr.p->endRange[loopPageRangePtr.p->currentIndexPos] += noPages;
- } else {
- jam();
- break;
- }//if
- }//while
- regFragPtr->noOfPages += noPages;
- return true;
-}//Dbtup::insertPageRangeTab()
-
-
-void Dbtup::releaseFragPages(Fragrecord* regFragPtr)
-{
- if (regFragPtr->rootPageRange == RNIL) {
- jam();
- return;
- }//if
- PageRangePtr regPRPtr;
- regPRPtr.i = regFragPtr->rootPageRange;
- ptrCheckGuard(regPRPtr, cnoOfPageRangeRec, pageRange);
- while (true) {
- jam();
- const Uint32 indexPos = regPRPtr.p->currentIndexPos;
- ndbrequire(indexPos < 4);
-
- const Uint32 basePageId = regPRPtr.p->basePageId[indexPos];
- regPRPtr.p->basePageId[indexPos] = RNIL;
- if (basePageId == RNIL) {
- jam();
- /**
- * Finished with indexPos continue with next
- */
- if (indexPos > 0) {
- jam();
- regPRPtr.p->currentIndexPos--;
- continue;
- }//if
-
- /* ---------------------------------------------------------------- */
- /* THE PAGE RANGE REC IS EMPTY. RELEASE IT. */
- /*----------------------------------------------------------------- */
- Uint32 parentPtr = regPRPtr.p->parentPtr;
- releasePagerange(regPRPtr);
-
- if (parentPtr != RNIL) {
- jam();
- regPRPtr.i = parentPtr;
- ptrCheckGuard(regPRPtr, cnoOfPageRangeRec, pageRange);
- continue;
- }//if
-
- jam();
- ndbrequire(regPRPtr.i == regFragPtr->rootPageRange);
- initFragRange(regFragPtr);
- for (Uint32 i = 0; i<MAX_FREE_LIST; i++)
- {
- LocalDLList<Page> tmp(c_page_pool, regFragPtr->free_var_page_array[i]);
- tmp.remove();
- }
-
- {
- LocalDLList<Page> tmp(c_page_pool, regFragPtr->emptyPrimPage);
- tmp.remove();
- }
-
- {
- LocalDLFifoList<Page> tmp(c_page_pool, regFragPtr->thFreeFirst);
- tmp.remove();
- }
-
- {
- LocalSLList<Page> tmp(c_page_pool, regFragPtr->m_empty_pages);
- tmp.remove();
- }
-
- return;
- } else {
- if (regPRPtr.p->type[indexPos] == ZNON_LEAF) {
- jam();
- /* ---------------------------------------------------------------- */
- // A non-leaf node, we must release everything below it before we
- // release this node.
- /* ---------------------------------------------------------------- */
- regPRPtr.i = basePageId;
- ptrCheckGuard(regPRPtr, cnoOfPageRangeRec, pageRange);
- } else {
- jam();
- ndbrequire(regPRPtr.p->type[indexPos] == ZLEAF);
- /* ---------------------------------------------------------------- */
- /* PAGE_RANGE_PTR /= RNIL AND THE CURRENT POS IS NOT A CHLED. */
- /*----------------------------------------------------------------- */
- const Uint32 start = regPRPtr.p->startRange[indexPos];
- const Uint32 stop = regPRPtr.p->endRange[indexPos];
- ndbrequire(stop >= start);
- const Uint32 retNo = (stop - start + 1);
- returnCommonArea(basePageId, retNo);
- }//if
- }//if
- }//while
-}//Dbtup::releaseFragPages()
-
-void Dbtup::initializePageRange()
-{
- PageRangePtr regPTRPtr;
- for (regPTRPtr.i = 0;
- regPTRPtr.i < cnoOfPageRangeRec; regPTRPtr.i++) {
- ptrAss(regPTRPtr, pageRange);
- regPTRPtr.p->nextFree = regPTRPtr.i + 1;
- }//for
- regPTRPtr.i = cnoOfPageRangeRec - 1;
- ptrAss(regPTRPtr, pageRange);
- regPTRPtr.p->nextFree = RNIL;
- cfirstfreerange = 0;
- c_noOfFreePageRanges = cnoOfPageRangeRec;
-}//Dbtup::initializePageRange()
-
-void Dbtup::initFragRange(Fragrecord* const regFragPtr)
-{
- regFragPtr->rootPageRange = RNIL;
- regFragPtr->currentPageRange = RNIL;
- regFragPtr->noOfPages = 0;
- regFragPtr->noOfVarPages = 0;
- regFragPtr->noOfPagesToGrow = 2;
- regFragPtr->nextStartRange = 0;
-}//initFragRange()
-
-Uint32 Dbtup::allocFragPages(Fragrecord* regFragPtr, Uint32 tafpNoAllocRequested)
-{
- Uint32 tafpPagesAllocated = 0;
- while (true) {
- Uint32 noOfPagesAllocated = 0;
- Uint32 noPagesToAllocate = tafpNoAllocRequested - tafpPagesAllocated;
- Uint32 retPageRef = RNIL;
- allocConsPages(noPagesToAllocate, noOfPagesAllocated, retPageRef);
- if (noOfPagesAllocated == 0) {
- jam();
- return tafpPagesAllocated;
- }//if
-/* ---------------------------------------------------------------- */
-/* IT IS NOW TIME TO PUT THE ALLOCATED AREA INTO THE PAGE */
-/* RANGE TABLE. */
-/* ---------------------------------------------------------------- */
- Uint32 startRange = regFragPtr->nextStartRange;
- if (!insertPageRangeTab(regFragPtr, retPageRef, noOfPagesAllocated)) {
- jam();
- returnCommonArea(retPageRef, noOfPagesAllocated);
- return tafpPagesAllocated;
- }//if
- tafpPagesAllocated += noOfPagesAllocated;
- Uint32 loopLimit = retPageRef + noOfPagesAllocated;
- PagePtr loopPagePtr;
-/* ---------------------------------------------------------------- */
-/* SINCE A NUMBER OF PAGES WERE ALLOCATED FROM COMMON AREA */
-/* WITH SUCCESS IT IS NOW TIME TO CHANGE THE STATE OF */
-/* THOSE PAGES TO EMPTY_MM AND LINK THEM INTO THE EMPTY */
-/* PAGE LIST OF THE FRAGMENT. */
-/* ---------------------------------------------------------------- */
- Uint32 prev = RNIL;
- for (loopPagePtr.i = retPageRef; loopPagePtr.i < loopLimit; loopPagePtr.i++) {
- jam();
- c_page_pool.getPtr(loopPagePtr);
- loopPagePtr.p->page_state = ZEMPTY_MM;
- loopPagePtr.p->frag_page_id = startRange +
- (loopPagePtr.i - retPageRef);
- loopPagePtr.p->physical_page_id = loopPagePtr.i;
- loopPagePtr.p->nextList = loopPagePtr.i + 1;
- loopPagePtr.p->prevList = prev;
- prev = loopPagePtr.i;
- }//for
- loopPagePtr.i--;
- ndbassert(loopPagePtr.p == c_page_pool.getPtr(loopPagePtr.i));
- loopPagePtr.p->nextList = RNIL;
-
- LocalDLList<Page> alloc(c_page_pool, regFragPtr->emptyPrimPage);
- if (noOfPagesAllocated > 1)
- {
- alloc.add(retPageRef, loopPagePtr);
- }
- else
- {
- alloc.add(loopPagePtr);
- }
-
-/* ---------------------------------------------------------------- */
-/* WAS ENOUGH PAGES ALLOCATED OR ARE MORE NEEDED. */
-/* ---------------------------------------------------------------- */
- if (tafpPagesAllocated < tafpNoAllocRequested) {
- jam();
- } else {
- ndbrequire(tafpPagesAllocated == tafpNoAllocRequested);
- jam();
- return tafpNoAllocRequested;
- }//if
- }//while
-}//Dbtup::allocFragPages()
-
-void Dbtup::allocMoreFragPages(Fragrecord* const regFragPtr)
-{
- Uint32 noAllocPages = regFragPtr->noOfPagesToGrow >> 3; // 12.5%
- noAllocPages += regFragPtr->noOfPagesToGrow >> 4; // 6.25%
- noAllocPages += 2;
-/* -----------------------------------------------------------------*/
-// We will grow by 18.75% plus two more additional pages to grow
-// a little bit quicker in the beginning.
-/* -----------------------------------------------------------------*/
-
- if (noAllocPages > m_max_allocate_pages)
- {
- noAllocPages = m_max_allocate_pages;
- }
- Uint32 allocated = allocFragPages(regFragPtr, noAllocPages);
- regFragPtr->noOfPagesToGrow += allocated;
-}//Dbtup::allocMoreFragPages()
-
-Uint32 Dbtup::leafPageRangeFull(Fragrecord* const regFragPtr, PageRangePtr currPageRangePtr)
-{
-/* ---------------------------------------------------------------- */
-/* THE COMPLEX CASE WHEN THE LEAF NODE IS FULL. GO UP THE TREE*/
-/* TO FIND THE FIRST RECORD WITH A FREE ENTRY. ALLOCATE NEW */
-/* PAGE RANGE RECORDS THEN ALL THE WAY DOWN TO THE LEAF LEVEL */
-/* AGAIN. THE TREE SHOULD ALWAYS REMAIN BALANCED. */
-/* ---------------------------------------------------------------- */
- PageRangePtr parentPageRangePtr;
- PageRangePtr foundPageRangePtr;
- parentPageRangePtr = currPageRangePtr;
- Uint32 tiprNoLevels = 1;
- while (true) {
- jam();
- parentPageRangePtr.i = parentPageRangePtr.p->parentPtr;
- if (parentPageRangePtr.i == RNIL) {
- jam();
-/* ---------------------------------------------------------------- */
-/* WE HAVE REACHED THE ROOT. A NEW ROOT MUST BE ALLOCATED. */
-/* ---------------------------------------------------------------- */
- if (c_noOfFreePageRanges < tiprNoLevels) {
- jam();
- return RNIL;
- }//if
- PageRangePtr oldRootPRPtr;
- PageRangePtr newRootPRPtr;
- oldRootPRPtr.i = regFragPtr->rootPageRange;
- ptrCheckGuard(oldRootPRPtr, cnoOfPageRangeRec, pageRange);
- seizePagerange(newRootPRPtr);
- regFragPtr->rootPageRange = newRootPRPtr.i;
- oldRootPRPtr.p->parentPtr = newRootPRPtr.i;
-
- newRootPRPtr.p->basePageId[0] = oldRootPRPtr.i;
- newRootPRPtr.p->parentPtr = RNIL;
- newRootPRPtr.p->startRange[0] = 0;
- newRootPRPtr.p->endRange[0] = regFragPtr->nextStartRange - 1;
- newRootPRPtr.p->type[0] = ZNON_LEAF;
- newRootPRPtr.p->startRange[1] = regFragPtr->nextStartRange;
- newRootPRPtr.p->endRange[1] = regFragPtr->nextStartRange - 1;
- newRootPRPtr.p->type[1] = ZNON_LEAF;
- newRootPRPtr.p->currentIndexPos = 1;
- foundPageRangePtr = newRootPRPtr;
- break;
- } else {
- jam();
- ptrCheckGuard(parentPageRangePtr, cnoOfPageRangeRec, pageRange);
- if (parentPageRangePtr.p->currentIndexPos < 3) {
- jam();
-
- if (c_noOfFreePageRanges < tiprNoLevels)
- {
- jam();
- return RNIL;
- }//if
-
-/* ---------------------------------------------------------------- */
-/* WE HAVE FOUND AN EMPTY ENTRY IN A PAGE RANGE RECORD. */
-/* ALLOCATE A NEW PAGE RANGE RECORD, FILL IN THE START RANGE, */
-/* ALLOCATE A NEW PAGE RANGE RECORD AND UPDATE THE POINTERS */
-/* ---------------------------------------------------------------- */
- parentPageRangePtr.p->currentIndexPos++;
- parentPageRangePtr.p->startRange[parentPageRangePtr.p->currentIndexPos] = regFragPtr->nextStartRange;
- parentPageRangePtr.p->endRange[parentPageRangePtr.p->currentIndexPos] = regFragPtr->nextStartRange - 1;
- parentPageRangePtr.p->type[parentPageRangePtr.p->currentIndexPos] = ZNON_LEAF;
- foundPageRangePtr = parentPageRangePtr;
- break;
- } else {
- jam();
- ndbrequire(parentPageRangePtr.p->currentIndexPos == 3);
-/* ---------------------------------------------------------------- */
-/* THE PAGE RANGE RECORD WAS FULL. FIND THE PARENT RECORD */
-/* AND INCREASE THE NUMBER OF LEVELS WE HAVE TRAVERSED */
-/* GOING UP THE TREE. */
-/* ---------------------------------------------------------------- */
- tiprNoLevels++;
- }//if
- }//if
- }//while
-/* ---------------------------------------------------------------- */
-/* REMEMBER THE ERROR LEVEL IN CASE OF ALLOCATION ERRORS */
-/* ---------------------------------------------------------------- */
- PageRangePtr newPageRangePtr;
- PageRangePtr prevPageRangePtr;
- prevPageRangePtr = foundPageRangePtr;
- if (c_noOfFreePageRanges < tiprNoLevels) {
- jam();
- return RNIL;
- }//if
-/* ---------------------------------------------------------------- */
-/* NOW WE HAVE PERFORMED THE SEARCH UPWARDS AND FILLED IN THE */
-/* PROPER FIELDS IN THE PAGE RANGE RECORD WHERE SOME SPACE */
-/* WAS FOUND. THE NEXT STEP IS TO ALLOCATE PAGE RANGES SO */
-/* THAT WE KEEP THE B-TREE BALANCED. THE NEW PAGE RANGE */
-/* ARE ALSO PROPERLY UPDATED ON THE PATH TO THE LEAF LEVEL. */
-/* ---------------------------------------------------------------- */
- while (true) {
- jam();
- seizePagerange(newPageRangePtr);
- tiprNoLevels--;
- ndbrequire(prevPageRangePtr.p->currentIndexPos < 4);
- prevPageRangePtr.p->basePageId[prevPageRangePtr.p->currentIndexPos] = newPageRangePtr.i;
- newPageRangePtr.p->parentPtr = prevPageRangePtr.i;
- newPageRangePtr.p->currentIndexPos = 0;
- if (tiprNoLevels > 0) {
- jam();
- newPageRangePtr.p->startRange[0] = regFragPtr->nextStartRange;
- newPageRangePtr.p->endRange[0] = regFragPtr->nextStartRange - 1;
- newPageRangePtr.p->type[0] = ZNON_LEAF;
- prevPageRangePtr = newPageRangePtr;
- } else {
- jam();
- break;
- }//if
- }//while
- return newPageRangePtr.i;
-}//Dbtup::leafPageRangeFull()
-
-void Dbtup::releasePagerange(PageRangePtr regPRPtr)
-{
- regPRPtr.p->nextFree = cfirstfreerange;
- cfirstfreerange = regPRPtr.i;
- c_noOfFreePageRanges++;
-}//Dbtup::releasePagerange()
-
-void Dbtup::seizePagerange(PageRangePtr& regPageRangePtr)
-{
- regPageRangePtr.i = cfirstfreerange;
- ptrCheckGuard(regPageRangePtr, cnoOfPageRangeRec, pageRange);
- cfirstfreerange = regPageRangePtr.p->nextFree;
- regPageRangePtr.p->nextFree = RNIL;
- regPageRangePtr.p->currentIndexPos = 0;
- regPageRangePtr.p->parentPtr = RNIL;
- for (Uint32 i = 0; i < 4; i++) {
- regPageRangePtr.p->startRange[i] = 1;
- regPageRangePtr.p->endRange[i] = 0;
- regPageRangePtr.p->type[i] = ZNON_LEAF;
- regPageRangePtr.p->basePageId[i] = (Uint32)-1;
- }//for
- c_noOfFreePageRanges--;
-}//Dbtup::seizePagerange()
-
-void Dbtup::errorHandler(Uint32 errorCode)
-{
- switch (errorCode) {
- case 0:
- jam();
- break;
- case 1:
- jam();
- break;
- case 2:
- jam();
- break;
- default:
- jam();
- }
- ndbrequire(false);
-}//Dbtup::errorHandler()
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
deleted file mode 100644
index 1a027315060..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ /dev/null
@@ -1,1687 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_ROUTINES_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <AttributeDescriptor.hpp>
-#include "AttributeOffset.hpp"
-#include <AttributeHeader.hpp>
-
-void
-Dbtup::setUpQueryRoutines(Tablerec *regTabPtr)
-{
- Uint32 startDescriptor= regTabPtr->tabDescriptor;
- ndbrequire((startDescriptor + (regTabPtr->m_no_of_attributes << ZAD_LOG_SIZE))
- <= cnoOfTabDescrRec);
- for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++) {
- Uint32 attrDescrStart= startDescriptor + (i << ZAD_LOG_SIZE);
- Uint32 attrDescr= tableDescriptor[attrDescrStart].tabDescr;
- Uint32 attrOffset= tableDescriptor[attrDescrStart + 1].tabDescr;
- if (!AttributeDescriptor::getDynamic(attrDescr)) {
- if (AttributeDescriptor::getArrayType(attrDescr) == NDB_ARRAYTYPE_FIXED){
- if (!AttributeDescriptor::getNullable(attrDescr)) {
- if (AttributeDescriptor::getSize(attrDescr) == 0){
- jam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNotNULL;
- } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 4) {
- jam();
- regTabPtr->readFunctionArray[i]=
- &Dbtup::readFixedSizeTHOneWordNotNULL;
- regTabPtr->updateFunctionArray[i]=
- &Dbtup::updateFixedSizeTHOneWordNotNULL;
- } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 8) {
- jam();
- regTabPtr->readFunctionArray[i]=
- &Dbtup::readFixedSizeTHTwoWordNotNULL;
- regTabPtr->updateFunctionArray[i]=
- &Dbtup::updateFixedSizeTHTwoWordNotNULL;
- } else {
- jam();
- regTabPtr->readFunctionArray[i]=
- &Dbtup::readFixedSizeTHManyWordNotNULL;
- regTabPtr->updateFunctionArray[i]=
- &Dbtup::updateFixedSizeTHManyWordNotNULL;
- }
- // replace functions for char attribute
- if (AttributeOffset::getCharsetFlag(attrOffset)) {
- jam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNotNULL;
- }
- } else {
- if (AttributeDescriptor::getSize(attrDescr) == 0){
- jam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNULLable;
- } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 4){
- jam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHOneWordNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
- } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 8) {
- jam();
- regTabPtr->readFunctionArray[i]=
- &Dbtup::readFixedSizeTHTwoWordNULLable;
- regTabPtr->updateFunctionArray[i]=
- &Dbtup::updateFixedSizeTHManyWordNULLable;
- } else {
- jam();
- regTabPtr->readFunctionArray[i]=
- &Dbtup::readFixedSizeTHManyWordNULLable;
- regTabPtr->updateFunctionArray[i]=
- &Dbtup::updateFixedSizeTHManyWordNULLable;
- }
- // replace functions for char attribute
- if (AttributeOffset::getCharsetFlag(attrOffset)) {
- jam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
- }
- }
- } else {
- if (!AttributeDescriptor::getNullable(attrDescr)) {
- regTabPtr->readFunctionArray[i]=
- &Dbtup::readVarSizeNotNULL;
- regTabPtr->updateFunctionArray[i]=
- &Dbtup::updateVarSizeNotNULL;
- } else {
- regTabPtr->readFunctionArray[i]=
- &Dbtup::readVarSizeNULLable;
- regTabPtr->updateFunctionArray[i]=
- &Dbtup::updateVarSizeNULLable;
- }
- }
- if(AttributeDescriptor::getDiskBased(attrDescr))
- {
- // array initializer crashes gcc-2.95.3
- ReadFunction r[6];
- {
- r[0] = &Dbtup::readDiskBitsNotNULL;
- r[1] = &Dbtup::readDiskBitsNULLable;
- r[2] = &Dbtup::readDiskFixedSizeNotNULL;
- r[3] = &Dbtup::readDiskFixedSizeNULLable;
- r[4] = &Dbtup::readDiskVarSizeNULLable;
- r[5] = &Dbtup::readDiskVarSizeNotNULL;
- }
- UpdateFunction u[6];
- {
- u[0] = &Dbtup::updateDiskBitsNotNULL;
- u[1] = &Dbtup::updateDiskBitsNULLable;
- u[2] = &Dbtup::updateDiskFixedSizeNotNULL;
- u[3] = &Dbtup::updateDiskFixedSizeNULLable;
- u[4] = &Dbtup::updateDiskVarSizeNULLable;
- u[5] = &Dbtup::updateDiskVarSizeNotNULL;
- }
- Uint32 a=
- AttributeDescriptor::getArrayType(attrDescr) == NDB_ARRAYTYPE_FIXED ? 2 : 4;
-
- if(AttributeDescriptor::getSize(attrDescr) == 0)
- a= 0;
-
- Uint32 b=
- AttributeDescriptor::getNullable(attrDescr)? 1 : 0;
- regTabPtr->readFunctionArray[i]= r[a+b];
- regTabPtr->updateFunctionArray[i]= u[a+b];
- }
- } else {
- if (AttributeDescriptor::getArrayType(attrDescr) == NDB_ARRAYTYPE_FIXED){
- jam();
- regTabPtr->readFunctionArray[i]= &Dbtup::readDynFixedSize;
- regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynFixedSize;
- } else {
- regTabPtr->readFunctionArray[i]= &Dbtup::readDynVarSize;
- regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynVarSize;
- }
- }
- }
-}
-
-/* ---------------------------------------------------------------- */
-/* THIS ROUTINE IS USED TO READ A NUMBER OF ATTRIBUTES IN THE */
-/* DATABASE AND PLACE THE RESULT IN ATTRINFO RECORDS. */
-//
-// In addition to the parameters used in the call it also relies on the
-// following variables set-up properly.
-//
-// operPtr.p Operation record pointer
-// fragptr.p Fragment record pointer
-// tabptr.p Table record pointer
-
-// It requires the following fields in KeyReqStruct to be properly
-// filled in:
-// tuple_header Reference to the tuple
-// check_offset Record size
-// attr_descr Reference to the Table Descriptor for the table
-//
-// The read functions in addition expects that the following fields in
-// KeyReqStruct is set up:
-// out_buf_index Index for output buffer
-// max_read Size of output buffer
-// attr_descriptor Attribute Descriptor from where attribute size
-// can be read
-/* ---------------------------------------------------------------- */
-int Dbtup::readAttributes(KeyReqStruct *req_struct,
- const Uint32* inBuffer,
- Uint32 inBufLen,
- Uint32* outBuffer,
- Uint32 maxRead,
- bool xfrm_flag)
-{
- Uint32 attributeId, descr_index, tmpAttrBufIndex, inBufIndex;
- Uint32 attributeOffset;
- TableDescriptor* attr_descr;
- AttributeHeader* ahOut;
-
- Tablerec* const regTabPtr= tabptr.p;
- Uint32 numAttributes= regTabPtr->m_no_of_attributes;
-
- inBufIndex= 0;
- req_struct->out_buf_index= 0;
- req_struct->max_read= maxRead;
- req_struct->xfrm_flag= xfrm_flag;
- while (inBufIndex < inBufLen) {
- tmpAttrBufIndex= req_struct->out_buf_index;
- AttributeHeader ahIn(inBuffer[inBufIndex]);
- inBufIndex++;
- attributeId= ahIn.getAttributeId();
- descr_index= attributeId << ZAD_LOG_SIZE;
- jam();
-
- AttributeHeader::init(&outBuffer[tmpAttrBufIndex], attributeId, 0);
- ahOut= (AttributeHeader*)&outBuffer[tmpAttrBufIndex];
- req_struct->out_buf_index= tmpAttrBufIndex + 1;
- attr_descr= req_struct->attr_descr;
- if (attributeId < numAttributes) {
- attributeOffset= attr_descr[descr_index + 1].tabDescr;
- ReadFunction f= regTabPtr->readFunctionArray[attributeId];
- req_struct->attr_descriptor= attr_descr[descr_index].tabDescr;
- if ((this->*f)(outBuffer,
- req_struct,
- ahOut,
- attributeOffset)) {
- continue;
- } else {
- return -1;
- }
- } else if(attributeId & AttributeHeader::PSEUDO) {
- if (attributeId == AttributeHeader::ANY_VALUE)
- {
- jam();
- Uint32 RlogSize = req_struct->log_size;
- operPtr.p->m_any_value = inBuffer[inBufIndex];
- * (clogMemBuffer + RlogSize) = inBuffer[inBufIndex - 1];
- * (clogMemBuffer + RlogSize + 1) = inBuffer[inBufIndex];
- inBufIndex++;
- req_struct->out_buf_index = tmpAttrBufIndex;
- req_struct->log_size = RlogSize + 2;
- continue;
- }
- jam();
- Uint32 sz= read_pseudo(attributeId,
- req_struct,
- outBuffer+tmpAttrBufIndex+1);
- AttributeHeader::init(&outBuffer[tmpAttrBufIndex], attributeId, sz << 2);
- req_struct->out_buf_index= tmpAttrBufIndex + 1 + sz;
- } else {
- terrorCode = ZATTRIBUTE_ID_ERROR;
- return -1;
- }//if
- }//while
- return req_struct->out_buf_index;
-}
-
-bool
-Dbtup::readFixedSizeTHOneWordNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
- Uint32 indexBuf= req_struct->out_buf_index;
- Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
- Uint32 const wordRead= tuple_header[readOffset];
- Uint32 newIndexBuf= indexBuf + 1;
- Uint32 maxRead= req_struct->max_read;
-
- ndbrequire(readOffset < req_struct->check_offset[MM]);
- if (newIndexBuf <= maxRead) {
- jam();
- outBuffer[indexBuf]= wordRead;
- ahOut->setDataSize(1);
- req_struct->out_buf_index= newIndexBuf;
- return true;
- } else {
- jam();
- terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::readFixedSizeTHTwoWordNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
- Uint32 indexBuf= req_struct->out_buf_index;
- Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
- Uint32 const wordReadFirst= tuple_header[readOffset];
- Uint32 const wordReadSecond= tuple_header[readOffset + 1];
- Uint32 newIndexBuf= indexBuf + 2;
- Uint32 maxRead= req_struct->max_read;
-
- ndbrequire(readOffset + 1 < req_struct->check_offset[MM]);
- if (newIndexBuf <= maxRead) {
- jam();
- ahOut->setDataSize(2);
- outBuffer[indexBuf]= wordReadFirst;
- outBuffer[indexBuf + 1]= wordReadSecond;
- req_struct->out_buf_index= newIndexBuf;
- return true;
- } else {
- jam();
- terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Uint32 attrDescriptor= req_struct->attr_descriptor;
- Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
- Uint32 indexBuf= req_struct->out_buf_index;
- Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
- Uint32 attrNoOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 maxRead= req_struct->max_read;
- Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
-
- ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[MM]);
- if (! charsetFlag || ! req_struct->xfrm_flag) {
- Uint32 newIndexBuf = indexBuf + attrNoOfWords;
- if (newIndexBuf <= maxRead) {
- jam();
- ahOut->setByteSize(AttributeDescriptor::getSizeInBytes(attrDescriptor));
- MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
- &tuple_header[readOffset],
- attrNoOfWords);
- req_struct->out_buf_index = newIndexBuf;
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- }//if
- } else {
- jam();
- Tablerec* regTabPtr = tabptr.p;
- Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
- uchar* dstPtr = (uchar*)&outBuffer[indexBuf];
- const uchar* srcPtr = (uchar*)&tuple_header[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);
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- Uint32 dstLen = xmul * (srcBytes - lb);
- Uint32 maxIndexBuf = indexBuf + (dstLen >> 2);
- if (maxIndexBuf <= maxRead && ok) {
- jam();
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- int m = n;
- while ((m & 3) != 0) {
- dstPtr[m++] = 0;
- }
- ahOut->setByteSize(n);
- Uint32 newIndexBuf = indexBuf + (m >> 2);
- ndbrequire(newIndexBuf <= maxRead);
- req_struct->out_buf_index = newIndexBuf;
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- }
- }
- return false;
-}//Dbtup::readFixedSizeTHManyWordNotNULL()
-
-bool
-Dbtup::readFixedSizeTHOneWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- if (!nullFlagCheck(req_struct, attrDes2)) {
- jam();
- return readFixedSizeTHOneWordNotNULL(outBuffer,
- req_struct,
- ahOut,
- attrDes2);
- } else {
- jam();
- ahOut->setNULL();
- return true;
- }
-}
-
-bool
-Dbtup::readFixedSizeTHTwoWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- if (!nullFlagCheck(req_struct, attrDes2)) {
- jam();
- return readFixedSizeTHTwoWordNotNULL(outBuffer,
- req_struct,
- ahOut,
- attrDes2);
- } else {
- jam();
- ahOut->setNULL();
- return true;
- }
-}
-
-bool
-Dbtup::readFixedSizeTHManyWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- if (!nullFlagCheck(req_struct, attrDes2)) {
- jam();
- return readFixedSizeTHManyWordNotNULL(outBuffer,
- req_struct,
- ahOut,
- attrDes2);
- } else {
- jam();
- ahOut->setNULL();
- return true;
- }
-}
-
-bool
-Dbtup::readFixedSizeTHZeroWordNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- jam();
- if (nullFlagCheck(req_struct, attrDes2)) {
- jam();
- ahOut->setNULL();
- }
- return true;
-}
-
-bool
-Dbtup::nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2)
-{
- Tablerec* const regTabPtr= tabptr.p;
- Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
- Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
-
- return BitmaskImpl::get(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
-}
-
-bool
-Dbtup::disk_nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2)
-{
- Tablerec* const regTabPtr= tabptr.p;
- Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
- Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
-
- return BitmaskImpl::get(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
-}
-
-bool
-Dbtup::readVarSizeNotNULL(Uint32* out_buffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ah_out,
- Uint32 attr_des2)
-{
- Uint32 attr_descriptor, index_buf, var_index;
- Uint32 vsize_in_bytes, vsize_in_words, new_index, max_var_size;
- Uint32 var_attr_pos, max_read;
-
- Uint32 idx= req_struct->m_var_data[MM].m_var_len_offset;
- var_index= AttributeOffset::getOffset(attr_des2);
- Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attr_des2);
- var_attr_pos= req_struct->m_var_data[MM].m_offset_array_ptr[var_index];
- vsize_in_bytes= req_struct->m_var_data[MM].m_offset_array_ptr[var_index+idx] - var_attr_pos;
- attr_descriptor= req_struct->attr_descriptor;
- index_buf= req_struct->out_buf_index;
- max_var_size= AttributeDescriptor::getSizeInWords(attr_descriptor);
- max_read= req_struct->max_read;
- vsize_in_words= convert_byte_to_word_size(vsize_in_bytes);
- new_index= index_buf + vsize_in_words;
-
- ndbrequire(vsize_in_words <= max_var_size);
- if (! charsetFlag || ! req_struct->xfrm_flag)
- {
- if (new_index <= max_read) {
- jam();
- ah_out->setByteSize(vsize_in_bytes);
- out_buffer[index_buf + (vsize_in_bytes >> 2)] = 0;
- memcpy(out_buffer+index_buf,
- req_struct->m_var_data[MM].m_data_ptr+var_attr_pos,
- vsize_in_bytes);
- req_struct->out_buf_index= new_index;
- return true;
- }
- }
- else
- {
- jam();
- Tablerec* regTabPtr = tabptr.p;
- Uint32 maxBytes = AttributeDescriptor::getSizeInBytes(attr_descriptor);
- Uint32 srcBytes = vsize_in_bytes;
- uchar* dstPtr = (uchar*)(out_buffer+index_buf);
- const uchar* srcPtr = (uchar*)(req_struct->m_var_data[MM].m_data_ptr+var_attr_pos);
- Uint32 i = AttributeOffset::getCharsetPos(attr_des2);
- ndbrequire(i < regTabPtr->noOfCharsets);
- CHARSET_INFO* cs = regTabPtr->charsetArray[i];
- Uint32 typeId = AttributeDescriptor::getType(attr_descriptor);
- Uint32 lb, len;
- bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- // see comment in DbtcMain.cpp
- Uint32 dstLen = xmul * (maxBytes - lb);
- Uint32 maxIndexBuf = index_buf + (dstLen >> 2);
- if (maxIndexBuf <= max_read && ok) {
- jam();
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- int m = n;
- while ((m & 3) != 0) {
- dstPtr[m++] = 0;
- }
- ah_out->setByteSize(n);
- Uint32 newIndexBuf = index_buf + (m >> 2);
- ndbrequire(newIndexBuf <= max_read);
- req_struct->out_buf_index = newIndexBuf;
- return true;
- }
- }
- jam();
- terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
-}
-
-bool
-Dbtup::readVarSizeNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- if (!nullFlagCheck(req_struct, attrDes2)) {
- jam();
- return readVarSizeNotNULL(outBuffer,
- req_struct,
- ahOut,
- attrDes2);
- } else {
- jam();
- ahOut->setNULL();
- return true;
- }
-}
-
-bool
-Dbtup::readDynFixedSize(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- jam();
- terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}
-
-bool
-Dbtup::readDynVarSize(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- jam();
- terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readDynBigVarSize()
-
-bool
-Dbtup::readDiskFixedSizeNotNULL(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Uint32 attrDescriptor= req_struct->attr_descriptor;
- Uint32 *tuple_header= req_struct->m_disk_ptr->m_data;
- Uint32 indexBuf= req_struct->out_buf_index;
- Uint32 readOffset= AttributeOffset::getOffset(attrDes2);
- Uint32 attrNoOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 maxRead= req_struct->max_read;
- Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
-
- ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[DD]);
- if (! charsetFlag || ! req_struct->xfrm_flag) {
- Uint32 newIndexBuf = indexBuf + attrNoOfWords;
- if (newIndexBuf <= maxRead) {
- jam();
- ahOut->setByteSize(AttributeDescriptor::getSizeInBytes(attrDescriptor));
- MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
- &tuple_header[readOffset],
- attrNoOfWords);
- req_struct->out_buf_index = newIndexBuf;
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- }//if
- } else {
- jam();
- Tablerec* regTabPtr = tabptr.p;
- Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
- uchar* dstPtr = (uchar*)&outBuffer[indexBuf];
- const uchar* srcPtr = (uchar*)&tuple_header[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);
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- Uint32 dstLen = xmul * (srcBytes - lb);
- Uint32 maxIndexBuf = indexBuf + (dstLen >> 2);
- if (maxIndexBuf <= maxRead && ok) {
- jam();
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- int m = n;
- while ((m & 3) != 0) {
- dstPtr[m++] = 0;
- }
- ahOut->setByteSize(n);
- Uint32 newIndexBuf = indexBuf + (m >> 2);
- ndbrequire(newIndexBuf <= maxRead);
- req_struct->out_buf_index = newIndexBuf;
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- }
- }
- return false;
-}
-
-bool
-Dbtup::readDiskFixedSizeNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- if (!disk_nullFlagCheck(req_struct, attrDes2)) {
- jam();
- return readDiskFixedSizeNotNULL(outBuffer,
- req_struct,
- ahOut,
- attrDes2);
- } else {
- jam();
- ahOut->setNULL();
- return true;
- }
-}
-
-bool
-Dbtup::readDiskVarSizeNotNULL(Uint32* out_buffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ah_out,
- Uint32 attr_des2)
-{
- Uint32 attr_descriptor, index_buf, var_index;
- Uint32 vsize_in_bytes, vsize_in_words, new_index, max_var_size;
- Uint32 var_attr_pos, max_read;
-
- Uint32 idx= req_struct->m_var_data[DD].m_var_len_offset;
- var_index= AttributeOffset::getOffset(attr_des2);
- var_attr_pos= req_struct->m_var_data[DD].m_offset_array_ptr[var_index];
- vsize_in_bytes= req_struct->m_var_data[DD].m_offset_array_ptr[var_index+idx] - var_attr_pos;
- attr_descriptor= req_struct->attr_descriptor;
- index_buf= req_struct->out_buf_index;
- max_var_size= AttributeDescriptor::getSizeInWords(attr_descriptor);
- max_read= req_struct->max_read;
- vsize_in_words= convert_byte_to_word_size(vsize_in_bytes);
- new_index= index_buf + vsize_in_words;
-
- ndbrequire(vsize_in_words <= max_var_size);
- if (new_index <= max_read) {
- jam();
- ah_out->setByteSize(vsize_in_bytes);
- memcpy(out_buffer+index_buf,
- req_struct->m_var_data[DD].m_data_ptr+var_attr_pos,
- vsize_in_bytes);
- req_struct->out_buf_index= new_index;
- return true;
- } else {
- jam();
- terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::readDiskVarSizeNULLable(Uint32* outBuffer,
- KeyReqStruct *req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- if (!disk_nullFlagCheck(req_struct, attrDes2)) {
- jam();
- return readDiskVarSizeNotNULL(outBuffer,
- req_struct,
- ahOut,
- attrDes2);
- } else {
- jam();
- 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 */
-/* CALLED SEVERAL TIMES FROM THE INTERPRETER. */
-// In addition to the parameters used in the call it also relies on the
-// following variables set-up properly.
-//
-// operPtr.p Operation record pointer
-// tabptr.p Table record pointer
-/* ---------------------------------------------------------------------- */
-int Dbtup::updateAttributes(KeyReqStruct *req_struct,
- Uint32* inBuffer,
- Uint32 inBufLen)
-{
- Tablerec* const regTabPtr= tabptr.p;
- Operationrec* const regOperPtr= operPtr.p;
- Uint32 numAttributes= regTabPtr->m_no_of_attributes;
- TableDescriptor *attr_descr= req_struct->attr_descr;
-
- Uint32 inBufIndex= 0;
- req_struct->in_buf_index= 0;
- req_struct->in_buf_len= inBufLen;
-
- while (inBufIndex < inBufLen) {
- AttributeHeader ahIn(inBuffer[inBufIndex]);
- Uint32 attributeId= ahIn.getAttributeId();
- Uint32 attrDescriptorIndex= attributeId << ZAD_LOG_SIZE;
- if (likely(attributeId < numAttributes)) {
- Uint32 attrDescriptor= attr_descr[attrDescriptorIndex].tabDescr;
- Uint32 attributeOffset= attr_descr[attrDescriptorIndex + 1].tabDescr;
- if ((AttributeDescriptor::getPrimaryKey(attrDescriptor)) &&
- (regOperPtr->op_struct.op_type != ZINSERT)) {
- if (checkUpdateOfPrimaryKey(req_struct,
- &inBuffer[inBufIndex],
- regTabPtr)) {
- jam();
- terrorCode= ZTRY_UPDATE_PRIMARY_KEY;
- return -1;
- }
- }
- UpdateFunction f= regTabPtr->updateFunctionArray[attributeId];
- jam();
- req_struct->attr_descriptor= attrDescriptor;
- req_struct->changeMask.set(attributeId);
- if (attributeId >= 64) {
- if (req_struct->max_attr_id_updated < attributeId) {
- Uint32 no_changed_attrs= req_struct->no_changed_attrs;
- req_struct->max_attr_id_updated= attributeId;
- req_struct->no_changed_attrs= no_changed_attrs + 1;
- }
- }
- if ((this->*f)(inBuffer,
- req_struct,
- attributeOffset)) {
- inBufIndex= req_struct->in_buf_index;
- continue;
- } else {
- jam();
- return -1;
- }
- }
- else if(attributeId == AttributeHeader::DISK_REF)
- {
- jam();
- Uint32 sz= ahIn.getDataSize();
- ndbrequire(sz == 2);
- req_struct->m_tuple_ptr->m_header_bits |= Tuple_header::DISK_PART;
- memcpy(req_struct->m_tuple_ptr->get_disk_ref_ptr(regTabPtr),
- inBuffer+inBufIndex+1, sz << 2);
- inBufIndex += 1 + sz;
- req_struct->in_buf_index = inBufIndex;
- }
- else if(attributeId == AttributeHeader::ANY_VALUE)
- {
- jam();
- Uint32 sz= ahIn.getDataSize();
- ndbrequire(sz == 1);
- regOperPtr->m_any_value = * (inBuffer + inBufIndex + 1);
- inBufIndex += 1 + sz;
- req_struct->in_buf_index = inBufIndex;
- }
- else
- {
- jam();
- terrorCode= ZATTRIBUTE_ID_ERROR;
- return -1;
- }
- }
- return 0;
-}
-
-bool
-Dbtup::checkUpdateOfPrimaryKey(KeyReqStruct* req_struct,
- Uint32* updateBuffer,
- Tablerec* const regTabPtr)
-{
- Uint32 keyReadBuffer[MAX_KEY_SIZE_IN_WORDS];
- TableDescriptor* attr_descr = req_struct->attr_descr;
- AttributeHeader ahIn(*updateBuffer);
- Uint32 attributeId = ahIn.getAttributeId();
- Uint32 attrDescriptorIndex = attributeId << ZAD_LOG_SIZE;
- Uint32 attrDescriptor = attr_descr[attrDescriptorIndex].tabDescr;
- Uint32 attributeOffset = attr_descr[attrDescriptorIndex + 1].tabDescr;
-
- Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
- Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attributeOffset);
- if (charsetFlag) {
- 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;
- }
-
- ReadFunction f = regTabPtr->readFunctionArray[attributeId];
-
- AttributeHeader attributeHeader(attributeId, 0);
- req_struct->out_buf_index = 0;
- req_struct->max_read = MAX_KEY_SIZE_IN_WORDS;
- req_struct->attr_descriptor = attrDescriptor;
-
- bool tmp = req_struct->xfrm_flag;
- req_struct->xfrm_flag = true;
- ndbrequire((this->*f)(&keyReadBuffer[0],
- req_struct,
- &attributeHeader,
- attributeOffset));
- req_struct->xfrm_flag = tmp;
-
- ndbrequire(req_struct->out_buf_index == attributeHeader.getDataSize());
- if (ahIn.getDataSize() != attributeHeader.getDataSize()) {
- jam();
- return true;
- }
- if (memcmp(&keyReadBuffer[0],
- &updateBuffer[1],
- req_struct->out_buf_index << 2) != 0) {
- jam();
- return true;
- }
- return false;
-}
-
-bool
-Dbtup::updateFixedSizeTHOneWordNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Uint32 indexBuf= req_struct->in_buf_index;
- Uint32 inBufLen= req_struct->in_buf_len;
- Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 newIndex= indexBuf + 2;
- Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
- ndbrequire(updateOffset < req_struct->check_offset[MM]);
-
- if (newIndex <= inBufLen) {
- Uint32 updateWord= inBuffer[indexBuf + 1];
- if (!nullIndicator) {
- jam();
- req_struct->in_buf_index= newIndex;
- tuple_header[updateOffset]= updateWord;
- return true;
- } else {
- jam();
- terrorCode= ZNOT_NULL_ATTR;
- return false;
- }
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
- return true;
-}
-
-bool
-Dbtup::updateFixedSizeTHTwoWordNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Uint32 indexBuf= req_struct->in_buf_index;
- Uint32 inBufLen= req_struct->in_buf_len;
- Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 newIndex= indexBuf + 3;
- Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
- ndbrequire((updateOffset + 1) < req_struct->check_offset[MM]);
-
- if (newIndex <= inBufLen) {
- Uint32 updateWord1= inBuffer[indexBuf + 1];
- Uint32 updateWord2= inBuffer[indexBuf + 2];
- if (!nullIndicator) {
- jam();
- req_struct->in_buf_index= newIndex;
- tuple_header[updateOffset]= updateWord1;
- tuple_header[updateOffset + 1]= updateWord2;
- return true;
- } else {
- jam();
- terrorCode= ZNOT_NULL_ATTR;
- return false;
- }
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Uint32 attrDescriptor= req_struct->attr_descriptor;
- Uint32 indexBuf= req_struct->in_buf_index;
- Uint32 inBufLen= req_struct->in_buf_len;
- Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
- Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
-
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 newIndex= indexBuf + noOfWords + 1;
- Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
- ndbrequire((updateOffset + noOfWords - 1) < req_struct->check_offset[MM]);
-
- if (newIndex <= inBufLen) {
- if (!nullIndicator) {
- jam();
- if (charsetFlag) {
- jam();
- 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[indexBuf + 1];
- Uint32 lb, len;
- if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
- jam();
- 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) {
- jam();
- terrorCode = ZINVALID_CHAR_FORMAT;
- return false;
- }
- }
- req_struct->in_buf_index= newIndex;
- MEMCOPY_NO_WORDS(&tuple_header[updateOffset],
- &inBuffer[indexBuf + 1],
- noOfWords);
-
- return true;
- } else {
- jam();
- terrorCode= ZNOT_NULL_ATTR;
- return false;
- }
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::updateFixedSizeTHManyWordNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr= tabptr.p;
- AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
-
- if (!nullIndicator) {
- jam();
- BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
- return updateFixedSizeTHManyWordNotNULL(inBuffer,
- req_struct,
- attrDes2);
- } else {
- Uint32 newIndex= req_struct->in_buf_index + 1;
- if (newIndex <= req_struct->in_buf_len) {
- BitmaskImpl::set(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
- jam();
- req_struct->in_buf_index= newIndex;
- return true;
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
- }
-}
-
-bool
-Dbtup::updateVarSizeNotNULL(Uint32* in_buffer,
- KeyReqStruct *req_struct,
- Uint32 attr_des2)
-{
- Uint32 attr_descriptor, index_buf, in_buf_len, var_index, null_ind;
- Uint32 vsize_in_words, new_index, max_var_size;
- Uint32 var_attr_pos;
- char *var_data_start;
- Uint16 *vpos_array;
-
- attr_descriptor= req_struct->attr_descriptor;
- index_buf= req_struct->in_buf_index;
- in_buf_len= req_struct->in_buf_len;
- var_index= AttributeOffset::getOffset(attr_des2);
- AttributeHeader ahIn(in_buffer[index_buf]);
- null_ind= ahIn.isNULL();
- Uint32 size_in_bytes = ahIn.getByteSize();
- vsize_in_words= (size_in_bytes + 3) >> 2;
- max_var_size= AttributeDescriptor::getSizeInBytes(attr_descriptor);
- new_index= index_buf + vsize_in_words + 1;
- vpos_array= req_struct->m_var_data[MM].m_offset_array_ptr;
- Uint32 idx= req_struct->m_var_data[MM].m_var_len_offset;
- Uint32 check_offset= req_struct->m_var_data[MM].m_max_var_offset;
-
- if (new_index <= in_buf_len && vsize_in_words <= max_var_size) {
- if (!null_ind) {
- jam();
- var_attr_pos= vpos_array[var_index];
- var_data_start= req_struct->m_var_data[MM].m_data_ptr;
- vpos_array[var_index+idx]= var_attr_pos+size_in_bytes;
- req_struct->in_buf_index= new_index;
-
- ndbrequire(var_attr_pos+size_in_bytes <= check_offset);
- memcpy(var_data_start+var_attr_pos, &in_buffer[index_buf + 1],
- size_in_bytes);
- return true;
- } else {
- jam();
- terrorCode= ZNOT_NULL_ATTR;
- return false;
- }
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
- return false;
-}
-
-bool
-Dbtup::updateVarSizeNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr= tabptr.p;
- AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
- Uint32 idx= req_struct->m_var_data[MM].m_var_len_offset;
-
- if (!nullIndicator) {
- jam();
- BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
- return updateVarSizeNotNULL(inBuffer,
- req_struct,
- attrDes2);
- } else {
- Uint32 newIndex= req_struct->in_buf_index + 1;
- Uint32 var_index= AttributeOffset::getOffset(attrDes2);
- Uint32 var_pos= req_struct->var_pos_array[var_index];
- if (newIndex <= req_struct->in_buf_len) {
- jam();
- BitmaskImpl::set(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
- req_struct->var_pos_array[var_index+idx]= var_pos;
- req_struct->in_buf_index= newIndex;
- return true;
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
- }
-}
-
-bool
-Dbtup::updateDynFixedSize(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- jam();
- terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}
-
-bool
-Dbtup::updateDynVarSize(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- jam();
- terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}
-
-Uint32
-Dbtup::read_pseudo(Uint32 attrId,
- KeyReqStruct *req_struct,
- Uint32* outBuffer)
-{
- Uint32 tmp[sizeof(SignalHeader)+25];
- Signal * signal = (Signal*)&tmp;
- switch(attrId){
- case AttributeHeader::FRAGMENT:
- * outBuffer = fragptr.p->fragmentId;
- return 1;
- case AttributeHeader::FRAGMENT_FIXED_MEMORY:
- {
- Uint64 tmp= fragptr.p->noOfPages;
- tmp*= 32768;
- memcpy(outBuffer,&tmp,8);
- }
- return 2;
- case AttributeHeader::FRAGMENT_VARSIZED_MEMORY:
- {
- Uint64 tmp= fragptr.p->noOfVarPages;
- tmp*= 32768;
- memcpy(outBuffer,&tmp,8);
- }
- return 2;
- case AttributeHeader::ROW_SIZE:
- * outBuffer = tabptr.p->m_offsets[MM].m_fix_header_size << 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_PSEUDO_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_PSEUDO_REQ, signal, 2);
- outBuffer[0] = signal->theData[0];
- return 1;
- case AttributeHeader::DISK_REF:
- {
- Uint32 *ref= req_struct->m_tuple_ptr->get_disk_ref_ptr(tabptr.p);
- outBuffer[0] = ref[0];
- outBuffer[1] = ref[1];
- return 2;
- }
- case AttributeHeader::RECORDS_IN_RANGE:
- signal->theData[0] = operPtr.p->userpointer;
- signal->theData[1] = attrId;
-
- EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
- outBuffer[0] = signal->theData[0];
- outBuffer[1] = signal->theData[1];
- outBuffer[2] = signal->theData[2];
- outBuffer[3] = signal->theData[3];
- return 4;
- case AttributeHeader::ROWID:
- outBuffer[0] = req_struct->frag_page_id;
- outBuffer[1] = operPtr.p->m_tuple_location.m_page_idx;
- return 2;
- case AttributeHeader::ROW_GCI:
- if (tabptr.p->m_bits & Tablerec::TR_RowGCI)
- {
- Uint64 tmp = * req_struct->m_tuple_ptr->get_mm_gci(tabptr.p);
- memcpy(outBuffer, &tmp, sizeof(tmp));
- return 2;
- }
- return 0;
- case AttributeHeader::COPY_ROWID:
- outBuffer[0] = operPtr.p->m_copy_tuple_location.m_page_no;
- outBuffer[1] = operPtr.p->m_copy_tuple_location.m_page_idx;
- return 2;
- default:
- return 0;
- }
-}
-
-bool
-Dbtup::readBitsNotNULL(Uint32* outBuffer,
- KeyReqStruct* req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
- Uint32 indexBuf = req_struct->out_buf_index;
- Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
- Uint32 maxRead = req_struct->max_read;
- Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
- if (newIndexBuf <= maxRead) {
- jam();
- ahOut->setDataSize((bitCount + 31) >> 5);
- req_struct->out_buf_index = newIndexBuf;
-
- BitmaskImpl::getField(regTabPtr->m_offsets[MM].m_null_words, bits, pos,
- bitCount, outBuffer+indexBuf);
-
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }//if
-}
-
-bool
-Dbtup::readBitsNULLable(Uint32* outBuffer,
- KeyReqStruct* req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
-
- Uint32 indexBuf = req_struct->out_buf_index;
- Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
- Uint32 maxRead = req_struct->max_read;
- Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
-
- if(BitmaskImpl::get(regTabPtr->m_offsets[MM].m_null_words, bits, pos))
- {
- jam();
- ahOut->setNULL();
- return true;
- }
-
- if (newIndexBuf <= maxRead) {
- jam();
- ahOut->setDataSize((bitCount + 31) >> 5);
- req_struct->out_buf_index = newIndexBuf;
- BitmaskImpl::getField(regTabPtr->m_offsets[MM].m_null_words, bits, pos+1,
- bitCount, outBuffer+indexBuf);
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }//if
-}
-
-bool
-Dbtup::updateBitsNotNULL(Uint32* inBuffer,
- KeyReqStruct* req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 indexBuf = req_struct->in_buf_index;
- Uint32 inBufLen = req_struct->in_buf_len;
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 nullIndicator = ahIn.isNULL();
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
- Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
- Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
-
- if (newIndex <= inBufLen) {
- if (!nullIndicator) {
- BitmaskImpl::setField(regTabPtr->m_offsets[MM].m_null_words, bits, pos,
- bitCount, inBuffer+indexBuf+1);
- req_struct->in_buf_index = newIndex;
- return true;
- } else {
- jam();
- terrorCode = ZNOT_NULL_ATTR;
- return false;
- }//if
- } else {
- jam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
- return false;
- }//if
- return true;
-}
-
-bool
-Dbtup::updateBitsNULLable(Uint32* inBuffer,
- KeyReqStruct* req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 indexBuf = req_struct->in_buf_index;
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 nullIndicator = ahIn.isNULL();
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
- Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
-
- if (!nullIndicator) {
- BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
- BitmaskImpl::setField(regTabPtr->m_offsets[MM].m_null_words, bits, pos+1,
- bitCount, inBuffer+indexBuf+1);
-
- Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
- req_struct->in_buf_index = newIndex;
- return true;
- } else {
- Uint32 newIndex = indexBuf + 1;
- if (newIndex <= req_struct->in_buf_len)
- {
- jam();
- BitmaskImpl::set(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
-
- req_struct->in_buf_index = newIndex;
- return true;
- } else {
- jam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
- return false;
- }//if
- }//if
-}
-
-bool
-Dbtup::updateDiskFixedSizeNotNULL(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Uint32 attrDescriptor= req_struct->attr_descriptor;
- Uint32 indexBuf= req_struct->in_buf_index;
- Uint32 inBufLen= req_struct->in_buf_len;
- Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
- Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
-
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 newIndex= indexBuf + noOfWords + 1;
- Uint32 *tuple_header= req_struct->m_disk_ptr->m_data;
- ndbrequire((updateOffset + noOfWords - 1) < req_struct->check_offset[DD]);
-
- if (newIndex <= inBufLen) {
- if (!nullIndicator) {
- jam();
- if (charsetFlag) {
- jam();
- 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[indexBuf + 1];
- Uint32 lb, len;
- if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
- jam();
- 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) {
- jam();
- terrorCode = ZINVALID_CHAR_FORMAT;
- return false;
- }
- }
- req_struct->in_buf_index= newIndex;
- MEMCOPY_NO_WORDS(&tuple_header[updateOffset],
- &inBuffer[indexBuf + 1],
- noOfWords);
- return true;
- } else {
- jam();
- terrorCode= ZNOT_NULL_ATTR;
- return false;
- }
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::updateDiskFixedSizeNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr= tabptr.p;
- AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
-
- if (!nullIndicator) {
- jam();
- BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
- return updateDiskFixedSizeNotNULL(inBuffer,
- req_struct,
- attrDes2);
- } else {
- Uint32 newIndex= req_struct->in_buf_index + 1;
- if (newIndex <= req_struct->in_buf_len) {
- BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
- jam();
- req_struct->in_buf_index= newIndex;
- return true;
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
- }
-}
-
-bool
-Dbtup::updateDiskVarSizeNotNULL(Uint32* in_buffer,
- KeyReqStruct *req_struct,
- Uint32 attr_des2)
-{
- Uint32 attr_descriptor, index_buf, in_buf_len, var_index, null_ind;
- Uint32 vsize_in_words, new_index, max_var_size;
- Uint32 var_attr_pos;
- char *var_data_start;
- Uint16 *vpos_array;
-
- attr_descriptor= req_struct->attr_descriptor;
- index_buf= req_struct->in_buf_index;
- in_buf_len= req_struct->in_buf_len;
- var_index= AttributeOffset::getOffset(attr_des2);
- AttributeHeader ahIn(in_buffer[index_buf]);
- null_ind= ahIn.isNULL();
- Uint32 size_in_bytes = ahIn.getByteSize();
- vsize_in_words= (size_in_bytes + 3) >> 2;
- max_var_size= AttributeDescriptor::getSizeInBytes(attr_descriptor);
- new_index= index_buf + vsize_in_words + 1;
- vpos_array= req_struct->m_var_data[DD].m_offset_array_ptr;
- Uint32 idx= req_struct->m_var_data[DD].m_var_len_offset;
- Uint32 check_offset= req_struct->m_var_data[DD].m_max_var_offset;
-
- if (new_index <= in_buf_len && vsize_in_words <= max_var_size) {
- if (!null_ind) {
- jam();
- var_attr_pos= vpos_array[var_index];
- var_data_start= req_struct->m_var_data[DD].m_data_ptr;
- vpos_array[var_index+idx]= var_attr_pos+size_in_bytes;
- req_struct->in_buf_index= new_index;
-
- ndbrequire(var_attr_pos+size_in_bytes <= check_offset);
- memcpy(var_data_start+var_attr_pos, &in_buffer[index_buf + 1],
- size_in_bytes);
- return true;
- } else {
- jam();
- terrorCode= ZNOT_NULL_ATTR;
- return false;
- }
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
- return false;
-}
-
-bool
-Dbtup::updateDiskVarSizeNULLable(Uint32* inBuffer,
- KeyReqStruct *req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr= tabptr.p;
- AttributeHeader ahIn(inBuffer[req_struct->in_buf_index]);
- Uint32 nullIndicator= ahIn.isNULL();
- Uint32 pos= AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
- Uint32 idx= req_struct->m_var_data[DD].m_var_len_offset;
-
- if (!nullIndicator) {
- jam();
- BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
- return updateDiskVarSizeNotNULL(inBuffer,
- req_struct,
- attrDes2);
- } else {
- Uint32 newIndex= req_struct->in_buf_index + 1;
- Uint32 var_index= AttributeOffset::getOffset(attrDes2);
- Uint32 var_pos= req_struct->var_pos_array[var_index];
- if (newIndex <= req_struct->in_buf_len) {
- jam();
- BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
- req_struct->var_pos_array[var_index+idx]= var_pos;
- req_struct->in_buf_index= newIndex;
- return true;
- } else {
- jam();
- terrorCode= ZAI_INCONSISTENCY_ERROR;
- return false;
- }
- }
-}
-
-bool
-Dbtup::readDiskBitsNotNULL(Uint32* outBuffer,
- KeyReqStruct* req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
- Uint32 indexBuf = req_struct->out_buf_index;
- Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
- Uint32 maxRead = req_struct->max_read;
- Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
- if (newIndexBuf <= maxRead) {
- jam();
- ahOut->setDataSize((bitCount + 31) >> 5);
- req_struct->out_buf_index = newIndexBuf;
-
- BitmaskImpl::getField(regTabPtr->m_offsets[DD].m_null_words, bits, pos,
- bitCount, outBuffer+indexBuf);
-
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }//if
-}
-
-bool
-Dbtup::readDiskBitsNULLable(Uint32* outBuffer,
- KeyReqStruct* req_struct,
- AttributeHeader* ahOut,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
-
- Uint32 indexBuf = req_struct->out_buf_index;
- Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
- Uint32 maxRead = req_struct->max_read;
- Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
-
- if(BitmaskImpl::get(regTabPtr->m_offsets[DD].m_null_words, bits, pos))
- {
- jam();
- ahOut->setNULL();
- return true;
- }
-
- if (newIndexBuf <= maxRead) {
- jam();
- ahOut->setDataSize((bitCount + 31) >> 5);
- req_struct->out_buf_index = newIndexBuf;
- BitmaskImpl::getField(regTabPtr->m_offsets[DD].m_null_words, bits, pos+1,
- bitCount, outBuffer+indexBuf);
- return true;
- } else {
- jam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }//if
-}
-
-bool
-Dbtup::updateDiskBitsNotNULL(Uint32* inBuffer,
- KeyReqStruct* req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 indexBuf = req_struct->in_buf_index;
- Uint32 inBufLen = req_struct->in_buf_len;
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 nullIndicator = ahIn.isNULL();
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
- Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
- Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
-
- if (newIndex <= inBufLen) {
- if (!nullIndicator) {
- BitmaskImpl::setField(regTabPtr->m_offsets[DD].m_null_words, bits, pos,
- bitCount, inBuffer+indexBuf+1);
- req_struct->in_buf_index = newIndex;
- return true;
- } else {
- jam();
- terrorCode = ZNOT_NULL_ATTR;
- return false;
- }//if
- } else {
- jam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
- return false;
- }//if
- return true;
-}
-
-bool
-Dbtup::updateDiskBitsNULLable(Uint32* inBuffer,
- KeyReqStruct* req_struct,
- Uint32 attrDes2)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 indexBuf = req_struct->in_buf_index;
- AttributeHeader ahIn(inBuffer[indexBuf]);
- Uint32 nullIndicator = ahIn.isNULL();
- Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount =
- AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
- Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
-
- if (!nullIndicator) {
- BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
- BitmaskImpl::setField(regTabPtr->m_offsets[DD].m_null_words, bits, pos+1,
- bitCount, inBuffer+indexBuf+1);
-
- Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
- req_struct->in_buf_index = newIndex;
- return true;
- } else {
- Uint32 newIndex = indexBuf + 1;
- if (newIndex <= req_struct->in_buf_len)
- {
- jam();
- BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
-
- req_struct->in_buf_index = newIndex;
- return true;
- } else {
- jam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
- return false;
- }//if
- }//if
-}
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
deleted file mode 100644
index 572be897a13..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
+++ /dev/null
@@ -1,1209 +0,0 @@
-/* Copyright (c) 2003, 2005-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_SCAN_CPP
-#include "Dbtup.hpp"
-#include <signaldata/AccScan.hpp>
-#include <signaldata/NextScan.hpp>
-#include <signaldata/AccLock.hpp>
-#include <md5_hash.hpp>
-
-#undef jam
-#undef jamEntry
-#define jam() { jamLine(32000 + __LINE__); }
-#define jamEntry() { jamEntryLine(32000 + __LINE__); }
-
-#ifdef VM_TRACE
-#define dbg(x) globalSignalLoggers.log x
-#else
-#define dbg(x)
-#endif
-
-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 fragment
- TablerecPtr tablePtr;
- tablePtr.i = req->tableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- FragrecordPtr fragPtr;
- Uint32 fragId = req->fragmentNo;
- fragPtr.i = RNIL;
- getFragmentrec(fragPtr, fragId, tablePtr.p);
- ndbrequire(fragPtr.i != RNIL);
- Fragrecord& frag = *fragPtr.p;
- // flags
- Uint32 bits = 0;
-
-
- if (AccScanReq::getLcpScanFlag(req->requestInfo))
- {
- jam();
- bits |= ScanOp::SCAN_LCP;
- c_scanOpPool.getPtr(scanPtr, c_lcp_scan_op);
- }
- else
- {
- // seize from pool and link to per-fragment list
- LocalDLList<ScanOp> list(c_scanOpPool, frag.m_scanList);
- if (! list.seize(scanPtr)) {
- jam();
- break;
- }
- }
-
- if (!AccScanReq::getNoDiskScanFlag(req->requestInfo)
- && tablePtr.p->m_no_of_disk_attributes)
- {
- bits |= ScanOp::SCAN_DD;
- }
-
- bool mm = (bits & ScanOp::SCAN_DD);
- if (tablePtr.p->m_attributes[mm].m_no_of_varsize > 0) {
- bits |= ScanOp::SCAN_VS;
-
- // disk pages have fixed page format
- ndbrequire(! (bits & ScanOp::SCAN_DD));
- }
- if (! AccScanReq::getReadCommittedFlag(req->requestInfo)) {
- if (AccScanReq::getLockMode(req->requestInfo) == 0)
- bits |= ScanOp::SCAN_LOCK_SH;
- else
- bits |= ScanOp::SCAN_LOCK_EX;
- }
-
- if (AccScanReq::getNRScanFlag(req->requestInfo))
- {
- jam();
- bits |= ScanOp::SCAN_NR;
- scanPtr.p->m_endPage = req->maxPage;
- if (req->maxPage != RNIL && req->maxPage > frag.noOfPages)
- {
- ndbout_c("%u %u endPage: %u (noOfPages: %u)",
- tablePtr.i, fragId,
- req->maxPage, fragPtr.p->noOfPages);
- }
- }
- else
- {
- jam();
- scanPtr.p->m_endPage = RNIL;
- }
-
- if (AccScanReq::getLcpScanFlag(req->requestInfo))
- {
- jam();
- ndbrequire((bits & ScanOp::SCAN_DD) == 0);
- ndbrequire((bits & ScanOp::SCAN_LOCK) == 0);
- }
-
- // set up scan op
- new (scanPtr.p) ScanOp();
- ScanOp& scan = *scanPtr.p;
- scan.m_state = ScanOp::First;
- scan.m_bits = bits;
- scan.m_userPtr = req->senderData;
- scan.m_userRef = req->senderRef;
- scan.m_tableId = tablePtr.i;
- scan.m_fragId = frag.fragmentId;
- scan.m_fragPtrI = fragPtr.i;
- scan.m_transId1 = req->transId1;
- scan.m_transId2 = req->transId2;
- scan.m_savePointId = req->savePointId;
-
- // 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;
- switch (req->scanFlag) {
- case NextScanReq::ZSCAN_NEXT:
- jam();
- break;
- case NextScanReq::ZSCAN_NEXT_COMMIT:
- jam();
- case NextScanReq::ZSCAN_COMMIT:
- jam();
- if ((scan.m_bits & ScanOp::SCAN_LOCK) != 0) {
- jam();
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Unlock;
- lockReq->accOpPtr = req->accOperationPtr;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
- signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- removeAccLockOp(scan, req->accOperationPtr);
- }
- if (req->scanFlag == NextScanReq::ZSCAN_COMMIT) {
- 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();
- if (scan.m_bits & ScanOp::SCAN_LOCK_WAIT) {
- jam();
- ndbrequire(scan.m_accLockOp != RNIL);
- // use ACC_ABORTCONF to flush out any reply in job buffer
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::AbortWithConf;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
- signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_state = ScanOp::Aborting;
- return;
- }
- if (scan.m_state == ScanOp::Locked) {
- jam();
- ndbrequire(scan.m_accLockOp != RNIL);
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
- signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOp = RNIL;
- }
- scan.m_state = ScanOp::Aborting;
- 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;
- // fragment
- FragrecordPtr fragPtr;
- fragPtr.i = scan.m_fragPtrI;
- 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_bits & ScanOp::SCAN_LOCK_WAIT) {
- jam();
- // LQH asks if we are waiting for lock and we tell it to ask again
- NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
- conf->scanPtr = scan.m_userPtr;
- conf->accOperationPtr = RNIL; // no tuple returned
- conf->fragId = frag.fragmentId;
- unsigned signalLength = 3;
- // if TC has ordered scan close, it will be detected here
- sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
- signal, signalLength, JBB);
- return; // stop
- }
- if (scan.m_state == ScanOp::First) {
- jam();
- scanFirst(signal, scanPtr);
- }
- if (scan.m_state == ScanOp::Next) {
- jam();
- bool immediate = scanNext(signal, scanPtr);
- if (! immediate) {
- jam();
- // time-slicing via TUP or PGMAN
- return;
- }
- }
- scanReply(signal, scanPtr);
-}
-
-void
-Dbtup::scanReply(Signal* signal, ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
- FragrecordPtr fragPtr;
- fragPtr.i = scan.m_fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- Fragrecord& frag = *fragPtr.p;
- // for reading tuple key in Current state
- Uint32* pkData = (Uint32*)c_dataBuffer;
- unsigned pkSize = 0;
- if (scan.m_state == ScanOp::Current) {
- // found an entry to return
- jam();
- ndbrequire(scan.m_accLockOp == RNIL);
- if (scan.m_bits & ScanOp::SCAN_LOCK) {
- jam();
- // read tuple key - use TUX routine
- const ScanPos& pos = scan.m_scanPos;
- const Local_key& key_mm = pos.m_key_mm;
- int ret = tuxReadPk(fragPtr.i, pos.m_realpid_mm, key_mm.m_page_idx,
- pkData, true);
- ndbrequire(ret > 0);
- pkSize = ret;
- dbg((DBTUP, "PK size=%d data=%08x", pkSize, pkData[0]));
- // get read lock or exclusive lock
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = (scan.m_bits & ScanOp::SCAN_LOCK_SH) ?
- AccLockReq::LockShared : AccLockReq::LockExclusive;
- lockReq->accOpPtr = RNIL;
- lockReq->userPtr = scanPtr.i;
- lockReq->userRef = reference();
- lockReq->tableId = scan.m_tableId;
- lockReq->fragId = frag.fragmentId;
- lockReq->fragPtrI = RNIL; // no cached frag ptr yet
- lockReq->hashValue = md5_hash((Uint64*)pkData, pkSize);
- lockReq->tupAddr = key_mm.ref();
- lockReq->transId1 = scan.m_transId1;
- lockReq->transId2 = scan.m_transId2;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
- signal, AccLockReq::LockSignalLength);
- jamEntry();
- switch (lockReq->returnCode) {
- case AccLockReq::Success:
- jam();
- scan.m_state = ScanOp::Locked;
- scan.m_accLockOp = lockReq->accOpPtr;
- break;
- case AccLockReq::IsBlocked:
- jam();
- // normal lock wait
- scan.m_state = ScanOp::Blocked;
- scan.m_bits |= ScanOp::SCAN_LOCK_WAIT;
- scan.m_accLockOp = lockReq->accOpPtr;
- // LQH will wake us up
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = true;
- EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
- jamEntry();
- return;
- break;
- case AccLockReq::Refused:
- jam();
- // we cannot see deleted tuple (assert only)
- ndbassert(false);
- // skip it
- scan.m_state = ScanOp::Next;
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = true;
- EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
- jamEntry();
- return;
- break;
- case AccLockReq::NoFreeOp:
- jam();
- // max ops should depend on max scans (assert only)
- ndbassert(false);
- // stay in Current state
- scan.m_state = ScanOp::Current;
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = true;
- EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
- jamEntry();
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }
- } else {
- scan.m_state = ScanOp::Locked;
- }
- }
-
- if (scan.m_state == ScanOp::Locked) {
- // we have lock or do not need one
- jam();
- // conf signal
- NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
- conf->scanPtr = scan.m_userPtr;
- // the lock is passed to LQH
- Uint32 accLockOp = scan.m_accLockOp;
- if (accLockOp != RNIL) {
- scan.m_accLockOp = RNIL;
- // remember it until LQH unlocks it
- addAccLockOp(scan, accLockOp);
- } else {
- ndbrequire(! (scan.m_bits & ScanOp::SCAN_LOCK));
- // operation RNIL in LQH would signal no tuple returned
- accLockOp = (Uint32)-1;
- }
- const ScanPos& pos = scan.m_scanPos;
- conf->accOperationPtr = accLockOp;
- conf->fragId = frag.fragmentId;
- conf->localKey[0] = pos.m_key_mm.ref();
- conf->localKey[1] = 0;
- conf->localKeyLength = 1;
- unsigned signalLength = 6;
- if (scan.m_bits & ScanOp::SCAN_LOCK) {
- sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
- signal, signalLength, JBB);
- } else {
- 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);
-}
-
-/*
- * Lock succeeded (after delay) in ACC. If the lock is for current
- * entry, set state to Locked. If the lock is for an entry we were
- * moved away from, simply unlock it. Finally, if we are closing the
- * scan, do nothing since we have already sent an abort request.
- */
-void
-Dbtup::execACCKEYCONF(Signal* signal)
-{
- jamEntry();
- ScanOpPtr scanPtr;
- scanPtr.i = signal->theData[0];
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
- ndbrequire(scan.m_bits & ScanOp::SCAN_LOCK_WAIT && scan.m_accLockOp != RNIL);
- scan.m_bits &= ~ ScanOp::SCAN_LOCK_WAIT;
- if (scan.m_state == ScanOp::Blocked) {
- // the lock wait was for current entry
- jam();
- scan.m_state = ScanOp::Locked;
- // LQH has the ball
- return;
- }
- if (scan.m_state != ScanOp::Aborting) {
- // we were moved, release lock
- jam();
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOp = RNIL;
- // LQH has the ball
- return;
- }
- // lose the lock
- scan.m_accLockOp = RNIL;
- // continue at ACC_ABORTCONF
-}
-
-/*
- * Lock failed (after delay) in ACC. Probably means somebody ahead of
- * us in lock queue deleted the tuple.
- */
-void
-Dbtup::execACCKEYREF(Signal* signal)
-{
- jamEntry();
- ScanOpPtr scanPtr;
- scanPtr.i = signal->theData[0];
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
- ndbrequire(scan.m_bits & ScanOp::SCAN_LOCK_WAIT && scan.m_accLockOp != RNIL);
- scan.m_bits &= ~ ScanOp::SCAN_LOCK_WAIT;
- if (scan.m_state != ScanOp::Aborting) {
- jam();
- // release the operation
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOp = RNIL;
- // scan position should already have been moved (assert only)
- if (scan.m_state == ScanOp::Blocked) {
- jam();
- //ndbassert(false);
- if (scan.m_bits & ScanOp::SCAN_NR)
- {
- jam();
- scan.m_state = ScanOp::Next;
- scan.m_scanPos.m_get = ScanPos::Get_tuple;
- ndbout_c("Ignoring scan.m_state == ScanOp::Blocked, refetch");
- }
- else
- {
- jam();
- scan.m_state = ScanOp::Next;
- ndbout_c("Ignoring scan.m_state == ScanOp::Blocked");
- }
- }
- // LQH has the ball
- return;
- }
- // lose the lock
- scan.m_accLockOp = RNIL;
- // continue at ACC_ABORTCONF
-}
-
-/*
- * Received when scan is closing. This signal arrives after any
- * ACCKEYCON or ACCKEYREF which may have been in job buffer.
- */
-void
-Dbtup::execACC_ABORTCONF(Signal* signal)
-{
- jamEntry();
- ScanOpPtr scanPtr;
- scanPtr.i = signal->theData[0];
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
- ndbrequire(scan.m_state == ScanOp::Aborting);
- // most likely we are still in lock wait
- if (scan.m_bits & ScanOp::SCAN_LOCK_WAIT) {
- jam();
- scan.m_bits &= ~ ScanOp::SCAN_LOCK_WAIT;
- scan.m_accLockOp = RNIL;
- }
- scanClose(signal, scanPtr);
-}
-
-void
-Dbtup::scanFirst(Signal*, ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
- ScanPos& pos = scan.m_scanPos;
- Local_key& key = pos.m_key;
- const Uint32 bits = scan.m_bits;
- // fragment
- FragrecordPtr fragPtr;
- fragPtr.i = scan.m_fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- Fragrecord& frag = *fragPtr.p;
- // in the future should not pre-allocate pages
- if (frag.noOfPages == 0 && ((bits & ScanOp::SCAN_NR) == 0)) {
- jam();
- scan.m_state = ScanOp::Last;
- return;
- }
- if (! (bits & ScanOp::SCAN_DD)) {
- key.m_file_no = ZNIL;
- key.m_page_no = 0;
- pos.m_get = ScanPos::Get_page_mm;
- // for MM scan real page id is cached for efficiency
- pos.m_realpid_mm = RNIL;
- } else {
- Disk_alloc_info& alloc = frag.m_disk_alloc_info;
- // for now must check disk part explicitly
- if (alloc.m_extent_list.firstItem == RNIL) {
- jam();
- scan.m_state = ScanOp::Last;
- return;
- }
- pos.m_extent_info_ptr_i = alloc.m_extent_list.firstItem;
- Extent_info* ext = c_extent_pool.getPtr(pos.m_extent_info_ptr_i);
- key.m_file_no = ext->m_key.m_file_no;
- key.m_page_no = ext->m_first_page_no;
- pos.m_get = ScanPos::Get_page_dd;
- }
- key.m_page_idx = 0;
- // let scanNext() do the work
- scan.m_state = ScanOp::Next;
-}
-
-bool
-Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
- ScanPos& pos = scan.m_scanPos;
- Local_key& key = pos.m_key;
- const Uint32 bits = scan.m_bits;
- // table
- TablerecPtr tablePtr;
- tablePtr.i = scan.m_tableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- Tablerec& table = *tablePtr.p;
- // fragment
- FragrecordPtr fragPtr;
- fragPtr.i = scan.m_fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- Fragrecord& frag = *fragPtr.p;
- // tuple found
- Tuple_header* th = 0;
- Uint32 thbits = 0;
- Uint32 loop_count = 0;
- Uint32 scanGCI = scanPtr.p->m_scanGCI;
- Uint32 foundGCI;
-
- const bool mm = (bits & ScanOp::SCAN_DD);
- const bool lcp = (bits & ScanOp::SCAN_LCP);
-
- Uint32 lcp_list = fragPtr.p->m_lcp_keep_list;
- Uint32 size = table.m_offsets[mm].m_fix_header_size;
-
- if (lcp && lcp_list != RNIL)
- goto found_lcp_keep;
-
- switch(pos.m_get){
- case ScanPos::Get_next_tuple:
- case ScanPos::Get_next_tuple_fs:
- jam();
- key.m_page_idx += size;
- // fall through
- case ScanPos::Get_tuple:
- case ScanPos::Get_tuple_fs:
- jam();
- /**
- * We need to refetch page after timeslice
- */
- pos.m_get = ScanPos::Get_page;
- break;
- default:
- break;
- }
-
- while (true) {
- switch (pos.m_get) {
- case ScanPos::Get_next_page:
- // move to next page
- jam();
- {
- if (! (bits & ScanOp::SCAN_DD))
- pos.m_get = ScanPos::Get_next_page_mm;
- else
- pos.m_get = ScanPos::Get_next_page_dd;
- }
- continue;
- case ScanPos::Get_page:
- // get real page
- jam();
- {
- if (! (bits & ScanOp::SCAN_DD))
- pos.m_get = ScanPos::Get_page_mm;
- else
- pos.m_get = ScanPos::Get_page_dd;
- }
- continue;
- case ScanPos::Get_next_page_mm:
- // move to next logical TUP page
- jam();
- {
- key.m_page_no++;
- if (key.m_page_no >= frag.noOfPages) {
- jam();
-
- if ((bits & ScanOp::SCAN_NR) && (scan.m_endPage != RNIL))
- {
- jam();
- if (key.m_page_no < scan.m_endPage)
- {
- jam();
- ndbout_c("scanning page %u", key.m_page_no);
- goto cont;
- }
- }
- // no more pages, scan ends
- pos.m_get = ScanPos::Get_undef;
- scan.m_state = ScanOp::Last;
- return true;
- }
- cont:
- key.m_page_idx = 0;
- pos.m_get = ScanPos::Get_page_mm;
- // clear cached value
- pos.m_realpid_mm = RNIL;
- }
- /*FALLTHRU*/
- case ScanPos::Get_page_mm:
- // get TUP real page
- jam();
- {
- if (pos.m_realpid_mm == RNIL) {
- jam();
- if (key.m_page_no < frag.noOfPages)
- pos.m_realpid_mm = getRealpid(fragPtr.p, key.m_page_no);
- else
- {
- ndbassert(bits & ScanOp::SCAN_NR);
- goto nopage;
- }
- }
- PagePtr pagePtr;
- c_page_pool.getPtr(pagePtr, pos.m_realpid_mm);
-
- if (pagePtr.p->page_state == ZEMPTY_MM) {
- // skip empty page
- jam();
- if (! (bits & ScanOp::SCAN_NR))
- {
- pos.m_get = ScanPos::Get_next_page_mm;
- break; // incr loop count
- }
- else
- {
- jam();
- pos.m_realpid_mm = RNIL;
- }
- }
- nopage:
- pos.m_page = pagePtr.p;
- pos.m_get = ScanPos::Get_tuple;
- }
- continue;
- case ScanPos::Get_next_page_dd:
- // move to next disk page
- jam();
- {
- Disk_alloc_info& alloc = frag.m_disk_alloc_info;
- Local_fragment_extent_list list(c_extent_pool, alloc.m_extent_list);
- Ptr<Extent_info> ext_ptr;
- c_extent_pool.getPtr(ext_ptr, pos.m_extent_info_ptr_i);
- Extent_info* ext = ext_ptr.p;
- key.m_page_no++;
- if (key.m_page_no >= ext->m_first_page_no + alloc.m_extent_size) {
- // no more pages in this extent
- jam();
- if (! list.next(ext_ptr)) {
- // no more extents, scan ends
- jam();
- pos.m_get = ScanPos::Get_undef;
- scan.m_state = ScanOp::Last;
- return true;
- } else {
- // move to next extent
- jam();
- pos.m_extent_info_ptr_i = ext_ptr.i;
- ext = c_extent_pool.getPtr(pos.m_extent_info_ptr_i);
- key.m_file_no = ext->m_key.m_file_no;
- key.m_page_no = ext->m_first_page_no;
- }
- }
- key.m_page_idx = 0;
- pos.m_get = ScanPos::Get_page_dd;
- /*
- read ahead for scan in disk order
- do read ahead every 8:th page
- */
- if ((bits & ScanOp::SCAN_DD) &&
- (((key.m_page_no - ext->m_first_page_no) & 7) == 0))
- {
- jam();
- // initialize PGMAN request
- Page_cache_client::Request preq;
- preq.m_page = pos.m_key;
- preq.m_callback = TheNULLCallback;
-
- // set maximum read ahead
- Uint32 read_ahead = m_max_page_read_ahead;
-
- while (true)
- {
- // prepare page read ahead in current extent
- Uint32 page_no = preq.m_page.m_page_no;
- Uint32 page_no_limit = page_no + read_ahead;
- Uint32 limit = ext->m_first_page_no + alloc.m_extent_size;
- if (page_no_limit > limit)
- {
- jam();
- // read ahead crosses extent, set limit for this extent
- read_ahead = page_no_limit - limit;
- page_no_limit = limit;
- // and make sure we only read one extra extent next time around
- if (read_ahead > alloc.m_extent_size)
- read_ahead = alloc.m_extent_size;
- }
- else
- {
- jam();
- read_ahead = 0; // no more to read ahead after this
- }
- // do read ahead pages for this extent
- while (page_no < page_no_limit)
- {
- // page request to PGMAN
- jam();
- preq.m_page.m_page_no = page_no;
- int flags = 0;
- // ignore result
- m_pgman.get_page(signal, preq, flags);
- jamEntry();
- page_no++;
- }
- if (!read_ahead || !list.next(ext_ptr))
- {
- // no more extents after this or read ahead done
- jam();
- break;
- }
- // move to next extent and initialize PGMAN request accordingly
- Extent_info* ext = c_extent_pool.getPtr(ext_ptr.i);
- preq.m_page.m_file_no = ext->m_key.m_file_no;
- preq.m_page.m_page_no = ext->m_first_page_no;
- }
- } // if ScanOp::SCAN_DD read ahead
- }
- /*FALLTHRU*/
- case ScanPos::Get_page_dd:
- // get global page in PGMAN cache
- jam();
- {
- // check if page is un-allocated or empty
- if (likely(! (bits & ScanOp::SCAN_NR)))
- {
- Tablespace_client tsman(signal, c_tsman,
- frag.fragTableId,
- frag.fragmentId,
- frag.m_tablespace_id);
- unsigned uncommitted, committed;
- uncommitted = committed = ~(unsigned)0;
- int ret = tsman.get_page_free_bits(&key, &uncommitted, &committed);
- ndbrequire(ret == 0);
- if (committed == 0 && uncommitted == 0) {
- // skip empty page
- jam();
- pos.m_get = ScanPos::Get_next_page_dd;
- break; // incr loop count
- }
- }
- // page request to PGMAN
- Page_cache_client::Request preq;
- preq.m_page = pos.m_key;
- preq.m_callback.m_callbackData = scanPtr.i;
- preq.m_callback.m_callbackFunction =
- safe_cast(&Dbtup::disk_page_tup_scan_callback);
- int flags = 0;
- int res = m_pgman.get_page(signal, preq, flags);
- jamEntry();
- if (res == 0) {
- jam();
- // request queued
- pos.m_get = ScanPos::Get_tuple;
- return false;
- }
- ndbrequire(res > 0);
- pos.m_page = (Page*)m_pgman.m_ptr.p;
- }
- pos.m_get = ScanPos::Get_tuple;
- continue;
- // get tuple
- // move to next tuple
- case ScanPos::Get_next_tuple:
- case ScanPos::Get_next_tuple_fs:
- // move to next fixed size tuple
- jam();
- {
- key.m_page_idx += size;
- pos.m_get = ScanPos::Get_tuple_fs;
- }
- /*FALLTHRU*/
- case ScanPos::Get_tuple:
- case ScanPos::Get_tuple_fs:
- // get fixed size tuple
- jam();
- {
- Fix_page* page = (Fix_page*)pos.m_page;
- if (key.m_page_idx + size <= Fix_page::DATA_WORDS)
- {
- pos.m_get = ScanPos::Get_next_tuple_fs;
- th = (Tuple_header*)&page->m_data[key.m_page_idx];
-
- if (likely(! (bits & ScanOp::SCAN_NR)))
- {
- jam();
- thbits = th->m_header_bits;
- if (! (thbits & Tuple_header::FREE))
- {
- goto found_tuple;
- }
- }
- else
- {
- if (pos.m_realpid_mm == RNIL)
- {
- jam();
- foundGCI = 0;
- goto found_deleted_rowid;
- }
- thbits = th->m_header_bits;
- if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI ||
- foundGCI == 0)
- {
- if (! (thbits & Tuple_header::FREE))
- {
- jam();
- goto found_tuple;
- }
- else
- {
- goto found_deleted_rowid;
- }
- }
- else if (thbits != Fix_page::FREE_RECORD &&
- th->m_operation_ptr_i != RNIL)
- {
- jam();
- goto found_tuple; // Locked tuple...
- // skip free tuple
- }
- }
- } else {
- jam();
- // no more tuples on this page
- pos.m_get = ScanPos::Get_next_page;
- }
- }
- break; // incr loop count
- found_tuple:
- // found possible tuple to return
- jam();
- {
- // caller has already set pos.m_get to next tuple
- if (! (bits & ScanOp::SCAN_LCP && thbits & Tuple_header::LCP_SKIP)) {
- Local_key& key_mm = pos.m_key_mm;
- if (! (bits & ScanOp::SCAN_DD)) {
- key_mm = pos.m_key;
- // real page id is already set
- } else {
- key_mm.assref(th->m_base_record_ref);
- // recompute for each disk tuple
- pos.m_realpid_mm = getRealpid(fragPtr.p, key_mm.m_page_no);
- }
- // TUPKEYREQ handles savepoint stuff
- scan.m_state = ScanOp::Current;
- return true;
- } else {
- jam();
- // clear it so that it will show up in next LCP
- th->m_header_bits = thbits & ~(Uint32)Tuple_header::LCP_SKIP;
- if (tablePtr.p->m_bits & Tablerec::TR_Checksum) {
- jam();
- setChecksum(th, tablePtr.p);
- }
- }
- }
- break;
- found_deleted_rowid:
- jam();
- {
- ndbassert(bits & ScanOp::SCAN_NR);
- Local_key& key_mm = pos.m_key_mm;
- if (! (bits & ScanOp::SCAN_DD)) {
- key_mm = pos.m_key;
- // caller has already set pos.m_get to next tuple
- // real page id is already set
- } else {
- key_mm.assref(th->m_base_record_ref);
- // recompute for each disk tuple
- pos.m_realpid_mm = getRealpid(fragPtr.p, key_mm.m_page_no);
-
- Fix_page *mmpage = (Fix_page*)c_page_pool.getPtr(pos.m_realpid_mm);
- th = (Tuple_header*)(mmpage->m_data + key_mm.m_page_idx);
- if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI ||
- foundGCI == 0)
- {
- if (! (thbits & Tuple_header::FREE))
- break;
- }
- }
-
- NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
- conf->scanPtr = scan.m_userPtr;
- conf->accOperationPtr = RNIL;
- conf->fragId = frag.fragmentId;
- conf->localKey[0] = pos.m_key_mm.ref();
- conf->localKey[1] = 0;
- conf->localKeyLength = 1;
- conf->gci = foundGCI;
- Uint32 blockNo = refToBlock(scan.m_userRef);
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 7);
- jamEntry();
-
- // TUPKEYREQ handles savepoint stuff
- loop_count = 32;
- scan.m_state = ScanOp::Next;
- return false;
- }
- break; // incr loop count
- default:
- ndbrequire(false);
- break;
- }
- if (++loop_count >= 32)
- break;
- }
- // TODO: at drop table we have to flush and terminate these
- jam();
- signal->theData[0] = ZTUP_SCAN;
- signal->theData[1] = scanPtr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return false;
-
-found_lcp_keep:
- Local_key tmp;
- tmp.assref(lcp_list);
- tmp.m_page_no = getRealpid(fragPtr.p, tmp.m_page_no);
-
- Ptr<Page> pagePtr;
- c_page_pool.getPtr(pagePtr, tmp.m_page_no);
- Tuple_header* ptr = (Tuple_header*)
- ((Fix_page*)pagePtr.p)->get_ptr(tmp.m_page_idx, 0);
- Uint32 headerbits = ptr->m_header_bits;
- ndbrequire(headerbits & Tuple_header::LCP_KEEP);
-
- Uint32 next = ptr->m_operation_ptr_i;
- ptr->m_operation_ptr_i = RNIL;
- ptr->m_header_bits = headerbits & ~(Uint32)Tuple_header::FREE;
-
- if (tablePtr.p->m_bits & Tablerec::TR_Checksum) {
- jam();
- setChecksum(ptr, tablePtr.p);
- }
-
- NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
- conf->scanPtr = scan.m_userPtr;
- conf->accOperationPtr = (Uint32)-1;
- conf->fragId = frag.fragmentId;
- conf->localKey[0] = lcp_list;
- conf->localKey[1] = 0;
- conf->localKeyLength = 1;
- conf->gci = 0;
- Uint32 blockNo = refToBlock(scan.m_userRef);
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 7);
-
- fragPtr.p->m_lcp_keep_list = next;
- ptr->m_header_bits |= Tuple_header::FREED; // RESTORE free flag
- if (headerbits & Tuple_header::FREED)
- {
- if (tablePtr.p->m_attributes[MM].m_no_of_varsize)
- {
- jam();
- free_var_rec(fragPtr.p, tablePtr.p, &tmp, pagePtr);
- } else {
- jam();
- free_fix_rec(fragPtr.p, tablePtr.p, &tmp, (Fix_page*)pagePtr.p);
- }
- }
- return false;
-}
-
-void
-Dbtup::scanCont(Signal* signal, ScanOpPtr scanPtr)
-{
- bool immediate = scanNext(signal, scanPtr);
- if (! immediate) {
- jam();
- // time-slicing again
- return;
- }
- scanReply(signal, scanPtr);
-}
-
-void
-Dbtup::disk_page_tup_scan_callback(Signal* signal, Uint32 scanPtrI, Uint32 page_i)
-{
- ScanOpPtr scanPtr;
- c_scanOpPool.getPtr(scanPtr, scanPtrI);
- ScanOp& scan = *scanPtr.p;
- ScanPos& pos = scan.m_scanPos;
- // get cache page
- Ptr<GlobalPage> gptr;
- m_global_page_pool.getPtr(gptr, page_i);
- pos.m_page = (Page*)gptr.p;
- // continue
- scanCont(signal, scanPtr);
-}
-
-void
-Dbtup::scanClose(Signal* signal, ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
- ndbrequire(! (scan.m_bits & ScanOp::SCAN_LOCK_WAIT) && scan.m_accLockOp == RNIL);
- // unlock all not unlocked by LQH
- LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
- ScanLockPtr lockPtr;
- while (list.first(lockPtr)) {
- jam();
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = lockPtr.p->m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- list.release(lockPtr);
- }
- // send conf
- 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::addAccLockOp(ScanOp& scan, Uint32 accLockOp)
-{
- LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
- ScanLockPtr lockPtr;
-#ifdef VM_TRACE
- list.first(lockPtr);
- while (lockPtr.i != RNIL) {
- ndbrequire(lockPtr.p->m_accLockOp != accLockOp);
- list.next(lockPtr);
- }
-#endif
- bool ok = list.seize(lockPtr);
- ndbrequire(ok);
- lockPtr.p->m_accLockOp = accLockOp;
-}
-
-void
-Dbtup::removeAccLockOp(ScanOp& scan, Uint32 accLockOp)
-{
- LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
- ScanLockPtr lockPtr;
- list.first(lockPtr);
- while (lockPtr.i != RNIL) {
- if (lockPtr.p->m_accLockOp == accLockOp) {
- jam();
- break;
- }
- list.next(lockPtr);
- }
- ndbrequire(lockPtr.i != RNIL);
- list.release(lockPtr);
-}
-
-void
-Dbtup::releaseScanOp(ScanOpPtr& scanPtr)
-{
- FragrecordPtr fragPtr;
- fragPtr.i = scanPtr.p->m_fragPtrI;
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
-
- if(scanPtr.p->m_bits & ScanOp::SCAN_LCP)
- {
- jam();
- fragPtr.p->m_lcp_scan_op = RNIL;
- scanPtr.p->m_fragPtrI = RNIL;
- }
- else
- {
- jam();
- LocalDLList<ScanOp> list(c_scanOpPool, fragPtr.p->m_scanList);
- list.release(scanPtr);
- }
-}
-
-void
-Dbtup::execLCP_FRAG_ORD(Signal* signal)
-{
- LcpFragOrd* req= (LcpFragOrd*)signal->getDataPtr();
-
- TablerecPtr tablePtr;
- tablePtr.i = req->tableId;
- ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
-
- if (tablePtr.p->m_no_of_disk_attributes)
- {
- jam();
- FragrecordPtr fragPtr;
- Uint32 fragId = req->fragmentId;
- fragPtr.i = RNIL;
- getFragmentrec(fragPtr, fragId, tablePtr.p);
- ndbrequire(fragPtr.i != RNIL);
- Fragrecord& frag = *fragPtr.p;
-
- ndbrequire(frag.m_lcp_scan_op == RNIL && c_lcp_scan_op != RNIL);
- frag.m_lcp_scan_op = c_lcp_scan_op;
- ScanOpPtr scanPtr;
- c_scanOpPool.getPtr(scanPtr, frag.m_lcp_scan_op);
- ndbrequire(scanPtr.p->m_fragPtrI == RNIL);
- scanPtr.p->m_fragPtrI = fragPtr.i;
-
- scanFirst(signal, scanPtr);
- scanPtr.p->m_state = ScanOp::First;
- }
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp
deleted file mode 100644
index 63f73593ff7..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright (c) 2003, 2005, 2007, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_STORE_PROC_DEF_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-/* ------------ADD/DROP STORED PROCEDURE MODULE ------------------- */
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::execSTORED_PROCREQ(Signal* signal)
-{
- OperationrecPtr regOperPtr;
- TablerecPtr regTabPtr;
- jamEntry();
- regOperPtr.i = signal->theData[0];
- c_operation_pool.getPtr(regOperPtr);
- regTabPtr.i = signal->theData[1];
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
- Uint32 requestInfo = signal->theData[3];
- TransState trans_state= get_trans_state(regOperPtr.p);
- ndbrequire(trans_state == TRANS_IDLE ||
- ((trans_state == TRANS_ERROR_WAIT_STORED_PROCREQ) &&
- (requestInfo == ZSTORED_PROCEDURE_DELETE)));
- ndbrequire(regTabPtr.p->tableStatus == DEFINED);
- switch (requestInfo) {
- case ZSCAN_PROCEDURE:
- jam();
- scanProcedure(signal,
- regOperPtr.p,
- signal->theData[4]);
- break;
- case ZCOPY_PROCEDURE:
- jam();
- copyProcedure(signal, regTabPtr, regOperPtr.p);
- break;
- case ZSTORED_PROCEDURE_DELETE:
- jam();
- deleteScanProcedure(signal, regOperPtr.p);
- break;
- default:
- ndbrequire(false);
- }//switch
-}//Dbtup::execSTORED_PROCREQ()
-
-void Dbtup::deleteScanProcedure(Signal* signal,
- Operationrec* regOperPtr)
-{
- StoredProcPtr storedPtr;
- Uint32 storedProcId = signal->theData[4];
- c_storedProcPool.getPtr(storedPtr, storedProcId);
- ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
- ndbrequire(storedPtr.p->storedCounter == 0);
- Uint32 firstAttrinbuf = storedPtr.p->storedLinkFirst;
- storedPtr.p->storedCode = ZSTORED_PROCEDURE_FREE;
- storedPtr.p->storedLinkFirst = RNIL;
- storedPtr.p->storedLinkLast = RNIL;
- storedPtr.p->storedProcLength = 0;
- c_storedProcPool.release(storedPtr);
- freeAttrinbufrec(firstAttrinbuf);
- regOperPtr->currentAttrinbufLen = 0;
- set_trans_state(regOperPtr, TRANS_IDLE);
- signal->theData[0] = regOperPtr->userpointer;
- signal->theData[1] = storedProcId;
- sendSignal(DBLQH_REF, GSN_STORED_PROCCONF, signal, 2, JBB);
-}//Dbtup::deleteScanProcedure()
-
-void Dbtup::scanProcedure(Signal* signal,
- Operationrec* regOperPtr,
- Uint32 lenAttrInfo)
-{
-//--------------------------------------------------------
-// We introduce the maxCheck so that there is always one
-// stored procedure entry free for copy procedures. Thus
-// no amount of scanning can cause problems for the node
-// recovery functionality.
-//--------------------------------------------------------
- StoredProcPtr storedPtr;
- c_storedProcPool.seize(storedPtr);
- ndbrequire(storedPtr.i != RNIL);
- storedPtr.p->storedCode = ZSCAN_PROCEDURE;
- storedPtr.p->storedCounter = 0;
- storedPtr.p->storedProcLength = lenAttrInfo;
- storedPtr.p->storedLinkFirst = RNIL;
- storedPtr.p->storedLinkLast = RNIL;
- set_trans_state(regOperPtr, TRANS_WAIT_STORED_PROCEDURE_ATTR_INFO);
- regOperPtr->attrinbufLen = lenAttrInfo;
- regOperPtr->currentAttrinbufLen = 0;
- regOperPtr->storedProcPtr = storedPtr.i;
- if (lenAttrInfo >= ZATTR_BUFFER_SIZE) { // yes ">="
- jam();
- // send REF and change state to ignore the ATTRINFO to come
- storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_TOO_MUCH_ATTRINFO_ERROR);
- }
-}//Dbtup::scanProcedure()
-
-void Dbtup::copyProcedure(Signal* signal,
- TablerecPtr regTabPtr,
- Operationrec* regOperPtr)
-{
- Uint32 TnoOfAttributes = regTabPtr.p->m_no_of_attributes;
- scanProcedure(signal,
- regOperPtr,
- TnoOfAttributes);
-
- Uint32 length = 0;
- for (Uint32 Ti = 0; Ti < TnoOfAttributes; Ti++) {
- AttributeHeader::init(&signal->theData[length + 1], Ti, 0);
- length++;
- if (length == 24) {
- jam();
- ndbrequire(storedProcedureAttrInfo(signal, regOperPtr,
- signal->theData+1, length, true));
- length = 0;
- }//if
- }//for
- if (length != 0) {
- jam();
- ndbrequire(storedProcedureAttrInfo(signal, regOperPtr,
- signal->theData+1, length, true));
- }//if
- ndbrequire(regOperPtr->currentAttrinbufLen == 0);
-}//Dbtup::copyProcedure()
-
-bool Dbtup::storedProcedureAttrInfo(Signal* signal,
- Operationrec* regOperPtr,
- const Uint32 *data,
- Uint32 length,
- bool copyProcedure)
-{
- AttrbufrecPtr regAttrPtr;
- Uint32 RnoFree = cnoFreeAttrbufrec;
- if (ERROR_INSERTED(4004) && !copyProcedure) {
- CLEAR_ERROR_INSERT_VALUE;
- storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_SEIZE_ATTRINBUFREC_ERROR);
- return false;
- }//if
- regOperPtr->currentAttrinbufLen += length;
- ndbrequire(regOperPtr->currentAttrinbufLen <= regOperPtr->attrinbufLen);
- if ((RnoFree > MIN_ATTRBUF) ||
- (copyProcedure)) {
- jam();
- regAttrPtr.i = cfirstfreeAttrbufrec;
- ptrCheckGuard(regAttrPtr, cnoOfAttrbufrec, attrbufrec);
- regAttrPtr.p->attrbuf[ZBUF_DATA_LEN] = 0;
- cfirstfreeAttrbufrec = regAttrPtr.p->attrbuf[ZBUF_NEXT];
- cnoFreeAttrbufrec = RnoFree - 1;
- regAttrPtr.p->attrbuf[ZBUF_NEXT] = RNIL;
- } else {
- jam();
- storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_SEIZE_ATTRINBUFREC_ERROR);
- return false;
- }//if
- if (regOperPtr->firstAttrinbufrec == RNIL) {
- jam();
- regOperPtr->firstAttrinbufrec = regAttrPtr.i;
- }//if
- regAttrPtr.p->attrbuf[ZBUF_NEXT] = RNIL;
- if (regOperPtr->lastAttrinbufrec != RNIL) {
- AttrbufrecPtr tempAttrinbufptr;
- jam();
- tempAttrinbufptr.i = regOperPtr->lastAttrinbufrec;
- ptrCheckGuard(tempAttrinbufptr, cnoOfAttrbufrec, attrbufrec);
- tempAttrinbufptr.p->attrbuf[ZBUF_NEXT] = regAttrPtr.i;
- }//if
- regOperPtr->lastAttrinbufrec = regAttrPtr.i;
-
- regAttrPtr.p->attrbuf[ZBUF_DATA_LEN] = length;
- MEMCOPY_NO_WORDS(&regAttrPtr.p->attrbuf[0],
- data,
- length);
-
- if (regOperPtr->currentAttrinbufLen < regOperPtr->attrinbufLen) {
- jam();
- return true;
- }//if
- if (ERROR_INSERTED(4005) && !copyProcedure) {
- CLEAR_ERROR_INSERT_VALUE;
- storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_SEIZE_ATTRINBUFREC_ERROR);
- return false;
- }//if
-
- StoredProcPtr storedPtr;
- c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->storedProcPtr);
- ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
-
- regOperPtr->currentAttrinbufLen = 0;
- storedPtr.p->storedLinkFirst = regOperPtr->firstAttrinbufrec;
- storedPtr.p->storedLinkLast = regOperPtr->lastAttrinbufrec;
- regOperPtr->firstAttrinbufrec = RNIL;
- regOperPtr->lastAttrinbufrec = RNIL;
- regOperPtr->m_any_value = 0;
- set_trans_state(regOperPtr, TRANS_IDLE);
- signal->theData[0] = regOperPtr->userpointer;
- signal->theData[1] = storedPtr.i;
- sendSignal(DBLQH_REF, GSN_STORED_PROCCONF, signal, 2, JBB);
- return true;
-}//Dbtup::storedProcedureAttrInfo()
-
-void Dbtup::storedSeizeAttrinbufrecErrorLab(Signal* signal,
- Operationrec* regOperPtr,
- Uint32 errorCode)
-{
- StoredProcPtr storedPtr;
- c_storedProcPool.getPtr(storedPtr, regOperPtr->storedProcPtr);
- ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
-
- storedPtr.p->storedLinkFirst = regOperPtr->firstAttrinbufrec;
- regOperPtr->firstAttrinbufrec = RNIL;
- regOperPtr->lastAttrinbufrec = RNIL;
- regOperPtr->m_any_value = 0;
- set_trans_state(regOperPtr, TRANS_ERROR_WAIT_STORED_PROCREQ);
- signal->theData[0] = regOperPtr->userpointer;
- signal->theData[1] = errorCode;
- signal->theData[2] = regOperPtr->storedProcPtr;
- sendSignal(DBLQH_REF, GSN_STORED_PROCREF, signal, 3, JBB);
-}//Dbtup::storedSeizeAttrinbufrecErrorLab()
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
deleted file mode 100644
index 71a19c1840e..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_TAB_DES_MAN_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-
-/*
- * TABLE DESCRIPTOR MEMORY MANAGER
- *
- * Each table has a descriptor which is a contiguous array of words.
- * The descriptor is allocated from a global array using a buddy
- * algorithm. Free lists exist for each power of 2 words. Freeing
- * a piece first merges with free right and left neighbours and then
- * divides itself up into free list chunks.
- */
-
-Uint32
-Dbtup::getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset)
-{
- // belongs to configure.in
- unsigned sizeOfPointer = sizeof(CHARSET_INFO*);
- ndbrequire((sizeOfPointer & 0x3) == 0);
- sizeOfPointer = (sizeOfPointer >> 2);
- // do in layout order and return offsets (see DbtupMeta.cpp)
- Uint32 allocSize = 0;
- // magically aligned to 8 bytes
- offset[0] = allocSize += ZTD_SIZE;
- offset[1] = allocSize += regTabPtr->m_no_of_attributes* sizeOfReadFunction();
- offset[2] = allocSize += regTabPtr->m_no_of_attributes* sizeOfReadFunction();
- offset[3] = allocSize += regTabPtr->noOfCharsets * sizeOfPointer;
- offset[4] = allocSize += regTabPtr->noOfKeyAttr;
- offset[5] = allocSize += regTabPtr->m_no_of_attributes * ZAD_SIZE;
- offset[6] = allocSize += (regTabPtr->m_no_of_attributes + 1) >> 1; // real order
- allocSize += ZTD_TRAILER_SIZE;
- // return number of words
- return allocSize;
-}
-
-Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset)
-{
- Uint32 reference = RNIL;
- Uint32 allocSize = getTabDescrOffsets(regTabPtr, offset);
-/* ---------------------------------------------------------------- */
-/* ALWAYS ALLOCATE A MULTIPLE OF 16 WORDS */
-/* ---------------------------------------------------------------- */
- allocSize = (((allocSize - 1) >> 4) + 1) << 4;
- Uint32 list = nextHigherTwoLog(allocSize - 1); /* CALCULATE WHICH LIST IT BELONGS TO */
- for (Uint32 i = list; i < 16; i++) {
- jam();
- if (cfreeTdList[i] != RNIL) {
- jam();
- reference = cfreeTdList[i];
- removeTdArea(reference, i); /* REMOVE THE AREA FROM THE FREELIST */
- Uint32 retNo = (1 << i) - allocSize; /* CALCULATE THE DIFFERENCE */
- if (retNo >= ZTD_FREE_SIZE) {
- jam();
- // return unused words, of course without attempting left merge
- Uint32 retRef = reference + allocSize;
- freeTabDescr(retRef, retNo, false);
- } else {
- jam();
- allocSize = 1 << i;
- }//if
- break;
- }//if
- }//for
- if (reference == RNIL) {
- jam();
- terrorCode = ZMEM_NOTABDESCR_ERROR;
- return RNIL;
- } else {
- jam();
- setTabDescrWord((reference + allocSize) - ZTD_TR_TYPE, ZTD_TYPE_NORMAL);
- setTabDescrWord(reference + ZTD_DATASIZE, allocSize);
-
- /* INITIALIZE THE TRAILER RECORD WITH TYPE AND SIZE */
- /* THE TRAILER IS USED TO SIMPLIFY MERGE OF FREE AREAS */
-
- setTabDescrWord(reference + ZTD_HEADER, ZTD_TYPE_NORMAL);
- setTabDescrWord((reference + allocSize) - ZTD_TR_SIZE, allocSize);
- return reference;
- }//if
-}//Dbtup::allocTabDescr()
-
-void Dbtup::freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal)
-{
- itdaMergeTabDescr(retRef, retNo, normal); /* MERGE WITH POSSIBLE NEIGHBOURS */
- while (retNo >= ZTD_FREE_SIZE) {
- jam();
- Uint32 list = nextHigherTwoLog(retNo);
- list--; /* RETURN TO NEXT LOWER LIST */
- Uint32 sizeOfChunk = 1 << list;
- insertTdArea(retRef, list);
- retRef += sizeOfChunk;
- retNo -= sizeOfChunk;
- }//while
- ndbassert(retNo == 0);
-}//Dbtup::freeTabDescr()
-
-Uint32
-Dbtup::getTabDescrWord(Uint32 index)
-{
- ndbrequire(index < cnoOfTabDescrRec);
- return tableDescriptor[index].tabDescr;
-}//Dbtup::getTabDescrWord()
-
-void
-Dbtup::setTabDescrWord(Uint32 index, Uint32 word)
-{
- ndbrequire(index < cnoOfTabDescrRec);
- tableDescriptor[index].tabDescr = word;
-}//Dbtup::setTabDescrWord()
-
-void Dbtup::insertTdArea(Uint32 tabDesRef, Uint32 list)
-{
- ndbrequire(list < 16);
- setTabDescrWord(tabDesRef + ZTD_FL_HEADER, ZTD_TYPE_FREE);
- setTabDescrWord(tabDesRef + ZTD_FL_NEXT, cfreeTdList[list]);
- if (cfreeTdList[list] != RNIL) {
- jam(); /* PREVIOUSLY EMPTY SLOT */
- setTabDescrWord(cfreeTdList[list] + ZTD_FL_PREV, tabDesRef);
- }//if
- cfreeTdList[list] = tabDesRef; /* RELINK THE LIST */
-
- setTabDescrWord(tabDesRef + ZTD_FL_PREV, RNIL);
- setTabDescrWord(tabDesRef + ZTD_FL_SIZE, 1 << list);
- setTabDescrWord((tabDesRef + (1 << list)) - ZTD_TR_TYPE, ZTD_TYPE_FREE);
- setTabDescrWord((tabDesRef + (1 << list)) - ZTD_TR_SIZE, 1 << list);
-}//Dbtup::insertTdArea()
-
-/*
- * Merge to-be-removed chunk (which need not be initialized with header
- * and trailer) with left and right buddies. The start point retRef
- * moves to left and the size retNo increases to match the new chunk.
- */
-void Dbtup::itdaMergeTabDescr(Uint32& retRef, Uint32& retNo, bool normal)
-{
- // merge right
- while ((retRef + retNo) < cnoOfTabDescrRec) {
- jam();
- Uint32 tabDesRef = retRef + retNo;
- Uint32 headerWord = getTabDescrWord(tabDesRef + ZTD_FL_HEADER);
- if (headerWord == ZTD_TYPE_FREE) {
- jam();
- Uint32 sizeOfMergedPart = getTabDescrWord(tabDesRef + ZTD_FL_SIZE);
-
- retNo += sizeOfMergedPart;
- Uint32 list = nextHigherTwoLog(sizeOfMergedPart - 1);
- removeTdArea(tabDesRef, list);
- } else {
- jam();
- break;
- }
- }
- // merge left
- const bool mergeLeft = normal;
- while (mergeLeft && retRef > 0) {
- jam();
- Uint32 trailerWord = getTabDescrWord(retRef - ZTD_TR_TYPE);
- if (trailerWord == ZTD_TYPE_FREE) {
- jam();
- Uint32 sizeOfMergedPart = getTabDescrWord(retRef - ZTD_TR_SIZE);
- ndbrequire(retRef >= sizeOfMergedPart);
- retRef -= sizeOfMergedPart;
- retNo += sizeOfMergedPart;
- Uint32 list = nextHigherTwoLog(sizeOfMergedPart - 1);
- removeTdArea(retRef, list);
- } else {
- jam();
- break;
- }
- }
- ndbrequire((retRef + retNo) <= cnoOfTabDescrRec);
-}//Dbtup::itdaMergeTabDescr()
-
-/* ---------------------------------------------------------------- */
-/* ------------------------ REMOVE_TD_AREA ------------------------ */
-/* ---------------------------------------------------------------- */
-/* */
-/* THIS ROUTINE REMOVES A TD CHUNK FROM THE POOL OF TD RECORDS */
-/* */
-/* INPUT: TLIST LIST TO USE */
-/* TAB_DESCR_PTR POINTS TO THE CHUNK TO BE REMOVED */
-/* */
-/* SHORTNAME: RMTA */
-/* -----------------------------------------------------------------*/
-void Dbtup::removeTdArea(Uint32 tabDesRef, Uint32 list)
-{
- ndbrequire(list < 16);
- Uint32 tabDescrNextPtr = getTabDescrWord(tabDesRef + ZTD_FL_NEXT);
- Uint32 tabDescrPrevPtr = getTabDescrWord(tabDesRef + ZTD_FL_PREV);
-
- setTabDescrWord(tabDesRef + ZTD_HEADER, ZTD_TYPE_NORMAL);
- setTabDescrWord((tabDesRef + (1 << list)) - ZTD_TR_TYPE, ZTD_TYPE_NORMAL);
-
- if (tabDesRef == cfreeTdList[list]) {
- jam();
- cfreeTdList[list] = tabDescrNextPtr; /* RELINK THE LIST */
- }//if
- if (tabDescrNextPtr != RNIL) {
- jam();
- setTabDescrWord(tabDescrNextPtr + ZTD_FL_PREV, tabDescrPrevPtr);
- }//if
- if (tabDescrPrevPtr != RNIL) {
- jam();
- setTabDescrWord(tabDescrPrevPtr + ZTD_FL_NEXT, tabDescrNextPtr);
- }//if
-}//Dbtup::removeTdArea()
-
-#ifdef VM_TRACE
-void
-Dbtup::verifytabdes()
-{
- struct WordType {
- short fl; // free list 0-15
- short ti; // table id
- WordType() : fl(-1), ti(-1) {}
- };
- WordType* wt = new WordType [cnoOfTabDescrRec];
- uint free_frags = 0;
- // free lists
- {
- for (uint i = 0; i < 16; i++) {
- Uint32 desc2 = RNIL;
- Uint32 desc = cfreeTdList[i];
- while (desc != RNIL) {
- const Uint32 size = (1 << i);
- ndbrequire(size >= ZTD_FREE_SIZE);
- ndbrequire(desc + size <= cnoOfTabDescrRec);
- { Uint32 index = desc + ZTD_FL_HEADER;
- ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_FREE);
- }
- { Uint32 index = desc + ZTD_FL_SIZE;
- ndbrequire(tableDescriptor[index].tabDescr == size);
- }
- { Uint32 index = desc + size - ZTD_TR_TYPE;
- ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_FREE);
- }
- { Uint32 index = desc + size - ZTD_TR_SIZE;
- ndbrequire(tableDescriptor[index].tabDescr == size);
- }
- { Uint32 index = desc + ZTD_FL_PREV;
- ndbrequire(tableDescriptor[index].tabDescr == desc2);
- }
- for (uint j = 0; j < size; j++) {
- ndbrequire(wt[desc + j].fl == -1);
- wt[desc + j].fl = i;
- }
- desc2 = desc;
- desc = tableDescriptor[desc + ZTD_FL_NEXT].tabDescr;
- free_frags++;
- }
- }
- }
- // tables
- {
- for (uint i = 0; i < cnoOfTablerec; i++) {
- TablerecPtr ptr;
- ptr.i = i;
- ptrAss(ptr, tablerec);
- if (ptr.p->tableStatus == DEFINED) {
- Uint32 offset[10];
- const Uint32 alloc = getTabDescrOffsets(ptr.p, offset);
- const Uint32 desc = ptr.p->readKeyArray - offset[3];
- Uint32 size = alloc;
- if (size % ZTD_FREE_SIZE != 0)
- size += ZTD_FREE_SIZE - size % ZTD_FREE_SIZE;
- ndbrequire(desc + size <= cnoOfTabDescrRec);
- { Uint32 index = desc + ZTD_FL_HEADER;
- ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_NORMAL);
- }
- { Uint32 index = desc + ZTD_FL_SIZE;
- ndbrequire(tableDescriptor[index].tabDescr == size);
- }
- { Uint32 index = desc + size - ZTD_TR_TYPE;
- ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_NORMAL);
- }
- { Uint32 index = desc + size - ZTD_TR_SIZE;
- ndbrequire(tableDescriptor[index].tabDescr == size);
- }
- for (uint j = 0; j < size; j++) {
- ndbrequire(wt[desc + j].ti == -1);
- wt[desc + j].ti = i;
- }
- }
- }
- }
- // all words
- {
- for (uint i = 0; i < cnoOfTabDescrRec; i++) {
- bool is_fl = wt[i].fl != -1;
- bool is_ti = wt[i].ti != -1;
- ndbrequire(is_fl != is_ti);
- }
- }
- delete [] wt;
- ndbout << "verifytabdes: frags=" << free_frags << endl;
-}
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
deleted file mode 100644
index f202959b4da..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ /dev/null
@@ -1,1291 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define DBTUP_C
-#define DBTUP_TRIGGER_CPP
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <AttributeDescriptor.hpp>
-#include "AttributeOffset.hpp"
-#include <AttributeHeader.hpp>
-#include <signaldata/FireTrigOrd.hpp>
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/TuxMaint.hpp>
-
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* ----------------------- TRIGGER HANDLING ----------------------- */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-
-DLList<Dbtup::TupTriggerData>*
-Dbtup::findTriggerList(Tablerec* table,
- TriggerType::Value ttype,
- TriggerActionTime::Value ttime,
- TriggerEvent::Value tevent)
-{
- DLList<TupTriggerData>* tlist = NULL;
- switch (ttype) {
- case TriggerType::SUBSCRIPTION:
- case TriggerType::SUBSCRIPTION_BEFORE:
- switch (tevent) {
- case TriggerEvent::TE_INSERT:
- jam();
- if (ttime == TriggerActionTime::TA_DETACHED)
- tlist = &table->subscriptionInsertTriggers;
- break;
- case TriggerEvent::TE_UPDATE:
- jam();
- if (ttime == TriggerActionTime::TA_DETACHED)
- tlist = &table->subscriptionUpdateTriggers;
- break;
- case TriggerEvent::TE_DELETE:
- jam();
- if (ttime == TriggerActionTime::TA_DETACHED)
- tlist = &table->subscriptionDeleteTriggers;
- break;
- default:
- break;
- }
- break;
- case TriggerType::SECONDARY_INDEX:
- switch (tevent) {
- case TriggerEvent::TE_INSERT:
- jam();
- if (ttime == TriggerActionTime::TA_AFTER)
- tlist = &table->afterInsertTriggers;
- break;
- case TriggerEvent::TE_UPDATE:
- jam();
- if (ttime == TriggerActionTime::TA_AFTER)
- tlist = &table->afterUpdateTriggers;
- break;
- case TriggerEvent::TE_DELETE:
- jam();
- if (ttime == TriggerActionTime::TA_AFTER)
- tlist = &table->afterDeleteTriggers;
- break;
- default:
- break;
- }
- break;
- case TriggerType::ORDERED_INDEX:
- switch (tevent) {
- case TriggerEvent::TE_CUSTOM:
- jam();
- if (ttime == TriggerActionTime::TA_CUSTOM)
- tlist = &table->tuxCustomTriggers;
- break;
- default:
- break;
- }
- break;
- case TriggerType::READ_ONLY_CONSTRAINT:
- switch (tevent) {
- case TriggerEvent::TE_UPDATE:
- jam();
- if (ttime == TriggerActionTime::TA_AFTER)
- tlist = &table->constraintUpdateTriggers;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- return tlist;
-}
-
-// Trigger signals
-void
-Dbtup::execCREATE_TRIG_REQ(Signal* signal)
-{
- jamEntry();
- BlockReference senderRef = signal->getSendersBlockRef();
- const CreateTrigReq reqCopy = *(const CreateTrigReq*)signal->getDataPtr();
- const CreateTrigReq* const req = &reqCopy;
- CreateTrigRef::ErrorCode error= CreateTrigRef::NoError;
-
- // Find table
- TablerecPtr tabPtr;
- tabPtr.i = req->getTableId();
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- if (tabPtr.p->tableStatus != DEFINED )
- {
- jam();
- error= CreateTrigRef::InvalidTable;
- }
- // Create trigger and associate it with the table
- else if (createTrigger(tabPtr.p, req))
- {
- jam();
- // Send conf
- CreateTrigConf* const conf = (CreateTrigConf*)signal->getDataPtrSend();
- conf->setUserRef(reference());
- conf->setConnectionPtr(req->getConnectionPtr());
- conf->setRequestType(req->getRequestType());
- conf->setTableId(req->getTableId());
- conf->setIndexId(req->getIndexId());
- conf->setTriggerId(req->getTriggerId());
- conf->setTriggerInfo(req->getTriggerInfo());
- sendSignal(senderRef, GSN_CREATE_TRIG_CONF,
- signal, CreateTrigConf::SignalLength, JBB);
- return;
- }
- else
- {
- jam();
- error= CreateTrigRef::TooManyTriggers;
- }
- ndbassert(error != CreateTrigRef::NoError);
- // Send ref
- CreateTrigRef* const ref = (CreateTrigRef*)signal->getDataPtrSend();
- ref->setUserRef(reference());
- ref->setConnectionPtr(req->getConnectionPtr());
- ref->setRequestType(req->getRequestType());
- ref->setTableId(req->getTableId());
- ref->setIndexId(req->getIndexId());
- ref->setTriggerId(req->getTriggerId());
- ref->setTriggerInfo(req->getTriggerInfo());
- ref->setErrorCode(error);
- sendSignal(senderRef, GSN_CREATE_TRIG_REF,
- signal, CreateTrigRef::SignalLength, JBB);
-}//Dbtup::execCREATE_TRIG_REQ()
-
-void
-Dbtup::execDROP_TRIG_REQ(Signal* signal)
-{
- jamEntry();
- BlockReference senderRef = signal->getSendersBlockRef();
- const DropTrigReq reqCopy = *(const DropTrigReq*)signal->getDataPtr();
- const DropTrigReq* const req = &reqCopy;
-
- // Find table
- TablerecPtr tabPtr;
- tabPtr.i = req->getTableId();
- ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
-
- // Drop trigger
- Uint32 r = dropTrigger(tabPtr.p, req, refToBlock(senderRef));
- if (r == 0){
- // Send conf
- DropTrigConf* const conf = (DropTrigConf*)signal->getDataPtrSend();
- conf->setUserRef(senderRef);
- conf->setConnectionPtr(req->getConnectionPtr());
- conf->setRequestType(req->getRequestType());
- conf->setTableId(req->getTableId());
- conf->setIndexId(req->getIndexId());
- conf->setTriggerId(req->getTriggerId());
- sendSignal(senderRef, GSN_DROP_TRIG_CONF,
- signal, DropTrigConf::SignalLength, JBB);
- } else {
- // Send ref
- DropTrigRef* const ref = (DropTrigRef*)signal->getDataPtrSend();
- ref->setUserRef(senderRef);
- ref->setConnectionPtr(req->getConnectionPtr());
- ref->setRequestType(req->getRequestType());
- ref->setTableId(req->getTableId());
- ref->setIndexId(req->getIndexId());
- ref->setTriggerId(req->getTriggerId());
- ref->setErrorCode((DropTrigRef::ErrorCode)r);
- ref->setErrorLine(__LINE__);
- ref->setErrorNode(refToNode(reference()));
- sendSignal(senderRef, GSN_DROP_TRIG_REF,
- signal, DropTrigRef::SignalLength, JBB);
- }
-}//Dbtup::DROP_TRIG_REQ()
-
-/* ---------------------------------------------------------------- */
-/* ------------------------- createTrigger ------------------------ */
-/* */
-/* Creates a new trigger record by fetching one from the trigger */
-/* pool and associates it with the given table. */
-/* Trigger type can be one of secondary_index, subscription, */
-/* constraint(NYI), foreign_key(NYI), schema_upgrade(NYI), */
-/* api_trigger(NYI) or sql_trigger(NYI). */
-/* Note that this method only checks for total number of allowed */
-/* triggers. Checking the number of allowed triggers per table is */
-/* done by TRIX. */
-/* */
-/* ---------------------------------------------------------------- */
-bool
-Dbtup::createTrigger(Tablerec* table, const CreateTrigReq* req)
-{
- if (ERROR_INSERTED(4003)) {
- CLEAR_ERROR_INSERT_VALUE;
- return false;
- }
- TriggerType::Value ttype = req->getTriggerType();
- TriggerActionTime::Value ttime = req->getTriggerActionTime();
- TriggerEvent::Value tevent = req->getTriggerEvent();
-
- DLList<TupTriggerData>* tlist = findTriggerList(table, ttype, ttime, tevent);
- ndbrequire(tlist != NULL);
-
- TriggerPtr tptr;
- if (!tlist->seize(tptr))
- return false;
-
- // Set trigger id
- tptr.p->triggerId = req->getTriggerId();
-
- // ndbout_c("Create TupTrigger %u = %u %u %u %u", tptr.p->triggerId, table, ttype, ttime, tevent);
-
- // Set index id
- tptr.p->indexId = req->getIndexId();
-
- // Set trigger type etc
- tptr.p->triggerType = ttype;
- tptr.p->triggerActionTime = ttime;
- tptr.p->triggerEvent = tevent;
-
- tptr.p->sendBeforeValues = true;
- if ((tptr.p->triggerType == TriggerType::SUBSCRIPTION) &&
- ((tptr.p->triggerEvent == TriggerEvent::TE_UPDATE) ||
- (tptr.p->triggerEvent == TriggerEvent::TE_DELETE))) {
- jam();
- tptr.p->sendBeforeValues = false;
- }
- /*
- tptr.p->sendOnlyChangedAttributes = false;
- if (((tptr.p->triggerType == TriggerType::SUBSCRIPTION) ||
- (tptr.p->triggerType == TriggerType::SUBSCRIPTION_BEFORE)) &&
- (tptr.p->triggerEvent == TriggerEvent::TE_UPDATE)) {
- jam();
- tptr.p->sendOnlyChangedAttributes = true;
- }
- */
- tptr.p->sendOnlyChangedAttributes = !req->getReportAllMonitoredAttributes();
- // Set monitor all
- tptr.p->monitorAllAttributes = req->getMonitorAllAttributes();
- tptr.p->monitorReplicas = req->getMonitorReplicas();
- tptr.p->m_receiverBlock = refToBlock(req->getReceiverRef());
-
- tptr.p->attributeMask.clear();
- if (tptr.p->monitorAllAttributes) {
- jam();
- for(Uint32 i = 0; i < table->m_no_of_attributes; i++) {
- if (!primaryKey(table, i)) {
- jam();
- tptr.p->attributeMask.set(i);
- }
- }
- } else {
- // Set attribute mask
- jam();
- tptr.p->attributeMask = req->getAttributeMask();
- }
- return true;
-}//Dbtup::createTrigger()
-
-bool
-Dbtup::primaryKey(Tablerec* const regTabPtr, Uint32 attrId)
-{
- Uint32 attrDescriptorStart = regTabPtr->tabDescriptor;
- Uint32 attrDescriptor = getTabDescrWord(attrDescriptorStart +
- (attrId * ZAD_SIZE));
- return (bool)AttributeDescriptor::getPrimaryKey(attrDescriptor);
-}//Dbtup::primaryKey()
-
-/* ---------------------------------------------------------------- */
-/* -------------------------- dropTrigger ------------------------- */
-/* */
-/* Deletes a trigger record by disassociating it with the given */
-/* table and returning it to the trigger pool. */
-/* Trigger type can be one of secondary_index, subscription, */
-/* constraint(NYI), foreign_key(NYI), schema_upgrade(NYI), */
-/* api_trigger(NYI) or sql_trigger(NYI). */
-/* */
-/* ---------------------------------------------------------------- */
-Uint32
-Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req, BlockNumber sender)
-{
- if (ERROR_INSERTED(4004)) {
- CLEAR_ERROR_INSERT_VALUE;
- return 9999;
- }
- Uint32 triggerId = req->getTriggerId();
-
- TriggerType::Value ttype = req->getTriggerType();
- TriggerActionTime::Value ttime = req->getTriggerActionTime();
- TriggerEvent::Value tevent = req->getTriggerEvent();
-
- // ndbout_c("Drop TupTrigger %u = %u %u %u %u by %u", triggerId, table, ttype, ttime, tevent, sender);
-
- DLList<TupTriggerData>* tlist = findTriggerList(table, ttype, ttime, tevent);
- ndbrequire(tlist != NULL);
-
- Ptr<TupTriggerData> ptr;
- for (tlist->first(ptr); !ptr.isNull(); tlist->next(ptr)) {
- jam();
- if (ptr.p->triggerId == triggerId) {
- if(ttype==TriggerType::SUBSCRIPTION && sender != ptr.p->m_receiverBlock)
- {
- /**
- * You can only drop your own triggers for subscription triggers.
- * Trigger IDs are private for each block.
- *
- * SUMA encodes information in the triggerId
- *
- * Backup doesn't really care about the Ids though.
- */
- jam();
- continue;
- }
- jam();
- tlist->release(ptr.i);
- return 0;
- }
- }
- return DropTrigRef::TriggerNotFound;
-}//Dbtup::dropTrigger()
-
-/* ---------------------------------------------------------------- */
-/* -------------- checkImmediateTriggersAfterOp ------------------ */
-/* */
-/* Called after an insert, delete, or update operation takes */
-/* place. Fetches before tuple for deletes and updates and */
-/* after tuple for inserts and updates. */
-/* Executes immediate triggers by sending FIRETRIGORD */
-/* */
-/* ---------------------------------------------------------------- */
-void
-Dbtup::checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
- Operationrec *regOperPtr,
- Tablerec *regTablePtr,
- bool disk)
-{
- if(refToBlock(req_struct->TC_ref) != DBTC) {
- return;
- }
-
- if ((regOperPtr->op_struct.primary_replica) &&
- (!(regTablePtr->afterInsertTriggers.isEmpty()))) {
- jam();
- fireImmediateTriggers(req_struct,
- regTablePtr->afterInsertTriggers,
- regOperPtr,
- disk);
- }
-}
-
-void
-Dbtup::checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* regTablePtr,
- bool disk)
-{
- if(refToBlock(req_struct->TC_ref) != DBTC) {
- return;
- }
-
- if ((regOperPtr->op_struct.primary_replica) &&
- (!(regTablePtr->afterUpdateTriggers.isEmpty()))) {
- jam();
- fireImmediateTriggers(req_struct,
- regTablePtr->afterUpdateTriggers,
- regOperPtr,
- disk);
- }
- if ((regOperPtr->op_struct.primary_replica) &&
- (!(regTablePtr->constraintUpdateTriggers.isEmpty()))) {
- jam();
- fireImmediateTriggers(req_struct,
- regTablePtr->constraintUpdateTriggers,
- regOperPtr,
- disk);
- }
-}
-
-void
-Dbtup::checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* regTablePtr,
- bool disk)
-{
- if(refToBlock(req_struct->TC_ref) != DBTC) {
- return;
- }
-
- if ((regOperPtr->op_struct.primary_replica) &&
- (!(regTablePtr->afterDeleteTriggers.isEmpty()))) {
- jam();
- executeTriggers(req_struct,
- regTablePtr->afterDeleteTriggers,
- regOperPtr,
- disk);
- }
-}
-
-#if 0
-/* ---------------------------------------------------------------- */
-/* --------------------- checkDeferredTriggers -------------------- */
-/* */
-/* Called before commit after an insert, delete, or update */
-/* operation. Fetches before tuple for deletes and updates and */
-/* after tuple for inserts and updates. */
-/* Executes deferred triggers by sending FIRETRIGORD */
-/* */
-/* ---------------------------------------------------------------- */
-void Dbtup::checkDeferredTriggers(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTablePtr)
-{
- jam();
- // NYI
-}//Dbtup::checkDeferredTriggers()
-#endif
-
-/* ---------------------------------------------------------------- */
-/* --------------------- checkDetachedTriggers -------------------- */
-/* */
-/* Called at commit after an insert, delete, or update operation. */
-/* Fetches before tuple for deletes and updates and */
-/* after tuple for inserts and updates. */
-/* Executes detached triggers by sending FIRETRIGORD */
-/* */
-/* ---------------------------------------------------------------- */
-void Dbtup::checkDetachedTriggers(KeyReqStruct *req_struct,
- Operationrec* regOperPtr,
- Tablerec* regTablePtr,
- bool disk)
-{
- Uint32 save_type = regOperPtr->op_struct.op_type;
- Tuple_header *save_ptr = req_struct->m_tuple_ptr;
-
- switch (save_type) {
- case ZUPDATE:
- case ZINSERT:
- req_struct->m_tuple_ptr = (Tuple_header*)
- c_undo_buffer.get_ptr(&regOperPtr->m_copy_tuple_location);
- break;
- }
-
- /**
- * Set correct operation type and fix change mask
- * Note ALLOC is set in "orig" tuple
- */
- if (save_ptr->m_header_bits & Tuple_header::ALLOC) {
- if (save_type == ZDELETE) {
- // insert + delete = nothing
- jam();
- return;
- goto end;
- }
- regOperPtr->op_struct.op_type = ZINSERT;
- }
- else if (save_type == ZINSERT) {
- /**
- * Tuple was not created but last op is INSERT.
- * This is possible only on DELETE + INSERT
- */
- regOperPtr->op_struct.op_type = ZUPDATE;
- }
-
- switch(regOperPtr->op_struct.op_type) {
- case(ZINSERT):
- jam();
- if (regTablePtr->subscriptionInsertTriggers.isEmpty()) {
- // Table has no active triggers monitoring inserts at commit
- jam();
- goto end;
- }
-
- // If any fired immediate insert trigger then fetch after tuple
- fireDetachedTriggers(req_struct,
- regTablePtr->subscriptionInsertTriggers,
- regOperPtr, disk);
- break;
- case(ZDELETE):
- jam();
- if (regTablePtr->subscriptionDeleteTriggers.isEmpty()) {
- // Table has no active triggers monitoring deletes at commit
- jam();
- goto end;
- }
-
- // Execute any after delete triggers by sending
- // FIRETRIGORD with the before tuple
- fireDetachedTriggers(req_struct,
- regTablePtr->subscriptionDeleteTriggers,
- regOperPtr, disk);
- break;
- case(ZUPDATE):
- jam();
- if (regTablePtr->subscriptionUpdateTriggers.isEmpty()) {
- // Table has no active triggers monitoring updates at commit
- jam();
- goto end;
- }
-
- // If any fired immediate update trigger then fetch after tuple
- // and send two FIRETRIGORD one with before tuple and one with after tuple
- fireDetachedTriggers(req_struct,
- regTablePtr->subscriptionUpdateTriggers,
- regOperPtr, disk);
- break;
- default:
- ndbrequire(false);
- break;
- }
-
-end:
- regOperPtr->op_struct.op_type = save_type;
- req_struct->m_tuple_ptr = save_ptr;
-}
-
-void
-Dbtup::fireImmediateTriggers(KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* const regOperPtr,
- bool disk)
-{
- TriggerPtr trigPtr;
- triggerList.first(trigPtr);
- while (trigPtr.i != RNIL) {
- jam();
- if (trigPtr.p->monitorAllAttributes ||
- trigPtr.p->attributeMask.overlaps(req_struct->changeMask)) {
- jam();
- executeTrigger(req_struct,
- trigPtr.p,
- regOperPtr,
- disk);
- }//if
- triggerList.next(trigPtr);
- }//while
-}//Dbtup::fireImmediateTriggers()
-
-#if 0
-void
-Dbtup::fireDeferredTriggers(Signal* signal,
- KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* const regOperPtr)
-{
- TriggerPtr trigPtr;
- triggerList.first(trigPtr);
- while (trigPtr.i != RNIL) {
- jam();
- if (trigPtr.p->monitorAllAttributes ||
- trigPtr.p->attributeMask.overlaps(req_struct->changeMask)) {
- jam();
- executeTrigger(req_struct,
- trigPtr,
- regOperPtr);
- }//if
- triggerList.next(trigPtr);
- }//while
-}//Dbtup::fireDeferredTriggers()
-#endif
-
-void
-Dbtup::fireDetachedTriggers(KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* const regOperPtr,
- bool disk)
-{
-
- TriggerPtr trigPtr;
-
- /**
- * Set disk page
- */
- req_struct->m_disk_page_ptr.i = m_pgman.m_ptr.i;
-
- ndbrequire(regOperPtr->is_first_operation());
- triggerList.first(trigPtr);
- while (trigPtr.i != RNIL) {
- jam();
- if ((trigPtr.p->monitorReplicas ||
- regOperPtr->op_struct.primary_replica) &&
- (trigPtr.p->monitorAllAttributes ||
- trigPtr.p->attributeMask.overlaps(req_struct->changeMask))) {
- jam();
- executeTrigger(req_struct,
- trigPtr.p,
- regOperPtr,
- disk);
- }
- triggerList.next(trigPtr);
- }
-}
-
-void Dbtup::executeTriggers(KeyReqStruct *req_struct,
- DLList<TupTriggerData>& triggerList,
- Operationrec* regOperPtr,
- bool disk)
-{
- TriggerPtr trigPtr;
- triggerList.first(trigPtr);
- while (trigPtr.i != RNIL) {
- jam();
- executeTrigger(req_struct,
- trigPtr.p,
- regOperPtr,
- disk);
- triggerList.next(trigPtr);
-
- }
-}
-
-void Dbtup::executeTrigger(KeyReqStruct *req_struct,
- TupTriggerData* const trigPtr,
- Operationrec* const regOperPtr,
- bool disk)
-{
- /**
- * The block below does not work together with GREP.
- * I have 2 db nodes (2 replicas) -> one node group.
- * I want to have FIRETRIG_ORD sent to all SumaParticipants,
- * from all nodes in the node group described above. However,
- * only one of the nodes in the node group actually sends the
- * FIRE_TRIG_ORD, and the other node enters this "hack" below.
- * I don't really know what the code snippet below does, but it
- * does not work with GREP the way Lars and I want it.
- * We need to have triggers fired from both the primary and the
- * backup replica, not only the primary as it is now.
- *
- * Note: In Suma, I have changed triggers to be created with
- * setMonitorReplicas(true).
- * /Johan
- *
- * See RT 709
- */
- // XXX quick fix to NR, should fix in LQHKEYREQ instead
- /*
- if (refToBlock(req_struct->TC_ref) == DBLQH) {
- jam();
- return;
- }
- */
- Signal* signal= req_struct->signal;
- BlockReference ref = trigPtr->m_receiverBlock;
- Uint32* const keyBuffer = &cinBuffer[0];
- Uint32* const afterBuffer = &coutBuffer[0];
- Uint32* const beforeBuffer = &clogMemBuffer[0];
-
- Uint32 noPrimKey, noAfterWords, noBeforeWords;
- FragrecordPtr regFragPtr;
- regFragPtr.i= regOperPtr->fragmentPtr;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
-
- if (ref == BACKUP) {
- jam();
- /*
- In order for the implementation of BACKUP to work even when changing
- primaries in the middle of the backup we need to set the trigger on
- all replicas. This check checks whether this is the node where this
- trigger should be fired. The check should preferably have been put
- completely in the BACKUP block but it was about five times simpler
- to put it here and also much faster for the backup (small overhead
- for everybody else.
- */
- signal->theData[0] = trigPtr->triggerId;
- signal->theData[1] = regFragPtr.p->fragmentId;
- EXECUTE_DIRECT(BACKUP, GSN_BACKUP_TRIG_REQ, signal, 2);
- jamEntry();
- if (signal->theData[0] == 0) {
- jam();
- return;
- }
- }
- if (!readTriggerInfo(trigPtr,
- regOperPtr,
- req_struct,
- regFragPtr.p,
- keyBuffer,
- noPrimKey,
- afterBuffer,
- noAfterWords,
- beforeBuffer,
- noBeforeWords,
- disk)) {
- jam();
- return;
- }
-//--------------------------------------------------------------------
-// Now all data for this trigger has been read. It is now time to send
-// the trigger information consisting of two or three sets of TRIG_
-// ATTRINFO signals and one FIRE_TRIG_ORD signal.
-// We start by setting common header info for all TRIG_ATTRINFO signals.
-//--------------------------------------------------------------------
- bool executeDirect;
- TrigAttrInfo* const trigAttrInfo = (TrigAttrInfo *)signal->getDataPtrSend();
- trigAttrInfo->setConnectionPtr(req_struct->TC_index);
- trigAttrInfo->setTriggerId(trigPtr->triggerId);
-
- switch(trigPtr->triggerType) {
- case (TriggerType::SECONDARY_INDEX):
- jam();
- ref = req_struct->TC_ref;
- executeDirect = false;
- break;
- case (TriggerType::SUBSCRIPTION):
- case (TriggerType::SUBSCRIPTION_BEFORE):
- jam();
- // Since only backup uses subscription triggers we send to backup directly for now
- ref = trigPtr->m_receiverBlock;
- executeDirect = true;
- break;
- case (TriggerType::READ_ONLY_CONSTRAINT):
- terrorCode = ZREAD_ONLY_CONSTRAINT_VIOLATION;
- // XXX should return status and abort the rest
- return;
- default:
- ndbrequire(false);
- executeDirect= false; // remove warning
- }//switch
-
- req_struct->no_fired_triggers++;
-
- trigAttrInfo->setAttrInfoType(TrigAttrInfo::PRIMARY_KEY);
- sendTrigAttrInfo(signal, keyBuffer, noPrimKey, executeDirect, ref);
-
- switch(regOperPtr->op_struct.op_type) {
- case(ZINSERT):
- jam();
- // Send AttrInfo signals with new attribute values
- trigAttrInfo->setAttrInfoType(TrigAttrInfo::AFTER_VALUES);
- sendTrigAttrInfo(signal, afterBuffer, noAfterWords, executeDirect, ref);
- break;
- case(ZDELETE):
- if (trigPtr->sendBeforeValues) {
- jam();
- trigAttrInfo->setAttrInfoType(TrigAttrInfo::BEFORE_VALUES);
- sendTrigAttrInfo(signal, beforeBuffer, noBeforeWords, executeDirect,ref);
- }
- break;
- case(ZUPDATE):
- jam();
- if (trigPtr->sendBeforeValues) {
- jam();
- trigAttrInfo->setAttrInfoType(TrigAttrInfo::BEFORE_VALUES);
- sendTrigAttrInfo(signal, beforeBuffer, noBeforeWords, executeDirect,ref);
- }
- trigAttrInfo->setAttrInfoType(TrigAttrInfo::AFTER_VALUES);
- sendTrigAttrInfo(signal, afterBuffer, noAfterWords, executeDirect, ref);
- break;
- default:
- ndbrequire(false);
- }
- sendFireTrigOrd(signal,
- req_struct,
- regOperPtr,
- trigPtr,
- regFragPtr.p->fragmentId,
- noPrimKey,
- noBeforeWords,
- noAfterWords);
-}
-
-Uint32 Dbtup::setAttrIds(Bitmask<MAXNROFATTRIBUTESINWORDS>& attributeMask,
- Uint32 m_no_of_attributesibutes,
- Uint32* inBuffer)
-{
- Uint32 bufIndx = 0;
- for (Uint32 i = 0; i < m_no_of_attributesibutes; i++) {
- jam();
- if (attributeMask.get(i)) {
- jam();
- AttributeHeader::init(&inBuffer[bufIndx++], i, 0);
- }
- }
- return bufIndx;
-}
-
-bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
- Operationrec* const regOperPtr,
- KeyReqStruct *req_struct,
- Fragrecord* const regFragPtr,
- Uint32* const keyBuffer,
- Uint32& noPrimKey,
- Uint32* const afterBuffer,
- Uint32& noAfterWords,
- Uint32* const beforeBuffer,
- Uint32& noBeforeWords,
- bool disk)
-{
- noAfterWords = 0;
- noBeforeWords = 0;
- Uint32 readBuffer[MAX_ATTRIBUTES_IN_TABLE];
-
-//---------------------------------------------------------------------------
-// Set-up variables needed by readAttributes operPtr.p, tabptr.p
-//---------------------------------------------------------------------------
- operPtr.p = regOperPtr;
- tabptr.i = regFragPtr->fragTableId;
- ptrCheckGuard(tabptr, cnoOfTablerec, tablerec);
-
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 num_attr= regTabPtr->m_no_of_attributes;
- Uint32 descr_start= regTabPtr->tabDescriptor;
- ndbrequire(descr_start + (num_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
-
- req_struct->check_offset[MM]= regTabPtr->get_check_offset(MM);
- req_struct->check_offset[DD]= regTabPtr->get_check_offset(DD);
- req_struct->attr_descr= &tableDescriptor[descr_start];
-
-//--------------------------------------------------------------------
-// Read Primary Key Values
-//--------------------------------------------------------------------
- Tuple_header *save0= req_struct->m_tuple_ptr;
- if (regOperPtr->op_struct.op_type == ZDELETE &&
- !regOperPtr->is_first_operation())
- {
- jam();
- req_struct->m_tuple_ptr= (Tuple_header*)
- c_undo_buffer.get_ptr(&req_struct->prevOpPtr.p->m_copy_tuple_location);
- }
-
- if (regTabPtr->need_expand(disk))
- prepare_read(req_struct, regTabPtr, disk);
-
- int ret = readAttributes(req_struct,
- &tableDescriptor[regTabPtr->readKeyArray].tabDescr,
- regTabPtr->noOfKeyAttr,
- keyBuffer,
- ZATTR_BUFFER_SIZE,
- false);
- ndbrequire(ret != -1);
- noPrimKey= ret;
-
- req_struct->m_tuple_ptr = save0;
-
- Uint32 numAttrsToRead;
- if ((regOperPtr->op_struct.op_type == ZUPDATE) &&
- (trigPtr->sendOnlyChangedAttributes)) {
- jam();
-//--------------------------------------------------------------------
-// Update that sends only changed information
-//--------------------------------------------------------------------
- Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
- attributeMask = trigPtr->attributeMask;
- attributeMask.bitAND(req_struct->changeMask);
- numAttrsToRead = setAttrIds(attributeMask, regTabPtr->m_no_of_attributes,
- &readBuffer[0]);
-
- } else if ((regOperPtr->op_struct.op_type == ZDELETE) &&
- (!trigPtr->sendBeforeValues)) {
- jam();
-//--------------------------------------------------------------------
-// Delete without sending before values only read Primary Key
-//--------------------------------------------------------------------
- return true;
- } else {
- jam();
-//--------------------------------------------------------------------
-// All others send all attributes that are monitored, except:
-// Omit unchanged blob inlines on update i.e.
-// attributeMask & ~ (blobAttributeMask & ~ changeMask)
-//--------------------------------------------------------------------
- Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
- attributeMask = trigPtr->attributeMask;
- if (regOperPtr->op_struct.op_type == ZUPDATE) {
- Bitmask<MAXNROFATTRIBUTESINWORDS> tmpMask = regTabPtr->blobAttributeMask;
- tmpMask.bitANDC(req_struct->changeMask);
- attributeMask.bitANDC(tmpMask);
- }
- numAttrsToRead = setAttrIds(attributeMask, regTabPtr->m_no_of_attributes,
- &readBuffer[0]);
- }
- ndbrequire(numAttrsToRead < MAX_ATTRIBUTES_IN_TABLE);
-//--------------------------------------------------------------------
-// Read Main tuple values
-//--------------------------------------------------------------------
- if (regOperPtr->op_struct.op_type != ZDELETE)
- {
- jam();
- int ret = readAttributes(req_struct,
- &readBuffer[0],
- numAttrsToRead,
- afterBuffer,
- ZATTR_BUFFER_SIZE,
- false);
- ndbrequire(ret != -1);
- noAfterWords= ret;
- } else {
- jam();
- noAfterWords = 0;
- }
-
-//--------------------------------------------------------------------
-// Read Copy tuple values for UPDATE's
-//--------------------------------------------------------------------
-// Initialise pagep and tuple offset for read of copy tuple
-//--------------------------------------------------------------------
- if ((regOperPtr->op_struct.op_type == ZUPDATE ||
- regOperPtr->op_struct.op_type == ZDELETE) &&
- (trigPtr->sendBeforeValues)) {
- jam();
-
- Tuple_header *save= req_struct->m_tuple_ptr;
- PagePtr tmp;
- if(regOperPtr->is_first_operation())
- {
- Uint32 *ptr= get_ptr(&tmp, &regOperPtr->m_tuple_location, regTabPtr);
- req_struct->m_tuple_ptr= (Tuple_header*)ptr;
- }
- else
- {
- Uint32 *ptr=
- c_undo_buffer.get_ptr(&req_struct->prevOpPtr.p->m_copy_tuple_location);
-
- req_struct->m_tuple_ptr= (Tuple_header*)ptr;
- }
-
- if (regTabPtr->need_expand(disk))
- prepare_read(req_struct, regTabPtr, disk);
-
- int ret = readAttributes(req_struct,
- &readBuffer[0],
- numAttrsToRead,
- beforeBuffer,
- ZATTR_BUFFER_SIZE,
- false);
- req_struct->m_tuple_ptr= save;
- ndbrequire(ret != -1);
- noBeforeWords = ret;
- if (trigPtr->m_receiverBlock != SUMA &&
- (noAfterWords == noBeforeWords) &&
- (memcmp(afterBuffer, beforeBuffer, noAfterWords << 2) == 0)) {
-//--------------------------------------------------------------------
-// Although a trigger was fired it was not necessary since the old
-// value and the new value was exactly the same
-//--------------------------------------------------------------------
- jam();
- //XXX does this work with collations?
- return false;
- }
- }
- return true;
-}
-
-void Dbtup::sendTrigAttrInfo(Signal* signal,
- Uint32* data,
- Uint32 dataLen,
- bool executeDirect,
- BlockReference receiverReference)
-{
- TrigAttrInfo* const trigAttrInfo = (TrigAttrInfo *)signal->getDataPtrSend();
- Uint32 sigLen;
- Uint32 dataIndex = 0;
- do {
- sigLen = dataLen - dataIndex;
- if (sigLen > TrigAttrInfo::DataLength) {
- jam();
- sigLen = TrigAttrInfo::DataLength;
- }
- MEMCOPY_NO_WORDS(trigAttrInfo->getData(),
- data + dataIndex,
- sigLen);
- if (executeDirect) {
- jam();
- EXECUTE_DIRECT(receiverReference,
- GSN_TRIG_ATTRINFO,
- signal,
- TrigAttrInfo::StaticLength + sigLen);
- jamEntry();
- } else {
- jam();
- sendSignal(receiverReference,
- GSN_TRIG_ATTRINFO,
- signal,
- TrigAttrInfo::StaticLength + sigLen,
- JBB);
- }
- dataIndex += sigLen;
- } while (dataLen != dataIndex);
-}
-
-void Dbtup::sendFireTrigOrd(Signal* signal,
- KeyReqStruct *req_struct,
- Operationrec * const regOperPtr,
- TupTriggerData* const trigPtr,
- Uint32 fragmentId,
- Uint32 noPrimKeyWords,
- Uint32 noBeforeValueWords,
- Uint32 noAfterValueWords)
-{
- FireTrigOrd* const fireTrigOrd = (FireTrigOrd *)signal->getDataPtrSend();
-
- fireTrigOrd->setConnectionPtr(req_struct->TC_index);
- fireTrigOrd->setTriggerId(trigPtr->triggerId);
- fireTrigOrd->fragId= fragmentId;
-
- switch(regOperPtr->op_struct.op_type) {
- case(ZINSERT):
- jam();
- fireTrigOrd->setTriggerEvent(TriggerEvent::TE_INSERT);
- break;
- case(ZDELETE):
- jam();
- fireTrigOrd->setTriggerEvent(TriggerEvent::TE_DELETE);
- break;
- case(ZUPDATE):
- jam();
- fireTrigOrd->setTriggerEvent(TriggerEvent::TE_UPDATE);
- break;
- default:
- ndbrequire(false);
- break;
- }
-
- fireTrigOrd->setNoOfPrimaryKeyWords(noPrimKeyWords);
- fireTrigOrd->setNoOfBeforeValueWords(noBeforeValueWords);
- fireTrigOrd->setNoOfAfterValueWords(noAfterValueWords);
-
- switch(trigPtr->triggerType) {
- case (TriggerType::SECONDARY_INDEX):
- jam();
- sendSignal(req_struct->TC_ref, GSN_FIRE_TRIG_ORD,
- signal, FireTrigOrd::SignalLength, JBB);
- break;
- case (TriggerType::SUBSCRIPTION_BEFORE): // Only Suma
- jam();
- // Since only backup uses subscription triggers we
- // send to backup directly for now
- fireTrigOrd->setGCI(req_struct->gci);
- fireTrigOrd->setHashValue(req_struct->hash_value);
- fireTrigOrd->m_any_value = regOperPtr->m_any_value;
- EXECUTE_DIRECT(trigPtr->m_receiverBlock,
- GSN_FIRE_TRIG_ORD,
- signal,
- FireTrigOrd::SignalLengthSuma);
- break;
- case (TriggerType::SUBSCRIPTION):
- jam();
- // Since only backup uses subscription triggers we
- // send to backup directly for now
- fireTrigOrd->setGCI(req_struct->gci);
- EXECUTE_DIRECT(trigPtr->m_receiverBlock,
- GSN_FIRE_TRIG_ORD,
- signal,
- FireTrigOrd::SignalWithGCILength);
- break;
- default:
- ndbrequire(false);
- break;
- }
-}
-
-/*
- * Ordered index triggers.
- *
- * Insert: add entry to index
- * Update: add entry to index, de|ay remove until commit
- * Delete: do nothing, delay remove until commit
- * Commit: remove entry delayed from update and delete
- * Abort : remove entry added by insert and update
- *
- * See Notes.txt for the details.
- */
-
-int
-Dbtup::executeTuxInsertTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr)
-{
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- // fill in constant part
- req->tableId = regFragPtr->fragTableId;
- req->fragId = regFragPtr->fragmentId;
- req->pageId = regOperPtr->m_tuple_location.m_page_no;
- req->pageIndex = regOperPtr->m_tuple_location.m_page_idx;
- req->tupVersion = regOperPtr->tupVersion;
- req->opInfo = TuxMaintReq::OpAdd;
- return addTuxEntries(signal, regOperPtr, regTabPtr);
-}
-
-int
-Dbtup::executeTuxUpdateTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr)
-{
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- // fill in constant part
- req->tableId = regFragPtr->fragTableId;
- req->fragId = regFragPtr->fragmentId;
- req->pageId = regOperPtr->m_tuple_location.m_page_no;
- req->pageIndex = regOperPtr->m_tuple_location.m_page_idx;
- req->tupVersion = regOperPtr->tupVersion;
- req->opInfo = TuxMaintReq::OpAdd;
- return addTuxEntries(signal, regOperPtr, regTabPtr);
-}
-
-int
-Dbtup::addTuxEntries(Signal* signal,
- Operationrec* regOperPtr,
- Tablerec* regTabPtr)
-{
- if (ERROR_INSERTED(4022)) {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- terrorCode = 9999;
- return -1;
- }
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- const DLList<TupTriggerData>& triggerList = regTabPtr->tuxCustomTriggers;
- TriggerPtr triggerPtr;
- Uint32 failPtrI;
- triggerList.first(triggerPtr);
- while (triggerPtr.i != RNIL) {
- jam();
- req->indexId = triggerPtr.p->indexId;
- req->errorCode = RNIL;
- if (ERROR_INSERTED(4023) &&
- ! triggerList.hasNext(triggerPtr)) {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- terrorCode = 9999;
- failPtrI = triggerPtr.i;
- goto fail;
- }
- EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
- signal, TuxMaintReq::SignalLength);
- jamEntry();
- if (req->errorCode != 0) {
- jam();
- terrorCode = req->errorCode;
- failPtrI = triggerPtr.i;
- goto fail;
- }
- triggerList.next(triggerPtr);
- }
- return 0;
-fail:
- req->opInfo = TuxMaintReq::OpRemove;
- triggerList.first(triggerPtr);
- while (triggerPtr.i != failPtrI) {
- jam();
- req->indexId = triggerPtr.p->indexId;
- req->errorCode = RNIL;
- EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
- signal, TuxMaintReq::SignalLength);
- jamEntry();
- ndbrequire(req->errorCode == 0);
- triggerList.next(triggerPtr);
- }
-#ifdef VM_TRACE
- ndbout << "aborted partial tux update: op " << hex << regOperPtr << endl;
-#endif
- return -1;
-}
-
-int
-Dbtup::executeTuxDeleteTriggers(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr)
-{
- // do nothing
- return 0;
-}
-
-void
-Dbtup::executeTuxCommitTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr)
-{
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- Uint32 tupVersion;
- if (regOperPtr->op_struct.op_type == ZINSERT) {
- if (! regOperPtr->op_struct.delete_insert_flag)
- return;
- jam();
- tupVersion= decr_tup_version(regOperPtr->tupVersion);
- } else if (regOperPtr->op_struct.op_type == ZUPDATE) {
- jam();
- tupVersion= decr_tup_version(regOperPtr->tupVersion);
- } else if (regOperPtr->op_struct.op_type == ZDELETE) {
- if (regOperPtr->op_struct.delete_insert_flag)
- return;
- jam();
- tupVersion= regOperPtr->tupVersion;
- } else {
- ndbrequire(false);
- tupVersion= 0; // remove warning
- }
- // fill in constant part
- req->tableId = regFragPtr->fragTableId;
- req->fragId = regFragPtr->fragmentId;
- req->pageId = regOperPtr->m_tuple_location.m_page_no;
- req->pageIndex = regOperPtr->m_tuple_location.m_page_idx;
- req->tupVersion = tupVersion;
- req->opInfo = TuxMaintReq::OpRemove;
- removeTuxEntries(signal, regTabPtr);
-}
-
-void
-Dbtup::executeTuxAbortTriggers(Signal* signal,
- Operationrec* regOperPtr,
- Fragrecord* regFragPtr,
- Tablerec* regTabPtr)
-{
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- // get version
- Uint32 tupVersion;
- if (regOperPtr->op_struct.op_type == ZINSERT) {
- jam();
- tupVersion = regOperPtr->tupVersion;
- } else if (regOperPtr->op_struct.op_type == ZUPDATE) {
- jam();
- tupVersion = regOperPtr->tupVersion;
- } else if (regOperPtr->op_struct.op_type == ZDELETE) {
- jam();
- return;
- } else {
- ndbrequire(false);
- tupVersion= 0; // remove warning
- }
- // fill in constant part
- req->tableId = regFragPtr->fragTableId;
- req->fragId = regFragPtr->fragmentId;
- req->pageId = regOperPtr->m_tuple_location.m_page_no;
- req->pageIndex = regOperPtr->m_tuple_location.m_page_idx;
- req->tupVersion = tupVersion;
- req->opInfo = TuxMaintReq::OpRemove;
- removeTuxEntries(signal, regTabPtr);
-}
-
-void
-Dbtup::removeTuxEntries(Signal* signal,
- Tablerec* regTabPtr)
-{
- TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- const DLList<TupTriggerData>& triggerList = regTabPtr->tuxCustomTriggers;
- TriggerPtr triggerPtr;
- triggerList.first(triggerPtr);
- while (triggerPtr.i != RNIL) {
- jam();
- req->indexId = triggerPtr.p->indexId;
- req->errorCode = RNIL,
- EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
- signal, TuxMaintReq::SignalLength);
- jamEntry();
- // must succeed
- ndbrequire(req->errorCode == 0);
- triggerList.next(triggerPtr);
- }
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp
deleted file mode 100644
index 499a05a40f6..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
-/* Copyright (c) 2004-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUP_C
-#define DBTUP_VAR_ALLOC_CPP
-#include "Dbtup.hpp"
-
-void Dbtup::init_list_sizes(void)
-{
- c_min_list_size[0]= 200;
- c_max_list_size[0]= 499;
-
- c_min_list_size[1]= 500;
- c_max_list_size[1]= 999;
-
- c_min_list_size[2]= 1000;
- c_max_list_size[2]= 4079;
-
- c_min_list_size[3]= 4080;
- c_max_list_size[3]= 8159;
-
- c_min_list_size[4]= 0;
- c_max_list_size[4]= 199;
-}
-
-/*
- Allocator for variable sized segments
- Part of the external interface for variable sized segments
-
- This method is used to allocate and free variable sized tuples and
- parts of tuples. This part can be used to implement variable sized
- attributes without wasting memory. It can be used to support small
- BLOB's attached to the record. It can also be used to support adding
- and dropping attributes without the need to copy the entire table.
-
- SYNOPSIS
- fragPtr A pointer to the fragment description
- tabPtr A pointer to the table description
- alloc_size Size of the allocated record
- signal The signal object to be used if a signal needs to
- be sent
- RETURN VALUES
- Returns true if allocation was successful otherwise false
-
- page_offset Page offset of allocated record
- page_index Page index of allocated record
- page_ptr The i and p value of the page where the record was
- allocated
-*/
-Uint32* Dbtup::alloc_var_rec(Fragrecord* fragPtr,
- Tablerec* tabPtr,
- Uint32 alloc_size,
- Local_key* key,
- Uint32 * out_frag_page_id)
-{
- /**
- * TODO alloc fix+var part
- */
- Uint32 *ptr = alloc_fix_rec(fragPtr, tabPtr, key, out_frag_page_id);
- if (unlikely(ptr == 0))
- {
- return 0;
- }
-
- ndbassert(alloc_size >= tabPtr->m_offsets[MM].m_fix_header_size);
-
- alloc_size -= tabPtr->m_offsets[MM].m_fix_header_size;
-
-
- Local_key varref;
- if (likely(alloc_var_part(fragPtr, tabPtr, alloc_size, &varref) != 0))
- {
- Tuple_header* tuple = (Tuple_header*)ptr;
- Var_part_ref* dst = tuple->get_var_part_ref_ptr(tabPtr);
- dst->assign(&varref);
- return ptr;
- }
-
- PagePtr pagePtr;
- c_page_pool.getPtr(pagePtr, key->m_page_no);
- free_fix_rec(fragPtr, tabPtr, key, (Fix_page*)pagePtr.p);
- return 0;
-}
-
-Uint32*
-Dbtup::alloc_var_part(Fragrecord* fragPtr,
- Tablerec* tabPtr,
- Uint32 alloc_size,
- Local_key* key)
-{
- PagePtr pagePtr;
- pagePtr.i= get_alloc_page(fragPtr, (alloc_size + 1));
- if (pagePtr.i == RNIL) {
- jam();
- if ((pagePtr.i= get_empty_var_page(fragPtr)) == RNIL) {
- jam();
- return 0;
- }
- c_page_pool.getPtr(pagePtr);
- ((Var_page*)pagePtr.p)->init();
- pagePtr.p->list_index = MAX_FREE_LIST - 1;
- LocalDLList<Page> list(c_page_pool,
- fragPtr->free_var_page_array[MAX_FREE_LIST-1]);
- list.add(pagePtr);
- /*
- * Tup scan and index build check ZEMPTY_MM to skip un-init()ed
- * page. Change state here. For varsize it means "page in use".
- */
- pagePtr.p->page_state = ZTH_MM_FREE;
- } else {
- c_page_pool.getPtr(pagePtr);
- jam();
- }
- Uint32 idx= ((Var_page*)pagePtr.p)
- ->alloc_record(alloc_size, (Var_page*)ctemp_page, Var_page::CHAIN);
-
- key->m_page_no = pagePtr.i;
- key->m_page_idx = idx;
-
- update_free_page_list(fragPtr, pagePtr);
- return ((Var_page*)pagePtr.p)->get_ptr(idx);
-}
-
-/*
- Deallocator for variable sized segments
- Part of the external interface for variable sized segments
-
- SYNOPSIS
- fragPtr A pointer to the fragment description
- tabPtr A pointer to the table description
- signal The signal object to be used if a signal needs to
- be sent
- page_ptr A reference to the page of the variable sized
- segment
- free_page_index Page index on page of variable sized segment
- which is freed
- RETURN VALUES
- Returns true if deallocation was successful otherwise false
-*/
-void Dbtup::free_var_rec(Fragrecord* fragPtr,
- Tablerec* tabPtr,
- Local_key* key,
- Ptr<Page> pagePtr)
-{
- /**
- * TODO free fix + var part
- */
- Uint32 *ptr = ((Fix_page*)pagePtr.p)->get_ptr(key->m_page_idx, 0);
- Tuple_header* tuple = (Tuple_header*)ptr;
-
- Local_key ref;
- Var_part_ref * varref = tuple->get_var_part_ref_ptr(tabPtr);
- varref->copyout(&ref);
-
- free_fix_rec(fragPtr, tabPtr, key, (Fix_page*)pagePtr.p);
-
- c_page_pool.getPtr(pagePtr, ref.m_page_no);
- ((Var_page*)pagePtr.p)->free_record(ref.m_page_idx, Var_page::CHAIN);
-
- ndbassert(pagePtr.p->free_space <= Var_page::DATA_WORDS);
- if (pagePtr.p->free_space == Var_page::DATA_WORDS - 1)
- {
- jam();
- /*
- This code could be used when we release pages.
- remove_free_page(signal,fragPtr,page_header,page_header->list_index);
- return_empty_page(fragPtr, page_header);
- */
- update_free_page_list(fragPtr, pagePtr);
- } else {
- jam();
- update_free_page_list(fragPtr, pagePtr);
- }
- return;
-}
-
-int
-Dbtup::realloc_var_part(Fragrecord* fragPtr, Tablerec* tabPtr, PagePtr pagePtr,
- Var_part_ref* refptr, Uint32 oldsz, Uint32 newsz)
-{
- Uint32 add = newsz - oldsz;
- Var_page* pageP = (Var_page*)pagePtr.p;
- Local_key oldref;
- refptr->copyout(&oldref);
-
- if (pageP->free_space >= add)
- {
- jam();
- if(!pageP->is_space_behind_entry(oldref.m_page_idx, add))
- {
- if(0) printf("extra reorg");
- jam();
- /**
- * In this case we need to reorganise the page to fit. To ensure we
- * don't complicate matters we make a little trick here where we
- * fool the reorg_page to avoid copying the entry at hand and copy
- * that separately at the end. This means we need to copy it out of
- * the page before reorg_page to save the entry contents.
- */
- Uint32* copyBuffer= cinBuffer;
- memcpy(copyBuffer, pageP->get_ptr(oldref.m_page_idx), 4*oldsz);
- pageP->set_entry_len(oldref.m_page_idx, 0);
- pageP->free_space += oldsz;
- pageP->reorg((Var_page*)ctemp_page);
- memcpy(pageP->get_free_space_ptr(), copyBuffer, 4*oldsz);
- pageP->set_entry_offset(oldref.m_page_idx, pageP->insert_pos);
- add += oldsz;
- }
- pageP->grow_entry(oldref.m_page_idx, add);
- update_free_page_list(fragPtr, pagePtr);
- }
- else
- {
- Local_key newref;
- Uint32 *src = pageP->get_ptr(oldref.m_page_idx);
- Uint32 *dst = alloc_var_part(fragPtr, tabPtr, newsz, &newref);
- if (unlikely(dst == 0))
- return -1;
-
- ndbassert(oldref.m_page_no != newref.m_page_no);
- ndbassert(pageP->get_entry_len(oldref.m_page_idx) == oldsz);
- memcpy(dst, src, 4*oldsz);
- refptr->assign(&newref);
-
- pageP->free_record(oldref.m_page_idx, Var_page::CHAIN);
- update_free_page_list(fragPtr, pagePtr);
- }
-
- return 0;
-}
-
-
-/* ------------------------------------------------------------------------ */
-// Get a page from one of free lists. If the desired free list is empty we
-// try with the next until we have tried all possible lists.
-/* ------------------------------------------------------------------------ */
-Uint32
-Dbtup::get_alloc_page(Fragrecord* fragPtr, Uint32 alloc_size)
-{
- Uint32 i, start_index, loop= 0;
- PagePtr pagePtr;
-
- start_index= calculate_free_list_impl(alloc_size);
- if (start_index == (MAX_FREE_LIST - 1)) {
- jam();
- } else {
- jam();
- ndbrequire(start_index < (MAX_FREE_LIST - 1));
- start_index++;
- }
- for (i= start_index; i < MAX_FREE_LIST; i++) {
- jam();
- if (!fragPtr->free_var_page_array[i].isEmpty()) {
- jam();
- return fragPtr->free_var_page_array[i].firstItem;
- }
- }
- ndbrequire(start_index > 0);
- i= start_index - 1;
- LocalDLList<Page> list(c_page_pool, fragPtr->free_var_page_array[i]);
- for(list.first(pagePtr); !pagePtr.isNull() && loop < 16; )
- {
- jam();
- if (pagePtr.p->free_space >= alloc_size) {
- jam();
- return pagePtr.i;
- }
- loop++;
- list.next(pagePtr);
- }
- return RNIL;
-}
-
-Uint32
-Dbtup::get_empty_var_page(Fragrecord* fragPtr)
-{
- PagePtr ptr;
- LocalSLList<Page> list(c_page_pool, fragPtr->m_empty_pages);
- if (list.remove_front(ptr))
- {
- return ptr.i;
- }
-
- Uint32 cnt;
- allocConsPages(10, cnt, ptr.i);
- fragPtr->noOfVarPages+= cnt;
- if (unlikely(cnt == 0))
- {
- return RNIL;
- }
-
- PagePtr ret = ptr;
- for (Uint32 i = 0; i<cnt; i++, ptr.i++)
- {
- c_page_pool.getPtr(ptr);
- ptr.p->physical_page_id = ptr.i;
- ptr.p->page_state = ZEMPTY_MM;
- ptr.p->nextList = ptr.i + 1;
- ptr.p->prevList = RNIL;
- ptr.p->frag_page_id = RNIL;
- }
-
- if (cnt > 1)
- {
- ptr.p->nextList = RNIL;
- list.add(ret.i + 1, ptr);
- }
-
- c_page_pool.getPtr(ret);
-
- Var_page* page = (Var_page*)ret.p;
- page->chunk_size = cnt;
- page->next_chunk = fragPtr->m_var_page_chunks;
- fragPtr->m_var_page_chunks = ret.i;
-
- return ret.i;
-}
-
-/* ------------------------------------------------------------------------ */
-// Check if the page needs to go to a new free page list.
-/* ------------------------------------------------------------------------ */
-void Dbtup::update_free_page_list(Fragrecord* fragPtr,
- Ptr<Page> pagePtr)
-{
- Uint32 free_space, list_index;
- free_space= pagePtr.p->free_space;
- list_index= pagePtr.p->list_index;
- if ((free_space < c_min_list_size[list_index]) ||
- (free_space > c_max_list_size[list_index])) {
- Uint32 new_list_index= calculate_free_list_impl(free_space);
- if (list_index != MAX_FREE_LIST) {
- jam();
- /*
- * Only remove it from its list if it is in a list
- */
- LocalDLList<Page>
- list(c_page_pool, fragPtr->free_var_page_array[list_index]);
- list.remove(pagePtr);
- }
- if (free_space < c_min_list_size[new_list_index]) {
- /*
- We have not sufficient amount of free space to put it into any
- free list. Thus the page will not be available for new inserts.
- This can only happen for the free list with least guaranteed
- free space.
- */
- jam();
- ndbrequire(new_list_index == 0);
- pagePtr.p->list_index= MAX_FREE_LIST;
- } else {
- jam();
- LocalDLList<Page> list(c_page_pool,
- fragPtr->free_var_page_array[new_list_index]);
- list.add(pagePtr);
- pagePtr.p->list_index = new_list_index;
- }
- }
-}
-
-/* ------------------------------------------------------------------------ */
-// Given size of free space, calculate the free list to put it into
-/* ------------------------------------------------------------------------ */
-Uint32 Dbtup::calculate_free_list_impl(Uint32 free_space_size) const
-{
- Uint32 i;
- for (i = 0; i < MAX_FREE_LIST; i++) {
- jam();
- if (free_space_size <= c_max_list_size[i]) {
- jam();
- return i;
- }
- }
- ndbrequire(false);
- return 0;
-}
-
-Uint32*
-Dbtup::alloc_var_rowid(Fragrecord* fragPtr,
- Tablerec* tabPtr,
- Uint32 alloc_size,
- Local_key* key,
- Uint32 * out_frag_page_id)
-{
- Uint32 *ptr = alloc_fix_rowid(fragPtr, tabPtr, key, out_frag_page_id);
- if (unlikely(ptr == 0))
- {
- return 0;
- }
-
- ndbassert(alloc_size >= tabPtr->m_offsets[MM].m_fix_header_size);
-
- alloc_size -= tabPtr->m_offsets[MM].m_fix_header_size;
-
- Local_key varref;
- if (likely(alloc_var_part(fragPtr, tabPtr, alloc_size, &varref) != 0))
- {
- Tuple_header* tuple = (Tuple_header*)ptr;
- Var_part_ref* dst = (Var_part_ref*)tuple->get_var_part_ref_ptr(tabPtr);
- dst->assign(&varref);
- return ptr;
- }
-
- PagePtr pagePtr;
- c_page_pool.getPtr(pagePtr, key->m_page_no);
- free_fix_rec(fragPtr, tabPtr, key, (Fix_page*)pagePtr.p);
- return 0;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/Makefile.am b/storage/ndb/src/kernel/blocks/dbtup/Makefile.am
deleted file mode 100644
index 3c424449dc5..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2004-2005 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
-
-EXTRA_PROGRAMS = test_varpage
-test_varpage_SOURCES = test_varpage.cpp tuppage.cpp
-test_varpage_LDFLAGS = @ndb_bin_am_ldflags@ \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
diff --git a/storage/ndb/src/kernel/blocks/dbtup/Notes.txt b/storage/ndb/src/kernel/blocks/dbtup/Notes.txt
deleted file mode 100644
index c2973bb0a76..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/Notes.txt
+++ /dev/null
@@ -1,198 +0,0 @@
-Operations, tuples, versions
-============================
-
-Operation types.
-
-INSERT insert new original tuple, or insert after delete
-UPDATE update
-DELETE delete
-
-Following need not be considered here.
-
-READ does not change tuples or versions
-WRITE turns into INSERT or UPDATE in LQH
-
-We use more specific names in some cases:
-
-first/INSERT initial insert of new tuple
-delete/INSERT INSERT preceded by DELETE
-DELETE/last DELETE as last operation
-DELETE/insert DELETE followed by INSERT
-
-Tuple + op Can be followed by
--------------- ------------------
-does not exist first/INSERT
-tuple exists UPDATE DELETE
-INSERT UPDATE DELETE
-UPDATE UPDATE DELETE
-DELETE delete/INSERT
-
-Operations on same tuple are kept in doubly linked list until
-commit or abort. The links at both ends are RNIL i.e. the list
-is not circular. The links are:
-
-nextActiveOp the operation BEFORE this one, in event order
-prevActiveOp the operation AFTER this one, in event order
-
-Operations are done on the "original tuple" i.e. the tuple is
-modified in place. If an operation is about to write over data
-in original tuple, it first copies the tuple to a "copy tuple".
-
-Operation Copy tuple
---------- ----------
-first/INSERT no
-delete/INSERT yes (this is in effect an update)
-UPDATE yes
-DELETE no
-
-The operation points to the tuples via:
-
-realPageId page i-value of original tuple
-pageOffset word offset of original tuple on the page
-realPageIdC page i-value of copy tuple or RNIL is no copy exists
-pageOffsetC word offset of copy tuple on the page
-
-The original tuple and the copy tuple (if any) point back to
-the operation via word 0. In copy tuple this pointer is never
-changed. In original tuple however it always points to the LATEST
-existing operation i.e. the one with prevActiveOp == RNIL.
-Thus word 0 of original tuple is changed on 2 occasions:
-
-- when a new operation is added to the list
-- when commit or abort removes the latest operation
-
-Note that commit/abort of operations occurs in random order.
-The list is adjusted accordingly.
-
-Versions
---------
-
-Tuple version is stored in tuple word 1. A new original tuple
-gets version 0. The version is incremented by each new operation
-which makes a copy tuple. Version number wraps around at 15 bits.
-
-When a copy tuple is made, the version in original tuple is copied
-to copy tuple as part of tuple data. This takes place before
-the version in original tuple is updated.
-
-Each operation record contains tuple version called tupVersion.
-
-- at insert of new original tuple, tupVersion is set to 0
-
-- if tuple already exists, the FIRST operation (in event order)
- reads tupVersion from tuple word 1. If the operation is
- not DELETE, the version is incremented
-
-- subsequent operation reads tupVersion from the operation
- BEFORE it (nextActiveOp). If this subsequent operation is
- not DELETE, the version is incremented
-
-When the operation writes the tuple it sets word 1 to tupVersion.
-In detail, per operation type, where INSERT is divided into
-insert of new original tuple and insert after delete:
-
-Operation Copy Increment Set version in original
---------- ---- --------- -----------------------
-first/INSERT no no yes, to 0
-delete/INSERT yes yes yes
-UPDATE yes yes yes
-DELETE no no no
-
-Thus an existing version is incremented if and only if
-a copy tuple is made.
-
-Ordered index maintenance
--------------------------
-
-Each index entry has logical tuple address and tuple version.
-Index entries are added during prepare phase (when each operation
-is executed) and removed during commit or abort phase.
-
-Access to correct tuple version (original or copy) is required
-in TUX which reads index key values 1) to check that at least one
-is not null 2) to do tree search 3) to set min/max prefixes.
-See "Read attributes" below.
-
-An additional complication is that commit/abort of operations
-arrives in random order. So we cannot check for, for example,
-DELETE/insert by looking at prevActiveOp.
-
-Phase Op Action Version in
------ -- ------ ----------
-prepare INSERT add op and original
-prepare UPDATE add op and original
-prepare DELETE none -
-
-commit first/INSERT none -
-commit delete/INSERT remove copy tuple 1)
-commit UPDATE remove copy tuple 1)
-commit DELETE/last remove op and original
-commit DELETE/insert none -
-
-abort INSERT remove op
-abort UPDATE remove op
-abort DELETE none -
-
-1) alternatively, store prevTupVersion in operation record.
-
-Abort from ordered index error
-------------------------------
-
-Obviously, index update failure causes operation failure.
-The operation is then aborted later by TC.
-
-The problem here is with multiple indexes. Some may have been
-updated successfully before the one that failed. Therefore
-the trigger code aborts the successful ones already in
-the prepare phase.
-
-In other words, multiple indexes are treated as one.
-
-Abort from any cause
---------------------
-
-[ hairy stuff ]
-
-Read attributes, query status
------------------------------
-
-TUP_READ_ATTRS signal (or equivalent direct call) reads attribute
-values. Input is logical address of original tuple and tuple
-version. The steps are:
-
-- Translate logical address to physical address of original tuple.
-
-- If version of original tuple in word 1 is right, stop.
-
-- Otherwise word 0 points to LATEST not yet deleted operation.
- Walk through operation list via nextActiveOp.
-
-- If an operation on the list has realPageIdC == RNIL, skip it.
-
-- Otherwise find copy tuple via realPageIdC, pageOffsetC.
- If the version of the copy tuple in word 1 is right, stop.
-
-- Call readAttributes() on the tuple found (original or copy).
-
-In short, the version must exist in some not yet deleted tuple,
-either in original or in some copy.
-
-Note that this must work during all phases since index code
-needs to read index key attributes from correct tuple version in
-each add/remove operation.
-
-TUP_QUERY_TH signal (or equivalent direct call) does same search
-for tuple version. It is called from index scan and returns info
-used to decide if the scan can see the tuple.
-
-This signal may also be called during any phase since commit/abort
-of all operations is not done in one time-slice.
-
-Problems
---------
-
-Current abort code can destroy a tuple version too early. This
-happens in test case "ticuur" (insert-commit-update-update-rollback),
-if abort of first update arrives before abort of second update.
-
-vim: set textwidth=68:
diff --git a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp
deleted file mode 100644
index bb45f4e0e0e..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "Undo_buffer.hpp"
-#define DBTUP_C
-#include "Dbtup.hpp"
-
-#if ZPAGE_STATE_POS != 0
-#error "PROBLEM!"
-#endif
-
-struct UndoPage
-{
- File_formats::Page_header m_page_header;
- Uint32 _tupdata1;
- Uint32 m_state; // Used by buddy alg
- Uint32 m_words_used;
- Uint32 m_ref_count;
- Uint32 m_data[GLOBAL_PAGE_SIZE_WORDS-4-(sizeof(File_formats::Page_header)>>2)];
-
- STATIC_CONST( DATA_WORDS = GLOBAL_PAGE_SIZE_WORDS-4-(sizeof(File_formats::Page_header)>>2) );
-};
-
-Undo_buffer::Undo_buffer(Dbtup* tup)
-{
- m_tup= tup;
- m_first_free= RNIL;
-}
-
-Uint32 *
-Undo_buffer::alloc_copy_tuple(Local_key* dst, Uint32 words)
-{
- UndoPage* page;
- assert(words);
- if(m_first_free == RNIL)
- {
- Uint32 count;
- m_tup->allocConsPages(1, count, m_first_free);
- if(count == 0)
- return 0;
- page= (UndoPage*)m_tup->c_page_pool.getPtr(m_first_free);
- page->m_state= ~ZFREE_COMMON;
- page->m_words_used= 0;
- page->m_ref_count= 0;
- }
-
- page= (UndoPage*)m_tup->c_page_pool.getPtr(m_first_free);
-
- Uint32 pos= page->m_words_used;
- if(words + pos > UndoPage::DATA_WORDS)
- {
- m_first_free= RNIL;
- return alloc_copy_tuple(dst, words);
- }
-
- dst->m_page_no = m_first_free;
- dst->m_page_idx = pos;
-
- page->m_ref_count++;
- page->m_words_used = pos + words;
- return page->m_data + pos;
-}
-
-void
-Undo_buffer::shrink_copy_tuple(Local_key* key, Uint32 words)
-{
- assert(key->m_page_no == m_first_free);
- UndoPage* page= (UndoPage*)m_tup->c_page_pool.getPtr(key->m_page_no);
- assert(page->m_words_used >= words);
- page->m_words_used -= words;
-}
-
-void
-Undo_buffer::free_copy_tuple(Local_key* key)
-{
- UndoPage* page= (UndoPage*)m_tup->c_page_pool.getPtr(key->m_page_no);
- Uint32 cnt= page->m_ref_count;
- assert(cnt);
-
- page->m_ref_count= cnt - 1;
-
- if(cnt - 1 == 0)
- {
- page->m_words_used= 0;
- if(m_first_free == key->m_page_no)
- {
- //ndbout_c("resetting page");
- }
- else
- {
- //ndbout_c("returning page");
- m_tup->returnCommonArea(key->m_page_no, 1);
- }
- }
- key->setNull();
-}
-
-Uint32 *
-Undo_buffer::get_ptr(Local_key* key)
-{
- return ((UndoPage*)(m_tup->c_page_pool.getPtr(key->m_page_no)))->m_data+key->m_page_idx;
-}
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp
deleted file mode 100644
index 67ddefd0480..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef __UNDO_BUFFER_HPP
-#define __UNDO_BUFFER_HPP
-
-#include <ndb_global.h>
-#include <kernel_types.h>
-
-struct Undo_buffer
-{
- Undo_buffer(class Dbtup*);
-
- /**
- * Alloc space for a copy tuple of size <em>words</em>
- * store address to copy in dst
- * supply pointer to original in curr
- *
- * @return 0 if unable to alloc space
- */
- Uint32 * alloc_copy_tuple(Local_key* dst, Uint32 words);
-
- /**
- * Shrink size of copy tuple
- * note: Only shrink latest allocated tuple
- */
- void shrink_copy_tuple(Local_key* dst, Uint32 words);
-
- /**
- * Free space for copy tuple at key
- */
- void free_copy_tuple(Local_key* key);
-
- /**
- * Get pointer to copy tuple
- */
- Uint32 * get_ptr(Local_key* key);
-
-private:
- class Dbtup* m_tup;
- Uint32 m_first_free;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp b/storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp
deleted file mode 100644
index 2e52fe04949..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-/* Copyright (C) 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include <ndb_global.h>
-#include "tuppage.hpp"
-#include <Vector.hpp>
-
-struct Record
-{
- Uint32 idx;
- Uint32 size;
- Uint32* data;
-};
-
-NdbOut&
-operator <<(NdbOut& out, const Record& rec)
-{
- out << "[ idx: " << rec.idx << " sz: " << rec.size << " ]";
- return out;
-}
-
-#define TRACE(x) x
-
-static
-bool
-cmp(const Uint32 *p1, const Uint32 *p2, Uint32 words)
-{
- if(memcmp(p1, p2, 4*words) == 0)
- return true;
-
- for(Uint32 i = 0; i<words; i++)
- printf(" %.8x", p1[i]);
- printf("\n");
-
- for(Uint32 i = 0; i<words; i++)
- printf(" %.8x", p2[i]);
- printf("\n");
-
- return false;
-}
-
-static
-void
-do_test(int loops, int dist[5])
-{
- fprintf(stderr, "do_test(%d, [ %d %d %d %d %d ])\n",
- loops,
- dist[0],
- dist[1],
- dist[2],
- dist[3],
- dist[4]);
- int allocated= 0;
- Record records[8192];
-
- Tup_varsize_page page, tmp;
- page.init();
-
- for(int i = 0; i<loops; i++)
- {
- assert(page.high_index + page.insert_pos <= page.DATA_WORDS);
-
- for(int j = 0; j<allocated; j++)
- {
- Record rec= records[j];
- Uint32* ptr= page.get_ptr(rec.idx);
- Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
- if (page.get_entry_len(rec.idx) != rec.size)
- {
- ndbout << "INVALID LEN " << j << " " << rec << " pos: " << pos << endl;
- ndbout << page << endl;
- abort();
- }
-
- if(!cmp(ptr, rec.data, rec.size))
- {
- ndbout << "FAILED " << j << " " << rec << " pos: " << pos << endl;
- ndbout << page << endl;
- abort();
- }
- }
-
-loop:
- int op;
- int rnd= rand() % 100;
- for(op= 0; op<5; op++)
- if(rnd < dist[op])
- break;
-
- if(allocated == 0)
- op= 0;
- if(page.free_space <= 2 && op == 0) goto loop;
-
- switch(op){
- case 0: // Alloc
- {
- Record rec;
- rec.size= 1 + (rand() % (page.free_space-1));
- rec.data = new Uint32[rec.size];
- for(Uint32 i= 0; i<rec.size; i++)
- {
- rec.data[i] = rand();
- }
- ndbout << "Alloc hi: " << page.high_index << " (" <<
- ((rnd < 30) ? "any" :
- (rnd < 60) ? "dir" :
- (rnd < 80) ? "exp" : "fail") << ") ";
- ndbout << rec.size << flush;
- if (rnd < 30)
- {
- rec.idx= page.alloc_record(rec.size, &tmp, 0);
- }
- else if (rnd < 60)
- {
- // Alloc with id, from directory
- Vector<Uint32> free;
- for(Uint32 i = page.high_index - 1; i > 0; i--)
- {
- if (page.get_index_word(i) & page.FREE)
- {
- free.push_back(i);
- if (free.size() > 100)
- break;
- }
- }
- if (free.size())
- {
- rec.idx = free[rand() % free.size()];
- if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
- {
- abort();
- }
- }
- else
- {
- rec.idx = page.high_index;
- if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
- {
- if (rec.size + 1 != page.free_space)
- abort();
- delete [] rec.data;
- ndbout_c(" FAIL");
- break;
- }
- }
- }
- else if(rnd < 80)
- {
- // Alloc with id, outside of directory
- rec.idx = page.high_index + (rand() % (page.free_space - rec.size));
- if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
- {
- abort();
- }
- }
- else
- {
- rec.idx = page.high_index + (page.free_space - rec.size) + 1;
- if (page.alloc_record(rec.idx, rec.size, &tmp) == rec.idx)
- {
- abort();
- }
- delete [] rec.data;
- ndbout_c(" FAIL");
- break;
- }
-
- Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
- ndbout << " -> " << rec.idx
- << " pos: " << pos << endl;
- Uint32* ptr= page.get_ptr(rec.idx);
- memcpy(ptr, rec.data, 4*rec.size);
- records[allocated++] = rec;
- break;
- }
- case 1: // Free
- {
- int no= rand() % allocated;
- Record rec= records[no];
- Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
- ndbout << "Free hi: " << page.high_index << " no: " << no << " idx: " << rec.idx << " pos: " << pos << endl;
- Uint32* ptr= page.get_ptr(rec.idx);
- assert(page.get_entry_len(rec.idx) == rec.size);
- cmp(ptr, rec.data, rec.size);
- delete[] rec.data;
- page.free_record(rec.idx, 0);
-
- for (unsigned k = no; k + 1 < allocated; k++)
- records[k] = records[k+1];
- allocated--;
-
- break;
- }
- case 2: // Reorg
- ndbout << "Reorg" << endl;
- page.reorg(&tmp);
- break;
- case 3:
- {
- Uint32 free = page.free_space;
- if (free <= 2)
- {
- goto shrink;
- }
- free /= 2;
- int no = rand() % allocated;
- Record rec= records[no];
- ndbout << "Expand no: " << no << " idx: " << rec.idx
- << " add: " << free << " reorg: "
- << !page.is_space_behind_entry(rec.idx, free)
- << endl;
- if (!page.is_space_behind_entry(rec.idx, free))
- {
- Uint32 buffer[8192];
- Uint32 len = page.get_entry_len(rec.idx);
- memcpy(buffer, page.get_ptr(rec.idx), 4*len);
- page.set_entry_len(rec.idx, 0);
- page.free_space += len;
- page.reorg(&tmp);
- memcpy(page.get_free_space_ptr(), buffer, 4*len);
- page.set_entry_offset(rec.idx, page.insert_pos);
- free += len;
- records[no].size = 0;
- }
-
- page.grow_entry(rec.idx, free);
- records[no].size += free;
- Uint32 *ptr = page.get_ptr(rec.idx);
- Uint32 *new_data = new Uint32[records[no].size];
- for(Uint32 i= 0; i<records[no].size; i++)
- {
- ptr[i] = new_data[i] = rand();
- }
- delete []rec.data;
- records[no].data = new_data;
- break;
- }
- case 4:
- {
- shrink:
- int no = rand() % allocated;
- Record rec = records[no];
- Uint32 sz = rec.size / 2 + 1;
- ndbout << "Shrink no: " << no << " idx: " << rec.idx << " remove: "
- << (rec.size - sz) << endl;
- page.shrink_entry(rec.idx, sz);
- records[no].size = sz;
- break;
- }
- }
-
- }
- ndbout << page << endl;
-}
-
-int
-main(int argc, char **argv)
-{
- ndb_init();
-
- if (argc > 1)
- {
- time_t seed = time(0);
- srand(seed);
- fprintf(stderr, "srand(%d)\n", seed);
- }
- // alloc, free, reorg, grow, shrink
-
- int t1[] = { 10, 60, 70, 85, 100 };
- int t2[] = { 30, 60, 70, 85, 100 };
- int t3[] = { 50, 60, 70, 85, 100 };
-
- do_test(10000, t1);
- do_test(10000, t2);
- do_test(10000, t3);
-
- return 0;
-}
-
-template class Vector<Record>;
-
-// hp3750
-struct Signal { Signal(); int foo; };
-Signal::Signal(){}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp b/storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp
deleted file mode 100644
index 524592b99ee..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp
+++ /dev/null
@@ -1,480 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include "tuppage.hpp"
-#include "Dbtup.hpp"
-
-/**
- * Fix pages maintain a double linked list of free entries
- *
- * Var pages has a directory where each entry is
- * [ C(1), F(1), L(15), P(15) ]
- * C is chain bit, (is it a full tuple or just chain)
- * F is free bit
- * If true, L is prev free entry (in directory)
- * P is next free entry (in directory)
- * else
- * L is len of entry
- * P is pos of entry
- */
-
-Uint32
-Tup_fixsize_page::alloc_record()
-{
- assert(free_space);
- Uint32 page_idx = next_free_index;
- assert(page_idx + 1 < DATA_WORDS);
-
- Uint32 prev = m_data[page_idx] >> 16;
- Uint32 next = m_data[page_idx] & 0xFFFF;
-
- assert(prev == 0xFFFF);
- assert(m_data[page_idx + 1] == FREE_RECORD);
-
- m_data[page_idx + 1] = 0;
- if (next != 0xFFFF)
- {
- assert(free_space > 1);
- Uint32 nextP = m_data[next];
- assert((nextP >> 16) == page_idx);
- m_data[next] = 0xFFFF0000 | (nextP & 0xFFFF);
- }
- else
- {
- assert(free_space == 1);
- }
-
- next_free_index = next;
- free_space--;
- return page_idx;
-}
-
-Uint32
-Tup_fixsize_page::alloc_record(Uint32 page_idx)
-{
- assert(page_idx + 1 < DATA_WORDS);
- if (likely(free_space && m_data[page_idx + 1] == FREE_RECORD))
- {
- Uint32 prev = m_data[page_idx] >> 16;
- Uint32 next = m_data[page_idx] & 0xFFFF;
-
- assert(prev != 0xFFFF || (next_free_index == page_idx));
- if (prev == 0xFFFF)
- {
- next_free_index = next;
- }
- else
- {
- Uint32 prevP = m_data[prev];
- m_data[prev] = (prevP & 0xFFFF0000) | next;
- }
-
- if (next != 0xFFFF)
- {
- Uint32 nextP = m_data[next];
- m_data[next] = (prev << 16) | (nextP & 0xFFFF);
- }
- free_space --;
- m_data[page_idx + 1] = 0;
- return page_idx;
- }
- return ~0;
-}
-
-Uint32
-Tup_fixsize_page::free_record(Uint32 page_idx)
-{
- Uint32 next = next_free_index;
-
- assert(page_idx + 1 < DATA_WORDS);
- assert(m_data[page_idx + 1] != FREE_RECORD);
-
- if (next == 0xFFFF)
- {
- assert(free_space == 0);
- }
- else
- {
- assert(free_space);
- assert(next + 1 < DATA_WORDS);
- Uint32 nextP = m_data[next];
- assert((nextP >> 16) == 0xFFFF);
- m_data[next] = (page_idx << 16) | (nextP & 0xFFFF);
- assert(m_data[next + 1] == FREE_RECORD);
- }
-
- next_free_index = page_idx;
- m_data[page_idx] = 0xFFFF0000 | next;
- m_data[page_idx + 1] = FREE_RECORD;
-
- return ++free_space;
-}
-
-void
-Tup_varsize_page::init()
-{
- free_space= DATA_WORDS - 1;
- high_index= 1;
- insert_pos= 0;
- next_free_index= END_OF_FREE_LIST;
- m_page_header.m_page_type = File_formats::PT_Tup_varsize_page;
-}
-
-Uint32
-Tup_varsize_page::alloc_record(Uint32 page_idx, Uint32 alloc_size,
- Tup_varsize_page* temp)
-{
- assert(page_idx); // 0 is not allowed
- Uint32 free = free_space;
- Uint32 largest_size= DATA_WORDS - (insert_pos + high_index);
- Uint32 free_list = next_free_index;
-
- if (page_idx < high_index)
- {
- Uint32 *ptr = get_index_ptr(page_idx);
- Uint32 word = *ptr;
-
- if (unlikely((free < alloc_size) || ! (word & FREE)))
- {
- return ~0;
- }
-
- if (alloc_size >= largest_size)
- {
- /*
- We can't fit this segment between the insert position and the end of
- the index entries. We will pack the page so that all free space
- exists between the insert position and the end of the index entries.
- */
- reorg(temp);
- }
-
- Uint32 next = (word & NEXT_MASK) >> NEXT_SHIFT;
- Uint32 prev = (word & PREV_MASK) >> PREV_SHIFT;
-
- if (next != END_OF_FREE_LIST)
- {
- Uint32 * next_ptr = get_index_ptr(next);
- Uint32 next_word = * next_ptr;
- * next_ptr = (next_word & ~PREV_MASK) | (prev << PREV_SHIFT);
- }
-
- if (prev != END_OF_FREE_LIST)
- {
- Uint32 * prev_ptr = get_index_ptr(prev);
- Uint32 prev_word = * prev_ptr;
- * prev_ptr = (prev_word & ~NEXT_MASK) | (next << NEXT_SHIFT);
- }
- else
- {
- assert(next_free_index == page_idx);
- next_free_index = next;
- }
-
- * ptr = insert_pos + (alloc_size << LEN_SHIFT);
- free -= alloc_size;
- }
- else
- {
- /**
- * We need to expand directory
- */
- Uint32 hi = high_index;
- Uint32 expand = (page_idx + 1 - hi);
- Uint32 size = alloc_size + expand;
- if (unlikely(size > free))
- {
- return ~0;
- }
-
- if (size >= largest_size)
- {
- /*
- We can't fit this segment between the insert position and the end of
- the index entries. We will pack the page so that all free space
- exists between the insert position and the end of the index entries.
- */
- reorg(temp);
- }
-
- Uint32 *ptr = m_data + DATA_WORDS - hi;
- if (page_idx == hi)
- {
- * ptr = insert_pos + (alloc_size << LEN_SHIFT);
- }
- else
- {
- if (free_list != END_OF_FREE_LIST)
- {
- Uint32 * prev_ptr = get_index_ptr(free_list);
- Uint32 prev_word = * prev_ptr;
- * prev_ptr = (prev_word & ~PREV_MASK) | (hi << PREV_SHIFT);
- }
-
- for (; hi < page_idx;)
- {
- * ptr-- = FREE | (free_list << NEXT_SHIFT) | ((hi+1) << PREV_SHIFT);
- free_list = hi++;
- }
-
- * ptr++ = insert_pos + (alloc_size << LEN_SHIFT);
- * ptr = ((* ptr) & ~PREV_MASK) | (END_OF_FREE_LIST << PREV_SHIFT);
-
- next_free_index = hi - 1;
- }
- high_index = hi + 1;
- free -= size;
- }
-
- free_space = free;
- insert_pos += alloc_size;
-
- return page_idx;
-}
-
-Uint32
-Tup_varsize_page::alloc_record(Uint32 alloc_size,
- Tup_varsize_page* temp, Uint32 chain)
-{
- assert(free_space >= alloc_size);
- Uint32 largest_size= DATA_WORDS - (insert_pos + high_index);
- if (alloc_size >= largest_size) {
- /*
- We can't fit this segment between the insert position and the end of
- the index entries. We will pack the page so that all free space
- exists between the insert position and the end of the index entries.
- */
- reorg(temp);
- largest_size= DATA_WORDS - (insert_pos + high_index);
- }
- assert(largest_size > alloc_size);
-
- Uint32 page_idx;
- if (next_free_index == END_OF_FREE_LIST) {
- /*
- We are out of free index slots. We will extend the array of free
- slots
- */
- page_idx= high_index++;
- free_space--;
- } else {
- // Pick an empty slot among the index entries
- page_idx= next_free_index;
- assert((get_index_word(page_idx) & FREE) == FREE);
- assert(((get_index_word(page_idx) & PREV_MASK) >> PREV_SHIFT) ==
- END_OF_FREE_LIST);
- next_free_index= (get_index_word(page_idx) & NEXT_MASK) >> NEXT_SHIFT;
- assert(next_free_index);
- if (next_free_index != END_OF_FREE_LIST)
- {
- Uint32 *ptr = get_index_ptr(next_free_index);
- Uint32 word = *ptr;
- * ptr = (word & ~PREV_MASK) | (END_OF_FREE_LIST << PREV_SHIFT);
- }
- }
-
- assert(chain == 0 || chain == CHAIN);
- * get_index_ptr(page_idx) = insert_pos + chain + (alloc_size << LEN_SHIFT);
-
- insert_pos += alloc_size;
- free_space -= alloc_size;
- //ndbout_c("%p->alloc_record(%d%s) -> %d", this,alloc_size, (chain ? " CHAIN" : ""),page_idx);
- return page_idx;
-}
-
-Uint32
-Tup_varsize_page::free_record(Uint32 page_idx, Uint32 chain)
-{
- //ndbout_c("%p->free_record(%d%s)", this, page_idx, (chain ? " CHAIN": ""));
- Uint32 *index_ptr= get_index_ptr(page_idx);
- Uint32 index_word= * index_ptr;
- Uint32 entry_pos= (index_word & POS_MASK) >> POS_SHIFT;
- Uint32 entry_len= (index_word & LEN_MASK) >> LEN_SHIFT;
- assert(chain == 0 || chain == CHAIN);
- assert((index_word & CHAIN) == chain);
-#ifdef VM_TRACE
- memset(m_data + entry_pos, 0xF2, 4*entry_len);
-#endif
- if (page_idx + 1 == high_index) {
- /*
- We are removing the last in the entry list. We could potentially
- have several free entries also before this. To take that into account
- we will rebuild the free list and thus compress it and update the
- free space accordingly.
- */
- rebuild_index(index_ptr);
- } else {
- if (next_free_index != END_OF_FREE_LIST)
- {
- Uint32 *ptr = get_index_ptr(next_free_index);
- Uint32 word = *ptr;
- assert(((word & PREV_MASK) >> PREV_SHIFT) == END_OF_FREE_LIST);
- * ptr = (word & ~PREV_MASK) | (page_idx << PREV_SHIFT);
- }
- * index_ptr= FREE | next_free_index | (END_OF_FREE_LIST << PREV_SHIFT);
- next_free_index= page_idx;
- assert(next_free_index);
- }
-
- free_space+= entry_len;
- // If we're the "last" entry, decrease insert_pos
- insert_pos -= (entry_pos + entry_len == insert_pos ? entry_len : 0);
-
- return free_space;
-}
-
-void
-Tup_varsize_page::rebuild_index(Uint32* index_ptr)
-{
- Uint32 empty= 1;
- Uint32 *end= m_data + DATA_WORDS;
-
- /**
- * Scan until you find first non empty index pos
- */
- for(index_ptr++; index_ptr < end; index_ptr++)
- if((* index_ptr) & FREE)
- empty++;
- else
- break;
-
- if(index_ptr == end)
- {
- // Totally free page
- high_index = 1;
- free_space += empty;
- next_free_index = END_OF_FREE_LIST;
- return;
- }
-
- Uint32 next= END_OF_FREE_LIST;
- Uint32 dummy;
- Uint32 *prev_ptr = &dummy;
- for(index_ptr++; index_ptr < end; index_ptr++)
- {
- if ((* index_ptr) & FREE)
- {
- * index_ptr= FREE | next;
- next= (end - index_ptr);
- * prev_ptr |= (next << PREV_SHIFT);
- prev_ptr = index_ptr;
- }
- }
-
- * prev_ptr |= (END_OF_FREE_LIST << PREV_SHIFT);
-
- high_index -= empty;
- free_space += empty;
- next_free_index= next;
- assert(next_free_index);
-}
-
-void
-Tup_varsize_page::reorg(Tup_varsize_page* copy_page)
-{
- Uint32 new_insert_pos= 0;
- Uint32 old_insert_pos= insert_pos;
-
- // Copy key data part of page to a temporary page.
- memcpy(copy_page->m_data, m_data, 4*old_insert_pos);
- assert(high_index > 0);
- Uint32* index_ptr= get_index_ptr(high_index-1);
- Uint32 *end_of_page= m_data + DATA_WORDS;
- for (; index_ptr < end_of_page; index_ptr++)
- {
- Uint32 index_word= * index_ptr;
- Uint32 entry_len= (index_word & LEN_MASK) >> LEN_SHIFT;
- if (!(index_word & FREE) && entry_len)
- {
- /*
- We found an index item that needs to be packed.
- We will update the index entry and copy the data to the page.
- */
- Uint32 entry_pos= (index_word & POS_MASK) >> POS_SHIFT;
- assert(entry_pos + entry_len <= old_insert_pos);
- assert(new_insert_pos + entry_len <= old_insert_pos);
- * index_ptr= (new_insert_pos << POS_SHIFT) + (index_word & ~POS_MASK);
- memcpy(m_data+new_insert_pos, copy_page->m_data+entry_pos, 4*entry_len);
-
- new_insert_pos += entry_len;
- }
- }
- insert_pos= new_insert_pos;
-}
-
-NdbOut&
-operator<< (NdbOut& out, const Tup_varsize_page& page)
-{
- out << "[ Varpage " << &page << ": free: " << page.free_space
- << " (" << (page.DATA_WORDS - (page.insert_pos + page.high_index + 1)) << ")"
- << " insert_pos: " << page.insert_pos
- << " high_index: " << page.high_index
- << " index: " << flush;
-
- const Uint32 *index_ptr= page.m_data+page.DATA_WORDS-1;
- for(Uint32 i = 1; i<page.high_index; i++, index_ptr--)
- {
- out << " [ " << i;
- if(! (*index_ptr & page.FREE))
- out << " pos: " << ((* index_ptr & page.POS_MASK) >> page.POS_SHIFT)
- << " len: " << ((* index_ptr & page.LEN_MASK) >> page.LEN_SHIFT)
- << ((* index_ptr & page.CHAIN) ? " CHAIN " : " ")
- << "]" << flush;
- else
- out << " FREE ]" << flush;
- }
-
- out << " free list: " << flush;
- Uint32 next= page.next_free_index;
- while(next != page.END_OF_FREE_LIST)
- {
- out << next << " " << flush;
- next= ((* (page.m_data+page.DATA_WORDS-next)) & page.NEXT_MASK) >> page.NEXT_SHIFT;
- }
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<< (NdbOut& out, const Tup_fixsize_page& page)
-{
- out << "[ Fixpage " << &page
- << ": frag_page: " << page.frag_page_id
- << " page_no: " << page.m_page_no
- << " file_no: " << page.m_file_no
- << " table: " << page.m_table_id
- << " fragment: " << page.m_fragment_id
- << " uncommitted_used_space: " << page.uncommitted_used_space
- << " free: " << page.free_space;
-
- out << " free list: " << hex << page.next_free_index << " " << flush;
-#if 0
- Uint32 startTuple = page.next_free_index >> 16;
- Uint32 cnt = 0;
- Uint32 next= startTuple;
- while((next & 0xFFFF) != 0xFFFF)
- {
- cnt++;
- out << dec << "(" << (next & 0xFFFF) << " " << hex << next << ") " << flush;
- assert(page.m_data[(next & 0xFFFF) + 1] == Dbtup::Tuple_header::FREE);
- next= * (page.m_data + ( next & 0xFFFF ));
- }
- assert(cnt == page.free_space);
-#endif
- out << "]";
- return out;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp b/storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp
deleted file mode 100644
index 9558a911a86..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef __NDB_TUP_PAGE_HPP
-#define __NDB_TUP_PAGE_HPP
-
-#include <ndb_types.h>
-#include "../diskpage.hpp"
-
-struct Tup_page
-{
- struct File_formats::Page_header m_page_header;
- Uint32 m_restart_seq;
- Uint32 page_state;
- union {
- Uint32 next_page;
- Uint32 nextList;
- };
- union {
- Uint32 prev_page;
- Uint32 prevList;
- };
- Uint32 first_cluster_page;
- Uint32 last_cluster_page;
- Uint32 next_cluster_page;
- Uint32 prev_cluster_page;
- Uint32 frag_page_id;
- Uint32 physical_page_id;
- Uint32 free_space;
- Uint32 next_free_index;
- Uint32 list_index; // free space in page bits/list, 0x8000 means not in free
- Uint32 uncommitted_used_space;
- Uint32 m_page_no;
- Uint32 m_file_no;
- Uint32 m_table_id;
- Uint32 m_fragment_id;
- Uint32 m_extent_no;
- Uint32 m_extent_info_ptr;
- Uint32 unused_ph[9];
-
- STATIC_CONST( DATA_WORDS = File_formats::NDB_PAGE_SIZE_WORDS - 32 );
-
- Uint32 m_data[DATA_WORDS];
-};
-
-struct Tup_fixsize_page
-{
- struct File_formats::Page_header m_page_header;
- Uint32 m_restart_seq;
- Uint32 page_state;
- Uint32 next_page;
- Uint32 prev_page;
- Uint32 first_cluster_page;
- Uint32 last_cluster_page;
- Uint32 next_cluster_page;
- Uint32 prev_cluster_page;
- Uint32 frag_page_id;
- Uint32 physical_page_id;
- Uint32 free_space;
- Uint32 next_free_index;
- Uint32 list_index;
- Uint32 uncommitted_used_space;
- Uint32 m_page_no;
- Uint32 m_file_no;
- Uint32 m_table_id;
- Uint32 m_fragment_id;
- Uint32 m_extent_no;
- Uint32 m_extent_info_ptr;
- Uint32 unused_ph[9];
-
- STATIC_CONST( FREE_RECORD = ~(Uint32)0 );
- STATIC_CONST( DATA_WORDS = File_formats::NDB_PAGE_SIZE_WORDS - 32 );
-
- Uint32 m_data[DATA_WORDS];
-
- Uint32* get_ptr(Uint32 page_idx, Uint32 rec_size){
- assert(page_idx + rec_size <= DATA_WORDS);
- return m_data + page_idx;
- }
-
- /**
- * Alloc record from page
- * return page_idx
- **/
- Tup_fixsize_page() {}
- Uint32 alloc_record();
- Uint32 alloc_record(Uint32 page_idx);
- Uint32 free_record(Uint32 page_idx);
-};
-
-struct Tup_varsize_page
-{
- struct File_formats::Page_header m_page_header;
- Uint32 m_restart_seq;
- Uint32 page_state;
- Uint32 next_page;
- Uint32 prev_page;
- union {
- Uint32 first_cluster_page;
- Uint32 chunk_size;
- };
- union {
- Uint32 last_cluster_page;
- Uint32 next_chunk;
- };
- Uint32 next_cluster_page;
- Uint32 prev_cluster_page;
- Uint32 frag_page_id;
- Uint32 physical_page_id;
- Uint32 free_space;
- Uint32 next_free_index;
- Uint32 list_index;
- Uint32 uncommitted_used_space;
- Uint32 m_page_no;
- Uint32 m_file_no;
- Uint32 m_table_id;
- Uint32 m_fragment_id;
- Uint32 m_extent_no;
- Uint32 m_extent_info_ptr;
- Uint32 high_index; // size of index + 1
- Uint32 insert_pos;
- Uint32 unused_ph[7];
-
- STATIC_CONST( DATA_WORDS = File_formats::NDB_PAGE_SIZE_WORDS - 32 );
- STATIC_CONST( CHAIN = 0x80000000 );
- STATIC_CONST( FREE = 0x40000000 );
- STATIC_CONST( LEN_MASK = 0x3FFF8000 );
- STATIC_CONST( POS_MASK = 0x00007FFF );
- STATIC_CONST( LEN_SHIFT = 15 );
- STATIC_CONST( POS_SHIFT = 0 );
- STATIC_CONST( END_OF_FREE_LIST = POS_MASK );
-
- STATIC_CONST( NEXT_MASK = POS_MASK );
- STATIC_CONST( NEXT_SHIFT = POS_SHIFT );
- STATIC_CONST( PREV_MASK = LEN_MASK );
- STATIC_CONST( PREV_SHIFT = LEN_SHIFT );
-
- Uint32 m_data[DATA_WORDS];
-
- Tup_varsize_page() {}
- void init();
-
- Uint32* get_free_space_ptr() {
- return m_data+insert_pos;
- }
-
- Uint32 largest_frag_size() const {
- return DATA_WORDS - (high_index + insert_pos);
- }
-
- Uint32 *get_index_ptr(Uint32 page_idx) {
- assert(page_idx < high_index);
- return (m_data + (DATA_WORDS - page_idx));
- }
-
- Uint32 get_index_word(Uint32 page_idx) const {
- assert(page_idx < high_index);
- return * (m_data + (DATA_WORDS - page_idx));
- }
-
- /**
- * Alloc record from page, return page_idx
- * temp is used when having to reorg page before allocating
- */
- Uint32 alloc_record(Uint32 size, Tup_varsize_page* temp, Uint32 chain);
-
- /**
- * Alloc page_idx from page, return page_idx
- * temp is used when having to reorg page before allocating
- */
- Uint32 alloc_record(Uint32 page_idx, Uint32 size, Tup_varsize_page* temp);
-
- /**
- * Free record from page
- */
- Uint32 free_record(Uint32 page_idx, Uint32 chain);
-
- void reorg(Tup_varsize_page* temp);
- void rebuild_index(Uint32* ptr);
-
- /**
- * Check if one can grow tuple wo/ reorg
- */
- bool is_space_behind_entry(Uint32 page_index, Uint32 growth_len) const {
- Uint32 idx= get_index_word(page_index);
- Uint32 pos= (idx & POS_MASK) >> POS_SHIFT;
- Uint32 len= (idx & LEN_MASK) >> LEN_SHIFT;
- if ((pos + len == insert_pos) &&
- (insert_pos + growth_len < DATA_WORDS - high_index))
- return true;
- return false;
- }
-
- void grow_entry(Uint32 page_index, Uint32 growth_len) {
- assert(free_space >= growth_len);
-
- Uint32 *pos= get_index_ptr(page_index);
- Uint32 idx= *pos;
- assert(! (idx & FREE));
- assert((((idx & POS_MASK) >> POS_SHIFT) + ((idx & LEN_MASK) >> LEN_SHIFT))
- == insert_pos);
-
- * pos= idx + (growth_len << LEN_SHIFT);
- insert_pos+= growth_len;
- free_space-= growth_len;
- }
-
- void shrink_entry(Uint32 page_index, Uint32 new_size){
- Uint32 *pos= get_index_ptr(page_index);
- Uint32 idx= *pos;
- Uint32 old_pos = (idx & POS_MASK) >> POS_SHIFT;
- Uint32 old_size = (idx & LEN_MASK) >> LEN_SHIFT;
-
- assert( ! (idx & FREE));
- assert(old_size >= new_size);
-
- * pos= (idx & ~LEN_MASK) + (new_size << LEN_SHIFT);
- Uint32 shrink = old_size - new_size;
-#ifdef VM_TRACE
- memset(m_data + old_pos + new_size, 0xF1, 4 * shrink);
-#endif
- free_space+= shrink;
- if(insert_pos == (old_pos + old_size))
- insert_pos -= shrink;
- }
-
- Uint32* get_ptr(Uint32 page_idx) {
- return m_data + ((get_index_word(page_idx) & POS_MASK) >> POS_SHIFT);
- }
-
- void set_entry_offset(Uint32 page_idx, Uint32 offset){
- Uint32 *pos= get_index_ptr(page_idx);
- * pos = (* pos & ~POS_MASK) + (offset << POS_SHIFT);
- }
-
- void set_entry_len(Uint32 page_idx, Uint32 len) {
- Uint32 *pos= get_index_ptr(page_idx);
- * pos = (*pos & ~LEN_MASK) + (len << LEN_SHIFT);
- }
-
- Uint32 get_entry_len(Uint32 page_idx) const {
- return (get_index_word(page_idx) & LEN_MASK) >> LEN_SHIFT;
- }
-
- Uint32 get_entry_chain(Uint32 page_idx) const {
- return get_index_word(page_idx) & CHAIN;
- }
-};
-
-NdbOut& operator<< (NdbOut& out, const Tup_varsize_page& page);
-NdbOut& operator<< (NdbOut& out, const Tup_fixsize_page& page);
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
deleted file mode 100644
index 55a0c97b74a..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ /dev/null
@@ -1,1208 +0,0 @@
-/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBTUX_H
-#define DBTUX_H
-
-#include <ndb_limits.h>
-#include <SimulatedBlock.hpp>
-#include <AttributeDescriptor.hpp>
-#include <AttributeHeader.hpp>
-#include <ArrayPool.hpp>
-#include <DataBuffer.hpp>
-#include <DLFifoList.hpp>
-#include <md5_hash.hpp>
-
-// big brother
-#include <dbtup/Dbtup.hpp>
-
-// signal classes
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/TuxContinueB.hpp>
-#include <signaldata/TupFrag.hpp>
-#include <signaldata/AlterIndx.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/TuxMaint.hpp>
-#include <signaldata/AccScan.hpp>
-#include <signaldata/TuxBound.hpp>
-#include <signaldata/NextScan.hpp>
-#include <signaldata/AccLock.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-
-// debug
-#ifdef VM_TRACE
-#include <NdbOut.hpp>
-#include <OutputStream.hpp>
-#endif
-
-// jams
-#undef jam
-#undef jamEntry
-#ifdef DBTUX_GEN_CPP
-#define jam() jamLine(10000 + __LINE__)
-#define jamEntry() jamEntryLine(10000 + __LINE__)
-#endif
-#ifdef DBTUX_META_CPP
-#define jam() jamLine(20000 + __LINE__)
-#define jamEntry() jamEntryLine(20000 + __LINE__)
-#endif
-#ifdef DBTUX_MAINT_CPP
-#define jam() jamLine(30000 + __LINE__)
-#define jamEntry() jamEntryLine(30000 + __LINE__)
-#endif
-#ifdef DBTUX_NODE_CPP
-#define jam() jamLine(40000 + __LINE__)
-#define jamEntry() jamEntryLine(40000 + __LINE__)
-#endif
-#ifdef DBTUX_TREE_CPP
-#define jam() jamLine(50000 + __LINE__)
-#define jamEntry() jamEntryLine(50000 + __LINE__)
-#endif
-#ifdef DBTUX_SCAN_CPP
-#define jam() jamLine(60000 + __LINE__)
-#define jamEntry() jamEntryLine(60000 + __LINE__)
-#endif
-#ifdef DBTUX_SEARCH_CPP
-#define jam() jamLine(70000 + __LINE__)
-#define jamEntry() jamEntryLine(70000 + __LINE__)
-#endif
-#ifdef DBTUX_CMP_CPP
-#define jam() jamLine(80000 + __LINE__)
-#define jamEntry() jamEntryLine(80000 + __LINE__)
-#endif
-#ifdef DBTUX_STAT_CPP
-#define jam() jamLine(90000 + __LINE__)
-#define jamEntry() jamEntryLine(90000 + __LINE__)
-#endif
-#ifdef DBTUX_DEBUG_CPP
-#define jam() jamLine(100000 + __LINE__)
-#define jamEntry() jamEntryLine(100000 + __LINE__)
-#endif
-#ifndef jam
-#define jam() jamLine(__LINE__)
-#define jamEntry() jamEntryLine(__LINE__)
-#endif
-
-#undef max
-#undef min
-
-class Configuration;
-
-class Dbtux : public SimulatedBlock {
-public:
- Dbtux(Block_context& ctx);
- virtual ~Dbtux();
-
- // pointer to TUP instance in this thread
- Dbtup* c_tup;
-
-private:
- // sizes are in words (Uint32)
- STATIC_CONST( MaxIndexFragments = MAX_FRAG_PER_NODE );
- STATIC_CONST( MaxIndexAttributes = MAX_ATTRIBUTES_IN_INDEX );
- STATIC_CONST( MaxAttrDataSize = 2048 );
-public:
- STATIC_CONST( DescPageSize = 256 );
-private:
- STATIC_CONST( MaxTreeNodeSize = MAX_TTREE_NODE_SIZE );
- STATIC_CONST( MaxPrefSize = MAX_TTREE_PREF_SIZE );
- STATIC_CONST( ScanBoundSegmentSize = 7 );
- STATIC_CONST( MaxAccLockOps = MAX_PARALLEL_OP_PER_SCAN );
- STATIC_CONST( MaxTreeDepth = 32 ); // strict
- BLOCK_DEFINES(Dbtux);
-
- // forward declarations
- struct DescEnt;
-
- // Pointer to array of Uint32 represents attribute data and bounds
-
- typedef Uint32 *Data;
- inline AttributeHeader& ah(Data data) {
- return *reinterpret_cast<AttributeHeader*>(data);
- }
-
- typedef const Uint32* ConstData;
- inline const AttributeHeader& ah(ConstData data) {
- return *reinterpret_cast<const AttributeHeader*>(data);
- }
-
- // AttributeHeader size is assumed to be 1 word
- STATIC_CONST( AttributeHeaderSize = 1 );
-
- /*
- * Logical tuple address, "local key". Identifies table tuples.
- */
- typedef Uint32 TupAddr;
- STATIC_CONST( NullTupAddr = (Uint32)-1 );
-
- /*
- * Physical tuple address in TUP. Provides fast access to table tuple
- * or index node. Valid within the db node and across timeslices.
- * Not valid between db nodes or across restarts.
- *
- * To avoid wasting an Uint16 the pageid is split in two.
- */
- struct TupLoc {
- private:
- Uint16 m_pageId1; // page i-value (big-endian)
- Uint16 m_pageId2;
- Uint16 m_pageOffset; // page offset in words
- public:
- TupLoc();
- TupLoc(Uint32 pageId, Uint16 pageOffset);
- Uint32 getPageId() const;
- void setPageId(Uint32 pageId);
- Uint32 getPageOffset() const;
- void setPageOffset(Uint32 pageOffset);
- bool operator==(const TupLoc& loc) const;
- bool operator!=(const TupLoc& loc) const;
- };
-
- /*
- * There is no const member NullTupLoc since the compiler may not be
- * able to optimize it to TupLoc() constants. Instead null values are
- * constructed on the stack with TupLoc().
- */
-#define NullTupLoc TupLoc()
-
- // tree definitions
-
- /*
- * Tree entry. Points to a tuple in primary table via physical
- * address of "original" tuple and tuple version.
- *
- * ZTUP_VERSION_BITS must be 15 (or less).
- */
- struct TreeEnt;
- friend struct TreeEnt;
- struct TreeEnt {
- TupLoc m_tupLoc; // address of original tuple
- unsigned m_tupVersion : 15; // version
- TreeEnt();
- // methods
- bool eqtuple(const TreeEnt ent) const;
- bool eq(const TreeEnt ent) const;
- int cmp(const TreeEnt ent) const;
- };
- STATIC_CONST( TreeEntSize = sizeof(TreeEnt) >> 2 );
- static const TreeEnt NullTreeEnt;
-
- /*
- * Tree node has 1) fixed part 2) a prefix of index key data for min
- * entry 3) max and min entries 4) rest of entries 5) one extra entry
- * used as work space.
- *
- * struct TreeNode part 1, size 6 words
- * min prefix part 2, size TreeHead::m_prefSize
- * max entry part 3
- * min entry part 3
- * rest of entries part 4
- * work entry part 5
- *
- * There are 3 links to other nodes: left child, right child, parent.
- * Occupancy (number of entries) is at least 1 except temporarily when
- * a node is about to be removed.
- */
- struct TreeNode;
- friend struct TreeNode;
- struct TreeNode {
- TupLoc m_link[3]; // link to 0-left child 1-right child 2-parent
- unsigned m_side : 2; // we are 0-left child 1-right child 2-root
- unsigned m_balance : 2; // balance -1, 0, +1 plus 1 for Solaris CC
- unsigned pad1 : 4;
- Uint8 m_occup; // current number of entries
- Uint32 m_nodeScan; // list of scans at this node
- TreeNode();
- };
- STATIC_CONST( NodeHeadSize = sizeof(TreeNode) >> 2 );
-
- /*
- * Tree node "access size" was for an early version with signal
- * interface to TUP. It is now used only to compute sizes.
- */
- enum AccSize {
- AccNone = 0,
- AccHead = 1, // part 1
- AccPref = 2, // parts 1-3
- AccFull = 3 // parts 1-5
- };
-
- /*
- * Tree header. There is one in each fragment. Contains tree
- * parameters and address of root node.
- */
- struct TreeHead;
- friend struct TreeHead;
- struct TreeHead {
- Uint8 m_nodeSize; // words in tree node
- Uint8 m_prefSize; // words in min prefix
- Uint8 m_minOccup; // min entries in internal node
- Uint8 m_maxOccup; // max entries in node
- Uint32 m_entryCount; // stat: current entries
- TupLoc m_root; // root node
- TreeHead();
- // methods
- unsigned getSize(AccSize acc) const;
- Data getPref(TreeNode* node) const;
- TreeEnt* getEntList(TreeNode* node) const;
- };
-
- /*
- * Tree position. Specifies node, position within node (from 0 to
- * m_occup), and whether the position is at an existing entry or
- * before one (if any). Position m_occup points past the node and is
- * also represented by position 0 of next node. Includes direction
- * used by scan.
- */
- struct TreePos;
- friend struct TreePos;
- struct TreePos {
- TupLoc m_loc; // physical node address
- Uint16 m_pos; // position 0 to m_occup
- Uint8 m_dir; // see scanNext
- TreePos();
- };
-
- // packed metadata
-
- /*
- * Descriptor page. The "hot" metadata for an index is stored as
- * a contiguous array of words on some page.
- */
- struct DescPage;
- friend struct DescPage;
- struct DescPage {
- Uint32 m_nextPage;
- Uint32 m_numFree; // number of free words
- union {
- Uint32 m_data[DescPageSize];
- Uint32 nextPool;
- };
- DescPage();
- };
- typedef Ptr<DescPage> DescPagePtr;
- ArrayPool<DescPage> c_descPagePool;
- Uint32 c_descPageList;
-
- /*
- * Header for index metadata. Size must be multiple of word size.
- */
- struct DescHead {
- unsigned m_indexId : 24;
- unsigned pad1 : 8;
- };
- STATIC_CONST( DescHeadSize = sizeof(DescHead) >> 2 );
-
- /*
- * Attribute metadata. Size must be multiple of word size.
- *
- * Prefix comparison of char data must use strxfrm and binary
- * comparison. The charset is currently unused.
- */
- struct DescAttr {
- Uint32 m_attrDesc; // standard AttributeDescriptor
- Uint16 m_primaryAttrId;
- unsigned m_typeId : 6;
- unsigned m_charset : 10;
- };
- STATIC_CONST( DescAttrSize = sizeof(DescAttr) >> 2 );
-
- /*
- * Complete metadata for one index. The array of attributes has
- * variable size.
- */
- friend struct DescEnt;
- struct DescEnt {
- DescHead m_descHead;
- DescAttr m_descAttr[1]; // variable size data
- };
-
- // range scan
-
- /*
- * Scan bounds are stored in linked list of segments.
- */
- typedef DataBuffer<ScanBoundSegmentSize> ScanBound;
- typedef DataBuffer<ScanBoundSegmentSize>::ConstDataBufferIterator ScanBoundIterator;
- typedef DataBuffer<ScanBoundSegmentSize>::DataBufferPool ScanBoundPool;
- ScanBoundPool c_scanBoundPool;
-
- // ScanLock
- struct ScanLock {
- Uint32 m_accLockOp;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- typedef Ptr<ScanLock> ScanLockPtr;
- ArrayPool<ScanLock> c_scanLockPool;
-
- /*
- * Scan operation.
- *
- * Tuples are locked one at a time. The current lock op is set to
- * RNIL as soon as the lock is obtained and passed to LQH. We must
- * however remember all locks which LQH has not returned for unlocking
- * since they must be aborted by us when the scan is closed.
- *
- * Scan state describes the entry we are interested in. There is
- * a separate lock wait flag. It may be for current entry or it may
- * be for an entry we were moved away from. In any case nothing
- * happens with current entry before lock wait flag is cleared.
- *
- * An unfinished scan is always linked to some tree node, and has
- * current position and direction (see comments at scanNext). There
- * is also a copy of latest entry found.
- */
- struct ScanOp;
- friend struct ScanOp;
- struct ScanOp {
- enum {
- Undef = 0,
- First = 1, // before first entry
- Current = 2, // at some entry
- Found = 3, // return current as next scan result
- Blocked = 4, // found and waiting for ACC lock
- Locked = 5, // found and locked or no lock needed
- Next = 6, // looking for next extry
- Last = 7, // after last entry
- Aborting = 8, // lock wait at scan close
- Invalid = 9 // cannot return REF to LQH currently
- };
- Uint16 m_state;
- Uint16 m_lockwait;
- Uint32 m_userPtr; // scanptr.i in LQH
- Uint32 m_userRef;
- Uint32 m_tableId;
- Uint32 m_indexId;
- Uint32 m_fragId;
- Uint32 m_fragPtrI;
- Uint32 m_transId1;
- Uint32 m_transId2;
- Uint32 m_savePointId;
- // lock waited for or obtained and not yet passed to LQH
- Uint32 m_accLockOp;
- // locks obtained and passed to LQH but not yet returned by LQH
- DLFifoList<ScanLock>::Head m_accLockOps;
- Uint8 m_readCommitted; // no locking
- Uint8 m_lockMode;
- Uint8 m_descending;
- ScanBound m_boundMin;
- ScanBound m_boundMax;
- ScanBound* m_bound[2]; // pointers to above 2
- Uint16 m_boundCnt[2]; // number of bounds in each
- TreePos m_scanPos; // position
- TreeEnt m_scanEnt; // latest entry found
- Uint32 m_nodeScan; // next scan at node (single-linked)
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- ScanOp(ScanBoundPool& scanBoundPool);
- };
- typedef Ptr<ScanOp> ScanOpPtr;
- ArrayPool<ScanOp> c_scanOpPool;
-
- // indexes and fragments
-
- /*
- * Ordered index. Top level data structure. The primary table (table
- * being indexed) lives in TUP.
- */
- struct Index;
- friend struct Index;
- struct Index {
- enum State {
- NotDefined = 0,
- Defining = 1,
- Online = 2, // triggers activated and build done
- Dropping = 9
- };
- State m_state;
- DictTabInfo::TableType m_tableType;
- Uint32 m_tableId;
- Uint16 unused;
- Uint16 m_numFrags;
- Uint32 m_fragId[MaxIndexFragments];
- Uint32 m_fragPtrI[MaxIndexFragments];
- Uint32 m_descPage; // descriptor page
- Uint16 m_descOff; // offset within the page
- Uint16 m_numAttrs;
- bool m_storeNullKey;
- union {
- Uint32 nextPool;
- };
- Index();
- };
- typedef Ptr<Index> IndexPtr;
- ArrayPool<Index> c_indexPool;
-
- /*
- * Fragment of an index, as known to DIH/TC. Represents the two
- * duplicate fragments known to LQH/ACC/TUP. Includes tree header.
- * There are no maintenance operation records yet.
- */
- struct Frag;
- friend struct Frag;
- struct Frag {
- Uint32 m_tableId; // copy from index level
- Uint32 m_indexId;
- Uint16 unused;
- Uint16 m_fragId;
- Uint32 m_descPage; // copy from index level
- Uint16 m_descOff;
- Uint16 m_numAttrs;
- bool m_storeNullKey;
- TreeHead m_tree;
- TupLoc m_freeLoc; // list of free index nodes
- DLList<ScanOp> m_scanList; // current scans on this fragment
- Uint32 m_tupIndexFragPtrI;
- Uint32 m_tupTableFragPtrI;
- Uint32 m_accTableFragPtrI;
- union {
- Uint32 nextPool;
- };
- Frag(ArrayPool<ScanOp>& scanOpPool);
- };
- typedef Ptr<Frag> FragPtr;
- ArrayPool<Frag> c_fragPool;
-
- /*
- * Fragment metadata operation.
- */
- struct FragOp {
- Uint32 m_userPtr;
- Uint32 m_userRef;
- Uint32 m_indexId;
- Uint32 m_fragId;
- Uint32 m_fragPtrI;
- Uint32 m_fragNo; // fragment number starting at zero
- Uint32 m_numAttrsRecvd;
- union {
- Uint32 nextPool;
- };
- FragOp();
- };
- typedef Ptr<FragOp> FragOpPtr;
- ArrayPool<FragOp> c_fragOpPool;
-
- // node handles
-
- /*
- * A node handle is a reference to a tree node in TUP. It is used to
- * operate on the node. Node handles are allocated on the stack.
- */
- struct NodeHandle;
- friend struct NodeHandle;
- struct NodeHandle {
- Frag& m_frag; // fragment using the node
- TupLoc m_loc; // physical node address
- TreeNode* m_node; // pointer to node storage
- NodeHandle(Frag& frag);
- NodeHandle(const NodeHandle& node);
- NodeHandle& operator=(const NodeHandle& node);
- // check if unassigned
- bool isNull();
- // getters
- TupLoc getLink(unsigned i);
- unsigned getChilds(); // cannot spell
- unsigned getSide();
- unsigned getOccup();
- int getBalance();
- Uint32 getNodeScan();
- // setters
- void setLink(unsigned i, TupLoc loc);
- void setSide(unsigned i);
- void setOccup(unsigned n);
- void setBalance(int b);
- void setNodeScan(Uint32 scanPtrI);
- // access other parts of the node
- Data getPref();
- TreeEnt getEnt(unsigned pos);
- TreeEnt getMinMax(unsigned i);
- // for ndbrequire and ndbassert
- void progError(int line, int cause, const char* file);
- };
-
- // methods
-
- /*
- * DbtuxGen.cpp
- */
- void execCONTINUEB(Signal* signal);
- void execSTTOR(Signal* signal);
- void execREAD_CONFIG_REQ(Signal* signal);
- // utils
- void setKeyAttrs(const Frag& frag);
- void readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData);
- void readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize);
- void copyAttrs(const Frag& frag, ConstData data1, Data data2, unsigned maxlen2 = MaxAttrDataSize);
- void unpackBound(const ScanBound& bound, Data data);
-
- /*
- * DbtuxMeta.cpp
- */
- void execTUXFRAGREQ(Signal* signal);
- void execTUX_ADD_ATTRREQ(Signal* signal);
- void execALTER_INDX_REQ(Signal* signal);
- void execDROP_TAB_REQ(Signal* signal);
- bool allocDescEnt(IndexPtr indexPtr);
- void freeDescEnt(IndexPtr indexPtr);
- void abortAddFragOp(Signal* signal);
- void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData);
-
- /*
- * DbtuxMaint.cpp
- */
- void execTUX_MAINT_REQ(Signal* signal);
-
- /*
- * DbtuxNode.cpp
- */
- int allocNode(Signal* signal, NodeHandle& node);
- void selectNode(NodeHandle& node, TupLoc loc);
- void insertNode(NodeHandle& node);
- void deleteNode(NodeHandle& node);
- void setNodePref(NodeHandle& node);
- // node operations
- void nodePushUp(NodeHandle& node, unsigned pos, const TreeEnt& ent, Uint32 scanList);
- void nodePushUpScans(NodeHandle& node, unsigned pos);
- void nodePopDown(NodeHandle& node, unsigned pos, TreeEnt& en, Uint32* scanList);
- void nodePopDownScans(NodeHandle& node, unsigned pos);
- void nodePushDown(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32& scanList);
- void nodePushDownScans(NodeHandle& node, unsigned pos);
- void nodePopUp(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32 scanList);
- void nodePopUpScans(NodeHandle& node, unsigned pos);
- void nodeSlide(NodeHandle& dstNode, NodeHandle& srcNode, unsigned cnt, unsigned i);
- // scans linked to node
- void addScanList(NodeHandle& node, unsigned pos, Uint32 scanList);
- void removeScanList(NodeHandle& node, unsigned pos, Uint32& scanList);
- void moveScanList(NodeHandle& node, unsigned pos);
- void linkScan(NodeHandle& node, ScanOpPtr scanPtr);
- void unlinkScan(NodeHandle& node, ScanOpPtr scanPtr);
- bool islinkScan(NodeHandle& node, ScanOpPtr scanPtr);
-
- /*
- * DbtuxTree.cpp
- */
- // add entry
- void treeAdd(Frag& frag, TreePos treePos, TreeEnt ent);
- void treeAddFull(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent);
- void treeAddNode(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent, NodeHandle parentNode, unsigned i);
- void treeAddRebalance(Frag& frag, NodeHandle node, unsigned i);
- // remove entry
- void treeRemove(Frag& frag, TreePos treePos);
- void treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos);
- void treeRemoveSemi(Frag& frag, NodeHandle node, unsigned i);
- void treeRemoveLeaf(Frag& frag, NodeHandle node);
- void treeRemoveNode(Frag& frag, NodeHandle node);
- void treeRemoveRebalance(Frag& frag, NodeHandle node, unsigned i);
- // rotate
- void treeRotateSingle(Frag& frag, NodeHandle& node, unsigned i);
- void treeRotateDouble(Frag& frag, NodeHandle& node, unsigned i);
-
- /*
- * DbtuxScan.cpp
- */
- void execACC_SCANREQ(Signal* signal);
- void execTUX_BOUND_INFO(Signal* signal);
- void execNEXT_SCANREQ(Signal* signal);
- void execACC_CHECK_SCAN(Signal* signal);
- void execACCKEYCONF(Signal* signal);
- void execACCKEYREF(Signal* signal);
- void execACC_ABORTCONF(Signal* signal);
- void scanFirst(ScanOpPtr scanPtr);
- void scanFind(ScanOpPtr scanPtr);
- void scanNext(ScanOpPtr scanPtr, bool fromMaintReq);
- bool scanCheck(ScanOpPtr scanPtr, TreeEnt ent);
- bool scanVisible(ScanOpPtr scanPtr, TreeEnt ent);
- void scanClose(Signal* signal, ScanOpPtr scanPtr);
- void abortAccLockOps(Signal* signal, ScanOpPtr scanPtr);
- void addAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
- void removeAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
- void releaseScanOp(ScanOpPtr& scanPtr);
-
- /*
- * DbtuxSearch.cpp
- */
- bool searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
- bool searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, 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
- */
- int cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, ConstData entryData, unsigned maxlen = MaxAttrDataSize);
- int cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen = MaxAttrDataSize);
-
- /*
- * DbtuxStat.cpp
- */
- void execREAD_PSEUDO_REQ(Signal* signal);
- void statRecordsInRange(ScanOpPtr scanPtr, Uint32* out);
- Uint32 getEntriesBeforeOrAfter(Frag& frag, TreePos pos, unsigned idir);
- unsigned getPathToNode(NodeHandle node, Uint16* path);
-
- /*
- * DbtuxDebug.cpp
- */
- void execDUMP_STATE_ORD(Signal* signal);
-#ifdef VM_TRACE
- struct PrintPar {
- char m_path[100]; // LR prefix
- unsigned m_side; // expected side
- TupLoc m_parent; // expected parent address
- int m_depth; // returned depth
- unsigned m_occup; // returned occupancy
- TreeEnt m_minmax[2]; // returned subtree min and max
- bool m_ok; // returned status
- PrintPar();
- };
- void printTree(Signal* signal, Frag& frag, NdbOut& out);
- void printNode(Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par);
- friend class NdbOut& operator<<(NdbOut&, const TupLoc&);
- friend class NdbOut& operator<<(NdbOut&, const TreeEnt&);
- friend class NdbOut& operator<<(NdbOut&, const TreeNode&);
- friend class NdbOut& operator<<(NdbOut&, const TreeHead&);
- friend class NdbOut& operator<<(NdbOut&, const TreePos&);
- friend class NdbOut& operator<<(NdbOut&, const DescAttr&);
- friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
- friend class NdbOut& operator<<(NdbOut&, const Index&);
- friend class NdbOut& operator<<(NdbOut&, const Frag&);
- friend class NdbOut& operator<<(NdbOut&, const FragOp&);
- friend class NdbOut& operator<<(NdbOut&, const NodeHandle&);
- FILE* debugFile;
- NdbOut debugOut;
- unsigned debugFlags;
- enum {
- DebugMeta = 1, // log create and drop index
- DebugMaint = 2, // log maintenance ops
- DebugTree = 4, // log and check tree after each op
- DebugScan = 8, // log scans
- DebugLock = 16 // log ACC locks
- };
- STATIC_CONST( DataFillByte = 0xa2 );
- STATIC_CONST( NodeFillByte = 0xa4 );
-#endif
-
- // start up info
- Uint32 c_internalStartPhase;
- Uint32 c_typeOfStart;
-
- /*
- * Global data set at operation start. Unpacked from index metadata.
- * Not passed as parameter to methods. Invalid across timeslices.
- *
- * TODO inline all into index metadata
- */
-
- // index key attr ids with sizes in AttributeHeader format
- Data c_keyAttrs;
-
- // pointers to index key comparison functions
- NdbSqlUtil::Cmp** c_sqlCmp;
-
- /*
- * Other buffers used during the operation.
- */
-
- // buffer for search key data with headers
- Data c_searchKey;
-
- // buffer for current entry key data with headers
- Data c_entryKey;
-
- // buffer for scan bounds and keyinfo (primary key)
- Data c_dataBuffer;
-
- // inlined utils
- DescEnt& getDescEnt(Uint32 descPage, Uint32 descOff);
- Uint32 getTupAddr(const Frag& frag, TreeEnt ent);
- static unsigned min(unsigned x, unsigned y);
- static unsigned max(unsigned x, unsigned y);
-};
-
-// Dbtux::TupLoc
-
-inline
-Dbtux::TupLoc::TupLoc() :
- m_pageId1(RNIL >> 16),
- m_pageId2(RNIL & 0xFFFF),
- m_pageOffset(0)
-{
-}
-
-inline
-Dbtux::TupLoc::TupLoc(Uint32 pageId, Uint16 pageOffset) :
- m_pageId1(pageId >> 16),
- m_pageId2(pageId & 0xFFFF),
- m_pageOffset(pageOffset)
-{
-}
-
-inline Uint32
-Dbtux::TupLoc::getPageId() const
-{
- return (m_pageId1 << 16) | m_pageId2;
-}
-
-inline void
-Dbtux::TupLoc::setPageId(Uint32 pageId)
-{
- m_pageId1 = (pageId >> 16);
- m_pageId2 = (pageId & 0xFFFF);
-}
-
-inline Uint32
-Dbtux::TupLoc::getPageOffset() const
-{
- return (Uint32)m_pageOffset;
-}
-
-inline void
-Dbtux::TupLoc::setPageOffset(Uint32 pageOffset)
-{
- m_pageOffset = (Uint16)pageOffset;
-}
-
-inline bool
-Dbtux::TupLoc::operator==(const TupLoc& loc) const
-{
- return
- m_pageId1 == loc.m_pageId1 &&
- m_pageId2 == loc.m_pageId2 &&
- m_pageOffset == loc.m_pageOffset;
-}
-
-inline bool
-Dbtux::TupLoc::operator!=(const TupLoc& loc) const
-{
- return ! (*this == loc);
-}
-
-// Dbtux::TreeEnt
-
-inline
-Dbtux::TreeEnt::TreeEnt() :
- m_tupLoc(),
- m_tupVersion(0)
-{
-}
-
-inline bool
-Dbtux::TreeEnt::eqtuple(const TreeEnt ent) const
-{
- return
- m_tupLoc == ent.m_tupLoc;
-}
-
-inline bool
-Dbtux::TreeEnt::eq(const TreeEnt ent) const
-{
- return
- m_tupLoc == ent.m_tupLoc &&
- m_tupVersion == ent.m_tupVersion;
-}
-
-inline int
-Dbtux::TreeEnt::cmp(const TreeEnt ent) const
-{
- if (m_tupLoc.getPageId() < ent.m_tupLoc.getPageId())
- return -1;
- if (m_tupLoc.getPageId() > ent.m_tupLoc.getPageId())
- return +1;
- if (m_tupLoc.getPageOffset() < ent.m_tupLoc.getPageOffset())
- return -1;
- if (m_tupLoc.getPageOffset() > ent.m_tupLoc.getPageOffset())
- return +1;
- /*
- * Guess if one tuple version has wrapped around. This is well
- * defined ordering on existing versions since versions are assigned
- * consecutively and different versions exists only on uncommitted
- * tuple. Assuming max 2**14 uncommitted ops on same tuple.
- */
- const unsigned version_wrap_limit = (1 << (ZTUP_VERSION_BITS - 1));
- if (m_tupVersion < ent.m_tupVersion) {
- if (unsigned(ent.m_tupVersion - m_tupVersion) < version_wrap_limit)
- return -1;
- else
- return +1;
- }
- if (m_tupVersion > ent.m_tupVersion) {
- if (unsigned(m_tupVersion - ent.m_tupVersion) < version_wrap_limit)
- return +1;
- else
- return -1;
- }
- return 0;
-}
-
-// Dbtux::TreeNode
-
-inline
-Dbtux::TreeNode::TreeNode() :
- m_side(2),
- m_balance(0 + 1),
- pad1(0),
- m_occup(0),
- m_nodeScan(RNIL)
-{
- m_link[0] = NullTupLoc;
- m_link[1] = NullTupLoc;
- m_link[2] = NullTupLoc;
-}
-
-// Dbtux::TreeHead
-
-inline
-Dbtux::TreeHead::TreeHead() :
- m_nodeSize(0),
- m_prefSize(0),
- m_minOccup(0),
- m_maxOccup(0),
- m_entryCount(0),
- m_root()
-{
-}
-
-inline unsigned
-Dbtux::TreeHead::getSize(AccSize acc) const
-{
- switch (acc) {
- case AccNone:
- return 0;
- case AccHead:
- return NodeHeadSize;
- case AccPref:
- return NodeHeadSize + m_prefSize + 2 * TreeEntSize;
- case AccFull:
- return m_nodeSize;
- }
- return 0;
-}
-
-inline Dbtux::Data
-Dbtux::TreeHead::getPref(TreeNode* node) const
-{
- Uint32* ptr = (Uint32*)node + NodeHeadSize;
- return ptr;
-}
-
-inline Dbtux::TreeEnt*
-Dbtux::TreeHead::getEntList(TreeNode* node) const
-{
- Uint32* ptr = (Uint32*)node + NodeHeadSize + m_prefSize;
- return (TreeEnt*)ptr;
-}
-
-// Dbtux::TreePos
-
-inline
-Dbtux::TreePos::TreePos() :
- m_loc(),
- m_pos(ZNIL),
- m_dir(255)
-{
-}
-
-// Dbtux::DescPage
-
-inline
-Dbtux::DescPage::DescPage() :
- m_nextPage(RNIL),
- m_numFree(ZNIL)
-{
- for (unsigned i = 0; i < DescPageSize; i++) {
-#ifdef VM_TRACE
- m_data[i] = 0x13571357;
-#else
- m_data[i] = 0;
-#endif
- }
-}
-
-// Dbtux::ScanOp
-
-inline
-Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
- m_state(Undef),
- m_lockwait(false),
- m_userPtr(RNIL),
- m_userRef(RNIL),
- m_tableId(RNIL),
- m_indexId(RNIL),
- m_fragPtrI(RNIL),
- m_transId1(0),
- m_transId2(0),
- m_savePointId(0),
- m_accLockOp(RNIL),
- m_accLockOps(),
- m_readCommitted(0),
- m_lockMode(0),
- m_descending(0),
- m_boundMin(scanBoundPool),
- m_boundMax(scanBoundPool),
- m_scanPos(),
- m_scanEnt(),
- m_nodeScan(RNIL)
-{
- m_bound[0] = &m_boundMin;
- m_bound[1] = &m_boundMax;
- m_boundCnt[0] = 0;
- m_boundCnt[1] = 0;
-}
-
-// Dbtux::Index
-
-inline
-Dbtux::Index::Index() :
- m_state(NotDefined),
- m_tableType(DictTabInfo::UndefTableType),
- m_tableId(RNIL),
- m_numFrags(0),
- m_descPage(RNIL),
- m_descOff(0),
- m_numAttrs(0),
- m_storeNullKey(false)
-{
- for (unsigned i = 0; i < MaxIndexFragments; i++) {
- m_fragId[i] = ZNIL;
- m_fragPtrI[i] = RNIL;
- };
-}
-
-// Dbtux::Frag
-
-inline
-Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
- m_tableId(RNIL),
- m_indexId(RNIL),
- m_fragId(ZNIL),
- m_descPage(RNIL),
- m_descOff(0),
- m_numAttrs(ZNIL),
- m_storeNullKey(false),
- m_tree(),
- m_freeLoc(),
- m_scanList(scanOpPool),
- m_tupIndexFragPtrI(RNIL)
-{
- m_tupTableFragPtrI = RNIL;
- m_accTableFragPtrI = RNIL;
-}
-
-// Dbtux::FragOp
-
-inline
-Dbtux::FragOp::FragOp() :
- m_userPtr(RNIL),
- m_userRef(RNIL),
- m_indexId(RNIL),
- m_fragId(ZNIL),
- m_fragPtrI(RNIL),
- m_fragNo(ZNIL),
- m_numAttrsRecvd(ZNIL)
-{
-}
-
-// Dbtux::NodeHandle
-
-inline
-Dbtux::NodeHandle::NodeHandle(Frag& frag) :
- m_frag(frag),
- m_loc(),
- m_node(0)
-{
-}
-
-inline
-Dbtux::NodeHandle::NodeHandle(const NodeHandle& node) :
- m_frag(node.m_frag),
- m_loc(node.m_loc),
- m_node(node.m_node)
-{
-}
-
-inline Dbtux::NodeHandle&
-Dbtux::NodeHandle::operator=(const NodeHandle& node)
-{
- ndbassert(&m_frag == &node.m_frag);
- m_loc = node.m_loc;
- m_node = node.m_node;
- return *this;
-}
-
-inline bool
-Dbtux::NodeHandle::isNull()
-{
- return m_node == 0;
-}
-
-inline Dbtux::TupLoc
-Dbtux::NodeHandle::getLink(unsigned i)
-{
- ndbrequire(i <= 2);
- return m_node->m_link[i];
-}
-
-inline unsigned
-Dbtux::NodeHandle::getChilds()
-{
- return (m_node->m_link[0] != NullTupLoc) + (m_node->m_link[1] != NullTupLoc);
-}
-
-inline unsigned
-Dbtux::NodeHandle::getSide()
-{
- return m_node->m_side;
-}
-
-inline unsigned
-Dbtux::NodeHandle::getOccup()
-{
- return m_node->m_occup;
-}
-
-inline int
-Dbtux::NodeHandle::getBalance()
-{
- return (int)m_node->m_balance - 1;
-}
-
-inline Uint32
-Dbtux::NodeHandle::getNodeScan()
-{
- return m_node->m_nodeScan;
-}
-
-inline void
-Dbtux::NodeHandle::setLink(unsigned i, TupLoc loc)
-{
- ndbrequire(i <= 2);
- m_node->m_link[i] = loc;
-}
-
-inline void
-Dbtux::NodeHandle::setSide(unsigned i)
-{
- ndbrequire(i <= 2);
- m_node->m_side = i;
-}
-
-inline void
-Dbtux::NodeHandle::setOccup(unsigned n)
-{
- TreeHead& tree = m_frag.m_tree;
- ndbrequire(n <= tree.m_maxOccup);
- m_node->m_occup = n;
-}
-
-inline void
-Dbtux::NodeHandle::setBalance(int b)
-{
- ndbrequire(abs(b) <= 1);
- m_node->m_balance = (unsigned)(b + 1);
-}
-
-inline void
-Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
-{
- m_node->m_nodeScan = scanPtrI;
-}
-
-inline Dbtux::Data
-Dbtux::NodeHandle::getPref()
-{
- TreeHead& tree = m_frag.m_tree;
- return tree.getPref(m_node);
-}
-
-inline Dbtux::TreeEnt
-Dbtux::NodeHandle::getEnt(unsigned pos)
-{
- TreeHead& tree = m_frag.m_tree;
- TreeEnt* entList = tree.getEntList(m_node);
- const unsigned occup = m_node->m_occup;
- ndbrequire(pos < occup);
- return entList[(1 + pos) % occup];
-}
-
-inline Dbtux::TreeEnt
-Dbtux::NodeHandle::getMinMax(unsigned i)
-{
- const unsigned occup = m_node->m_occup;
- ndbrequire(i <= 1 && occup != 0);
- return getEnt(i == 0 ? 0 : occup - 1);
-}
-
-// parameters for methods
-
-#ifdef VM_TRACE
-inline
-Dbtux::PrintPar::PrintPar() :
- // caller fills in
- m_path(),
- m_side(255),
- m_parent(),
- // default return values
- m_depth(0),
- m_occup(0),
- m_ok(true)
-{
-}
-#endif
-
-// utils
-
-inline Dbtux::DescEnt&
-Dbtux::getDescEnt(Uint32 descPage, Uint32 descOff)
-{
- DescPagePtr pagePtr;
- pagePtr.i = descPage;
- c_descPagePool.getPtr(pagePtr);
- ndbrequire(descOff < DescPageSize);
- DescEnt* descEnt = (DescEnt*)&pagePtr.p->m_data[descOff];
- return *descEnt;
-}
-
-inline Uint32
-Dbtux::getTupAddr(const Frag& frag, TreeEnt ent)
-{
- const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
- const TupLoc tupLoc = ent.m_tupLoc;
- Uint32 tupAddr = NullTupAddr;
- c_tup->tuxGetTupAddr(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), tupAddr);
- jamEntry();
- return tupAddr;
-}
-
-inline unsigned
-Dbtux::min(unsigned x, unsigned y)
-{
- return x < y ? x : y;
-}
-
-inline unsigned
-Dbtux::max(unsigned x, unsigned y)
-{
- return x > y ? x : y;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
deleted file mode 100644
index 32520502991..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_CMP_CPP
-#include "Dbtux.hpp"
-
-/*
- * 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);
- // skip to right position in search key only
- for (unsigned i = 0; i < start; i++) {
- jam();
- searchKey += AttributeHeaderSize + ah(searchKey).getDataSize();
- }
- // number of words of entry data left
- unsigned len2 = maxlen;
- int ret = 0;
- while (start < numAttrs) {
- if (len2 <= AttributeHeaderSize) {
- jam();
- ret = NdbSqlUtil::CmpUnknown;
- break;
- }
- len2 -= AttributeHeaderSize;
- if (! ah(searchKey).isNULL()) {
- if (! ah(entryData).isNULL()) {
- jam();
- // verify attribute id
- const DescAttr& descAttr = descEnt.m_descAttr[start];
- ndbrequire(ah(searchKey).getAttributeId() == descAttr.m_primaryAttrId);
- ndbrequire(ah(entryData).getAttributeId() == descAttr.m_primaryAttrId);
- // sizes
- const unsigned size1 = ah(searchKey).getDataSize();
- const unsigned size2 = min(ah(entryData).getDataSize(), len2);
- len2 -= size2;
- // compare
- NdbSqlUtil::Cmp* const cmp = c_sqlCmp[start];
- const Uint32* const p1 = &searchKey[AttributeHeaderSize];
- const Uint32* const p2 = &entryData[AttributeHeaderSize];
- const bool full = (maxlen == MaxAttrDataSize);
- ret = (*cmp)(0, p1, size1 << 2, p2, size2 << 2, full);
- if (ret != 0) {
- jam();
- break;
- }
- } else {
- jam();
- // not NULL > NULL
- ret = +1;
- break;
- }
- } else {
- if (! ah(entryData).isNULL()) {
- jam();
- // NULL < not NULL
- ret = -1;
- break;
- }
- }
- searchKey += AttributeHeaderSize + ah(searchKey).getDataSize();
- entryData += AttributeHeaderSize + ah(entryData).getDataSize();
- start++;
- }
- return ret;
-}
-
-/*
- * Scan bound vs node prefix or entry.
- *
- * Compare lower or upper bound and index entry data. The entry data
- * may be partial in which case CmpUnknown may be returned. Otherwise
- * returns -1 if the bound is to the left of the entry and +1 if the
- * bound is to the right of the entry.
- *
- * The routine is similar to cmpSearchKey, but 0 is never returned.
- * Suppose all attributes compare equal. Recall that all bounds except
- * possibly the last one are non-strict. Use the given bound direction
- * (0-lower 1-upper) and strictness of last bound to return -1 or +1.
- *
- * Following example illustrates this. We are at (a=2, b=3).
- *
- * 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 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(idir <= 1);
- // number of words of data left
- unsigned len2 = maxlen;
- // in case of no bounds, init last type to something non-strict
- unsigned type = 4;
- while (boundCount != 0) {
- if (len2 <= AttributeHeaderSize) {
- jam();
- return NdbSqlUtil::CmpUnknown;
- }
- len2 -= AttributeHeaderSize;
- // get and skip bound type (it is used after the loop)
- type = boundInfo[0];
- boundInfo += 1;
- if (! ah(boundInfo).isNULL()) {
- if (! ah(entryData).isNULL()) {
- jam();
- // verify attribute id
- const Uint32 index = ah(boundInfo).getAttributeId();
- ndbrequire(index < frag.m_numAttrs);
- const DescAttr& descAttr = descEnt.m_descAttr[index];
- ndbrequire(ah(entryData).getAttributeId() == descAttr.m_primaryAttrId);
- // sizes
- const unsigned size1 = ah(boundInfo).getDataSize();
- const unsigned size2 = min(ah(entryData).getDataSize(), len2);
- len2 -= size2;
- // compare
- NdbSqlUtil::Cmp* const cmp = c_sqlCmp[index];
- const Uint32* const p1 = &boundInfo[AttributeHeaderSize];
- const Uint32* const p2 = &entryData[AttributeHeaderSize];
- const bool full = (maxlen == MaxAttrDataSize);
- int ret = (*cmp)(0, p1, size1 << 2, p2, size2 << 2, full);
- if (ret != 0) {
- jam();
- return ret;
- }
- } else {
- jam();
- // not NULL > NULL
- return +1;
- }
- } else {
- jam();
- if (! ah(entryData).isNULL()) {
- jam();
- // NULL < not NULL
- return -1;
- }
- }
- boundInfo += AttributeHeaderSize + ah(boundInfo).getDataSize();
- entryData += AttributeHeaderSize + ah(entryData).getDataSize();
- boundCount -= 1;
- }
- // all attributes were equal
- const int strict = (type & 0x1);
- return (idir == 0 ? (strict == 0 ? -1 : +1) : (strict == 0 ? +1 : -1));
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
deleted file mode 100644
index 933ec77258e..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ /dev/null
@@ -1,417 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_DEBUG_CPP
-#include "Dbtux.hpp"
-
-/*
- * 12001 log file 0-close 1-open 2-append 3-append to signal log
- * 12002 log flags 1-meta 2-maint 4-tree 8-scan
- */
-void
-Dbtux::execDUMP_STATE_ORD(Signal* signal)
-{
- jamEntry();
-#ifdef VM_TRACE
- if (signal->theData[0] == DumpStateOrd::TuxLogToFile) {
- unsigned flag = signal->theData[1];
- const char* const tuxlog = "tux.log";
- FILE* slFile = globalSignalLoggers.getOutputStream();
- if (flag <= 3) {
- if (debugFile != 0) {
- if (debugFile != slFile)
- fclose(debugFile);
- debugFile = 0;
- debugOut = *new NdbOut(*new NullOutputStream());
- }
- if (flag == 1)
- debugFile = fopen(tuxlog, "w");
- if (flag == 2)
- debugFile = fopen(tuxlog, "a");
- if (flag == 3)
- debugFile = slFile;
- if (debugFile != 0)
- debugOut = *new NdbOut(*new FileOutputStream(debugFile));
- }
- return;
- }
- if (signal->theData[0] == DumpStateOrd::TuxSetLogFlags) {
- debugFlags = signal->theData[1];
- return;
- }
- if (signal->theData[0] == DumpStateOrd::TuxMetaDataJunk) {
- abort();
- }
-#endif
-}
-
-#ifdef VM_TRACE
-
-void
-Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
-{
- TreeHead& tree = frag.m_tree;
- PrintPar par;
- strcpy(par.m_path, ".");
- par.m_side = 2;
- par.m_parent = NullTupLoc;
- printNode(frag, out, tree.m_root, par);
- out.m_out->flush();
- if (! par.m_ok) {
- if (debugFile == 0) {
- signal->theData[0] = 12001;
- signal->theData[1] = 1;
- execDUMP_STATE_ORD(signal);
- if (debugFile != 0) {
- printTree(signal, frag, debugOut);
- }
- }
- ndbrequire(false);
- }
-}
-
-void
-Dbtux::printNode(Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par)
-{
- if (loc == NullTupLoc) {
- par.m_depth = 0;
- return;
- }
- TreeHead& tree = frag.m_tree;
- NodeHandle node(frag);
- selectNode(node, loc);
- out << par.m_path << " " << node << endl;
- // check children
- PrintPar cpar[2];
- ndbrequire(strlen(par.m_path) + 1 < sizeof(par.m_path));
- for (unsigned i = 0; i <= 1; i++) {
- sprintf(cpar[i].m_path, "%s%c", par.m_path, "LR"[i]);
- cpar[i].m_side = i;
- cpar[i].m_depth = 0;
- cpar[i].m_parent = loc;
- printNode(frag, out, node.getLink(i), cpar[i]);
- if (! cpar[i].m_ok) {
- par.m_ok = false;
- }
- }
- static const char* const sep = " *** ";
- // check child-parent links
- if (node.getLink(2) != par.m_parent) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "parent loc " << hex << node.getLink(2);
- out << " should be " << hex << par.m_parent << endl;
- }
- if (node.getSide() != par.m_side) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "side " << dec << node.getSide();
- out << " should be " << dec << par.m_side << endl;
- }
- // check balance
- const int balance = -cpar[0].m_depth + cpar[1].m_depth;
- if (node.getBalance() != balance) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "balance " << node.getBalance();
- out << " should be " << balance << endl;
- }
- if (abs(node.getBalance()) > 1) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "balance " << node.getBalance() << " is invalid" << endl;
- }
- // check occupancy
- if (node.getOccup() == 0 || node.getOccup() > tree.m_maxOccup) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "occupancy " << node.getOccup();
- out << " zero or greater than max " << tree.m_maxOccup << endl;
- }
- // check for occupancy of interior node
- if (node.getChilds() == 2 && node.getOccup() < tree.m_minOccup) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "occupancy " << node.getOccup() << " of interior node";
- out << " less than min " << tree.m_minOccup << endl;
- }
-#ifdef dbtux_totally_groks_t_trees
- // check missed semi-leaf/leaf merge
- for (unsigned i = 0; i <= 1; i++) {
- if (node.getLink(i) != NullTupLoc &&
- node.getLink(1 - i) == NullTupLoc &&
- // our semi-leaf seems to satify interior minOccup condition
- node.getOccup() < tree.m_minOccup) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "missed merge with child " << i << endl;
- }
- }
-#endif
- // check inline prefix
- { ConstData data1 = node.getPref();
- Uint32 data2[MaxPrefSize];
- memset(data2, DataFillByte, MaxPrefSize << 2);
- readKeyAttrs(frag, node.getMinMax(0), 0, c_searchKey);
- copyAttrs(frag, c_searchKey, data2, tree.m_prefSize);
- for (unsigned n = 0; n < tree.m_prefSize; n++) {
- if (data1[n] != data2[n]) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << "inline prefix mismatch word " << n;
- out << " value " << hex << data1[n];
- out << " should be " << hex << data2[n] << endl;
- break;
- }
- }
- }
- // check ordering within node
- for (unsigned j = 1; j < node.getOccup(); j++) {
- const TreeEnt ent1 = node.getEnt(j - 1);
- const TreeEnt ent2 = node.getEnt(j);
- unsigned start = 0;
- readKeyAttrs(frag, ent1, start, c_searchKey);
- readKeyAttrs(frag, ent2, start, c_entryKey);
- int ret = cmpSearchKey(frag, start, c_searchKey, c_entryKey);
- if (ret == 0)
- ret = ent1.cmp(ent2);
- if (ret != -1) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << " disorder within node at pos " << j << endl;
- }
- }
- // check ordering wrt subtrees
- for (unsigned i = 0; i <= 1; i++) {
- if (node.getLink(i) == NullTupLoc)
- continue;
- const TreeEnt ent1 = cpar[i].m_minmax[1 - i];
- const TreeEnt ent2 = node.getMinMax(i);
- unsigned start = 0;
- readKeyAttrs(frag, ent1, start, c_searchKey);
- readKeyAttrs(frag, ent2, start, c_entryKey);
- int ret = cmpSearchKey(frag, start, c_searchKey, c_entryKey);
- if (ret == 0)
- ret = ent1.cmp(ent2);
- if (ret != (i == 0 ? -1 : +1)) {
- par.m_ok = false;
- out << par.m_path << sep;
- out << " disorder wrt subtree " << i << endl;
- }
- }
- // return values
- par.m_depth = 1 + max(cpar[0].m_depth, cpar[1].m_depth);
- par.m_occup = node.getOccup();
- for (unsigned i = 0; i <= 1; i++) {
- if (node.getLink(i) == NullTupLoc)
- par.m_minmax[i] = node.getMinMax(i);
- else
- par.m_minmax[i] = cpar[i].m_minmax[i];
- }
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::TupLoc& loc)
-{
- if (loc == Dbtux::NullTupLoc) {
- out << "null";
- } else {
- out << dec << loc.getPageId();
- out << "." << dec << loc.getPageOffset();
- }
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::TreeEnt& ent)
-{
- out << ent.m_tupLoc;
- out << "-" << dec << ent.m_tupVersion;
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::TreeNode& node)
-{
- out << "[TreeNode " << hex << &node;
- out << " [left " << node.m_link[0] << "]";
- out << " [right " << node.m_link[1] << "]";
- out << " [up " << node.m_link[2] << "]";
- out << " [side " << dec << node.m_side << "]";
- out << " [occup " << dec << node.m_occup << "]";
- out << " [balance " << dec << (int)node.m_balance - 1 << "]";
- out << " [nodeScan " << hex << node.m_nodeScan << "]";
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::TreeHead& tree)
-{
- out << "[TreeHead " << hex << &tree;
- out << " [nodeSize " << dec << tree.m_nodeSize << "]";
- out << " [prefSize " << dec << tree.m_prefSize << "]";
- out << " [minOccup " << dec << tree.m_minOccup << "]";
- out << " [maxOccup " << dec << tree.m_maxOccup << "]";
- out << " [AccHead " << dec << tree.getSize(Dbtux::AccHead) << "]";
- out << " [AccPref " << dec << tree.getSize(Dbtux::AccPref) << "]";
- out << " [AccFull " << dec << tree.getSize(Dbtux::AccFull) << "]";
- out << " [root " << hex << tree.m_root << "]";
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::TreePos& pos)
-{
- out << "[TreePos " << hex << &pos;
- out << " [loc " << pos.m_loc << "]";
- out << " [pos " << dec << pos.m_pos << "]";
- out << " [dir " << dec << pos.m_dir << "]";
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::DescAttr& descAttr)
-{
- out << "[DescAttr " << hex << &descAttr;
- out << " [attrDesc " << hex << descAttr.m_attrDesc;
- out << " [primaryAttrId " << dec << descAttr.m_primaryAttrId << "]";
- out << " [typeId " << dec << descAttr.m_typeId << "]";
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
-{
- Dbtux* tux = (Dbtux*)globalData.getBlock(DBTUX);
- out << "[ScanOp " << hex << &scan;
- out << " [state " << dec << scan.m_state << "]";
- out << " [lockwait " << dec << scan.m_lockwait << "]";
- out << " [indexId " << dec << scan.m_indexId << "]";
- out << " [fragId " << dec << scan.m_fragId << "]";
- out << " [transId " << hex << scan.m_transId1 << " " << scan.m_transId2 << "]";
- out << " [savePointId " << dec << scan.m_savePointId << "]";
- out << " [accLockOp " << hex << scan.m_accLockOp << "]";
- out << " [accLockOps";
- {
- DLFifoList<Dbtux::ScanLock>::Head head = scan.m_accLockOps;
- LocalDLFifoList<Dbtux::ScanLock> list(tux->c_scanLockPool, head);
- Dbtux::ScanLockPtr lockPtr;
- list.first(lockPtr);
- while (lockPtr.i != RNIL) {
- out << " " << hex << lockPtr.p->m_accLockOp;
- list.next(lockPtr);
- }
- }
- out << "]";
- out << " [readCommitted " << dec << scan.m_readCommitted << "]";
- out << " [lockMode " << dec << scan.m_lockMode << "]";
- out << " [descending " << dec << scan.m_descending << "]";
- out << " [pos " << scan.m_scanPos << "]";
- out << " [ent " << scan.m_scanEnt << "]";
- for (unsigned i = 0; i <= 1; i++) {
- out << " [bound " << dec << i;
- Dbtux::ScanBound& bound = *scan.m_bound[i];
- Dbtux::ScanBoundIterator iter;
- bound.first(iter);
- for (unsigned j = 0; j < bound.getSize(); j++) {
- out << " " << hex << *iter.data;
- bound.next(iter);
- }
- out << "]";
- }
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::Index& index)
-{
- Dbtux* tux = (Dbtux*)globalData.getBlock(DBTUX);
- out << "[Index " << hex << &index;
- out << " [tableId " << dec << index.m_tableId << "]";
- out << " [numFrags " << dec << index.m_numFrags << "]";
- for (unsigned i = 0; i < index.m_numFrags; i++) {
- out << " [frag " << dec << i << " ";
- const Dbtux::Frag& frag = *tux->c_fragPool.getPtr(index.m_fragPtrI[i]);
- out << frag;
- out << "]";
- }
- out << " [descPage " << hex << index.m_descPage << "]";
- out << " [descOff " << dec << index.m_descOff << "]";
- out << " [numAttrs " << dec << index.m_numAttrs << "]";
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::Frag& frag)
-{
- out << "[Frag " << hex << &frag;
- out << " [tableId " << dec << frag.m_tableId << "]";
- out << " [indexId " << dec << frag.m_indexId << "]";
- out << " [fragId " << dec << frag.m_fragId << "]";
- out << " [descPage " << hex << frag.m_descPage << "]";
- out << " [descOff " << dec << frag.m_descOff << "]";
- out << " [numAttrs " << dec << frag.m_numAttrs << "]";
- out << " [tree " << frag.m_tree << "]";
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::FragOp& fragOp)
-{
- out << "[FragOp " << hex << &fragOp;
- out << " [userPtr " << dec << fragOp.m_userPtr << "]";
- out << " [indexId " << dec << fragOp.m_indexId << "]";
- out << " [fragId " << dec << fragOp.m_fragId << "]";
- out << " [fragNo " << dec << fragOp.m_fragNo << "]";
- out << " numAttrsRecvd " << dec << fragOp.m_numAttrsRecvd << "]";
- out << "]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
-{
- const Dbtux::Frag& frag = node.m_frag;
- const Dbtux::TreeHead& tree = frag.m_tree;
- out << "[NodeHandle " << hex << &node;
- out << " [loc " << node.m_loc << "]";
- out << " [node " << *node.m_node << "]";
- const Uint32* data;
- out << " [pref";
- data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize;
- for (unsigned j = 0; j < tree.m_prefSize; j++)
- out << " " << hex << data[j];
- out << "]";
- out << " [entList";
- unsigned numpos = node.m_node->m_occup;
- data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + tree.m_prefSize;
- const Dbtux::TreeEnt* entList = (const Dbtux::TreeEnt*)data;
- // print entries in logical order
- for (unsigned pos = 1; pos <= numpos; pos++)
- out << " " << entList[pos % numpos];
- out << "]";
- out << "]";
- return out;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
deleted file mode 100644
index fde64161cab..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_GEN_CPP
-#include "Dbtux.hpp"
-
-Dbtux::Dbtux(Block_context& ctx) :
- SimulatedBlock(DBTUX, ctx),
- c_tup(0),
- c_descPageList(RNIL),
-#ifdef VM_TRACE
- debugFile(0),
- debugOut(*new NullOutputStream()),
- debugFlags(0),
-#endif
- c_internalStartPhase(0),
- c_typeOfStart(NodeState::ST_ILLEGAL_TYPE),
- c_dataBuffer(0)
-{
- BLOCK_CONSTRUCTOR(Dbtux);
- // verify size assumptions (also when release-compiled)
- ndbrequire(
- (sizeof(TreeEnt) & 0x3) == 0 &&
- (sizeof(TreeNode) & 0x3) == 0 &&
- (sizeof(DescHead) & 0x3) == 0 &&
- (sizeof(DescAttr) & 0x3) == 0
- );
- /*
- * DbtuxGen.cpp
- */
- addRecSignal(GSN_CONTINUEB, &Dbtux::execCONTINUEB);
- addRecSignal(GSN_STTOR, &Dbtux::execSTTOR);
- addRecSignal(GSN_READ_CONFIG_REQ, &Dbtux::execREAD_CONFIG_REQ, true);
- /*
- * DbtuxMeta.cpp
- */
- addRecSignal(GSN_TUXFRAGREQ, &Dbtux::execTUXFRAGREQ);
- addRecSignal(GSN_TUX_ADD_ATTRREQ, &Dbtux::execTUX_ADD_ATTRREQ);
- addRecSignal(GSN_ALTER_INDX_REQ, &Dbtux::execALTER_INDX_REQ);
- addRecSignal(GSN_DROP_TAB_REQ, &Dbtux::execDROP_TAB_REQ);
- /*
- * DbtuxMaint.cpp
- */
- addRecSignal(GSN_TUX_MAINT_REQ, &Dbtux::execTUX_MAINT_REQ);
- /*
- * DbtuxScan.cpp
- */
- addRecSignal(GSN_ACC_SCANREQ, &Dbtux::execACC_SCANREQ);
- addRecSignal(GSN_TUX_BOUND_INFO, &Dbtux::execTUX_BOUND_INFO);
- addRecSignal(GSN_NEXT_SCANREQ, &Dbtux::execNEXT_SCANREQ);
- addRecSignal(GSN_ACC_CHECK_SCAN, &Dbtux::execACC_CHECK_SCAN);
- addRecSignal(GSN_ACCKEYCONF, &Dbtux::execACCKEYCONF);
- addRecSignal(GSN_ACCKEYREF, &Dbtux::execACCKEYREF);
- addRecSignal(GSN_ACC_ABORTCONF, &Dbtux::execACC_ABORTCONF);
- /*
- * DbtuxStat.cpp
- */
- addRecSignal(GSN_READ_PSEUDO_REQ, &Dbtux::execREAD_PSEUDO_REQ);
- /*
- * DbtuxDebug.cpp
- */
- addRecSignal(GSN_DUMP_STATE_ORD, &Dbtux::execDUMP_STATE_ORD);
-}
-
-Dbtux::~Dbtux()
-{
-}
-
-void
-Dbtux::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- const Uint32* data = signal->getDataPtr();
- switch (data[0]) {
- case TuxContinueB::DropIndex: // currently unused
- {
- IndexPtr indexPtr;
- c_indexPool.getPtr(indexPtr, data[1]);
- dropIndex(signal, indexPtr, data[2], data[3]);
- }
- break;
- default:
- ndbrequire(false);
- break;
- }
-}
-
-/*
- * STTOR is sent to one block at a time. In NDBCNTR it triggers
- * NDB_STTOR to the "old" blocks. STTOR carries start phase (SP) and
- * NDB_STTOR carries internal start phase (ISP).
- *
- * SP ISP activities
- * 1 none
- * 2 1
- * 3 2 recover metadata, activate indexes
- * 4 3 recover data
- * 5 4-6
- * 6 skip
- * 7 skip
- * 8 7 build non-logged indexes on SR
- *
- * DBTUX catches type of start (IS, SR, NR, INR) at SP 3 and updates
- * internal start phase at SP 7. These are used to prevent index
- * maintenance operations caused by redo log at SR.
- */
-void
-Dbtux::execSTTOR(Signal* signal)
-{
- jamEntry();
- Uint32 startPhase = signal->theData[1];
- switch (startPhase) {
- case 1:
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- c_tup = (Dbtup*)globalData.getBlock(DBTUP);
- ndbrequire(c_tup != 0);
- break;
- case 3:
- jam();
- c_typeOfStart = signal->theData[7];
- break;
- case 7:
- c_internalStartPhase = 6;
- default:
- jam();
- break;
- }
- signal->theData[0] = 0; // garbage
- signal->theData[1] = 0; // garbage
- signal->theData[2] = 0; // garbage
- signal->theData[3] = 1;
- signal->theData[4] = 3; // for c_typeOfStart
- signal->theData[5] = 7; // for c_internalStartPhase
- signal->theData[6] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
-}
-
-void
-Dbtux::execREAD_CONFIG_REQ(Signal* signal)
-{
- jamEntry();
-
- const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
- Uint32 ref = req->senderRef;
- Uint32 senderData = req->senderData;
- ndbrequire(req->noOfParameters == 0);
-
- Uint32 nIndex;
- Uint32 nFragment;
- Uint32 nAttribute;
- Uint32 nScanOp;
- Uint32 nScanBatch;
-
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_INDEX, &nIndex));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_FRAGMENT, &nFragment));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_ATTRIBUTE, &nAttribute));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_BATCH_SIZE, &nScanBatch));
-
- const Uint32 nDescPage = (nIndex * DescHeadSize + nAttribute * DescAttrSize + DescPageSize - 1) / DescPageSize;
- const Uint32 nScanBoundWords = nScanOp * ScanBoundSegmentSize * 4;
- const Uint32 nScanLock = nScanOp * nScanBatch;
-
- c_indexPool.setSize(nIndex);
- c_fragPool.setSize(nFragment);
- c_descPagePool.setSize(nDescPage);
- c_fragOpPool.setSize(MaxIndexFragments);
- c_scanOpPool.setSize(nScanOp);
- c_scanBoundPool.setSize(nScanBoundWords);
- c_scanLockPool.setSize(nScanLock);
- /*
- * Index id is physical array index. We seize and initialize all
- * index records now.
- */
- IndexPtr indexPtr;
- while (1) {
- jam();
- refresh_watch_dog();
- c_indexPool.seize(indexPtr);
- if (indexPtr.i == RNIL) {
- jam();
- break;
- }
- new (indexPtr.p) Index();
- }
- // allocate buffers
- c_keyAttrs = (Uint32*)allocRecord("c_keyAttrs", sizeof(Uint32), MaxIndexAttributes);
- c_sqlCmp = (NdbSqlUtil::Cmp**)allocRecord("c_sqlCmp", sizeof(NdbSqlUtil::Cmp*), MaxIndexAttributes);
- c_searchKey = (Uint32*)allocRecord("c_searchKey", sizeof(Uint32), MaxAttrDataSize);
- c_entryKey = (Uint32*)allocRecord("c_entryKey", sizeof(Uint32), MaxAttrDataSize);
- c_dataBuffer = (Uint32*)allocRecord("c_dataBuffer", sizeof(Uint64), (MaxAttrDataSize + 1) >> 1);
- // ack
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
-// utils
-
-void
-Dbtux::setKeyAttrs(const Frag& frag)
-{
- Data keyAttrs = c_keyAttrs; // global
- NdbSqlUtil::Cmp** sqlCmp = c_sqlCmp; // global
- 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
- ah(keyAttrs) = AttributeHeader(descAttr.m_primaryAttrId, size);
- keyAttrs += 1;
- // set comparison method pointer
- const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getTypeBinary(descAttr.m_typeId);
- ndbrequire(sqlType.m_cmp != 0);
- *(sqlCmp++) = sqlType.m_cmp;
- }
-}
-
-void
-Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData)
-{
- ConstData keyAttrs = c_keyAttrs; // global
- const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
- const TupLoc tupLoc = ent.m_tupLoc;
- const Uint32 tupVersion = ent.m_tupVersion;
- ndbrequire(start < frag.m_numAttrs);
- const Uint32 numAttrs = frag.m_numAttrs - start;
- // skip to start position in keyAttrs only
- keyAttrs += start;
- int ret = c_tup->tuxReadAttrs(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), tupVersion, keyAttrs, numAttrs, 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 = ah(data).getAttributeId();
- Uint32 dataSize = ah(data).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
-Dbtux::readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize)
-{
- const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
- const TupLoc tupLoc = ent.m_tupLoc;
- int ret = c_tup->tuxReadPk(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), pkData, true);
- jamEntry();
- // TODO handle error
- ndbrequire(ret > 0);
- pkSize = ret;
-}
-
-/*
- * Copy attribute data with headers. Input is all index key data.
- * Copies whatever fits.
- */
-void
-Dbtux::copyAttrs(const Frag& frag, ConstData data1, Data data2, unsigned maxlen2)
-{
- unsigned n = frag.m_numAttrs;
- unsigned len2 = maxlen2;
- while (n != 0) {
- jam();
- const unsigned dataSize = ah(data1).getDataSize();
- // copy header
- if (len2 == 0)
- return;
- data2[0] = data1[0];
- data1 += 1;
- data2 += 1;
- len2 -= 1;
- // copy data
- for (unsigned i = 0; i < dataSize; i++) {
- if (len2 == 0)
- return;
- data2[i] = data1[i];
- len2 -= 1;
- }
- data1 += dataSize;
- data2 += dataSize;
- n -= 1;
- }
-#ifdef VM_TRACE
- memset(data2, DataFillByte, len2 << 2);
-#endif
-}
-
-void
-Dbtux::unpackBound(const ScanBound& bound, Data dest)
-{
- ScanBoundIterator iter;
- bound.first(iter);
- const unsigned n = bound.getSize();
- unsigned j;
- for (j = 0; j < n; j++) {
- dest[j] = *iter.data;
- bound.next(iter);
- }
-}
-
-BLOCK_FUNCTIONS(Dbtux)
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
deleted file mode 100644
index 65fc1d114f0..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_MAINT_CPP
-#include "Dbtux.hpp"
-
-/*
- * Maintain index.
- */
-
-void
-Dbtux::execTUX_MAINT_REQ(Signal* signal)
-{
- jamEntry();
- TuxMaintReq* const sig = (TuxMaintReq*)signal->getDataPtrSend();
- // ignore requests from redo log
- if (c_internalStartPhase < 6 &&
- c_typeOfStart != NodeState::ST_NODE_RESTART &&
- c_typeOfStart != NodeState::ST_INITIAL_NODE_RESTART) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugMaint) {
- TupLoc tupLoc(sig->pageId, sig->pageIndex);
- debugOut << "opInfo=" << hex << sig->opInfo;
- debugOut << " tableId=" << dec << sig->tableId;
- debugOut << " indexId=" << dec << sig->indexId;
- debugOut << " fragId=" << dec << sig->fragId;
- debugOut << " tupLoc=" << tupLoc;
- debugOut << " tupVersion=" << dec << sig->tupVersion;
- debugOut << " -- ignored at ISP=" << dec << c_internalStartPhase;
- debugOut << " TOS=" << dec << c_typeOfStart;
- debugOut << endl;
- }
-#endif
- sig->errorCode = 0;
- return;
- }
- TuxMaintReq reqCopy = *sig;
- TuxMaintReq* const req = &reqCopy;
- const Uint32 opCode = req->opInfo & 0xFF;
- const Uint32 opFlag = req->opInfo >> 8;
- // get the index
- IndexPtr indexPtr;
- c_indexPool.getPtr(indexPtr, req->indexId);
- ndbrequire(indexPtr.p->m_tableId == req->tableId);
- // get base fragment id and extra bits
- const Uint32 fragId = req->fragId;
- // get the fragment
- FragPtr fragPtr;
- fragPtr.i = RNIL;
- for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) {
- jam();
- if (indexPtr.p->m_fragId[i] == fragId) {
- jam();
- c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
- break;
- }
- }
- ndbrequire(fragPtr.i != RNIL);
- Frag& frag = *fragPtr.p;
- // set up index keys for this operation
- setKeyAttrs(frag);
- // set up search entry
- TreeEnt ent;
- ent.m_tupLoc = TupLoc(req->pageId, req->pageIndex);
- ent.m_tupVersion = req->tupVersion;
- // read search key
- readKeyAttrs(frag, ent, 0, c_searchKey);
- if (! frag.m_storeNullKey) {
- // check if all keys are null
- const unsigned numAttrs = frag.m_numAttrs;
- bool allNull = true;
- for (unsigned i = 0; i < numAttrs; i++) {
- if (c_searchKey[i] != 0) {
- jam();
- allNull = false;
- break;
- }
- }
- if (allNull) {
- jam();
- req->errorCode = 0;
- *sig = *req;
- return;
- }
- }
-#ifdef VM_TRACE
- if (debugFlags & DebugMaint) {
- debugOut << "opCode=" << dec << opCode;
- debugOut << " opFlag=" << dec << opFlag;
- debugOut << " tableId=" << dec << req->tableId;
- debugOut << " indexId=" << dec << req->indexId;
- debugOut << " fragId=" << dec << req->fragId;
- debugOut << " entry=" << ent;
- debugOut << endl;
- }
-#endif
- // do the operation
- req->errorCode = 0;
- TreePos treePos;
- bool ok;
- switch (opCode) {
- case TuxMaintReq::OpAdd:
- jam();
- ok = searchToAdd(frag, c_searchKey, ent, treePos);
-#ifdef VM_TRACE
- if (debugFlags & DebugMaint) {
- debugOut << treePos << (! ok ? " - error" : "") << endl;
- }
-#endif
- if (! ok) {
- jam();
- // there is no "Building" state so this will have to do
- if (indexPtr.p->m_state == Index::Online) {
- jam();
- req->errorCode = TuxMaintReq::SearchError;
- }
- break;
- }
- /*
- * At most one new node is inserted in the operation. Pre-allocate
- * it so that the operation cannot fail.
- */
- if (frag.m_freeLoc == NullTupLoc) {
- jam();
- NodeHandle node(frag);
- req->errorCode = allocNode(signal, node);
- if (req->errorCode != 0) {
- jam();
- break;
- }
- // link to freelist
- node.setLink(0, frag.m_freeLoc);
- frag.m_freeLoc = node.m_loc;
- ndbrequire(frag.m_freeLoc != NullTupLoc);
- }
- treeAdd(frag, treePos, ent);
- break;
- case TuxMaintReq::OpRemove:
- jam();
- ok = searchToRemove(frag, c_searchKey, ent, treePos);
-#ifdef VM_TRACE
- if (debugFlags & DebugMaint) {
- debugOut << treePos << (! ok ? " - error" : "") << endl;
- }
-#endif
- if (! ok) {
- jam();
- // there is no "Building" state so this will have to do
- if (indexPtr.p->m_state == Index::Online) {
- jam();
- req->errorCode = TuxMaintReq::SearchError;
- }
- break;
- }
- treeRemove(frag, treePos);
- break;
- default:
- ndbrequire(false);
- break;
- }
-#ifdef VM_TRACE
- if (debugFlags & DebugTree) {
- printTree(signal, frag, debugOut);
- }
-#endif
- // copy back
- *sig = *req;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
deleted file mode 100644
index 423ca83af14..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_META_CPP
-#include "Dbtux.hpp"
-#include <my_sys.h>
-
-/*
- * Create index.
- *
- * For historical reasons it looks like we are adding random fragments
- * and attributes to existing index. In fact all fragments must be
- * created at one time and they have identical attributes.
- */
-
-void
-Dbtux::execTUXFRAGREQ(Signal* signal)
-{
- jamEntry();
- if (signal->theData[0] == (Uint32)-1) {
- jam();
- abortAddFragOp(signal);
- return;
- }
- const TuxFragReq reqCopy = *(const TuxFragReq*)signal->getDataPtr();
- const TuxFragReq* const req = &reqCopy;
- IndexPtr indexPtr;
- indexPtr.i = RNIL;
- FragOpPtr fragOpPtr;
- fragOpPtr.i = RNIL;
- TuxFragRef::ErrorCode errorCode = TuxFragRef::NoError;
- do {
- // get the index record
- if (req->tableId >= c_indexPool.getSize()) {
- jam();
- errorCode = TuxFragRef::InvalidRequest;
- break;
- }
- c_indexPool.getPtr(indexPtr, req->tableId);
- if (indexPtr.p->m_state != Index::NotDefined &&
- indexPtr.p->m_state != Index::Defining) {
- jam();
- errorCode = TuxFragRef::InvalidRequest;
- indexPtr.i = RNIL; // leave alone
- break;
- }
- // get new operation record
- c_fragOpPool.seize(fragOpPtr);
- ndbrequire(fragOpPtr.i != RNIL);
- new (fragOpPtr.p) FragOp();
- fragOpPtr.p->m_userPtr = req->userPtr;
- fragOpPtr.p->m_userRef = req->userRef;
- fragOpPtr.p->m_indexId = req->tableId;
- fragOpPtr.p->m_fragId = req->fragId;
- fragOpPtr.p->m_fragNo = indexPtr.p->m_numFrags;
- fragOpPtr.p->m_numAttrsRecvd = 0;
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Seize frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
- }
-#endif
- // check if index has place for more fragments
- ndbrequire(indexPtr.p->m_numFrags < MaxIndexFragments);
- // seize new fragment record
- FragPtr fragPtr;
- c_fragPool.seize(fragPtr);
- if (fragPtr.i == RNIL) {
- jam();
- errorCode = TuxFragRef::NoFreeFragment;
- break;
- }
- new (fragPtr.p) Frag(c_scanOpPool);
- fragPtr.p->m_tableId = req->primaryTableId;
- fragPtr.p->m_indexId = req->tableId;
- fragPtr.p->m_fragId = req->fragId;
- fragPtr.p->m_numAttrs = req->noOfAttr;
- fragPtr.p->m_storeNullKey = true; // not yet configurable
- fragPtr.p->m_tupIndexFragPtrI = req->tupIndexFragPtrI;
- fragPtr.p->m_tupTableFragPtrI = req->tupTableFragPtrI[0];
- fragPtr.p->m_accTableFragPtrI = req->accTableFragPtrI[0];
- // add the fragment to the index
- indexPtr.p->m_fragId[indexPtr.p->m_numFrags] = req->fragId;
- indexPtr.p->m_fragPtrI[indexPtr.p->m_numFrags] = fragPtr.i;
- indexPtr.p->m_numFrags++;
- // save under operation
- fragOpPtr.p->m_fragPtrI = fragPtr.i;
- // prepare to receive attributes
- if (fragOpPtr.p->m_fragNo == 0) {
- jam();
- // receiving first fragment
- ndbrequire(
- indexPtr.p->m_state == Index::NotDefined &&
- DictTabInfo::isOrderedIndex(req->tableType) &&
- req->noOfAttr > 0 &&
- req->noOfAttr <= MaxIndexAttributes &&
- indexPtr.p->m_descPage == RNIL);
- indexPtr.p->m_state = Index::Defining;
- indexPtr.p->m_tableType = (DictTabInfo::TableType)req->tableType;
- indexPtr.p->m_tableId = req->primaryTableId;
- indexPtr.p->m_numAttrs = req->noOfAttr;
- indexPtr.p->m_storeNullKey = true; // not yet configurable
- // allocate attribute descriptors
- if (! allocDescEnt(indexPtr)) {
- jam();
- errorCode = TuxFragRef::NoFreeAttributes;
- break;
- }
- } else {
- // receiving subsequent fragment
- jam();
- ndbrequire(
- indexPtr.p->m_state == Index::Defining &&
- indexPtr.p->m_tableType == (DictTabInfo::TableType)req->tableType &&
- indexPtr.p->m_tableId == req->primaryTableId &&
- indexPtr.p->m_numAttrs == req->noOfAttr);
- }
- // copy metadata address to each fragment
- fragPtr.p->m_descPage = indexPtr.p->m_descPage;
- fragPtr.p->m_descOff = indexPtr.p->m_descOff;
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Add frag " << fragPtr.i << " " << *fragPtr.p << endl;
- }
-#endif
- // error inserts
- if (ERROR_INSERTED(12001) && fragOpPtr.p->m_fragNo == 0 ||
- ERROR_INSERTED(12002) && fragOpPtr.p->m_fragNo == 1) {
- jam();
- errorCode = (TuxFragRef::ErrorCode)1;
- CLEAR_ERROR_INSERT_VALUE;
- break;
- }
- // success
- TuxFragConf* const conf = (TuxFragConf*)signal->getDataPtrSend();
- conf->userPtr = req->userPtr;
- conf->tuxConnectPtr = fragOpPtr.i;
- conf->fragPtr = fragPtr.i;
- conf->fragId = fragPtr.p->m_fragId;
- sendSignal(req->userRef, GSN_TUXFRAGCONF,
- signal, TuxFragConf::SignalLength, JBB);
- return;
- } while (0);
- // error
- TuxFragRef* const ref = (TuxFragRef*)signal->getDataPtrSend();
- ref->userPtr = req->userPtr;
- ref->errorCode = errorCode;
- sendSignal(req->userRef, GSN_TUXFRAGREF,
- signal, TuxFragRef::SignalLength, JBB);
- if (fragOpPtr.i != RNIL) {
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Release on frag error frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
- }
-#endif
- c_fragOpPool.release(fragOpPtr);
- }
- if (indexPtr.i != RNIL) {
- jam();
- // let DICT drop the unfinished index
- }
-}
-
-void
-Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
-{
- jamEntry();
- const TuxAddAttrReq reqCopy = *(const TuxAddAttrReq*)signal->getDataPtr();
- const TuxAddAttrReq* const req = &reqCopy;
- // get the records
- FragOpPtr fragOpPtr;
- IndexPtr indexPtr;
- FragPtr fragPtr;
- c_fragOpPool.getPtr(fragOpPtr, req->tuxConnectPtr);
- c_indexPool.getPtr(indexPtr, fragOpPtr.p->m_indexId);
- c_fragPool.getPtr(fragPtr, fragOpPtr.p->m_fragPtrI);
- TuxAddAttrRef::ErrorCode errorCode = TuxAddAttrRef::NoError;
- do {
- // expected attribute id
- const unsigned attrId = fragOpPtr.p->m_numAttrsRecvd++;
- ndbrequire(
- indexPtr.p->m_state == Index::Defining &&
- attrId < indexPtr.p->m_numAttrs &&
- attrId == req->attrId);
- // define the attribute
- DescEnt& descEnt = getDescEnt(indexPtr.p->m_descPage, indexPtr.p->m_descOff);
- DescAttr& descAttr = descEnt.m_descAttr[attrId];
- descAttr.m_attrDesc = req->attrDescriptor;
- descAttr.m_primaryAttrId = req->primaryAttrId;
- descAttr.m_typeId = AttributeDescriptor::getType(req->attrDescriptor);
- descAttr.m_charset = (req->extTypeInfo >> 16);
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Add frag " << fragPtr.i << " attr " << attrId << " " << descAttr << endl;
- }
-#endif
- // check that type is valid and has a binary comparison method
- const NdbSqlUtil::Type& type = NdbSqlUtil::getTypeBinary(descAttr.m_typeId);
- if (type.m_typeId == NdbSqlUtil::Type::Undefined ||
- type.m_cmp == 0) {
- jam();
- errorCode = TuxAddAttrRef::InvalidAttributeType;
- break;
- }
- if (descAttr.m_charset != 0) {
- 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::ErrorCode) err;
- break;
- }
- }
- 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 ||
- ERROR_INSERTED(12005) && fragOpPtr.p->m_fragNo == 1 && attrId == 0 ||
- ERROR_INSERTED(12006) && fragOpPtr.p->m_fragNo == 1 && lastAttr) {
- errorCode = (TuxAddAttrRef::ErrorCode)1;
- CLEAR_ERROR_INSERT_VALUE;
- break;
- }
- if (lastAttr) {
- jam();
- // initialize tree header
- TreeHead& tree = fragPtr.p->m_tree;
- new (&tree) TreeHead();
- // make these configurable later
- tree.m_nodeSize = MAX_TTREE_NODE_SIZE;
- tree.m_prefSize = MAX_TTREE_PREF_SIZE;
- const unsigned maxSlack = MAX_TTREE_NODE_SLACK;
- // size up to and including first 2 entries
- const unsigned pref = tree.getSize(AccPref);
- if (! (pref <= tree.m_nodeSize)) {
- jam();
- errorCode = TuxAddAttrRef::InvalidNodeSize;
- break;
- }
- const unsigned slots = (tree.m_nodeSize - pref) / TreeEntSize;
- // leave out work space entry
- tree.m_maxOccup = 2 + slots - 1;
- // min occupancy of interior node must be at least 2
- if (! (2 + maxSlack <= tree.m_maxOccup)) {
- jam();
- errorCode = TuxAddAttrRef::InvalidNodeSize;
- break;
- }
- tree.m_minOccup = tree.m_maxOccup - maxSlack;
- // root node does not exist (also set by ctor)
- tree.m_root = NullTupLoc;
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- if (fragOpPtr.p->m_fragNo == 0) {
- debugOut << "Index id=" << indexPtr.i;
- debugOut << " nodeSize=" << tree.m_nodeSize;
- debugOut << " headSize=" << NodeHeadSize;
- debugOut << " prefSize=" << tree.m_prefSize;
- debugOut << " entrySize=" << TreeEntSize;
- debugOut << " minOccup=" << tree.m_minOccup;
- debugOut << " maxOccup=" << tree.m_maxOccup;
- debugOut << endl;
- }
- }
-#endif
- // fragment is defined
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Release frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
- }
-#endif
- c_fragOpPool.release(fragOpPtr);
- }
- // success
- TuxAddAttrConf* conf = (TuxAddAttrConf*)signal->getDataPtrSend();
- conf->userPtr = fragOpPtr.p->m_userPtr;
- conf->lastAttr = lastAttr;
- sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRCONF,
- signal, TuxAddAttrConf::SignalLength, JBB);
- return;
- } while (0);
- // error
- TuxAddAttrRef* ref = (TuxAddAttrRef*)signal->getDataPtrSend();
- ref->userPtr = fragOpPtr.p->m_userPtr;
- ref->errorCode = errorCode;
- sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRREF,
- signal, TuxAddAttrRef::SignalLength, JBB);
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Release on attr error frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
- }
-#endif
- c_fragOpPool.release(fragOpPtr);
- // let DICT drop the unfinished index
-}
-
-/*
- * LQH aborts on-going create index operation.
- */
-void
-Dbtux::abortAddFragOp(Signal* signal)
-{
- FragOpPtr fragOpPtr;
- IndexPtr indexPtr;
- c_fragOpPool.getPtr(fragOpPtr, signal->theData[1]);
- c_indexPool.getPtr(indexPtr, fragOpPtr.p->m_indexId);
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Release on abort frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
- }
-#endif
- c_fragOpPool.release(fragOpPtr);
- // let DICT drop the unfinished index
-}
-
-/*
- * Set index online. Currently at system restart this arrives before
- * build and is therefore not correct.
- */
-void
-Dbtux::execALTER_INDX_REQ(Signal* signal)
-{
- jamEntry();
- const AlterIndxReq reqCopy = *(const AlterIndxReq*)signal->getDataPtr();
- const AlterIndxReq* const req = &reqCopy;
- // set index online after build
- IndexPtr indexPtr;
- c_indexPool.getPtr(indexPtr, req->getIndexId());
- indexPtr.p->m_state = Index::Online;
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Online index " << indexPtr.i << " " << *indexPtr.p << endl;
- }
-#endif
- // success
- AlterIndxConf* const conf = (AlterIndxConf*)signal->getDataPtrSend();
- conf->setUserRef(reference());
- conf->setConnectionPtr(req->getConnectionPtr());
- conf->setRequestType(req->getRequestType());
- conf->setTableId(req->getTableId());
- conf->setIndexId(req->getIndexId());
- conf->setIndexVersion(req->getIndexVersion());
- sendSignal(req->getUserRef(), GSN_ALTER_INDX_CONF,
- signal, AlterIndxConf::SignalLength, JBB);
-}
-
-/*
- * Drop index.
- *
- * Uses same DROP_TAB_REQ signal as normal tables.
- */
-
-void
-Dbtux::execDROP_TAB_REQ(Signal* signal)
-{
- jamEntry();
- const DropTabReq reqCopy = *(const DropTabReq*)signal->getDataPtr();
- const DropTabReq* const req = &reqCopy;
- IndexPtr indexPtr;
-
- Uint32 tableId = req->tableId;
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- if (tableId >= c_indexPool.getSize()) {
- jam();
- // reply to sender
- DropTabConf* const conf = (DropTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->tableId = tableId;
- sendSignal(senderRef, GSN_DROP_TAB_CONF,
- signal, DropTabConf::SignalLength, JBB);
- return;
- }
-
- c_indexPool.getPtr(indexPtr, req->tableId);
- // drop works regardless of index state
-#ifdef VM_TRACE
- if (debugFlags & DebugMeta) {
- debugOut << "Drop index " << indexPtr.i << " " << *indexPtr.p << endl;
- }
-#endif
- ndbrequire(req->senderRef != 0);
- dropIndex(signal, indexPtr, req->senderRef, req->senderData);
-}
-
-void
-Dbtux::dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData)
-{
- jam();
- indexPtr.p->m_state = Index::Dropping;
- // drop fragments
- while (indexPtr.p->m_numFrags > 0) {
- jam();
- Uint32 i = --indexPtr.p->m_numFrags;
- FragPtr fragPtr;
- c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
- c_fragPool.release(fragPtr);
- }
- // drop attributes
- if (indexPtr.p->m_descPage != RNIL) {
- jam();
- freeDescEnt(indexPtr);
- indexPtr.p->m_descPage = RNIL;
- }
- if (senderRef != 0) {
- jam();
- // reply to sender
- DropTabConf* const conf = (DropTabConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->tableId = indexPtr.i;
- sendSignal(senderRef, GSN_DROP_TAB_CONF,
- signal, DropTabConf::SignalLength, JBB);
- }
- new (indexPtr.p) Index();
-}
-
-/*
- * Subroutines.
- */
-
-bool
-Dbtux::allocDescEnt(IndexPtr indexPtr)
-{
- jam();
- const unsigned size = DescHeadSize + indexPtr.p->m_numAttrs * DescAttrSize;
- DescPagePtr pagePtr;
- pagePtr.i = c_descPageList;
- while (pagePtr.i != RNIL) {
- jam();
- c_descPagePool.getPtr(pagePtr);
- if (pagePtr.p->m_numFree >= size) {
- jam();
- break;
- }
- pagePtr.i = pagePtr.p->m_nextPage;
- }
- if (pagePtr.i == RNIL) {
- jam();
- if (! c_descPagePool.seize(pagePtr)) {
- jam();
- return false;
- }
- new (pagePtr.p) DescPage();
- // add in front of list
- pagePtr.p->m_nextPage = c_descPageList;
- c_descPageList = pagePtr.i;
- pagePtr.p->m_numFree = DescPageSize;
- }
- ndbrequire(pagePtr.p->m_numFree >= size);
- indexPtr.p->m_descPage = pagePtr.i;
- indexPtr.p->m_descOff = DescPageSize - pagePtr.p->m_numFree;
- pagePtr.p->m_numFree -= size;
- DescEnt& descEnt = getDescEnt(indexPtr.p->m_descPage, indexPtr.p->m_descOff);
- descEnt.m_descHead.m_indexId = indexPtr.i;
- descEnt.m_descHead.pad1 = 0;
- return true;
-}
-
-void
-Dbtux::freeDescEnt(IndexPtr indexPtr)
-{
- DescPagePtr pagePtr;
- c_descPagePool.getPtr(pagePtr, indexPtr.p->m_descPage);
- Uint32* const data = pagePtr.p->m_data;
- const unsigned size = DescHeadSize + indexPtr.p->m_numAttrs * DescAttrSize;
- unsigned off = indexPtr.p->m_descOff;
- // move the gap to the free area at the top
- while (off + size < DescPageSize - pagePtr.p->m_numFree) {
- jam();
- // next entry to move over the gap
- DescEnt& descEnt2 = *(DescEnt*)&data[off + size];
- Uint32 indexId2 = descEnt2.m_descHead.m_indexId;
- Index& index2 = *c_indexPool.getPtr(indexId2);
- unsigned size2 = DescHeadSize + index2.m_numAttrs * DescAttrSize;
- ndbrequire(
- index2.m_descPage == pagePtr.i &&
- index2.m_descOff == off + size);
- // move the entry (overlapping copy if size < size2)
- unsigned i;
- for (i = 0; i < size2; i++) {
- jam();
- data[off + i] = data[off + size + i];
- }
- off += size2;
- // adjust page offset in index and all fragments
- index2.m_descOff -= size;
- for (i = 0; i < index2.m_numFrags; i++) {
- jam();
- Frag& frag2 = *c_fragPool.getPtr(index2.m_fragPtrI[i]);
- frag2.m_descOff -= size;
- ndbrequire(
- frag2.m_descPage == index2.m_descPage &&
- frag2.m_descOff == index2.m_descOff);
- }
- }
- ndbrequire(off + size == DescPageSize - pagePtr.p->m_numFree);
- pagePtr.p->m_numFree += size;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
deleted file mode 100644
index 4cbd9103c94..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+++ /dev/null
@@ -1,590 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_NODE_CPP
-#include "Dbtux.hpp"
-
-/*
- * Allocate index node in TUP.
- */
-int
-Dbtux::allocNode(Signal* signal, NodeHandle& node)
-{
- if (ERROR_INSERTED(12007)) {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- return TuxMaintReq::NoMemError;
- }
- Frag& frag = node.m_frag;
- Uint32 pageId = NullTupLoc.getPageId();
- Uint32 pageOffset = NullTupLoc.getPageOffset();
- Uint32* node32 = 0;
- int errorCode = c_tup->tuxAllocNode(signal, frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
- jamEntry();
- if (errorCode == 0) {
- jam();
- node.m_loc = TupLoc(pageId, pageOffset);
- node.m_node = reinterpret_cast<TreeNode*>(node32);
- ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
- } else {
- switch (errorCode) {
- case 827:
- errorCode = TuxMaintReq::NoMemError;
- break;
- }
- }
- return errorCode;
-}
-
-/*
- * Set handle to point to existing node.
- */
-void
-Dbtux::selectNode(NodeHandle& node, TupLoc loc)
-{
- Frag& frag = node.m_frag;
- ndbrequire(loc != NullTupLoc);
- Uint32 pageId = loc.getPageId();
- Uint32 pageOffset = loc.getPageOffset();
- Uint32* node32 = 0;
- c_tup->tuxGetNode(frag.m_tupIndexFragPtrI, pageId, pageOffset, node32);
- jamEntry();
- node.m_loc = loc;
- node.m_node = reinterpret_cast<TreeNode*>(node32);
- ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
-}
-
-/*
- * Set handle to point to new node. Uses a pre-allocated node.
- */
-void
-Dbtux::insertNode(NodeHandle& node)
-{
- Frag& frag = node.m_frag;
- // unlink from freelist
- selectNode(node, frag.m_freeLoc);
- frag.m_freeLoc = node.getLink(0);
- new (node.m_node) TreeNode();
-#ifdef VM_TRACE
- TreeHead& tree = frag.m_tree;
- memset(node.getPref(), DataFillByte, tree.m_prefSize << 2);
- TreeEnt* entList = tree.getEntList(node.m_node);
- memset(entList, NodeFillByte, (tree.m_maxOccup + 1) * (TreeEntSize << 2));
-#endif
-}
-
-/*
- * Delete existing node. Simply put it on the freelist.
- */
-void
-Dbtux::deleteNode(NodeHandle& node)
-{
- Frag& frag = node.m_frag;
- ndbrequire(node.getOccup() == 0);
- // link to freelist
- node.setLink(0, frag.m_freeLoc);
- frag.m_freeLoc = node.m_loc;
- // invalidate the handle
- node.m_loc = NullTupLoc;
- node.m_node = 0;
-}
-
-/*
- * Set prefix. Copies the number of words that fits. Includes
- * attribute headers for now. XXX use null mask instead
- */
-void
-Dbtux::setNodePref(NodeHandle& node)
-{
- const Frag& frag = node.m_frag;
- const TreeHead& tree = frag.m_tree;
- readKeyAttrs(frag, node.getMinMax(0), 0, c_entryKey);
- copyAttrs(frag, c_entryKey, node.getPref(), tree.m_prefSize);
-}
-
-// node operations
-
-/*
- * Add entry at position. Move entries greater than or equal to the old
- * one (if any) to the right.
- *
- * X
- * v
- * A B C D E _ _ => A B C X D E _
- * 0 1 2 3 4 5 6 0 1 2 3 4 5 6
- *
- * Add list of scans at the new entry.
- */
-void
-Dbtux::nodePushUp(NodeHandle& node, unsigned pos, const TreeEnt& ent, Uint32 scanList)
-{
- Frag& frag = node.m_frag;
- TreeHead& tree = frag.m_tree;
- const unsigned occup = node.getOccup();
- ndbrequire(occup < tree.m_maxOccup && pos <= occup);
- // fix old scans
- if (node.getNodeScan() != RNIL)
- nodePushUpScans(node, pos);
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- for (unsigned i = occup; i > pos; i--) {
- jam();
- tmpList[i] = tmpList[i - 1];
- }
- tmpList[pos] = ent;
- entList[0] = entList[occup + 1];
- node.setOccup(occup + 1);
- // add new scans
- if (scanList != RNIL)
- addScanList(node, pos, scanList);
- // fix prefix
- if (occup == 0 || pos == 0)
- setNodePref(node);
-}
-
-void
-Dbtux::nodePushUpScans(NodeHandle& node, unsigned pos)
-{
- const unsigned occup = node.getOccup();
- ScanOpPtr scanPtr;
- scanPtr.i = node.getNodeScan();
- do {
- jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
- if (scanPos.m_pos >= pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At pushUp pos=" << pos << " " << node << endl;
- }
-#endif
- scanPos.m_pos++;
- }
- scanPtr.i = scanPtr.p->m_nodeScan;
- } while (scanPtr.i != RNIL);
-}
-
-/*
- * Remove and return entry at position. Move entries greater than the
- * removed one to the left. This is the opposite of nodePushUp.
- *
- * D
- * ^ ^
- * A B C D E F _ => A B C E F _ _
- * 0 1 2 3 4 5 6 0 1 2 3 4 5 6
- *
- * Scans at removed entry are returned if non-zero location is passed or
- * else moved forward.
- */
-void
-Dbtux::nodePopDown(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32* scanList)
-{
- Frag& frag = node.m_frag;
- TreeHead& tree = frag.m_tree;
- const unsigned occup = node.getOccup();
- ndbrequire(occup <= tree.m_maxOccup && pos < occup);
- if (node.getNodeScan() != RNIL) {
- // remove or move scans at this position
- if (scanList == 0)
- moveScanList(node, pos);
- else
- removeScanList(node, pos, *scanList);
- // fix other scans
- if (node.getNodeScan() != RNIL)
- nodePopDownScans(node, pos);
- }
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- ent = tmpList[pos];
- for (unsigned i = pos; i < occup - 1; i++) {
- jam();
- tmpList[i] = tmpList[i + 1];
- }
- entList[0] = entList[occup - 1];
- node.setOccup(occup - 1);
- // fix prefix
- if (occup != 1 && pos == 0)
- setNodePref(node);
-}
-
-void
-Dbtux::nodePopDownScans(NodeHandle& node, unsigned pos)
-{
- const unsigned occup = node.getOccup();
- ScanOpPtr scanPtr;
- scanPtr.i = node.getNodeScan();
- do {
- jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
- // handled before
- ndbrequire(scanPos.m_pos != pos);
- if (scanPos.m_pos > pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At popDown pos=" << pos << " " << node << endl;
- }
-#endif
- scanPos.m_pos--;
- }
- scanPtr.i = scanPtr.p->m_nodeScan;
- } while (scanPtr.i != RNIL);
-}
-
-/*
- * Add entry at existing position. Move entries less than or equal to
- * the old one to the left. Remove and return old min entry.
- *
- * X A
- * ^ v ^
- * A B C D E _ _ => B C D X E _ _
- * 0 1 2 3 4 5 6 0 1 2 3 4 5 6
- *
- * Return list of scans at the removed position 0.
- */
-void
-Dbtux::nodePushDown(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32& scanList)
-{
- Frag& frag = node.m_frag;
- TreeHead& tree = frag.m_tree;
- const unsigned occup = node.getOccup();
- ndbrequire(occup <= tree.m_maxOccup && pos < occup);
- if (node.getNodeScan() != RNIL) {
- // remove scans at 0
- removeScanList(node, 0, scanList);
- // fix other scans
- if (node.getNodeScan() != RNIL)
- nodePushDownScans(node, pos);
- }
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- TreeEnt oldMin = tmpList[0];
- for (unsigned i = 0; i < pos; i++) {
- jam();
- tmpList[i] = tmpList[i + 1];
- }
- tmpList[pos] = ent;
- ent = oldMin;
- entList[0] = entList[occup];
- // fix prefix
- if (true)
- setNodePref(node);
-}
-
-void
-Dbtux::nodePushDownScans(NodeHandle& node, unsigned pos)
-{
- const unsigned occup = node.getOccup();
- ScanOpPtr scanPtr;
- scanPtr.i = node.getNodeScan();
- do {
- jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
- // handled before
- ndbrequire(scanPos.m_pos != 0);
- if (scanPos.m_pos <= pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At pushDown pos=" << pos << " " << node << endl;
- }
-#endif
- scanPos.m_pos--;
- }
- scanPtr.i = scanPtr.p->m_nodeScan;
- } while (scanPtr.i != RNIL);
-}
-
-/*
- * Remove and return entry at position. Move entries less than the
- * removed one to the right. Replace min entry by the input entry.
- * This is the opposite of nodePushDown.
- *
- * X D
- * v ^ ^
- * A B C D E _ _ => X A B C E _ _
- * 0 1 2 3 4 5 6 0 1 2 3 4 5 6
- *
- * Move scans at removed entry and add scans at the new entry.
- */
-void
-Dbtux::nodePopUp(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32 scanList)
-{
- Frag& frag = node.m_frag;
- TreeHead& tree = frag.m_tree;
- const unsigned occup = node.getOccup();
- ndbrequire(occup <= tree.m_maxOccup && pos < occup);
- if (node.getNodeScan() != RNIL) {
- // move scans whose entry disappears
- moveScanList(node, pos);
- // fix other scans
- if (node.getNodeScan() != RNIL)
- nodePopUpScans(node, pos);
- }
- // fix node
- TreeEnt* const entList = tree.getEntList(node.m_node);
- entList[occup] = entList[0];
- TreeEnt* const tmpList = entList + 1;
- TreeEnt newMin = ent;
- ent = tmpList[pos];
- for (unsigned i = pos; i > 0; i--) {
- jam();
- tmpList[i] = tmpList[i - 1];
- }
- tmpList[0] = newMin;
- entList[0] = entList[occup];
- // add scans
- if (scanList != RNIL)
- addScanList(node, 0, scanList);
- // fix prefix
- if (true)
- setNodePref(node);
-}
-
-void
-Dbtux::nodePopUpScans(NodeHandle& node, unsigned pos)
-{
- const unsigned occup = node.getOccup();
- ScanOpPtr scanPtr;
- scanPtr.i = node.getNodeScan();
- do {
- jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc && scanPos.m_pos < occup);
- ndbrequire(scanPos.m_pos != pos);
- if (scanPos.m_pos < pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Fix scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At popUp pos=" << pos << " " << node << endl;
- }
-#endif
- scanPos.m_pos++;
- }
- scanPtr.i = scanPtr.p->m_nodeScan;
- } while (scanPtr.i != RNIL);
-}
-
-/*
- * Move number of entries from another node to this node before the min
- * (i=0) or after the max (i=1). Expensive but not often used.
- */
-void
-Dbtux::nodeSlide(NodeHandle& dstNode, NodeHandle& srcNode, unsigned cnt, unsigned i)
-{
- ndbrequire(i <= 1);
- while (cnt != 0) {
- TreeEnt ent;
- Uint32 scanList = RNIL;
- nodePopDown(srcNode, i == 0 ? srcNode.getOccup() - 1 : 0, ent, &scanList);
- nodePushUp(dstNode, i == 0 ? 0 : dstNode.getOccup(), ent, scanList);
- cnt--;
- }
-}
-
-// scans linked to node
-
-
-/*
- * Add list of scans to node at given position.
- */
-void
-Dbtux::addScanList(NodeHandle& node, unsigned pos, Uint32 scanList)
-{
- ScanOpPtr scanPtr;
- scanPtr.i = scanList;
- do {
- jam();
- c_scanOpPool.getPtr(scanPtr);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Add scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "To pos=" << pos << " " << node << endl;
- }
-#endif
- const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
- scanPtr.p->m_nodeScan = RNIL;
- linkScan(node, scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- // set position but leave direction alone
- scanPos.m_loc = node.m_loc;
- scanPos.m_pos = pos;
- scanPtr.i = nextPtrI;
- } while (scanPtr.i != RNIL);
-}
-
-/*
- * Remove list of scans from node at given position. The return
- * location must point to existing list (in fact RNIL always).
- */
-void
-Dbtux::removeScanList(NodeHandle& node, unsigned pos, Uint32& scanList)
-{
- ScanOpPtr scanPtr;
- scanPtr.i = node.getNodeScan();
- do {
- jam();
- c_scanOpPool.getPtr(scanPtr);
- const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
- TreePos& scanPos = scanPtr.p->m_scanPos;
- ndbrequire(scanPos.m_loc == node.m_loc);
- if (scanPos.m_pos == pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Remove scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "Fron pos=" << pos << " " << node << endl;
- }
-#endif
- unlinkScan(node, scanPtr);
- scanPtr.p->m_nodeScan = scanList;
- scanList = scanPtr.i;
- // unset position but leave direction alone
- scanPos.m_loc = NullTupLoc;
- scanPos.m_pos = ZNIL;
- }
- scanPtr.i = nextPtrI;
- } while (scanPtr.i != RNIL);
-}
-
-/*
- * Move list of scans away from entry about to be removed. Uses scan
- * method scanNext().
- */
-void
-Dbtux::moveScanList(NodeHandle& node, unsigned pos)
-{
- ScanOpPtr scanPtr;
- scanPtr.i = node.getNodeScan();
- do {
- jam();
- c_scanOpPool.getPtr(scanPtr);
- TreePos& scanPos = scanPtr.p->m_scanPos;
- const Uint32 nextPtrI = scanPtr.p->m_nodeScan;
- ndbrequire(scanPos.m_loc == node.m_loc);
- if (scanPos.m_pos == pos) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Move scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "At pos=" << pos << " " << node << endl;
- }
-#endif
- scanNext(scanPtr, true);
- ndbrequire(! (scanPos.m_loc == node.m_loc && scanPos.m_pos == pos));
- }
- scanPtr.i = nextPtrI;
- } while (scanPtr.i != RNIL);
-}
-
-/*
- * Link scan to the list under the node. The list is single-linked and
- * ordering does not matter.
- */
-void
-Dbtux::linkScan(NodeHandle& node, ScanOpPtr scanPtr)
-{
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Link scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "To node " << node << endl;
- }
-#endif
- ndbrequire(! islinkScan(node, scanPtr) && scanPtr.p->m_nodeScan == RNIL);
- scanPtr.p->m_nodeScan = node.getNodeScan();
- node.setNodeScan(scanPtr.i);
-}
-
-/*
- * Unlink a scan from the list under the node.
- */
-void
-Dbtux::unlinkScan(NodeHandle& node, ScanOpPtr scanPtr)
-{
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Unlink scan " << scanPtr.i << " " << *scanPtr.p << endl;
- debugOut << "From node " << node << endl;
- }
-#endif
- ScanOpPtr currPtr;
- currPtr.i = node.getNodeScan();
- ScanOpPtr prevPtr;
- prevPtr.i = RNIL;
- while (true) {
- jam();
- c_scanOpPool.getPtr(currPtr);
- Uint32 nextPtrI = currPtr.p->m_nodeScan;
- if (currPtr.i == scanPtr.i) {
- jam();
- if (prevPtr.i == RNIL) {
- node.setNodeScan(nextPtrI);
- } else {
- jam();
- prevPtr.p->m_nodeScan = nextPtrI;
- }
- scanPtr.p->m_nodeScan = RNIL;
- // check for duplicates
- ndbrequire(! islinkScan(node, scanPtr));
- return;
- }
- prevPtr = currPtr;
- currPtr.i = nextPtrI;
- }
-}
-
-/*
- * Check if a scan is linked to this node. Only for ndbrequire.
- */
-bool
-Dbtux::islinkScan(NodeHandle& node, ScanOpPtr scanPtr)
-{
- ScanOpPtr currPtr;
- currPtr.i = node.getNodeScan();
- while (currPtr.i != RNIL) {
- jam();
- c_scanOpPool.getPtr(currPtr);
- if (currPtr.i == scanPtr.i) {
- jam();
- return true;
- }
- currPtr.i = currPtr.p->m_nodeScan;
- }
- return false;
-}
-
-void
-Dbtux::NodeHandle::progError(int line, int cause, const char* file)
-{
- ErrorReporter::handleAssert("Dbtux::NodeHandle: assert failed", file, line);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
deleted file mode 100644
index 0b910eff341..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ /dev/null
@@ -1,1123 +0,0 @@
-/* Copyright (c) 2003-2006, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_SCAN_CPP
-#include "Dbtux.hpp"
-#include <my_sys.h>
-
-void
-Dbtux::execACC_SCANREQ(Signal* signal)
-{
- jamEntry();
- const AccScanReq reqCopy = *(const AccScanReq*)signal->getDataPtr();
- const AccScanReq* const req = &reqCopy;
- ScanOpPtr scanPtr;
- scanPtr.i = RNIL;
- do {
- // get the index
- IndexPtr indexPtr;
- c_indexPool.getPtr(indexPtr, req->tableId);
- // get the fragment
- FragPtr fragPtr;
- fragPtr.i = RNIL;
- for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) {
- jam();
- if (indexPtr.p->m_fragId[i] == req->fragmentNo) {
- jam();
- c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
- break;
- }
- }
- ndbrequire(fragPtr.i != RNIL);
- Frag& frag = *fragPtr.p;
- // must be normal DIH/TC fragment
- TreeHead& tree = frag.m_tree;
- // check for empty fragment
- if (tree.m_root == NullTupLoc) {
- jam();
- AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend();
- conf->scanPtr = req->senderData;
- conf->accPtr = RNIL;
- conf->flag = AccScanConf::ZEMPTY_FRAGMENT;
- sendSignal(req->senderRef, GSN_ACC_SCANCONF,
- signal, AccScanConf::SignalLength, JBB);
- return;
- }
- // seize from pool and link to per-fragment list
- if (! frag.m_scanList.seize(scanPtr)) {
- jam();
- break;
- }
- new (scanPtr.p) ScanOp(c_scanBoundPool);
- scanPtr.p->m_state = ScanOp::First;
- scanPtr.p->m_userPtr = req->senderData;
- scanPtr.p->m_userRef = req->senderRef;
- scanPtr.p->m_tableId = indexPtr.p->m_tableId;
- scanPtr.p->m_indexId = indexPtr.i;
- scanPtr.p->m_fragId = fragPtr.p->m_fragId;
- scanPtr.p->m_fragPtrI = fragPtr.i;
- scanPtr.p->m_transId1 = req->transId1;
- scanPtr.p->m_transId2 = req->transId2;
- 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_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;
- 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);
-}
-
-/*
- * Receive bounds for scan in single direct call. The bounds can arrive
- * in any order. Attribute ids are those of index table.
- *
- * Replace EQ by equivalent LE + GE. Check for conflicting bounds.
- * Check that sets of lower and upper bounds are on initial sequences of
- * keys and that all but possibly last bound is non-strict.
- *
- * Finally save the sets of lower and upper bounds (i.e. start key and
- * end key). Full bound type 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();
- // get records
- TuxBoundInfo* const sig = (TuxBoundInfo*)signal->getDataPtrSend();
- const TuxBoundInfo* const req = (const TuxBoundInfo*)sig;
- ScanOp& scan = *c_scanOpPool.getPtr(req->tuxScanPtrI);
- 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 };
- // 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];
- const AttributeHeader* ah = (const AttributeHeader*)&data[offset + 1];
- const Uint32 attrId = ah->getAttributeId();
- const Uint32 dataSize = ah->getDataSize();
- 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 uchar* srcPtr = (const uchar*)&data[offset + 2];
- const DescAttr& descAttr = descEnt.m_descAttr[attrId];
- Uint32 typeId = descAttr.m_typeId;
- Uint32 maxBytes = AttributeDescriptor::getSizeInBytes(descAttr.m_attrDesc);
- Uint32 lb, len;
- bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, maxBytes, lb, len);
- if (! ok) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidCharFormat;
- return;
- }
- Uint32 srcBytes = lb + len;
- 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];
- if (descAttr.m_charset == 0) {
- memcpy(dstPtr, srcPtr, srcWords << 2);
- dstWords = srcWords;
- } else {
- jam();
- 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 * (maxBytes - 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)
- continue;
- // EQ -> LE, GE
- const unsigned type2 = (type & 0x1) | luBit;
- // fill in any gap
- while (maxAttrId[j] <= attrId) {
- jam();
- BoundInfo& b = boundInfo[j][maxAttrId[j]];
- maxAttrId[j]++;
- b.type2 = -1;
- }
- BoundInfo& b = boundInfo[j][attrId];
- 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
- 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();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
- return;
- }
- for (unsigned j = 0; j <= 1; j++) {
- // save lower/upper bound in index attribute id order
- for (unsigned i = 0; i < maxAttrId[j]; i++) {
- jam();
- const BoundInfo& b = boundInfo[j][i];
- // check for gap or strict bound before last
- if (b.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(&xfrmData[b.offset], b.size);
- if (! ok) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::OutOfBuffers;
- return;
- }
- }
- scan.m_boundCnt[j] = maxAttrId[j];
- }
- // no error
- sig->errorCode = 0;
-}
-
-void
-Dbtux::execNEXT_SCANREQ(Signal* signal)
-{
- jamEntry();
- const NextScanReq reqCopy = *(const NextScanReq*)signal->getDataPtr();
- const NextScanReq* const req = &reqCopy;
- ScanOpPtr scanPtr;
- scanPtr.i = req->accPtr;
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "NEXT_SCANREQ scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- // handle unlock previous and close scan
- switch (req->scanFlag) {
- case NextScanReq::ZSCAN_NEXT:
- jam();
- break;
- case NextScanReq::ZSCAN_NEXT_COMMIT:
- jam();
- case NextScanReq::ZSCAN_COMMIT:
- jam();
- if (! scan.m_readCommitted) {
- jam();
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Unlock;
- lockReq->accOpPtr = req->accOperationPtr;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- removeAccLockOp(scanPtr, req->accOperationPtr);
- }
- if (req->scanFlag == 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();
- // unlink from tree node first to avoid state changes
- if (scan.m_scanPos.m_loc != NullTupLoc) {
- jam();
- const TupLoc loc = scan.m_scanPos.m_loc;
- NodeHandle node(frag);
- selectNode(node, loc);
- unlinkScan(node, scanPtr);
- scan.m_scanPos.m_loc = NullTupLoc;
- }
- if (scan.m_lockwait) {
- jam();
- ndbrequire(scan.m_accLockOp != RNIL);
- // use ACC_ABORTCONF to flush out any reply in job buffer
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::AbortWithConf;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal,
- AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_state = ScanOp::Aborting;
- return;
- }
- if (scan.m_state == ScanOp::Locked) {
- jam();
- ndbrequire(scan.m_accLockOp != RNIL);
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal,
- AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOp = RNIL;
- }
- scan.m_state = ScanOp::Aborting;
- 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(DBTUX, GSN_ACC_CHECK_SCAN, signal, AccCheckScan::SignalLength);
- jamEntry();
-}
-
-void
-Dbtux::execACC_CHECK_SCAN(Signal* signal)
-{
- jamEntry();
- const AccCheckScan reqCopy = *(const AccCheckScan*)signal->getDataPtr();
- const AccCheckScan* const req = &reqCopy;
- ScanOpPtr scanPtr;
- scanPtr.i = req->accPtr;
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "ACC_CHECK_SCAN scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- 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; // stop
- }
- if (scan.m_lockwait) {
- jam();
- // LQH asks if we are waiting for lock and we tell it to ask again
- const TreeEnt ent = scan.m_scanEnt;
- NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
- conf->scanPtr = scan.m_userPtr;
- conf->accOperationPtr = RNIL; // no tuple returned
- conf->fragId = frag.m_fragId;
- unsigned signalLength = 3;
- // if TC has ordered scan close, it will be detected here
- sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
- signal, signalLength, JBB);
- return; // stop
- }
- if (scan.m_state == ScanOp::First) {
- jam();
- // search is done only once in single range scan
- scanFirst(scanPtr);
- }
- if (scan.m_state == ScanOp::Current ||
- scan.m_state == ScanOp::Next) {
- jam();
- // look for next
- scanFind(scanPtr);
- }
- // for reading tuple key in Found or Locked state
- Data pkData = c_dataBuffer;
- unsigned pkSize = 0; // indicates not yet done
- if (scan.m_state == ScanOp::Found) {
- // found an entry to return
- jam();
- ndbrequire(scan.m_accLockOp == RNIL);
- if (! scan.m_readCommitted) {
- jam();
- const TreeEnt ent = scan.m_scanEnt;
- // read tuple key
- readTablePk(frag, ent, pkData, pkSize);
- // get read lock or exclusive lock
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo =
- scan.m_lockMode == 0 ? AccLockReq::LockShared : AccLockReq::LockExclusive;
- lockReq->accOpPtr = RNIL;
- lockReq->userPtr = scanPtr.i;
- lockReq->userRef = reference();
- lockReq->tableId = scan.m_tableId;
- lockReq->fragId = frag.m_fragId;
- lockReq->fragPtrI = frag.m_accTableFragPtrI;
- const Uint32* const buf32 = static_cast<Uint32*>(pkData);
- const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32);
- lockReq->hashValue = md5_hash(buf64, pkSize);
- lockReq->tupAddr = getTupAddr(frag, ent);
- lockReq->transId1 = scan.m_transId1;
- lockReq->transId2 = scan.m_transId2;
- // execute
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::LockSignalLength);
- jamEntry();
- switch (lockReq->returnCode) {
- case AccLockReq::Success:
- jam();
- scan.m_state = ScanOp::Locked;
- scan.m_accLockOp = lockReq->accOpPtr;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "Lock immediate scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- break;
- case AccLockReq::IsBlocked:
- jam();
- // normal lock wait
- scan.m_state = ScanOp::Blocked;
- scan.m_lockwait = true;
- scan.m_accLockOp = lockReq->accOpPtr;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "Lock wait scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- // LQH will wake us up
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = true;
- EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
- jamEntry();
- return; // stop
- break;
- case AccLockReq::Refused:
- jam();
- // we cannot see deleted tuple (assert only)
- ndbassert(false);
- // skip it
- scan.m_state = ScanOp::Next;
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = true;
- EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
- jamEntry();
- return; // stop
- break;
- case AccLockReq::NoFreeOp:
- jam();
- // max ops should depend on max scans (assert only)
- ndbassert(false);
- // stay in Found state
- scan.m_state = ScanOp::Found;
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = true;
- EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
- jamEntry();
- return; // stop
- break;
- default:
- ndbrequire(false);
- break;
- }
- } else {
- scan.m_state = ScanOp::Locked;
- }
- }
- if (scan.m_state == ScanOp::Locked) {
- // we have lock or do not need one
- jam();
- // read keys if not already done (uses signal)
- const TreeEnt ent = scan.m_scanEnt;
- // conf signal
- NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
- conf->scanPtr = scan.m_userPtr;
- // the lock is passed to LQH
- Uint32 accLockOp = scan.m_accLockOp;
- if (accLockOp != RNIL) {
- scan.m_accLockOp = RNIL;
- // remember it until LQH unlocks it
- addAccLockOp(scanPtr, accLockOp);
- } else {
- ndbrequire(scan.m_readCommitted);
- // operation RNIL in LQH would signal no tuple returned
- accLockOp = (Uint32)-1;
- }
- conf->accOperationPtr = accLockOp;
- conf->fragId = frag.m_fragId;
- conf->localKey[0] = getTupAddr(frag, ent);
- conf->localKey[1] = 0;
- conf->localKeyLength = 1;
- unsigned signalLength = 6;
- // add key info
- if (! scan.m_readCommitted) {
- sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
- signal, signalLength, JBB);
- } else {
- Uint32 blockNo = refToBlock(scan.m_userRef);
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
- }
- // next time look for next entry
- scan.m_state = ScanOp::Next;
- return;
- }
- // XXX in ACC this is checked before req->checkLcpStop
- 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);
-}
-
-/*
- * Lock succeeded (after delay) in ACC. If the lock is for current
- * entry, set state to Locked. If the lock is for an entry we were
- * moved away from, simply unlock it. Finally, if we are closing the
- * scan, do nothing since we have already sent an abort request.
- */
-void
-Dbtux::execACCKEYCONF(Signal* signal)
-{
- jamEntry();
- ScanOpPtr scanPtr;
- scanPtr.i = signal->theData[0];
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "Lock obtained scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- ndbrequire(scan.m_lockwait && scan.m_accLockOp != RNIL);
- scan.m_lockwait = false;
- if (scan.m_state == ScanOp::Blocked) {
- // the lock wait was for current entry
- jam();
- scan.m_state = ScanOp::Locked;
- // LQH has the ball
- return;
- }
- if (scan.m_state != ScanOp::Aborting) {
- // we were moved, release lock
- jam();
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOp = RNIL;
- // LQH has the ball
- return;
- }
- // lose the lock
- scan.m_accLockOp = RNIL;
- // continue at ACC_ABORTCONF
-}
-
-/*
- * Lock failed (after delay) in ACC. Probably means somebody ahead of
- * us in lock queue deleted the tuple.
- */
-void
-Dbtux::execACCKEYREF(Signal* signal)
-{
- jamEntry();
- ScanOpPtr scanPtr;
- scanPtr.i = signal->theData[0];
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "Lock refused scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- ndbrequire(scan.m_lockwait && scan.m_accLockOp != RNIL);
- scan.m_lockwait = false;
- if (scan.m_state != ScanOp::Aborting) {
- jam();
- // release the operation
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = scan.m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOp = RNIL;
- // scan position should already have been moved (assert only)
- if (scan.m_state == ScanOp::Blocked) {
- jam();
- ndbassert(false);
- scan.m_state = ScanOp::Next;
- }
- // LQH has the ball
- return;
- }
- // lose the lock
- scan.m_accLockOp = RNIL;
- // continue at ACC_ABORTCONF
-}
-
-/*
- * Received when scan is closing. This signal arrives after any
- * ACCKEYCON or ACCKEYREF which may have been in job buffer.
- */
-void
-Dbtux::execACC_ABORTCONF(Signal* signal)
-{
- jamEntry();
- ScanOpPtr scanPtr;
- scanPtr.i = signal->theData[0];
- c_scanOpPool.getPtr(scanPtr);
- ScanOp& scan = *scanPtr.p;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "ACC_ABORTCONF scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- ndbrequire(scan.m_state == ScanOp::Aborting);
- // most likely we are still in lock wait
- if (scan.m_lockwait) {
- jam();
- scan.m_lockwait = false;
- scan.m_accLockOp = RNIL;
- }
- scanClose(signal, scanPtr);
-}
-
-/*
- * Find start position for single range scan.
- */
-void
-Dbtux::scanFirst(ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Enter first scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- // set up index keys for this operation
- setKeyAttrs(frag);
- // scan direction 0, 1
- const unsigned idir = scan.m_descending;
- unpackBound(*scan.m_bound[idir], c_dataBuffer);
- TreePos treePos;
- searchToScan(frag, c_dataBuffer, scan.m_boundCnt[idir], scan.m_descending, treePos);
- if (treePos.m_loc != NullTupLoc) {
- scan.m_scanPos = treePos;
- // link the scan to node found
- NodeHandle node(frag);
- selectNode(node, treePos.m_loc);
- linkScan(node, scanPtr);
- if (treePos.m_dir == 3) {
- jam();
- // check upper bound
- TreeEnt ent = node.getEnt(treePos.m_pos);
- if (scanCheck(scanPtr, ent))
- scan.m_state = ScanOp::Current;
- else
- scan.m_state = ScanOp::Last;
- } else {
- scan.m_state = ScanOp::Next;
- }
- } else {
- jam();
- scan.m_state = ScanOp::Last;
- }
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Leave first scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
-}
-
-/*
- * Look for entry to return as scan result.
- */
-void
-Dbtux::scanFind(ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Enter find scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- ndbrequire(scan.m_state == ScanOp::Current || scan.m_state == ScanOp::Next);
- while (1) {
- jam();
- if (scan.m_state == ScanOp::Next)
- scanNext(scanPtr, false);
- if (scan.m_state == ScanOp::Current) {
- jam();
- const TreePos pos = scan.m_scanPos;
- NodeHandle node(frag);
- selectNode(node, pos.m_loc);
- const TreeEnt ent = node.getEnt(pos.m_pos);
- if (scanVisible(scanPtr, ent)) {
- jam();
- scan.m_state = ScanOp::Found;
- scan.m_scanEnt = ent;
- break;
- }
- } else {
- jam();
- break;
- }
- scan.m_state = ScanOp::Next;
- }
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Leave find scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
-}
-
-/*
- * 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 (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)
- * 2 - up from root (the scan ends)
- * 3 - left to right within node (at end proceed to right child)
- * 4 - down from parent (proceed to left child)
- *
- * If an entry was found, scan direction is 3. Therefore tree
- * re-organizations need not worry about scan direction.
- *
- * This method is also used to move a scan when its entry is removed
- * (see moveScanList). If the scan is Blocked, we check if it remains
- * Blocked on a different version of the tuple. Otherwise the tuple is
- * lost and state becomes Current.
- */
-void
-Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
-{
- ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
-#ifdef VM_TRACE
- if (debugFlags & (DebugMaint | DebugScan)) {
- debugOut << "Enter next scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- // cannot be moved away from tuple we have locked
- ndbrequire(scan.m_state != ScanOp::Locked);
- // set up index keys for this operation
- setKeyAttrs(frag);
- // scan direction
- const unsigned idir = scan.m_descending; // 0, 1
- const int jdir = 1 - 2 * (int)idir; // 1, -1
- // use copy of position
- TreePos pos = scan.m_scanPos;
- // get and remember original node
- NodeHandle origNode(frag);
- selectNode(origNode, pos.m_loc);
- ndbrequire(islinkScan(origNode, scanPtr));
- // current node in loop
- NodeHandle node = origNode;
- // copy of entry found
- TreeEnt ent;
- while (true) {
- jam();
-#ifdef VM_TRACE
- if (debugFlags & (DebugMaint | DebugScan)) {
- debugOut << "Current scan " << scanPtr.i << " pos " << pos << " node " << node << endl;
- }
-#endif
- if (pos.m_dir == 2) {
- // coming up from root ends the scan
- jam();
- pos.m_loc = NullTupLoc;
- break;
- }
- if (node.m_loc != pos.m_loc) {
- jam();
- selectNode(node, pos.m_loc);
- }
- if (pos.m_dir == 4) {
- // coming down from parent proceed to left child
- jam();
- TupLoc loc = node.getLink(idir);
- if (loc != NullTupLoc) {
- jam();
- pos.m_loc = loc;
- pos.m_dir = 4; // unchanged
- continue;
- }
- // pretend we came from left child
- 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 == idir) {
- // coming up from left child scan current node
- jam();
- pos.m_pos = idir == 0 ? (Uint16)-1 : occup;
- pos.m_dir = 3;
- }
- if (pos.m_dir == 3) {
- // before or within node
- jam();
- // advance position - becomes ZNIL (> occup) if 0 and descending
- pos.m_pos += jdir;
- if (pos.m_pos < occup) {
- jam();
- pos.m_dir = 3; // unchanged
- ent = node.getEnt(pos.m_pos);
- if (! scanCheck(scanPtr, ent)) {
- jam();
- pos.m_loc = NullTupLoc;
- }
- break;
- }
- // after node proceed to right child
- TupLoc loc = node.getLink(1 - idir);
- if (loc != NullTupLoc) {
- jam();
- pos.m_loc = loc;
- pos.m_dir = 4;
- continue;
- }
- // pretend we came from right child
- pos.m_dir = 1 - idir;
- }
- if (pos.m_dir == 1 - idir) {
- // coming up from right child proceed to parent
- jam();
- pos.m_loc = node.getLink(2);
- pos.m_dir = node.getSide();
- continue;
- }
- ndbrequire(false);
- }
- // copy back position
- scan.m_scanPos = pos;
- // relink
- if (pos.m_loc != NullTupLoc) {
- ndbrequire(pos.m_dir == 3);
- ndbrequire(pos.m_loc == node.m_loc);
- if (origNode.m_loc != node.m_loc) {
- jam();
- unlinkScan(origNode, scanPtr);
- linkScan(node, scanPtr);
- }
- if (scan.m_state != ScanOp::Blocked) {
- scan.m_state = ScanOp::Current;
- } else {
- jam();
- ndbrequire(fromMaintReq);
- TreeEnt& scanEnt = scan.m_scanEnt;
- ndbrequire(scanEnt.m_tupLoc != NullTupLoc);
- if (scanEnt.eqtuple(ent)) {
- // remains blocked on another version
- scanEnt = ent;
- } else {
- jam();
- scanEnt.m_tupLoc = NullTupLoc;
- scan.m_state = ScanOp::Current;
- }
- }
- } else {
- jam();
- unlinkScan(origNode, scanPtr);
- scan.m_state = ScanOp::Last;
- }
-#ifdef VM_TRACE
- if (debugFlags & (DebugMaint | DebugScan)) {
- debugOut << "Leave next scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
-}
-
-/*
- * Check end key. Return true if scan is still within range.
- */
-bool
-Dbtux::scanCheck(ScanOpPtr scanPtr, TreeEnt ent)
-{
- ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
- const unsigned idir = scan.m_descending;
- const int jdir = 1 - 2 * (int)idir;
- unpackBound(*scan.m_bound[1 - idir], c_dataBuffer);
- unsigned boundCnt = scan.m_boundCnt[1 - idir];
- readKeyAttrs(frag, ent, 0, c_entryKey);
- int ret = cmpScanBound(frag, 1 - idir, c_dataBuffer, boundCnt, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- if (jdir * ret > 0)
- return true;
- // hit upper bound of single range scan
- return false;
-}
-
-/*
- * Check if an entry is visible to the scan.
- *
- * There is a special check to never accept same tuple twice in a row.
- * This is faster than asking TUP. It also fixes some special cases
- * which are not analyzed or handled yet.
- */
-bool
-Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent)
-{
- const ScanOp& scan = *scanPtr.p;
- const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
- Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
- Uint32 pageId = ent.m_tupLoc.getPageId();
- Uint32 pageOffset = ent.m_tupLoc.getPageOffset();
- Uint32 tupVersion = ent.m_tupVersion;
- // check for same tuple twice in row
- if (scan.m_scanEnt.m_tupLoc == ent.m_tupLoc)
- {
- jam();
- return false;
- }
- Uint32 transId1 = scan.m_transId1;
- Uint32 transId2 = scan.m_transId2;
- bool dirty = scan.m_readCommitted;
- Uint32 savePointId = scan.m_savePointId;
- bool ret = c_tup->tuxQueryTh(tableFragPtrI, pageId, pageOffset, tupVersion, transId1, transId2, dirty, savePointId);
- jamEntry();
- return ret;
-}
-
-/*
- * Finish closing of scan and send conf. Any lock wait has been done
- * already.
- */
-void
-Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
- ndbrequire(! scan.m_lockwait && scan.m_accLockOp == RNIL);
- // unlock all not unlocked by LQH
- if (! scan.m_accLockOps.isEmpty()) {
- jam();
- abortAccLockOps(signal, scanPtr);
- }
- // send conf
- 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
-Dbtux::abortAccLockOps(Signal* signal, ScanOpPtr scanPtr)
-{
- ScanOp& scan = *scanPtr.p;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "Abort locks in scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
- ScanLockPtr lockPtr;
- while (list.first(lockPtr)) {
- jam();
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = lockPtr.p->m_accLockOp;
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- list.release(lockPtr);
- }
-}
-
-void
-Dbtux::addAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp)
-{
- ScanOp& scan = *scanPtr.p;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "Add lock " << hex << accLockOp << dec
- << " to scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
- ScanLockPtr lockPtr;
-#ifdef VM_TRACE
- list.first(lockPtr);
- while (lockPtr.i != RNIL) {
- ndbrequire(lockPtr.p->m_accLockOp != accLockOp);
- list.next(lockPtr);
- }
-#endif
- bool ok = list.seize(lockPtr);
- ndbrequire(ok);
- ndbrequire(accLockOp != RNIL);
- lockPtr.p->m_accLockOp = accLockOp;
-}
-
-void
-Dbtux::removeAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp)
-{
- ScanOp& scan = *scanPtr.p;
-#ifdef VM_TRACE
- if (debugFlags & (DebugScan | DebugLock)) {
- debugOut << "Remove lock " << hex << accLockOp << dec
- << " from scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
- LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
- ScanLockPtr lockPtr;
- list.first(lockPtr);
- while (lockPtr.i != RNIL) {
- if (lockPtr.p->m_accLockOp == accLockOp) {
- jam();
- break;
- }
- list.next(lockPtr);
- }
- ndbrequire(lockPtr.i != RNIL);
- list.release(lockPtr);
-}
-
-/*
- * Release allocated records.
- */
-void
-Dbtux::releaseScanOp(ScanOpPtr& scanPtr)
-{
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Release scan " << scanPtr.i << " " << *scanPtr.p << endl;
- }
-#endif
- Frag& frag = *c_fragPool.getPtr(scanPtr.p->m_fragPtrI);
- scanPtr.p->m_boundMin.release();
- scanPtr.p->m_boundMax.release();
- // unlink from per-fragment list and release from pool
- frag.m_scanList.release(scanPtr);
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
deleted file mode 100644
index 9e84f61ab70..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_SEARCH_CPP
-#include "Dbtux.hpp"
-
-/*
- * Search for entry to add.
- *
- * Similar to searchToRemove (see below).
- */
-bool
-Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
-{
- const TreeHead& tree = frag.m_tree;
- const unsigned numAttrs = frag.m_numAttrs;
- NodeHandle currNode(frag);
- currNode.m_loc = tree.m_root;
- if (currNode.m_loc == NullTupLoc) {
- // empty tree
- jam();
- return true;
- }
- NodeHandle glbNode(frag); // potential g.l.b of final node
- /*
- * In order to not (yet) change old behaviour, a position between
- * 2 nodes returns the one at the bottom of the tree.
- */
- NodeHandle bottomNode(frag);
- while (true) {
- jam();
- selectNode(currNode, currNode.m_loc);
- int ret;
- // compare prefix
- unsigned start = 0;
- ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
- if (ret == NdbSqlUtil::CmpUnknown) {
- jam();
- // read and compare remaining attributes
- ndbrequire(start < numAttrs);
- readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
- ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- }
- if (ret == 0) {
- jam();
- // keys are equal, compare entry values
- ret = searchEnt.cmp(currNode.getMinMax(0));
- }
- if (ret < 0) {
- jam();
- const TupLoc loc = currNode.getLink(0);
- if (loc != NullTupLoc) {
- jam();
- // continue to left subtree
- currNode.m_loc = loc;
- continue;
- }
- if (! glbNode.isNull()) {
- jam();
- // move up to the g.l.b but remember the bottom node
- bottomNode = currNode;
- currNode = glbNode;
- }
- } else if (ret > 0) {
- jam();
- const TupLoc loc = currNode.getLink(1);
- if (loc != NullTupLoc) {
- jam();
- // save potential g.l.b
- glbNode = currNode;
- // continue to right subtree
- currNode.m_loc = loc;
- continue;
- }
- } else {
- jam();
- treePos.m_loc = currNode.m_loc;
- treePos.m_pos = 0;
- // entry found - error
- return false;
- }
- break;
- }
- // anticipate
- treePos.m_loc = currNode.m_loc;
- // binary search
- int lo = -1;
- int hi = currNode.getOccup();
- int ret;
- while (1) {
- jam();
- // hi - lo > 1 implies lo < j < hi
- int j = (hi + lo) / 2;
- // read and compare attributes
- unsigned start = 0;
- readKeyAttrs(frag, currNode.getEnt(j), start, c_entryKey);
- ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- if (ret == 0) {
- jam();
- // keys are equal, compare entry values
- ret = searchEnt.cmp(currNode.getEnt(j));
- }
- if (ret < 0)
- hi = j;
- else if (ret > 0)
- lo = j;
- else {
- treePos.m_pos = j;
- // entry found - error
- return false;
- }
- if (hi - lo == 1)
- break;
- }
- if (ret < 0) {
- jam();
- treePos.m_pos = hi;
- return true;
- }
- if ((uint) hi < currNode.getOccup()) {
- jam();
- treePos.m_pos = hi;
- return true;
- }
- if (bottomNode.isNull()) {
- jam();
- treePos.m_pos = hi;
- return true;
- }
- jam();
- // backwards compatible for now
- treePos.m_loc = bottomNode.m_loc;
- treePos.m_pos = 0;
- return true;
-}
-
-/*
- * Search for entry to remove.
- *
- * Compares search key to each node min. A move to right subtree can
- * overshoot target node. The last such node is saved. The final node
- * is a semi-leaf or leaf. If search key is less than final node min
- * then the saved node is the g.l.b of the final node and we move back
- * to it.
- */
-bool
-Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
-{
- const TreeHead& tree = frag.m_tree;
- const unsigned numAttrs = frag.m_numAttrs;
- NodeHandle currNode(frag);
- currNode.m_loc = tree.m_root;
- if (currNode.m_loc == NullTupLoc) {
- // empty tree - failed
- jam();
- return false;
- }
- NodeHandle glbNode(frag); // potential g.l.b of final node
- while (true) {
- jam();
- selectNode(currNode, currNode.m_loc);
- int ret;
- // compare prefix
- unsigned start = 0;
- ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
- if (ret == NdbSqlUtil::CmpUnknown) {
- jam();
- // read and compare remaining attributes
- ndbrequire(start < numAttrs);
- readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
- ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- }
- if (ret == 0) {
- jam();
- // keys are equal, compare entry values
- ret = searchEnt.cmp(currNode.getMinMax(0));
- }
- if (ret < 0) {
- jam();
- const TupLoc loc = currNode.getLink(0);
- if (loc != NullTupLoc) {
- jam();
- // continue to left subtree
- currNode.m_loc = loc;
- continue;
- }
- if (! glbNode.isNull()) {
- jam();
- // move up to the g.l.b
- currNode = glbNode;
- }
- } else if (ret > 0) {
- jam();
- const TupLoc loc = currNode.getLink(1);
- if (loc != NullTupLoc) {
- jam();
- // save potential g.l.b
- glbNode = currNode;
- // continue to right subtree
- currNode.m_loc = loc;
- continue;
- }
- } else {
- jam();
- treePos.m_loc = currNode.m_loc;
- treePos.m_pos = 0;
- return true;
- }
- break;
- }
- // anticipate
- treePos.m_loc = currNode.m_loc;
- // pos 0 was handled above
- for (unsigned j = 1, occup = currNode.getOccup(); j < occup; j++) {
- jam();
- // compare only the entry
- if (searchEnt.eq(currNode.getEnt(j))) {
- jam();
- treePos.m_pos = j;
- return true;
- }
- }
- treePos.m_pos = currNode.getOccup();
- // not found - failed
- return false;
-}
-
-/*
- * Search for scan start position.
- *
- * 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, bool descending, TreePos& treePos)
-{
- const TreeHead& tree = frag.m_tree;
- 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);
- while (true) {
- jam();
- selectNode(currNode, currNode.m_loc);
- int ret;
- // compare prefix
- ret = cmpScanBound(frag, 0, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize);
- if (ret == NdbSqlUtil::CmpUnknown) {
- jam();
- // read and compare all attributes
- readKeyAttrs(frag, currNode.getMinMax(0), 0, c_entryKey);
- ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- }
- if (ret < 0) {
- // 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 {
- // start scanning this node
- treePos.m_loc = currNode.m_loc;
- treePos.m_pos = 0;
- treePos.m_dir = 3;
- return;
- }
- } else {
- // 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;
- }
- }
- 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, 0, boundInfo, boundCount, c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- if (ret < 0) {
- // found first entry satisfying the bound
- treePos.m_loc = currNode.m_loc;
- treePos.m_pos = j;
- 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_dir = 3;
- return;
- }
- // start scanning upwards (pretend we came from right child)
- 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);
- 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 {
- // 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;
- }
- }
- 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/storage/ndb/src/kernel/blocks/dbtux/DbtuxStat.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxStat.cpp
deleted file mode 100644
index 143996bf7ff..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxStat.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_STAT_CPP
-#include "Dbtux.hpp"
-
-void
-Dbtux::execREAD_PSEUDO_REQ(Signal* signal)
-{
- jamEntry();
- ScanOpPtr scanPtr;
- scanPtr.i = signal->theData[0];
- c_scanOpPool.getPtr(scanPtr);
- if (signal->theData[1] == AttributeHeader::RECORDS_IN_RANGE) {
- jam();
- statRecordsInRange(scanPtr, &signal->theData[0]);
- } else {
- ndbassert(false);
- }
-}
-
-/*
- * Estimate entries in range. Scan is at first entry. Search for last
- * entry i.e. start of descending scan. Use the 2 positions to estimate
- * entries before and after the range. Finally get entries in range by
- * subtracting from total. Errors come from imperfectly balanced tree
- * and from uncommitted entries which differ only in tuple version.
- *
- * Returns 4 Uint32 values: 0) total entries 1) in range 2) before range
- * 3) after range. 1-3) are estimates and need not add up to 0).
- */
-void
-Dbtux::statRecordsInRange(ScanOpPtr scanPtr, Uint32* out)
-{
- ScanOp& scan = *scanPtr.p;
- Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
- TreeHead& tree = frag.m_tree;
- // get first and last position
- TreePos pos1 = scan.m_scanPos;
- TreePos pos2;
- { // as in scanFirst()
- setKeyAttrs(frag);
- const unsigned idir = 1;
- const ScanBound& bound = *scan.m_bound[idir];
- ScanBoundIterator iter;
- bound.first(iter);
- for (unsigned j = 0; j < bound.getSize(); j++) {
- jam();
- c_dataBuffer[j] = *iter.data;
- bound.next(iter);
- }
- searchToScan(frag, c_dataBuffer, scan.m_boundCnt[idir], true, pos2);
- // committed read (same timeslice) and range not empty
- ndbrequire(pos2.m_loc != NullTupLoc);
- }
- out[0] = frag.m_tree.m_entryCount;
- out[2] = getEntriesBeforeOrAfter(frag, pos1, 0);
- out[3] = getEntriesBeforeOrAfter(frag, pos2, 1);
- if (pos1.m_loc == pos2.m_loc) {
- ndbrequire(pos2.m_pos >= pos1.m_pos);
- out[1] = pos2.m_pos - pos1.m_pos + 1;
- } else {
- Uint32 rem = out[2] + out[3];
- if (out[0] > rem) {
- out[1] = out[0] - rem;
- } else {
- // random guess one node apart
- out[1] = tree.m_maxOccup;
- }
- }
-}
-
-/*
- * Estimate number of entries strictly before or after given position.
- * Each branch to right direction wins parent node and the subtree on
- * the other side. Subtree entries is estimated from depth and total
- * entries by assuming that the tree is perfectly balanced.
- */
-Uint32
-Dbtux::getEntriesBeforeOrAfter(Frag& frag, TreePos pos, unsigned idir)
-{
- NodeHandle node(frag);
- selectNode(node, pos.m_loc);
- Uint16 path[MaxTreeDepth + 1];
- unsigned depth = getPathToNode(node, path);
- ndbrequire(depth != 0 && depth <= MaxTreeDepth);
- TreeHead& tree = frag.m_tree;
- Uint32 cnt = 0;
- Uint32 tot = tree.m_entryCount;
- unsigned i = 0;
- // contribution from levels above
- while (i + 1 < depth) {
- unsigned occup2 = (path[i] >> 8);
- unsigned side = (path[i + 1] & 0xFF);
- // subtree of this node has about half the entries
- tot = tot >= occup2 ? (tot - occup2) / 2 : 0;
- // branch to other side wins parent and a subtree
- if (side != idir) {
- cnt += occup2;
- cnt += tot;
- }
- i++;
- }
- // contribution from this node
- unsigned occup = (path[i] >> 8);
- ndbrequire(pos.m_pos < occup);
- if (idir == 0) {
- if (pos.m_pos != 0)
- cnt += pos.m_pos - 1;
- } else {
- cnt += occup - (pos.m_pos + 1);
- }
- // contribution from levels below
- tot = tot >= occup ? (tot - occup) / 2 : 0;
- cnt += tot;
- return cnt;
-}
-
-/*
- * Construct path to given node. Returns depth. Root node has path
- * 2 and depth 1. In general the path is 2{0,1}* where 0,1 is the side
- * (left,right branch). In addition the occupancy of each node is
- * returned in the upper 8 bits.
- */
-unsigned
-Dbtux::getPathToNode(NodeHandle node, Uint16* path)
-{
- TupLoc loc = node.m_loc;
- unsigned i = MaxTreeDepth;
- while (loc != NullTupLoc) {
- jam();
- selectNode(node, loc);
- path[i] = node.getSide() | (node.getOccup() << 8);
- loc = node.getLink(2);
- ndbrequire(i != 0);
- i--;
- }
- unsigned depth = MaxTreeDepth - i;
- unsigned j = 0;
- while (j < depth) {
- path[j] = path[i + 1 + j];
- j++;
- }
- path[j] = 0xFFFF; // catch bug
- return depth;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
deleted file mode 100644
index c130a71b60e..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+++ /dev/null
@@ -1,717 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define DBTUX_TREE_CPP
-#include "Dbtux.hpp"
-
-/*
- * Add entry. Handle the case when there is room for one more. This
- * is the common case given slack in nodes.
- */
-void
-Dbtux::treeAdd(Frag& frag, TreePos treePos, TreeEnt ent)
-{
- TreeHead& tree = frag.m_tree;
- NodeHandle node(frag);
- do {
- if (treePos.m_loc != NullTupLoc) {
- // non-empty tree
- jam();
- selectNode(node, treePos.m_loc);
- unsigned pos = treePos.m_pos;
- if (node.getOccup() < tree.m_maxOccup) {
- // node has room
- jam();
- nodePushUp(node, pos, ent, RNIL);
- break;
- }
- treeAddFull(frag, node, pos, ent);
- break;
- }
- jam();
- insertNode(node);
- nodePushUp(node, 0, ent, RNIL);
- node.setSide(2);
- tree.m_root = node.m_loc;
- break;
- } while (0);
- tree.m_entryCount++;
-}
-
-/*
- * Add entry when node is full. Handle the case when there is g.l.b
- * node in left subtree with room for one more. It will receive the min
- * entry of this node. The min entry could be the entry to add.
- */
-void
-Dbtux::treeAddFull(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent)
-{
- TreeHead& tree = frag.m_tree;
- TupLoc loc = lubNode.getLink(0);
- if (loc != NullTupLoc) {
- // find g.l.b node
- NodeHandle glbNode(frag);
- do {
- jam();
- selectNode(glbNode, loc);
- loc = glbNode.getLink(1);
- } while (loc != NullTupLoc);
- if (glbNode.getOccup() < tree.m_maxOccup) {
- // g.l.b node has room
- jam();
- Uint32 scanList = RNIL;
- if (pos != 0) {
- jam();
- // add the new entry and return min entry
- nodePushDown(lubNode, pos - 1, ent, scanList);
- }
- // g.l.b node receives min entry from l.u.b node
- nodePushUp(glbNode, glbNode.getOccup(), ent, scanList);
- return;
- }
- treeAddNode(frag, lubNode, pos, ent, glbNode, 1);
- return;
- }
- treeAddNode(frag, lubNode, pos, ent, lubNode, 0);
-}
-
-/*
- * Add entry when there is no g.l.b node in left subtree or the g.l.b
- * node is full. We must add a new left or right child node which
- * becomes the new g.l.b node.
- */
-void
-Dbtux::treeAddNode(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent, NodeHandle parentNode, unsigned i)
-{
- NodeHandle glbNode(frag);
- insertNode(glbNode);
- // connect parent and child
- parentNode.setLink(i, glbNode.m_loc);
- glbNode.setLink(2, parentNode.m_loc);
- glbNode.setSide(i);
- Uint32 scanList = RNIL;
- if (pos != 0) {
- jam();
- // add the new entry and return min entry
- nodePushDown(lubNode, pos - 1, ent, scanList);
- }
- // g.l.b node receives min entry from l.u.b node
- nodePushUp(glbNode, 0, ent, scanList);
- // re-balance the tree
- treeAddRebalance(frag, parentNode, i);
-}
-
-/*
- * Re-balance tree after adding a node. The process starts with the
- * parent of the added node.
- */
-void
-Dbtux::treeAddRebalance(Frag& frag, NodeHandle node, unsigned i)
-{
- while (true) {
- // height of subtree i has increased by 1
- int j = (i == 0 ? -1 : +1);
- int b = node.getBalance();
- if (b == 0) {
- // perfectly balanced
- jam();
- node.setBalance(j);
- // height change propagates up
- } else if (b == -j) {
- // height of shorter subtree increased
- jam();
- node.setBalance(0);
- // height of tree did not change - done
- break;
- } else if (b == j) {
- // height of longer subtree increased
- jam();
- NodeHandle childNode(frag);
- selectNode(childNode, node.getLink(i));
- int b2 = childNode.getBalance();
- if (b2 == b) {
- jam();
- treeRotateSingle(frag, node, i);
- } else if (b2 == -b) {
- jam();
- treeRotateDouble(frag, node, i);
- } else {
- // height of subtree increased so it cannot be perfectly balanced
- ndbrequire(false);
- }
- // height of tree did not increase - done
- break;
- } else {
- ndbrequire(false);
- }
- TupLoc parentLoc = node.getLink(2);
- if (parentLoc == NullTupLoc) {
- jam();
- // root node - done
- break;
- }
- i = node.getSide();
- selectNode(node, parentLoc);
- }
-}
-
-/*
- * Remove entry. Optimize for nodes with slack. Handle the case when
- * there is no underflow i.e. occupancy remains at least minOccup. For
- * interior nodes this is a requirement. For others it means that we do
- * not need to consider merge of semi-leaf and leaf.
- */
-void
-Dbtux::treeRemove(Frag& frag, TreePos treePos)
-{
- TreeHead& tree = frag.m_tree;
- unsigned pos = treePos.m_pos;
- NodeHandle node(frag);
- selectNode(node, treePos.m_loc);
- TreeEnt ent;
- do {
- if (node.getOccup() > tree.m_minOccup) {
- // no underflow in any node type
- jam();
- nodePopDown(node, pos, ent, 0);
- break;
- }
- if (node.getChilds() == 2) {
- // underflow in interior node
- jam();
- treeRemoveInner(frag, node, pos);
- break;
- }
- // remove entry in semi/leaf
- nodePopDown(node, pos, ent, 0);
- if (node.getLink(0) != NullTupLoc) {
- jam();
- treeRemoveSemi(frag, node, 0);
- break;
- }
- if (node.getLink(1) != NullTupLoc) {
- jam();
- treeRemoveSemi(frag, node, 1);
- break;
- }
- treeRemoveLeaf(frag, node);
- break;
- } while (0);
- ndbrequire(tree.m_entryCount != 0);
- tree.m_entryCount--;
-}
-
-/*
- * Remove entry when interior node underflows. There is g.l.b node in
- * left subtree to borrow an entry from. The max entry of the g.l.b
- * node becomes the min entry of this node.
- */
-void
-Dbtux::treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos)
-{
- TreeEnt ent;
- // find g.l.b node
- NodeHandle glbNode(frag);
- TupLoc loc = lubNode.getLink(0);
- do {
- jam();
- selectNode(glbNode, loc);
- loc = glbNode.getLink(1);
- } while (loc != NullTupLoc);
- // borrow max entry from semi/leaf
- Uint32 scanList = RNIL;
- nodePopDown(glbNode, glbNode.getOccup() - 1, ent, &scanList);
- // 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();
- treeRemoveSemi(frag, glbNode, 0);
- return;
- }
- treeRemoveLeaf(frag, glbNode);
-}
-
-/*
- * Handle semi-leaf after removing an entry. Move entries from leaf to
- * semi-leaf to bring semi-leaf occupancy above minOccup, if possible.
- * The leaf may become empty.
- */
-void
-Dbtux::treeRemoveSemi(Frag& frag, NodeHandle semiNode, unsigned i)
-{
- TreeHead& tree = frag.m_tree;
- ndbrequire(semiNode.getChilds() < 2);
- TupLoc leafLoc = semiNode.getLink(i);
- NodeHandle leafNode(frag);
- selectNode(leafNode, leafLoc);
- if (semiNode.getOccup() < tree.m_minOccup) {
- jam();
- unsigned cnt = min(leafNode.getOccup(), tree.m_minOccup - semiNode.getOccup());
- nodeSlide(semiNode, leafNode, cnt, i);
- if (leafNode.getOccup() == 0) {
- // remove empty leaf
- jam();
- treeRemoveNode(frag, leafNode);
- }
- }
-}
-
-/*
- * Handle leaf after removing an entry. If parent is semi-leaf, move
- * entries to it as in the semi-leaf case. If parent is interior node,
- * do nothing.
- */
-void
-Dbtux::treeRemoveLeaf(Frag& frag, NodeHandle leafNode)
-{
- TreeHead& tree = frag.m_tree;
- TupLoc parentLoc = leafNode.getLink(2);
- if (parentLoc != NullTupLoc) {
- jam();
- NodeHandle parentNode(frag);
- selectNode(parentNode, parentLoc);
- unsigned i = leafNode.getSide();
- if (parentNode.getLink(1 - i) == NullTupLoc) {
- // parent is semi-leaf
- jam();
- if (parentNode.getOccup() < tree.m_minOccup) {
- jam();
- unsigned cnt = min(leafNode.getOccup(), tree.m_minOccup - parentNode.getOccup());
- nodeSlide(parentNode, leafNode, cnt, i);
- }
- }
- }
- if (leafNode.getOccup() == 0) {
- jam();
- // remove empty leaf
- treeRemoveNode(frag, leafNode);
- }
-}
-
-/*
- * Remove empty leaf.
- */
-void
-Dbtux::treeRemoveNode(Frag& frag, NodeHandle leafNode)
-{
- TreeHead& tree = frag.m_tree;
- ndbrequire(leafNode.getChilds() == 0);
- TupLoc parentLoc = leafNode.getLink(2);
- unsigned i = leafNode.getSide();
- deleteNode(leafNode);
- if (parentLoc != NullTupLoc) {
- jam();
- NodeHandle parentNode(frag);
- selectNode(parentNode, parentLoc);
- parentNode.setLink(i, NullTupLoc);
- // re-balance the tree
- treeRemoveRebalance(frag, parentNode, i);
- return;
- }
- // tree is now empty
- tree.m_root = NullTupLoc;
-}
-
-/*
- * Re-balance tree after removing a node. The process starts with the
- * parent of the removed node.
- */
-void
-Dbtux::treeRemoveRebalance(Frag& frag, NodeHandle node, unsigned i)
-{
- while (true) {
- // height of subtree i has decreased by 1
- int j = (i == 0 ? -1 : +1);
- int b = node.getBalance();
- if (b == 0) {
- // perfectly balanced
- jam();
- node.setBalance(-j);
- // height of tree did not change - done
- return;
- } else if (b == j) {
- // height of longer subtree has decreased
- jam();
- node.setBalance(0);
- // height change propagates up
- } else if (b == -j) {
- // height of shorter subtree has decreased
- jam();
- // child on the other side
- NodeHandle childNode(frag);
- selectNode(childNode, node.getLink(1 - i));
- int b2 = childNode.getBalance();
- if (b2 == b) {
- jam();
- treeRotateSingle(frag, node, 1 - i);
- // height of tree decreased and propagates up
- } else if (b2 == -b) {
- jam();
- treeRotateDouble(frag, node, 1 - i);
- // height of tree decreased and propagates up
- } else {
- jam();
- treeRotateSingle(frag, node, 1 - i);
- // height of tree did not change - done
- return;
- }
- } else {
- ndbrequire(false);
- }
- TupLoc parentLoc = node.getLink(2);
- if (parentLoc == NullTupLoc) {
- jam();
- // root node - done
- return;
- }
- i = node.getSide();
- selectNode(node, parentLoc);
- }
-}
-
-/*
- * Single rotation about node 5. One of LL (i=0) or RR (i=1).
- *
- * 0 0
- * | |
- * 5 ==> 3
- * / \ / \
- * 3 6 2 5
- * / \ / / \
- * 2 4 1 4 6
- * /
- * 1
- *
- * In this change 5,3 and 2 must always be there. 0, 1, 2, 4 and 6 are
- * all optional. If 4 are there it changes side.
-*/
-void
-Dbtux::treeRotateSingle(Frag& frag, NodeHandle& node, unsigned i)
-{
- ndbrequire(i <= 1);
- /*
- 5 is the old top node that have been unbalanced due to an insert or
- delete. The balance is still the old balance before the update.
- Verify that bal5 is 1 if RR rotate and -1 if LL rotate.
- */
- NodeHandle node5 = node;
- const TupLoc loc5 = node5.m_loc;
- const int bal5 = node5.getBalance();
- const int side5 = node5.getSide();
- ndbrequire(bal5 + (1 - i) == i);
- /*
- 3 is the new root of this part of the tree which is to swap place with
- node 5. For an insert to cause this it must have the same balance as 5.
- For deletes it can have the balance 0.
- */
- TupLoc loc3 = node5.getLink(i);
- NodeHandle node3(frag);
- selectNode(node3, loc3);
- const int bal3 = node3.getBalance();
- /*
- 2 must always be there but is not changed. Thus we mereley check that it
- exists.
- */
- ndbrequire(node3.getLink(i) != NullTupLoc);
- /*
- 4 is not necessarily there but if it is there it will move from one
- side of 3 to the other side of 5. For LL it moves from the right side
- to the left side and for RR it moves from the left side to the right
- side. This means that it also changes parent from 3 to 5.
- */
- TupLoc loc4 = node3.getLink(1 - i);
- NodeHandle node4(frag);
- if (loc4 != NullTupLoc) {
- jam();
- selectNode(node4, loc4);
- ndbrequire(node4.getSide() == (1 - i) &&
- node4.getLink(2) == loc3);
- node4.setSide(i);
- node4.setLink(2, loc5);
- }//if
-
- /*
- Retrieve the address of 5's parent before it is destroyed
- */
- TupLoc loc0 = node5.getLink(2);
-
- /*
- The next step is to perform the rotation. 3 will inherit 5's parent
- and side. 5 will become a child of 3 on the right side for LL and on
- the left side for RR.
- 5 will get 3 as the parent. It will get 4 as a child and it will be
- on the right side of 3 for LL and left side of 3 for RR.
- The final step of the rotate is to check whether 5 originally had any
- parent. If it had not then 3 is the new root node.
- We will also verify some preconditions for the change to occur.
- 1. 3 must have had 5 as parent before the change.
- 2. 3's side is left for LL and right for RR before change.
- */
- ndbrequire(node3.getLink(2) == loc5);
- ndbrequire(node3.getSide() == i);
- node3.setLink(1 - i, loc5);
- node3.setLink(2, loc0);
- node3.setSide(side5);
- node5.setLink(i, loc4);
- node5.setLink(2, loc3);
- node5.setSide(1 - i);
- if (loc0 != NullTupLoc) {
- jam();
- NodeHandle node0(frag);
- selectNode(node0, loc0);
- node0.setLink(side5, loc3);
- } else {
- jam();
- frag.m_tree.m_root = loc3;
- }//if
- /* The final step of the change is to update the balance of 3 and
- 5 that changed places. There are two cases here. The first case is
- when 3 unbalanced in the same direction by an insert or a delete.
- In this case the changes will make the tree balanced again for both
- 3 and 5.
- The second case only occurs at deletes. In this case 3 starts out
- balanced. In the figure above this could occur if 4 starts out with
- a right node and the rotate is triggered by a delete of 6's only child.
- In this case 5 will change balance but still be unbalanced and 3 will
- be unbalanced in the opposite direction of 5.
- */
- if (bal3 == bal5) {
- jam();
- node3.setBalance(0);
- node5.setBalance(0);
- } else if (bal3 == 0) {
- jam();
- node3.setBalance(-bal5);
- node5.setBalance(bal5);
- } else {
- ndbrequire(false);
- }//if
- /*
- Set node to 3 as return parameter for enabling caller to continue
- traversing the tree.
- */
- node = node3;
-}
-
-/*
- * Double rotation about node 6. One of LR (i=0) or RL (i=1).
- *
- * 0 0
- * | |
- * 6 ==> 4
- * / \ / \
- * 2 7 2 6
- * / \ / \ / \
- * 1 4 1 3 5 7
- * / \
- * 3 5
- *
- * In this change 6, 2 and 4 must be there, all others are optional.
- * We will start by proving a Lemma.
- * Lemma:
- * The height of the sub-trees 1 and 7 and the maximum height of the
- * threes from 3 and 5 are all the same.
- * Proof:
- * maxheight(3,5) is defined as the maximum height of 3 and 5.
- * If height(7) > maxheight(3,5) then the AVL condition is ok and we
- * don't need to perform a rotation.
- * If height(7) < maxheight(3,5) then the balance of 6 would be at least
- * -3 which cannot happen in an AVL tree even before a rotation.
- * Thus we conclude that height(7) == maxheight(3,5)
- *
- * The next step is to prove that the height of 1 is equal to maxheight(3,5).
- * If height(1) - 1 > maxheight(3,5) then we would have
- * balance in 6 equal to -3 at least which cannot happen in an AVL-tree.
- * If height(1) - 1 = maxheight(3,5) then we should have solved the
- * unbalance with a single rotate and not with a double rotate.
- * If height(1) + 1 = maxheight(3,5) then we would be doing a rotate
- * with node 2 as the root of the rotation.
- * If height(1) + k = maxheight(3,5) where k >= 2 then the tree could not have
- * been an AVL-tree before the insert or delete.
- * Thus we conclude that height(1) = maxheight(3,5)
- *
- * Thus we conclude that height(1) = maxheight(3,5) = height(7).
- *
- * Observation:
- * The balance of node 4 before the rotation can be any (-1, 0, +1).
- *
- * The following changes are needed:
- * Node 6:
- * 1) Changes parent from 0 -> 4
- * 2) 1 - i link stays the same
- * 3) i side link is derived from 1 - i side link from 4
- * 4) Side is set to 1 - i
- * 5) Balance change:
- * If balance(4) == 0 then balance(6) = 0
- * since height(3) = height(5) = maxheight(3,5) = height(7)
- * If balance(4) == +1 then balance(6) = 0
- * since height(5) = maxheight(3,5) = height(7)
- * If balance(4) == -1 then balance(6) = 1
- * since height(5) + 1 = maxheight(3,5) = height(7)
- *
- * Node 2:
- * 1) Changes parent from 6 -> 4
- * 2) i side link stays the same
- * 3) 1 - i side link is derived from i side link of 4
- * 4) Side is set to i (thus not changed)
- * 5) Balance change:
- * If balance(4) == 0 then balance(2) = 0
- * since height(3) = height(5) = maxheight(3,5) = height(1)
- * If balance(4) == -1 then balance(2) = 0
- * since height(3) = maxheight(3,5) = height(1)
- * If balance(4) == +1 then balance(6) = 1
- * since height(3) + 1 = maxheight(3,5) = height(1)
- *
- * Node 4:
- * 1) Inherits parent from 6
- * 2) i side link is 2
- * 3) 1 - i side link is 6
- * 4) Side is inherited from 6
- * 5) Balance(4) = 0 independent of previous balance
- * Proof:
- * If height(1) = 0 then only 2, 4 and 6 are involved and then it is
- * trivially true.
- * If height(1) >= 1 then we are sure that 1 and 7 exist with the same
- * height and that if 3 and 5 exist they are of the same height as 1 and
- * 7 and thus we know that 4 is balanced since newheight(2) = newheight(6).
- *
- * If Node 3 exists:
- * 1) Change parent from 4 to 2
- * 2) Change side from i to 1 - i
- *
- * If Node 5 exists:
- * 1) Change parent from 4 to 6
- * 2) Change side from 1 - i to i
- *
- * If Node 0 exists:
- * 1) previous link to 6 is replaced by link to 4 on proper side
- *
- * Node 1 and 7 needs no changes at all.
- *
- * Some additional requires are that balance(2) = - balance(6) = -1/+1 since
- * otherwise we would do a single rotate.
- *
- * The balance(6) is -1 if i == 0 and 1 if i == 1
- *
- */
-void
-Dbtux::treeRotateDouble(Frag& frag, NodeHandle& node, unsigned i)
-{
- TreeHead& tree = frag.m_tree;
-
- // old top node
- NodeHandle node6 = node;
- const TupLoc loc6 = node6.m_loc;
- // the un-updated balance
- const int bal6 = node6.getBalance();
- const unsigned side6 = node6.getSide();
-
- // level 1
- TupLoc loc2 = node6.getLink(i);
- NodeHandle node2(frag);
- selectNode(node2, loc2);
- const int bal2 = node2.getBalance();
-
- // level 2
- TupLoc loc4 = node2.getLink(1 - i);
- NodeHandle node4(frag);
- selectNode(node4, loc4);
- const int bal4 = node4.getBalance();
-
- ndbrequire(i <= 1);
- ndbrequire(bal6 + (1 - i) == i);
- ndbrequire(bal2 == -bal6);
- ndbrequire(node2.getLink(2) == loc6);
- ndbrequire(node2.getSide() == i);
- ndbrequire(node4.getLink(2) == loc2);
-
- // level 3
- TupLoc loc3 = node4.getLink(i);
- TupLoc loc5 = node4.getLink(1 - i);
-
- // fill up leaf before it becomes internal
- if (loc3 == NullTupLoc && loc5 == NullTupLoc) {
- jam();
- if (node4.getOccup() < tree.m_minOccup) {
- jam();
- unsigned cnt = tree.m_minOccup - node4.getOccup();
- ndbrequire(cnt < node2.getOccup());
- nodeSlide(node4, node2, cnt, i);
- ndbrequire(node4.getOccup() >= tree.m_minOccup);
- ndbrequire(node2.getOccup() != 0);
- }
- } else {
- if (loc3 != NullTupLoc) {
- jam();
- NodeHandle node3(frag);
- selectNode(node3, loc3);
- node3.setLink(2, loc2);
- node3.setSide(1 - i);
- }
- if (loc5 != NullTupLoc) {
- jam();
- NodeHandle node5(frag);
- selectNode(node5, loc5);
- node5.setLink(2, node6.m_loc);
- node5.setSide(i);
- }
- }
- // parent
- TupLoc loc0 = node6.getLink(2);
- NodeHandle node0(frag);
- // perform the rotation
- node6.setLink(i, loc5);
- node6.setLink(2, loc4);
- node6.setSide(1 - i);
-
- node2.setLink(1 - i, loc3);
- node2.setLink(2, loc4);
-
- node4.setLink(i, loc2);
- node4.setLink(1 - i, loc6);
- node4.setLink(2, loc0);
- node4.setSide(side6);
-
- if (loc0 != NullTupLoc) {
- jam();
- selectNode(node0, loc0);
- node0.setLink(side6, loc4);
- } else {
- jam();
- frag.m_tree.m_root = loc4;
- }
- // set balance of changed nodes
- node4.setBalance(0);
- if (bal4 == 0) {
- jam();
- node2.setBalance(0);
- node6.setBalance(0);
- } else if (bal4 == -bal2) {
- jam();
- node2.setBalance(0);
- node6.setBalance(bal2);
- } else if (bal4 == bal2) {
- jam();
- node2.setBalance(-bal2);
- node6.setBalance(0);
- } else {
- ndbrequire(false);
- }
- // new top node
- node = node4;
-}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/Times.txt b/storage/ndb/src/kernel/blocks/dbtux/Times.txt
deleted file mode 100644
index 68120084846..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/Times.txt
+++ /dev/null
@@ -1,151 +0,0 @@
-ordered index performance
-=========================
-
-"mc02" 2x1700 MHz linux-2.4.9 gcc-2.96 -O3 one db-node
-
-case a: maintenance: index on Unsigned
-testOIBasic -case u -table 1 -index 2 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
-
-case b: maintenance: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned
-testOIBasic -case u -table 2 -index 5 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
-
-case c: full scan: index on PK Unsigned
-testOIBasic -case v -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
-
-case d: scan 1 tuple via EQ: index on PK Unsigned
-testOIBasic -case w -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -samples 50000 -subloop 1 -nologging -v2
-
-a, b
-1 million rows, pk update without index, pk update with index
-shows ms / 1000 rows for each and pct overhead
-
-c
-1 million rows, index on PK, full table scan, full index scan
-shows ms / 1000 rows for each and index time overhead
-
-d
-1 million rows, index on PK, read table via each pk, scan index for each pk
-shows ms / 1000 rows for each and index time overhead
-samples 10% of all PKs (100,000 pk reads, 100,000 scans)
-
-the "pct" values are from more accurate total times (not shown)
-comments [ ... ] are after the case
-
-040616 mc02/a 40 ms 87 ms 114 pct
- mc02/b 51 ms 128 ms 148 pct
-
-optim 1 mc02/a 38 ms 85 ms 124 pct
- mc02/b 51 ms 123 ms 140 pct
-
-optim 2 mc02/a 41 ms 80 ms 96 pct
- mc02/b 51 ms 117 ms 128 pct
-
-optim 3 mc02/a 43 ms 80 ms 85 pct
- mc02/b 54 ms 118 ms 117 pct
-
-optim 4 mc02/a 42 ms 80 ms 87 pct
- mc02/b 51 ms 119 ms 129 pct
-
-optim 5 mc02/a 43 ms 77 ms 77 pct
- mc02/b 54 ms 118 ms 117 pct
-
-optim 6 mc02/a 42 ms 70 ms 66 pct
- mc02/b 53 ms 109 ms 105 pct
-
-optim 7 mc02/a 42 ms 69 ms 61 pct
- mc02/b 52 ms 106 ms 101 pct
-
-optim 8 mc02/a 42 ms 69 ms 62 pct
- mc02/b 54 ms 104 ms 92 pct
-
-optim 9 mc02/a 43 ms 67 ms 54 pct
- mc02/b 53 ms 102 ms 91 pct
-
-optim 10 mc02/a 44 ms 65 ms 46 pct
- mc02/b 53 ms 88 ms 66 pct
-
-optim 11 mc02/a 43 ms 63 ms 46 pct
- mc02/b 52 ms 86 ms 63 pct
-
-optim 12 mc02/a 38 ms 55 ms 43 pct
- mc02/b 47 ms 77 ms 63 pct
- mc02/c 10 ms 14 ms 47 pct
- mc02/d 176 ms 281 ms 59 pct
-
-optim 13 mc02/a 40 ms 57 ms 42 pct
- mc02/b 47 ms 77 ms 61 pct
- mc02/c 9 ms 13 ms 50 pct
- mc02/d 170 ms 256 ms 50 pct
-
-optim 13 mc02/a 39 ms 59 ms 50 pct
- mc02/b 47 ms 77 ms 61 pct
- mc02/c 9 ms 12 ms 44 pct
- mc02/d 246 ms 289 ms 17 pct
-
-[ after wl-1884 store all-NULL keys (the tests have pctnull=10 per column) ]
-[ case d: bug in testOIBasic killed PK read performance ]
-
-optim 14 mc02/a 41 ms 60 ms 44 pct
- mc02/b 46 ms 81 ms 73 pct
- mc02/c 9 ms 13 ms 37 pct
- mc02/d 242 ms 285 ms 17 pct
-
-[ case b: do long keys suffer from many subroutine calls? ]
-[ case d: bug in testOIBasic killed PK read performance ]
-
-none mc02/a 35 ms 60 ms 71 pct
- mc02/b 42 ms 75 ms 76 pct
- mc02/c 5 ms 12 ms 106 pct
- mc02/d 165 ms 238 ms 44 pct
-
-[ johan re-installed mc02 as fedora gcc-3.3.2, tux uses more C++ stuff than tup]
-
-charsets mc02/a 35 ms 60 ms 71 pct
- mc02/b 42 ms 84 ms 97 pct
- mc02/c 5 ms 12 ms 109 pct
- mc02/d 190 ms 236 ms 23 pct
-
-[ case b: TUX can no longer use pointers to TUP data ]
-
-optim 15 mc02/a 34 ms 60 ms 72 pct
- mc02/b 42 ms 85 ms 100 pct
- mc02/c 5 ms 12 ms 110 pct
- mc02/d 178 ms 242 ms 35 pct
-
-[ corrected wasted space in index node ]
-
-optim 16 mc02/a 34 ms 53 ms 53 pct
- mc02/b 42 ms 75 ms 75 pct
-
-[ binary search of bounding node when adding entry ]
-
-none mc02/a 35 ms 53 ms 51 pct
- mc02/b 42 ms 75 ms 76 pct
-
-[ rewrote treeAdd / treeRemove ]
-
-optim 17 mc02/a 35 ms 52 ms 49 pct
- mc02/b 43 ms 75 ms 75 pct
-
-[ allow slack (2) in interior nodes - almost no effect?? ]
-
-wl-1942 mc02/a 35 ms 52 ms 49 pct
- mc02/b 42 ms 75 ms 76 pct
-
-before mc02/c 5 ms 13 ms 126 pct
- mc02/d 134 ms 238 ms 78 pct
-
-after mc02/c 5 ms 10 ms 70 pct
- mc02/d 178 ms 242 ms 69 pct
-
-[ prelim 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/storage/ndb/src/kernel/blocks/dbtux/tuxstatus.html b/storage/ndb/src/kernel/blocks/dbtux/tuxstatus.html
deleted file mode 100644
index 264809cefd3..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtux/tuxstatus.html
+++ /dev/null
@@ -1,120 +0,0 @@
-<HTML>
-<HEAD>
-<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
-<TITLE>NDB Ordered Index Status</TITLE>
-</HEAD>
-<BODY LINK="#0000ff" VLINK="#800080" BGCOLOR="#ffffff">
-<p>
-<h2>NDB Ordered Index Status</h2>
-<p>
-<h3>Alpha release Jan 30, 2004</h3>
-<p>
-<ul>
- <li>
- Up to 32 index attributes of any type, possibly nullable.
- <li>
- Index build i.e. table need not be empty.
- <li>
- Logging NOT done, index rebuilt at system restart.
- <li>
- Single range scan with lower and upper bounds.
- <li>
- Scan with locking: read latest, read for update.
- <li>
- LIMITED number of parallel scans.
- <li>
- Total result set NOT in index key order.
- <li>
- NDB ODBC optimizer to use ordered index for equality but NOT for ranges.
- <li>
- MySQL optimizer to use ordered index for equality and ranges.
-</ul>
-<p>
-As an example, consider following index on integer attributes.
-<p>
-<tt>SQL&gt;create index X on T (A, B, C) nologging;</tt>
-<p>
-Single range scan means that bounds are set on
-an initial sequence of index keys, and all but last is an equality.
-<br>
-For example following scans are supported (the last 2 not via NDB ODBC).
-<p>
-<tt>SQL&gt;select * from T where A = 1;</tt>
-<br>
-<tt>SQL&gt;select * from T where A = 1 and B = 10 and C = 20;</tt>
-<br>
-<tt>SQL&gt;select * from T where A &lt; 10;</tt>
-<br>
-<tt>SQL&gt;select * from T where A = 1 and 10 &lt; B and B &lt; 20;</tt>
-<p>
-Following scans are NOT supported:
-<p>
-<tt>SQL&gt;select * from T where B = 1;</tt>
-<br>
-<tt>SQL&gt;select * from T where A &lt; 10 and B &lt; 20;</tt>
-<br>
-<h3>Features and dates</h3>
-[ Now = Jan 19 ]
-<p>
-<table border=1 cellpadding=1>
-<tr align="left">
- <th width="40%">Feature</th>
- <th width="15%">Now</th> <th width="15%">Jan 30</th> <th width="15%">Mar 01</th> <th width="15%">Never</th>
-</tr>
-<tr align=left>
- <td>Index maintenance</td>
- <td>X</td> <td>-</td> <td>-</td> <td>-</td>
-</tr>
-<tr align=left>
- <td>Basic scan</td>
- <td>X 1)</td> <td>-</td> <td>-</td> <td>-</td>
-</tr>
-<tr align=left>
- <td>Scan bounds on nullable attributes</td>
- <td>-</td> <td>X</td> <td>-</td> <td>-</td>
-</tr>
-<tr align=left>
- <td>Scan with locking</td>
- <td>-</td> <td>X</td> <td>-</td> <td>-</td>
-</tr>
-<tr align="left">
- <td>NDB ODBC equality bounds</td>
- <td>-</td> <td>X</td> <td>-</td> <td>-</td>
-</tr>
-<tr align="left">
- <td>MySQL integration</td>
- <td>-</td> <td>X</td> <td>-</td> <td>-</td>
-</tr>
-<tr align=left>
- <td>Index build</td>
- <td>2)</td> <td>X</td> <td>-</td> <td>-</td>
-</tr>
-<tr align=left>
- <td>Unlimited number of scans</td>
- <td>3)</td> <td>-</td> <td>X</td> <td>-</td>
-</tr>
-<tr align=left>
- <td>Total ordering</td>
- <td>-</td> <td>-</td> <td>X</td> <td>-</td>
-</tr>
-<tr align=left>
- <td>Multiple range scan</td>
- <td>-</td> <td>-</td> <td>X</td> <td>-</td>
-</tr>
-<tr align="left">
- <td>NDB ODBC range bounds</td>
- <td>-</td> <td>-</td> <td>-</td> <td>X</td>
-</tr>
-<tr align=left>
- <td>Logging</td>
- <td>-</td> <td>-</td> <td>-</td> <td>X</td>
-</tr>
-</table>
-<p>
-1) No locking and bounds must be on non-nullable key attributes.
-<br>
-2) Currently table must be empty when index is created.
-<br>
-3) Currently limited to 11 simultaneous per fragment.
-</BODY>
-</HTML>
diff --git a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
deleted file mode 100644
index 398c63add84..00000000000
--- a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
+++ /dev/null
@@ -1,2608 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include "DbUtil.hpp"
-
-#include <ndb_version.h>
-
-#include <signaldata/WaitGCP.hpp>
-#include <signaldata/KeyInfo.hpp>
-#include <signaldata/AttrInfo.hpp>
-#include <signaldata/TcKeyConf.hpp>
-#include <signaldata/TcKeyFailConf.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/DictTabInfo.hpp>
-
-#include <signaldata/UtilSequence.hpp>
-#include <signaldata/UtilPrepare.hpp>
-#include <signaldata/UtilRelease.hpp>
-#include <signaldata/UtilExecute.hpp>
-#include <signaldata/UtilLock.hpp>
-
-#include <SectionReader.hpp>
-#include <Interpreter.hpp>
-#include <AttributeHeader.hpp>
-
-#include <NdbTick.h>
-
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Startup
- * ------------------------------------------------------------------------
- *
- * Constructors, startup, initializations
- **************************************************************************/
-
-DbUtil::DbUtil(Block_context& ctx) :
- SimulatedBlock(DBUTIL, ctx),
- c_runningPrepares(c_preparePool),
- c_seizingTransactions(c_transactionPool),
- c_runningTransactions(c_transactionPool),
- c_lockQueues(c_lockQueuePool)
-{
- 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);
- addRecSignal(GSN_CONTINUEB, &DbUtil::execCONTINUEB);
-
- //addRecSignal(GSN_TCSEIZEREF, &DbUtil::execTCSEIZEREF);
- addRecSignal(GSN_TCSEIZECONF, &DbUtil::execTCSEIZECONF);
- addRecSignal(GSN_TCKEYCONF, &DbUtil::execTCKEYCONF);
- addRecSignal(GSN_TCKEYREF, &DbUtil::execTCKEYREF);
- addRecSignal(GSN_TCROLLBACKREP, &DbUtil::execTCROLLBACKREP);
-
- //addRecSignal(GSN_TCKEY_FAILCONF, &DbUtil::execTCKEY_FAILCONF);
- //addRecSignal(GSN_TCKEY_FAILREF, &DbUtil::execTCKEY_FAILREF);
- addRecSignal(GSN_TRANSID_AI, &DbUtil::execTRANSID_AI);
-
- /**
- * Sequence Service
- */
- addRecSignal(GSN_UTIL_SEQUENCE_REQ, &DbUtil::execUTIL_SEQUENCE_REQ);
- // Debug
- addRecSignal(GSN_UTIL_SEQUENCE_REF, &DbUtil::execUTIL_SEQUENCE_REF);
- addRecSignal(GSN_UTIL_SEQUENCE_CONF, &DbUtil::execUTIL_SEQUENCE_CONF);
-
- /**
- * Locking
- */
- addRecSignal(GSN_UTIL_CREATE_LOCK_REQ, &DbUtil::execUTIL_CREATE_LOCK_REQ);
- addRecSignal(GSN_UTIL_DESTROY_LOCK_REQ, &DbUtil::execUTIL_DESTORY_LOCK_REQ);
- addRecSignal(GSN_UTIL_LOCK_REQ, &DbUtil::execUTIL_LOCK_REQ);
- addRecSignal(GSN_UTIL_UNLOCK_REQ, &DbUtil::execUTIL_UNLOCK_REQ);
-
- /**
- * Backend towards Dict
- */
- addRecSignal(GSN_GET_TABINFOREF, &DbUtil::execGET_TABINFOREF);
- addRecSignal(GSN_GET_TABINFO_CONF, &DbUtil::execGET_TABINFO_CONF);
-
- /**
- * Prepare / Execute / Release Services
- */
- addRecSignal(GSN_UTIL_PREPARE_REQ, &DbUtil::execUTIL_PREPARE_REQ);
- addRecSignal(GSN_UTIL_PREPARE_CONF, &DbUtil::execUTIL_PREPARE_CONF);
- addRecSignal(GSN_UTIL_PREPARE_REF, &DbUtil::execUTIL_PREPARE_REF);
-
- addRecSignal(GSN_UTIL_EXECUTE_REQ, &DbUtil::execUTIL_EXECUTE_REQ);
- addRecSignal(GSN_UTIL_EXECUTE_CONF, &DbUtil::execUTIL_EXECUTE_CONF);
- addRecSignal(GSN_UTIL_EXECUTE_REF, &DbUtil::execUTIL_EXECUTE_REF);
-
- 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);
-}
-
-DbUtil::~DbUtil()
-{
-}
-
-BLOCK_FUNCTIONS(DbUtil)
-
-void
-DbUtil::releasePrepare(PreparePtr prepPtr) {
- prepPtr.p->preparePages.release();
- c_runningPrepares.release(prepPtr); // Automatic release in pool
-}
-
-void
-DbUtil::releasePreparedOperation(PreparedOperationPtr prepOpPtr) {
- prepOpPtr.p->attrMapping.release();
- prepOpPtr.p->attrInfo.release();
- prepOpPtr.p->rsInfo.release();
- prepOpPtr.p->pkBitmask.clear();
- c_preparedOperationPool.release(prepOpPtr); // No list holding these structs
-}
-
-void
-DbUtil::releaseTransaction(TransactionPtr transPtr){
- transPtr.p->executePages.release();
- OperationPtr opPtr;
- for(transPtr.p->operations.first(opPtr); opPtr.i != RNIL;
- transPtr.p->operations.next(opPtr)){
- opPtr.p->attrInfo.release();
- opPtr.p->keyInfo.release();
- opPtr.p->rs.release();
- if (opPtr.p->prepOp != 0 && opPtr.p->prepOp_i != RNIL) {
- if (opPtr.p->prepOp->releaseFlag) {
- PreparedOperationPtr prepOpPtr;
- prepOpPtr.i = opPtr.p->prepOp_i;
- prepOpPtr.p = opPtr.p->prepOp;
- releasePreparedOperation(prepOpPtr);
- }
- }
- }
- transPtr.p->operations.release();
- 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 =
- m_ctx.m_config.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)
-{
- jamEntry();
-
- const Uint32 startphase = signal->theData[1];
-
- if(startphase == 1){
- c_transId[0] = (number() << 20) + (getOwnNodeId() << 8);
- c_transId[1] = 0;
- }
-
- if(startphase == 6){
- hardcodedPrepare();
- connectTc(signal);
- }
-
- signal->theData[0] = 0;
- signal->theData[3] = 1;
- signal->theData[4] = 6;
- signal->theData[5] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
-
- return;
-}
-
-void
-DbUtil::execNDB_STTOR(Signal* signal)
-{
- (void)signal; // Don't want compiler warning
-
- jamEntry();
-}
-
-
-/***************************
- * Seize a number of TC records
- * to use for Util transactions
- */
-
-void
-DbUtil::connectTc(Signal* signal){
-
- TransactionPtr ptr;
- while(c_seizingTransactions.seize(ptr)){
- signal->theData[0] = ptr.i << 1; // See TcCommitConf
- signal->theData[1] = reference();
- sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB);
- }
-}
-
-void
-DbUtil::execTCSEIZECONF(Signal* signal){
- jamEntry();
-
- TransactionPtr ptr;
- ptr.i = signal->theData[0] >> 1;
- c_seizingTransactions.getPtr(ptr, signal->theData[0] >> 1);
- ptr.p->connectPtr = signal->theData[1];
-
- c_seizingTransactions.release(ptr);
-}
-
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Misc
- * ------------------------------------------------------------------------
- *
- * ContinueB, Dump
- **************************************************************************/
-
-void
-DbUtil::execCONTINUEB(Signal* signal){
- jamEntry();
- const Uint32 Tdata0 = signal->theData[0];
-
- switch(Tdata0){
- default:
- ndbrequire(0);
- }
-}
-
-void
-DbUtil::execDUMP_STATE_ORD(Signal* signal){
- jamEntry();
-
- /****************************************************************************
- * SEQUENCE SERVICE
- *
- * 200 : Simple test of Public Sequence Interface
- * ----------------------------------------------
- * - Sends a SEQUENCE_REQ signal to Util (itself)
- */
- const Uint32 tCase = signal->theData[0];
- if(tCase == 200){
- jam()
- ndbout << "--------------------------------------------------" << endl;
- UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
- Uint32 seqId = 1;
- Uint32 reqTy = UtilSequenceReq::CurrVal;
-
- if(signal->length() > 1) seqId = signal->theData[1];
- if(signal->length() > 2) reqTy = signal->theData[2];
-
- req->senderData = 12;
- req->sequenceId = seqId;
- req->requestType = reqTy;
-
- sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
- signal, UtilSequenceReq::SignalLength, JBB);
- }
-
- /****************************************************************************/
- /* // Obsolete tests, should be rewritten for long signals!!
- if(tCase == 210){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0], 128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Delete);
- w.add(UtilPrepareReq::TableName, "sys/def/SYSTAB_0");
- w.add(UtilPrepareReq::AttributeName, "SYSKEY_0"); // AttrNo = 0
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- if(tCase == 211){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Insert);
- w.add(UtilPrepareReq::TableName, "sys/def/SYSTAB_0");
- w.add(UtilPrepareReq::AttributeName, "SYSKEY_0"); // AttrNo = 0
- w.add(UtilPrepareReq::AttributeName, "NEXTID"); // AttrNo = 1
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- if(tCase == 212){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Update);
- w.add(UtilPrepareReq::TableName, "sys/def/SYSTAB_0");
- w.add(UtilPrepareReq::AttributeName, "SYSKEY_0"); // AttrNo = 0
- w.add(UtilPrepareReq::AttributeName, "NEXTID"); // AttrNo = 1
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- if(tCase == 213){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Read);
- w.add(UtilPrepareReq::TableName, "sys/def/SYSTAB_0");
- w.add(UtilPrepareReq::AttributeName, "SYSKEY_0"); // AttrNo = 0
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- if(tCase == 214){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0], 128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Delete);
- w.add(UtilPrepareReq::TableId, (unsigned int)0); // SYSTAB_0
- w.add(UtilPrepareReq::AttributeId, (unsigned int)0);// SYSKEY_0
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- if(tCase == 215){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Insert);
- w.add(UtilPrepareReq::TableId, (unsigned int)0); // SYSTAB_0
- w.add(UtilPrepareReq::AttributeId, (unsigned int)0); // SYSKEY_0
- w.add(UtilPrepareReq::AttributeId, 1); // NEXTID
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- if(tCase == 216){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Update);
- w.add(UtilPrepareReq::TableId, (unsigned int)0); // SYSTAB_0
- w.add(UtilPrepareReq::AttributeId, (unsigned int)0);// SYSKEY_0
- w.add(UtilPrepareReq::AttributeId, 1); // NEXTID
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- if(tCase == 217){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Read);
- w.add(UtilPrepareReq::TableId, (unsigned int)0); // SYSTAB_0
- w.add(UtilPrepareReq::AttributeId, (unsigned int)0);// SYSKEY_0
- Uint32 length = w.getWordsUsed();
- ndbassert(length <= pageSizeInWords);
-
- sendUtilPrepareReqSignals(signal, propPage, length);
- }
- */
- /****************************************************************************/
- /* // Obsolete tests, should be rewritten for long signals!!
- if(tCase == 220){
- jam();
- ndbout << "--------------------------------------------------" << endl;
- Uint32 prepI = signal->theData[1];
- Uint32 length = signal->theData[2];
- Uint32 attributeValue0 = signal->theData[3];
- Uint32 attributeValue1a = signal->theData[4];
- Uint32 attributeValue1b = signal->theData[5];
- ndbrequire(prepI != 0);
-
- UtilExecuteReq * req = (UtilExecuteReq *)signal->getDataPtrSend();
-
- req->senderData = 221;
- req->prepareId = prepI;
- req->totalDataLen = length; // Including headers
- req->offset = 0;
-
- AttributeHeader::init(&req->attrData[0], 0, 1); // AttrNo 0, DataSize
- req->attrData[1] = attributeValue0; // AttrValue
- AttributeHeader::init(&req->attrData[2], 1, 2); // AttrNo 1, DataSize
- req->attrData[3] = attributeValue1a; // AttrValue
- req->attrData[4] = attributeValue1b; // AttrValue
-
- printUTIL_EXECUTE_REQ(stdout, signal->getDataPtrSend(), 3 + 5,0);
- sendSignal(DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal, 3 + 5, JBB);
- }
-*/
- /****************************************************************************
- * 230 : PRINT STATE
- */
-#ifdef ARRAY_GUARD
- if(tCase == 230){
- jam();
-
- ndbout << "--------------------------------------------------" << endl;
- if (signal->length() <= 1) {
- ndbout << "Usage: DUMP 230 <recordType> <recordNo>" << endl
- << "[1] Print Prepare (running) records" << endl
- << "[2] Print PreparedOperation records" << endl
- << "[3] Print Transaction records" << endl
- << "[4] Print Operation records" << endl
- << "Ex. \"dump 230 1 2\" prints Prepare record no 2." << endl
- << endl
- << "210 : PREPARE_REQ DELETE SYSTAB_0 SYSKEY_0" << endl
- << "211 : PREPARE_REQ INSERT SYSTAB_0 SYSKEY_0 NEXTID" << endl
- << "212 : PREPARE_REQ UPDATE SYSTAB_0 SYSKEY_0 NEXTID" << endl
- << "213 : PREPARE_REQ READ SYSTAB_0 SYSKEY_0" << endl
- << "214 : PREPARE_REQ DELETE SYSTAB_0 SYSKEY_0 using id" << endl
- << "215 : PREPARE_REQ INSERT SYSTAB_0 SYSKEY_0 NEXTID using id" << endl
- << "216 : PREPARE_REQ UPDATE SYSTAB_0 SYSKEY_0 NEXTID using id" << endl
- << "217 : PREPARE_REQ READ SYSTAB_0 SYSKEY_0 using id" << endl
- << "220 : EXECUTE_REQ <PrepId> <Len> <Val1> <Val2a> <Val2b>" <<endl
- << "299 : Crash system (using ndbrequire(0))"
- << endl
- << "Ex. \"dump 220 3 5 1 0 17 \" prints Prepare record no 2."
- << endl;
- return;
- }
-
- switch (signal->theData[1]) {
- case 1:
- // ** Print a specific record **
- if (signal->length() >= 3) {
- PreparePtr prepPtr;
- if (!c_preparePool.isSeized(signal->theData[2])) {
- ndbout << "Prepare Id: " << signal->theData[2]
- << " (Not seized!)" << endl;
- } else {
- c_preparePool.getPtr(prepPtr, signal->theData[2]);
- prepPtr.p->print();
- }
- return;
- }
-
- // ** Print all records **
- PreparePtr prepPtr;
- if (!c_runningPrepares.first(prepPtr)) {
- ndbout << "No Prepare records exist" << endl;
- return;
- }
-
- while (!prepPtr.isNull()) {
- prepPtr.p->print();
- c_runningPrepares.next(prepPtr);
- }
- return;
-
- case 2:
- // ** Print a specific record **
- if (signal->length() >= 3) {
- if (!c_preparedOperationPool.isSeized(signal->theData[2])) {
- ndbout << "PreparedOperation Id: " << signal->theData[2]
- << " (Not seized!)" << endl;
- return;
- }
- ndbout << "PreparedOperation Id: " << signal->theData[2] << endl;
- PreparedOperationPtr prepOpPtr;
- c_preparedOperationPool.getPtr(prepOpPtr, signal->theData[2]);
- prepOpPtr.p->print();
- return;
- }
-
- // ** Print all records **
-#if 0 // not implemented
- PreparedOperationPtr prepOpPtr;
- if (!c_runningPreparedOperations.first(prepOpPtr)) {
- ndbout << "No PreparedOperations exist" << endl;
- return;
- }
- while (!prepOpPtr.isNull()) {
- ndbout << "[-PreparedOperation no " << prepOpPtr.i << ":";
- prepOpPtr.p->print();
- ndbout << "]";
- c_runningPreparedOperations.next(prepOpPtr);
- }
-#endif
- return;
-
- case 3:
- // ** Print a specific record **
- if (signal->length() >= 3) {
- ndbout << "Print specific record not implemented." << endl;
- return;
- }
-
- // ** Print all records **
- ndbout << "Print all records not implemented, specify an Id." << endl;
- return;
-
- case 4:
- ndbout << "Not implemented" << endl;
- return;
-
- default:
- ndbout << "Unknown input (try without any data)" << endl;
- return;
- }
- }
-#endif
- if(tCase == 240 && signal->getLength() == 2){
- MutexManager::ActiveMutexPtr ptr;
- ndbrequire(c_mutexMgr.seize(ptr));
- ptr.p->m_mutexId = signal->theData[1];
- Callback c = { safe_cast(&DbUtil::mutex_created), ptr.i };
- ptr.p->m_callback = c;
- c_mutexMgr.create(signal, ptr);
- ndbout_c("c_mutexMgr.create ptrI=%d mutexId=%d", ptr.i, ptr.p->m_mutexId);
- }
-
- if(tCase == 241 && signal->getLength() == 2){
- MutexManager::ActiveMutexPtr ptr;
- ndbrequire(c_mutexMgr.seize(ptr));
- ptr.p->m_mutexId = signal->theData[1];
- Callback c = { safe_cast(&DbUtil::mutex_locked), ptr.i };
- ptr.p->m_callback = c;
- c_mutexMgr.lock(signal, ptr);
- ndbout_c("c_mutexMgr.lock ptrI=%d mutexId=%d", ptr.i, ptr.p->m_mutexId);
- }
-
- if(tCase == 242 && signal->getLength() == 2){
- MutexManager::ActiveMutexPtr ptr;
- ptr.i = signal->theData[1];
- c_mutexMgr.getPtr(ptr);
- Callback c = { safe_cast(&DbUtil::mutex_unlocked), ptr.i };
- ptr.p->m_callback = c;
- c_mutexMgr.unlock(signal, ptr);
- ndbout_c("c_mutexMgr.unlock ptrI=%d mutexId=%d", ptr.i, ptr.p->m_mutexId);
- }
-
- if(tCase == 243 && signal->getLength() == 3){
- MutexManager::ActiveMutexPtr ptr;
- ndbrequire(c_mutexMgr.seize(ptr));
- ptr.p->m_mutexId = signal->theData[1];
- ptr.p->m_mutexKey = signal->theData[2];
- Callback c = { safe_cast(&DbUtil::mutex_destroyed), ptr.i };
- ptr.p->m_callback = c;
- c_mutexMgr.destroy(signal, ptr);
- ndbout_c("c_mutexMgr.destroy ptrI=%d mutexId=%d key=%d",
- ptr.i, ptr.p->m_mutexId, ptr.p->m_mutexKey);
- }
-}
-
-void
-DbUtil::mutex_created(Signal* signal, Uint32 ptrI, Uint32 retVal){
- MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
- c_mutexMgr.getPtr(ptr);
- ndbout_c("mutex_created - mutexId=%d, retVal=%d",
- ptr.p->m_mutexId, retVal);
- c_mutexMgr.release(ptrI);
-}
-
-void
-DbUtil::mutex_destroyed(Signal* signal, Uint32 ptrI, Uint32 retVal){
- MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
- c_mutexMgr.getPtr(ptr);
- ndbout_c("mutex_destroyed - mutexId=%d, retVal=%d",
- ptr.p->m_mutexId, retVal);
- c_mutexMgr.release(ptrI);
-}
-
-void
-DbUtil::mutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){
- MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
- c_mutexMgr.getPtr(ptr);
- ndbout_c("mutex_locked - mutexId=%d, retVal=%d key=%d ptrI=%d",
- ptr.p->m_mutexId, retVal, ptr.p->m_mutexKey, ptrI);
- if(retVal)
- c_mutexMgr.release(ptrI);
-}
-
-void
-DbUtil::mutex_unlocked(Signal* signal, Uint32 ptrI, Uint32 retVal){
- MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
- c_mutexMgr.getPtr(ptr);
- ndbout_c("mutex_unlocked - mutexId=%d, retVal=%d",
- ptr.p->m_mutexId, retVal);
- if(!retVal)
- c_mutexMgr.release(ptrI);
-}
-
-void
-DbUtil::execUTIL_SEQUENCE_REF(Signal* signal){
- jamEntry();
- ndbout << "UTIL_SEQUENCE_REF" << endl;
- printUTIL_SEQUENCE_REF(stdout, signal->getDataPtrSend(), signal->length(), 0);
-}
-
-void
-DbUtil::execUTIL_SEQUENCE_CONF(Signal* signal){
- jamEntry();
- ndbout << "UTIL_SEQUENCE_CONF" << endl;
- printUTIL_SEQUENCE_CONF(stdout, signal->getDataPtrSend(), signal->length(),0);
-}
-
-void
-DbUtil::execUTIL_PREPARE_CONF(Signal* signal){
- jamEntry();
- ndbout << "UTIL_PREPARE_CONF" << endl;
- printUTIL_PREPARE_CONF(stdout, signal->getDataPtrSend(), signal->length(), 0);
-}
-
-void
-DbUtil::execUTIL_PREPARE_REF(Signal* signal){
- jamEntry();
- ndbout << "UTIL_PREPARE_REF" << endl;
- printUTIL_PREPARE_REF(stdout, signal->getDataPtrSend(), signal->length(), 0);
-}
-
-void
-DbUtil::execUTIL_EXECUTE_CONF(Signal* signal) {
- jamEntry();
- ndbout << "UTIL_EXECUTE_CONF" << endl;
- printUTIL_EXECUTE_CONF(stdout, signal->getDataPtrSend(), signal->length(), 0);
-}
-
-void
-DbUtil::execUTIL_EXECUTE_REF(Signal* signal) {
- jamEntry();
-
- ndbout << "UTIL_EXECUTE_REF" << endl;
- printUTIL_EXECUTE_REF(stdout, signal->getDataPtrSend(), signal->length(), 0);
-}
-
-void
-DbUtil::execUTIL_RELEASE_CONF(Signal* signal) {
- jamEntry();
- ndbout << "UTIL_RELEASE_CONF" << endl;
-}
-
-void
-DbUtil::execUTIL_RELEASE_REF(Signal* signal) {
- jamEntry();
-
- ndbout << "UTIL_RELEASE_REF" << endl;
-}
-
-void
-DbUtil::sendUtilPrepareRef(Signal* signal, UtilPrepareRef::ErrorCode error,
- Uint32 recipient, Uint32 senderData){
- UtilPrepareRef * ref = (UtilPrepareRef *)signal->getDataPtrSend();
- ref->errorCode = error;
- ref->senderData = senderData;
-
- sendSignal(recipient, GSN_UTIL_PREPARE_REF, signal,
- UtilPrepareRef::SignalLength, JBB);
-}
-
-void
-DbUtil::sendUtilExecuteRef(Signal* signal, UtilExecuteRef::ErrorCode error,
- Uint32 TCerror, Uint32 recipient, Uint32 senderData){
-
- UtilExecuteRef * ref = (UtilExecuteRef *)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->errorCode = error;
- ref->TCErrorCode = TCerror;
-
- sendSignal(recipient, GSN_UTIL_EXECUTE_REF, signal,
- UtilPrepareRef::SignalLength, JBB);
-}
-
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Prepare service
- * ------------------------------------------------------------------------
- *
- * Prepares a transaction by storing info in some structs
- **************************************************************************/
-
-void
-DbUtil::execUTIL_PREPARE_REQ(Signal* signal)
-{
- jamEntry();
-
- /****************
- * Decode Signal
- ****************/
- UtilPrepareReq * req = (UtilPrepareReq *)signal->getDataPtr();
- const Uint32 senderRef = req->senderRef;
- const Uint32 senderData = req->senderData;
-
- if(signal->getNoOfSections() == 0) {
- // Missing prepare data
- jam();
- releaseSections(signal);
- sendUtilPrepareRef(signal, UtilPrepareRef::MISSING_PROPERTIES_SECTION,
- senderRef, senderData);
- return;
- }
-
- PreparePtr prepPtr;
- SegmentedSectionPtr ptr;
-
- jam();
- if(!c_runningPrepares.seize(prepPtr)) {
- jam();
- releaseSections(signal);
- sendUtilPrepareRef(signal, UtilPrepareRef::PREPARE_SEIZE_ERROR,
- senderRef, senderData);
- return;
- };
- signal->getSection(ptr, UtilPrepareReq::PROPERTIES_SECTION);
- const Uint32 noPages = (ptr.sz + sizeof(Page32)) / sizeof(Page32);
- ndbassert(noPages > 0);
- if (!prepPtr.p->preparePages.seize(noPages)) {
- jam();
- releaseSections(signal);
- sendUtilPrepareRef(signal, UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR,
- senderRef, senderData);
- c_preparePool.release(prepPtr);
- return;
- }
- // Save SimpleProperties
- Uint32* target = &prepPtr.p->preparePages.getPtr(0)->data[0];
- copy(target, ptr);
- prepPtr.p->prepDataLen = ptr.sz;
- // Release long signal sections
- releaseSections(signal);
- // Check table properties with DICT
- SimplePropertiesSectionReader reader(ptr, getSectionSegmentPool());
- prepPtr.p->clientRef = senderRef;
- prepPtr.p->clientData = senderData;
- // Release long signal sections
- releaseSections(signal);
- readPrepareProps(signal, &reader, prepPtr.i);
-}
-
-void DbUtil::readPrepareProps(Signal* signal,
- SimpleProperties::Reader* reader,
- Uint32 senderData)
-{
- jam();
-#if 0
- printf("DbUtil::readPrepareProps: Received SimpleProperties:\n");
- reader->printAll(ndbout);
-#endif
- ndbrequire(reader->first());
- ndbrequire(reader->getKey() == UtilPrepareReq::NoOfOperations);
- ndbrequire(reader->getUint32() == 1); // Only one op/trans implemented
-
- ndbrequire(reader->next());
- ndbrequire(reader->getKey() == UtilPrepareReq::OperationType);
-
- ndbrequire(reader->next());
- UtilPrepareReq::KeyValue tableKey =
- (UtilPrepareReq::KeyValue) reader->getKey();
- ndbrequire((tableKey == UtilPrepareReq::TableName) ||
- (tableKey == UtilPrepareReq::TableId));
-
- /************************
- * Ask Dict for metadata
- ************************/
- {
- GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = senderData;
- if (tableKey == UtilPrepareReq::TableName) {
- jam();
- char tableName[MAX_TAB_NAME_SIZE];
- req->requestType = GetTabInfoReq::RequestByName |
- GetTabInfoReq::LongSignalConf;
-
- req->tableNameLen = reader->getValueLen(); // Including trailing \0
-
- /********************************************
- * Code signal data and send signals to DICT
- ********************************************/
-
- ndbrequire(req->tableNameLen < MAX_TAB_NAME_SIZE);
- reader->getString((char*)tableName);
- LinearSectionPtr ptr[1];
- ptr[0].p = (Uint32*)tableName;
- ptr[0].sz = req->tableNameLen;
- sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB, ptr,1);
-
- }
- else { // (tableKey == UtilPrepareReq::TableId)
- jam();
- req->requestType = GetTabInfoReq::RequestById |
- GetTabInfoReq::LongSignalConf;
- req->tableId = reader->getUint32();
- sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB);
- }
-
- }
-}
-
-/**
- * @note We assume that this signal comes due to a request related
- * to a Prepare struct. DictTabInfo:s 'senderData' denotes
- * the Prepare struct related to the request.
- */
-void
-DbUtil::execGET_TABINFO_CONF(Signal* signal){
- jamEntry();
-
- if(!assembleFragments(signal)){
- jam();
- return;
- }
-
- /****************
- * Decode signal
- ****************/
- GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
- const Uint32 prepI = conf->senderData;
- const Uint32 totalLen = conf->totalLen;
-
- SegmentedSectionPtr dictTabInfoPtr;
- signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
- ndbrequire(dictTabInfoPtr.sz == totalLen);
-
- PreparePtr prepPtr;
- c_runningPrepares.getPtr(prepPtr, prepI);
- prepareOperation(signal, prepPtr);
-}
-
-void
-DbUtil::execGET_TABINFOREF(Signal* signal){
- jamEntry();
-
- GetTabInfoRef * ref = (GetTabInfoRef *)signal->getDataPtr();
- Uint32 prepI = ref->senderData;
-#define EVENT_DEBUG
-#if 0 //def EVENT_DEBUG
- ndbout << "Signal GET_TABINFOREF received." << endl;
- ndbout << "Error Code: " << ref->errorCode << endl;
-
- switch (ref->errorCode) {
- case GetTabInfoRef::InvalidTableId:
- ndbout << " Msg: Invalid table id" << endl;
- break;
- case GetTabInfoRef::TableNotDefined:
- ndbout << " Msg: Table not defined" << endl;
- break;
- case GetTabInfoRef::TableNameToLong:
- ndbout << " Msg: Table node too long" << endl;
- break;
- default:
- ndbout << " Msg: Unknown error returned from Dict" << endl;
- break;
- }
-#endif
-
- PreparePtr prepPtr;
- c_runningPrepares.getPtr(prepPtr, prepI);
-
- sendUtilPrepareRef(signal, UtilPrepareRef::DICT_TAB_INFO_ERROR,
- prepPtr.p->clientRef, prepPtr.p->clientData);
-
- releasePrepare(prepPtr);
-}
-
-
-/******************************************************************************
- * Prepare Operation
- *
- * Using a prepare record, prepare an operation (i.e. create PreparedOperation).
- * Info from both Pepare request (PreparePages) and DictTabInfo is used.
- *
- * Algorithm:
- * -# Seize AttrbuteMapping
- * - Lookup in preparePages how many attributes should be prepared
- * - Seize AttributeMapping
- * -# For each attributes in preparePages
- * - Lookup id and isPK in dictInfoPages
- * - Store "no -> (AttributeId, Position)" in AttributeMapping
- * -# For each map in AttributeMapping
- * - if (isPK) then assign offset
- ******************************************************************************/
-void
-DbUtil::prepareOperation(Signal* signal, PreparePtr prepPtr)
-{
- jam();
-
- /*******************************************
- * Seize and store PreparedOperation struct
- *******************************************/
- PreparedOperationPtr prepOpPtr;
- if(!c_preparedOperationPool.seize(prepOpPtr)) {
- jam();
- releaseSections(signal);
- sendUtilPrepareRef(signal, UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR,
- prepPtr.p->clientRef, prepPtr.p->clientData);
- releasePrepare(prepPtr);
- return;
- }
- prepPtr.p->prepOpPtr = prepOpPtr;
-
- /********************
- * Read request info
- ********************/
- SimplePropertiesLinearReader prepPagesReader(&prepPtr.p->preparePages.getPtr(0)->data[0],
- prepPtr.p->prepDataLen);
-
- ndbrequire(prepPagesReader.first());
- ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::NoOfOperations);
- const Uint32 noOfOperations = prepPagesReader.getUint32();
- ndbrequire(noOfOperations == 1);
-
- ndbrequire(prepPagesReader.next());
- ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::OperationType);
- const Uint32 operationType = prepPagesReader.getUint32();
-
- ndbrequire(prepPagesReader.next());
-
- char tableName[MAX_TAB_NAME_SIZE];
- Uint32 tableId;
- UtilPrepareReq::KeyValue tableKey =
- (UtilPrepareReq::KeyValue) prepPagesReader.getKey();
- if (tableKey == UtilPrepareReq::TableId) {
- jam();
- tableId = prepPagesReader.getUint32();
- }
- else {
- jam();
- ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::TableName);
- ndbrequire(prepPagesReader.getValueLen() <= MAX_TAB_NAME_SIZE);
- prepPagesReader.getString(tableName);
- }
- /******************************************************************
- * Seize AttributeMapping (by counting no of attribs in prepPages)
- ******************************************************************/
- Uint32 noOfAttributes = 0; // No of attributes in PreparePages (used later)
- while(prepPagesReader.next()) {
- if (tableKey == UtilPrepareReq::TableName) {
- jam();
- ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::AttributeName);
- } else {
- jam();
- ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::AttributeId);
- }
- noOfAttributes++;
- }
- ndbrequire(prepPtr.p->prepOpPtr.p->attrMapping.seize(noOfAttributes));
- if (operationType == UtilPrepareReq::Read) {
- ndbrequire(prepPtr.p->prepOpPtr.p->rsInfo.seize(noOfAttributes));
- }
- /***************************************
- * For each attribute name, lookup info
- ***************************************/
- // Goto start of attribute names
- ndbrequire(prepPagesReader.first() && prepPagesReader.next() &&
- prepPagesReader.next());
-
- DictTabInfo::Table tableDesc; tableDesc.init();
- AttrMappingBuffer::DataBufferIterator attrMappingIt;
- ndbrequire(prepPtr.p->prepOpPtr.p->attrMapping.first(attrMappingIt));
-
- ResultSetBuffer::DataBufferIterator rsInfoIt;
- if (operationType == UtilPrepareReq::Read) {
- ndbrequire(prepPtr.p->prepOpPtr.p->rsInfo.first(rsInfoIt));
- }
-
- Uint32 noOfPKAttribsStored = 0;
- Uint32 noOfNonPKAttribsStored = 0;
- Uint32 attrLength = 0;
- Uint32 pkAttrLength = 0;
- char attrNameRequested[MAX_ATTR_NAME_SIZE];
- Uint32 attrIdRequested;
-
- while(prepPagesReader.next()) {
- UtilPrepareReq::KeyValue attributeKey =
- (UtilPrepareReq::KeyValue) prepPagesReader.getKey();
-
- ndbrequire((attributeKey == UtilPrepareReq::AttributeName) ||
- (attributeKey == UtilPrepareReq::AttributeId));
- if (attributeKey == UtilPrepareReq::AttributeName) {
- jam();
- ndbrequire(prepPagesReader.getValueLen() <= MAX_ATTR_NAME_SIZE);
-
- prepPagesReader.getString(attrNameRequested);
- attrIdRequested= ~0u;
- } else {
- jam();
- attrIdRequested = prepPagesReader.getUint32();
- }
- /*****************************************
- * Copy DictTabInfo into tableDesc struct
- *****************************************/
-
- SegmentedSectionPtr ptr;
- signal->getSection(ptr, GetTabInfoConf::DICT_TAB_INFO);
- SimplePropertiesSectionReader dictInfoReader(ptr, getSectionSegmentPool());
-
- SimpleProperties::UnpackStatus unpackStatus;
- unpackStatus = SimpleProperties::unpack(dictInfoReader, &tableDesc,
- DictTabInfo::TableMapping,
- DictTabInfo::TableMappingSize,
- true, true);
- ndbrequire(unpackStatus == SimpleProperties::Break);
-
- /************************
- * Lookup in DictTabInfo
- ************************/
- DictTabInfo::Attribute attrDesc; attrDesc.init();
- char attrName[MAX_ATTR_NAME_SIZE];
- Uint32 attrId= ~(Uint32)0;
- bool attributeFound = false;
- Uint32 noOfKeysFound = 0; // # PK attrs found before attr in DICTdata
- Uint32 noOfNonKeysFound = 0; // # nonPK attrs found before attr in DICTdata
- for (Uint32 i=0; i<tableDesc.NoOfAttributes; i++) {
- if (tableKey == UtilPrepareReq::TableName) {
- jam();
- ndbrequire(dictInfoReader.getKey() == DictTabInfo::AttributeName);
- ndbrequire(dictInfoReader.getValueLen() <= MAX_ATTR_NAME_SIZE);
- dictInfoReader.getString(attrName);
- attrId= ~(Uint32)0; // attrId not used
- } else { // (tableKey == UtilPrepareReq::TableId)
- jam();
- dictInfoReader.next(); // Skip name
- ndbrequire(dictInfoReader.getKey() == DictTabInfo::AttributeId);
- attrId = dictInfoReader.getUint32();
- attrName[0]= '\0'; // attrName not used
- }
- unpackStatus = SimpleProperties::unpack(dictInfoReader, &attrDesc,
- DictTabInfo::AttributeMapping,
- DictTabInfo::AttributeMappingSize,
- true, true);
- ndbrequire(unpackStatus == SimpleProperties::Break);
- //attrDesc.print(stdout);
-
- if (attrDesc.AttributeKeyFlag) { jam(); noOfKeysFound++; }
- else { jam(); noOfNonKeysFound++; }
- if (attributeKey == UtilPrepareReq::AttributeName) {
- if (strcmp(attrName, attrNameRequested) == 0) {
- attributeFound = true;
- break;
- }
- }
- else // (attributeKey == UtilPrepareReq::AttributeId)
- if (attrId == attrIdRequested) {
- attributeFound = true;
- break;
- }
-
- // Move to next attribute
- ndbassert(dictInfoReader.getKey() == DictTabInfo::AttributeEnd);
- dictInfoReader.next();
- }
-
- /**********************
- * Attribute not found
- **********************/
- if (!attributeFound) {
- jam();
- releaseSections(signal);
- sendUtilPrepareRef(signal,
- UtilPrepareRef::DICT_TAB_INFO_ERROR,
- prepPtr.p->clientRef, prepPtr.p->clientData);
- infoEvent("UTIL: Unknown attribute requested: %s in table: %s",
- attrNameRequested, tableName);
- releasePreparedOperation(prepOpPtr);
- releasePrepare(prepPtr);
- return;
- }
-
- /**************************************************************
- * Attribute found - store in mapping (AttributeId, Position)
- **************************************************************/
- AttributeHeader attrMap(attrDesc.AttributeId, // 1. Store AttrId
- 0);
-
- if (attrDesc.AttributeKeyFlag) {
- // ** Attribute belongs to PK **
- prepOpPtr.p->pkBitmask.set(attrDesc.AttributeId);
- attrMap.setDataSize(noOfKeysFound - 1); // 2. Store Position
- noOfPKAttribsStored++;
- } else {
- attrMap.setDataSize(0x3fff); // 2. Store Position (fake)
- noOfNonPKAttribsStored++;
-
- /***********************************************************
- * Error: Read nonPK Attr before all PK attr have been read
- ***********************************************************/
- if (noOfPKAttribsStored != tableDesc.NoOfKeyAttr) {
- jam();
- releaseSections(signal);
- sendUtilPrepareRef(signal,
- UtilPrepareRef::DICT_TAB_INFO_ERROR,
- prepPtr.p->clientRef, prepPtr.p->clientData);
- infoEvent("UTIL: Non-PK attr not allowed before "
- "all PK attrs have been defined, table: %s",
- tableName);
- releasePreparedOperation(prepOpPtr);
- releasePrepare(prepPtr);
- return;
- }
- }
- *(attrMappingIt.data) = attrMap.m_value;
-#if 0
- ndbout << "BEFORE: attrLength: " << attrLength << endl;
-#endif
- {
- int len = 0;
- switch (attrDesc.AttributeSize) {
- case DictTabInfo::an8Bit:
- len = (attrDesc.AttributeArraySize + 3)/ 4;
- break;
- case DictTabInfo::a16Bit:
- len = (attrDesc.AttributeArraySize + 1) / 2;
- break;
- case DictTabInfo::a32Bit:
- len = attrDesc.AttributeArraySize;
- break;
- case DictTabInfo::a64Bit:
- len = attrDesc.AttributeArraySize * 2;
- break;
- case DictTabInfo::a128Bit:
- len = attrDesc.AttributeArraySize * 4;
- break;
- }
- attrLength += len;
- if (attrDesc.AttributeKeyFlag)
- pkAttrLength += len;
-
- if (operationType == UtilPrepareReq::Read) {
- AttributeHeader::init(rsInfoIt.data,
- attrDesc.AttributeId, // 1. Store AttrId
- len << 2);
- prepOpPtr.p->rsInfo.next(rsInfoIt, 1);
- }
- }
-#if 0
- ndbout << ": AttributeSize: " << attrDesc.AttributeSize << endl;
- ndbout << ": AttributeArraySize: " << attrDesc.AttributeArraySize << endl;
- ndbout << "AFTER: attrLength: " << attrLength << endl;
-#endif
- //attrMappingIt.print(stdout);
- //prepPtr.p->prepOpPtr.p->attrMapping.print(stdout);
- prepPtr.p->prepOpPtr.p->attrMapping.next(attrMappingIt, 1);
- }
-
- /***************************
- * Error: Not all PKs found
- ***************************/
- if (noOfPKAttribsStored != tableDesc.NoOfKeyAttr) {
- jam();
- releaseSections(signal);
- sendUtilPrepareRef(signal,
- UtilPrepareRef::DICT_TAB_INFO_ERROR,
- prepPtr.p->clientRef, prepPtr.p->clientData);
- infoEvent("UTIL: Not all primary key attributes requested for table: %s",
- tableName);
- releasePreparedOperation(prepOpPtr);
- releasePrepare(prepPtr);
- return;
- }
-
-#if 0
- AttrMappingBuffer::ConstDataBufferIterator tmpIt;
- for (prepPtr.p->prepOpPtr.p->attrMapping.first(tmpIt); tmpIt.curr.i != RNIL;
- prepPtr.p->prepOpPtr.p->attrMapping.next(tmpIt)) {
- AttributeHeader* ah = (AttributeHeader *) tmpIt.data;
- ah->print(stdout);
- }
-#endif
-
- /**********************************************
- * Preparing of PreparedOperation signal train
- **********************************************/
- Uint32 static_len = TcKeyReq::StaticLength;
- prepOpPtr.p->tckey.tableId = tableDesc.TableId;
- prepOpPtr.p->tckey.tableSchemaVersion = tableDesc.TableVersion;
- prepOpPtr.p->noOfKeyAttr = tableDesc.NoOfKeyAttr;
- prepOpPtr.p->keyLen = tableDesc.KeyLength; // Total no of words in PK
- if (prepOpPtr.p->keyLen > TcKeyReq::MaxKeyInfo) {
- jam();
- prepOpPtr.p->tckeyLenInBytes = (static_len + TcKeyReq::MaxKeyInfo) * 4;
- } else {
- jam();
- prepOpPtr.p->tckeyLenInBytes = (static_len + prepOpPtr.p->keyLen) * 4;
- }
- prepOpPtr.p->keyDataPos = static_len; // Start of keyInfo[] in tckeyreq
-
- Uint32 requestInfo = 0;
- TcKeyReq::setAbortOption(requestInfo, TcKeyReq::AbortOnError);
- TcKeyReq::setKeyLength(requestInfo, tableDesc.KeyLength);
- switch(operationType) {
- case(UtilPrepareReq::Read):
- prepOpPtr.p->rsLen =
- attrLength +
- tableDesc.NoOfKeyAttr +
- noOfNonPKAttribsStored; // Read needs a resultset
- prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
- prepOpPtr.p->tckey.attrLen = prepOpPtr.p->noOfAttr;
- TcKeyReq::setOperationType(requestInfo, ZREAD);
- break;
- case(UtilPrepareReq::Update):
- prepOpPtr.p->rsLen = 0;
- prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
- prepOpPtr.p->tckey.attrLen = attrLength + prepOpPtr.p->noOfAttr;
- TcKeyReq::setOperationType(requestInfo, ZUPDATE);
- break;
- case(UtilPrepareReq::Insert):
- prepOpPtr.p->rsLen = 0;
- prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
- prepOpPtr.p->tckey.attrLen = attrLength + prepOpPtr.p->noOfAttr;
- TcKeyReq::setOperationType(requestInfo, ZINSERT);
- break;
- case(UtilPrepareReq::Delete):
- // The number of attributes should equal the size of the primary key
- ndbrequire(tableDesc.KeyLength == attrLength);
- prepOpPtr.p->rsLen = 0;
- prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr;
- prepOpPtr.p->tckey.attrLen = 0;
- TcKeyReq::setOperationType(requestInfo, ZDELETE);
- break;
- case(UtilPrepareReq::Write):
- prepOpPtr.p->rsLen = 0;
- prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
- prepOpPtr.p->tckey.attrLen = attrLength + prepOpPtr.p->noOfAttr;
- TcKeyReq::setOperationType(requestInfo, ZWRITE);
- break;
- }
- TcKeyReq::setAIInTcKeyReq(requestInfo, 0); // Attrinfo sent separately
- prepOpPtr.p->tckey.requestInfo = requestInfo;
-
- /****************************
- * Confirm completed prepare
- ****************************/
- UtilPrepareConf * conf = (UtilPrepareConf *)signal->getDataPtr();
- conf->senderData = prepPtr.p->clientData;
- conf->prepareId = prepPtr.p->prepOpPtr.i;
-
- releaseSections(signal);
- sendSignal(prepPtr.p->clientRef, GSN_UTIL_PREPARE_CONF, signal,
- UtilPrepareConf::SignalLength, JBB);
-
-#if 0
- prepPtr.p->prepOpPtr.p->print();
-#endif
- releasePrepare(prepPtr);
-}
-
-
-void
-DbUtil::execUTIL_RELEASE_REQ(Signal* signal){
- jamEntry();
-
- UtilReleaseReq * req = (UtilReleaseReq *)signal->getDataPtr();
- const Uint32 clientRef = signal->senderBlockRef();
- const Uint32 prepareId = req->prepareId;
- const Uint32 senderData = req->senderData;
-
-#if 0
- /**
- * This only works in when ARRAY_GUARD is defined (debug-mode)
- */
- if (!c_preparedOperationPool.isSeized(prepareId)) {
- UtilReleaseRef * ref = (UtilReleaseRef *)signal->getDataPtr();
- ref->prepareId = prepareId;
- ref->errorCode = UtilReleaseRef::NO_SUCH_PREPARE_SEIZED;
- sendSignal(clientRef, GSN_UTIL_RELEASE_REF, signal,
- UtilReleaseRef::SignalLength, JBB);
- }
-#endif
- PreparedOperationPtr prepOpPtr;
- c_preparedOperationPool.getPtr(prepOpPtr, prepareId);
-
- releasePreparedOperation(prepOpPtr);
-
- UtilReleaseConf * const conf = (UtilReleaseConf*)signal->getDataPtrSend();
- conf->senderData = senderData;
- sendSignal(clientRef, GSN_UTIL_RELEASE_CONF, signal,
- UtilReleaseConf::SignalLength, JBB);
-}
-
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Sequence Service
- * ------------------------------------------------------------------------
- *
- * A service with a stored incrementable number
- **************************************************************************/
-
-void
-DbUtil::hardcodedPrepare() {
- /**
- * Prepare SequenceCurrVal (READ)
- */
- {
- PreparedOperationPtr ptr;
- ndbrequire(c_preparedOperationPool.seizeId(ptr, 0));
- ptr.p->keyLen = 1;
- ptr.p->tckey.attrLen = 1;
- ptr.p->rsLen = 3;
- ptr.p->tckeyLenInBytes = (TcKeyReq::StaticLength +
- ptr.p->keyLen + ptr.p->tckey.attrLen) * 4;
- ptr.p->keyDataPos = TcKeyReq::StaticLength;
- ptr.p->tckey.tableId = 0;
- Uint32 requestInfo = 0;
- TcKeyReq::setAbortOption(requestInfo, TcKeyReq::CommitIfFailFree);
- TcKeyReq::setOperationType(requestInfo, ZREAD);
- TcKeyReq::setKeyLength(requestInfo, 1);
- TcKeyReq::setAIInTcKeyReq(requestInfo, 1);
- ptr.p->tckey.requestInfo = requestInfo;
- ptr.p->tckey.tableSchemaVersion = 1;
-
- // This is actually attr data
- AttributeHeader::init(&ptr.p->tckey.distrGroupHashValue, 1, 0);
-
- ndbrequire(ptr.p->rsInfo.seize(1));
- ResultSetInfoBuffer::DataBufferIterator it;
- ptr.p->rsInfo.first(it);
- AttributeHeader::init(it.data, 1, 2 << 2); // Attribute 1 - 2 data words
- }
-
- /**
- * Prepare SequenceNextVal (UPDATE)
- */
- {
- PreparedOperationPtr ptr;
- ndbrequire(c_preparedOperationPool.seizeId(ptr, 1));
- ptr.p->keyLen = 1;
- ptr.p->rsLen = 3;
- ptr.p->tckeyLenInBytes = (TcKeyReq::StaticLength + ptr.p->keyLen + 5) * 4;
- ptr.p->keyDataPos = TcKeyReq::StaticLength;
- ptr.p->tckey.attrLen = 11;
- ptr.p->tckey.tableId = 0;
- Uint32 requestInfo = 0;
- TcKeyReq::setAbortOption(requestInfo, TcKeyReq::CommitIfFailFree);
- TcKeyReq::setOperationType(requestInfo, ZUPDATE);
- TcKeyReq::setKeyLength(requestInfo, 1);
- TcKeyReq::setAIInTcKeyReq(requestInfo, 5);
- TcKeyReq::setInterpretedFlag(requestInfo, 1);
- ptr.p->tckey.requestInfo = requestInfo;
- ptr.p->tckey.tableSchemaVersion = 1;
-
- // Signal is packed, which is why attrInfo is at distrGroupHashValue
- // position
- Uint32 * attrInfo = &ptr.p->tckey.distrGroupHashValue;
- attrInfo[0] = 0; // IntialReadSize
- attrInfo[1] = 5; // InterpretedSize
- attrInfo[2] = 0; // FinalUpdateSize
- attrInfo[3] = 1; // FinalReadSize
- attrInfo[4] = 0; // SubroutineSize
-
- { // AttrInfo
- ndbrequire(ptr.p->attrInfo.seize(6));
- AttrInfoBuffer::DataBufferIterator it;
- ptr.p->attrInfo.first(it);
- * it.data = Interpreter::Read(1, 6);
- ndbrequire(ptr.p->attrInfo.next(it));
- * it.data = Interpreter::LoadConst16(7, 1);
- ndbrequire(ptr.p->attrInfo.next(it));
- * it.data = Interpreter::Add(7, 6, 7);
- ndbrequire(ptr.p->attrInfo.next(it));
- * it.data = Interpreter::Write(1, 7);
- ndbrequire(ptr.p->attrInfo.next(it));
- * it.data = Interpreter::ExitOK();
-
- ndbrequire(ptr.p->attrInfo.next(it));
- AttributeHeader::init(it.data, 1, 0);
- }
-
- { // ResultSet
- ndbrequire(ptr.p->rsInfo.seize(1));
- ResultSetInfoBuffer::DataBufferIterator it;
- ptr.p->rsInfo.first(it);
- AttributeHeader::init(it.data, 1, 2 << 2); // Attribute 1 - 2 data words
- }
- }
-
- /**
- * Prepare CreateSequence (INSERT)
- */
- {
- PreparedOperationPtr ptr;
- ndbrequire(c_preparedOperationPool.seizeId(ptr, 2));
- ptr.p->keyLen = 1;
- ptr.p->tckey.attrLen = 5;
- ptr.p->rsLen = 0;
- ptr.p->tckeyLenInBytes = (TcKeyReq::StaticLength +
- ptr.p->keyLen + ptr.p->tckey.attrLen) * 4;
- ptr.p->keyDataPos = TcKeyReq::StaticLength;
- ptr.p->tckey.tableId = 0;
- Uint32 requestInfo = 0;
- TcKeyReq::setAbortOption(requestInfo, TcKeyReq::CommitIfFailFree);
- TcKeyReq::setOperationType(requestInfo, ZINSERT);
- TcKeyReq::setKeyLength(requestInfo, 1);
- TcKeyReq::setAIInTcKeyReq(requestInfo, 0);
- ptr.p->tckey.requestInfo = requestInfo;
- ptr.p->tckey.tableSchemaVersion = 1;
- }
-}
-
-void
-DbUtil::execUTIL_SEQUENCE_REQ(Signal* signal){
- jamEntry();
-
- UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtr();
-
- PreparedOperation * prepOp;
-
- switch(req->requestType){
- case UtilSequenceReq::CurrVal:
- prepOp = c_preparedOperationPool.getPtr(0); //c_SequenceCurrVal
- break;
- case UtilSequenceReq::NextVal:
- prepOp = c_preparedOperationPool.getPtr(1); //c_SequenceNextVal
- break;
- case UtilSequenceReq::Create:
- prepOp = c_preparedOperationPool.getPtr(2); //c_CreateSequence
- break;
- default:
- ndbrequire(false);
- prepOp = 0; // remove warning
- }
-
- /**
- * 1 Transaction with 1 operation
- */
- TransactionPtr transPtr;
- ndbrequire(c_runningTransactions.seize(transPtr));
-
- OperationPtr opPtr;
- ndbrequire(transPtr.p->operations.seize(opPtr));
-
- ndbrequire(opPtr.p->rs.seize(prepOp->rsLen));
- ndbrequire(opPtr.p->keyInfo.seize(prepOp->keyLen));
-
- transPtr.p->gsn = GSN_UTIL_SEQUENCE_REQ;
- transPtr.p->clientRef = signal->senderBlockRef();
- transPtr.p->clientData = req->senderData;
- transPtr.p->sequence.sequenceId = req->sequenceId;
- transPtr.p->sequence.requestType = req->requestType;
-
- opPtr.p->prepOp = prepOp;
- opPtr.p->prepOp_i = RNIL;
-
- KeyInfoBuffer::DataBufferIterator it;
- opPtr.p->keyInfo.first(it);
- it.data[0] = transPtr.p->sequence.sequenceId;
-
- if(req->requestType == UtilSequenceReq::Create){
- ndbrequire(opPtr.p->attrInfo.seize(5));
- AttrInfoBuffer::DataBufferIterator it;
-
- opPtr.p->attrInfo.first(it);
- AttributeHeader::init(it.data, 0, 1 << 2);
-
- ndbrequire(opPtr.p->attrInfo.next(it));
- * it.data = transPtr.p->sequence.sequenceId;
-
- ndbrequire(opPtr.p->attrInfo.next(it));
- AttributeHeader::init(it.data, 1, 2 << 2);
-
- ndbrequire(opPtr.p->attrInfo.next(it));
- * it.data = 0;
-
- ndbrequire(opPtr.p->attrInfo.next(it));
- * it.data = 0;
- }
-
- runTransaction(signal, transPtr);
-}
-
-int
-DbUtil::getResultSet(Signal* signal, const Transaction * transP,
- struct LinearSectionPtr sectionsPtr[]) {
- OperationPtr opPtr;
- ndbrequire(transP->operations.first(opPtr));
- ndbrequire(transP->operations.hasNext(opPtr) == false);
-
- int noAttr = 0;
- int dataSz = 0;
- Uint32* tmpBuf = signal->theData + 25;
- const Uint32* headerBuffer = tmpBuf;
-
- const ResultSetBuffer & rs = opPtr.p->rs;
- ResultSetInfoBuffer::ConstDataBufferIterator it;
-
- // extract headers
- for(rs.first(it); it.curr.i != RNIL; ) {
- *tmpBuf++ = it.data[0];
- rs.next(it, ((AttributeHeader*)&it.data[0])->getDataSize() + 1);
- noAttr++;
- }
-
- if (noAttr == 0)
- return 0;
-
- const Uint32* dataBuffer = tmpBuf;
-
- // extract data
- for(rs.first(it); it.curr.i != RNIL; ) {
- int sz = ((AttributeHeader*)&it.data[0])->getDataSize();
- rs.next(it,1);
- for (int i = 0; i < sz; i++) {
- *tmpBuf++ = *it.data;
- rs.next(it,1);
- dataSz++;
- }
- }
-
- sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = (Uint32 *)headerBuffer;
- sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz = noAttr;
- sectionsPtr[UtilExecuteReq::DATA_SECTION].p = (Uint32 *)dataBuffer;
- sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataSz;
-
- return 1;
-}
-
-void
-DbUtil::reportSequence(Signal* signal, const Transaction * transP){
- OperationPtr opPtr;
- ndbrequire(transP->operations.first(opPtr));
- ndbrequire(transP->operations.hasNext(opPtr) == false);
-
- if(transP->errorCode == 0){
- jam(); // OK
-
- UtilSequenceConf * ret = (UtilSequenceConf *)signal->getDataPtrSend();
- ret->senderData = transP->clientData;
- ret->sequenceId = transP->sequence.sequenceId;
- ret->requestType = transP->sequence.requestType;
-
- bool ok = false;
- switch(transP->sequence.requestType){
- case UtilSequenceReq::CurrVal:
- case UtilSequenceReq::NextVal:{
- ok = true;
- ndbrequire(opPtr.p->rsRecv == 3);
-
- ResultSetBuffer::DataBufferIterator rsit;
- ndbrequire(opPtr.p->rs.first(rsit));
-
- ret->sequenceValue[0] = rsit.data[1];
- ret->sequenceValue[1] = rsit.data[2];
- break;
- }
- case UtilSequenceReq::Create:
- ok = true;
- ret->sequenceValue[0] = 0;
- ret->sequenceValue[1] = 0;
- break;
- }
- ndbrequire(ok);
- sendSignal(transP->clientRef, GSN_UTIL_SEQUENCE_CONF, signal,
- UtilSequenceConf::SignalLength, JBB);
- return;
- }
-
- UtilSequenceRef::ErrorCode errCode = UtilSequenceRef::TCError;
-
- switch(transP->sequence.requestType)
- {
- case UtilSequenceReq::CurrVal:
- case UtilSequenceReq::NextVal:{
- if (transP->errorCode == 626)
- errCode = UtilSequenceRef::NoSuchSequence;
- break;
- }
- case UtilSequenceReq::Create:
- break;
- }
-
- UtilSequenceRef * ret = (UtilSequenceRef *)signal->getDataPtrSend();
- ret->senderData = transP->clientData;
- ret->sequenceId = transP->sequence.sequenceId;
- ret->requestType = transP->sequence.requestType;
- ret->errorCode = (Uint32)errCode;
- sendSignal(transP->clientRef, GSN_UTIL_SEQUENCE_REF, signal,
- UtilSequenceRef::SignalLength, JBB);
-}
-#if 0
- Ndb ndb("ndb","def");
- NdbConnection* tConnection = ndb.startTransaction();
- NdbOperation* tOperation = tConnection->getNdbOperation("SYSTAB_0");
-
- //#if 0 && API_CODE
- if( tOperation != NULL ) {
- tOperation->interpretedUpdateTuple();
- tOperation->equal((U_Int32)0, keyValue );
- tNextId_Result = tOperation->getValue((U_Int32)1);
- tOperation->incValue((U_Int32)1, (U_Int32)8192);
-
- if (tConnection->execute( Commit ) != -1 ) {
- U_Int64 tValue = tNextId_Result->u_64_value(); // Read result value
- theFirstTransId = tValue;
- theLastTransId = tValue + 8191;
- closeTransaction(tConnection);
- return startTransactionLocal(aPriority, nodeId);
- }
- }
- /**
- * IntialReadSize = 0;
- * InterpretedSize = incValue(1);
- * FinalUpdateSize = 0;
- * FinalReadSize = 1; // Read value
- * SubroutineSize = 0;
- */
-#endif
-
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Transaction execution request
- * ------------------------------------------------------------------------
- *
- * Handle requests to execute a prepared transaction
- **************************************************************************/
-
-void
-DbUtil::execUTIL_EXECUTE_REQ(Signal* signal)
-{
- jamEntry();
-
- UtilExecuteReq * req = (UtilExecuteReq *)signal->getDataPtr();
- const Uint32 clientRef = req->senderRef;
- const Uint32 clientData = req->senderData;
- const Uint32 prepareId = req->getPrepareId();
- const bool releaseFlag = req->getReleaseFlag();
-
- if(signal->getNoOfSections() == 0) {
- // Missing prepare data
- jam();
- releaseSections(signal);
- sendUtilExecuteRef(signal, UtilExecuteRef::MissingDataSection,
- 0, clientRef, clientData);
- return;
- }
- /*******************************
- * Get PreparedOperation struct
- *******************************/
- PreparedOperationPtr prepOpPtr;
- c_preparedOperationPool.getPtr(prepOpPtr, prepareId);
-
- prepOpPtr.p->releaseFlag = releaseFlag;
-
- TransactionPtr transPtr;
- OperationPtr opPtr;
- SegmentedSectionPtr headerPtr, dataPtr;
-
- signal->getSection(headerPtr, UtilExecuteReq::HEADER_SECTION);
- SectionReader headerReader(headerPtr, getSectionSegmentPool());
- signal->getSection(dataPtr, UtilExecuteReq::DATA_SECTION);
- SectionReader dataReader(dataPtr, getSectionSegmentPool());
-
-#if 0 //def EVENT_DEBUG
- // Debugging
- printf("DbUtil::execUTIL_EXECUTEL_REQ: Headers (%u): ", headerPtr.sz);
- Uint32 word;
- while(headerReader.getWord(&word))
- printf("H'%.8x ", word);
- printf("\n");
- printf("DbUtil::execUTIL_EXECUTEL_REQ: Data (%u): ", dataPtr.sz);
- headerReader.reset();
- while(dataReader.getWord(&word))
- printf("H'%.8x ", word);
- printf("\n");
- dataReader.reset();
-#endif
-
-// Uint32 totalDataLen = headerPtr.sz + dataPtr.sz;
-
- /************************************************************
- * Seize Transaction record
- ************************************************************/
- ndbrequire(c_runningTransactions.seize(transPtr));
- transPtr.p->gsn = GSN_UTIL_EXECUTE_REQ;
- transPtr.p->clientRef = clientRef;
- transPtr.p->clientData = clientData;
- ndbrequire(transPtr.p->operations.seize(opPtr));
- opPtr.p->prepOp = prepOpPtr.p;
- opPtr.p->prepOp_i = prepOpPtr.i;
-
-#if 0 //def EVENT_DEBUG
- printf("opPtr.p->rs.seize( %u )\n", prepOpPtr.p->rsLen);
-#endif
- ndbrequire(opPtr.p->rs.seize(prepOpPtr.p->rsLen));
-
- /***********************************************************
- * Store signal data on linear memory in Transaction record
- ***********************************************************/
- KeyInfoBuffer* keyInfo = &opPtr.p->keyInfo;
- AttrInfoBuffer* attrInfo = &opPtr.p->attrInfo;
- AttributeHeader header;
- Uint32* tempBuf = signal->theData + 25;
- bool dataComplete = true;
-
- while(headerReader.getWord((Uint32 *)&header)) {
- Uint32* bufStart = tempBuf;
- header.insertHeader(tempBuf++);
- for(unsigned int i = 0; i < header.getDataSize(); i++) {
- if (!dataReader.getWord(tempBuf++)) {
- dataComplete = false;
- break;
- }
- }
- bool res = true;
-
-#if 0 //def EVENT_DEBUG
- if (TcKeyReq::getOperationType(prepOpPtr.p->tckey.requestInfo) ==
- TcKeyReq::Read) {
- if(prepOpPtr.p->pkBitmask.get(header.getAttributeId()))
- printf("PrimaryKey\n");
- }
- printf("AttrId %u Hdrsz %d Datasz %u \n",
- header.getAttributeId(),
- header.getHeaderSize(),
- header.getDataSize());
-#endif
-
- if(prepOpPtr.p->pkBitmask.get(header.getAttributeId()))
- // A primary key attribute
- res = keyInfo->append(bufStart + header.getHeaderSize(),
- header.getDataSize());
-
- switch (TcKeyReq::getOperationType(prepOpPtr.p->tckey.requestInfo)) {
- case ZREAD:
- res &= attrInfo->append(bufStart, header.getHeaderSize());
- break;
- case ZDELETE:
- // no attrinfo for Delete
- break;
- default:
- res &= attrInfo->append(bufStart,
- header.getHeaderSize() + header.getDataSize());
- }
-
- if (!res) {
- // Failed to allocate buffer data
- jam();
- releaseSections(signal);
- sendUtilExecuteRef(signal, UtilExecuteRef::AllocationError,
- 0, clientRef, clientData);
- releaseTransaction(transPtr);
- return;
- }
- }
- if (!dataComplete) {
- // Missing data in data section
- jam();
- releaseSections(signal);
- sendUtilExecuteRef(signal, UtilExecuteRef::MissingData,
- 0, clientRef, clientData);
- releaseTransaction(transPtr);
- return;
- }
-
- // quick hack for hash index build
- if (TcKeyReq::getOperationType(prepOpPtr.p->tckey.requestInfo) != ZREAD){
- prepOpPtr.p->tckey.attrLen =
- prepOpPtr.p->attrInfo.getSize() + opPtr.p->attrInfo.getSize();
- TcKeyReq::setKeyLength(prepOpPtr.p->tckey.requestInfo, keyInfo->getSize());
- }
-
-#if 0
- const Uint32 l1 = prepOpPtr.p->tckey.attrLen;
- const Uint32 l2 =
- prepOpPtr.p->attrInfo.getSize() + opPtr.p->attrInfo.getSize();
-
- if (TcKeyReq::getOperationType(prepOpPtr.p->tckey.requestInfo) != ZREAD){
- ndbrequire(l1 == l2);
- } else {
- ndbout_c("TcKeyReq::Read");
- }
-#endif
-
- releaseSections(signal);
- transPtr.p->noOfRetries = 3;
- runTransaction(signal, transPtr);
-}
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: General transaction machinery
- * ------------------------------------------------------------------------
- * Executes a prepared transaction
- **************************************************************************/
-void
-DbUtil::runTransaction(Signal* signal, TransactionPtr transPtr){
-
- /* Init transaction */
- transPtr.p->sent = 0;
- transPtr.p->recv = 0;
- transPtr.p->errorCode = 0;
- getTransId(transPtr.p);
-
- OperationPtr opPtr;
- ndbrequire(transPtr.p->operations.first(opPtr));
-
- /* First operation */
- Uint32 start = 0;
- TcKeyReq::setStartFlag(start, 1);
- runOperation(signal, transPtr, opPtr, start);
- transPtr.p->sent ++;
-
- /* Rest of operations */
- start = 0;
- while(opPtr.i != RNIL){
- runOperation(signal, transPtr, opPtr, start);
- transPtr.p->sent ++;
- }
- //transPtr.p->print();
-}
-
-void
-DbUtil::runOperation(Signal* signal, TransactionPtr & transPtr,
- OperationPtr & opPtr, Uint32 start) {
- Uint32 opI = opPtr.i;
- Operation * op = opPtr.p;
- const PreparedOperation * pop = op->prepOp;
-
- if(!transPtr.p->operations.next(opPtr)){
- TcKeyReq::setCommitFlag(start, 1); // Last operation
- TcKeyReq::setExecuteFlag(start, 1);
- }
-
-#if 0 //def EVENT_DEBUG
- if (TcKeyReq::getOperationType(pop->tckey.requestInfo) ==
- TcKeyReq::Read) {
- printf("TcKeyReq::Read runOperation\n");
- }
-#endif
-
- /**
- * Init operation w.r.t result set
- */
- initResultSet(op->rs, pop->rsInfo);
- op->rs.first(op->rsIterator);
- op->rsRecv = 0;
-#if 0 //def EVENT_DEBUG
- printf("pop->rsLen %u\n", pop->rsLen);
-#endif
- op->rsExpect = 0;
- op->transPtrI = transPtr.i;
-
- TcKeyReq * tcKey = (TcKeyReq*)signal->getDataPtrSend();
- //ndbout << "*** 6 ***"<< endl; pop->print();
- memcpy(tcKey, &pop->tckey, pop->tckeyLenInBytes);
- //ndbout << "*** 6b ***"<< endl;
- //printTCKEYREQ(stdout, signal->getDataPtrSend(),
- // pop->tckeyLenInBytes >> 2, 0);
- tcKey->apiConnectPtr = transPtr.p->connectPtr;
- tcKey->senderData = opI;
- tcKey->transId1 = transPtr.p->transId[0];
- tcKey->transId2 = transPtr.p->transId[1];
- tcKey->requestInfo |= start;
-
-#if 0 //def EVENT_DEBUG
- // Debugging
- printf("DbUtil::runOperation: KEYINFO\n");
- op->keyInfo.print(stdout);
- printf("DbUtil::runOperation: ATTRINFO\n");
- op->attrInfo.print(stdout);
-#endif
-
- /**
- * Key Info
- */
- //KeyInfoBuffer::DataBufferIterator kit;
- KeyInfoIterator kit;
- op->keyInfo.first(kit);
- Uint32 *keyDst = ((Uint32*)tcKey) + pop->keyDataPos;
- for(Uint32 i = 0; i<8 && kit.curr.i != RNIL; i++, op->keyInfo.next(kit)){
- keyDst[i] = * kit.data;
- }
- //ndbout << "*** 7 ***" << endl;
- //printTCKEYREQ(stdout, signal->getDataPtrSend(),
- // pop->tckeyLenInBytes >> 2, 0);
-
-#if 0 //def EVENT_DEBUG
- printf("DbUtil::runOperation: sendSignal(DBTC_REF, GSN_TCKEYREQ, signal, %d , JBB)\n", pop->tckeyLenInBytes >> 2);
- printTCKEYREQ(stdout, signal->getDataPtr(), pop->tckeyLenInBytes >> 2,0);
-#endif
- sendSignal(DBTC_REF, GSN_TCKEYREQ, signal, pop->tckeyLenInBytes >> 2, JBB);
-
- /**
- * More the 8 words of key info not implemented
- */
- // ndbrequire(kit.curr.i == RNIL); // Yes it is
-
- /**
- * KeyInfo
- */
- KeyInfo* keyInfo = (KeyInfo *)signal->getDataPtrSend();
- keyInfo->connectPtr = transPtr.p->connectPtr;
- keyInfo->transId[0] = transPtr.p->transId[0];
- keyInfo->transId[1] = transPtr.p->transId[1];
- sendKeyInfo(signal, keyInfo, op->keyInfo, kit);
-
- /**
- * AttrInfo
- */
- AttrInfo* attrInfo = (AttrInfo *)signal->getDataPtrSend();
- attrInfo->connectPtr = transPtr.p->connectPtr;
- attrInfo->transId[0] = transPtr.p->transId[0];
- attrInfo->transId[1] = transPtr.p->transId[1];
-
- AttrInfoIterator ait;
- pop->attrInfo.first(ait);
- sendAttrInfo(signal, attrInfo, pop->attrInfo, ait);
-
- op->attrInfo.first(ait);
- sendAttrInfo(signal, attrInfo, op->attrInfo, ait);
-}
-
-void
-DbUtil::sendKeyInfo(Signal* signal,
- KeyInfo* keyInfo,
- const KeyInfoBuffer & keyBuf,
- KeyInfoIterator & kit)
-{
- while(kit.curr.i != RNIL) {
- Uint32 *keyDst = keyInfo->keyData;
- Uint32 keyDataLen = 0;
- for(Uint32 i = 0; i<KeyInfo::DataLength && kit.curr.i != RNIL;
- i++, keyBuf.next(kit)){
- keyDst[i] = * kit.data;
- keyDataLen++;
- }
-#if 0 //def EVENT_DEBUG
- printf("DbUtil::sendKeyInfo: sendSignal(DBTC_REF, GSN_KEYINFO, signal, %d , JBB)\n", KeyInfo::HeaderLength + keyDataLen);
-#endif
- sendSignal(DBTC_REF, GSN_KEYINFO, signal,
- KeyInfo::HeaderLength + keyDataLen, JBB);
- }
-}
-
-void
-DbUtil::sendAttrInfo(Signal* signal,
- AttrInfo* attrInfo,
- const AttrInfoBuffer & attrBuf,
- AttrInfoIterator & ait)
-{
- while(ait.curr.i != RNIL) {
- Uint32 *attrDst = attrInfo->attrData;
- Uint32 i = 0;
- for(i = 0; i<AttrInfo::DataLength && ait.curr.i != RNIL;
- i++, attrBuf.next(ait)){
- attrDst[i] = * ait.data;
- }
-#if 0 //def EVENT_DEBUG
- printf("DbUtil::sendAttrInfo: sendSignal(DBTC_REF, GSN_ATTRINFO, signal, %d , JBB)\n", AttrInfo::HeaderLength + i);
-#endif
- sendSignal(DBTC_REF, GSN_ATTRINFO, signal,
- AttrInfo::HeaderLength + i, JBB);
- }
-}
-
-void
-DbUtil::initResultSet(ResultSetBuffer & rs,
- const ResultSetInfoBuffer & rsi){
-
- ResultSetBuffer::DataBufferIterator rsit;
- rs.first(rsit);
-
- ResultSetInfoBuffer::ConstDataBufferIterator rsiit;
- for(rsi.first(rsiit); rsiit.curr.i != RNIL; rsi.next(rsiit)){
- ndbrequire(rsit.curr.i != RNIL);
-
- rsit.data[0] = rsiit.data[0];
-#if 0 //def EVENT_DEBUG
- printf("Init resultset %u, sz %d\n",
- rsit.curr.i,
- ((AttributeHeader*)&rsit.data[0])->getDataSize() + 1);
-#endif
- rs.next(rsit, ((AttributeHeader*)&rsit.data[0])->getDataSize() + 1);
- }
-}
-
-void
-DbUtil::getTransId(Transaction * transP){
-
- Uint32 tmp[2];
- tmp[0] = c_transId[0];
- tmp[1] = c_transId[1];
-
- transP->transId[0] = tmp[0];
- transP->transId[1] = tmp[1];
-
- c_transId[1] = tmp[1] + 1;
-}
-
-
-
-/**************************************************************************
- * ------------------------------------------------------------------------
- * MODULE: Post Execute
- * ------------------------------------------------------------------------
- *
- * Handles result from a sent transaction
- **************************************************************************/
-
-/**
- * execTRANSID_AI
- *
- * Receive result from transaction
- *
- * NOTE: This codes assumes that
- * TransidAI::DataLength = ResultSetBuffer::getSegmentSize() * n
- */
-void
-DbUtil::execTRANSID_AI(Signal* signal){
- jamEntry();
-#if 0 //def EVENT_DEBUG
- ndbout_c("File: %s line: %u",__FILE__,__LINE__);
-#endif
-
- const Uint32 opI = signal->theData[0];
- const Uint32 transId1 = signal->theData[1];
- const Uint32 transId2 = signal->theData[2];
- const Uint32 dataLen = signal->length() - 3;
-
- Operation * opP = c_operationPool.getPtr(opI);
- TransactionPtr transPtr;
- c_runningTransactions.getPtr(transPtr, opP->transPtrI);
-
- ndbrequire(transId1 == transPtr.p->transId[0] &&
- transId2 == transPtr.p->transId[1]);
- opP->rsRecv += dataLen;
-
- /**
- * Save result
- */
- const Uint32 *src = &signal->theData[3];
- ResultSetBuffer::DataBufferIterator rs = opP->rsIterator;
-
- ndbrequire(opP->rs.import(rs,src,dataLen));
- opP->rs.next(rs, dataLen);
- opP->rsIterator = rs;
-
- if(!opP->complete()){
- jam();
- return;
- }
-
- transPtr.p->recv++;
- if(!transPtr.p->complete()){
- jam();
- return;
- }
-
- finishTransaction(signal, transPtr);
-}
-
-void
-DbUtil::execTCKEYCONF(Signal* signal){
- jamEntry();
-#if 0 //def EVENT_DEBUG
- ndbout_c("File: %s line: %u",__FILE__,__LINE__);
-#endif
-
- TcKeyConf * keyConf = (TcKeyConf*)signal->getDataPtr();
-
- //const Uint32 gci = keyConf->gci;
- const Uint32 transI = keyConf->apiConnectPtr >> 1;
- const Uint32 confInfo = keyConf->confInfo;
- const Uint32 transId1 = keyConf->transId1;
- const Uint32 transId2 = keyConf->transId2;
-
- Uint32 recv = 0;
- const Uint32 ops = TcKeyConf::getNoOfOperations(confInfo);
- for(Uint32 i = 0; i<ops; i++){
- OperationPtr opPtr;
- c_operationPool.getPtr(opPtr, keyConf->operations[i].apiOperationPtr);
-
- ndbrequire(opPtr.p->transPtrI == transI);
- opPtr.p->rsExpect += keyConf->operations[i].attrInfoLen;
- if(opPtr.p->complete()){
- recv++;
- }
- }
-
- /**
- * Check commit ack marker flag
- */
- if (TcKeyConf::getMarkerFlag(confInfo)){
- signal->theData[0] = transId1;
- signal->theData[1] = transId2;
- sendSignal(DBTC_REF, GSN_TC_COMMIT_ACK, signal, 2, JBB);
- }//if
-
- TransactionPtr transPtr;
- c_runningTransactions.getPtr(transPtr, transI);
- ndbrequire(transId1 == transPtr.p->transId[0] &&
- transId2 == transPtr.p->transId[1]);
-
- transPtr.p->recv += recv;
- if(!transPtr.p->complete()){
- jam();
- return;
- }
- finishTransaction(signal, transPtr);
-}
-
-void
-DbUtil::execTCKEYREF(Signal* signal){
- jamEntry();
-#if 0 //def EVENT_DEBUG
- ndbout_c("File: %s line: %u",__FILE__,__LINE__);
-#endif
-
- const Uint32 transI = signal->theData[0] >> 1;
- const Uint32 transId1 = signal->theData[1];
- const Uint32 transId2 = signal->theData[2];
- const Uint32 errCode = signal->theData[3];
-
- TransactionPtr transPtr;
- c_runningTransactions.getPtr(transPtr, transI);
- ndbrequire(transId1 == transPtr.p->transId[0] &&
- transId2 == transPtr.p->transId[1]);
-
- //if(getClassification(errCode) == PermanentError){
- //}
-
- //ndbout << "Transaction error (code: " << errCode << ")" << endl;
-
- transPtr.p->errorCode = errCode;
- finishTransaction(signal, transPtr);
-}
-
-void
-DbUtil::execTCROLLBACKREP(Signal* signal){
- jamEntry();
-#if 0 //def EVENT_DEBUG
- ndbout_c("File: %s line: %u",__FILE__,__LINE__);
-#endif
-
- const Uint32 transI = signal->theData[0] >> 1;
- const Uint32 transId1 = signal->theData[1];
- const Uint32 transId2 = signal->theData[2];
- const Uint32 errCode = signal->theData[3];
-
- TransactionPtr transPtr;
- c_runningTransactions.getPtr(transPtr, transI);
- ndbrequire(transId1 == transPtr.p->transId[0] &&
- transId2 == transPtr.p->transId[1]);
-
- //if(getClassification(errCode) == PermanentError){
- //}
-
-#if 0 //def EVENT_DEBUG
- ndbout << "Transaction error (code: " << errCode << ")" << endl;
-#endif
-
- if(transPtr.p->noOfRetries > 0){
- transPtr.p->noOfRetries--;
- switch(errCode){
- case 266:
- case 410:
- case 1204:
-#if 0
- ndbout_c("errCode: %d noOfRetries: %d -> retry",
- errCode, transPtr.p->noOfRetries);
-#endif
- runTransaction(signal, transPtr);
- return;
- }
- }
-
- transPtr.p->errorCode = errCode;
- finishTransaction(signal, transPtr);
-}
-
-void
-DbUtil::finishTransaction(Signal* signal, TransactionPtr transPtr){
-#if 0 //def EVENT_DEBUG
- ndbout_c("Transaction %x %x completed %s",
- transPtr.p->transId[0],
- transPtr.p->transId[1],
- transPtr.p->errorCode == 0 ? "OK" : "FAILED");
-#endif
-
- /*
- How to find the correct RS? Could we have multi-RS/transaction?
-
- Operation * opP = c_operationPool.getPtr(opI);
-
- ResultSetBuffer::DataBufferIterator rsit;
- ndbrequire(opP->rs.first(rsit));
- ndbout << "F Result: " << rsit.data << endl;
-
- while (opP->rs.next(rsit)) {
- ndbout << "R Result: " << rsit.data << endl;
- }
- */
-
- switch(transPtr.p->gsn){
- case GSN_UTIL_SEQUENCE_REQ:
- jam();
- reportSequence(signal, transPtr.p);
- break;
- case GSN_UTIL_EXECUTE_REQ:
- if (transPtr.p->errorCode) {
- UtilExecuteRef * ret = (UtilExecuteRef *)signal->getDataPtrSend();
- ret->senderData = transPtr.p->clientData;
- ret->errorCode = UtilExecuteRef::TCError;
- ret->TCErrorCode = transPtr.p->errorCode;
- sendSignal(transPtr.p->clientRef, GSN_UTIL_EXECUTE_REF, signal,
- UtilExecuteRef::SignalLength, JBB);
- } else {
- struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections];
- UtilExecuteConf * ret = (UtilExecuteConf *)signal->getDataPtrSend();
- ret->senderData = transPtr.p->clientData;
- if (getResultSet(signal, transPtr.p, sectionsPtr)) {
-#if 0 //def EVENT_DEBUG
- for (int j = 0; j < 2; j++) {
- printf("Result set %u %u\n", j,sectionsPtr[j].sz);
- for (int i=0; i < sectionsPtr[j].sz; i++)
- printf("H'%.8x ", sectionsPtr[j].p[i]);
- printf("\n");
- }
-#endif
- sendSignal(transPtr.p->clientRef, GSN_UTIL_EXECUTE_CONF, signal,
- UtilExecuteConf::SignalLength, JBB,
- sectionsPtr, UtilExecuteReq::NoOfSections);
- } else
- sendSignal(transPtr.p->clientRef, GSN_UTIL_EXECUTE_CONF, signal,
- UtilExecuteConf::SignalLength, JBB);
- }
- break;
- default:
- ndbrequire(0);
- break;
- }
- releaseTransaction(transPtr);
-}
-
-void
-DbUtil::execUTIL_LOCK_REQ(Signal * signal){
- jamEntry();
- UtilLockReq * req = (UtilLockReq*)signal->getDataPtr();
- const Uint32 lockId = req->lockId;
-
- LockQueuePtr lockQPtr;
- if(!c_lockQueues.find(lockQPtr, lockId)){
- jam();
- sendLOCK_REF(signal, req, UtilLockRef::NoSuchLock);
- return;
- }
-
-// const Uint32 requestInfo = req->requestInfo;
- const Uint32 senderNode = refToNode(req->senderRef);
- if(senderNode != getOwnNodeId() && senderNode != 0){
- jam();
- sendLOCK_REF(signal, req, UtilLockRef::DistributedLockNotSupported);
- return;
- }
-
- LocalDLFifoList<LockQueueElement> queue(c_lockElementPool,
- lockQPtr.p->m_queue);
- if(req->requestInfo & UtilLockReq::TryLock && !queue.isEmpty()){
- jam();
- sendLOCK_REF(signal, req, UtilLockRef::LockAlreadyHeld);
- return;
- }
-
- LockQueueElementPtr lockEPtr;
- if(!c_lockElementPool.seize(lockEPtr)){
- jam();
- sendLOCK_REF(signal, req, UtilLockRef::OutOfLockRecords);
- return;
- }
-
- lockEPtr.p->m_senderRef = req->senderRef;
- lockEPtr.p->m_senderData = req->senderData;
-
- if(queue.isEmpty()){
- jam();
- sendLOCK_CONF(signal, lockQPtr.p, lockEPtr.p);
- }
-
- queue.add(lockEPtr);
-}
-
-void
-DbUtil::execUTIL_UNLOCK_REQ(Signal* signal){
- jamEntry();
-
- UtilUnlockReq * req = (UtilUnlockReq*)signal->getDataPtr();
- const Uint32 lockId = req->lockId;
-
- LockQueuePtr lockQPtr;
- if(!c_lockQueues.find(lockQPtr, lockId)){
- jam();
- sendUNLOCK_REF(signal, req, UtilUnlockRef::NoSuchLock);
- return;
- }
-
- LocalDLFifoList<LockQueueElement> queue(c_lockElementPool,
- lockQPtr.p->m_queue);
- LockQueueElementPtr lockEPtr;
- if(!queue.first(lockEPtr)){
- jam();
- sendUNLOCK_REF(signal, req, UtilUnlockRef::NotLockOwner);
- return;
- }
-
- if(lockQPtr.p->m_lockKey != req->lockKey){
- jam();
- sendUNLOCK_REF(signal, req, UtilUnlockRef::NotLockOwner);
- return;
- }
-
- sendUNLOCK_CONF(signal, lockQPtr.p, lockEPtr.p);
- queue.release(lockEPtr);
-
- if(queue.first(lockEPtr)){
- jam();
- sendLOCK_CONF(signal, lockQPtr.p, lockEPtr.p);
- return;
- }
-}
-
-void
-DbUtil::sendLOCK_REF(Signal* signal,
- const UtilLockReq * req, UtilLockRef::ErrorCode err){
- const Uint32 senderData = req->senderData;
- const Uint32 senderRef = req->senderRef;
- const Uint32 lockId = req->lockId;
-
- UtilLockRef * ref = (UtilLockRef*)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->lockId = lockId;
- ref->errorCode = err;
- sendSignal(senderRef, GSN_UTIL_LOCK_REF, signal,
- UtilLockRef::SignalLength, JBB);
-}
-
-void
-DbUtil::sendLOCK_CONF(Signal* signal,
- LockQueue * lockQP,
- LockQueueElement * lockEP){
- const Uint32 senderData = lockEP->m_senderData;
- const Uint32 senderRef = lockEP->m_senderRef;
- const Uint32 lockId = lockQP->m_lockId;
- const Uint32 lockKey = ++lockQP->m_lockKey;
-
- UtilLockConf * conf = (UtilLockConf*)signal->getDataPtrSend();
- conf->senderData = senderData;
- conf->senderRef = reference();
- conf->lockId = lockId;
- conf->lockKey = lockKey;
- sendSignal(senderRef, GSN_UTIL_LOCK_CONF, signal,
- UtilLockConf::SignalLength, JBB);
-}
-
-void
-DbUtil::sendUNLOCK_REF(Signal* signal,
- const UtilUnlockReq* req, UtilUnlockRef::ErrorCode err){
-
- const Uint32 senderData = req->senderData;
- const Uint32 senderRef = req->senderRef;
- const Uint32 lockId = req->lockId;
-
- UtilUnlockRef * ref = (UtilUnlockRef*)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->lockId = lockId;
- ref->errorCode = err;
- sendSignal(senderRef, GSN_UTIL_UNLOCK_REF, signal,
- UtilUnlockRef::SignalLength, JBB);
-}
-
-void
-DbUtil::sendUNLOCK_CONF(Signal* signal,
- LockQueue * lockQP,
- LockQueueElement * lockEP){
- const Uint32 senderData = lockEP->m_senderData;
- const Uint32 senderRef = lockEP->m_senderRef;
- const Uint32 lockId = lockQP->m_lockId;
- ++lockQP->m_lockKey;
-
- UtilUnlockConf * conf = (UtilUnlockConf*)signal->getDataPtrSend();
- conf->senderData = senderData;
- conf->senderRef = reference();
- conf->lockId = lockId;
- sendSignal(senderRef, GSN_UTIL_UNLOCK_CONF, signal,
- UtilUnlockConf::SignalLength, JBB);
-}
-
-void
-DbUtil::execUTIL_CREATE_LOCK_REQ(Signal* signal){
- jamEntry();
- UtilCreateLockReq req = * (UtilCreateLockReq*)signal->getDataPtr();
-
- UtilCreateLockRef::ErrorCode err = UtilCreateLockRef::OK;
-
- do {
- LockQueuePtr lockQPtr;
- if(c_lockQueues.find(lockQPtr, req.lockId)){
- jam();
- err = UtilCreateLockRef::LockIdAlreadyUsed;
- break;
- }
-
- if(req.lockType != UtilCreateLockReq::Mutex){
- jam();
- err = UtilCreateLockRef::UnsupportedLockType;
- break;
- }
-
- if(!c_lockQueues.seize(lockQPtr)){
- jam();
- err = UtilCreateLockRef::OutOfLockQueueRecords;
- break;
- }
-
- new (lockQPtr.p) LockQueue(req.lockId);
- c_lockQueues.add(lockQPtr);
-
- UtilCreateLockConf * conf = (UtilCreateLockConf*)signal->getDataPtrSend();
- conf->senderData = req.senderData;
- conf->senderRef = reference();
- conf->lockId = req.lockId;
-
- sendSignal(req.senderRef, GSN_UTIL_CREATE_LOCK_CONF, signal,
- UtilCreateLockConf::SignalLength, JBB);
- return;
- } while(false);
-
- UtilCreateLockRef * ref = (UtilCreateLockRef*)signal->getDataPtrSend();
- ref->senderData = req.senderData;
- ref->senderRef = reference();
- ref->lockId = req.lockId;
- ref->errorCode = err;
-
- sendSignal(req.senderRef, GSN_UTIL_CREATE_LOCK_REF, signal,
- UtilCreateLockRef::SignalLength, JBB);
-}
-
-void
-DbUtil::execUTIL_DESTORY_LOCK_REQ(Signal* signal){
- jamEntry();
-
- UtilDestroyLockReq req = * (UtilDestroyLockReq*)signal->getDataPtr();
- UtilDestroyLockRef::ErrorCode err = UtilDestroyLockRef::OK;
- do {
- LockQueuePtr lockQPtr;
- if(!c_lockQueues.find(lockQPtr, req.lockId)){
- jam();
- err = UtilDestroyLockRef::NoSuchLock;
- break;
- }
-
- LocalDLFifoList<LockQueueElement> queue(c_lockElementPool,
- lockQPtr.p->m_queue);
- LockQueueElementPtr lockEPtr;
- if(!queue.first(lockEPtr)){
- jam();
- err = UtilDestroyLockRef::NotLockOwner;
- break;
- }
-
- if(lockQPtr.p->m_lockKey != req.lockKey){
- jam();
- err = UtilDestroyLockRef::NotLockOwner;
- break;
- }
-
- /**
- * OK
- */
-
- // Inform all in lock queue that queue has been destroyed
- UtilLockRef * ref = (UtilLockRef*)signal->getDataPtrSend();
- ref->lockId = req.lockId;
- ref->errorCode = UtilLockRef::NoSuchLock;
- ref->senderRef = reference();
- LockQueueElementPtr loopPtr = lockEPtr;
- for(queue.next(loopPtr); !loopPtr.isNull(); queue.next(loopPtr)){
- jam();
- ref->senderData = loopPtr.p->m_senderData;
- const Uint32 senderRef = loopPtr.p->m_senderRef;
- sendSignal(senderRef, GSN_UTIL_LOCK_REF, signal,
- UtilLockRef::SignalLength, JBB);
- }
- queue.release();
- c_lockQueues.release(lockQPtr);
-
- // Send Destroy conf
- UtilDestroyLockConf* conf=(UtilDestroyLockConf*)signal->getDataPtrSend();
- conf->senderData = req.senderData;
- conf->senderRef = reference();
- conf->lockId = req.lockId;
- sendSignal(req.senderRef, GSN_UTIL_DESTROY_LOCK_CONF, signal,
- UtilDestroyLockConf::SignalLength, JBB);
- return;
- } while(false);
-
- UtilDestroyLockRef * ref = (UtilDestroyLockRef*)signal->getDataPtrSend();
- ref->senderData = req.senderData;
- ref->senderRef = reference();
- ref->lockId = req.lockId;
- ref->errorCode = err;
- sendSignal(req.senderRef, GSN_UTIL_DESTROY_LOCK_REF, signal,
- UtilDestroyLockRef::SignalLength, JBB);
-}
-
-template class ArrayPool<DbUtil::Page32>;
diff --git a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
deleted file mode 100644
index 9f7b7202740..00000000000
--- a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
+++ /dev/null
@@ -1,485 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DBUTIL_H
-#define DBUTIL_H
-
-#include <ndb_limits.h>
-#include <SimulatedBlock.hpp>
-#include <NodeBitmask.hpp>
-
-#include <ArrayPool.hpp>
-#include <SLList.hpp>
-#include <DLList.hpp>
-#include <DLFifoList.hpp>
-#include <DataBuffer.hpp>
-#include <KeyTable.hpp>
-
-#include <signaldata/KeyInfo.hpp>
-#include <signaldata/AttrInfo.hpp>
-#include <signaldata/TcKeyReq.hpp>
-#include <signaldata/UtilPrepare.hpp>
-#include <signaldata/UtilExecute.hpp>
-#include <signaldata/UtilLock.hpp>
-#include <SimpleProperties.hpp>
-#include <Array.hpp>
-
-#define UTIL_WORDS_PER_PAGE 1023
-
-/**
- * @class DbUtil
- * @brief Database utilities
- *
- * This block implements transactional services which can be used by other
- * blocks.
- *
- * @section secSequence Module: The Sequence Service
- *
- * A sequence is a varaible stored in the database. Each time it is
- * requested with "NextVal" it returns a unique number. If requested
- * with "CurrVal" it returns the current number.
- *
- * - Request: SEQUENCE_REQ
- * Requests the 'NextVal' or 'CurrVal' for sequence variable 'sequenceId'.
- *
- * - Response: SEQUENCE_CONF / REF (if failure)
- * Returns value requested.
- */
-class DbUtil : public SimulatedBlock
-{
-public:
- DbUtil(Block_context& ctx);
- virtual ~DbUtil();
- BLOCK_DEFINES(DbUtil);
-
-protected:
- /**
- * Startup & Misc
- */
- void execREAD_CONFIG_REQ(Signal* signal);
- void execSTTOR(Signal* signal);
- void execNDB_STTOR(Signal* signal);
- void execDUMP_STATE_ORD(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- /**
- * Sequence Service : Public interface
- */
- void execUTIL_SEQUENCE_REQ(Signal* signal);
- void execUTIL_SEQUENCE_REF(Signal* signal);
- void execUTIL_SEQUENCE_CONF(Signal* signal);
-
- /**
- * Prepare Service : Public interface
- */
- void execUTIL_PREPARE_REQ(Signal* signal);
- void execUTIL_PREPARE_CONF(Signal* signal);
- void execUTIL_PREPARE_REF(Signal* signal);
-
- /**
- * Delete Service : Public interface
- */
- void execUTIL_DELETE_REQ(Signal* signal);
- void execUTIL_DELETE_REF(Signal* signal);
- void execUTIL_DELETE_CONF(Signal* signal);
-
- /**
- * Execute Service : Public interface
- */
- void execUTIL_EXECUTE_REQ(Signal* signal);
- void execUTIL_EXECUTE_REF(Signal* signal);
- void execUTIL_EXECUTE_CONF(Signal* signal);
-
- /**
- * Prepare Release Service : Public interface
- */
- void execUTIL_RELEASE_REQ(Signal* signal);
- void execUTIL_RELEASE_CONF(Signal* signal);
- void execUTIL_RELEASE_REF(Signal* signal);
-
- /**
- * Backend interface to a used TC service
- */
- void execTCSEIZECONF(Signal* signal);
- void execTCKEYCONF(Signal* signal);
- void execTCKEYREF(Signal* signal);
- void execTCROLLBACKREP(Signal* signal);
- void execTCKEY_FAILCONF(Signal* signal);
- void execTCKEY_FAILREF(Signal* signal);
- void execTRANSID_AI(Signal* signal);
-
- /**
- * Backend interface to a used DICT service
- */
- void execGET_TABINFOREF(Signal*);
- void execGET_TABINFO_CONF(Signal* signal);
-
-private:
-
-public:
- struct PreparedOperation;
-
- typedef DataBuffer<11> KeyInfoBuffer;
- typedef KeyInfoBuffer::ConstDataBufferIterator KeyInfoIterator;
- typedef DataBuffer<11> AttrInfoBuffer;
- typedef AttrInfoBuffer::ConstDataBufferIterator AttrInfoIterator;
- typedef DataBuffer<11> ResultSetBuffer;
- typedef DataBuffer<11> ResultSetInfoBuffer;
- typedef DataBuffer<1> AttrMappingBuffer;
-
- /**
- * @struct Page32
- * @brief For storing SimpleProperties objects and similar temporary data
- */
- struct Page32 {
- Uint32 data[UTIL_WORDS_PER_PAGE];
- Uint32 nextPool; // Note: This used as data when seized
- };
-
- /**
- * @struct Prepare
- * @brief Info regarding prepare request (contains a prepared operation)
- *
- * The prepare phase interprets the table and attribute names sent
- * in the prepare request from the client and asks DICT for meta
- * information.
- */
- struct Prepare {
- Prepare(ArrayPool<Page32> & ap) : preparePages(ap) {}
-
- /*** Client info ***/
- Uint32 clientRef;
- Uint32 clientData;
-
- /**
- * SimpleProp sent in UTIL_PREPARE_REQ
- *
- * Example format:
- * - UtilPrepareReq::NoOfOperations=1
- * - UtilPrepareReq::OperationType=UtilPrepareReq::Delete
- * - UtilPrepareReq::TableName="SYSTAB_0"
- * - UtilPrepareReq::AttributeName="SYSKEY_0"
- */
- Uint32 prepDataLen;
- Array<Page32> preparePages;
-
- /*** PreparedOperation constructed in Prepare phase ***/
- Ptr<PreparedOperation> prepOpPtr;
-
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
-
- void print() const {
- ndbout << "[-Prepare-" << endl
- << " clientRef: " << clientRef
- << ", clientData: " << clientData
- << "]" << endl;
- }
- };
-
- /**
- * @struct PreparedOperation
- * @brief Contains instantiated TcKeyReq signaldata for operation
- *
- * The prepare phase is finished by storing the request in a
- * PreparedOperation record.
- */
- struct PreparedOperation {
- PreparedOperation(AttrMappingBuffer::DataBufferPool & am,
- AttrInfoBuffer::DataBufferPool & ai,
- ResultSetInfoBuffer::DataBufferPool & rs) :
- releaseFlag(false), attrMapping(am), attrInfo(ai), rsInfo(rs)
- {
- pkBitmask.clear();
- }
-
- /*** Various Operation Info ***/
- Uint32 keyLen; // Length of primary key (fixed size is assumed)
- Uint32 rsLen; // Size of result set
- Uint32 noOfKeyAttr; // Number of key attributes
- Uint32 noOfAttr; // Number of attributes
- bool releaseFlag; // flag if operation release after completion
-
- /**
- * Attribute Mapping
- *
- * This datastructure (buffer of AttributeHeader:s) are used to map
- * each execute request to a TCKEYREQ train of signals.
- *
- * The datastructure contains (AttributeId, Position) pairs, where
- * - AttributeId is id used in database, and
- * - Position is position of attribute value in TCKEYREQ keyinfo
- * part of the train of signals which will be send to TC.
- * Position == 0x3fff means it should *not* be sent
- * in keyinfo part.
- */
- AttrMappingBuffer attrMapping;
-
- /*** First signal in tckeyreq train ***/
- Uint32 tckeyLenInBytes; // TcKeyReq total signal length (in bytes)
- Uint32 keyDataPos; // Where to store keydata[] in tckey signal
- // (in #words from base in tckey signal)
- TcKeyReq tckey; // Signaldata for first signal in train
-
- /*** Attrinfo signals sent to TC (part of tckeyreq train) ***/
- AttrInfoBuffer attrInfo;
-
- /*** Result of executed operation ***/
- ResultSetInfoBuffer rsInfo;
-
- Bitmask<MAX_ATTRIBUTES_IN_TABLE> pkBitmask;
-
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
-
- void print() const {
- ndbout << "[-PreparedOperation-" << endl
- << " keyLen: " << keyLen
- << ", rsLen: " << rsLen
- << ", noOfKeyAttr: " << noOfKeyAttr
- << ", noOfAttr: " << noOfAttr
- << ", tckeyLenInBytes: " << tckeyLenInBytes
- << ", keyDataPos: " << keyDataPos << endl
- << "-AttrMapping- (AttrId, KeyPos)-pairs "
- << "(Pos=3fff if non-key attr):" << endl;
- attrMapping.print(stdout);
- ndbout << "[-tckey- ";
- printTCKEYREQ(stdout, (Uint32*)&tckey, 8, 0);
- ndbout << "[-attrInfo- ";
- attrInfo.print(stdout);
- ndbout << "[-rsInfo- ";
- rsInfo.print(stdout);
- ndbout << "]]]]" << endl;
- }
- };
-
- /**
- * @struct Operation
- * @brief Used in execution (contains resultset and buffers for result)
- */
- struct Operation {
- Operation(KeyInfoBuffer::DataBufferPool & ki,
- AttrInfoBuffer::DataBufferPool & ai,
- ResultSetBuffer::DataBufferPool & _rs) :
- prepOp_i(RNIL), keyInfo(ki), attrInfo(ai), rs(_rs) {}
-
- PreparedOperation * prepOp;
- Uint32 prepOp_i;
- KeyInfoBuffer keyInfo;
- AttrInfoBuffer attrInfo;
- ResultSetBuffer rs;
- ResultSetBuffer::DataBufferIterator rsIterator;
-
- Uint32 transPtrI;
-
- Uint32 rsRecv;
- Uint32 rsExpect;
- inline bool complete() const { return rsRecv == rsExpect; }
-
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
-
- void print() const {
- ndbout << "[-Operation-" << endl
- << " transPtrI: " << transPtrI
- << ", rsRecv: " << rsRecv;
- ndbout << "[-PreparedOperation-" << endl;
- prepOp->print();
- ndbout << "[-keyInfo-" << endl;
- keyInfo.print(stdout);
- ndbout << "[-attrInfo-" << endl;
- attrInfo.print(stdout);
- ndbout << "]]" << endl;
- }
- };
-
- /**
- * @struct Transaction
- * @brief Used in execution (contains list of operations)
- */
- struct Transaction {
- Transaction(ArrayPool<Page32> & ap, ArrayPool<Operation> & op) :
- executePages(ap), operations(op) {}
-
- Uint32 clientRef;
- Uint32 clientData;
- Array<Page32> executePages;
-
- Uint32 gsn; // Request type (SEQUENCE, DELETE, etc)
- union {
- /**
- * Sequence transaction
- */
- struct {
- Uint32 sequenceId;
- Uint32 requestType;
- } sequence;
- };
-
- Uint32 connectPtr;
- Uint32 transId[2];
- SLList<Operation> operations;
-
- Uint32 errorCode;
- Uint32 noOfRetries;
- Uint32 sent; // No of operations sent
- Uint32 recv; // No of completed operations received
- inline bool complete() const { return sent == recv; };
-
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
-
- void print() const {
- ndbout << "[-Transaction-" << endl
- << " clientRef: " << clientRef
- << ", clientData: " << clientData
- << ", gsn: " << gsn
- << ", errorCode: " << errorCode
- << endl
- << " sent: " << sent << " operations"
- << ", recv: " << recv << " completed operations";
- OperationPtr opPtr;
- this->operations.first(opPtr);
- while(opPtr.i != RNIL){
- ndbout << "[-Operation-" << endl;
- opPtr.p->print();
- this->operations.next(opPtr);
- }
- ndbout << "]" << endl;
- }
- };
-
- typedef Ptr<Page32> Page32Ptr;
- typedef Ptr<Prepare> PreparePtr;
- typedef Ptr<Transaction> TransactionPtr;
- typedef Ptr<Operation> OperationPtr;
- typedef Ptr<PreparedOperation> PreparedOperationPtr;
-
- Uint32 c_transId[2];
- ArrayPool<Page32> c_pagePool;
- ArrayPool<Prepare> c_preparePool;
- ArrayPool<Operation> c_operationPool;
- ArrayPool<PreparedOperation> c_preparedOperationPool;
- ArrayPool<Transaction> c_transactionPool;
-
- DataBuffer<1>::DataBufferPool c_attrMappingPool;
- DataBuffer<11>::DataBufferPool c_dataBufPool;
- DLList<Prepare> c_runningPrepares;
- DLList<Transaction> c_seizingTransactions; // Being seized at TC
- DLList<Transaction> c_runningTransactions; // Seized and now exec.
-
- void getTransId(Transaction *);
- void initResultSet(ResultSetBuffer &, const ResultSetInfoBuffer &);
- void runTransaction(Signal* signal, TransactionPtr);
- void runOperation(Signal* signal, TransactionPtr &, OperationPtr &, Uint32);
- void sendKeyInfo(Signal* signal,
- KeyInfo* keyInfo,
- const KeyInfoBuffer & keyBuf,
- KeyInfoIterator & kit);
- void sendAttrInfo(Signal*,
- AttrInfo* attrInfo,
- const AttrInfoBuffer &,
- AttrInfoIterator & ait);
- int getResultSet(Signal* signal, const Transaction * transP,
- struct LinearSectionPtr sectionsPtr[]);
- void finishTransaction(Signal*, TransactionPtr);
- void releaseTransaction(TransactionPtr transPtr);
- void hardcodedPrepare();
- void connectTc(Signal* signal);
- void reportSequence(Signal*, const Transaction *);
- void readPrepareProps(Signal* signal,
- SimpleProperties::Reader* reader,
- Uint32 senderData);
- void prepareOperation(Signal*, PreparePtr);
- void sendUtilPrepareRef(Signal*, UtilPrepareRef::ErrorCode, Uint32, Uint32);
- void sendUtilExecuteRef(Signal*, UtilExecuteRef::ErrorCode,
- Uint32, Uint32, Uint32);
- void releasePrepare(PreparePtr);
- void releasePreparedOperation(PreparedOperationPtr);
-
- /***************************************************************************
- * Lock manager
- */
- struct LockQueueElement {
- Uint32 m_senderData;
- Uint32 m_senderRef;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- typedef Ptr<LockQueueElement> LockQueueElementPtr;
-
- struct LockQueue {
- LockQueue(){}
- LockQueue(Uint32 id) : m_queue() { m_lockId = id; m_lockKey = 0;}
- union {
- Uint32 m_lockId;
- Uint32 key;
- };
- Uint32 m_lockKey;
- DLFifoList<LockQueueElement>::Head m_queue;
- union {
- Uint32 nextHash;
- Uint32 nextPool;
- };
- Uint32 prevHash;
-
- Uint32 hashValue() const {
- return m_lockId;
- }
- bool equal(const LockQueue & rec) const {
- return m_lockId == rec.m_lockId;
- }
- };
- typedef Ptr<LockQueue> LockQueuePtr;
-
-
- ArrayPool<LockQueue> c_lockQueuePool;
- ArrayPool<LockQueueElement> c_lockElementPool;
- KeyTable<LockQueue> c_lockQueues;
-
- void execUTIL_CREATE_LOCK_REQ(Signal* signal);
- void execUTIL_DESTORY_LOCK_REQ(Signal* signal);
- void execUTIL_LOCK_REQ(Signal* signal);
- void execUTIL_UNLOCK_REQ(Signal* signal);
-
- void sendLOCK_REF(Signal*, const UtilLockReq * req, UtilLockRef::ErrorCode);
- void sendLOCK_CONF(Signal*, LockQueue *, LockQueueElement *);
-
- void sendUNLOCK_REF(Signal*, const UtilUnlockReq*, UtilUnlockRef::ErrorCode);
- void sendUNLOCK_CONF(Signal*, LockQueue *, LockQueueElement *);
-
- // For testing of mutex:es
- void mutex_created(Signal* signal, Uint32 mutexId, Uint32 retVal);
- void mutex_destroyed(Signal* signal, Uint32 mutexId, Uint32 retVal);
- void mutex_locked(Signal* signal, Uint32 mutexId, Uint32 retVal);
- void mutex_unlocked(Signal* signal, Uint32 mutexId, Uint32 retVal);
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.txt b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.txt
deleted file mode 100644
index cc8c1985009..00000000000
--- a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-UTIL Protocols
---------------
-Transactions are executed in two phases:
-1) PREPARE
-2) EXECUTE
-
-
-PREPARE PHASE
--------------
-1) ** REQUEST **
- Client (any block) requests prepare service from Util:
-
- Client --UTIL_PREPARE_REQ--> Util
- ...
- Client --UTIL_PREPARE_REQ--> Util
-
-2) ** DICTINFO **
- Util requests Dict for information about table:
-
- Util --GET_TABINFOREQ--> Dict
-
- Util <--DICTTABINFO-- Dict
- ...
- Util <--DICTTABINFO-- Dict
-
-3) ** PREPARE **
- Operation (= transaction) is prepared (DbUtil::prepareOperation)
-
- a) AttrMapping is created (a map used to read of the
- actual execute request attribute values and put them in KEYINFO)
-
- b) TC Signal train is prepared
-
-4) ** CONFIRM **
- Request is confirmed
-
- Client <--UTIL_PREPARE_CONF-- Util
-
-
-EXECUTE PHASE
--------------
-1) Client (any block) requests execute service from Util:
- (Execute can be INSERT, DELETE,...)
-
- Client --UTIL_EXECUTE_REQ--> Util (Multi-signals not yet implemented)
- ...
- Client --UTIL_EXECUTE_REQ--> Util
-
-2) Util --TCKEYREQ--> tc
-
- Util --KEYINFO--> tc (sometimes) (Not yet implemented)
- ...
- Util --KEYINFO--> tc
-
- Util --ATTRINFO--> tc (sometimes)
- ...
- Util --ATTRINFO--> tc
-
-3) Util <--TCKEYCONF-- tc
-
- Util --TC_COMMIT_ACK-->tc (sometimes)
-
- (in parallel with)
-
- Util <--TRANSID_AI-- tc (sometimes)
- ...
- Util <--TRANSID_AI-- tc
-
diff --git a/storage/ndb/src/kernel/blocks/diskpage.cpp b/storage/ndb/src/kernel/blocks/diskpage.cpp
deleted file mode 100644
index c782d1367d9..00000000000
--- a/storage/ndb/src/kernel/blocks/diskpage.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright (C) 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include <signaldata/SignalData.hpp>
-#include "diskpage.hpp"
-#include <NdbOut.hpp>
-#include <version.h>
-#include <time.h>
-
-void
-File_formats::Zero_page_header::init(File_type ft,
- Uint32 node_id,
- Uint32 version,
- Uint32 now)
-{
- memcpy(m_magic, "NDBDISK", 8);
- m_byte_order = 0x12345678;
- m_page_size = File_formats::NDB_PAGE_SIZE;
- m_ndb_version = version;
- m_node_id = node_id;
- m_file_type = ft;
- m_time = now;
-}
-
-int
-File_formats::Zero_page_header::validate(File_type ft,
- Uint32 node_id,
- Uint32 version,
- Uint32 now)
-{
- return 0; // TODO Check header
-}
-
-NdbOut&
-operator<<(NdbOut& out, const File_formats::Zero_page_header& obj)
-{
- char buf[256];
- out << "page size: " << obj.m_page_size << endl;
- out << "ndb version: " << obj.m_ndb_version << ", " <<
- ndbGetVersionString(obj.m_ndb_version, 0, buf, sizeof(buf)) << endl;
- out << "ndb node id: " << obj.m_node_id << endl;
- out << "file type: " << obj.m_file_type << endl;
- out << "time: " << obj.m_time << ", "
- << ctime((time_t*)&obj.m_time)<< endl;
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const File_formats::Datafile::Zero_page& obj)
-{
- out << obj.m_page_header << endl;
- out << "m_file_no: " << obj.m_file_no << endl;
- out << "m_tablespace_id: " << obj.m_tablespace_id << endl;
- out << "m_tablespace_version: " << obj.m_tablespace_version << endl;
- out << "m_data_pages: " << obj.m_data_pages << endl;
- out << "m_extent_pages: " << obj.m_extent_pages << endl;
- out << "m_extent_size: " << obj.m_extent_size << endl;
- out << "m_extent_count: " << obj.m_extent_count << endl;
- out << "m_extent_headers_per_page: " << obj.m_extent_headers_per_page << endl;
- out << "m_extent_header_words: " << obj.m_extent_header_words << endl;
- out << "m_extent_header_bits_per_page: " << obj.m_extent_header_bits_per_page << endl;
-
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const File_formats::Undofile::Zero_page& obj)
-{
- out << obj.m_page_header << endl;
- out << "m_file_id: " << obj.m_file_id << endl;
- out << "m_logfile_group_id: " << obj.m_logfile_group_id << endl;
- out << "m_logfile_group_version: " << obj.m_logfile_group_version << endl;
- out << "m_undo_pages: " << obj.m_undo_pages << endl;
-
- return out;
-}
-
diff --git a/storage/ndb/src/kernel/blocks/diskpage.hpp b/storage/ndb/src/kernel/blocks/diskpage.hpp
deleted file mode 100644
index 16098d39b45..00000000000
--- a/storage/ndb/src/kernel/blocks/diskpage.hpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef __NDB_DISKPAGE_HPP
-#define __NDB_DISKPAGE_HPP
-
-#include <ndb_types.h>
-
-struct File_formats
-{
- STATIC_CONST( NDB_PAGE_SIZE = 32768 );
- STATIC_CONST( NDB_PAGE_SIZE_WORDS = NDB_PAGE_SIZE >> 2);
-
- enum File_type
- {
- FT_Datafile = 0x1,
- FT_Undofile = 0x2
- };
-
- struct Page_header
- {
- Uint32 m_page_lsn_hi;
- Uint32 m_page_lsn_lo;
- Uint32 m_page_type;
- };
-
- enum Page_type
- {
- PT_Unallocated = 0x0,
- PT_Extent_page = 0x1,
- PT_Tup_fixsize_page = 0x2,
- PT_Tup_varsize_page = 0x3,
- PT_Undopage = 0x4
- };
-
- struct Zero_page_header
- {
- char m_magic[8];
- Uint32 m_byte_order;
- Uint32 m_page_size;
- Uint32 m_ndb_version;
- Uint32 m_node_id;
- Uint32 m_file_type;
- Uint32 m_time; // time(0)
- Zero_page_header() {}
- void init(File_type ft, Uint32 node_id, Uint32 version, Uint32 now);
- int validate(File_type ft, Uint32 node_id, Uint32 version, Uint32 now);
- };
-
- STATIC_CONST( NDB_PAGE_HEADER_WORDS = sizeof(Page_header) >> 2);
-
- struct Datafile
- {
- struct Zero_page
- {
- struct Zero_page_header m_page_header;
- Uint32 m_file_no; // Local_key
- Uint32 m_file_id; // DICT id
- Uint32 m_tablespace_id;
- Uint32 m_tablespace_version;
- Uint32 m_data_pages;
- Uint32 m_extent_pages;
- Uint32 m_extent_size;
- Uint32 m_extent_count;
- Uint32 m_extent_headers_per_page;
- Uint32 m_extent_header_words;
- Uint32 m_extent_header_bits_per_page;
- };
-
- struct Extent_header
- {
- Uint32 m_table;
- union
- {
- Uint32 m_fragment_id;
- Uint32 m_next_free_extent;
- };
- Extent_header() {}
- Uint32 m_page_bitmask[1]; // (BitsPerPage*ExtentSize)/(32*PageSize)
- Uint32 get_free_bits(Uint32 page) const;
- Uint32 get_free_word_offset(Uint32 page) const;
- void update_free_bits(Uint32 page, Uint32 bit);
- bool check_free(Uint32 extent_size) const ;
- };
-
- STATIC_CONST( EXTENT_HEADER_BITMASK_BITS_PER_PAGE = 4 );
- STATIC_CONST( EXTENT_HEADER_FIXED_WORDS = (sizeof(Extent_header)>>2) - 1);
- static Uint32 extent_header_words(Uint32 extent_size_in_pages);
-
- struct Extent_page
- {
- struct Page_header m_page_header;
- Extent_header m_extents[1];
-
- Extent_page() {}
- Extent_header* get_header(Uint32 extent_no, Uint32 extent_size);
- };
-
- STATIC_CONST( EXTENT_PAGE_WORDS = NDB_PAGE_SIZE_WORDS - NDB_PAGE_HEADER_WORDS );
-
- struct Data_page
- {
- struct Page_header m_page_header;
- };
- };
-
- struct Undofile
- {
- struct Zero_page
- {
- struct Zero_page_header m_page_header;
- Uint32 m_file_id;
- Uint32 m_logfile_group_id;
- Uint32 m_logfile_group_version;
- Uint32 m_undo_pages;
- };
- struct Undo_page
- {
- struct Page_header m_page_header;
- Uint32 m_words_used;
- Uint32 m_data[1];
- };
-
- struct Undo_entry
- {
- Uint32 m_file_no;
- Uint32 m_page_no;
- struct
- {
- Uint32 m_len_offset;
- Uint32 m_data[1];
- } m_changes[1];
- Uint32 m_length; // [ 16-bit type | 16 bit length of entry ]
- };
-
- enum Undo_type {
- UNDO_LCP_FIRST = 1 // First LCP record with specific lcp id
- ,UNDO_LCP = 2 // LCP Start
-
- /**
- * TUP Undo record
- */
- ,UNDO_TUP_ALLOC = 3
- ,UNDO_TUP_UPDATE = 4
- ,UNDO_TUP_FREE = 5
- ,UNDO_TUP_CREATE = 6
- ,UNDO_TUP_DROP = 7
- ,UNDO_TUP_ALLOC_EXTENT = 8
- ,UNDO_TUP_FREE_EXTENT = 9
-
- ,UNDO_END = 0x7FFF
- ,UNDO_NEXT_LSN = 0x8000
- };
-
- struct Undo_lcp
- {
- Uint32 m_lcp_id;
- Uint32 m_type_length; // 16 bit type, 16 bit length
- };
- };
- STATIC_CONST( UNDO_PAGE_WORDS = NDB_PAGE_SIZE_WORDS - NDB_PAGE_HEADER_WORDS - 1);
-};
-
-
-/**
- * Compute size of extent header in words
- */
-inline Uint32
-File_formats::Datafile::extent_header_words(Uint32 extent_size_in_pages)
-{
- return EXTENT_HEADER_FIXED_WORDS +
- ((extent_size_in_pages * EXTENT_HEADER_BITMASK_BITS_PER_PAGE + 31) >> 5);
-}
-
-inline
-File_formats::Datafile::Extent_header*
-File_formats::Datafile::Extent_page::get_header(Uint32 no, Uint32 extent_size)
-{
- Uint32 * tmp = (Uint32*)m_extents;
- tmp += no*File_formats::Datafile::extent_header_words(extent_size);
- return (Extent_header*)tmp;
-}
-
-inline
-Uint32
-File_formats::Datafile::Extent_header::get_free_bits(Uint32 page) const
-{
- return ((m_page_bitmask[page >> 3] >> ((page & 7) << 2))) & 15;
-}
-
-inline
-Uint32
-File_formats::Datafile::Extent_header::get_free_word_offset(Uint32 page) const
-{
- return page >> 3;
-}
-
-inline
-void
-File_formats::Datafile::Extent_header::update_free_bits(Uint32 page,
- Uint32 bit)
-{
- Uint32 shift = (page & 7) << 2;
- Uint32 mask = (15 << shift);
- Uint32 org = m_page_bitmask[page >> 3];
- m_page_bitmask[page >> 3] = (org & ~mask) | (bit << shift);
-}
-
-inline
-bool
-File_formats::Datafile::Extent_header::check_free(Uint32 extent_size) const
-{
- Uint32 words = (extent_size * EXTENT_HEADER_BITMASK_BITS_PER_PAGE + 31) >> 5;
- Uint32 sum = 0;
- for(; words; words--)
- sum |= m_page_bitmask[words-1];
-
- if(sum & 0x3333)
- return false;
-
- return true;
-}
-
-#include <NdbOut.hpp>
-NdbOut& operator<<(NdbOut& out, const File_formats::Zero_page_header&);
-NdbOut& operator<<(NdbOut& out, const File_formats::Datafile::Zero_page&);
-NdbOut& operator<<(NdbOut& out, const File_formats::Undofile::Zero_page&);
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/lgman.cpp b/storage/ndb/src/kernel/blocks/lgman.cpp
deleted file mode 100644
index cd3fc0d4fbb..00000000000
--- a/storage/ndb/src/kernel/blocks/lgman.cpp
+++ /dev/null
@@ -1,3209 +0,0 @@
-/*
- Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
-
- 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; version 2 of
- the License.
-
- 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#include "lgman.hpp"
-#include "diskpage.hpp"
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsCloseReq.hpp>
-#include <signaldata/CreateFilegroupImpl.hpp>
-#include <signaldata/DropFilegroupImpl.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-#include <signaldata/LCP.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <signaldata/LgmanContinueB.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include "ndbfs/Ndbfs.hpp"
-#include "dbtup/Dbtup.hpp"
-
-#include <EventLogger.hpp>
-extern EventLogger g_eventLogger;
-
-#include <record_types.hpp>
-
-/**
- * ---<a>-----<b>-----<c>-----<d>---> (time)
- *
- * <a> = start of lcp 1
- * <b> = stop of lcp 1
- * <c> = start of lcp 2
- * <d> = stop of lcp 2
- *
- * If ndb crashes before <d>
- * the entire undo log from crash point until <a> has to be applied
- *
- * at <d> the undo log can be cut til <c>
- */
-
-#define DEBUG_UNDO_EXECUTION 0
-#define DEBUG_SEARCH_LOG_HEAD 0
-
-Lgman::Lgman(Block_context & ctx) :
- SimulatedBlock(LGMAN, ctx),
- m_logfile_group_list(m_logfile_group_pool),
- m_logfile_group_hash(m_logfile_group_pool)
-{
- BLOCK_CONSTRUCTOR(Lgman);
-
- // Add received signals
- addRecSignal(GSN_STTOR, &Lgman::execSTTOR);
- addRecSignal(GSN_READ_CONFIG_REQ, &Lgman::execREAD_CONFIG_REQ);
- addRecSignal(GSN_DUMP_STATE_ORD, &Lgman::execDUMP_STATE_ORD);
- addRecSignal(GSN_CONTINUEB, &Lgman::execCONTINUEB);
-
- addRecSignal(GSN_CREATE_FILE_REQ, &Lgman::execCREATE_FILE_REQ);
- addRecSignal(GSN_CREATE_FILEGROUP_REQ, &Lgman::execCREATE_FILEGROUP_REQ);
-
- addRecSignal(GSN_DROP_FILE_REQ, &Lgman::execDROP_FILE_REQ);
- addRecSignal(GSN_DROP_FILEGROUP_REQ, &Lgman::execDROP_FILEGROUP_REQ);
-
- addRecSignal(GSN_FSWRITEREQ, &Lgman::execFSWRITEREQ);
- addRecSignal(GSN_FSWRITEREF, &Lgman::execFSWRITEREF, true);
- addRecSignal(GSN_FSWRITECONF, &Lgman::execFSWRITECONF);
-
- addRecSignal(GSN_FSOPENREF, &Lgman::execFSOPENREF, true);
- addRecSignal(GSN_FSOPENCONF, &Lgman::execFSOPENCONF);
-
- addRecSignal(GSN_FSCLOSECONF, &Lgman::execFSCLOSECONF);
-
- addRecSignal(GSN_FSREADREF, &Lgman::execFSREADREF, true);
- addRecSignal(GSN_FSREADCONF, &Lgman::execFSREADCONF);
-
- addRecSignal(GSN_LCP_FRAG_ORD, &Lgman::execLCP_FRAG_ORD);
- addRecSignal(GSN_END_LCP_REQ, &Lgman::execEND_LCP_REQ);
- addRecSignal(GSN_SUB_GCP_COMPLETE_REP, &Lgman::execSUB_GCP_COMPLETE_REP);
- addRecSignal(GSN_START_RECREQ, &Lgman::execSTART_RECREQ);
-
- addRecSignal(GSN_END_LCP_CONF, &Lgman::execEND_LCP_CONF);
-
- addRecSignal(GSN_GET_TABINFOREQ, &Lgman::execGET_TABINFOREQ);
-
- m_last_lsn = 1;
- m_logfile_group_hash.setSize(10);
-}
-
-Lgman::~Lgman()
-{
-}
-
-BLOCK_FUNCTIONS(Lgman)
-
-void
-Lgman::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Pool_context pc;
- pc.m_block = this;
- m_log_waiter_pool.wo_pool_init(RT_LGMAN_LOG_WAITER, pc);
- m_file_pool.init(RT_LGMAN_FILE, pc);
- m_logfile_group_pool.init(RT_LGMAN_FILEGROUP, pc);
- m_data_buffer_pool.setSize(10);
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
-void
-Lgman::execSTTOR(Signal* signal)
-{
- jamEntry();
- sendSTTORRY(signal);
-
- return;
-}//Lgman::execNDB_STTOR()
-
-void
-Lgman::sendSTTORRY(Signal* signal)
-{
- signal->theData[0] = 0;
- signal->theData[3] = 1;
- signal->theData[4] = 2;
- signal->theData[5] = 3;
- signal->theData[6] = 4;
- signal->theData[7] = 5;
- signal->theData[8] = 6;
- signal->theData[9] = 255; // No more start phases from missra
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 10, JBB);
-}
-
-void
-Lgman::execCONTINUEB(Signal* signal){
- jamEntry();
-
- Uint32 type= signal->theData[0];
- Uint32 ptrI = signal->theData[1];
- switch(type){
- case LgmanContinueB::FILTER_LOG:
- jam();
- break;
- case LgmanContinueB::CUT_LOG_TAIL:
- {
- jam();
- Ptr<Logfile_group> ptr;
- m_logfile_group_pool.getPtr(ptr, ptrI);
- cut_log_tail(signal, ptr);
- return;
- }
- case LgmanContinueB::FLUSH_LOG:
- {
- jam();
- Ptr<Logfile_group> ptr;
- m_logfile_group_pool.getPtr(ptr, ptrI);
- flush_log(signal, ptr, signal->theData[2]);
- return;
- }
- case LgmanContinueB::PROCESS_LOG_BUFFER_WAITERS:
- {
- jam();
- Ptr<Logfile_group> ptr;
- m_logfile_group_pool.getPtr(ptr, ptrI);
- process_log_buffer_waiters(signal, ptr);
- return;
- }
- case LgmanContinueB::FIND_LOG_HEAD:
- jam();
- Ptr<Logfile_group> ptr;
- if(ptrI != RNIL)
- {
- m_logfile_group_pool.getPtr(ptr, ptrI);
- find_log_head(signal, ptr);
- }
- else
- {
- init_run_undo_log(signal);
- }
- return;
- case LgmanContinueB::EXECUTE_UNDO_RECORD:
- jam();
- execute_undo_record(signal);
- return;
- case LgmanContinueB::STOP_UNDO_LOG:
- jam();
- stop_run_undo_log(signal);
- return;
- case LgmanContinueB::READ_UNDO_LOG:
- {
- jam();
- Ptr<Logfile_group> ptr;
- m_logfile_group_pool.getPtr(ptr, ptrI);
- read_undo_log(signal, ptr);
- return;
- }
- case LgmanContinueB::PROCESS_LOG_SYNC_WAITERS:
- {
- jam();
- Ptr<Logfile_group> ptr;
- m_logfile_group_pool.getPtr(ptr, ptrI);
- process_log_sync_waiters(signal, ptr);
- return;
- }
- case LgmanContinueB::FORCE_LOG_SYNC:
- {
- jam();
- Ptr<Logfile_group> ptr;
- m_logfile_group_pool.getPtr(ptr, ptrI);
- force_log_sync(signal, ptr, signal->theData[2], signal->theData[3]);
- return;
- }
- case LgmanContinueB::DROP_FILEGROUP:
- {
- jam();
- Ptr<Logfile_group> ptr;
- m_logfile_group_pool.getPtr(ptr, ptrI);
- if (ptr.p->m_state & Logfile_group::LG_THREAD_MASK)
- {
- jam();
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100,
- signal->length());
- return;
- }
- Uint32 ref = signal->theData[2];
- Uint32 data = signal->theData[3];
- drop_filegroup_drop_files(signal, ptr, ref, data);
- return;
- }
- }
-}
-
-void
-Lgman::execDUMP_STATE_ORD(Signal* signal){
- jamEntry();
- if(signal->theData[0] == 12001)
- {
- Ptr<Logfile_group> ptr;
- m_logfile_group_list.first(ptr);
- while(!ptr.isNull())
- {
- infoEvent("lfg %d state: %x fs: %d lsn "
- "[ last: %lld s(req): %lld s:ed: %lld lcp: %lld ] waiters: %d %d",
- ptr.p->m_logfile_group_id, ptr.p->m_state,
- ptr.p->m_outstanding_fs,
- ptr.p->m_last_lsn, ptr.p->m_last_sync_req_lsn,
- ptr.p->m_last_synced_lsn, ptr.p->m_last_lcp_lsn,
- !ptr.p->m_log_buffer_waiters.isEmpty(),
- !ptr.p->m_log_sync_waiters.isEmpty());
- if (!ptr.p->m_log_buffer_waiters.isEmpty())
- {
- Ptr<Log_waiter> waiter;
- Local_log_waiter_list
- list(m_log_waiter_pool, ptr.p->m_log_buffer_waiters);
- list.first(waiter);
- infoEvent(" free_buffer_words: %d head(waiters).sz: %d %d",
- ptr.p->m_free_buffer_words,
- waiter.p->m_size,
- 2*File_formats::UNDO_PAGE_WORDS);
- }
- if (!ptr.p->m_log_sync_waiters.isEmpty())
- {
- Ptr<Log_waiter> waiter;
- Local_log_waiter_list
- list(m_log_waiter_pool, ptr.p->m_log_sync_waiters);
- list.first(waiter);
- infoEvent(" m_last_synced_lsn: %lld head(waiters %x).m_sync_lsn: %lld",
- ptr.p->m_last_synced_lsn,
- waiter.i,
- waiter.p->m_sync_lsn);
-
- while(!waiter.isNull())
- {
- ndbout_c("ptr: %x %p lsn: %lld next: %x",
- waiter.i, waiter.p, waiter.p->m_sync_lsn, waiter.p->nextList);
- list.next(waiter);
- }
- }
- m_logfile_group_list.next(ptr);
- }
- }
-}
-
-void
-Lgman::execCREATE_FILEGROUP_REQ(Signal* signal){
- jamEntry();
- CreateFilegroupImplReq* req= (CreateFilegroupImplReq*)signal->getDataPtr();
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
-
- Ptr<Logfile_group> ptr;
- CreateFilegroupImplRef::ErrorCode err = CreateFilegroupImplRef::NoError;
- do {
- if (m_logfile_group_hash.find(ptr, req->filegroup_id))
- {
- jam();
- err = CreateFilegroupImplRef::FilegroupAlreadyExists;
- break;
- }
-
- if (!m_logfile_group_list.isEmpty())
- {
- jam();
- err = CreateFilegroupImplRef::OneLogfileGroupLimit;
- break;
- }
-
- if (!m_logfile_group_pool.seize(ptr))
- {
- jam();
- err = CreateFilegroupImplRef::OutOfFilegroupRecords;
- break;
- }
-
- new (ptr.p) Logfile_group(req);
-
- if (!alloc_logbuffer_memory(ptr, req->logfile_group.buffer_size))
- {
- jam();
- err= CreateFilegroupImplRef::OutOfLogBufferMemory;
- m_logfile_group_pool.release(ptr);
- break;
- }
-
- m_logfile_group_hash.add(ptr);
- m_logfile_group_list.add(ptr);
-
- if (getNodeState().getNodeRestartInProgress() ||
- getNodeState().getSystemRestartInProgress())
- {
- ptr.p->m_state = Logfile_group::LG_STARTING;
- }
-
- CreateFilegroupImplConf* conf=
- (CreateFilegroupImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILEGROUP_CONF, signal,
- CreateFilegroupImplConf::SignalLength, JBB);
-
- return;
- } while(0);
-
- CreateFilegroupImplRef* ref= (CreateFilegroupImplRef*)signal->getDataPtr();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->errorCode = err;
- sendSignal(senderRef, GSN_CREATE_FILEGROUP_REF, signal,
- CreateFilegroupImplRef::SignalLength, JBB);
-}
-
-void
-Lgman::execDROP_FILEGROUP_REQ(Signal* signal)
-{
- jamEntry();
-
- Uint32 errorCode = 0;
- DropFilegroupImplReq req = *(DropFilegroupImplReq*)signal->getDataPtr();
- do
- {
- Ptr<Logfile_group> ptr;
- if (!m_logfile_group_hash.find(ptr, req.filegroup_id))
- {
- errorCode = DropFilegroupImplRef::NoSuchFilegroup;
- break;
- }
-
- if (ptr.p->m_version != req.filegroup_version)
- {
- errorCode = DropFilegroupImplRef::InvalidFilegroupVersion;
- break;
- }
-
- switch(req.requestInfo){
- case DropFilegroupImplReq::Prepare:
- break;
- case DropFilegroupImplReq::Commit:
- m_logfile_group_list.remove(ptr);
- ptr.p->m_state |= Logfile_group::LG_DROPPING;
- signal->theData[0] = LgmanContinueB::DROP_FILEGROUP;
- signal->theData[1] = ptr.i;
- signal->theData[2] = req.senderRef;
- signal->theData[3] = req.senderData;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
- return;
- case DropFilegroupImplReq::Abort:
- break;
- default:
- ndbrequire(false);
- }
- } while(0);
-
- if (errorCode)
- {
- DropFilegroupImplRef* ref =
- (DropFilegroupImplRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = req.senderData;
- ref->errorCode = errorCode;
- sendSignal(req.senderRef, GSN_DROP_FILEGROUP_REF, signal,
- DropFilegroupImplRef::SignalLength, JBB);
- }
- else
- {
- DropFilegroupImplConf* conf =
- (DropFilegroupImplConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = req.senderData;
- sendSignal(req.senderRef, GSN_DROP_FILEGROUP_CONF, signal,
- DropFilegroupImplConf::SignalLength, JBB);
- }
-}
-
-void
-Lgman::drop_filegroup_drop_files(Signal* signal,
- Ptr<Logfile_group> ptr,
- Uint32 ref, Uint32 data)
-{
- jam();
- ndbrequire(! (ptr.p->m_state & Logfile_group::LG_THREAD_MASK));
- ndbrequire(ptr.p->m_outstanding_fs == 0);
-
- Local_undofile_list list(m_file_pool, ptr.p->m_files);
- Ptr<Undofile> file_ptr;
-
- if (list.first(file_ptr))
- {
- jam();
- ndbrequire(! (file_ptr.p->m_state & Undofile::FS_OUTSTANDING));
- file_ptr.p->m_create.m_senderRef = ref;
- file_ptr.p->m_create.m_senderData = data;
- create_file_abort(signal, ptr, file_ptr);
- return;
- }
-
- Local_undofile_list metalist(m_file_pool, ptr.p->m_meta_files);
- if (metalist.first(file_ptr))
- {
- jam();
- metalist.remove(file_ptr);
- list.add(file_ptr);
- file_ptr.p->m_create.m_senderRef = ref;
- file_ptr.p->m_create.m_senderData = data;
- create_file_abort(signal, ptr, file_ptr);
- return;
- }
-
- free_logbuffer_memory(ptr);
- m_logfile_group_hash.release(ptr);
- DropFilegroupImplConf *conf = (DropFilegroupImplConf*)signal->getDataPtr();
- conf->senderData = data;
- conf->senderRef = reference();
- sendSignal(ref, GSN_DROP_FILEGROUP_CONF, signal,
- DropFilegroupImplConf::SignalLength, JBB);
-}
-
-void
-Lgman::execCREATE_FILE_REQ(Signal* signal)
-{
- jamEntry();
- CreateFileImplReq* req= (CreateFileImplReq*)signal->getDataPtr();
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- Uint32 requestInfo = req->requestInfo;
-
- Ptr<Logfile_group> ptr;
- CreateFileImplRef::ErrorCode err = CreateFileImplRef::NoError;
- do {
- if (!m_logfile_group_hash.find(ptr, req->filegroup_id))
- {
- jam();
- err = CreateFileImplRef::InvalidFilegroup;
- break;
- }
-
- if (ptr.p->m_version != req->filegroup_version)
- {
- jam();
- err = CreateFileImplRef::InvalidFilegroupVersion;
- break;
- }
-
- Ptr<Undofile> file_ptr;
- switch(requestInfo){
- case CreateFileImplReq::Commit:
- {
- jam();
- ndbrequire(find_file_by_id(file_ptr, ptr.p->m_meta_files, req->file_id));
- file_ptr.p->m_create.m_senderRef = req->senderRef;
- file_ptr.p->m_create.m_senderData = req->senderData;
- create_file_commit(signal, ptr, file_ptr);
- return;
- }
- case CreateFileImplReq::Abort:
- {
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- if (find_file_by_id(file_ptr, ptr.p->m_meta_files, req->file_id))
- {
- jam();
- file_ptr.p->m_create.m_senderRef = senderRef;
- file_ptr.p->m_create.m_senderData = senderData;
- create_file_abort(signal, ptr, file_ptr);
- }
- else
- {
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- jam();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
- }
- return;
- }
- default: // prepare
- break;
- }
-
- if (!m_file_pool.seize(file_ptr))
- {
- jam();
- err = CreateFileImplRef::OutOfFileRecords;
- break;
- }
-
- if(ERROR_INSERTED(15000) ||
- (sizeof(void*) == 4 && req->file_size_hi & 0xFFFFFFFF))
- {
- jam();
- if(signal->getNoOfSections())
- releaseSections(signal);
-
- CreateFileImplRef* ref= (CreateFileImplRef*)signal->getDataPtr();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->errorCode = CreateFileImplRef::FileSizeTooLarge;
- sendSignal(senderRef, GSN_CREATE_FILE_REF, signal,
- CreateFileImplRef::SignalLength, JBB);
- return;
- }
-
- new (file_ptr.p) Undofile(req, ptr.i);
-
- Local_undofile_list tmp(m_file_pool, ptr.p->m_meta_files);
- tmp.add(file_ptr);
-
- open_file(signal, file_ptr, req->requestInfo);
- return;
- } while(0);
-
- CreateFileImplRef* ref= (CreateFileImplRef*)signal->getDataPtr();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->errorCode = err;
- sendSignal(senderRef, GSN_CREATE_FILE_REF, signal,
- CreateFileImplRef::SignalLength, JBB);
-}
-
-void
-Lgman::open_file(Signal* signal, Ptr<Undofile> ptr, Uint32 requestInfo)
-{
- FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
- req->userReference = reference();
- req->userPointer = ptr.i;
-
- memset(req->fileNumber, 0, sizeof(req->fileNumber));
- FsOpenReq::setVersion(req->fileNumber, 4); // Version 4 = specified filename
-
- req->fileFlags = 0;
- req->fileFlags |= FsOpenReq::OM_READWRITE;
- req->fileFlags |= FsOpenReq::OM_DIRECT;
- req->fileFlags |= FsOpenReq::OM_SYNC;
- switch(requestInfo){
- case CreateFileImplReq::Create:
- req->fileFlags |= FsOpenReq::OM_CREATE_IF_NONE;
- req->fileFlags |= FsOpenReq::OM_INIT;
- ptr.p->m_state = Undofile::FS_CREATING;
- break;
- case CreateFileImplReq::CreateForce:
- req->fileFlags |= FsOpenReq::OM_CREATE;
- req->fileFlags |= FsOpenReq::OM_INIT;
- ptr.p->m_state = Undofile::FS_CREATING;
- break;
- case CreateFileImplReq::Open:
- req->fileFlags |= FsOpenReq::OM_CHECK_SIZE;
- ptr.p->m_state = Undofile::FS_OPENING;
- break;
- default:
- ndbrequire(false);
- }
-
- req->page_size = File_formats::NDB_PAGE_SIZE;
- Uint64 size = (Uint64)ptr.p->m_file_size * (Uint64)File_formats::NDB_PAGE_SIZE;
- req->file_size_hi = size >> 32;
- req->file_size_lo = size & 0xFFFFFFFF;
-
- // Forward filename
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBB);
-}
-
-void
-Lgman::execFSWRITEREQ(Signal* signal)
-{
- jamEntry();
- Ptr<Undofile> ptr;
- Ptr<GlobalPage> page_ptr;
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtr();
-
- m_file_pool.getPtr(ptr, req->userPointer);
- m_global_page_pool.getPtr(page_ptr, req->data.pageData[0]);
-
- if (req->varIndex == 0)
- {
- jam();
- File_formats::Undofile::Zero_page* page =
- (File_formats::Undofile::Zero_page*)page_ptr.p;
- page->m_page_header.init(File_formats::FT_Undofile,
- getOwnNodeId(),
- ndbGetOwnVersion(),
- time(0));
- page->m_file_id = ptr.p->m_file_id;
- page->m_logfile_group_id = ptr.p->m_create.m_logfile_group_id;
- page->m_logfile_group_version = ptr.p->m_create.m_logfile_group_version;
- page->m_undo_pages = ptr.p->m_file_size - 1; // minus zero page
- }
- else
- {
- jam();
- File_formats::Undofile::Undo_page* page =
- (File_formats::Undofile::Undo_page*)page_ptr.p;
- page->m_page_header.m_page_lsn_hi = 0;
- page->m_page_header.m_page_lsn_lo = 0;
- page->m_page_header.m_page_type = File_formats::PT_Undopage;
- page->m_words_used = 0;
- }
-}
-
-void
-Lgman::execFSOPENREF(Signal* signal)
-{
- jamEntry();
-
- Ptr<Undofile> ptr;
- Ptr<Logfile_group> lg_ptr;
- FsRef* ref = (FsRef*)signal->getDataPtr();
-
- Uint32 errCode = ref->errorCode;
- Uint32 osErrCode = ref->osErrorCode;
-
- m_file_pool.getPtr(ptr, ref->userPointer);
- m_logfile_group_pool.getPtr(lg_ptr, ptr.p->m_logfile_group_ptr_i);
-
- {
- CreateFileImplRef* ref= (CreateFileImplRef*)signal->getDataPtr();
- ref->senderData = ptr.p->m_create.m_senderData;
- ref->senderRef = reference();
- ref->errorCode = CreateFileImplRef::FileError;
- ref->fsErrCode = errCode;
- ref->osErrCode = osErrCode;
- sendSignal(ptr.p->m_create.m_senderRef, GSN_CREATE_FILE_REF, signal,
- CreateFileImplRef::SignalLength, JBB);
- }
-
- Local_undofile_list meta(m_file_pool, lg_ptr.p->m_meta_files);
- meta.release(ptr);
-}
-
-#define HEAD 0
-#define TAIL 1
-
-void
-Lgman::execFSOPENCONF(Signal* signal)
-{
- jamEntry();
- Ptr<Undofile> ptr;
-
- FsConf* conf = (FsConf*)signal->getDataPtr();
-
- Uint32 fd = conf->filePointer;
- m_file_pool.getPtr(ptr, conf->userPointer);
-
- ptr.p->m_fd = fd;
-
- {
- Uint32 senderRef = ptr.p->m_create.m_senderRef;
- Uint32 senderData = ptr.p->m_create.m_senderData;
-
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
- }
-}
-
-bool
-Lgman::find_file_by_id(Ptr<Undofile>& ptr,
- Local_undofile_list::Head& head, Uint32 id)
-{
- Local_undofile_list list(m_file_pool, head);
- for(list.first(ptr); !ptr.isNull(); list.next(ptr))
- if(ptr.p->m_file_id == id)
- return true;
- return false;
-}
-
-void
-Lgman::create_file_commit(Signal* signal,
- Ptr<Logfile_group> lg_ptr,
- Ptr<Undofile> ptr)
-{
- Uint32 senderRef = ptr.p->m_create.m_senderRef;
- Uint32 senderData = ptr.p->m_create.m_senderData;
-
- bool first= false;
- if(ptr.p->m_state == Undofile::FS_CREATING &&
- (lg_ptr.p->m_state & Logfile_group::LG_ONLINE))
- {
- jam();
- Local_undofile_list free(m_file_pool, lg_ptr.p->m_files);
- Local_undofile_list meta(m_file_pool, lg_ptr.p->m_meta_files);
- first= free.isEmpty();
- meta.remove(ptr);
- if(!first)
- {
- /**
- * Add log file next after current head
- */
- Ptr<Undofile> curr;
- m_file_pool.getPtr(curr, lg_ptr.p->m_file_pos[HEAD].m_ptr_i);
- if(free.next(curr))
- free.insert(ptr, curr); // inserts before (that's why the extra next)
- else
- free.add(ptr);
-
- ptr.p->m_state = Undofile::FS_ONLINE | Undofile::FS_EMPTY;
- }
- else
- {
- /**
- * First file isn't empty as it can be written to at any time
- */
- free.add(ptr);
- ptr.p->m_state = Undofile::FS_ONLINE;
- lg_ptr.p->m_state |= Logfile_group::LG_FLUSH_THREAD;
- signal->theData[0] = LgmanContinueB::FLUSH_LOG;
- signal->theData[1] = lg_ptr.i;
- signal->theData[2] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- }
- }
- else
- {
- ptr.p->m_state = Undofile::FS_SORTING;
- }
-
- ptr.p->m_online.m_lsn = 0;
- ptr.p->m_online.m_outstanding = 0;
-
- Uint64 add= ptr.p->m_file_size - 1;
- lg_ptr.p->m_free_file_words += add * File_formats::UNDO_PAGE_WORDS;
-
- if(first)
- {
- jam();
-
- Buffer_idx tmp= { ptr.i, 0 };
- lg_ptr.p->m_file_pos[HEAD] = lg_ptr.p->m_file_pos[TAIL] = tmp;
-
- /**
- * Init log tail pointer
- */
- lg_ptr.p->m_tail_pos[0] = tmp;
- lg_ptr.p->m_tail_pos[1] = tmp;
- lg_ptr.p->m_tail_pos[2] = tmp;
- lg_ptr.p->m_next_reply_ptr_i = ptr.i;
- }
-
- validate_logfile_group(lg_ptr, "create_file_commit");
-
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
-}
-
-void
-Lgman::create_file_abort(Signal* signal,
- Ptr<Logfile_group> lg_ptr,
- Ptr<Undofile> ptr)
-{
- if (ptr.p->m_fd == RNIL)
- {
- ((FsConf*)signal->getDataPtr())->userPointer = ptr.i;
- execFSCLOSECONF(signal);
- return;
- }
-
- FsCloseReq *req= (FsCloseReq*)signal->getDataPtrSend();
- req->filePointer = ptr.p->m_fd;
- req->userReference = reference();
- req->userPointer = ptr.i;
- req->fileFlag = 0;
- FsCloseReq::setRemoveFileFlag(req->fileFlag, true);
-
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal,
- FsCloseReq::SignalLength, JBB);
-}
-
-void
-Lgman::execFSCLOSECONF(Signal* signal)
-{
- Ptr<Undofile> ptr;
- Ptr<Logfile_group> lg_ptr;
- Uint32 ptrI = ((FsConf*)signal->getDataPtr())->userPointer;
- m_file_pool.getPtr(ptr, ptrI);
-
- Uint32 senderRef = ptr.p->m_create.m_senderRef;
- Uint32 senderData = ptr.p->m_create.m_senderData;
-
- m_logfile_group_pool.getPtr(lg_ptr, ptr.p->m_logfile_group_ptr_i);
-
- if (lg_ptr.p->m_state & Logfile_group::LG_DROPPING)
- {
- jam();
- {
- Local_undofile_list list(m_file_pool, lg_ptr.p->m_files);
- list.release(ptr);
- }
- drop_filegroup_drop_files(signal, lg_ptr, senderRef, senderData);
- }
- else
- {
- jam();
- Local_undofile_list list(m_file_pool, lg_ptr.p->m_meta_files);
- list.release(ptr);
-
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
- }
-}
-
-void
-Lgman::execDROP_FILE_REQ(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}
-
-#define CONSUMER 0
-#define PRODUCER 1
-
-Lgman::Logfile_group::Logfile_group(const CreateFilegroupImplReq* req)
-{
- m_logfile_group_id = req->filegroup_id;
- m_version = req->filegroup_version;
- m_state = LG_ONLINE;
- m_outstanding_fs = 0;
- m_next_reply_ptr_i = RNIL;
-
- m_last_lsn = 0;
- m_last_synced_lsn = 0;
- m_last_sync_req_lsn = 0;
- m_max_sync_req_lsn = 0;
- m_last_read_lsn = 0;
- m_file_pos[0].m_ptr_i= m_file_pos[1].m_ptr_i = RNIL;
-
- m_free_file_words = 0;
- m_free_buffer_words = 0;
- m_pos[CONSUMER].m_current_page.m_ptr_i = RNIL;// { m_buffer_pages, idx }
- m_pos[CONSUMER].m_current_pos.m_ptr_i = RNIL; // { page ptr.i, m_words_used}
- m_pos[PRODUCER].m_current_page.m_ptr_i = RNIL;// { m_buffer_pages, idx }
- m_pos[PRODUCER].m_current_pos.m_ptr_i = RNIL; // { page ptr.i, m_words_used}
-
- m_tail_pos[2].m_ptr_i= RNIL;
- m_tail_pos[2].m_idx= ~0;
-
- m_tail_pos[0] = m_tail_pos[1] = m_tail_pos[2];
-}
-
-bool
-Lgman::alloc_logbuffer_memory(Ptr<Logfile_group> ptr, Uint32 bytes)
-{
- Uint32 pages= (((bytes + 3) >> 2) + File_formats::NDB_PAGE_SIZE_WORDS - 1)
- / File_formats::NDB_PAGE_SIZE_WORDS;
- Uint32 requested= pages;
- {
- Page_map map(m_data_buffer_pool, ptr.p->m_buffer_pages);
- while(pages)
- {
- Uint32 ptrI;
- Uint32 cnt = pages > 64 ? 64 : pages;
- m_ctx.m_mm.alloc_pages(RG_DISK_OPERATIONS, &ptrI, &cnt, 1);
- if (cnt)
- {
- Buffer_idx range;
- range.m_ptr_i= ptrI;
- range.m_idx = cnt;
-
- ndbrequire(map.append((Uint32*)&range, 2));
- pages -= range.m_idx;
- }
- else
- {
- break;
- }
- }
- }
-
- if(2*pages > requested)
- {
- // less than half allocated
- free_logbuffer_memory(ptr);
- return false;
- }
-
- if(pages != 0)
- {
- warningEvent("Allocated %d pages for log buffer space, logfile_group: %d"
- " , requested %d pages",
- (requested-pages), ptr.p->m_logfile_group_id, requested);
- }
-
- init_logbuffer_pointers(ptr);
- return true;
-}
-
-void
-Lgman::init_logbuffer_pointers(Ptr<Logfile_group> ptr)
-{
- Page_map map(m_data_buffer_pool, ptr.p->m_buffer_pages);
- Page_map::Iterator it;
- union {
- Uint32 tmp[2];
- Buffer_idx range;
- };
-
- map.first(it);
- tmp[0] = *it.data;
- ndbrequire(map.next(it));
- tmp[1] = *it.data;
-
- ptr.p->m_pos[CONSUMER].m_current_page.m_ptr_i = 0; // Index in page map
- ptr.p->m_pos[CONSUMER].m_current_page.m_idx = range.m_idx - 1;// left range
- ptr.p->m_pos[CONSUMER].m_current_pos.m_ptr_i = range.m_ptr_i; // Which page
- ptr.p->m_pos[CONSUMER].m_current_pos.m_idx = 0; // Page pos
-
- ptr.p->m_pos[PRODUCER].m_current_page.m_ptr_i = 0; // Index in page map
- ptr.p->m_pos[PRODUCER].m_current_page.m_idx = range.m_idx - 1;// left range
- ptr.p->m_pos[PRODUCER].m_current_pos.m_ptr_i = range.m_ptr_i; // Which page
- ptr.p->m_pos[PRODUCER].m_current_pos.m_idx = 0; // Page pos
-
- Uint32 pages= range.m_idx;
- while(map.next(it))
- {
- tmp[0] = *it.data;
- ndbrequire(map.next(it));
- tmp[1] = *it.data;
- pages += range.m_idx;
- }
-
- ptr.p->m_free_buffer_words = pages * File_formats::UNDO_PAGE_WORDS;
-}
-
-Uint32
-Lgman::compute_free_file_pages(Ptr<Logfile_group> ptr)
-{
- Buffer_idx head= ptr.p->m_file_pos[HEAD];
- Buffer_idx tail= ptr.p->m_file_pos[TAIL];
- Uint32 pages = 0;
- if (head.m_ptr_i == tail.m_ptr_i && head.m_idx < tail.m_idx)
- {
- pages += tail.m_idx - head.m_idx;
- }
- else
- {
- Ptr<Undofile> file;
- m_file_pool.getPtr(file, head.m_ptr_i);
- Local_undofile_list list(m_file_pool, ptr.p->m_files);
-
- do
- {
- pages += (file.p->m_file_size - head.m_idx - 1);
- if(!list.next(file))
- list.first(file);
- head.m_idx = 0;
- } while(file.i != tail.m_ptr_i);
-
- pages += tail.m_idx - head.m_idx;
- }
- return pages;
-}
-
-void
-Lgman::free_logbuffer_memory(Ptr<Logfile_group> ptr)
-{
- union {
- Uint32 tmp[2];
- Buffer_idx range;
- };
-
- Page_map map(m_data_buffer_pool, ptr.p->m_buffer_pages);
-
- Page_map::Iterator it;
- map.first(it);
- while(!it.isNull())
- {
- tmp[0] = *it.data;
- ndbrequire(map.next(it));
- tmp[1] = *it.data;
-
- m_ctx.m_mm.release_pages(RG_DISK_OPERATIONS, range.m_ptr_i, range.m_idx);
- map.next(it);
- }
- map.release();
-}
-
-Lgman::Undofile::Undofile(const struct CreateFileImplReq* req, Uint32 ptrI)
-{
- m_fd = RNIL;
- m_file_id = req->file_id;
- m_logfile_group_ptr_i= ptrI;
-
- Uint64 pages = req->file_size_hi;
- pages = (pages << 32) | req->file_size_lo;
- pages /= GLOBAL_PAGE_SIZE;
- m_file_size = pages;
-
- m_create.m_senderRef = req->senderRef; // During META
- m_create.m_senderData = req->senderData; // During META
- m_create.m_logfile_group_id = req->filegroup_id;
-}
-
-Logfile_client::Logfile_client(SimulatedBlock* block,
- Lgman* lgman, Uint32 logfile_group_id)
-{
- m_block= block->number();
- m_lgman= lgman;
- m_logfile_group_id= logfile_group_id;
-}
-
-int
-Logfile_client::sync_lsn(Signal* signal,
- Uint64 lsn, Request* req, Uint32 flags)
-{
- Ptr<Lgman::Logfile_group> ptr;
- if(m_lgman->m_logfile_group_list.first(ptr))
- {
- if(ptr.p->m_last_synced_lsn >= lsn)
- {
- return 1;
- }
-
- bool empty= false;
- Ptr<Lgman::Log_waiter> wait;
- {
- Lgman::Local_log_waiter_list
- list(m_lgman->m_log_waiter_pool, ptr.p->m_log_sync_waiters);
-
- empty= list.isEmpty();
- if(!list.seize(wait))
- return -1;
-
- wait.p->m_block= m_block;
- wait.p->m_sync_lsn= lsn;
- memcpy(&wait.p->m_callback, &req->m_callback,
- sizeof(SimulatedBlock::Callback));
-
- ptr.p->m_max_sync_req_lsn = lsn > ptr.p->m_max_sync_req_lsn ?
- lsn : ptr.p->m_max_sync_req_lsn;
- }
-
- if(ptr.p->m_last_sync_req_lsn < lsn &&
- ! (ptr.p->m_state & Lgman::Logfile_group::LG_FORCE_SYNC_THREAD))
- {
- ptr.p->m_state |= Lgman::Logfile_group::LG_FORCE_SYNC_THREAD;
- signal->theData[0] = LgmanContinueB::FORCE_LOG_SYNC;
- signal->theData[1] = ptr.i;
- signal->theData[2] = lsn >> 32;
- signal->theData[3] = lsn & 0xFFFFFFFF;
- m_lgman->sendSignalWithDelay(m_lgman->reference(),
- GSN_CONTINUEB, signal, 10, 4);
- }
- return 0;
- }
- return -1;
-}
-
-void
-Lgman::force_log_sync(Signal* signal,
- Ptr<Logfile_group> ptr,
- Uint32 lsn_hi, Uint32 lsn_lo)
-{
- Local_log_waiter_list list(m_log_waiter_pool, ptr.p->m_log_sync_waiters);
- Uint64 force_lsn = lsn_hi; force_lsn <<= 32; force_lsn += lsn_lo;
-
- if(ptr.p->m_last_sync_req_lsn < force_lsn)
- {
- /**
- * Do force
- */
- Buffer_idx pos= ptr.p->m_pos[PRODUCER].m_current_pos;
- GlobalPage *page = m_shared_page_pool.getPtr(pos.m_ptr_i);
-
- Uint32 free= File_formats::UNDO_PAGE_WORDS - pos.m_idx;
- if(pos.m_idx) // don't flush empty page...
- {
- Uint64 lsn= ptr.p->m_last_lsn - 1;
-
- File_formats::Undofile::Undo_page* undo=
- (File_formats::Undofile::Undo_page*)page;
- undo->m_page_header.m_page_lsn_lo = lsn & 0xFFFFFFFF;
- undo->m_page_header.m_page_lsn_hi = lsn >> 32;
- undo->m_words_used= File_formats::UNDO_PAGE_WORDS - free;
-
- /**
- * Update free space with extra NOOP
- */
- ndbrequire(ptr.p->m_free_file_words >= free);
- ndbrequire(ptr.p->m_free_buffer_words > free);
- ptr.p->m_free_file_words -= free;
- ptr.p->m_free_buffer_words -= free;
-
- validate_logfile_group(ptr, "force_log_sync");
-
- next_page(ptr.p, PRODUCER);
- ptr.p->m_pos[PRODUCER].m_current_pos.m_idx = 0;
- }
- }
-
-
-
- Uint64 max_req_lsn = ptr.p->m_max_sync_req_lsn;
- if(max_req_lsn > force_lsn &&
- max_req_lsn > ptr.p->m_last_sync_req_lsn)
- {
- ndbrequire(ptr.p->m_state & Lgman::Logfile_group::LG_FORCE_SYNC_THREAD);
- signal->theData[0] = LgmanContinueB::FORCE_LOG_SYNC;
- signal->theData[1] = ptr.i;
- signal->theData[2] = max_req_lsn >> 32;
- signal->theData[3] = max_req_lsn & 0xFFFFFFFF;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 10, 4);
- }
- else
- {
- ptr.p->m_state &= ~(Uint32)Lgman::Logfile_group::LG_FORCE_SYNC_THREAD;
- }
-}
-
-void
-Lgman::process_log_sync_waiters(Signal* signal, Ptr<Logfile_group> ptr)
-{
- Local_log_waiter_list
- list(m_log_waiter_pool, ptr.p->m_log_sync_waiters);
-
- if(list.isEmpty())
- {
- return;
- }
-
- bool removed= false;
- Ptr<Log_waiter> waiter;
- list.first(waiter);
- Uint32 logfile_group_id = ptr.p->m_logfile_group_id;
-
- if(waiter.p->m_sync_lsn <= ptr.p->m_last_synced_lsn)
- {
- removed= true;
- Uint32 block = waiter.p->m_block;
- SimulatedBlock* b = globalData.getBlock(block);
- b->execute(signal, waiter.p->m_callback, logfile_group_id);
-
- list.releaseFirst(waiter);
- }
-
- if(removed && !list.isEmpty())
- {
- ptr.p->m_state |= Logfile_group::LG_SYNC_WAITERS_THREAD;
- signal->theData[0] = LgmanContinueB::PROCESS_LOG_SYNC_WAITERS;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- }
- else
- {
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_SYNC_WAITERS_THREAD;
- }
-}
-
-
-Uint32*
-Lgman::get_log_buffer(Ptr<Logfile_group> ptr, Uint32 sz)
-{
- GlobalPage *page;
- page=m_shared_page_pool.getPtr(ptr.p->m_pos[PRODUCER].m_current_pos.m_ptr_i);
-
- Uint32 total_free= ptr.p->m_free_buffer_words;
- assert(total_free >= sz);
- Uint32 pos= ptr.p->m_pos[PRODUCER].m_current_pos.m_idx;
- Uint32 free= File_formats::UNDO_PAGE_WORDS - pos;
-
- if(sz <= free)
- {
-next:
- // fits this page wo/ problem
- ndbrequire(total_free > sz);
- ptr.p->m_free_buffer_words = total_free - sz;
- ptr.p->m_pos[PRODUCER].m_current_pos.m_idx = pos + sz;
- return ((File_formats::Undofile::Undo_page*)page)->m_data + pos;
- }
-
- /**
- * It didn't fit page...fill page with a NOOP log entry
- */
- Uint64 lsn= ptr.p->m_last_lsn - 1;
- File_formats::Undofile::Undo_page* undo=
- (File_formats::Undofile::Undo_page*)page;
- undo->m_page_header.m_page_lsn_lo = lsn & 0xFFFFFFFF;
- undo->m_page_header.m_page_lsn_hi = lsn >> 32;
- undo->m_words_used= File_formats::UNDO_PAGE_WORDS - free;
-
- /**
- * Update free space with extra NOOP
- */
- ndbrequire(ptr.p->m_free_file_words >= free);
- ptr.p->m_free_file_words -= free;
-
- validate_logfile_group(ptr, "get_log_buffer");
-
- pos= 0;
- assert(total_free >= free);
- total_free -= free;
- page= m_shared_page_pool.getPtr(next_page(ptr.p, PRODUCER));
- goto next;
-}
-
-Uint32
-Lgman::next_page(Logfile_group* ptrP, Uint32 i)
-{
- Uint32 page_ptr_i= ptrP->m_pos[i].m_current_pos.m_ptr_i;
- Uint32 left_in_range= ptrP->m_pos[i].m_current_page.m_idx;
- if(left_in_range > 0)
- {
- ptrP->m_pos[i].m_current_page.m_idx = left_in_range - 1;
- ptrP->m_pos[i].m_current_pos.m_ptr_i = page_ptr_i + 1;
- return page_ptr_i + 1;
- }
- else
- {
- Lgman::Page_map map(m_data_buffer_pool, ptrP->m_buffer_pages);
- Uint32 pos= (ptrP->m_pos[i].m_current_page.m_ptr_i + 2) % map.getSize();
- Lgman::Page_map::Iterator it;
- map.position(it, pos);
-
- union {
- Uint32 tmp[2];
- Lgman::Buffer_idx range;
- };
-
- tmp[0] = *it.data; map.next(it);
- tmp[1] = *it.data;
-
- ptrP->m_pos[i].m_current_page.m_ptr_i = pos; // New index in map
- ptrP->m_pos[i].m_current_page.m_idx = range.m_idx - 1; // Free pages
- ptrP->m_pos[i].m_current_pos.m_ptr_i = range.m_ptr_i; // Current page
- // No need to set ptrP->m_current_pos.m_idx, that is set "in higher"-func
- return range.m_ptr_i;
- }
-}
-
-int
-Logfile_client::get_log_buffer(Signal* signal, Uint32 sz,
- SimulatedBlock::Callback* callback)
-{
- sz += 2; // lsn
- Lgman::Logfile_group key;
- key.m_logfile_group_id= m_logfile_group_id;
- Ptr<Lgman::Logfile_group> ptr;
- if(m_lgman->m_logfile_group_hash.find(ptr, key))
- {
- if(ptr.p->m_free_buffer_words >= (sz + 2*File_formats::UNDO_PAGE_WORDS)&&
- ptr.p->m_log_buffer_waiters.isEmpty())
- {
- return 1;
- }
-
- bool empty= false;
- {
- Ptr<Lgman::Log_waiter> wait;
- Lgman::Local_log_waiter_list
- list(m_lgman->m_log_waiter_pool, ptr.p->m_log_buffer_waiters);
-
- empty= list.isEmpty();
- if(!list.seize(wait))
- {
- return -1;
- }
-
- wait.p->m_size= sz;
- wait.p->m_block= m_block;
- memcpy(&wait.p->m_callback, callback,sizeof(SimulatedBlock::Callback));
- }
-
- return 0;
- }
- return -1;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Lgman::Buffer_idx& pos)
-{
- out << "[ "
- << pos.m_ptr_i << " "
- << pos.m_idx << " ]";
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const Lgman::Logfile_group::Position& pos)
-{
- out << "[ ("
- << pos.m_current_page.m_ptr_i << " "
- << pos.m_current_page.m_idx << ") ("
- << pos.m_current_pos.m_ptr_i << " "
- << pos.m_current_pos.m_idx << ") ]";
- return out;
-}
-
-void
-Lgman::flush_log(Signal* signal, Ptr<Logfile_group> ptr, Uint32 force)
-{
- Logfile_group::Position consumer= ptr.p->m_pos[CONSUMER];
- Logfile_group::Position producer= ptr.p->m_pos[PRODUCER];
-
- jamEntry();
-
- if(consumer.m_current_page == producer.m_current_page)
- {
-
-#if 0
- if (force)
- {
- ndbout_c("force: %d ptr.p->m_file_pos[HEAD].m_ptr_i= %x",
- force, ptr.p->m_file_pos[HEAD].m_ptr_i);
- ndbout_c("consumer.m_current_page: %d %d producer.m_current_page: %d %d",
- consumer.m_current_page.m_ptr_i, consumer.m_current_page.m_idx,
- producer.m_current_page.m_ptr_i, producer.m_current_page.m_idx);
- }
-#endif
- if (! (ptr.p->m_state & Logfile_group::LG_DROPPING))
- {
- jam();
-
- if (ptr.p->m_log_buffer_waiters.isEmpty() || ptr.p->m_outstanding_fs)
- {
- force = 0;
- }
-
- if (force < 2)
- {
- signal->theData[0] = LgmanContinueB::FLUSH_LOG;
- signal->theData[1] = ptr.i;
- signal->theData[2] = force + 1;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
- force ? 10 : 100, 3);
- return;
- }
- else
- {
- Buffer_idx pos= producer.m_current_pos;
- GlobalPage *page = m_shared_page_pool.getPtr(pos.m_ptr_i);
-
- Uint32 free= File_formats::UNDO_PAGE_WORDS - pos.m_idx;
-
- ndbout_c("force flush %d %d", pos.m_idx, ptr.p->m_free_buffer_words);
-
- ndbrequire(pos.m_idx); // don't flush empty page...
- Uint64 lsn= ptr.p->m_last_lsn - 1;
-
- File_formats::Undofile::Undo_page* undo=
- (File_formats::Undofile::Undo_page*)page;
- undo->m_page_header.m_page_lsn_lo = lsn & 0xFFFFFFFF;
- undo->m_page_header.m_page_lsn_hi = lsn >> 32;
- undo->m_words_used= File_formats::UNDO_PAGE_WORDS - free;
-
- /**
- * Update free space with extra NOOP
- */
- ndbrequire(ptr.p->m_free_file_words >= free);
- ndbrequire(ptr.p->m_free_buffer_words > free);
- ptr.p->m_free_file_words -= free;
- ptr.p->m_free_buffer_words -= free;
-
- validate_logfile_group(ptr, "force_log_flush");
-
- next_page(ptr.p, PRODUCER);
- ptr.p->m_pos[PRODUCER].m_current_pos.m_idx = 0;
- producer = ptr.p->m_pos[PRODUCER];
- // break through
- }
- }
- else
- {
- jam();
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_FLUSH_THREAD;
- return;
- }
- }
-
- bool full= false;
- Uint32 tot= 0;
- while(!(consumer.m_current_page == producer.m_current_page) && !full)
- {
- validate_logfile_group(ptr, "before flush log");
-
- Uint32 cnt; // pages written
- Uint32 page= consumer.m_current_pos.m_ptr_i;
- if(consumer.m_current_page.m_ptr_i == producer.m_current_page.m_ptr_i)
- {
- if(consumer.m_current_page.m_idx > producer.m_current_page.m_idx)
- {
- jam();
- Uint32 tmp=
- consumer.m_current_page.m_idx - producer.m_current_page.m_idx;
- cnt= write_log_pages(signal, ptr, page, tmp);
- assert(cnt <= tmp);
-
- consumer.m_current_pos.m_ptr_i += cnt;
- consumer.m_current_page.m_idx -= cnt;
- full= (tmp > cnt);
- }
- else
- {
- // Only 1 chunk
- ndbrequire(ptr.p->m_buffer_pages.getSize() == 2);
- Uint32 tmp= consumer.m_current_page.m_idx + 1;
- cnt= write_log_pages(signal, ptr, page, tmp);
- assert(cnt <= tmp);
-
- if(cnt == tmp)
- {
- jam();
- /**
- * Entire chunk is written
- * move to next
- */
- ptr.p->m_pos[CONSUMER].m_current_page.m_idx= 0;
- next_page(ptr.p, CONSUMER);
- consumer = ptr.p->m_pos[CONSUMER];
- }
- else
- {
- jam();
- /**
- * Failed to write entire chunk...
- */
- full= true;
- consumer.m_current_page.m_idx -= cnt;
- consumer.m_current_pos.m_ptr_i += cnt;
- }
- }
- }
- else
- {
- Uint32 tmp= consumer.m_current_page.m_idx + 1;
- cnt= write_log_pages(signal, ptr, page, tmp);
- assert(cnt <= tmp);
-
- if(cnt == tmp)
- {
- jam();
- /**
- * Entire chunk is written
- * move to next
- */
- ptr.p->m_pos[CONSUMER].m_current_page.m_idx= 0;
- next_page(ptr.p, CONSUMER);
- consumer = ptr.p->m_pos[CONSUMER];
- }
- else
- {
- jam();
- /**
- * Failed to write entire chunk...
- */
- full= true;
- consumer.m_current_page.m_idx -= cnt;
- consumer.m_current_pos.m_ptr_i += cnt;
- }
- }
-
- tot += cnt;
- if(cnt)
- validate_logfile_group(ptr, " after flush_log");
- }
-
- ptr.p->m_pos[CONSUMER]= consumer;
-
- if (! (ptr.p->m_state & Logfile_group::LG_DROPPING))
- {
- signal->theData[0] = LgmanContinueB::FLUSH_LOG;
- signal->theData[1] = ptr.i;
- signal->theData[2] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
- }
- else
- {
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_FLUSH_THREAD;
- }
-}
-
-void
-Lgman::process_log_buffer_waiters(Signal* signal, Ptr<Logfile_group> ptr)
-{
- Uint32 free_buffer= ptr.p->m_free_buffer_words;
- Local_log_waiter_list
- list(m_log_waiter_pool, ptr.p->m_log_buffer_waiters);
-
- if(list.isEmpty())
- {
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_WAITERS_THREAD;
- return;
- }
-
- bool removed= false;
- Ptr<Log_waiter> waiter;
- list.first(waiter);
- Uint32 logfile_group_id = ptr.p->m_logfile_group_id;
- if(waiter.p->m_size + 2*File_formats::UNDO_PAGE_WORDS < free_buffer)
- {
- removed= true;
- Uint32 block = waiter.p->m_block;
- SimulatedBlock* b = globalData.getBlock(block);
- b->execute(signal, waiter.p->m_callback, logfile_group_id);
-
- list.releaseFirst(waiter);
- }
-
- if(removed && !list.isEmpty())
- {
- ptr.p->m_state |= Logfile_group::LG_WAITERS_THREAD;
- signal->theData[0] = LgmanContinueB::PROCESS_LOG_BUFFER_WAITERS;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- }
- else
- {
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_WAITERS_THREAD;
- }
-}
-
-#define REALLY_SLOW_FS 0
-
-Uint32
-Lgman::write_log_pages(Signal* signal, Ptr<Logfile_group> ptr,
- Uint32 pageId, Uint32 in_pages)
-{
- assert(in_pages);
- Ptr<Undofile> filePtr;
- Buffer_idx head= ptr.p->m_file_pos[HEAD];
- Buffer_idx tail= ptr.p->m_file_pos[TAIL];
- m_file_pool.getPtr(filePtr, head.m_ptr_i);
-
- if(filePtr.p->m_online.m_outstanding > 0)
- {
- jam();
- return 0;
- }
-
- Uint32 sz= filePtr.p->m_file_size - 1; // skip zero
- Uint32 max, pages= in_pages;
-
- if(!(head.m_ptr_i == tail.m_ptr_i && head.m_idx < tail.m_idx))
- {
- max= sz - head.m_idx;
- }
- else
- {
- max= tail.m_idx - head.m_idx;
- }
-
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = filePtr.p->m_fd;
- req->userReference = reference();
- req->userPointer = filePtr.i;
- req->varIndex = 1+head.m_idx; // skip zero page
- req->numberOfPages = pages;
- req->data.pageData[0] = pageId;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatSharedPage);
-
- if(max > pages)
- {
- jam();
- max= pages;
- head.m_idx += max;
- ptr.p->m_file_pos[HEAD] = head;
-
- if (REALLY_SLOW_FS)
- sendSignalWithDelay(NDBFS_REF, GSN_FSWRITEREQ, signal, REALLY_SLOW_FS,
- FsReadWriteReq::FixedLength + 1);
- else
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-
- ptr.p->m_outstanding_fs++;
- filePtr.p->m_online.m_outstanding = max;
- filePtr.p->m_state |= Undofile::FS_OUTSTANDING;
-
- File_formats::Undofile::Undo_page *page= (File_formats::Undofile::Undo_page*)
- m_shared_page_pool.getPtr(pageId + max - 1);
- Uint64 lsn = 0;
- lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32;
- lsn += page->m_page_header.m_page_lsn_lo;
-
- filePtr.p->m_online.m_lsn = lsn; // Store last writereq lsn on file
- ptr.p->m_last_sync_req_lsn = lsn; // And logfile_group
- }
- else
- {
- jam();
- req->numberOfPages = max;
- FsReadWriteReq::setSyncFlag(req->operationFlag, 1);
-
- if (REALLY_SLOW_FS)
- sendSignalWithDelay(NDBFS_REF, GSN_FSWRITEREQ, signal, REALLY_SLOW_FS,
- FsReadWriteReq::FixedLength + 1);
- else
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-
- ptr.p->m_outstanding_fs++;
- filePtr.p->m_online.m_outstanding = max;
- filePtr.p->m_state |= Undofile::FS_OUTSTANDING;
-
- File_formats::Undofile::Undo_page *page= (File_formats::Undofile::Undo_page*)
- m_shared_page_pool.getPtr(pageId + max - 1);
- Uint64 lsn = 0;
- lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32;
- lsn += page->m_page_header.m_page_lsn_lo;
-
- filePtr.p->m_online.m_lsn = lsn; // Store last writereq lsn on file
- ptr.p->m_last_sync_req_lsn = lsn; // And logfile_group
-
- Ptr<Undofile> next = filePtr;
- Local_undofile_list files(m_file_pool, ptr.p->m_files);
- if(!files.next(next))
- {
- jam();
- files.first(next);
- }
- ndbout_c("changing file from %d to %d", filePtr.i, next.i);
- filePtr.p->m_state |= Undofile::FS_MOVE_NEXT;
- next.p->m_state &= ~(Uint32)Undofile::FS_EMPTY;
-
- head.m_idx= 0;
- head.m_ptr_i= next.i;
- ptr.p->m_file_pos[HEAD] = head;
- if(max < pages)
- max += write_log_pages(signal, ptr, pageId + max, pages - max);
- }
-
- assert(max);
- return max;
-}
-
-void
-Lgman::execFSWRITEREF(Signal* signal)
-{
- jamEntry();
- SimulatedBlock::execFSWRITEREF(signal);
- ndbrequire(false);
-}
-
-void
-Lgman::execFSWRITECONF(Signal* signal)
-{
- jamEntry();
- FsConf * conf = (FsConf*)signal->getDataPtr();
- Ptr<Undofile> ptr;
- m_file_pool.getPtr(ptr, conf->userPointer);
-
- ndbrequire(ptr.p->m_state & Undofile::FS_OUTSTANDING);
- ptr.p->m_state &= ~(Uint32)Undofile::FS_OUTSTANDING;
-
- Ptr<Logfile_group> lg_ptr;
- m_logfile_group_pool.getPtr(lg_ptr, ptr.p->m_logfile_group_ptr_i);
-
- Uint32 cnt= lg_ptr.p->m_outstanding_fs;
- ndbrequire(cnt);
-
- if(lg_ptr.p->m_next_reply_ptr_i == ptr.i)
- {
- Uint32 tot= 0;
- Uint64 lsn = 0;
- {
- Local_undofile_list files(m_file_pool, lg_ptr.p->m_files);
- while(cnt && ! (ptr.p->m_state & Undofile::FS_OUTSTANDING))
- {
- Uint32 state= ptr.p->m_state;
- Uint32 pages= ptr.p->m_online.m_outstanding;
- ndbrequire(pages);
- ptr.p->m_online.m_outstanding= 0;
- ptr.p->m_state &= ~(Uint32)Undofile::FS_MOVE_NEXT;
- tot += pages;
- cnt--;
-
- lsn = ptr.p->m_online.m_lsn;
-
- if((state & Undofile::FS_MOVE_NEXT) && !files.next(ptr))
- files.first(ptr);
- }
- }
-
- ndbassert(tot);
- lg_ptr.p->m_outstanding_fs = cnt;
- lg_ptr.p->m_free_buffer_words += (tot * File_formats::UNDO_PAGE_WORDS);
- lg_ptr.p->m_next_reply_ptr_i = ptr.i;
- lg_ptr.p->m_last_synced_lsn = lsn;
-
- if(! (lg_ptr.p->m_state & Logfile_group::LG_SYNC_WAITERS_THREAD))
- {
- process_log_sync_waiters(signal, lg_ptr);
- }
-
- if(! (lg_ptr.p->m_state & Logfile_group::LG_WAITERS_THREAD))
- {
- process_log_buffer_waiters(signal, lg_ptr);
- }
- }
- else
- {
- ndbout_c("miss matched writes");
- }
-
- return;
-}
-
-void
-Lgman::execLCP_FRAG_ORD(Signal* signal)
-{
- jamEntry();
-
- LcpFragOrd * ord = (LcpFragOrd *)signal->getDataPtr();
- Uint32 lcp_id= ord->lcpId;
- Uint32 frag_id = ord->fragmentId;
- Uint32 table_id = ord->tableId;
-
- Ptr<Logfile_group> ptr;
- m_logfile_group_list.first(ptr);
-
- Uint32 entry= lcp_id == m_latest_lcp ?
- File_formats::Undofile::UNDO_LCP : File_formats::Undofile::UNDO_LCP_FIRST;
- if(!ptr.isNull() && ! (ptr.p->m_state & Logfile_group::LG_CUT_LOG_THREAD))
- {
- jam();
- ptr.p->m_state |= Logfile_group::LG_CUT_LOG_THREAD;
- signal->theData[0] = LgmanContinueB::CUT_LOG_TAIL;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- }
-
- if(!ptr.isNull() && ptr.p->m_last_lsn)
- {
- Uint32 undo[3];
- undo[0] = lcp_id;
- undo[1] = (table_id << 16) | frag_id;
- undo[2] = (entry << 16 ) | (sizeof(undo) >> 2);
-
- Uint64 last_lsn= m_last_lsn;
-
- if(ptr.p->m_last_lsn == last_lsn
-#ifdef VM_TRACE
- && ((rand() % 100) > 50)
-#endif
- )
- {
- undo[2] |= File_formats::Undofile::UNDO_NEXT_LSN << 16;
- Uint32 *dst= get_log_buffer(ptr, sizeof(undo) >> 2);
- memcpy(dst, undo, sizeof(undo));
- ndbrequire(ptr.p->m_free_file_words >= (sizeof(undo) >> 2));
- ptr.p->m_free_file_words -= (sizeof(undo) >> 2);
- }
- else
- {
- Uint32 *dst= get_log_buffer(ptr, (sizeof(undo) >> 2) + 2);
- * dst++ = last_lsn >> 32;
- * dst++ = last_lsn & 0xFFFFFFFF;
- memcpy(dst, undo, sizeof(undo));
- ndbrequire(ptr.p->m_free_file_words >= (sizeof(undo) >> 2));
- ptr.p->m_free_file_words -= ((sizeof(undo) >> 2) + 2);
- }
- ptr.p->m_last_lcp_lsn = last_lsn;
- m_last_lsn = ptr.p->m_last_lsn = last_lsn + 1;
-
- validate_logfile_group(ptr, "execLCP_FRAG_ORD");
- }
-
- while(!ptr.isNull())
- {
- if (ptr.p->m_last_lsn)
- {
- /**
- * First LCP_FRAGORD for each LCP, sets tail pos
- */
- if(m_latest_lcp != lcp_id)
- {
- ptr.p->m_tail_pos[0] = ptr.p->m_tail_pos[1];
- ptr.p->m_tail_pos[1] = ptr.p->m_tail_pos[2];
- ptr.p->m_tail_pos[2] = ptr.p->m_file_pos[HEAD];
- }
-
- if(0)
- ndbout_c
- ("execLCP_FRAG_ORD (%d %d) (%d %d) (%d %d) free pages: %ld",
- ptr.p->m_tail_pos[0].m_ptr_i, ptr.p->m_tail_pos[0].m_idx,
- ptr.p->m_tail_pos[1].m_ptr_i, ptr.p->m_tail_pos[1].m_idx,
- ptr.p->m_tail_pos[2].m_ptr_i, ptr.p->m_tail_pos[2].m_idx,
- (long) (ptr.p->m_free_file_words / File_formats::UNDO_PAGE_WORDS));
- }
- m_logfile_group_list.next(ptr);
- }
-
- m_latest_lcp = lcp_id;
-}
-
-void
-Lgman::execEND_LCP_REQ(Signal* signal)
-{
- EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
- ndbrequire(m_latest_lcp == req->backupId);
-
- Ptr<Logfile_group> ptr;
- m_logfile_group_list.first(ptr);
- bool wait= false;
- while(!ptr.isNull())
- {
- Uint64 lcp_lsn = ptr.p->m_last_lcp_lsn;
- if(ptr.p->m_last_synced_lsn < lcp_lsn)
- {
- wait= true;
- if(signal->getSendersBlockRef() != reference())
- {
- Logfile_client tmp(this, this, ptr.p->m_logfile_group_id);
- Logfile_client::Request req;
- req.m_callback.m_callbackData = ptr.i;
- req.m_callback.m_callbackFunction = safe_cast(&Lgman::endlcp_callback);
- ndbrequire(tmp.sync_lsn(signal, lcp_lsn, &req, 0) == 0);
- }
- }
- else
- {
- ptr.p->m_last_lcp_lsn = 0;
- }
- m_logfile_group_list.next(ptr);
- }
-
- if(wait)
- {
- return;
- }
-
- signal->theData[0] = 0;
- sendSignal(DBLQH_REF, GSN_END_LCP_CONF, signal, 1, JBB);
-}
-
-void
-Lgman::endlcp_callback(Signal* signal, Uint32 ptr, Uint32 res)
-{
- EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
- req->backupId = m_latest_lcp;
- execEND_LCP_REQ(signal);
-}
-
-void
-Lgman::cut_log_tail(Signal* signal, Ptr<Logfile_group> ptr)
-{
- bool done= true;
- if (likely(ptr.p->m_last_lsn))
- {
- Buffer_idx tmp= ptr.p->m_tail_pos[0];
- Buffer_idx tail= ptr.p->m_file_pos[TAIL];
-
- Ptr<Undofile> filePtr;
- m_file_pool.getPtr(filePtr, tail.m_ptr_i);
-
- if(!(tmp == tail))
- {
- Uint32 free;
- if(tmp.m_ptr_i == tail.m_ptr_i && tail.m_idx < tmp.m_idx)
- {
- free= tmp.m_idx - tail.m_idx;
- ptr.p->m_free_file_words += free * File_formats::UNDO_PAGE_WORDS;
- ptr.p->m_file_pos[TAIL] = tmp;
- }
- else
- {
- free= filePtr.p->m_file_size - tail.m_idx - 1;
- ptr.p->m_free_file_words += free * File_formats::UNDO_PAGE_WORDS;
-
- Ptr<Undofile> next = filePtr;
- Local_undofile_list files(m_file_pool, ptr.p->m_files);
- while(files.next(next) && (next.p->m_state & Undofile::FS_EMPTY))
- ndbrequire(next.i != filePtr.i);
- if(next.isNull())
- {
- jam();
- files.first(next);
- while((next.p->m_state & Undofile::FS_EMPTY) && files.next(next))
- ndbrequire(next.i != filePtr.i);
- }
-
- tmp.m_idx= 0;
- tmp.m_ptr_i= next.i;
- ptr.p->m_file_pos[TAIL] = tmp;
- done= false;
- }
- }
-
- validate_logfile_group(ptr, "cut log");
- }
-
- if (done)
- {
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_CUT_LOG_THREAD;
- m_logfile_group_list.next(ptr);
- }
-
- if(!done || !ptr.isNull())
- {
- ptr.p->m_state |= Logfile_group::LG_CUT_LOG_THREAD;
- signal->theData[0] = LgmanContinueB::CUT_LOG_TAIL;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- }
-}
-
-void
-Lgman::execSUB_GCP_COMPLETE_REP(Signal* signal)
-{
- jamEntry();
-
- Ptr<Logfile_group> ptr;
- m_logfile_group_list.first(ptr);
-
- /**
- * Filter all logfile groups in parallell
- */
- return; // NOT IMPLETMENT YET
-
- signal->theData[0] = LgmanContinueB::FILTER_LOG;
- while(!ptr.isNull())
- {
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- m_logfile_group_list.next(ptr);
- }
-}
-
-int
-Lgman::alloc_log_space(Uint32 ref, Uint32 words)
-{
- ndbrequire(words);
- words += 2; // lsn
- Logfile_group key;
- key.m_logfile_group_id= ref;
- Ptr<Logfile_group> ptr;
- if(m_logfile_group_hash.find(ptr, key) &&
- ptr.p->m_free_file_words >= (words + (4 * File_formats::UNDO_PAGE_WORDS)))
- {
- ptr.p->m_free_file_words -= words;
- validate_logfile_group(ptr, "alloc_log_space");
- return 0;
- }
-
- if(ptr.isNull())
- {
- return -1;
- }
-
- return 1501;
-}
-
-int
-Lgman::free_log_space(Uint32 ref, Uint32 words)
-{
- ndbrequire(words);
- Logfile_group key;
- key.m_logfile_group_id= ref;
- Ptr<Logfile_group> ptr;
- if(m_logfile_group_hash.find(ptr, key))
- {
- ptr.p->m_free_file_words += (words + 2);
- validate_logfile_group(ptr, "free_log_space");
- return 0;
- }
- ndbrequire(false);
- return -1;
-}
-
-Uint64
-Logfile_client::add_entry(const Change* src, Uint32 cnt)
-{
- Uint32 i, tot= 0;
- for(i= 0; i<cnt; i++)
- {
- tot += src[i].len;
- }
-
- Uint32 *dst;
- Uint64 last_lsn= m_lgman->m_last_lsn;
- {
- Lgman::Logfile_group key;
- key.m_logfile_group_id= m_logfile_group_id;
- Ptr<Lgman::Logfile_group> ptr;
- if(m_lgman->m_logfile_group_hash.find(ptr, key))
- {
- Uint64 last_lsn_filegroup= ptr.p->m_last_lsn;
- if(last_lsn_filegroup == last_lsn
-#ifdef VM_TRACE
- && ((rand() % 100) > 50)
-#endif
- )
- {
- dst= m_lgman->get_log_buffer(ptr, tot);
- for(i= 0; i<cnt; i++)
- {
- memcpy(dst, src[i].ptr, 4*src[i].len);
- dst += src[i].len;
- }
- * (dst - 1) |= File_formats::Undofile::UNDO_NEXT_LSN << 16;
- ptr.p->m_free_file_words += 2;
- ptr.p->m_free_buffer_words += 2;
- m_lgman->validate_logfile_group(ptr);
- }
- else
- {
- dst= m_lgman->get_log_buffer(ptr, tot + 2);
- * dst++ = last_lsn >> 32;
- * dst++ = last_lsn & 0xFFFFFFFF;
- for(i= 0; i<cnt; i++)
- {
- memcpy(dst, src[i].ptr, 4*src[i].len);
- dst += src[i].len;
- }
- }
- }
-
- m_lgman->m_last_lsn = ptr.p->m_last_lsn = last_lsn + 1;
-
- return last_lsn;
- }
-}
-
-void
-Lgman::execSTART_RECREQ(Signal* signal)
-{
- m_latest_lcp = signal->theData[0];
-
- Ptr<Logfile_group> ptr;
- m_logfile_group_list.first(ptr);
-
- if(ptr.i != RNIL)
- {
- infoEvent("Applying undo to LCP: %d", m_latest_lcp);
- ndbout_c("Applying undo to LCP: %d", m_latest_lcp);
- find_log_head(signal, ptr);
- return;
- }
-
- signal->theData[0] = reference();
- sendSignal(DBLQH_REF, GSN_START_RECCONF, signal, 1, JBB);
-}
-
-void
-Lgman::find_log_head(Signal* signal, Ptr<Logfile_group> ptr)
-{
- ndbrequire(ptr.p->m_state &
- (Logfile_group::LG_STARTING | Logfile_group::LG_SORTING));
-
- if(ptr.p->m_meta_files.isEmpty() && ptr.p->m_files.isEmpty())
- {
- jam();
- /**
- * Logfile_group wo/ any files
- */
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_STARTING;
- ptr.p->m_state |= Logfile_group::LG_ONLINE;
- m_logfile_group_list.next(ptr);
- signal->theData[0] = LgmanContinueB::FIND_LOG_HEAD;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- }
-
- ptr.p->m_state = Logfile_group::LG_SORTING;
-
- /**
- * Read first page from each undofile (1 file at a time...)
- */
- Local_undofile_list files(m_file_pool, ptr.p->m_meta_files);
- Ptr<Undofile> file_ptr;
- files.first(file_ptr);
-
- if(!file_ptr.isNull())
- {
- /**
- * Use log buffer memory when reading
- */
- Uint32 page_id = ptr.p->m_pos[CONSUMER].m_current_pos.m_ptr_i;
- file_ptr.p->m_online.m_outstanding= page_id;
-
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = file_ptr.p->m_fd;
- req->userReference = reference();
- req->userPointer = file_ptr.i;
- req->varIndex = 1; // skip zero page
- req->numberOfPages = 1;
- req->data.pageData[0] = page_id;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatSharedPage);
-
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-
- ptr.p->m_outstanding_fs++;
- file_ptr.p->m_state |= Undofile::FS_OUTSTANDING;
- return;
- }
- else
- {
- /**
- * All files have read first page
- * and m_files is sorted acording to lsn
- */
- ndbrequire(!ptr.p->m_files.isEmpty());
- Local_undofile_list read_files(m_file_pool, ptr.p->m_files);
- read_files.last(file_ptr);
-
-
- /**
- * Init binary search
- */
- ptr.p->m_state = Logfile_group::LG_SEARCHING;
- file_ptr.p->m_state = Undofile::FS_SEARCHING;
- ptr.p->m_file_pos[TAIL].m_idx = 1; // left page
- ptr.p->m_file_pos[HEAD].m_idx = file_ptr.p->m_file_size;
- ptr.p->m_file_pos[HEAD].m_ptr_i = ((file_ptr.p->m_file_size - 1) >> 1) + 1;
-
- Uint32 page_id = ptr.p->m_pos[CONSUMER].m_current_pos.m_ptr_i;
- file_ptr.p->m_online.m_outstanding= page_id;
-
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = file_ptr.p->m_fd;
- req->userReference = reference();
- req->userPointer = file_ptr.i;
- req->varIndex = ptr.p->m_file_pos[HEAD].m_ptr_i;
- req->numberOfPages = 1;
- req->data.pageData[0] = page_id;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatSharedPage);
-
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-
- ptr.p->m_outstanding_fs++;
- file_ptr.p->m_state |= Undofile::FS_OUTSTANDING;
- return;
- }
-}
-
-void
-Lgman::execFSREADCONF(Signal* signal)
-{
- jamEntry();
-
- Ptr<Undofile> ptr;
- Ptr<Logfile_group> lg_ptr;
- FsConf* conf = (FsConf*)signal->getDataPtr();
-
- m_file_pool.getPtr(ptr, conf->userPointer);
- m_logfile_group_pool.getPtr(lg_ptr, ptr.p->m_logfile_group_ptr_i);
-
- ndbrequire(ptr.p->m_state & Undofile::FS_OUTSTANDING);
- ptr.p->m_state &= ~(Uint32)Undofile::FS_OUTSTANDING;
-
- Uint32 cnt= lg_ptr.p->m_outstanding_fs;
- ndbrequire(cnt);
-
- if((ptr.p->m_state & Undofile::FS_EXECUTING)== Undofile::FS_EXECUTING)
- {
- jam();
-
- if(lg_ptr.p->m_next_reply_ptr_i == ptr.i)
- {
- Uint32 tot= 0;
- Local_undofile_list files(m_file_pool, lg_ptr.p->m_files);
- while(cnt && ! (ptr.p->m_state & Undofile::FS_OUTSTANDING))
- {
- Uint32 state= ptr.p->m_state;
- Uint32 pages= ptr.p->m_online.m_outstanding;
- ndbrequire(pages);
- ptr.p->m_online.m_outstanding= 0;
- ptr.p->m_state &= ~(Uint32)Undofile::FS_MOVE_NEXT;
- tot += pages;
- cnt--;
-
- if((state & Undofile::FS_MOVE_NEXT) && !files.prev(ptr))
- files.last(ptr);
- }
-
- lg_ptr.p->m_outstanding_fs = cnt;
- lg_ptr.p->m_pos[PRODUCER].m_current_pos.m_idx += tot;
- lg_ptr.p->m_next_reply_ptr_i = ptr.i;
- }
- return;
- }
-
- lg_ptr.p->m_outstanding_fs = cnt - 1;
-
- Ptr<GlobalPage> page_ptr;
- m_shared_page_pool.getPtr(page_ptr, ptr.p->m_online.m_outstanding);
- ptr.p->m_online.m_outstanding= 0;
-
- File_formats::Undofile::Undo_page* page =
- (File_formats::Undofile::Undo_page*)page_ptr.p;
-
- Uint64 lsn = 0;
- lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32;
- lsn += page->m_page_header.m_page_lsn_lo;
-
- switch(ptr.p->m_state){
- case Undofile::FS_SORTING:
- jam();
- break;
- case Undofile::FS_SEARCHING:
- jam();
- find_log_head_in_file(signal, lg_ptr, ptr, lsn);
- return;
- default:
- case Undofile::FS_EXECUTING:
- case Undofile::FS_CREATING:
- case Undofile::FS_DROPPING:
- case Undofile::FS_ONLINE:
- case Undofile::FS_OPENING:
- case Undofile::FS_EMPTY:
- jam();
- ndbrequire(false);
- }
-
- /**
- * Prepare for execution
- */
- ptr.p->m_state = Undofile::FS_EXECUTING;
- ptr.p->m_online.m_lsn = lsn;
-
- /**
- * Insert into m_files
- */
- {
- Local_undofile_list meta(m_file_pool, lg_ptr.p->m_meta_files);
- Local_undofile_list files(m_file_pool, lg_ptr.p->m_files);
- meta.remove(ptr);
-
- Ptr<Undofile> loop;
- files.first(loop);
- while(!loop.isNull() && loop.p->m_online.m_lsn <= lsn)
- files.next(loop);
-
- if(loop.isNull())
- {
- /**
- * File has highest lsn, add last
- */
- jam();
- files.add(ptr);
- }
- else
- {
- /**
- * Insert file in correct position in file list
- */
- files.insert(ptr, loop);
- }
- }
- find_log_head(signal, lg_ptr);
-}
-
-void
-Lgman::execFSREADREF(Signal* signal)
-{
- jamEntry();
- SimulatedBlock::execFSREADREF(signal);
- ndbrequire(false);
-}
-
-void
-Lgman::find_log_head_in_file(Signal* signal,
- Ptr<Logfile_group> ptr,
- Ptr<Undofile> file_ptr,
- Uint64 last_lsn)
-{
- // a b
- // 3 4 5 0 1
- Uint32 curr= ptr.p->m_file_pos[HEAD].m_ptr_i;
- Uint32 head= ptr.p->m_file_pos[HEAD].m_idx;
- Uint32 tail= ptr.p->m_file_pos[TAIL].m_idx;
-
- ndbrequire(head > tail);
- Uint32 diff = head - tail;
-
- if(DEBUG_SEARCH_LOG_HEAD)
- printf("tail: %d(%lld) head: %d last: %d(%lld) -> ",
- tail, file_ptr.p->m_online.m_lsn,
- head, curr, last_lsn);
- if(last_lsn > file_ptr.p->m_online.m_lsn)
- {
- if(DEBUG_SEARCH_LOG_HEAD)
- printf("moving tail ");
-
- file_ptr.p->m_online.m_lsn = last_lsn;
- ptr.p->m_file_pos[TAIL].m_idx = tail = curr;
- }
- else
- {
- if(DEBUG_SEARCH_LOG_HEAD)
- printf("moving head ");
-
- ptr.p->m_file_pos[HEAD].m_idx = head = curr;
- }
-
- if(diff > 1)
- {
- // We need to find more pages to be sure...
- ptr.p->m_file_pos[HEAD].m_ptr_i = curr = ((head + tail) >> 1);
-
- if(DEBUG_SEARCH_LOG_HEAD)
- ndbout_c("-> new search tail: %d(%lld) head: %d -> %d",
- tail, file_ptr.p->m_online.m_lsn,
- head, curr);
-
- Uint32 page_id = ptr.p->m_pos[CONSUMER].m_current_pos.m_ptr_i;
- file_ptr.p->m_online.m_outstanding= page_id;
-
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = file_ptr.p->m_fd;
- req->userReference = reference();
- req->userPointer = file_ptr.i;
- req->varIndex = curr;
- req->numberOfPages = 1;
- req->data.pageData[0] = page_id;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatSharedPage);
-
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-
- ptr.p->m_outstanding_fs++;
- file_ptr.p->m_state |= Undofile::FS_OUTSTANDING;
- return;
- }
-
- ndbrequire(diff == 1);
- if(DEBUG_SEARCH_LOG_HEAD)
- ndbout_c("-> found last page: %d", tail);
-
- ptr.p->m_state = 0;
- file_ptr.p->m_state = Undofile::FS_EXECUTING;
- ptr.p->m_last_lsn = file_ptr.p->m_online.m_lsn;
- ptr.p->m_last_read_lsn = file_ptr.p->m_online.m_lsn;
- ptr.p->m_last_synced_lsn = file_ptr.p->m_online.m_lsn;
- m_last_lsn = file_ptr.p->m_online.m_lsn;
-
- /**
- * Set HEAD position
- */
- ptr.p->m_file_pos[HEAD].m_ptr_i = file_ptr.i;
- ptr.p->m_file_pos[HEAD].m_idx = tail;
-
- ptr.p->m_file_pos[TAIL].m_ptr_i = file_ptr.i;
- ptr.p->m_file_pos[TAIL].m_idx = tail - 1;
- ptr.p->m_next_reply_ptr_i = file_ptr.i;
-
- {
- Local_undofile_list files(m_file_pool, ptr.p->m_files);
- if(tail == 1)
- {
- /**
- * HEAD is first page in a file...
- * -> PREV should be in previous file
- */
- Ptr<Undofile> prev = file_ptr;
- if(!files.prev(prev))
- {
- files.last(prev);
- }
- ptr.p->m_file_pos[TAIL].m_ptr_i = prev.i;
- ptr.p->m_file_pos[TAIL].m_idx = prev.p->m_file_size - 1;
- ptr.p->m_next_reply_ptr_i = prev.i;
- }
-
- SimulatedBlock* fs = globalData.getBlock(NDBFS);
- infoEvent("Undo head - %s page: %d lsn: %lld",
- fs->get_filename(file_ptr.p->m_fd),
- tail, file_ptr.p->m_online.m_lsn);
- g_eventLogger.info("Undo head - %s page: %d lsn: %lld",
- fs->get_filename(file_ptr.p->m_fd),
- tail, file_ptr.p->m_online.m_lsn);
-
- for(files.prev(file_ptr); !file_ptr.isNull(); files.prev(file_ptr))
- {
- infoEvent(" - next - %s(%lld)",
- fs->get_filename(file_ptr.p->m_fd),
- file_ptr.p->m_online.m_lsn);
-
- g_eventLogger.info(" - next - %s(%lld)",
- fs->get_filename(file_ptr.p->m_fd),
- file_ptr.p->m_online.m_lsn);
- }
- }
-
- /**
- * Start next logfile group
- */
- m_logfile_group_list.next(ptr);
- signal->theData[0] = LgmanContinueB::FIND_LOG_HEAD;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Lgman::init_run_undo_log(Signal* signal)
-{
- /**
- * Perform initial sorting of logfile groups
- */
- Ptr<Logfile_group> group;
- Logfile_group_list& list= m_logfile_group_list;
- Logfile_group_list tmp(m_logfile_group_pool);
-
- list.first(group);
- while(!group.isNull())
- {
- Ptr<Logfile_group> ptr= group;
- list.next(group);
- list.remove(ptr);
-
- {
- /**
- * Init buffer pointers
- */
- ptr.p->m_free_buffer_words -= File_formats::UNDO_PAGE_WORDS;
- ptr.p->m_pos[CONSUMER].m_current_page.m_idx = 0; // 0 more pages read
- ptr.p->m_pos[PRODUCER].m_current_page.m_idx = 0; // 0 more pages read
-
- Uint32 page = ptr.p->m_pos[CONSUMER].m_current_pos.m_ptr_i;
- File_formats::Undofile::Undo_page* pageP =
- (File_formats::Undofile::Undo_page*)m_shared_page_pool.getPtr(page);
-
- ptr.p->m_pos[CONSUMER].m_current_pos.m_idx = pageP->m_words_used;
- ptr.p->m_pos[PRODUCER].m_current_pos.m_idx = 1;
- ptr.p->m_last_read_lsn++;
- }
-
- /**
- * Start producer thread
- */
- signal->theData[0] = LgmanContinueB::READ_UNDO_LOG;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-
- /**
- * Insert in correct position in list of logfile_group's
- */
- Ptr<Logfile_group> pos;
- for(tmp.first(pos); !pos.isNull(); tmp.next(pos))
- if(ptr.p->m_last_read_lsn >= pos.p->m_last_read_lsn)
- break;
-
- if(pos.isNull())
- tmp.add(ptr);
- else
- tmp.insert(ptr, pos);
-
- ptr.p->m_state =
- Logfile_group::LG_EXEC_THREAD | Logfile_group::LG_READ_THREAD;
- }
- list = tmp;
-
- execute_undo_record(signal);
-}
-
-void
-Lgman::read_undo_log(Signal* signal, Ptr<Logfile_group> ptr)
-{
- Uint32 cnt, free= ptr.p->m_free_buffer_words;
-
- if(! (ptr.p->m_state & Logfile_group::LG_EXEC_THREAD))
- {
- jam();
- /**
- * Logfile_group is done...
- */
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_READ_THREAD;
- stop_run_undo_log(signal);
- return;
- }
-
- if(free <= File_formats::UNDO_PAGE_WORDS)
- {
- signal->theData[0] = LgmanContinueB::READ_UNDO_LOG;
- signal->theData[1] = ptr.i;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
- return;
- }
-
- Logfile_group::Position producer= ptr.p->m_pos[PRODUCER];
- Logfile_group::Position consumer= ptr.p->m_pos[CONSUMER];
-
- if(producer.m_current_page.m_idx == 0)
- {
- /**
- * zero pages left in range -> switch range
- */
- Lgman::Page_map::Iterator it;
- Page_map map(m_data_buffer_pool, ptr.p->m_buffer_pages);
- Uint32 sz = map.getSize();
- Uint32 pos= (producer.m_current_page.m_ptr_i + sz - 2) % sz;
- map.position(it, pos);
- union {
- Uint32 _tmp[2];
- Lgman::Buffer_idx range;
- };
- _tmp[0] = *it.data; map.next(it); _tmp[1] = *it.data;
- producer.m_current_page.m_ptr_i = pos;
- producer.m_current_page.m_idx = range.m_idx;
- producer.m_current_pos.m_ptr_i = range.m_ptr_i + range.m_idx;
- }
-
- if(producer.m_current_page.m_ptr_i == consumer.m_current_page.m_ptr_i &&
- producer.m_current_pos.m_ptr_i > consumer.m_current_pos.m_ptr_i)
- {
- Uint32 max=
- producer.m_current_pos.m_ptr_i - consumer.m_current_pos.m_ptr_i - 1;
- ndbrequire(free >= max * File_formats::UNDO_PAGE_WORDS);
- cnt= read_undo_pages(signal, ptr, producer.m_current_pos.m_ptr_i, max);
- ndbrequire(cnt <= max);
- producer.m_current_pos.m_ptr_i -= cnt;
- producer.m_current_page.m_idx -= cnt;
- }
- else
- {
- Uint32 max= producer.m_current_page.m_idx;
- ndbrequire(free >= max * File_formats::UNDO_PAGE_WORDS);
- cnt= read_undo_pages(signal, ptr, producer.m_current_pos.m_ptr_i, max);
- ndbrequire(cnt <= max);
- producer.m_current_pos.m_ptr_i -= cnt;
- producer.m_current_page.m_idx -= cnt;
- }
-
- ndbrequire(free >= cnt * File_formats::UNDO_PAGE_WORDS);
- free -= (cnt * File_formats::UNDO_PAGE_WORDS);
- ptr.p->m_free_buffer_words = free;
- ptr.p->m_pos[PRODUCER] = producer;
-
- signal->theData[0] = LgmanContinueB::READ_UNDO_LOG;
- signal->theData[1] = ptr.i;
-
- if(free > File_formats::UNDO_PAGE_WORDS)
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- else
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
-}
-
-Uint32
-Lgman::read_undo_pages(Signal* signal, Ptr<Logfile_group> ptr,
- Uint32 pageId, Uint32 pages)
-{
- ndbrequire(pages);
- Ptr<Undofile> filePtr;
- Buffer_idx tail= ptr.p->m_file_pos[TAIL];
- m_file_pool.getPtr(filePtr, tail.m_ptr_i);
-
- if(filePtr.p->m_online.m_outstanding > 0)
- {
- jam();
- return 0;
- }
-
- Uint32 max= tail.m_idx;
-
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = filePtr.p->m_fd;
- req->userReference = reference();
- req->userPointer = filePtr.i;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatSharedPage);
-
-
- if(max > pages)
- {
- jam();
- tail.m_idx -= pages;
-
- req->varIndex = 1 + tail.m_idx;
- req->numberOfPages = pages;
- req->data.pageData[0] = pageId - pages;
- ptr.p->m_file_pos[TAIL] = tail;
-
- if(DEBUG_UNDO_EXECUTION)
- ndbout_c("a reading from file: %d page(%d-%d) into (%d-%d)",
- ptr.i, 1 + tail.m_idx, 1+tail.m_idx+pages-1,
- pageId - pages, pageId - 1);
-
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-
- ptr.p->m_outstanding_fs++;
- filePtr.p->m_state |= Undofile::FS_OUTSTANDING;
- filePtr.p->m_online.m_outstanding = pages;
- max = pages;
- }
- else
- {
- jam();
-
- ndbrequire(tail.m_idx - max == 0);
- req->varIndex = 1;
- req->numberOfPages = max;
- req->data.pageData[0] = pageId - max;
-
- if(DEBUG_UNDO_EXECUTION)
- ndbout_c("b reading from file: %d page(%d-%d) into (%d-%d)",
- ptr.i, 1 , 1+max-1,
- pageId - max, pageId - 1);
-
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-
- ptr.p->m_outstanding_fs++;
- filePtr.p->m_online.m_outstanding = max;
- filePtr.p->m_state |= Undofile::FS_OUTSTANDING | Undofile::FS_MOVE_NEXT;
-
- Ptr<Undofile> prev = filePtr;
- {
- Local_undofile_list files(m_file_pool, ptr.p->m_files);
- if(!files.prev(prev))
- {
- jam();
- files.last(prev);
- }
- }
- if(DEBUG_UNDO_EXECUTION)
- ndbout_c("changing file from %d to %d", filePtr.i, prev.i);
-
- tail.m_idx= prev.p->m_file_size - 1;
- tail.m_ptr_i= prev.i;
- ptr.p->m_file_pos[TAIL] = tail;
- if(max < pages && filePtr.i != prev.i)
- max += read_undo_pages(signal, ptr, pageId - max, pages - max);
- }
-
- return max;
-
-}
-
-void
-Lgman::execute_undo_record(Signal* signal)
-{
- Uint64 lsn;
- const Uint32* ptr;
- Dbtup* tup= (Dbtup*)globalData.getBlock(DBTUP);
- if((ptr = get_next_undo_record(&lsn)))
- {
- Uint32 len= (* ptr) & 0xFFFF;
- Uint32 type= (* ptr) >> 16;
- Uint32 mask= type & ~(Uint32)File_formats::Undofile::UNDO_NEXT_LSN;
- switch(mask){
- case File_formats::Undofile::UNDO_END:
- stop_run_undo_log(signal);
- return;
- case File_formats::Undofile::UNDO_LCP:
- case File_formats::Undofile::UNDO_LCP_FIRST:
- {
- Uint32 lcp = * (ptr - len + 1);
- if(m_latest_lcp && lcp > m_latest_lcp)
- {
- if (0)
- {
- const Uint32 * base = ptr - len + 1;
- Uint32 lcp = base[0];
- Uint32 tableId = base[1] >> 16;
- Uint32 fragId = base[1] & 0xFFFF;
-
- ndbout_c("NOT! ignoring lcp: %u tab: %u frag: %u",
- lcp, tableId, fragId);
- }
- }
-
- if(m_latest_lcp == 0 ||
- lcp < m_latest_lcp ||
- (lcp == m_latest_lcp &&
- mask == File_formats::Undofile::UNDO_LCP_FIRST))
- {
- stop_run_undo_log(signal);
- return;
- }
- // Fallthrough
- }
- case File_formats::Undofile::UNDO_TUP_ALLOC:
- case File_formats::Undofile::UNDO_TUP_UPDATE:
- case File_formats::Undofile::UNDO_TUP_FREE:
- case File_formats::Undofile::UNDO_TUP_CREATE:
- case File_formats::Undofile::UNDO_TUP_DROP:
- case File_formats::Undofile::UNDO_TUP_ALLOC_EXTENT:
- case File_formats::Undofile::UNDO_TUP_FREE_EXTENT:
- tup->disk_restart_undo(signal, lsn, mask, ptr - len + 1, len);
- return;
- default:
- ndbrequire(false);
- }
- }
- signal->theData[0] = LgmanContinueB::EXECUTE_UNDO_RECORD;
- sendSignal(LGMAN_REF, GSN_CONTINUEB, signal, 1, JBB);
-
- return;
-}
-
-const Uint32*
-Lgman::get_next_undo_record(Uint64 * this_lsn)
-{
- Ptr<Logfile_group> ptr;
- m_logfile_group_list.first(ptr);
-
- Logfile_group::Position consumer= ptr.p->m_pos[CONSUMER];
- Logfile_group::Position producer= ptr.p->m_pos[PRODUCER];
- if(producer.m_current_pos.m_idx < 2)
- {
- jam();
- /**
- * Wait for fetching pages...
- */
- return 0;
- }
-
- Uint32 pos = consumer.m_current_pos.m_idx;
- Uint32 page = consumer.m_current_pos.m_ptr_i;
-
- File_formats::Undofile::Undo_page* pageP=(File_formats::Undofile::Undo_page*)
- m_shared_page_pool.getPtr(page);
-
- if(pos == 0)
- {
- /**
- * End of log
- */
- pageP->m_data[0] = (File_formats::Undofile::UNDO_END << 16) | 1 ;
- pageP->m_page_header.m_page_lsn_hi = 0;
- pageP->m_page_header.m_page_lsn_lo = 0;
- pos= consumer.m_current_pos.m_idx= pageP->m_words_used = 1;
- this_lsn = 0;
- return pageP->m_data;
- }
-
- Uint32 *record= pageP->m_data + pos - 1;
- Uint32 len= (* record) & 0xFFFF;
- ndbrequire(len);
- Uint32 *prev= record - len;
- Uint64 lsn = 0;
-
- // Same page
- if(((* record) >> 16) & File_formats::Undofile::UNDO_NEXT_LSN)
- {
- lsn = ptr.p->m_last_read_lsn - 1;
- ndbrequire((Int64)lsn >= 0);
- }
- else
- {
- ndbrequire(pos >= 3);
- lsn += * (prev - 1); lsn <<= 32;
- lsn += * (prev - 0);
- len += 2;
- ndbrequire((Int64)lsn >= 0);
- }
-
-
- ndbrequire(pos >= len);
-
- if(pos == len)
- {
- /**
- * Switching page
- */
- ndbrequire(producer.m_current_pos.m_idx);
- ptr.p->m_pos[PRODUCER].m_current_pos.m_idx --;
-
- if(consumer.m_current_page.m_idx)
- {
- consumer.m_current_page.m_idx--; // left in range
- consumer.m_current_pos.m_ptr_i --; // page
- }
- else
- {
- // 0 pages left in range...switch range
- Lgman::Page_map::Iterator it;
- Page_map map(m_data_buffer_pool, ptr.p->m_buffer_pages);
- Uint32 sz = map.getSize();
- Uint32 tmp = (consumer.m_current_page.m_ptr_i + sz - 2) % sz;
-
- map.position(it, tmp);
- union {
- Uint32 _tmp[2];
- Lgman::Buffer_idx range;
- };
-
- _tmp[0] = *it.data; map.next(it); _tmp[1] = *it.data;
-
- consumer.m_current_page.m_idx = range.m_idx - 1; // left in range
- consumer.m_current_page.m_ptr_i = tmp; // pos in map
-
- consumer.m_current_pos.m_ptr_i = range.m_ptr_i + range.m_idx - 1; // page
- }
-
- if(DEBUG_UNDO_EXECUTION)
- ndbout_c("reading from %d", consumer.m_current_pos.m_ptr_i);
-
- pageP=(File_formats::Undofile::Undo_page*)
- m_shared_page_pool.getPtr(consumer.m_current_pos.m_ptr_i);
-
- pos= consumer.m_current_pos.m_idx= pageP->m_words_used;
-
- Uint64 tmp = 0;
- tmp += pageP->m_page_header.m_page_lsn_hi; tmp <<= 32;
- tmp += pageP->m_page_header.m_page_lsn_lo;
-
- prev = pageP->m_data + pos - 1;
-
- if(((* prev) >> 16) & File_formats::Undofile::UNDO_NEXT_LSN)
- ndbrequire(lsn + 1 == ptr.p->m_last_read_lsn);
-
- ptr.p->m_pos[CONSUMER] = consumer;
- ptr.p->m_free_buffer_words += File_formats::UNDO_PAGE_WORDS;
- }
- else
- {
- ptr.p->m_pos[CONSUMER].m_current_pos.m_idx -= len;
- }
-
- * this_lsn = ptr.p->m_last_read_lsn = lsn;
-
- /**
- * Re-sort log file groups
- */
- Ptr<Logfile_group> sort = ptr;
- if(m_logfile_group_list.next(sort))
- {
- while(!sort.isNull() && sort.p->m_last_read_lsn > lsn)
- m_logfile_group_list.next(sort);
-
- if(sort.i != ptr.p->nextList)
- {
- m_logfile_group_list.remove(ptr);
- if(sort.isNull())
- m_logfile_group_list.add(ptr);
- else
- m_logfile_group_list.insert(ptr, sort);
- }
- }
- return record;
-}
-
-void
-Lgman::stop_run_undo_log(Signal* signal)
-{
- bool running = false, outstanding = false;
- Ptr<Logfile_group> ptr;
- m_logfile_group_list.first(ptr);
- while(!ptr.isNull())
- {
- /**
- * Mark exec thread as completed
- */
- ptr.p->m_state &= ~(Uint32)Logfile_group::LG_EXEC_THREAD;
-
- if(ptr.p->m_state & Logfile_group::LG_READ_THREAD)
- {
- /**
- * Thread is still running...wait for it to complete
- */
- running = true;
- }
- else if(ptr.p->m_outstanding_fs)
- {
- outstanding = true; // a FSREADREQ is outstanding...wait for it
- }
- else if(ptr.p->m_state != Logfile_group::LG_ONLINE)
- {
- /**
- * Fix log TAIL
- */
- ndbrequire(ptr.p->m_state == 0);
- ptr.p->m_state = Logfile_group::LG_ONLINE;
- Buffer_idx tail= ptr.p->m_file_pos[TAIL];
- Uint32 pages= ptr.p->m_pos[PRODUCER].m_current_pos.m_idx;
-
- while(pages)
- {
- Ptr<Undofile> file;
- m_file_pool.getPtr(file, tail.m_ptr_i);
- Uint32 page= tail.m_idx;
- Uint32 size= file.p->m_file_size;
- ndbrequire(size >= page);
- Uint32 diff= size - page;
-
- if(pages >= diff)
- {
- pages -= diff;
- Local_undofile_list files(m_file_pool, ptr.p->m_files);
- if(!files.next(file))
- files.first(file);
- tail.m_idx = 1;
- tail.m_ptr_i= file.i;
- }
- else
- {
- tail.m_idx += pages;
- pages= 0;
- }
- }
- ptr.p->m_tail_pos[0] = tail;
- ptr.p->m_tail_pos[1] = tail;
- ptr.p->m_tail_pos[2] = tail;
- ptr.p->m_file_pos[TAIL] = tail;
-
- init_logbuffer_pointers(ptr);
-
- {
- Buffer_idx head= ptr.p->m_file_pos[HEAD];
- Ptr<Undofile> file;
- m_file_pool.getPtr(file, head.m_ptr_i);
- if (head.m_idx == file.p->m_file_size - 1)
- {
- Local_undofile_list files(m_file_pool, ptr.p->m_files);
- if(!files.next(file))
- {
- jam();
- files.first(file);
- }
- head.m_idx = 0;
- head.m_ptr_i = file.i;
- ptr.p->m_file_pos[HEAD] = head;
- }
- }
-
- ptr.p->m_free_file_words = (Uint64)File_formats::UNDO_PAGE_WORDS *
- (Uint64)compute_free_file_pages(ptr);
- ptr.p->m_next_reply_ptr_i = ptr.p->m_file_pos[HEAD].m_ptr_i;
-
- ptr.p->m_state |= Logfile_group::LG_FLUSH_THREAD;
- signal->theData[0] = LgmanContinueB::FLUSH_LOG;
- signal->theData[1] = ptr.i;
- signal->theData[2] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-
- if(1)
- {
- SimulatedBlock* fs = globalData.getBlock(NDBFS);
- Ptr<Undofile> hf, tf;
- m_file_pool.getPtr(tf, tail.m_ptr_i);
- m_file_pool.getPtr(hf, ptr.p->m_file_pos[HEAD].m_ptr_i);
- infoEvent("Logfile group: %d ", ptr.p->m_logfile_group_id);
- g_eventLogger.info("Logfile group: %d ", ptr.p->m_logfile_group_id);
- infoEvent(" head: %s page: %d",
- fs->get_filename(hf.p->m_fd),
- ptr.p->m_file_pos[HEAD].m_idx);
- g_eventLogger.info(" head: %s page: %d",
- fs->get_filename(hf.p->m_fd),
- ptr.p->m_file_pos[HEAD].m_idx);
- infoEvent(" tail: %s page: %d",
- fs->get_filename(tf.p->m_fd), tail.m_idx);
- g_eventLogger.info(" tail: %s page: %d",
- fs->get_filename(tf.p->m_fd), tail.m_idx);
- }
- }
-
- m_logfile_group_list.next(ptr);
- }
-
- if(running)
- {
- jam();
- return;
- }
-
- if(outstanding)
- {
- jam();
- signal->theData[0] = LgmanContinueB::STOP_UNDO_LOG;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
- return;
- }
-
- infoEvent("Flushing page cache after undo completion");
- g_eventLogger.info("Flushing page cache after undo completion");
-
- /**
- * Start flushing pages (local, LCP)
- */
- LcpFragOrd * ord = (LcpFragOrd *)signal->getDataPtr();
- ord->lcpId = m_latest_lcp;
- sendSignal(PGMAN_REF, GSN_LCP_FRAG_ORD, signal,
- LcpFragOrd::SignalLength, JBB);
-
- EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
- req->senderRef = reference();
- sendSignal(PGMAN_REF, GSN_END_LCP_REQ, signal,
- EndLcpReq::SignalLength, JBB);
-}
-
-void
-Lgman::execEND_LCP_CONF(Signal* signal)
-{
- Dbtup* tup= (Dbtup*)globalData.getBlock(DBTUP);
- tup->disk_restart_undo(signal, 0, File_formats::Undofile::UNDO_END, 0, 0);
-
- /**
- * pgman has completed flushing all pages
- *
- * insert "fake" LCP record preventing undo to be "rerun"
- */
- Uint32 undo[3];
- undo[0] = m_latest_lcp;
- undo[1] = (0 << 16) | 0;
- undo[2] = (File_formats::Undofile::UNDO_LCP_FIRST << 16 )
- | (sizeof(undo) >> 2);
-
- Ptr<Logfile_group> ptr;
- ndbrequire(m_logfile_group_list.first(ptr));
-
- Uint64 last_lsn= m_last_lsn;
- if(ptr.p->m_last_lsn == last_lsn
-#ifdef VM_TRACE
- && ((rand() % 100) > 50)
-#endif
- )
- {
- undo[2] |= File_formats::Undofile::UNDO_NEXT_LSN << 16;
- Uint32 *dst= get_log_buffer(ptr, sizeof(undo) >> 2);
- memcpy(dst, undo, sizeof(undo));
- ndbrequire(ptr.p->m_free_file_words >= (sizeof(undo) >> 2));
- ptr.p->m_free_file_words -= (sizeof(undo) >> 2);
- }
- else
- {
- Uint32 *dst= get_log_buffer(ptr, (sizeof(undo) >> 2) + 2);
- * dst++ = last_lsn >> 32;
- * dst++ = last_lsn & 0xFFFFFFFF;
- memcpy(dst, undo, sizeof(undo));
- ndbrequire(ptr.p->m_free_file_words >= ((sizeof(undo) >> 2) + 2));
- ptr.p->m_free_file_words -= ((sizeof(undo) >> 2) + 2);
- }
- m_last_lsn = ptr.p->m_last_lsn = last_lsn + 1;
-
- ptr.p->m_last_synced_lsn = last_lsn;
- while(m_logfile_group_list.next(ptr))
- ptr.p->m_last_synced_lsn = last_lsn;
-
- infoEvent("Flushing complete");
- g_eventLogger.info("Flushing complete");
-
- signal->theData[0] = reference();
- sendSignal(DBLQH_REF, GSN_START_RECCONF, signal, 1, JBB);
-}
-
-#ifdef VM_TRACE
-void
-Lgman::validate_logfile_group(Ptr<Logfile_group> ptr, const char * heading)
-{
- do
- {
- if (ptr.p->m_file_pos[HEAD].m_ptr_i == RNIL)
- break;
-
- Uint32 pages = compute_free_file_pages(ptr);
-
- Uint32 group_pages =
- ((ptr.p->m_free_file_words + File_formats::UNDO_PAGE_WORDS - 1)/ File_formats::UNDO_PAGE_WORDS) ;
- Uint32 last = ptr.p->m_free_file_words % File_formats::UNDO_PAGE_WORDS;
-
- if(! (pages >= group_pages))
- {
- ndbout << heading << " Tail: " << ptr.p->m_file_pos[TAIL]
- << " Head: " << ptr.p->m_file_pos[HEAD]
- << " free: " << group_pages << "(" << last << ")"
- << " found: " << pages;
- for(Uint32 i = 0; i<3; i++)
- {
- ndbout << " - " << ptr.p->m_tail_pos[i];
- }
- ndbout << endl;
-
- ndbrequire(pages >= group_pages);
- }
- } while(0);
-}
-#endif
-
-void Lgman::execGET_TABINFOREQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal))
- {
- return;
- }
-
- GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
-
- const Uint32 reqType = req->requestType & (~GetTabInfoReq::LongSignalConf);
- BlockReference retRef= req->senderRef;
- Uint32 senderData= req->senderData;
- Uint32 tableId= req->tableId;
-
- if(reqType == GetTabInfoReq::RequestByName){
- jam();
- if(signal->getNoOfSections())
- releaseSections(signal);
-
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::NoFetchByName);
- return;
- }
-
- Logfile_group key;
- key.m_logfile_group_id= tableId;
- Ptr<Logfile_group> ptr;
- m_logfile_group_hash.find(ptr, key);
-
- if(ptr.p->m_logfile_group_id != tableId)
- {
- jam();
- if(signal->getNoOfSections())
- releaseSections(signal);
-
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::InvalidTableId);
- return;
- }
-
-
- GetTabInfoConf *conf = (GetTabInfoConf *)&signal->theData[0];
-
- conf->senderData= senderData;
- conf->tableId= tableId;
- conf->freeWordsHi= ptr.p->m_free_file_words >> 32;
- conf->freeWordsLo= ptr.p->m_free_file_words & 0xFFFFFFFF;
- conf->tableType= DictTabInfo::LogfileGroup;
- conf->senderRef= reference();
- sendSignal(retRef, GSN_GET_TABINFO_CONF, signal,
- GetTabInfoConf::SignalLength, JBB);
-}
-
-void Lgman::sendGET_TABINFOREF(Signal* signal,
- GetTabInfoReq * req,
- GetTabInfoRef::ErrorCode errorCode)
-{
- jamEntry();
- GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
- /**
- * The format of GetTabInfo Req/Ref is the same
- */
- BlockReference retRef = req->senderRef;
- ref->errorCode = errorCode;
-
- sendSignal(retRef, GSN_GET_TABINFOREF, signal, signal->length(), JBB);
-}
diff --git a/storage/ndb/src/kernel/blocks/lgman.hpp b/storage/ndb/src/kernel/blocks/lgman.hpp
deleted file mode 100644
index c15e0d029e6..00000000000
--- a/storage/ndb/src/kernel/blocks/lgman.hpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef LGMAN_H
-#define LGMAN_H
-
-#include <SimulatedBlock.hpp>
-
-#include <SLList.hpp>
-#include <DLList.hpp>
-#include <DLFifoList.hpp>
-#include <KeyTable.hpp>
-#include <DLHashTable.hpp>
-#include <NodeBitmask.hpp>
-#include "diskpage.hpp"
-#include <signaldata/GetTabInfo.hpp>
-
-#include <WOPool.hpp>
-#include <SLFifoList.hpp>
-
-class Lgman : public SimulatedBlock
-{
-public:
- Lgman(Block_context& ctx);
- virtual ~Lgman();
- BLOCK_DEFINES(Lgman);
-
-protected:
-
- void execSTTOR(Signal* signal);
- void sendSTTORRY(Signal*);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execDUMP_STATE_ORD(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- void execCREATE_FILE_REQ(Signal* signal);
- void execCREATE_FILEGROUP_REQ(Signal* signal);
- void execDROP_FILE_REQ(Signal* signal);
- void execDROP_FILEGROUP_REQ(Signal* signal);
-
- void execFSWRITEREQ(Signal*);
- void execFSWRITEREF(Signal*);
- void execFSWRITECONF(Signal*);
-
- void execFSOPENREF(Signal*);
- void execFSOPENCONF(Signal*);
-
- void execFSCLOSEREF(Signal*);
- void execFSCLOSECONF(Signal*);
-
- void execFSREADREF(Signal*);
- void execFSREADCONF(Signal*);
-
- void execLCP_FRAG_ORD(Signal*);
- void execEND_LCP_REQ(Signal*);
- void execSUB_GCP_COMPLETE_REP(Signal*);
-
- void execSTART_RECREQ(Signal*);
- void execEND_LCP_CONF(Signal*);
-
- void execGET_TABINFOREQ(Signal*);
-
- void sendGET_TABINFOREF(Signal* signal,
- GetTabInfoReq * req,
- GetTabInfoRef::ErrorCode errorCode);
-
-public:
- struct Log_waiter
- {
- Callback m_callback;
- union {
- Uint32 m_size;
- Uint64 m_sync_lsn;
- };
- Uint32 m_block;
- Uint32 nextList;
- Uint32 m_magic;
- };
-
- typedef RecordPool<Log_waiter, WOPool> Log_waiter_pool;
- typedef SLFifoListImpl<Log_waiter_pool, Log_waiter> Log_waiter_list;
- typedef LocalSLFifoListImpl<Log_waiter_pool, Log_waiter> Local_log_waiter_list;
-
- struct Undofile
- {
- Undofile(){}
- Undofile(const struct CreateFileImplReq*, Uint32 lg_ptr_i);
-
- Uint32 m_magic;
- Uint32 m_file_id; // Dict obj id
- Uint32 m_logfile_group_ptr_i;
-
- Uint32 m_file_size;
- Uint32 m_state;
- Uint32 m_fd; // When speaking to NDBFS
-
- enum FileState
- {
- FS_CREATING = 0x1 // File is being created
- ,FS_DROPPING = 0x2 // File is being dropped
- ,FS_ONLINE = 0x4 // File is online
- ,FS_OPENING = 0x8 // File is being opened during SR
- ,FS_SORTING = 0x10 // Files in group are being sorted
- ,FS_SEARCHING = 0x20 // File is being searched for end of log
- ,FS_EXECUTING = 0x40 // File is used for executing UNDO log
- ,FS_EMPTY = 0x80 // File is empty (used when online)
- ,FS_OUTSTANDING = 0x100 // File has outstanding request
- ,FS_MOVE_NEXT = 0x200 // When receiving reply move to next file
- };
-
- union {
- struct {
- Uint32 m_outstanding; // Outstaning pages
- Uint64 m_lsn; // Used when finding log head
- } m_online;
- struct {
- Uint32 m_senderData;
- Uint32 m_senderRef;
- Uint32 m_logfile_group_id;
- Uint32 m_logfile_group_version;
- } m_create;
- };
-
- Uint32 nextList;
- union {
- Uint32 prevList;
- Uint32 nextPool;
- };
- };
-
- typedef RecordPool<Undofile, RWPool> Undofile_pool;
- typedef DLFifoListImpl<Undofile_pool, Undofile> Undofile_list;
- typedef LocalDLFifoListImpl<Undofile_pool, Undofile> Local_undofile_list;
- typedef LocalDataBuffer<15> Page_map;
-
- struct Buffer_idx
- {
- Uint32 m_ptr_i;
- Uint32 m_idx;
- bool operator== (const Buffer_idx& bi) const {
- return (m_ptr_i == bi.m_ptr_i && m_idx == bi.m_idx);
- }
- };
-
- struct Logfile_group
- {
- Logfile_group(){}
- Logfile_group(const struct CreateFilegroupImplReq*);
-
- Uint32 m_magic;
- union {
- Uint32 key;
- Uint32 m_logfile_group_id;
- };
- Uint32 m_version;
- Uint16 m_state;
- Uint16 m_outstanding_fs;
- Uint32 m_next_reply_ptr_i;
-
- enum Logfile_group_state
- {
- LG_ONLINE = 0x001
- ,LG_SORTING = 0x002 // Sorting files
- ,LG_SEARCHING = 0x004 // Searching in last file
- ,LG_EXEC_THREAD = 0x008 // Execute thread is running
- ,LG_READ_THREAD = 0x010 // Read thread is running
- ,LG_FORCE_SYNC_THREAD = 0x020
- ,LG_SYNC_WAITERS_THREAD = 0x040
- ,LG_CUT_LOG_THREAD = 0x080
- ,LG_WAITERS_THREAD = 0x100
- ,LG_FLUSH_THREAD = 0x200
- ,LG_DROPPING = 0x400
- ,LG_STARTING = 0x800
- };
-
- static const Uint32 LG_THREAD_MASK = Logfile_group::LG_FORCE_SYNC_THREAD |
- Logfile_group::LG_SYNC_WAITERS_THREAD |
- Logfile_group::LG_CUT_LOG_THREAD |
- Logfile_group::LG_WAITERS_THREAD |
- Logfile_group::LG_FLUSH_THREAD;
-
- Uint64 m_last_lsn;
- Uint64 m_last_sync_req_lsn; // Outstanding
- Uint64 m_last_synced_lsn; //
- Uint64 m_max_sync_req_lsn; // User requested lsn
- union {
- Uint64 m_last_read_lsn;
- Uint64 m_last_lcp_lsn;
- };
- Log_waiter_list::Head m_log_sync_waiters;
-
- Buffer_idx m_tail_pos[3]; // 0 is cut, 1 is saved, 2 is current
- Buffer_idx m_file_pos[2]; // 0 tail, 1 head = { file_ptr_i, page_no }
- Uint64 m_free_file_words; // Free words in logfile group
-
- Undofile_list::Head m_files; // Files in log
- Undofile_list::Head m_meta_files;// Files being created or dropped
-
- Uint32 m_free_buffer_words; // Free buffer page words
- Log_waiter_list::Head m_log_buffer_waiters;
- Page_map::Head m_buffer_pages; // Pairs of { ptr.i, count }
- struct Position {
- Buffer_idx m_current_page; // { m_buffer_pages.i, left in range }
- Buffer_idx m_current_pos; // { page ptr.i, m_words_used }
- } m_pos[2]; // 0 is reader (lgman) 1 is writer (tup)
-
- Uint32 nextHash;
- Uint32 prevHash;
- Uint32 nextList;
- union {
- Uint32 prevList;
- Uint32 nextPool;
- };
- Uint32 hashValue() const {
- return key;
- }
- bool equal(const Logfile_group& rec) const {
- return key == rec.key;
- }
- };
-
- typedef RecordPool<Logfile_group, RWPool> Logfile_group_pool;
- typedef DLFifoListImpl<Logfile_group_pool, Logfile_group> Logfile_group_list;
- typedef LocalDLFifoListImpl<Logfile_group_pool, Logfile_group> Local_logfile_group_list;
- typedef KeyTableImpl<Logfile_group_pool, Logfile_group> Logfile_group_hash;
-
- /**
- * Alloc/free space in log
- * Alloction will be removed at either/or
- * 1) Logfile_client::add_entry
- * 2) free_log_space
- */
- int alloc_log_space(Uint32 logfile_ref, Uint32 words);
- int free_log_space(Uint32 logfile_ref, Uint32 words);
-
-private:
- friend class Logfile_client;
-
- Undofile_pool m_file_pool;
- Logfile_group_pool m_logfile_group_pool;
- Log_waiter_pool m_log_waiter_pool;
-
- Page_map::DataBufferPool m_data_buffer_pool;
-
- Uint64 m_last_lsn;
- Uint32 m_latest_lcp;
- Logfile_group_list m_logfile_group_list;
- Logfile_group_hash m_logfile_group_hash;
-
- bool alloc_logbuffer_memory(Ptr<Logfile_group>, Uint32 pages);
- void init_logbuffer_pointers(Ptr<Logfile_group>);
- void free_logbuffer_memory(Ptr<Logfile_group>);
- Uint32 compute_free_file_pages(Ptr<Logfile_group>);
- Uint32* get_log_buffer(Ptr<Logfile_group>, Uint32 sz);
- void process_log_buffer_waiters(Signal* signal, Ptr<Logfile_group>);
- Uint32 next_page(Logfile_group* ptrP, Uint32 i);
-
- void force_log_sync(Signal*, Ptr<Logfile_group>, Uint32 lsnhi, Uint32 lnslo);
- void process_log_sync_waiters(Signal* signal, Ptr<Logfile_group>);
-
- void cut_log_tail(Signal*, Ptr<Logfile_group> ptr);
- void endlcp_callback(Signal*, Uint32, Uint32);
- void open_file(Signal*, Ptr<Undofile>, Uint32 requestInfo);
-
- void flush_log(Signal*, Ptr<Logfile_group>, Uint32 force);
- Uint32 write_log_pages(Signal*, Ptr<Logfile_group>,
- Uint32 pageId, Uint32 pages);
-
- void find_log_head(Signal* signal, Ptr<Logfile_group> ptr);
- void find_log_head_in_file(Signal*, Ptr<Logfile_group>,Ptr<Undofile>,Uint64);
-
- void init_run_undo_log(Signal*);
- void read_undo_log(Signal*, Ptr<Logfile_group> ptr);
- Uint32 read_undo_pages(Signal*, Ptr<Logfile_group>,
- Uint32 pageId, Uint32 pages);
-
- void execute_undo_record(Signal*);
- const Uint32* get_next_undo_record(Uint64* lsn);
- void stop_run_undo_log(Signal* signal);
- void init_tail_ptr(Signal* signal, Ptr<Logfile_group> ptr);
-
- bool find_file_by_id(Ptr<Undofile>&, Undofile_list::Head&, Uint32 id);
- void create_file_commit(Signal* signal, Ptr<Logfile_group>, Ptr<Undofile>);
- void create_file_abort(Signal* signal, Ptr<Logfile_group>, Ptr<Undofile>);
-
-#ifdef VM_TRACE
- void validate_logfile_group(Ptr<Logfile_group> ptr, const char * = 0);
-#else
- void validate_logfile_group(Ptr<Logfile_group> ptr, const char * = 0) {}
-#endif
-
- void drop_filegroup_drop_files(Signal*, Ptr<Logfile_group>,
- Uint32 ref, Uint32 data);
-};
-
-class Logfile_client {
- Uint32 m_block;
- Lgman * m_lgman;
-public:
- Uint32 m_logfile_group_id;
-
- Logfile_client() {}
- Logfile_client(SimulatedBlock* block, Lgman*, Uint32 logfile_group_id);
-
- struct Request
- {
- SimulatedBlock::Callback m_callback;
- };
-
- /**
- * Request flags
- */
- enum RequestFlags
- {
- };
-
- /**
- * Make sure a lsn is stored
- * @return -1, on error
- * 0, request in queued
- * >0, done
- */
- int sync_lsn(Signal*, Uint64, Request*, Uint32 flags);
-
- /**
- * Undolog entries
- */
- struct Change
- {
- const void * ptr;
- Uint32 len;
- };
-
- Uint64 add_entry(const void*, Uint32 len);
- Uint64 add_entry(const Change*, Uint32 cnt);
-
- Uint64 add_entry(Local_key, void * base, Change*);
- Uint64 add_entry(Local_key, Uint32 off, Uint32 change);
-
- /**
- * Check for space in log buffer
- *
- * return >0 if available
- * 0 on time slice
- * -1 on error
- */
- int get_log_buffer(Signal*, Uint32 sz, SimulatedBlock::Callback* m_callback);
-
-private:
- Uint32* get_log_buffer(Uint32 sz);
-};
-
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/mutexes.hpp b/storage/ndb/src/kernel/blocks/mutexes.hpp
deleted file mode 100644
index 64df5d45d27..00000000000
--- a/storage/ndb/src/kernel/blocks/mutexes.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef KERNEL_MUTEXES_HPP
-#define KERNEL_MUTEXES_HPP
-
-#include <ndb_types.h>
-
-/**
- * This mutex is used by:
- * DIH - before sending START_LCP to all participants
- * DICT - before commiting a CREATE TABLE
- * BACKUP - before sending DEFINE_BACKUP
- */
-#define DIH_START_LCP_MUTEX 0
-#define DICT_COMMIT_TABLE_MUTEX 0
-
-/**
- * This mutex is used by
- * DIH - before switching primary replica
- * BACKUP - before sending DEFINE_BACKUP
- */
-#define DIH_SWITCH_PRIMARY_MUTEX 1
-#define BACKUP_DEFINE_MUTEX 1
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp b/storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
deleted file mode 100644
index 03ed858db1e..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
+++ /dev/null
@@ -1,388 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef NDBCNTR_H
-#define NDBCNTR_H
-
-
-#include <pc.hpp>
-#include <SimulatedBlock.hpp>
-#include <ndb_limits.h>
-#include <signaldata/StopReq.hpp>
-#include <signaldata/ResumeReq.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/CntrStart.hpp>
-#include <signaldata/CheckNodeGroups.hpp>
-
-#include <signaldata/UpgradeStartup.hpp>
-
-#include <NodeState.hpp>
-#include <NdbTick.h>
-
-#ifdef NDBCNTR_C
-/*
-2.1 GLOBAL SYMBOLS
-------------------
-*/
-/*
-2.2 LOCAL SYMBOLS
------------------
-*/
-#define ZNO_NDB_BLOCKS 6 /* ACC, DICT, DIH, LQH, TC, TUP */
-
-#define ZNOT_AVAILABLE 913
-
-//------- OTHERS ---------------------------------------------
-#define ZSTARTUP 1
-#define ZSHUTDOWN 2
-
-#define ZSIZE_NDB_BLOCKS_REC 16 /* MAX BLOCKS IN NDB */
-#define ZSIZE_SYSTAB 2048
-#define ZSTART_PHASE_1 1
-#define ZSTART_PHASE_2 2
-#define ZSTART_PHASE_3 3
-#define ZSTART_PHASE_4 4
-#define ZSTART_PHASE_5 5
-#define ZSTART_PHASE_6 6
-#define ZSTART_PHASE_7 7
-#define ZSTART_PHASE_8 8
-#define ZSTART_PHASE_9 9
-#define ZSTART_PHASE_END 255
-#define ZWAITPOINT_4_1 1
-#define ZWAITPOINT_4_2 2
-#define ZWAITPOINT_5_1 3
-#define ZWAITPOINT_5_2 4
-#define ZWAITPOINT_6_1 5
-#define ZWAITPOINT_6_2 6
-#define ZWAITPOINT_7_1 7
-#define ZWAITPOINT_7_2 8
-#define ZSYSTAB_VERSION 1
-#endif
-
-class Ndbcntr: public SimulatedBlock {
-public:
-// Records
-
-/* FSREADREQ FSWRITEREQ */
-/**
- * 2.3 RECORDS AND FILESIZES
- * ------------------------------------------------------------
- */
-
- struct StartRecord {
- StartRecord() {}
- Uint64 m_startTime;
-
- void reset();
- NdbNodeBitmask m_starting;
- NdbNodeBitmask m_waiting; // == (m_withLog | m_withoutLog)
- NdbNodeBitmask m_withLog;
- NdbNodeBitmask m_withoutLog;
- Uint32 m_lastGci;
- Uint32 m_lastGciNodeId;
-
- Uint64 m_startPartialTimeout;
- Uint64 m_startPartitionedTimeout;
- Uint64 m_startFailureTimeout;
- struct {
- Uint32 m_nodeId;
- Uint32 m_lastGci;
- } m_logNodes[MAX_NDB_NODES];
- Uint32 m_logNodesCount;
- } c_start;
-
- struct NdbBlocksRec {
- BlockReference blockref;
- }; /* p2c: size = 2 bytes */
-
- typedef Ptr<NdbBlocksRec> NdbBlocksRecPtr;
-
- /**
- * Ndbcntr creates and initializes system tables on initial system start.
- * The tables are defined in static structs in NdbcntrSysTable.cpp.
- */
- struct SysColumn {
- unsigned pos;
- const char* name;
- // DictTabInfo
- DictTabInfo::ExtType type;
- Uint32 length;
- bool keyFlag;
- bool nullable;
- };
- struct SysTable {
- const char* name;
- unsigned columnCount;
- const SysColumn* columnList;
- // DictTabInfo
- DictTabInfo::TableType tableType;
- DictTabInfo::FragmentType fragmentType;
- bool tableLoggedFlag;
- // saved table id
- mutable Uint32 tableId;
- };
- struct SysIndex {
- const char* name;
- const SysTable* primaryTable;
- Uint32 columnCount;
- Uint32 columnList[4];
- // DictTabInfo
- DictTabInfo::TableType indexType;
- DictTabInfo::FragmentType fragmentType;
- bool indexLoggedFlag;
- // saved index table id
- mutable Uint32 indexId;
- };
- static const SysTable* g_sysTableList[];
- static const unsigned g_sysTableCount;
- // the system tables
- static const SysTable g_sysTable_SYSTAB_0;
- static const SysTable g_sysTable_NDBEVENTS_0;
-
-public:
- Ndbcntr(Block_context&);
- virtual ~Ndbcntr();
-
-private:
- BLOCK_DEFINES(Ndbcntr);
-
- // Transit signals
- void execAPI_START_REP(Signal*);
- void execCONTINUEB(Signal* signal);
- void execREAD_NODESCONF(Signal* signal);
- void execREAD_NODESREF(Signal* signal);
- void execCM_ADD_REP(Signal* signal);
- void execCNTR_START_REQ(Signal* signal);
- void execCNTR_START_REF(Signal* signal);
- void execCNTR_START_CONF(Signal* signal);
- void execCNTR_START_REP(Signal* signal);
- void execCNTR_WAITREP(Signal* signal);
- void execNODE_FAILREP(Signal* signal);
- void execSYSTEM_ERROR(Signal* signal);
-
- // 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);
- void execTCRELEASECONF(Signal* signal);
- void execTCRELEASEREF(Signal* signal);
- void execTCKEYCONF(Signal* signal);
- void execTCKEYREF(Signal* signal);
- void execTCROLLBACKREP(Signal* signal);
- void execGETGCICONF(Signal* signal);
- void execDIH_RESTARTCONF(Signal* signal);
- void execDIH_RESTARTREF(Signal* signal);
- void execCREATE_TABLE_REF(Signal* signal);
- void execCREATE_TABLE_CONF(Signal* signal);
- void execNDB_STTORRY(Signal* signal);
- void execNDB_STARTCONF(Signal* signal);
- void execREAD_NODESREQ(Signal* signal);
- void execNDB_STARTREF(Signal* signal);
-
- void execSTOP_PERM_REF(Signal* signal);
- void execSTOP_PERM_CONF(Signal* signal);
-
- void execSTOP_ME_REF(Signal* signal);
- void execSTOP_ME_CONF(Signal* signal);
-
- void execWAIT_GCP_REF(Signal* signal);
- void execWAIT_GCP_CONF(Signal* signal);
-
- void execSTOP_REQ(Signal* signal);
- void execSTOP_CONF(Signal* signal);
- void execRESUME_REQ(Signal* signal);
-
- void execCHANGE_NODE_STATE_CONF(Signal* signal);
-
- void execABORT_ALL_REF(Signal* signal);
- void execABORT_ALL_CONF(Signal* signal);
-
- // Statement blocks
- void sendCreateTabReq(Signal* signal, const char* buffer, Uint32 bufLen);
- void startInsertTransactions(Signal* signal);
- void initData(Signal* signal);
- void resetStartVariables(Signal* signal);
- void sendCntrStartReq(Signal* signal);
- void sendCntrStartRef(Signal*, Uint32 nodeId, CntrStartRef::ErrorCode);
- void sendNdbSttor(Signal* signal);
- void sendSttorry(Signal* signal);
-
- bool trySystemRestart(Signal* signal);
- void startWaitingNodes(Signal* signal);
- CheckNodeGroups::Output checkNodeGroups(Signal*, const NdbNodeBitmask &);
-
- // Generated statement blocks
- void systemErrorLab(Signal* signal, int line);
-
- void createSystableLab(Signal* signal, unsigned index);
- void crSystab7Lab(Signal* signal);
- void crSystab8Lab(Signal* signal);
- void crSystab9Lab(Signal* signal);
-
- void startPhase1Lab(Signal* signal);
- void startPhase2Lab(Signal* signal);
- void startPhase3Lab(Signal* signal);
- void startPhase4Lab(Signal* signal);
- void startPhase5Lab(Signal* signal);
- // jump 2 to resync phase counters
- void startPhase8Lab(Signal* signal);
- void startPhase9Lab(Signal* signal);
- void ph2ALab(Signal* signal);
- void ph2CLab(Signal* signal);
- void ph2ELab(Signal* signal);
- void ph2FLab(Signal* signal);
- void ph2GLab(Signal* signal);
- void ph3ALab(Signal* signal);
- void ph4ALab(Signal* signal);
- void ph4BLab(Signal* signal);
- void ph4CLab(Signal* signal);
- void ph5ALab(Signal* signal);
- void ph6ALab(Signal* signal);
- void ph6BLab(Signal* signal);
- void ph7ALab(Signal* signal);
- void ph8ALab(Signal* signal);
-
-
- void waitpoint41Lab(Signal* signal);
- void waitpoint51Lab(Signal* signal);
- void waitpoint52Lab(Signal* signal);
- void waitpoint61Lab(Signal* signal);
- void waitpoint71Lab(Signal* signal);
-
- void updateNodeState(Signal* signal, const NodeState & newState) const ;
- void getNodeGroup(Signal* signal);
-
- // Initialisation
- void initData();
- void initRecords();
-
- // Variables
- /**------------------------------------------------------------------------
- * CONTAIN INFO ABOUT ALL NODES IN CLUSTER. NODE_PTR ARE USED AS NODE NUMBER
- * IF THE STATE ARE ZDELETE THEN THE NODE DOESN'T EXIST. NODES ARE ALLOWED
- * TO REGISTER (ZADD) DURING RESTART.
- *
- * WHEN THE SYSTEM IS RUNNING THE MASTER WILL CHECK IF ANY NODE HAS MADE
- * A CNTR_MASTERREQ AND TAKE CARE OF THE REQUEST.
- * TO CONFIRM THE REQ, THE MASTER DEMANDS THAT ALL RUNNING NODES HAS VOTED
- * FOR THE NEW NODE.
- * NODE_PTR:MASTER_REQ IS USED DURING RESTART TO LOG
- * POSTPONED CNTR_MASTERREQ'S
- *------------------------------------------------------------------------*/
- NdbBlocksRec *ndbBlocksRec;
-
- /*
- 2.4 COMMON STORED VARIABLES
- */
- UintR cgciSystab;
- UintR ckey;
- //UintR csystabId;
- UintR cnoWaitrep6;
- UintR cnoWaitrep7;
- UintR ctcConnectionP;
- UintR ctcReqInfo;
- Uint8 ctransidPhase;
- Uint16 cresponses;
-
- Uint8 cstartPhase;
- Uint16 cinternalStartphase;
-
- Uint16 cmasterNodeId;
- Uint16 cndbBlocksCount;
- Uint16 cnoStartNodes;
- UintR cnoWaitrep;
- NodeState::StartType ctypeOfStart;
- Uint16 cdynamicNodeId;
-
- Uint32 c_fsRemoveCount;
- Uint32 c_nodeGroup;
- void clearFilesystem(Signal* signal);
- void execFSREMOVECONF(Signal* signal);
-
- NdbNodeBitmask c_allDefinedNodes;
- NdbNodeBitmask c_clusterNodes; // All members of qmgr cluster
- NdbNodeBitmask c_startedNodes; // All cntr started nodes
-
-public:
- struct StopRecord {
- public:
- StopRecord(Ndbcntr & _cntr) : cntr(_cntr) {
- stopReq.senderRef = 0;
- }
-
- Ndbcntr & cntr;
- StopReq stopReq; // Signal data
- NDB_TICKS stopInitiatedTime; // When was the stop initiated
-
- bool checkNodeFail(Signal* signal);
- void checkTimeout(Signal* signal);
- void checkApiTimeout(Signal* signal);
- void checkTcTimeout(Signal* signal);
- void checkLqhTimeout_1(Signal* signal);
- void checkLqhTimeout_2(Signal* signal);
-
- BlockNumber number() const { return cntr.number(); }
- void progError(int line, int cause, const char * extra) {
- cntr.progError(line, cause, extra);
- }
-
- enum StopNodesStep {
- SR_BLOCK_GCP_START_GCP = 0,
- SR_WAIT_COMPLETE_GCP = 1,
- SR_UNBLOCK_GCP_START_GCP = 2,
- SR_QMGR_STOP_REQ = 3,
- SR_WAIT_NODE_FAILURES = 4,
- SR_CLUSTER_SHUTDOWN = 12
- } m_state;
- SignalCounter m_stop_req_counter;
- };
-private:
- StopRecord c_stopRec;
- friend struct StopRecord;
-
- struct Missra {
- Missra(Ndbcntr & ref) : cntr(ref) { }
-
- Uint32 currentBlockIndex;
- Uint32 currentStartPhase;
- Uint32 nextStartPhase[NO_OF_BLOCKS];
-
- void execSTART_ORD(Signal* signal);
- void execSTTORRY(Signal* signal);
- void sendNextSTTOR(Signal* signal);
- void execREAD_CONFIG_CONF(Signal* signal);
- void sendNextREAD_CONFIG_REQ(Signal* signal);
-
- BlockNumber number() const { return cntr.number(); }
- void progError(int line, int cause, const char * extra) {
- cntr.progError(line, cause, extra);
- }
- Ndbcntr & cntr;
- };
-
- Missra c_missra;
- friend struct Missra;
-
- void execSTTORRY(Signal* signal);
- void execSTART_ORD(Signal* signal);
- void execREAD_CONFIG_CONF(Signal*);
-
- friend struct UpgradeStartup;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
deleted file mode 100644
index 3b1120926f6..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-
-#define NDBCNTR_C
-#include "Ndbcntr.hpp"
-#include <ndb_limits.h>
-
-#define DEBUG(x) { ndbout << "Ndbcntr::" << x << endl; }
-
-
-void Ndbcntr::initData()
-{
- c_start.reset();
- cmasterNodeId = 0;
- cnoStartNodes = 0;
- cnoWaitrep = 0;
- // Records with constant sizes
- ndbBlocksRec = new NdbBlocksRec[ZSIZE_NDB_BLOCKS_REC];
-}//Ndbcntr::initData()
-
-void Ndbcntr::initRecords()
-{
- // Records with dynamic sizes
-}//Ndbcntr::initRecords()
-
-Ndbcntr::Ndbcntr(Block_context& ctx):
- SimulatedBlock(NDBCNTR, ctx),
- cnoWaitrep6(0),
- cnoWaitrep7(0),
- c_stopRec(* this),
- c_missra(* this)
-{
-
- BLOCK_CONSTRUCTOR(Ndbcntr);
-
- // Transit signals
- addRecSignal(GSN_CONTINUEB, &Ndbcntr::execCONTINUEB);
- addRecSignal(GSN_READ_NODESCONF, &Ndbcntr::execREAD_NODESCONF);
- addRecSignal(GSN_READ_NODESREF, &Ndbcntr::execREAD_NODESREF);
- addRecSignal(GSN_CM_ADD_REP, &Ndbcntr::execCM_ADD_REP);
- addRecSignal(GSN_CNTR_START_REQ, &Ndbcntr::execCNTR_START_REQ);
- addRecSignal(GSN_CNTR_START_REF, &Ndbcntr::execCNTR_START_REF);
- addRecSignal(GSN_CNTR_START_CONF, &Ndbcntr::execCNTR_START_CONF);
- addRecSignal(GSN_CNTR_WAITREP, &Ndbcntr::execCNTR_WAITREP);
- addRecSignal(GSN_CNTR_START_REP, &Ndbcntr::execCNTR_START_REP);
- addRecSignal(GSN_API_START_REP, &Ndbcntr::execAPI_START_REP, true);
- addRecSignal(GSN_NODE_FAILREP, &Ndbcntr::execNODE_FAILREP);
- addRecSignal(GSN_SYSTEM_ERROR , &Ndbcntr::execSYSTEM_ERROR);
-
- // 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);
- addRecSignal(GSN_TCRELEASECONF, &Ndbcntr::execTCRELEASECONF);
- addRecSignal(GSN_TCRELEASEREF, &Ndbcntr::execTCRELEASEREF);
- addRecSignal(GSN_TCKEYCONF, &Ndbcntr::execTCKEYCONF);
- addRecSignal(GSN_TCKEYREF, &Ndbcntr::execTCKEYREF);
- addRecSignal(GSN_TCROLLBACKREP, &Ndbcntr::execTCROLLBACKREP);
- addRecSignal(GSN_GETGCICONF, &Ndbcntr::execGETGCICONF);
- addRecSignal(GSN_DIH_RESTARTCONF, &Ndbcntr::execDIH_RESTARTCONF);
- addRecSignal(GSN_DIH_RESTARTREF, &Ndbcntr::execDIH_RESTARTREF);
- addRecSignal(GSN_CREATE_TABLE_REF, &Ndbcntr::execCREATE_TABLE_REF);
- addRecSignal(GSN_CREATE_TABLE_CONF, &Ndbcntr::execCREATE_TABLE_CONF);
- addRecSignal(GSN_NDB_STTORRY, &Ndbcntr::execNDB_STTORRY);
- addRecSignal(GSN_NDB_STARTCONF, &Ndbcntr::execNDB_STARTCONF);
- addRecSignal(GSN_READ_NODESREQ, &Ndbcntr::execREAD_NODESREQ);
- addRecSignal(GSN_NDB_STARTREF, &Ndbcntr::execNDB_STARTREF);
-
- addRecSignal(GSN_STOP_PERM_REF, &Ndbcntr::execSTOP_PERM_REF);
- addRecSignal(GSN_STOP_PERM_CONF, &Ndbcntr::execSTOP_PERM_CONF);
-
- addRecSignal(GSN_STOP_ME_REF, &Ndbcntr::execSTOP_ME_REF);
- addRecSignal(GSN_STOP_ME_CONF, &Ndbcntr::execSTOP_ME_CONF);
-
- addRecSignal(GSN_STOP_REQ, &Ndbcntr::execSTOP_REQ);
- addRecSignal(GSN_STOP_CONF, &Ndbcntr::execSTOP_CONF);
- addRecSignal(GSN_RESUME_REQ, &Ndbcntr::execRESUME_REQ);
-
- addRecSignal(GSN_WAIT_GCP_REF, &Ndbcntr::execWAIT_GCP_REF);
- addRecSignal(GSN_WAIT_GCP_CONF, &Ndbcntr::execWAIT_GCP_CONF);
- addRecSignal(GSN_CHANGE_NODE_STATE_CONF,
- &Ndbcntr::execCHANGE_NODE_STATE_CONF);
-
- addRecSignal(GSN_ABORT_ALL_REF, &Ndbcntr::execABORT_ALL_REF);
- addRecSignal(GSN_ABORT_ALL_CONF, &Ndbcntr::execABORT_ALL_CONF);
-
- addRecSignal(GSN_START_ORD, &Ndbcntr::execSTART_ORD);
- addRecSignal(GSN_STTORRY, &Ndbcntr::execSTTORRY);
- addRecSignal(GSN_READ_CONFIG_CONF, &Ndbcntr::execREAD_CONFIG_CONF);
-
- addRecSignal(GSN_FSREMOVECONF, &Ndbcntr::execFSREMOVECONF);
-
- initData();
- ctypeOfStart = NodeState::ST_ILLEGAL_TYPE;
- c_start.m_startTime = NdbTick_CurrentMillisecond();
-}//Ndbcntr::Ndbcntr()
-
-Ndbcntr::~Ndbcntr()
-{
- delete []ndbBlocksRec;
-
-}//Ndbcntr::~Ndbcntr()
-
-BLOCK_FUNCTIONS(Ndbcntr)
diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
deleted file mode 100644
index 4c58509f9a1..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ /dev/null
@@ -1,3094 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#define NDBCNTR_C
-#include "Ndbcntr.hpp"
-
-#include <ndb_limits.h>
-#include <ndb_version.h>
-#include <SimpleProperties.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/CreateTable.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/TcKeyReq.hpp>
-#include <signaldata/TcKeyConf.hpp>
-#include <signaldata/EventReport.hpp>
-#include <signaldata/NodeStateSignalData.hpp>
-#include <signaldata/StopPerm.hpp>
-#include <signaldata/StopMe.hpp>
-#include <signaldata/WaitGCP.hpp>
-#include <signaldata/CheckNodeGroups.hpp>
-#include <signaldata/StartOrd.hpp>
-#include <signaldata/AbortAll.hpp>
-#include <signaldata/SystemError.hpp>
-#include <signaldata/NdbSttor.hpp>
-#include <signaldata/CntrStart.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-
-#include <signaldata/FsRemoveReq.hpp>
-#include <signaldata/ReadConfig.hpp>
-
-#include <signaldata/FailRep.hpp>
-
-#include <AttributeHeader.hpp>
-#include <Configuration.hpp>
-#include <DebuggerNames.hpp>
-
-#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
- *
- * NDBFS_REF Has to be before NDBCNTR_REF (due to "ndb -i" stuff)
- */
-struct BlockInfo {
- BlockReference Ref; // BlockReference
- Uint32 NextSP; // Next start phase
- Uint32 ErrorInsertStart;
- Uint32 ErrorInsertStop;
-};
-
-static BlockInfo ALL_BLOCKS[] = {
- { NDBFS_REF, 0 , 2000, 2999 },
- { DBTC_REF, 1 , 8000, 8035 },
- { DBDIH_REF, 1 , 7000, 7173 },
- { DBLQH_REF, 1 , 5000, 5030 },
- { DBACC_REF, 1 , 3000, 3999 },
- { DBTUP_REF, 1 , 4000, 4007 },
- { DBDICT_REF, 1 , 6000, 6003 },
- { NDBCNTR_REF, 0 , 1000, 1999 },
- { CMVMI_REF, 1 , 9000, 9999 }, // before QMGR
- { QMGR_REF, 1 , 1, 999 },
- { TRIX_REF, 1 , 0, 0 },
- { BACKUP_REF, 1 , 10000, 10999 },
- { DBUTIL_REF, 1 , 11000, 11999 },
- { SUMA_REF, 1 , 13000, 13999 },
- { DBTUX_REF, 1 , 12000, 12999 }
- ,{ TSMAN_REF, 1 , 0, 0 }
- ,{ LGMAN_REF, 1 , 0, 0 }
- ,{ PGMAN_REF, 1 , 0, 0 }
- ,{ RESTORE_REF,1 , 0, 0 }
-};
-
-static const Uint32 ALL_BLOCKS_SZ = sizeof(ALL_BLOCKS)/sizeof(BlockInfo);
-
-static BlockReference readConfigOrder[ALL_BLOCKS_SZ] = {
- CMVMI_REF,
- DBTUP_REF,
- DBACC_REF,
- DBTC_REF,
- DBLQH_REF,
- DBTUX_REF,
- DBDICT_REF,
- DBDIH_REF,
- NDBFS_REF,
- NDBCNTR_REF,
- QMGR_REF,
- TRIX_REF,
- BACKUP_REF,
- DBUTIL_REF,
- SUMA_REF,
- TSMAN_REF,
- LGMAN_REF,
- PGMAN_REF,
- RESTORE_REF
-};
-
-/*******************************/
-/* CONTINUEB */
-/*******************************/
-void Ndbcntr::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- UintR Ttemp1 = signal->theData[0];
- switch (Ttemp1) {
- case ZSTARTUP:{
- if(getNodeState().startLevel == NodeState::SL_STARTED){
- jam();
- return;
- }
-
- if(cmasterNodeId == getOwnNodeId() && c_start.m_starting.isclear()){
- jam();
- trySystemRestart(signal);
- // Fall-through
- }
-
- Uint64 now = NdbTick_CurrentMillisecond();
- if(now > c_start.m_startFailureTimeout)
- {
- jam();
- Uint32 to_3= 0;
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT, &to_3);
- BaseString tmp;
- tmp.append("Shutting down node as total restart time exceeds "
- " StartFailureTimeout as set in config file ");
- if(to_3 == 0)
- tmp.append(" 0 (inifinite)");
- else
- tmp.appfmt(" %d", to_3);
-
- progError(__LINE__, NDBD_EXIT_RESTART_TIMEOUT, tmp.c_str());
- }
-
- signal->theData[0] = ZSTARTUP;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1);
- break;
- }
- case ZSHUTDOWN:
- jam();
- c_stopRec.checkTimeout(signal);
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
-}//Ndbcntr::execCONTINUEB()
-
-void
-Ndbcntr::execAPI_START_REP(Signal* signal)
-{
- if(refToBlock(signal->getSendersBlockRef()) == QMGR)
- {
- for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){
- sendSignal(ALL_BLOCKS[i].Ref, GSN_API_START_REP, signal, 1, JBB);
- }
- }
-}
-/*******************************/
-/* SYSTEM_ERROR */
-/*******************************/
-void Ndbcntr::execSYSTEM_ERROR(Signal* signal)
-{
- const SystemError * const sysErr = (SystemError *)signal->getDataPtr();
- char buf[100];
- int killingNode = refToNode(sysErr->errorRef);
- Uint32 data1 = sysErr->data1;
-
- jamEntry();
- switch (sysErr->errorCode){
- case SystemError::GCPStopDetected:
- BaseString::snprintf(buf, sizeof(buf),
- "Node %d killed this node because "
- "GCP stop was detected",
- killingNode);
- break;
-
- case SystemError::CopyFragRefError:
- CRASH_INSERTION(1000);
- BaseString::snprintf(buf, sizeof(buf),
- "Killed by node %d as "
- "copyfrag failed, error: %u",
- killingNode, data1);
- break;
-
- case SystemError::StartFragRefError:
- BaseString::snprintf(buf, sizeof(buf),
- "Node %d killed this node because "
- "it replied StartFragRef error code: %u.",
- killingNode, data1);
- break;
-
- case SystemError::CopySubscriptionRef:
- BaseString::snprintf(buf, sizeof(buf),
- "Node %d killed this node because "
- "it could not copy a subscription during node restart. "
- "Copy subscription error code: %u.",
- killingNode, data1);
- break;
- case SystemError::CopySubscriberRef:
- BaseString::snprintf(buf, sizeof(buf),
- "Node %d killed this node because "
- "it could not start a subscriber during node restart. "
- "Copy subscription error code: %u.",
- killingNode, data1);
- break;
- default:
- BaseString::snprintf(buf, sizeof(buf), "System error %d, "
- " this node was killed by node %d",
- sysErr->errorCode, killingNode);
- break;
- }
-
- 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 =
- m_ctx.m_config.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();
- cstartPhase = signal->theData[1];
-
- cndbBlocksCount = 0;
- cinternalStartphase = cstartPhase - 1;
-
- switch (cstartPhase) {
- case 0:
- if(m_ctx.m_config.getInitialStart()){
- jam();
- c_fsRemoveCount = 0;
- clearFilesystem(signal);
- return;
- }
- sendSttorry(signal);
- break;
- case ZSTART_PHASE_1:
- jam();
- {
- Uint32 db_watchdog_interval = 0;
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndb_mgm_get_int_parameter(p, CFG_DB_WATCHDOG_INTERVAL, &db_watchdog_interval);
- ndbrequire(db_watchdog_interval);
- update_watch_dog_timer(db_watchdog_interval);
- }
- startPhase1Lab(signal);
- break;
- case ZSTART_PHASE_2:
- jam();
- startPhase2Lab(signal);
- break;
- case ZSTART_PHASE_3:
- jam();
- startPhase3Lab(signal);
- break;
- case ZSTART_PHASE_4:
- jam();
- startPhase4Lab(signal);
- break;
- case ZSTART_PHASE_5:
- jam();
- startPhase5Lab(signal);
- break;
- case 6:
- jam();
- getNodeGroup(signal);
- // Fall through
- break;
- case ZSTART_PHASE_8:
- jam();
- startPhase8Lab(signal);
- break;
- case ZSTART_PHASE_9:
- jam();
- startPhase9Lab(signal);
- break;
- default:
- jam();
- sendSttorry(signal);
- break;
- }//switch
-}//Ndbcntr::execSTTOR()
-
-void
-Ndbcntr::getNodeGroup(Signal* signal){
- jam();
- CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend();
- sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::GetNodeGroup;
- EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
- CheckNodeGroups::SignalLength);
- jamEntry();
- c_nodeGroup = sd->output;
- sendSttorry(signal);
-}
-
-/*******************************/
-/* NDB_STTORRY */
-/*******************************/
-void Ndbcntr::execNDB_STTORRY(Signal* signal)
-{
- jamEntry();
- switch (cstartPhase) {
- case ZSTART_PHASE_2:
- jam();
- ph2GLab(signal);
- return;
- break;
- case ZSTART_PHASE_3:
- jam();
- ph3ALab(signal);
- return;
- break;
- case ZSTART_PHASE_4:
- jam();
- ph4BLab(signal);
- return;
- break;
- case ZSTART_PHASE_5:
- jam();
- ph5ALab(signal);
- return;
- break;
- case ZSTART_PHASE_6:
- jam();
- ph6ALab(signal);
- return;
- break;
- case ZSTART_PHASE_7:
- jam();
- ph6BLab(signal);
- return;
- break;
- case ZSTART_PHASE_8:
- jam();
- ph7ALab(signal);
- return;
- break;
- case ZSTART_PHASE_9:
- jam();
- ph8ALab(signal);
- return;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
-}//Ndbcntr::execNDB_STTORRY()
-
-void Ndbcntr::startPhase1Lab(Signal* signal)
-{
- jamEntry();
-
- initData(signal);
-
- cdynamicNodeId = 0;
-
- NdbBlocksRecPtr ndbBlocksPtr;
- ndbBlocksPtr.i = 0;
- ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = DBLQH_REF;
- ndbBlocksPtr.i = 1;
- ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = DBDICT_REF;
- ndbBlocksPtr.i = 2;
- ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = DBTUP_REF;
- ndbBlocksPtr.i = 3;
- ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = DBACC_REF;
- ndbBlocksPtr.i = 4;
- ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = DBTC_REF;
- ndbBlocksPtr.i = 5;
- ptrAss(ndbBlocksPtr, ndbBlocksRec);
- ndbBlocksPtr.p->blockref = DBDIH_REF;
- sendSttorry(signal);
- return;
-}
-
-void Ndbcntr::execREAD_NODESREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Ndbcntr::execREAD_NODESREF()
-
-
-/*******************************/
-/* NDB_STARTREF */
-/*******************************/
-void Ndbcntr::execNDB_STARTREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Ndbcntr::execNDB_STARTREF()
-
-/*******************************/
-/* STTOR */
-/*******************************/
-void Ndbcntr::startPhase2Lab(Signal* signal)
-{
- c_start.m_lastGci = 0;
- c_start.m_lastGciNodeId = getOwnNodeId();
-
- signal->theData[0] = reference();
- sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB);
- return;
-}//Ndbcntr::startPhase2Lab()
-
-/*******************************/
-/* DIH_RESTARTCONF */
-/*******************************/
-void Ndbcntr::execDIH_RESTARTCONF(Signal* signal)
-{
- jamEntry();
- //cmasterDihId = signal->theData[0];
- c_start.m_lastGci = signal->theData[1];
- ctypeOfStart = NodeState::ST_SYSTEM_RESTART;
- ph2ALab(signal);
- return;
-}//Ndbcntr::execDIH_RESTARTCONF()
-
-/*******************************/
-/* DIH_RESTARTREF */
-/*******************************/
-void Ndbcntr::execDIH_RESTARTREF(Signal* signal)
-{
- jamEntry();
- ctypeOfStart = NodeState::ST_INITIAL_START;
- ph2ALab(signal);
- return;
-}//Ndbcntr::execDIH_RESTARTREF()
-
-void Ndbcntr::ph2ALab(Signal* signal)
-{
- /******************************/
- /* request configured nodes */
- /* from QMGR */
- /* READ_NODESREQ */
- /******************************/
- signal->theData[0] = reference();
- sendSignal(QMGR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
- return;
-}//Ndbcntr::ph2ALab()
-
-inline
-Uint64
-setTimeout(Uint64 time, Uint32 timeoutValue){
- if(timeoutValue == 0)
- return ~(Uint64)0;
- return time + timeoutValue;
-}
-
-/*******************************/
-/* READ_NODESCONF */
-/*******************************/
-void Ndbcntr::execREAD_NODESCONF(Signal* signal)
-{
- jamEntry();
- const ReadNodesConf * readNodes = (ReadNodesConf *)&signal->theData[0];
-
- cmasterNodeId = readNodes->masterNodeId;
- cdynamicNodeId = readNodes->ndynamicId;
-
- /**
- * All defined nodes...
- */
- c_allDefinedNodes.assign(NdbNodeBitmask::Size, readNodes->allNodes);
- c_clusterNodes.assign(NdbNodeBitmask::Size, readNodes->clusterNodes);
-
- Uint32 to_1 = 30000;
- Uint32 to_2 = 0;
- Uint32 to_3 = 0;
-
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
-
- ndbrequire(p != 0);
- ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT, &to_1);
- ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTITION_TIMEOUT, &to_2);
- ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT, &to_3);
-
- c_start.m_startTime = NdbTick_CurrentMillisecond();
- c_start.m_startPartialTimeout = setTimeout(c_start.m_startTime, to_1);
- c_start.m_startPartitionedTimeout = setTimeout(c_start.m_startTime, to_2);
- c_start.m_startFailureTimeout = setTimeout(c_start.m_startTime, to_3);
-
- UpgradeStartup::sendCmAppChg(* this, signal, 0); // ADD
-
- sendCntrStartReq(signal);
-
- signal->theData[0] = ZSTARTUP;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1);
-
- return;
-}
-
-void
-Ndbcntr::execCM_ADD_REP(Signal* signal){
- jamEntry();
- c_clusterNodes.set(signal->theData[0]);
-}
-
-void
-Ndbcntr::sendCntrStartReq(Signal * signal){
- jamEntry();
-
- CntrStartReq * req = (CntrStartReq*)signal->getDataPtrSend();
- req->startType = ctypeOfStart;
- req->lastGci = c_start.m_lastGci;
- req->nodeId = getOwnNodeId();
- sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_START_REQ,
- signal, CntrStartReq::SignalLength, JBB);
-}
-
-void
-Ndbcntr::execCNTR_START_REF(Signal * signal){
- jamEntry();
- const CntrStartRef * ref = (CntrStartRef*)signal->getDataPtr();
-
- switch(ref->errorCode){
- case CntrStartRef::NotMaster:
- jam();
- cmasterNodeId = ref->masterNodeId;
- sendCntrStartReq(signal);
- return;
- case CntrStartRef::StopInProgress:
- jam();
- progError(__LINE__, NDBD_EXIT_RESTART_DURING_SHUTDOWN);
- }
- ndbrequire(false);
-}
-
-void
-Ndbcntr::StartRecord::reset(){
- m_starting.clear();
- m_waiting.clear();
- m_withLog.clear();
- m_withoutLog.clear();
- m_lastGci = m_lastGciNodeId = 0;
- m_startPartialTimeout = ~0;
- m_startPartitionedTimeout = ~0;
- m_startFailureTimeout = ~0;
-
- m_logNodesCount = 0;
-}
-
-void
-Ndbcntr::execCNTR_START_CONF(Signal * signal){
- jamEntry();
- const CntrStartConf * conf = (CntrStartConf*)signal->getDataPtr();
-
- cnoStartNodes = conf->noStartNodes;
- ctypeOfStart = (NodeState::StartType)conf->startType;
- c_start.m_lastGci = conf->startGci;
- cmasterNodeId = conf->masterNodeId;
- NdbNodeBitmask tmp;
- tmp.assign(NdbNodeBitmask::Size, conf->startedNodes);
- c_startedNodes.bitOR(tmp);
- c_start.m_starting.assign(NdbNodeBitmask::Size, conf->startingNodes);
- ph2GLab(signal);
-
- UpgradeStartup::sendCmAppChg(* this, signal, 2); //START
-}
-
-/**
- * Tried with parallell nr, but it crashed in DIH
- * so I turned it off, as I don't want to debug DIH now...
- * Jonas 19/11-03
- *
- * After trying for 2 hours, I gave up.
- * DIH is not designed to support it, and
- * it requires quite of lot of changes to
- * make it work
- * Jonas 5/12-03
- */
-#define PARALLELL_NR 0
-
-#if PARALLELL_NR
-const bool parallellNR = true;
-#else
-const bool parallellNR = false;
-#endif
-
-void
-Ndbcntr::execCNTR_START_REP(Signal* signal){
- jamEntry();
- 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();
- return;
- }
-
- if(cmasterNodeId != getOwnNodeId()){
- jam();
- c_start.reset();
- return;
- }
-
- if(c_start.m_waiting.isclear()){
- jam();
- c_start.reset();
- return;
- }
-
- startWaitingNodes(signal);
-}
-
-void
-Ndbcntr::execCNTR_START_REQ(Signal * signal){
- jamEntry();
- const CntrStartReq * req = (CntrStartReq*)signal->getDataPtr();
-
- const Uint32 nodeId = req->nodeId;
- const Uint32 lastGci = req->lastGci;
- const NodeState::StartType st = (NodeState::StartType)req->startType;
-
- if(cmasterNodeId == 0){
- jam();
- // Has not completed READNODES yet
- sendSignalWithDelay(reference(), GSN_CNTR_START_REQ, signal, 100,
- signal->getLength());
- return;
- }
-
- if(cmasterNodeId != getOwnNodeId()){
- jam();
- sendCntrStartRef(signal, nodeId, CntrStartRef::NotMaster);
- return;
- }
-
- const NodeState & nodeState = getNodeState();
- switch(nodeState.startLevel){
- case NodeState::SL_NOTHING:
- case NodeState::SL_CMVMI:
- jam();
- ndbrequire(false);
- case NodeState::SL_STARTING:
- case NodeState::SL_STARTED:
- jam();
- break;
-
- case NodeState::SL_STOPPING_1:
- case NodeState::SL_STOPPING_2:
- case NodeState::SL_STOPPING_3:
- case NodeState::SL_STOPPING_4:
- jam();
- sendCntrStartRef(signal, nodeId, CntrStartRef::StopInProgress);
- return;
- }
-
- /**
- * Am I starting (or started)
- */
- const bool starting = (nodeState.startLevel != NodeState::SL_STARTED);
-
- c_start.m_waiting.set(nodeId);
- switch(st){
- case NodeState::ST_INITIAL_START:
- jam();
- c_start.m_withoutLog.set(nodeId);
- break;
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- c_start.m_withLog.set(nodeId);
- if(starting && lastGci > c_start.m_lastGci){
- jam();
- CntrStartRef * ref = (CntrStartRef*)signal->getDataPtrSend();
- ref->errorCode = CntrStartRef::NotMaster;
- ref->masterNodeId = nodeId;
- NodeReceiverGroup rg (NDBCNTR, c_start.m_waiting);
- sendSignal(rg, GSN_CNTR_START_REF, signal,
- CntrStartRef::SignalLength, JBB);
- return;
- }
- if(starting){
- jam();
- Uint32 i = c_start.m_logNodesCount++;
- c_start.m_logNodes[i].m_nodeId = nodeId;
- c_start.m_logNodes[i].m_lastGci = req->lastGci;
- }
- break;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- case NodeState::ST_ILLEGAL_TYPE:
- ndbrequire(false);
- }
-
- const bool startInProgress = !c_start.m_starting.isclear();
-
- if((starting && startInProgress) || (startInProgress && !parallellNR)){
- jam();
- // We're already starting together with a bunch of nodes
- // Let this node wait...
- return;
- }
-
- if(starting){
- jam();
- trySystemRestart(signal);
- } else {
- jam();
- startWaitingNodes(signal);
- }
- return;
-}
-
-void
-Ndbcntr::startWaitingNodes(Signal * signal){
-
-#if ! PARALLELL_NR
- const Uint32 nodeId = c_start.m_waiting.find(0);
- const Uint32 Tref = calcNdbCntrBlockRef(nodeId);
- ndbrequire(nodeId != c_start.m_waiting.NotFound);
-
- NodeState::StartType nrType = NodeState::ST_NODE_RESTART;
- if(c_start.m_withoutLog.get(nodeId)){
- jam();
- nrType = NodeState::ST_INITIAL_NODE_RESTART;
- }
-
- /**
- * Let node perform restart
- */
- CntrStartConf * conf = (CntrStartConf*)signal->getDataPtrSend();
- conf->noStartNodes = 1;
- conf->startType = nrType;
- conf->startGci = ~0; // Not used
- conf->masterNodeId = getOwnNodeId();
- BitmaskImpl::clear(NdbNodeBitmask::Size, conf->startingNodes);
- BitmaskImpl::set(NdbNodeBitmask::Size, conf->startingNodes, nodeId);
- c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes);
- sendSignal(Tref, GSN_CNTR_START_CONF, signal,
- CntrStartConf::SignalLength, JBB);
-
- c_start.m_waiting.clear(nodeId);
- c_start.m_withLog.clear(nodeId);
- c_start.m_withoutLog.clear(nodeId);
- c_start.m_starting.set(nodeId);
-#else
- // Parallell nr
-
- c_start.m_starting = c_start.m_waiting;
- c_start.m_waiting.clear();
-
- CntrStartConf * conf = (CntrStartConf*)signal->getDataPtrSend();
- conf->noStartNodes = 1;
- conf->startGci = ~0; // Not used
- conf->masterNodeId = getOwnNodeId();
- c_start.m_starting.copyto(NdbNodeBitmask::Size, conf->startingNodes);
- c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes);
-
- char buf[100];
- if(!c_start.m_withLog.isclear()){
- jam();
- ndbout_c("Starting nodes w/ log: %s", c_start.m_withLog.getText(buf));
-
- NodeReceiverGroup rg(NDBCNTR, c_start.m_withLog);
- conf->startType = NodeState::ST_NODE_RESTART;
-
- sendSignal(rg, GSN_CNTR_START_CONF, signal,
- CntrStartConf::SignalLength, JBB);
- }
-
- if(!c_start.m_withoutLog.isclear()){
- jam();
- ndbout_c("Starting nodes wo/ log: %s", c_start.m_withoutLog.getText(buf));
- NodeReceiverGroup rg(NDBCNTR, c_start.m_withoutLog);
- conf->startType = NodeState::ST_INITIAL_NODE_RESTART;
-
- sendSignal(rg, GSN_CNTR_START_CONF, signal,
- CntrStartConf::SignalLength, JBB);
- }
-
- c_start.m_waiting.clear();
- c_start.m_withLog.clear();
- c_start.m_withoutLog.clear();
-#endif
-}
-
-void
-Ndbcntr::sendCntrStartRef(Signal * signal,
- Uint32 nodeId, CntrStartRef::ErrorCode code){
- CntrStartRef * ref = (CntrStartRef*)signal->getDataPtrSend();
- ref->errorCode = code;
- ref->masterNodeId = cmasterNodeId;
- sendSignal(calcNdbCntrBlockRef(nodeId), GSN_CNTR_START_REF, signal,
- CntrStartRef::SignalLength, JBB);
-}
-
-CheckNodeGroups::Output
-Ndbcntr::checkNodeGroups(Signal* signal, const NdbNodeBitmask & mask){
- CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
- sd->blockRef = reference();
- sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
- sd->mask = mask;
- EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
- CheckNodeGroups::SignalLength);
- jamEntry();
- return (CheckNodeGroups::Output)sd->output;
-}
-
-bool
-Ndbcntr::trySystemRestart(Signal* signal){
- /**
- * System restart something
- */
- const bool allNodes = c_start.m_waiting.equal(c_allDefinedNodes);
- const bool allClusterNodes = c_start.m_waiting.equal(c_clusterNodes);
-
- if(!allClusterNodes){
- jam();
- return false;
- }
-
- NodeState::StartType srType = NodeState::ST_SYSTEM_RESTART;
- 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...
- c_start.m_withoutLog.clear();
- } else {
-
- CheckNodeGroups::Output wLog = checkNodeGroups(signal, c_start.m_withLog);
-
- switch (wLog) {
- case CheckNodeGroups::Win:
- jam();
- break;
- case CheckNodeGroups::Lose:
- jam();
- // If we lose with all nodes, then we're in trouble
- ndbrequire(!allNodes);
- return false;
- case CheckNodeGroups::Partitioning:
- jam();
- bool allowPartition = (c_start.m_startPartitionedTimeout != (Uint64)~0);
-
- if(allNodes){
- if(allowPartition){
- jam();
- break;
- }
- ndbrequire(false); // All nodes -> partitioning, which is not allowed
- }
-
- break;
- }
-
- // For now only with the "logged"-ones.
- // Let the others do node restart afterwards...
- c_start.m_starting = c_start.m_withLog;
- c_start.m_withLog.clear();
- }
-
- /**
- * Okidoki, we try to start
- */
- CntrStartConf * conf = (CntrStartConf*)signal->getDataPtr();
- conf->noStartNodes = c_start.m_starting.count();
- conf->startType = srType;
- conf->startGci = c_start.m_lastGci;
- conf->masterNodeId = c_start.m_lastGciNodeId;
- c_start.m_starting.copyto(NdbNodeBitmask::Size, conf->startingNodes);
- c_startedNodes.copyto(NdbNodeBitmask::Size, conf->startedNodes);
-
- ndbrequire(c_start.m_lastGciNodeId == getOwnNodeId());
-
- NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
- sendSignal(rg, GSN_CNTR_START_CONF, signal, CntrStartConf::SignalLength,JBB);
-
- c_start.m_waiting.bitANDC(c_start.m_starting);
-
- return true;
-}
-
-void Ndbcntr::ph2GLab(Signal* signal)
-{
- if (cndbBlocksCount < ZNO_NDB_BLOCKS) {
- jam();
- sendNdbSttor(signal);
- return;
- }//if
- sendSttorry(signal);
- return;
-}//Ndbcntr::ph2GLab()
-
-/*
-4.4 START PHASE 3 */
-/*###########################################################################*/
-// SEND SIGNAL NDBSTTOR TO ALL BLOCKS, ACC, DICT, DIH, LQH, TC AND TUP
-// WHEN ALL BLOCKS HAVE RETURNED THEIR NDB_STTORRY ALL BLOCK HAVE FINISHED
-// THEIR LOCAL CONNECTIONs SUCESSFULLY
-// AND THEN WE CAN SEND APPL_STARTREG TO INFORM QMGR THAT WE ARE READY TO
-// SET UP DISTRIBUTED CONNECTIONS.
-/*--------------------------------------------------------------*/
-// THIS IS NDB START PHASE 3.
-/*--------------------------------------------------------------*/
-/*******************************/
-/* STTOR */
-/*******************************/
-void Ndbcntr::startPhase3Lab(Signal* signal)
-{
- ph3ALab(signal);
- return;
-}//Ndbcntr::startPhase3Lab()
-
-/*******************************/
-/* NDB_STTORRY */
-/*******************************/
-void Ndbcntr::ph3ALab(Signal* signal)
-{
- if (cndbBlocksCount < ZNO_NDB_BLOCKS) {
- jam();
- sendNdbSttor(signal);
- return;
- }//if
-
- sendSttorry(signal);
- return;
-}//Ndbcntr::ph3ALab()
-
-/*
-4.5 START PHASE 4 */
-/*###########################################################################*/
-// WAIT FOR ALL NODES IN CLUSTER TO CHANGE STATE INTO ZSTART ,
-// APPL_CHANGEREP IS ALWAYS SENT WHEN SOMEONE HAVE
-// CHANGED THEIR STATE. APPL_STARTCONF INDICATES THAT ALL NODES ARE IN START
-// STATE SEND NDB_STARTREQ TO DIH AND THEN WAIT FOR NDB_STARTCONF
-/*---------------------------------------------------------------------------*/
-/*******************************/
-/* STTOR */
-/*******************************/
-void Ndbcntr::startPhase4Lab(Signal* signal)
-{
- ph4ALab(signal);
-}//Ndbcntr::startPhase4Lab()
-
-
-void Ndbcntr::ph4ALab(Signal* signal)
-{
- ph4BLab(signal);
- return;
-}//Ndbcntr::ph4ALab()
-
-/*******************************/
-/* NDB_STTORRY */
-/*******************************/
-void Ndbcntr::ph4BLab(Signal* signal)
-{
-/*--------------------------------------*/
-/* CASE: CSTART_PHASE = ZSTART_PHASE_4 */
-/*--------------------------------------*/
- if (cndbBlocksCount < ZNO_NDB_BLOCKS) {
- jam();
- sendNdbSttor(signal);
- return;
- }//if
- if ((ctypeOfStart == NodeState::ST_NODE_RESTART) ||
- (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- sendSttorry(signal);
- return;
- }//if
- waitpoint41Lab(signal);
- return;
-}//Ndbcntr::ph4BLab()
-
-void Ndbcntr::waitpoint41Lab(Signal* signal)
-{
- if (getOwnNodeId() == cmasterNodeId) {
- jam();
-/*--------------------------------------*/
-/* MASTER WAITS UNTIL ALL SLAVES HAS */
-/* SENT THE REPORTS */
-/*--------------------------------------*/
- cnoWaitrep++;
- if (cnoWaitrep == cnoStartNodes) {
- jam();
- cnoWaitrep = 0;
-/*---------------------------------------------------------------------------*/
-// NDB_STARTREQ STARTS UP ALL SET UP OF DISTRIBUTION INFORMATION IN DIH AND
-// DICT. AFTER SETTING UP THIS
-// DATA IT USES THAT DATA TO SET UP WHICH FRAGMENTS THAT ARE TO START AND
-// WHERE THEY ARE TO START. THEN
-// IT SETS UP THE FRAGMENTS AND RECOVERS THEM BY:
-// 1) READING A LOCAL CHECKPOINT FROM DISK.
-// 2) EXECUTING THE UNDO LOG ON INDEX AND DATA.
-// 3) EXECUTING THE FRAGMENT REDO LOG FROM ONE OR SEVERAL NODES TO
-// RESTORE THE RESTART CONFIGURATION OF DATA IN NDB CLUSTER.
-/*---------------------------------------------------------------------------*/
- signal->theData[0] = reference();
- signal->theData[1] = ctypeOfStart;
- sendSignal(DBDIH_REF, GSN_NDB_STARTREQ, signal, 2, JBB);
- }//if
- } else {
- jam();
-/*--------------------------------------*/
-/* SLAVE NODES WILL PASS HERE ONCE AND */
-/* SEND A WAITPOINT REPORT TO MASTER. */
-/* SLAVES WONT DO ANYTHING UNTIL THEY */
-/* RECEIVE A WAIT REPORT FROM THE MASTER*/
-/*--------------------------------------*/
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_4_1;
- sendSignal(calcNdbCntrBlockRef(cmasterNodeId),
- GSN_CNTR_WAITREP, signal, 2, JBB);
- }//if
- return;
-}//Ndbcntr::waitpoint41Lab()
-
-/*******************************/
-/* NDB_STARTCONF */
-/*******************************/
-void Ndbcntr::execNDB_STARTCONF(Signal* signal)
-{
- jamEntry();
-
- NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_4_2;
- sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
- return;
-}//Ndbcntr::execNDB_STARTCONF()
-
-/*
-4.6 START PHASE 5 */
-/*###########################################################################*/
-// SEND APPL_RUN TO THE QMGR IN THIS BLOCK
-// SEND NDB_STTOR ALL BLOCKS ACC, DICT, DIH, LQH, TC AND TUP THEN WAIT FOR
-// THEIR NDB_STTORRY
-/*---------------------------------------------------------------------------*/
-/*******************************/
-/* STTOR */
-/*******************************/
-void Ndbcntr::startPhase5Lab(Signal* signal)
-{
- ph5ALab(signal);
- return;
-}//Ndbcntr::startPhase5Lab()
-
-/*******************************/
-/* NDB_STTORRY */
-/*******************************/
-/*---------------------------------------------------------------------------*/
-// THIS IS NDB START PHASE 5.
-/*---------------------------------------------------------------------------*/
-// IN THIS START PHASE TUP INITIALISES DISK FILES FOR DISK STORAGE IF INITIAL
-// START. DIH WILL START UP
-// THE GLOBAL CHECKPOINT PROTOCOL AND WILL CONCLUDE ANY UNFINISHED TAKE OVERS
-// THAT STARTED BEFORE THE SYSTEM CRASH.
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::ph5ALab(Signal* signal)
-{
- if (cndbBlocksCount < ZNO_NDB_BLOCKS) {
- jam();
- sendNdbSttor(signal);
- return;
- }//if
-
- cstartPhase = cstartPhase + 1;
- cinternalStartphase = cstartPhase - 1;
- if (getOwnNodeId() == cmasterNodeId) {
- switch(ctypeOfStart){
- case NodeState::ST_INITIAL_START:
- jam();
- /*--------------------------------------*/
- /* MASTER CNTR IS RESPONSIBLE FOR */
- /* CREATING SYSTEM TABLES */
- /*--------------------------------------*/
- createSystableLab(signal, 0);
- return;
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- waitpoint52Lab(signal);
- return;
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
- break;
- case NodeState::ST_ILLEGAL_TYPE:
- jam();
- break;
- }
- ndbrequire(false);
- }
-
- /**
- * Not master
- */
- NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend();
- switch(ctypeOfStart){
- case NodeState::ST_NODE_RESTART:
- case NodeState::ST_INITIAL_NODE_RESTART:
- jam();
- /*----------------------------------------------------------------------*/
- // SEND NDB START PHASE 5 IN NODE RESTARTS TO COPY DATA TO THE NEWLY
- // STARTED NODE.
- /*----------------------------------------------------------------------*/
- req->senderRef = reference();
- req->nodeId = getOwnNodeId();
- req->internalStartPhase = cinternalStartphase;
- req->typeOfStart = ctypeOfStart;
- req->masterNodeId = cmasterNodeId;
-
- //#define TRACE_STTOR
-#ifdef TRACE_STTOR
- ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase);
-#endif
- sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal,
- NdbSttor::SignalLength, JBB);
- return;
- case NodeState::ST_INITIAL_START:
- case NodeState::ST_SYSTEM_RESTART:
- jam();
- /*--------------------------------------*/
- /* DURING SYSTEMRESTART AND INITALSTART:*/
- /* SLAVE NODES WILL PASS HERE ONCE AND */
- /* SEND A WAITPOINT REPORT TO MASTER. */
- /* SLAVES WONT DO ANYTHING UNTIL THEY */
- /* RECEIVE A WAIT REPORT FROM THE MASTER*/
- /* WHEN THE MASTER HAS FINISHED HIS WORK*/
- /*--------------------------------------*/
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_5_2;
- sendSignal(calcNdbCntrBlockRef(cmasterNodeId),
- GSN_CNTR_WAITREP, signal, 2, JBB);
- return;
- default:
- ndbrequire(false);
- }
-}//Ndbcntr::ph5ALab()
-
-void Ndbcntr::waitpoint52Lab(Signal* signal)
-{
- cnoWaitrep = cnoWaitrep + 1;
-/*---------------------------------------------------------------------------*/
-// THIS WAITING POINT IS ONLY USED BY A MASTER NODE. WE WILL EXECUTE NDB START
-// PHASE 5 FOR DIH IN THE
-// MASTER. THIS WILL START UP LOCAL CHECKPOINTS AND WILL ALSO CONCLUDE ANY
-// UNFINISHED LOCAL CHECKPOINTS
-// BEFORE THE SYSTEM CRASH. THIS WILL ENSURE THAT WE ALWAYS RESTART FROM A
-// WELL KNOWN STATE.
-/*---------------------------------------------------------------------------*/
-/*--------------------------------------*/
-/* MASTER WAITS UNTIL HE RECEIVED WAIT */
-/* REPORTS FROM ALL SLAVE CNTR */
-/*--------------------------------------*/
- if (cnoWaitrep == cnoStartNodes) {
- jam();
- cnoWaitrep = 0;
-
- NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->nodeId = getOwnNodeId();
- req->internalStartPhase = cinternalStartphase;
- req->typeOfStart = ctypeOfStart;
- req->masterNodeId = cmasterNodeId;
-#ifdef TRACE_STTOR
- ndbout_c("sending NDB_STTOR(%d) to DIH", cinternalStartphase);
-#endif
- sendSignal(DBDIH_REF, GSN_NDB_STTOR, signal,
- NdbSttor::SignalLength, JBB);
- }//if
- return;
-}//Ndbcntr::waitpoint52Lab()
-
-/*******************************/
-/* NDB_STTORRY */
-/*******************************/
-void Ndbcntr::ph6ALab(Signal* signal)
-{
- if ((ctypeOfStart == NodeState::ST_NODE_RESTART) ||
- (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- waitpoint51Lab(signal);
- return;
- }//if
-
- NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
- rg.m_nodes.clear(getOwnNodeId());
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_5_1;
- sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
-
- waitpoint51Lab(signal);
- return;
-}//Ndbcntr::ph6ALab()
-
-void Ndbcntr::waitpoint51Lab(Signal* signal)
-{
- cstartPhase = cstartPhase + 1;
-/*---------------------------------------------------------------------------*/
-// A FINAL STEP IS NOW TO SEND NDB_STTOR TO TC. THIS MAKES IT POSSIBLE TO
-// CONNECT TO TC FOR APPLICATIONS.
-// THIS IS NDB START PHASE 6 WHICH IS FOR ALL BLOCKS IN ALL NODES.
-/*---------------------------------------------------------------------------*/
- cinternalStartphase = cstartPhase - 1;
- cndbBlocksCount = 0;
- ph6BLab(signal);
- return;
-}//Ndbcntr::waitpoint51Lab()
-
-void Ndbcntr::ph6BLab(Signal* signal)
-{
- // c_missra.currentStartPhase - cstartPhase - cinternalStartphase =
- // 5 - 7 - 6
- if (cndbBlocksCount < ZNO_NDB_BLOCKS) {
- jam();
- sendNdbSttor(signal);
- return;
- }//if
- if ((ctypeOfStart == NodeState::ST_NODE_RESTART) ||
- (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- sendSttorry(signal);
- return;
- }
- waitpoint61Lab(signal);
-}
-
-void Ndbcntr::waitpoint61Lab(Signal* signal)
-{
- if (getOwnNodeId() == cmasterNodeId) {
- jam();
- cnoWaitrep6++;
- if (cnoWaitrep6 == cnoStartNodes) {
- jam();
- NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
- rg.m_nodes.clear(getOwnNodeId());
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_6_2;
- sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
- sendSttorry(signal);
- }
- } else {
- jam();
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_6_1;
- sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB);
- }
-}
-
-// Start phase 8 (internal 7)
-void Ndbcntr::startPhase8Lab(Signal* signal)
-{
- cinternalStartphase = cstartPhase - 1;
- cndbBlocksCount = 0;
- ph7ALab(signal);
-}
-
-void Ndbcntr::ph7ALab(Signal* signal)
-{
- while (cndbBlocksCount < ZNO_NDB_BLOCKS) {
- jam();
- sendNdbSttor(signal);
- return;
- }
- if ((ctypeOfStart == NodeState::ST_NODE_RESTART) ||
- (ctypeOfStart == NodeState::ST_INITIAL_NODE_RESTART)) {
- jam();
- sendSttorry(signal);
- return;
- }
- waitpoint71Lab(signal);
-}
-
-void Ndbcntr::waitpoint71Lab(Signal* signal)
-{
- if (getOwnNodeId() == cmasterNodeId) {
- jam();
- cnoWaitrep7++;
- if (cnoWaitrep7 == cnoStartNodes) {
- jam();
- NodeReceiverGroup rg(NDBCNTR, c_start.m_starting);
- rg.m_nodes.clear(getOwnNodeId());
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_7_2;
- sendSignal(rg, GSN_CNTR_WAITREP, signal, 2, JBB);
- sendSttorry(signal);
- }
- } else {
- jam();
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ZWAITPOINT_7_1;
- sendSignal(calcNdbCntrBlockRef(cmasterNodeId), GSN_CNTR_WAITREP, signal, 2, JBB);
- }
-}
-
-// Start phase 9 (internal 8)
-void Ndbcntr::startPhase9Lab(Signal* signal)
-{
- cinternalStartphase = cstartPhase - 1;
- cndbBlocksCount = 0;
- ph8ALab(signal);
-}
-
-void Ndbcntr::ph8ALab(Signal* signal)
-{
-/*---------------------------------------------------------------------------*/
-// NODES WHICH PERFORM A NODE RESTART NEEDS TO GET THE DYNAMIC ID'S
-// OF THE OTHER NODES HERE.
-/*---------------------------------------------------------------------------*/
- sendSttorry(signal);
- resetStartVariables(signal);
- return;
-}//Ndbcntr::ph8BLab()
-
-/*******************************/
-/* CNTR_WAITREP */
-/*******************************/
-void Ndbcntr::execCNTR_WAITREP(Signal* signal)
-{
- Uint16 twaitPoint;
-
- jamEntry();
- twaitPoint = signal->theData[1];
- switch (twaitPoint) {
- case ZWAITPOINT_4_1:
- jam();
- waitpoint41Lab(signal);
- break;
- case ZWAITPOINT_4_2:
- jam();
- sendSttorry(signal);
- break;
- case ZWAITPOINT_5_1:
- jam();
- waitpoint51Lab(signal);
- break;
- case ZWAITPOINT_5_2:
- jam();
- waitpoint52Lab(signal);
- break;
- case ZWAITPOINT_6_1:
- jam();
- waitpoint61Lab(signal);
- break;
- case ZWAITPOINT_6_2:
- jam();
- sendSttorry(signal);
- break;
- case ZWAITPOINT_7_1:
- jam();
- waitpoint71Lab(signal);
- break;
- case ZWAITPOINT_7_2:
- jam();
- sendSttorry(signal);
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- break;
- }//switch
-}//Ndbcntr::execCNTR_WAITREP()
-
-/*******************************/
-/* NODE_FAILREP */
-/*******************************/
-void Ndbcntr::execNODE_FAILREP(Signal* signal)
-{
- jamEntry();
-
- if (ERROR_INSERTED(1001))
- {
- sendSignalWithDelay(reference(), GSN_NODE_FAILREP, signal, 100,
- signal->getLength());
- return;
- }
-
- const NodeFailRep * nodeFail = (NodeFailRep *)&signal->theData[0];
- NdbNodeBitmask allFailed;
- allFailed.assign(NdbNodeBitmask::Size, nodeFail->theNodes);
-
- NdbNodeBitmask failedStarted = c_startedNodes;
- NdbNodeBitmask failedStarting = c_start.m_starting;
- NdbNodeBitmask failedWaiting = c_start.m_waiting;
-
- failedStarted.bitAND(allFailed);
- failedStarting.bitAND(allFailed);
- failedWaiting.bitAND(allFailed);
-
- const bool tMasterFailed = allFailed.get(cmasterNodeId);
- const bool tStarted = !failedStarted.isclear();
- const bool tStarting = !failedStarting.isclear();
-
- if(tMasterFailed){
- jam();
- /**
- * If master has failed choose qmgr president as master
- */
- cmasterNodeId = nodeFail->masterNodeId;
- }
-
- /**
- * Clear node bitmasks from failed nodes
- */
- c_start.m_starting.bitANDC(allFailed);
- c_start.m_waiting.bitANDC(allFailed);
- c_start.m_withLog.bitANDC(allFailed);
- c_start.m_withoutLog.bitANDC(allFailed);
- c_clusterNodes.bitANDC(allFailed);
- c_startedNodes.bitANDC(allFailed);
-
- const NodeState & st = getNodeState();
- if(st.startLevel == st.SL_STARTING){
- jam();
-
- const Uint32 phase = st.starting.startPhase;
-
- const bool tStartConf = (phase > 2) || (phase == 2 && cndbBlocksCount > 0);
-
- if(tMasterFailed){
- progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED,
- "Unhandled node failure during restart");
- }
-
- if(tStartConf && tStarting){
- // One of other starting nodes has crashed...
- 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__, NDBD_EXIT_SR_OTHERNODEFAILED,
- "Unhandled node failure of started node during restart");
- }
-
- Uint32 nodeId = 0;
- while(!allFailed.isclear()){
- nodeId = allFailed.find(nodeId + 1);
- allFailed.clear(nodeId);
- signal->theData[0] = nodeId;
- sendSignal(QMGR_REF, GSN_NDB_FAILCONF, signal, 1, JBB);
- }//for
-
- return;
- }
-
- ndbrequire(!allFailed.get(getOwnNodeId()));
-
- NodeFailRep * rep = (NodeFailRep *)&signal->theData[0];
- rep->masterNodeId = cmasterNodeId;
-
- sendSignal(DBTC_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- sendSignal(DBLQH_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- sendSignal(DBDIH_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- sendSignal(DBDICT_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- sendSignal(BACKUP_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- sendSignal(QMGR_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- if (c_stopRec.stopReq.senderRef)
- {
- jam();
- switch(c_stopRec.m_state){
- case StopRecord::SR_WAIT_NODE_FAILURES:
- {
- jam();
- NdbNodeBitmask tmp;
- tmp.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes);
- tmp.bitANDC(allFailed);
- tmp.copyto(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes);
-
- if (tmp.isclear())
- {
- jam();
- if (c_stopRec.stopReq.senderRef != RNIL)
- {
- jam();
- StopConf * const stopConf = (StopConf *)&signal->theData[0];
- stopConf->senderData = c_stopRec.stopReq.senderData;
- stopConf->nodeState = (Uint32) NodeState::SL_SINGLEUSER;
- sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_CONF, signal,
- StopConf::SignalLength, JBB);
- }
-
- c_stopRec.stopReq.senderRef = 0;
- WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = StopRecord::SR_UNBLOCK_GCP_START_GCP;
- req->requestType = WaitGCPReq::UnblockStartGcp;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBA);
- }
- break;
- }
- case StopRecord::SR_QMGR_STOP_REQ:
- {
- NdbNodeBitmask tmp;
- tmp.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes);
- tmp.bitANDC(allFailed);
-
- if (tmp.isclear())
- {
- Uint32 nodeId = allFailed.find(0);
- tmp.set(nodeId);
-
- StopConf* conf = (StopConf*)signal->getDataPtrSend();
- conf->senderData = c_stopRec.stopReq.senderData;
- conf->nodeId = nodeId;
- sendSignal(reference(),
- GSN_STOP_CONF, signal, StopConf::SignalLength, JBB);
- }
-
- tmp.copyto(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes);
-
- break;
- }
- case StopRecord::SR_BLOCK_GCP_START_GCP:
- case StopRecord::SR_WAIT_COMPLETE_GCP:
- case StopRecord::SR_UNBLOCK_GCP_START_GCP:
- case StopRecord::SR_CLUSTER_SHUTDOWN:
- break;
- }
- }
-
- signal->theData[0] = NDB_LE_NODE_FAILREP;
- signal->theData[2] = 0;
-
- Uint32 nodeId = 0;
- while(!allFailed.isclear()){
- nodeId = allFailed.find(nodeId + 1);
- allFailed.clear(nodeId);
- signal->theData[1] = nodeId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
- }//for
-
- return;
-}//Ndbcntr::execNODE_FAILREP()
-
-/*******************************/
-/* READ_NODESREQ */
-/*******************************/
-void Ndbcntr::execREAD_NODESREQ(Signal* signal)
-{
- jamEntry();
-
- /*----------------------------------------------------------------------*/
- // ANY BLOCK MAY SEND A REQUEST ABOUT NDB NODES AND VERSIONS IN THE
- // SYSTEM. THIS REQUEST CAN ONLY BE HANDLED IN
- // ABSOLUTE STARTPHASE 3 OR LATER
- /*----------------------------------------------------------------------*/
- BlockReference TuserBlockref = signal->theData[0];
- ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
-
- /**
- * Prepare inactiveNodes bitmask.
- * The concept as such is by the way pretty useless.
- * It makes parallell starts more or less impossible...
- */
- NdbNodeBitmask tmp1;
- tmp1.bitOR(c_startedNodes);
- if(!getNodeState().getNodeRestartInProgress()){
- tmp1.bitOR(c_start.m_starting);
- } else {
- tmp1.set(getOwnNodeId());
- }
-
- NdbNodeBitmask tmp2;
- tmp2.bitOR(c_allDefinedNodes);
- tmp2.bitANDC(tmp1);
- /**
- * Fill in return signal
- */
- tmp2.copyto(NdbNodeBitmask::Size, readNodes->inactiveNodes);
- c_allDefinedNodes.copyto(NdbNodeBitmask::Size, readNodes->allNodes);
- c_clusterNodes.copyto(NdbNodeBitmask::Size, readNodes->clusterNodes);
- c_startedNodes.copyto(NdbNodeBitmask::Size, readNodes->startedNodes);
- c_start.m_starting.copyto(NdbNodeBitmask::Size, readNodes->startingNodes);
-
- readNodes->noOfNodes = c_allDefinedNodes.count();
- readNodes->masterNodeId = cmasterNodeId;
- readNodes->ndynamicId = cdynamicNodeId;
- if (cstartPhase > ZSTART_PHASE_2) {
- jam();
- sendSignal(TuserBlockref, GSN_READ_NODESCONF, signal,
- ReadNodesConf::SignalLength, JBB);
-
- } else {
- jam();
- signal->theData[0] = ZNOT_AVAILABLE;
- sendSignal(TuserBlockref, GSN_READ_NODESREF, signal, 1, JBB);
- }//if
-}//Ndbcntr::execREAD_NODESREQ()
-
-/*----------------------------------------------------------------------*/
-// SENDS APPL_ERROR TO QMGR AND THEN SET A POINTER OUT OF BOUNDS
-/*----------------------------------------------------------------------*/
-void Ndbcntr::systemErrorLab(Signal* signal, int line)
-{
- progError(line, NDBD_EXIT_NDBREQUIRE); /* BUG INSERTION */
- return;
-}//Ndbcntr::systemErrorLab()
-
-/*###########################################################################*/
-/* CNTR MASTER CREATES AND INITIALIZES A SYSTEMTABLE AT INITIALSTART */
-/* |-2048| # 1 00000001 | */
-/* | : | : | */
-/* | -1 | # 1 00000001 | */
-/* | 1 | 0 | tupleid sequence now created on first use */
-/* | : | : | v */
-/* | 2048| 0 | v */
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
-{
- if (index >= g_sysTableCount) {
- ndbassert(index == g_sysTableCount);
- startInsertTransactions(signal);
- return;
- }
- const SysTable& table = *g_sysTableList[index];
- Uint32 propPage[256];
- LinearWriter w(propPage, 256);
-
- // XXX remove commented-out lines later
-
- w.first();
- w.add(DictTabInfo::TableName, table.name);
- w.add(DictTabInfo::TableLoggedFlag, table.tableLoggedFlag);
- //w.add(DictTabInfo::TableKValue, 6);
- //w.add(DictTabInfo::MinLoadFactor, 70);
- //w.add(DictTabInfo::MaxLoadFactor, 80);
- w.add(DictTabInfo::FragmentTypeVal, (Uint32)table.fragmentType);
- //w.add(DictTabInfo::NoOfKeyAttr, 1);
- w.add(DictTabInfo::NoOfAttributes, (Uint32)table.columnCount);
- //w.add(DictTabInfo::NoOfNullable, (Uint32)0);
- //w.add(DictTabInfo::NoOfVariable, (Uint32)0);
- //w.add(DictTabInfo::KeyLength, 1);
- w.add(DictTabInfo::TableTypeVal, (Uint32)table.tableType);
- w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
-
- for (unsigned i = 0; i < table.columnCount; i++) {
- const SysColumn& column = table.columnList[i];
- ndbassert(column.pos == i);
- w.add(DictTabInfo::AttributeName, column.name);
- w.add(DictTabInfo::AttributeId, (Uint32)i);
- w.add(DictTabInfo::AttributeKeyFlag, (Uint32)column.keyFlag);
- w.add(DictTabInfo::AttributeStorageType,
- (Uint32)NDB_STORAGETYPE_MEMORY);
- w.add(DictTabInfo::AttributeArrayType,
- (Uint32)NDB_ARRAYTYPE_FIXED);
- w.add(DictTabInfo::AttributeNullableFlag, (Uint32)column.nullable);
- w.add(DictTabInfo::AttributeExtType, (Uint32)column.type);
- w.add(DictTabInfo::AttributeExtLength, (Uint32)column.length);
- w.add(DictTabInfo::AttributeEnd, (Uint32)true);
- }
- w.add(DictTabInfo::TableEnd, (Uint32)true);
-
- Uint32 length = w.getWordsUsed();
- LinearSectionPtr ptr[3];
- ptr[0].p = &propPage[0];
- ptr[0].sz = length;
-
- CreateTableReq* const req = (CreateTableReq*)signal->getDataPtrSend();
- req->senderData = index;
- req->senderRef = reference();
- sendSignal(DBDICT_REF, GSN_CREATE_TABLE_REQ, signal,
- CreateTableReq::SignalLength, JBB, ptr, 1);
- return;
-}//Ndbcntr::createSystableLab()
-
-void Ndbcntr::execCREATE_TABLE_REF(Signal* signal)
-{
- jamEntry();
- progError(__LINE__,NDBD_EXIT_NDBREQUIRE, "CREATE_TABLE_REF");
- return;
-}//Ndbcntr::execDICTTABREF()
-
-void Ndbcntr::execCREATE_TABLE_CONF(Signal* signal)
-{
- jamEntry();
- CreateTableConf * const conf = (CreateTableConf*)signal->getDataPtrSend();
- //csystabId = conf->tableId;
- ndbrequire(conf->senderData < g_sysTableCount);
- const SysTable& table = *g_sysTableList[conf->senderData];
- table.tableId = conf->tableId;
- createSystableLab(signal, conf->senderData + 1);
- //startInsertTransactions(signal);
- return;
-}//Ndbcntr::execDICTTABCONF()
-
-/*******************************/
-/* DICTRELEASECONF */
-/*******************************/
-void Ndbcntr::startInsertTransactions(Signal* signal)
-{
- jamEntry();
-
- ckey = 1;
- ctransidPhase = ZTRUE;
- signal->theData[0] = 0;
- signal->theData[1] = reference();
- sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB);
- return;
-}//Ndbcntr::startInsertTransactions()
-
-/*******************************/
-/* TCSEIZECONF */
-/*******************************/
-void Ndbcntr::execTCSEIZECONF(Signal* signal)
-{
- jamEntry();
- ctcConnectionP = signal->theData[1];
- crSystab7Lab(signal);
- return;
-}//Ndbcntr::execTCSEIZECONF()
-
-const unsigned int RowsPerCommit = 16;
-void Ndbcntr::crSystab7Lab(Signal* signal)
-{
- UintR tkey;
- UintR Tmp;
-
- TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
-
- UintR reqInfo_Start = 0;
- tcKeyReq->setOperationType(reqInfo_Start, ZINSERT); // Insert
- tcKeyReq->setKeyLength (reqInfo_Start, 1);
- tcKeyReq->setAIInTcKeyReq (reqInfo_Start, 5);
- tcKeyReq->setAbortOption (reqInfo_Start, TcKeyReq::AbortOnError);
-
-/* KEY LENGTH = 1, ATTRINFO LENGTH IN TCKEYREQ = 5 */
- cresponses = 0;
- const UintR guard0 = ckey + (RowsPerCommit - 1);
- for (Tmp = ckey; Tmp <= guard0; Tmp++) {
- UintR reqInfo = reqInfo_Start;
- if (Tmp == ckey) { // First iteration, Set start flag
- jam();
- tcKeyReq->setStartFlag(reqInfo, 1);
- } //if
- if (Tmp == guard0) { // Last iteration, Set commit flag
- jam();
- tcKeyReq->setCommitFlag(reqInfo, 1);
- tcKeyReq->setExecuteFlag(reqInfo, 1);
- } //if
- if (ctransidPhase == ZTRUE) {
- jam();
- tkey = 0;
- tkey = tkey - Tmp;
- } else {
- jam();
- tkey = Tmp;
- }//if
-
- tcKeyReq->apiConnectPtr = ctcConnectionP;
- tcKeyReq->attrLen = 5;
- tcKeyReq->tableId = g_sysTable_SYSTAB_0.tableId;
- tcKeyReq->requestInfo = reqInfo;
- tcKeyReq->tableSchemaVersion = ZSYSTAB_VERSION;
- tcKeyReq->transId1 = 0;
- tcKeyReq->transId2 = ckey;
-
-//-------------------------------------------------------------
-// There is no optional part in this TCKEYREQ. There is one
-// key word and five ATTRINFO words.
-//-------------------------------------------------------------
- Uint32* tKeyDataPtr = &tcKeyReq->scanInfo;
- Uint32* tAIDataPtr = &tKeyDataPtr[1];
-
- tKeyDataPtr[0] = tkey;
-
- AttributeHeader::init(&tAIDataPtr[0], 0, 1 << 2);
- tAIDataPtr[1] = tkey;
- AttributeHeader::init(&tAIDataPtr[2], 1, 2 << 2);
- tAIDataPtr[3] = (tkey << 16);
- tAIDataPtr[4] = 1;
- sendSignal(DBTC_REF, GSN_TCKEYREQ, signal,
- TcKeyReq::StaticLength + 6, JBB);
- }//for
- ckey = ckey + RowsPerCommit;
- return;
-}//Ndbcntr::crSystab7Lab()
-
-/*******************************/
-/* TCKEYCONF09 */
-/*******************************/
-void Ndbcntr::execTCKEYCONF(Signal* signal)
-{
- const TcKeyConf * const keyConf = (TcKeyConf *)&signal->theData[0];
-
- jamEntry();
- cgciSystab = keyConf->gci;
- UintR confInfo = keyConf->confInfo;
-
- if (TcKeyConf::getMarkerFlag(confInfo)){
- Uint32 transId1 = keyConf->transId1;
- Uint32 transId2 = keyConf->transId2;
- signal->theData[0] = transId1;
- signal->theData[1] = transId2;
- sendSignal(DBTC_REF, GSN_TC_COMMIT_ACK, signal, 2, JBB);
- }//if
-
- cresponses = cresponses + TcKeyConf::getNoOfOperations(confInfo);
- if (TcKeyConf::getCommitFlag(confInfo)){
- jam();
- ndbrequire(cresponses == RowsPerCommit);
-
- crSystab8Lab(signal);
- return;
- }
- return;
-}//Ndbcntr::tckeyConfLab()
-
-void Ndbcntr::crSystab8Lab(Signal* signal)
-{
- if (ckey < ZSIZE_SYSTAB) {
- jam();
- crSystab7Lab(signal);
- return;
- } else if (ctransidPhase == ZTRUE) {
- jam();
- ckey = 1;
- ctransidPhase = ZFALSE;
- // skip 2nd loop - tupleid sequence now created on first use
- }//if
- signal->theData[0] = ctcConnectionP;
- signal->theData[1] = reference();
- signal->theData[2] = 0;
- sendSignal(DBTC_REF, GSN_TCRELEASEREQ, signal, 2, JBB);
- return;
-}//Ndbcntr::crSystab8Lab()
-
-/*******************************/
-/* TCRELEASECONF */
-/*******************************/
-void Ndbcntr::execTCRELEASECONF(Signal* signal)
-{
- jamEntry();
- waitpoint52Lab(signal);
- return;
-}//Ndbcntr::execTCRELEASECONF()
-
-void Ndbcntr::crSystab9Lab(Signal* signal)
-{
- signal->theData[1] = reference();
- sendSignalWithDelay(DBDIH_REF, GSN_GETGCIREQ, signal, 100, 2);
- return;
-}//Ndbcntr::crSystab9Lab()
-
-/*******************************/
-/* GETGCICONF */
-/*******************************/
-void Ndbcntr::execGETGCICONF(Signal* signal)
-{
- jamEntry();
-
-#ifndef NO_GCP
- if (signal->theData[1] < cgciSystab) {
- jam();
-/*--------------------------------------*/
-/* MAKE SURE THAT THE SYSTABLE IS */
-/* NOW SAFE ON DISK */
-/*--------------------------------------*/
- crSystab9Lab(signal);
- return;
- }//if
-#endif
- waitpoint52Lab(signal);
- return;
-}//Ndbcntr::execGETGCICONF()
-
-void Ndbcntr::execTCKEYREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Ndbcntr::execTCKEYREF()
-
-void Ndbcntr::execTCROLLBACKREP(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Ndbcntr::execTCROLLBACKREP()
-
-void Ndbcntr::execTCRELEASEREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Ndbcntr::execTCRELEASEREF()
-
-void Ndbcntr::execTCSEIZEREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Ndbcntr::execTCSEIZEREF()
-
-
-/*---------------------------------------------------------------------------*/
-/*INITIALIZE VARIABLES AND RECORDS */
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::initData(Signal* signal)
-{
- c_start.reset();
- cmasterNodeId = 0;
- cnoStartNodes = 0;
- cnoWaitrep = 0;
-}//Ndbcntr::initData()
-
-
-/*---------------------------------------------------------------------------*/
-/*RESET VARIABLES USED DURING THE START */
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::resetStartVariables(Signal* signal)
-{
- cnoStartNodes = 0;
- cnoWaitrep6 = cnoWaitrep7 = 0;
-}//Ndbcntr::resetStartVariables()
-
-
-/*---------------------------------------------------------------------------*/
-// SEND THE SIGNAL
-// INPUT CNDB_BLOCKS_COUNT
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::sendNdbSttor(Signal* signal)
-{
- NdbBlocksRecPtr ndbBlocksPtr;
-
- ndbBlocksPtr.i = cndbBlocksCount;
- ptrCheckGuard(ndbBlocksPtr, ZSIZE_NDB_BLOCKS_REC, ndbBlocksRec);
-
- NdbSttor * const req = (NdbSttor*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->nodeId = getOwnNodeId();
- req->internalStartPhase = cinternalStartphase;
- req->typeOfStart = ctypeOfStart;
- req->masterNodeId = cmasterNodeId;
-
- for (int i = 0; i < 16; i++) {
- // Garbage
- req->config[i] = 0x88776655;
- //cfgBlockPtr.p->cfgData[i];
- }
-
- //#define MAX_STARTPHASE 2
-#ifdef TRACE_STTOR
- ndbout_c("sending NDB_STTOR(%d) to %s",
- cinternalStartphase,
- getBlockName( refToBlock(ndbBlocksPtr.p->blockref)));
-#endif
- sendSignal(ndbBlocksPtr.p->blockref, GSN_NDB_STTOR, signal, 22, JBB);
- cndbBlocksCount++;
-}//Ndbcntr::sendNdbSttor()
-
-/*---------------------------------------------------------------------------*/
-// JUST SEND THE SIGNAL
-/*---------------------------------------------------------------------------*/
-void Ndbcntr::sendSttorry(Signal* signal)
-{
- signal->theData[3] = ZSTART_PHASE_1;
- signal->theData[4] = ZSTART_PHASE_2;
- signal->theData[5] = ZSTART_PHASE_3;
- signal->theData[6] = ZSTART_PHASE_4;
- signal->theData[7] = ZSTART_PHASE_5;
- signal->theData[8] = ZSTART_PHASE_6;
- // skip simulated phase 7
- signal->theData[9] = ZSTART_PHASE_8;
- signal->theData[10] = ZSTART_PHASE_9;
- signal->theData[11] = ZSTART_PHASE_END;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 12, JBB);
-}//Ndbcntr::sendSttorry()
-
-void
-Ndbcntr::execDUMP_STATE_ORD(Signal* signal)
-{
- DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
- Uint32 arg = dumpState->args[0];
-
- if(arg == 13){
- infoEvent("Cntr: cstartPhase = %d, cinternalStartphase = %d, block = %d",
- cstartPhase, cinternalStartphase, cndbBlocksCount);
- infoEvent("Cntr: cmasterNodeId = %d", cmasterNodeId);
- }
-
- if (arg == DumpStateOrd::NdbcntrTestStopOnError){
- if (m_ctx.m_config.stopOnError() == true)
- ((Configuration&)m_ctx.m_config).stopOnError(false);
-
- const BlockReference tblockref = calcNdbCntrBlockRef(getOwnNodeId());
-
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::TestStopOnError;
- sysErr->errorRef = reference();
- sendSignal(tblockref, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBA);
- }
-
- if (arg == DumpStateOrd::NdbcntrStopNodes)
- {
- NdbNodeBitmask mask;
- for(Uint32 i = 1; i<signal->getLength(); i++)
- mask.set(signal->theData[i]);
-
- StopReq* req = (StopReq*)signal->getDataPtrSend();
- req->senderRef = RNIL;
- req->senderData = 123;
- req->requestInfo = 0;
- req->singleuser = 0;
- req->singleUserApi = 0;
- mask.copyto(NdbNodeBitmask::Size, req->nodes);
- StopReq::setPerformRestart(req->requestInfo, 1);
- StopReq::setNoStart(req->requestInfo, 1);
- StopReq::setStopNodes(req->requestInfo, 1);
- StopReq::setStopAbort(req->requestInfo, 1);
-
- sendSignal(reference(), GSN_STOP_REQ, signal,
- StopReq::SignalLength, JBB);
- return;
- }
-
-}//Ndbcntr::execDUMP_STATE_ORD()
-
-void Ndbcntr::updateNodeState(Signal* signal, const NodeState& newState) const{
- NodeStateRep * const stateRep = (NodeStateRep *)&signal->theData[0];
-
- if (newState.startLevel == NodeState::SL_STARTED)
- {
- CRASH_INSERTION(1000);
- }
-
- stateRep->nodeState = newState;
- stateRep->nodeState.masterNodeId = cmasterNodeId;
- stateRep->nodeState.setNodeGroup(c_nodeGroup);
-
- for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){
- sendSignal(ALL_BLOCKS[i].Ref, GSN_NODE_STATE_REP, signal,
- NodeStateRep::SignalLength, JBB);
- }
-}
-
-void
-Ndbcntr::execRESUME_REQ(Signal* signal){
- //ResumeReq * const req = (ResumeReq *)&signal->theData[0];
- //ResumeRef * const ref = (ResumeRef *)&signal->theData[0];
-
- jamEntry();
-
- signal->theData[0] = NDB_LE_SingleUser;
- signal->theData[1] = 2;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- //Uint32 senderData = req->senderData;
- //BlockReference senderRef = req->senderRef;
- NodeState newState(NodeState::SL_STARTED);
- updateNodeState(signal, newState);
- c_stopRec.stopReq.senderRef=0;
-}
-
-void
-Ndbcntr::execSTOP_REQ(Signal* signal){
- StopReq * const req = (StopReq *)&signal->theData[0];
- StopRef * const ref = (StopRef *)&signal->theData[0];
- Uint32 singleuser = req->singleuser;
- jamEntry();
- Uint32 senderData = req->senderData;
- BlockReference senderRef = req->senderRef;
- bool abort = StopReq::getStopAbort(req->requestInfo);
- bool stopnodes = StopReq::getStopNodes(req->requestInfo);
-
- if(!singleuser &&
- (getNodeState().startLevel < NodeState::SL_STARTED ||
- (abort && !stopnodes)))
- {
- /**
- * Node is not started yet
- *
- * So stop it quickly
- */
- jam();
- const Uint32 reqInfo = req->requestInfo;
- if(StopReq::getPerformRestart(reqInfo)){
- jam();
- StartOrd * startOrd = (StartOrd *)&signal->theData[0];
- startOrd->restartInfo = reqInfo;
- sendSignal(CMVMI_REF, GSN_START_ORD, signal, 1, JBA);
- } else {
- jam();
- sendSignal(CMVMI_REF, GSN_STOP_ORD, signal, 1, JBA);
- }
- return;
- }
-
- if(c_stopRec.stopReq.senderRef != 0 ||
- (cmasterNodeId == getOwnNodeId() && !c_start.m_starting.isclear()))
- {
- /**
- * Requested a system shutdown
- */
- if(!singleuser && StopReq::getSystemStop(req->requestInfo)){
- jam();
- sendSignalWithDelay(reference(), GSN_STOP_REQ, signal, 100,
- StopReq::SignalLength);
- return;
- }
-
- /**
- * Requested a node shutdown
- */
- 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);
- return;
- }
-
- if (stopnodes && !abort)
- {
- jam();
- ref->errorCode = StopRef::UnsupportedNodeShutdown;
- ref->senderData = senderData;
- ref->masterNodeId = cmasterNodeId;
- if (senderRef != RNIL)
- sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
- return;
- }
-
- if (stopnodes && cmasterNodeId != getOwnNodeId())
- {
- jam();
- ref->errorCode = StopRef::MultiNodeShutdownNotMaster;
- ref->senderData = senderData;
- ref->masterNodeId = cmasterNodeId;
- if (senderRef != RNIL)
- sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
- return;
- }
-
- c_stopRec.stopReq = * req;
- c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond();
-
- if (stopnodes)
- {
- jam();
-
- if(!c_stopRec.checkNodeFail(signal))
- {
- jam();
- return;
- }
-
- char buf[100];
- NdbNodeBitmask mask;
- mask.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes);
- infoEvent("Initiating shutdown abort of %s", mask.getText(buf));
- ndbout_c("Initiating shutdown abort of %s", mask.getText(buf));
-
- WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = StopRecord::SR_BLOCK_GCP_START_GCP;
- req->requestType = WaitGCPReq::BlockStartGcp;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBB);
- return;
- }
- else if(!singleuser)
- {
- if(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo))
- {
- jam();
- if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo))
- {
- ((Configuration&)m_ctx.m_config).stopOnError(false);
- }
- }
- if(!c_stopRec.checkNodeFail(signal))
- {
- jam();
- return;
- }
- 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] = NDB_LE_SingleUser;
- signal->theData[1] = 0;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
- }
-
- NodeState newState(NodeState::SL_STOPPING_1,
- StopReq::getSystemStop(c_stopRec.stopReq.requestInfo));
-
- if(singleuser) {
- newState.setSingleUser(true);
- newState.setSingleUserApi(c_stopRec.stopReq.singleUserApi);
- }
- updateNodeState(signal, newState);
- signal->theData[0] = ZSHUTDOWN;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
-}
-
-void
-Ndbcntr::StopRecord::checkTimeout(Signal* signal){
- jamEntry();
-
- if(!cntr.getNodeState().getSingleUserMode())
- if(!checkNodeFail(signal)){
- jam();
- return;
- }
-
- switch(cntr.getNodeState().startLevel){
- case NodeState::SL_STOPPING_1:
- checkApiTimeout(signal);
- break;
- case NodeState::SL_STOPPING_2:
- checkTcTimeout(signal);
- break;
- case NodeState::SL_STOPPING_3:
- checkLqhTimeout_1(signal);
- break;
- case NodeState::SL_STOPPING_4:
- checkLqhTimeout_2(signal);
- break;
- case NodeState::SL_SINGLEUSER:
- break;
- default:
- ndbrequire(false);
- }
-}
-
-bool
-Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
- jam();
- if(StopReq::getSystemStop(stopReq.requestInfo)){
- jam();
- return true;
- }
-
- /**
- * Check if I can survive me stopping
- */
- NodeBitmask ndbMask;
- ndbMask.assign(cntr.c_startedNodes);
-
- if (StopReq::getStopNodes(stopReq.requestInfo))
- {
- NdbNodeBitmask tmp;
- tmp.assign(NdbNodeBitmask::Size, stopReq.nodes);
-
- NdbNodeBitmask ndbStopNodes;
- ndbStopNodes.assign(NdbNodeBitmask::Size, stopReq.nodes);
- ndbStopNodes.bitAND(ndbMask);
- ndbStopNodes.copyto(NdbNodeBitmask::Size, stopReq.nodes);
-
- ndbMask.bitANDC(tmp);
-
- bool allNodesStopped = true;
- int i ;
- for( i = 0; i < (int) NdbNodeBitmask::Size; i++ ){
- if ( stopReq.nodes[i] != 0 ){
- allNodesStopped = false;
- break;
- }
- }
-
- if ( allNodesStopped ) {
- StopConf * const stopConf = (StopConf *)&signal->theData[0];
- stopConf->senderData = stopReq.senderData;
- stopConf->nodeState = (Uint32) NodeState::SL_NOTHING;
- cntr.sendSignal(stopReq.senderRef, GSN_STOP_CONF, signal,
- StopConf::SignalLength, JBB);
- stopReq.senderRef = 0;
- return false;
- }
-
- }
- else
- {
- ndbMask.clear(cntr.getOwnNodeId());
- }
-
- CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
- sd->blockRef = cntr.reference();
- sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
- sd->mask = ndbMask;
- cntr.EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
- CheckNodeGroups::SignalLength);
- jamEntry();
- switch (sd->output) {
- case CheckNodeGroups::Win:
- case CheckNodeGroups::Partitioning:
- return true;
- break;
- }
-
- StopRef * const ref = (StopRef *)&signal->theData[0];
-
- ref->senderData = stopReq.senderData;
- ref->errorCode = StopRef::NodeShutdownWouldCauseSystemCrash;
- ref->masterNodeId = cntr.cmasterNodeId;
-
- const BlockReference bref = stopReq.senderRef;
- if (bref != RNIL)
- cntr.sendSignal(bref, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
-
- stopReq.senderRef = 0;
-
- if (cntr.getNodeState().startLevel != NodeState::SL_SINGLEUSER)
- {
- NodeState newState(NodeState::SL_STARTED);
- cntr.updateNodeState(signal, newState);
- }
-
- signal->theData[0] = NDB_LE_NDBStopAborted;
- cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
-
- return false;
-}
-
-void
-Ndbcntr::StopRecord::checkApiTimeout(Signal* signal){
- const Int32 timeout = stopReq.apiTimeout;
- const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout;
- const NDB_TICKS now = NdbTick_CurrentMillisecond();
- if((timeout >= 0 && now >= alarm)){
- // || checkWithApiInSomeMagicWay)
- jam();
- NodeState newState(NodeState::SL_STOPPING_2,
- StopReq::getSystemStop(stopReq.requestInfo));
- if(stopReq.singleuser) {
- newState.setSingleUser(true);
- newState.setSingleUserApi(stopReq.singleUserApi);
- }
- cntr.updateNodeState(signal, newState);
-
- stopInitiatedTime = now;
- }
-
- signal->theData[0] = ZSHUTDOWN;
- cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1);
-}
-
-void
-Ndbcntr::StopRecord::checkTcTimeout(Signal* signal){
- const Int32 timeout = stopReq.transactionTimeout;
- const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout;
- const NDB_TICKS now = NdbTick_CurrentMillisecond();
- if((timeout >= 0 && now >= alarm)){
- // || checkWithTcInSomeMagicWay)
- jam();
- if(stopReq.getSystemStop(stopReq.requestInfo) || stopReq.singleuser){
- jam();
- if(stopReq.singleuser)
- {
- jam();
- AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
- req->senderRef = cntr.reference();
- req->senderData = 12;
- cntr.sendSignal(DBTC_REF, GSN_ABORT_ALL_REQ, signal,
- AbortAllReq::SignalLength, JBB);
- }
- else
- {
- WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
- req->senderRef = cntr.reference();
- req->senderData = StopRecord::SR_CLUSTER_SHUTDOWN;
- req->requestType = WaitGCPReq::CompleteForceStart;
- cntr.sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBB);
- }
- } else {
- jam();
- StopPermReq * req = (StopPermReq*)&signal->theData[0];
- req->senderRef = cntr.reference();
- req->senderData = 12;
- cntr.sendSignal(DBDIH_REF, GSN_STOP_PERM_REQ, signal,
- StopPermReq::SignalLength, JBB);
- }
- return;
- }
- signal->theData[0] = ZSHUTDOWN;
- cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1);
-}
-
-void Ndbcntr::execSTOP_PERM_REF(Signal* signal){
- //StopPermRef* const ref = (StopPermRef*)&signal->theData[0];
-
- jamEntry();
-
- signal->theData[0] = ZSHUTDOWN;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
-}
-
-void Ndbcntr::execSTOP_PERM_CONF(Signal* signal){
- jamEntry();
-
- AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = 12;
- sendSignal(DBTC_REF, GSN_ABORT_ALL_REQ, signal,
- AbortAllReq::SignalLength, JBB);
-}
-
-void Ndbcntr::execABORT_ALL_CONF(Signal* signal){
- jamEntry();
- if(c_stopRec.stopReq.singleuser) {
- jam();
-
- NodeState newState(NodeState::SL_SINGLEUSER);
- newState.setSingleUser(true);
- newState.setSingleUserApi(c_stopRec.stopReq.singleUserApi);
- updateNodeState(signal, newState);
- c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond();
-
- StopConf * const stopConf = (StopConf *)&signal->theData[0];
- stopConf->senderData = c_stopRec.stopReq.senderData;
- stopConf->nodeState = (Uint32) NodeState::SL_SINGLEUSER;
- sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_CONF, signal, StopConf::SignalLength, JBB);
-
- c_stopRec.stopReq.senderRef = 0; // the command is done
-
- 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);
- }
- else
- {
- jam();
- NodeState newState(NodeState::SL_STOPPING_3,
- StopReq::getSystemStop(c_stopRec.stopReq.requestInfo));
- updateNodeState(signal, newState);
-
- c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond();
-
- signal->theData[0] = ZSHUTDOWN;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
- }
-}
-
-void Ndbcntr::execABORT_ALL_REF(Signal* signal){
- jamEntry();
-
- 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);
-}
-
-void
-Ndbcntr::StopRecord::checkLqhTimeout_1(Signal* signal){
- const Int32 timeout = stopReq.readOperationTimeout;
- const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout;
- const NDB_TICKS now = NdbTick_CurrentMillisecond();
-
- if((timeout >= 0 && now >= alarm)){
- // || checkWithLqhInSomeMagicWay)
- jam();
-
- ChangeNodeStateReq * req = (ChangeNodeStateReq*)&signal->theData[0];
-
- NodeState newState(NodeState::SL_STOPPING_4,
- StopReq::getSystemStop(stopReq.requestInfo));
- req->nodeState = newState;
- req->senderRef = cntr.reference();
- req->senderData = 12;
- cntr.sendSignal(DBLQH_REF, GSN_CHANGE_NODE_STATE_REQ, signal, 2, JBB);
- return;
- }
- signal->theData[0] = ZSHUTDOWN;
- cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1);
-}
-
-void Ndbcntr::execCHANGE_NODE_STATE_CONF(Signal* signal){
- jamEntry();
- signal->theData[0] = reference();
- signal->theData[1] = 12;
- sendSignal(DBDIH_REF, GSN_STOP_ME_REQ, signal, 2, JBB);
-}
-
-void Ndbcntr::execSTOP_ME_REF(Signal* signal){
- jamEntry();
- ndbrequire(false);
-}
-
-
-void Ndbcntr::execSTOP_ME_CONF(Signal* signal){
- jamEntry();
-
- NodeState newState(NodeState::SL_STOPPING_4,
- StopReq::getSystemStop(c_stopRec.stopReq.requestInfo));
- updateNodeState(signal, newState);
-
- c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond();
- signal->theData[0] = ZSHUTDOWN;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 1);
-}
-
-void
-Ndbcntr::StopRecord::checkLqhTimeout_2(Signal* signal){
- const Int32 timeout = stopReq.operationTimeout;
- const NDB_TICKS alarm = stopInitiatedTime + (NDB_TICKS)timeout;
- const NDB_TICKS now = NdbTick_CurrentMillisecond();
-
- if((timeout >= 0 && now >= alarm)){
- // || checkWithLqhInSomeMagicWay)
- jam();
- if(StopReq::getPerformRestart(stopReq.requestInfo)){
- jam();
- StartOrd * startOrd = (StartOrd *)&signal->theData[0];
- startOrd->restartInfo = stopReq.requestInfo;
- cntr.sendSignal(CMVMI_REF, GSN_START_ORD, signal, 2, JBA);
- } else {
- jam();
- cntr.sendSignal(CMVMI_REF, GSN_STOP_ORD, signal, 1, JBA);
- }
- return;
- }
- signal->theData[0] = ZSHUTDOWN;
- cntr.sendSignalWithDelay(cntr.reference(), GSN_CONTINUEB, signal, 100, 1);
-}
-
-void Ndbcntr::execWAIT_GCP_REF(Signal* signal){
- jamEntry();
-
- //WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0];
-
- WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = StopRecord::SR_CLUSTER_SHUTDOWN;
- req->requestType = WaitGCPReq::CompleteForceStart;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBB);
-}
-
-void Ndbcntr::execWAIT_GCP_CONF(Signal* signal){
- jamEntry();
-
- WaitGCPConf* conf = (WaitGCPConf*)signal->getDataPtr();
-
- switch(conf->senderData){
- case StopRecord::SR_BLOCK_GCP_START_GCP:
- {
- jam();
- /**
- *
- */
- if(!c_stopRec.checkNodeFail(signal))
- {
- jam();
- goto unblock;
- }
-
- WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = StopRecord::SR_WAIT_COMPLETE_GCP;
- req->requestType = WaitGCPReq::CompleteIfRunning;
-
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBB);
- return;
- }
- case StopRecord::SR_UNBLOCK_GCP_START_GCP:
- {
- jam();
- return;
- }
- case StopRecord::SR_WAIT_COMPLETE_GCP:
- {
- jam();
- if(!c_stopRec.checkNodeFail(signal))
- {
- jam();
- goto unblock;
- }
-
- NdbNodeBitmask tmp;
- tmp.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes);
- c_stopRec.m_stop_req_counter = tmp;
- NodeReceiverGroup rg(QMGR, tmp);
- StopReq * stopReq = (StopReq *)&signal->theData[0];
- * stopReq = c_stopRec.stopReq;
- stopReq->senderRef = reference();
- sendSignal(rg, GSN_STOP_REQ, signal, StopReq::SignalLength, JBA);
- c_stopRec.m_state = StopRecord::SR_QMGR_STOP_REQ;
- return;
- }
- case StopRecord::SR_CLUSTER_SHUTDOWN:
- {
- jam();
- break;
- }
- }
-
- {
- ndbrequire(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo));
- NodeState newState(NodeState::SL_STOPPING_3, true);
-
- /**
- * Inform QMGR so that arbitrator won't kill us
- */
- NodeStateRep * rep = (NodeStateRep *)&signal->theData[0];
- rep->nodeState = newState;
- rep->nodeState.masterNodeId = cmasterNodeId;
- rep->nodeState.setNodeGroup(c_nodeGroup);
- EXECUTE_DIRECT(QMGR, GSN_NODE_STATE_REP, signal,
- NodeStateRep::SignalLength);
-
- if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){
- jam();
- StartOrd * startOrd = (StartOrd *)&signal->theData[0];
- startOrd->restartInfo = c_stopRec.stopReq.requestInfo;
- sendSignalWithDelay(CMVMI_REF, GSN_START_ORD, signal, 500,
- StartOrd::SignalLength);
- } else {
- jam();
- sendSignalWithDelay(CMVMI_REF, GSN_STOP_ORD, signal, 500, 1);
- }
- return;
- }
-
-unblock:
- WaitGCPReq * req = (WaitGCPReq*)&signal->theData[0];
- req->senderRef = reference();
- req->senderData = StopRecord::SR_UNBLOCK_GCP_START_GCP;
- req->requestType = WaitGCPReq::UnblockStartGcp;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength, JBB);
-}
-
-void
-Ndbcntr::execSTOP_CONF(Signal* signal)
-{
- jamEntry();
- StopConf *conf = (StopConf*)signal->getDataPtr();
- ndbrequire(c_stopRec.m_state == StopRecord::SR_QMGR_STOP_REQ);
- c_stopRec.m_stop_req_counter.clearWaitingFor(conf->nodeId);
- if (c_stopRec.m_stop_req_counter.done())
- {
- char buf[100];
- NdbNodeBitmask mask;
- mask.assign(NdbNodeBitmask::Size, c_stopRec.stopReq.nodes);
- infoEvent("Stopping of %s", mask.getText(buf));
- ndbout_c("Stopping of %s", mask.getText(buf));
-
- /**
- * Kill any node...
- */
- FailRep * const failRep = (FailRep *)&signal->theData[0];
- failRep->failCause = FailRep::ZMULTI_NODE_SHUTDOWN;
- NodeReceiverGroup rg(QMGR, c_clusterNodes);
- Uint32 nodeId = 0;
- while ((nodeId = NdbNodeBitmask::find(c_stopRec.stopReq.nodes, nodeId+1))
- != NdbNodeBitmask::NotFound)
- {
- failRep->failNodeId = nodeId;
- sendSignal(rg, GSN_FAIL_REP, signal, FailRep::SignalLength, JBA);
- }
- c_stopRec.m_state = StopRecord::SR_WAIT_NODE_FAILURES;
- return;
- }
-}
-
-void Ndbcntr::execSTTORRY(Signal* signal){
- jamEntry();
- c_missra.execSTTORRY(signal);
-}
-
-void Ndbcntr::execREAD_CONFIG_CONF(Signal* signal){
- jamEntry();
- c_missra.execREAD_CONFIG_CONF(signal);
-}
-
-void Ndbcntr::execSTART_ORD(Signal* signal){
- jamEntry();
- c_missra.execSTART_ORD(signal);
-}
-
-#define CLEAR_DX 13
-#define CLEAR_LCP 3
-
-void
-Ndbcntr::clearFilesystem(Signal* signal)
-{
- const Uint32 lcp = c_fsRemoveCount >= CLEAR_DX;
-
- FsRemoveReq * req = (FsRemoveReq *)signal->getDataPtrSend();
- req->userReference = reference();
- req->userPointer = 0;
- req->directory = 1;
- req->ownDirectory = 1;
-
- if (lcp == 0)
- {
- FsOpenReq::setVersion(req->fileNumber, 3);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_CTL); // Can by any...
- FsOpenReq::v1_setDisk(req->fileNumber, c_fsRemoveCount);
- }
- else
- {
- FsOpenReq::setVersion(req->fileNumber, 5);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
- FsOpenReq::v5_setLcpNo(req->fileNumber, c_fsRemoveCount - CLEAR_DX);
- FsOpenReq::v5_setTableId(req->fileNumber, 0);
- FsOpenReq::v5_setFragmentId(req->fileNumber, 0);
- }
- sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
- FsRemoveReq::SignalLength, JBA);
- c_fsRemoveCount++;
-}
-
-void
-Ndbcntr::execFSREMOVECONF(Signal* signal){
- jamEntry();
- if(c_fsRemoveCount == CLEAR_DX + CLEAR_LCP){
- jam();
- sendSttorry(signal);
- } else {
- jam();
- ndbrequire(c_fsRemoveCount < CLEAR_DX + CLEAR_LCP);
- clearFilesystem(signal);
- }//if
-}
-
-void Ndbcntr::Missra::execSTART_ORD(Signal* signal){
- signal->theData[0] = NDB_LE_NDBStartStarted;
- signal->theData[1] = NDB_VERSION;
- cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- currentBlockIndex = 0;
- sendNextREAD_CONFIG_REQ(signal);
-}
-
-void Ndbcntr::Missra::sendNextREAD_CONFIG_REQ(Signal* signal){
-
- if(currentBlockIndex < ALL_BLOCKS_SZ){
- jam();
-
- ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtrSend();
- req->senderData = 0;
- req->senderRef = cntr.reference();
- req->noOfParameters = 0;
-
- const BlockReference ref = readConfigOrder[currentBlockIndex];
-
-#if 0
- ndbout_c("sending READ_CONFIG_REQ to %s(ref=%x index=%d)",
- getBlockName( refToBlock(ref)),
- ref,
- currentBlockIndex);
-#endif
-
- cntr.sendSignal(ref, GSN_READ_CONFIG_REQ, signal,
- ReadConfigReq::SignalLength, JBB);
- return;
- }
-
- /**
- * Finished...
- */
- currentStartPhase = 0;
- for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){
- if(ALL_BLOCKS[i].NextSP < currentStartPhase)
- currentStartPhase = ALL_BLOCKS[i].NextSP;
- }
-
- currentBlockIndex = 0;
- sendNextSTTOR(signal);
-}
-
-void Ndbcntr::Missra::execREAD_CONFIG_CONF(Signal* signal){
- const ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtr();
-
- const Uint32 ref = conf->senderRef;
- ndbrequire(refToBlock(readConfigOrder[currentBlockIndex])
- == refToBlock(ref));
-
- currentBlockIndex++;
- sendNextREAD_CONFIG_REQ(signal);
-}
-
-void Ndbcntr::Missra::execSTTORRY(Signal* signal){
- const BlockReference ref = signal->senderBlockRef();
- ndbrequire(refToBlock(ref) == refToBlock(ALL_BLOCKS[currentBlockIndex].Ref));
-
- /**
- * Update next start phase
- */
- for (Uint32 i = 3; i < 25; i++){
- jam();
- if (signal->theData[i] > currentStartPhase){
- jam();
- ALL_BLOCKS[currentBlockIndex].NextSP = signal->theData[i];
- break;
- }
- }
-
- currentBlockIndex++;
- sendNextSTTOR(signal);
-}
-
-void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){
-
- for(; currentStartPhase < 255 ;
- currentStartPhase++, g_currentStartPhase = currentStartPhase){
- jam();
-
- const Uint32 start = currentBlockIndex;
-
- if (currentStartPhase == ZSTART_PHASE_6)
- {
- // Ndbd has passed the critical startphases.
- // Change error handler from "startup" state
- // to normal state.
- ErrorReporter::setErrorHandlerShutdownType();
- }
-
- for(; currentBlockIndex < ALL_BLOCKS_SZ; currentBlockIndex++){
- jam();
- if(ALL_BLOCKS[currentBlockIndex].NextSP == currentStartPhase){
- jam();
- signal->theData[0] = 0;
- signal->theData[1] = currentStartPhase;
- signal->theData[2] = 0;
- signal->theData[3] = 0;
- signal->theData[4] = 0;
- signal->theData[5] = 0;
- signal->theData[6] = 0;
- signal->theData[7] = cntr.ctypeOfStart;
-
- const BlockReference ref = ALL_BLOCKS[currentBlockIndex].Ref;
-
-#ifdef MAX_STARTPHASE
- ndbrequire(currentStartPhase <= MAX_STARTPHASE);
-#endif
-
-#ifdef TRACE_STTOR
- ndbout_c("sending STTOR(%d) to %s(ref=%x index=%d)",
- currentStartPhase,
- getBlockName( refToBlock(ref)),
- ref,
- currentBlockIndex);
-#endif
-
- cntr.sendSignal(ref, GSN_STTOR, signal, 8, JBB);
-
- return;
- }
- }
-
- currentBlockIndex = 0;
-
- NodeState newState(NodeState::SL_STARTING, currentStartPhase,
- (NodeState::StartType)cntr.ctypeOfStart);
- cntr.updateNodeState(signal, newState);
-
- if(start != 0){
- /**
- * At least one wanted this start phase, report it
- */
- jam();
- 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] = NDB_LE_NDBStartCompleted;
- signal->theData[1] = NDB_VERSION;
- cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- NodeState newState(NodeState::SL_STARTED);
- cntr.updateNodeState(signal, newState);
-
- /**
- * Backward
- */
- UpgradeStartup::sendCmAppChg(cntr, signal, 3); //RUN
-
- NdbNodeBitmask nodes = cntr.c_clusterNodes;
- Uint32 node = 0;
- while((node = nodes.find(node+1)) != NdbNodeBitmask::NotFound){
- if(cntr.getNodeInfo(node).m_version < MAKE_VERSION(3,5,0)){
- nodes.clear(node);
- }
- }
-
- NodeReceiverGroup rg(NDBCNTR, nodes);
- signal->theData[0] = cntr.getOwnNodeId();
- cntr.sendSignal(rg, GSN_CNTR_START_REP, signal, 1, JBB);
-}
-
-/**
- * Backward compatible code
- */
-void
-UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){
-
- if(cntr.getNodeInfo(cntr.cmasterNodeId).m_version >= MAKE_VERSION(3,5,0)){
- jam();
- return;
- }
-
- /**
- * Old NDB running
- */
-
- signal->theData[0] = startLevel;
- signal->theData[1] = cntr.getOwnNodeId();
- signal->theData[2] = 3 | ('N' << 8);
- signal->theData[3] = 'D' | ('B' << 8);
- signal->theData[4] = 0;
- signal->theData[5] = 0;
- signal->theData[6] = 0;
- signal->theData[7] = 0;
- signal->theData[8] = 0;
- signal->theData[9] = 0;
- signal->theData[10] = 0;
- signal->theData[11] = 0;
-
- NdbNodeBitmask nodes = cntr.c_clusterNodes;
- nodes.clear(cntr.getOwnNodeId());
- Uint32 node = 0;
- while((node = nodes.find(node+1)) != NdbNodeBitmask::NotFound){
- if(cntr.getNodeInfo(node).m_version < MAKE_VERSION(3,5,0)){
- cntr.sendSignal(cntr.calcQmgrBlockRef(node),
- GSN_CM_APPCHG, signal, 12, JBB);
- } else {
- cntr.c_startedNodes.set(node); // Fake started
- }
- }
-}
-
-void
-UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
- Uint32 state = signal->theData[0];
- Uint32 nodeId = signal->theData[1];
- if(block.number() == QMGR){
- Ndbcntr& cntr = * (Ndbcntr*)globalData.getBlock(CNTR);
- switch(state){
- case 0: // ZADD
- break;
- case 2: // ZSTART
- break;
- case 3: // ZRUN{
- cntr.c_startedNodes.set(nodeId);
-
- Uint32 recv = cntr.c_startedNodes.count();
- Uint32 cnt = cntr.c_clusterNodes.count();
- if(recv + 1 == cnt){ //+1 == own node
- /**
- * Check master
- */
- sendCntrMasterReq(cntr, signal, 0);
- }
- return;
- }
- }
- block.progError(__LINE__,NDBD_EXIT_NDBREQUIRE,
- "UpgradeStartup::execCM_APPCHG");
-}
-
-void
-UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
- Uint32 node = cntr.c_startedNodes.find(n);
- if(node != NdbNodeBitmask::NotFound &&
- (node == cntr.getOwnNodeId() ||
- cntr.getNodeInfo(node).m_version >= MAKE_VERSION(3,5,0))){
- node = cntr.c_startedNodes.find(node+1);
- }
-
- if(node == NdbNodeBitmask::NotFound){
- cntr.progError(__LINE__,NDBD_EXIT_NDBREQUIRE,
- "UpgradeStartup::sendCntrMasterReq "
- "NdbNodeBitmask::NotFound");
- }
-
- CntrMasterReq * const cntrMasterReq = (CntrMasterReq*)&signal->theData[0];
- cntr.c_clusterNodes.copyto(NdbNodeBitmask::Size, cntrMasterReq->theNodes);
- NdbNodeBitmask::clear(cntrMasterReq->theNodes, cntr.getOwnNodeId());
- cntrMasterReq->userBlockRef = 0;
- cntrMasterReq->userNodeId = cntr.getOwnNodeId();
- cntrMasterReq->typeOfStart = NodeState::ST_INITIAL_NODE_RESTART;
- cntrMasterReq->noRestartNodes = cntr.c_clusterNodes.count() - 1;
- cntr.sendSignal(cntr.calcNdbCntrBlockRef(node), GSN_CNTR_MASTERREQ,
- signal, CntrMasterReq::SignalLength, JBB);
-}
-
-void
-UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
- Uint32 gsn = signal->header.theVerId_signalNumber;
- Uint32 node = refToNode(signal->getSendersBlockRef());
- if(block.number() == CNTR){
- Ndbcntr& cntr = (Ndbcntr&)block;
- switch(gsn){
- case GSN_CNTR_MASTERREF:
- sendCntrMasterReq(cntr, signal, node + 1);
- return;
- break;
- case GSN_CNTR_MASTERCONF:{
- CntrStartConf* conf = (CntrStartConf*)signal->getDataPtrSend();
- conf->startGci = 0;
- conf->masterNodeId = node;
- conf->noStartNodes = 1;
- conf->startType = NodeState::ST_INITIAL_NODE_RESTART;
- NodeBitmask mask;
- mask.clear();
- mask.copyto(NdbNodeBitmask::Size, conf->startedNodes);
- mask.clear();
- mask.set(cntr.getOwnNodeId());
- mask.copyto(NdbNodeBitmask::Size, conf->startingNodes);
- cntr.execCNTR_START_CONF(signal);
- return;
- }
- }
- }
- block.progError(__LINE__,NDBD_EXIT_NDBREQUIRE,
- "UpgradeStartup::execCNTR_MASTER_REPLY");
-}
diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrSysTable.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrSysTable.cpp
deleted file mode 100644
index 9b4b12867b7..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrSysTable.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "Ndbcntr.hpp"
-
-#define arrayLength(x) sizeof(x)/sizeof(x[0])
-
-// SYSTAB_0
-
-static const Ndbcntr::SysColumn
-column_SYSTAB_0[] = {
- { 0, "SYSKEY_0",
- DictTabInfo::ExtUnsigned, 1,
- true, false
- },
- { 1, "NEXTID",
- DictTabInfo::ExtBigunsigned, 1,
- false, false
- }
-};
-
-const Ndbcntr::SysTable
-Ndbcntr::g_sysTable_SYSTAB_0 = {
- "sys/def/SYSTAB_0",
- arrayLength(column_SYSTAB_0), column_SYSTAB_0,
- DictTabInfo::SystemTable,
- DictTabInfo::AllNodesSmallTable,
- true, ~0
-};
-
-// NDB$EVENTS_0
-
-static const Ndbcntr::SysColumn
-column_NDBEVENTS_0[] = {
- { 0, "NAME",
- DictTabInfo::ExtBinary, MAX_TAB_NAME_SIZE,
- true, false
- },
- { 1, "EVENT_TYPE",
- DictTabInfo::ExtUnsigned, 1,
- false, false
- },
- { 2, "TABLEID",
- DictTabInfo::ExtUnsigned, 1,
- false, false
- },
- { 3, "TABLEVERSION",
- DictTabInfo::ExtUnsigned, 1,
- false, false
- },
- { 4, "TABLE_NAME",
- DictTabInfo::ExtBinary, MAX_TAB_NAME_SIZE,
- false, false
- },
- { 5, "ATTRIBUTE_MASK",
- DictTabInfo::ExtUnsigned, MAXNROFATTRIBUTESINWORDS,
- false, false
- },
- { 6, "SUBID",
- DictTabInfo::ExtUnsigned, 1,
- false, false
- },
- { 7, "SUBKEY",
- DictTabInfo::ExtUnsigned, 1,
- false, false
- },
-};
-
-const Ndbcntr::SysTable
-Ndbcntr::g_sysTable_NDBEVENTS_0 = {
- "sys/def/NDB$EVENTS_0",
- arrayLength(column_NDBEVENTS_0), column_NDBEVENTS_0,
- DictTabInfo::SystemTable,
- DictTabInfo::AllNodesSmallTable,
- true, ~0
-};
-
-// all
-
-const Ndbcntr::SysTable*
-Ndbcntr::g_sysTableList[] = {
- &g_sysTable_SYSTAB_0,
- &g_sysTable_NDBEVENTS_0
-};
-
-//TODO Backup needs this info to allocate appropriate number of records
-//BackupInit.cpp
-const unsigned
-Ndbcntr::g_sysTableCount = arrayLength(Ndbcntr::g_sysTableList);
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
deleted file mode 100644
index e26e611dd7e..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ /dev/null
@@ -1,1387 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include <my_sys.h>
-#include <my_pthread.h>
-
-#ifdef HAVE_XFS_XFS_H
-#include <xfs/xfs.h>
-#endif
-
-#include "AsyncFile.hpp"
-
-#include <ErrorHandlingMacros.hpp>
-#include <kernel_types.h>
-#include <ndbd_malloc.hpp>
-#include <NdbThread.h>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-
-// use this to test broken pread code
-//#define HAVE_BROKEN_PREAD
-
-#ifdef HAVE_BROKEN_PREAD
-#undef HAVE_PWRITE
-#undef HAVE_PREAD
-#endif
-
-#if defined NDB_WIN32
-#else
-// For readv and writev
-#include <sys/uio.h>
-#endif
-
-#ifndef NDB_WIN32
-#include <dirent.h>
-#endif
-
-// Use this define if you want printouts from AsyncFile class
-//#define DEBUG_ASYNCFILE
-
-#ifdef DEBUG_ASYNCFILE
-#include <NdbOut.hpp>
-#define DEBUG(x) x
-#define PRINT_ERRORANDFLAGS(f) printErrorAndFlags(f)
-void printErrorAndFlags(Uint32 used_flags);
-#else
-#define DEBUG(x)
-#define PRINT_ERRORANDFLAGS(f)
-#endif
-
-// Define the size of the write buffer (for each thread)
-#define WRITEBUFFERSIZE 262144
-
-const char *actionName[] = {
- "open",
- "close",
- "closeRemove",
- "read",
- "readv",
- "write",
- "writev",
- "writeSync",
- "writevSync",
- "sync",
- "end" };
-
-static int numAsyncFiles = 0;
-
-extern "C" void * runAsyncFile(void* arg)
-{
- ((AsyncFile*)arg)->run();
- return (NULL);
-}
-
-AsyncFile::AsyncFile(SimulatedBlock& fs) :
- theFileName(),
-#ifdef NDB_WIN32
- hFile(INVALID_HANDLE_VALUE),
-#else
- theFd(-1),
-#endif
- theReportTo(0),
- theMemoryChannelPtr(NULL),
- m_fs(fs)
-{
- m_page_ptr.setNull();
- m_current_request= m_last_request= 0;
- m_open_flags = 0;
-}
-
-void
-AsyncFile::doStart()
-{
- // Stacksize for filesystem threads
-#if !defined(DBUG_OFF) && defined (__hpux)
- // Empirical evidence indicates at least 32k
- const NDB_THREAD_STACKSIZE stackSize = 32768;
-#else
- // Otherwise an 8k stack should be enough
- const NDB_THREAD_STACKSIZE stackSize = 8192;
-#endif
-
- char buf[16];
- numAsyncFiles++;
- BaseString::snprintf(buf, sizeof(buf), "AsyncFile%d", numAsyncFiles);
-
- theStartMutexPtr = NdbMutex_Create();
- theStartConditionPtr = NdbCondition_Create();
- NdbMutex_Lock(theStartMutexPtr);
- theStartFlag = false;
- theThreadPtr = NdbThread_Create(runAsyncFile,
- (void**)this,
- stackSize,
- (char*)&buf,
- NDB_THREAD_PRIO_MEAN);
- if (theThreadPtr == 0)
- ERROR_SET(fatal, NDBD_EXIT_MEMALLOC, "","Could not allocate file system thread");
-
- NdbCondition_Wait(theStartConditionPtr,
- theStartMutexPtr);
- NdbMutex_Unlock(theStartMutexPtr);
- NdbMutex_Destroy(theStartMutexPtr);
- NdbCondition_Destroy(theStartConditionPtr);
-}
-
-AsyncFile::~AsyncFile()
-{
- void *status;
- Request request;
- request.action = Request::end;
- theMemoryChannelPtr->writeChannel( &request );
- NdbThread_WaitFor(theThreadPtr, &status);
- NdbThread_Destroy(&theThreadPtr);
- delete theMemoryChannelPtr;
-}
-
-void
-AsyncFile::reportTo( MemoryChannel<Request> *reportTo )
-{
- theReportTo = reportTo;
-}
-
-void AsyncFile::execute(Request* request)
-{
- theMemoryChannelPtr->writeChannel( request );
-}
-
-void
-AsyncFile::run()
-{
- Request *request;
- // Create theMemoryChannel in the thread that will wait for it
- NdbMutex_Lock(theStartMutexPtr);
- theMemoryChannelPtr = new MemoryChannel<Request>();
- theStartFlag = true;
- // Create write buffer for bigger writes
- theWriteBufferSize = WRITEBUFFERSIZE;
- theWriteBufferUnaligned = (char *) ndbd_malloc(theWriteBufferSize +
- NDB_O_DIRECT_WRITE_ALIGNMENT-1);
- theWriteBuffer = (char *)
- (((UintPtr)theWriteBufferUnaligned + NDB_O_DIRECT_WRITE_ALIGNMENT - 1) &
- ~(UintPtr)(NDB_O_DIRECT_WRITE_ALIGNMENT - 1));
-
- NdbMutex_Unlock(theStartMutexPtr);
- NdbCondition_Signal(theStartConditionPtr);
-
- if (!theWriteBuffer) {
- DEBUG(ndbout_c("AsyncFile::writeReq, Failed allocating write buffer"));
- return;
- }//if
-
- while (1) {
- request = theMemoryChannelPtr->readChannel();
- if (!request) {
- DEBUG(ndbout_c("Nothing read from Memory Channel in AsyncFile"));
- endReq();
- return;
- }//if
- m_current_request= request;
- switch (request->action) {
- case Request:: open:
- openReq(request);
- break;
- case Request:: close:
- closeReq(request);
- break;
- case Request:: closeRemove:
- closeReq(request);
- removeReq(request);
- break;
- case Request:: readPartial:
- case Request:: read:
- readReq(request);
- break;
- case Request:: readv:
- readvReq(request);
- break;
- case Request:: write:
- writeReq(request);
- break;
- case Request:: writev:
- writevReq(request);
- break;
- case Request:: writeSync:
- writeReq(request);
- syncReq(request);
- break;
- case Request:: writevSync:
- writevReq(request);
- syncReq(request);
- break;
- case Request:: sync:
- syncReq(request);
- break;
- case Request:: append:
- appendReq(request);
- break;
- case Request:: append_synch:
- appendReq(request);
- syncReq(request);
- break;
- case Request::rmrf:
- rmrfReq(request, (char*)theFileName.c_str(), request->par.rmrf.own_directory);
- break;
- case Request:: end:
- if (theFd > 0)
- closeReq(request);
- endReq();
- return;
- default:
- DEBUG(ndbout_c("Invalid Request"));
- abort();
- break;
- }//switch
- m_last_request= request;
- m_current_request= 0;
-
- // No need to signal as ndbfs only uses tryRead
- theReportTo->writeChannelNoSignal(request);
- }//while
-}//AsyncFile::run()
-
-#ifdef O_DIRECT
-static char g_odirect_readbuf[2*GLOBAL_PAGE_SIZE -1];
-#endif
-
-int
-AsyncFile::check_odirect_write(Uint32 flags, int& new_flags, int mode)
-{
- assert(new_flags & (O_CREAT | O_TRUNC));
-#ifdef O_DIRECT
- int ret;
- char * bufptr = (char*)((UintPtr(g_odirect_readbuf)+(GLOBAL_PAGE_SIZE - 1)) & ~(GLOBAL_PAGE_SIZE - 1));
- while (((ret = ::write(theFd, bufptr, GLOBAL_PAGE_SIZE)) == -1) &&
- (errno == EINTR));
- if (ret == -1)
- {
- new_flags &= ~O_DIRECT;
- ndbout_c("%s Failed to write using O_DIRECT, disabling",
- theFileName.c_str());
- }
-
- close(theFd);
- theFd = ::open(theFileName.c_str(), new_flags, mode);
- if (theFd == -1)
- return errno;
-#endif
-
- return 0;
-}
-
-int
-AsyncFile::check_odirect_read(Uint32 flags, int &new_flags, int mode)
-{
-#ifdef O_DIRECT
- int ret;
- char * bufptr = (char*)((UintPtr(g_odirect_readbuf)+(GLOBAL_PAGE_SIZE - 1)) & ~(GLOBAL_PAGE_SIZE - 1));
- while (((ret = ::read(theFd, bufptr, GLOBAL_PAGE_SIZE)) == -1) &&
- (errno == EINTR));
- if (ret == -1)
- {
- ndbout_c("%s Failed to read using O_DIRECT, disabling",
- theFileName.c_str());
- goto reopen;
- }
-
- if(lseek(theFd, 0, SEEK_SET) != 0)
- {
- return errno;
- }
-
- if ((flags & FsOpenReq::OM_CHECK_SIZE) == 0)
- {
- struct stat buf;
- if ((fstat(theFd, &buf) == -1))
- {
- return errno;
- }
- else if ((buf.st_size % GLOBAL_PAGE_SIZE) != 0)
- {
- ndbout_c("%s filesize not a multiple of %d, disabling O_DIRECT",
- theFileName.c_str(), GLOBAL_PAGE_SIZE);
- goto reopen;
- }
- }
-
- return 0;
-
-reopen:
- close(theFd);
- new_flags &= ~O_DIRECT;
- theFd = ::open(theFileName.c_str(), new_flags, mode);
- if (theFd == -1)
- return errno;
-#endif
- return 0;
-}
-
-void AsyncFile::openReq(Request* request)
-{
- m_auto_sync_freq = 0;
- m_write_wo_sync = 0;
- m_open_flags = request->par.open.flags;
-
- // for open.flags, see signal FSOPENREQ
-#ifdef NDB_WIN32
- DWORD dwCreationDisposition;
- DWORD dwDesiredAccess = 0;
- DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
- DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_NO_BUFFERING;
- Uint32 flags = request->par.open.flags;
-
- // Convert file open flags from Solaris to Windows
- if ((flags & FsOpenReq::OM_CREATE) && (flags & FsOpenReq::OM_TRUNCATE)){
- dwCreationDisposition = CREATE_ALWAYS;
- } else if (flags & FsOpenReq::OM_TRUNCATE){
- dwCreationDisposition = TRUNCATE_EXISTING;
- } else if (flags & FsOpenReq::OM_CREATE){
- dwCreationDisposition = CREATE_NEW;
- } else {
- dwCreationDisposition = OPEN_EXISTING;
- }
-
- switch(flags & 3){
- case FsOpenReq::OM_READONLY:
- dwDesiredAccess = GENERIC_READ;
- break;
- case FsOpenReq::OM_WRITEONLY:
- dwDesiredAccess = GENERIC_WRITE;
- break;
- case FsOpenReq::OM_READWRITE:
- dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
- break;
- default:
- request->error = 1000;
- break;
- return;
- }
-
- hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode,
- 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
-
- if(INVALID_HANDLE_VALUE == hFile) {
- request->error = GetLastError();
- if(((ERROR_PATH_NOT_FOUND == request->error) || (ERROR_INVALID_NAME == request->error))
- && (flags & FsOpenReq::OM_CREATE)) {
- createDirectories();
- hFile = CreateFile(theFileName.c_str(), dwDesiredAccess, dwShareMode,
- 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
-
- if(INVALID_HANDLE_VALUE == hFile)
- request->error = GetLastError();
- else
- request->error = 0;
-
- return;
- }
- }
- else {
- request->error = 0;
- return;
- }
-#else
- Uint32 flags = request->par.open.flags;
- int new_flags = 0;
-
- // Convert file open flags from Solaris to Liux
- if (flags & FsOpenReq::OM_CREATE)
- {
- new_flags |= O_CREAT;
- }
-
- if (flags & FsOpenReq::OM_TRUNCATE){
-#if 0
- if(Global_unlinkO_CREAT){
- unlink(theFileName.c_str());
- } else
-#endif
- new_flags |= O_TRUNC;
- }
-
- if (flags & FsOpenReq::OM_AUTOSYNC)
- {
- m_auto_sync_freq = request->par.open.auto_sync_size;
- }
-
- if (flags & FsOpenReq::OM_APPEND){
- new_flags |= O_APPEND;
- }
-
- if (flags & FsOpenReq::OM_DIRECT)
-#ifdef O_DIRECT
- {
- new_flags |= O_DIRECT;
- }
-#endif
-
- if ((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT))
- {
-#ifdef O_SYNC
- new_flags |= O_SYNC;
-#endif
- }
-
- const char * rw = "";
- switch(flags & 0x3){
- case FsOpenReq::OM_READONLY:
- rw = "r";
- new_flags |= O_RDONLY;
- break;
- case FsOpenReq::OM_WRITEONLY:
- rw = "w";
- new_flags |= O_WRONLY;
- break;
- case FsOpenReq::OM_READWRITE:
- rw = "rw";
- new_flags |= O_RDWR;
- break;
- default:
- request->error = 1000;
- break;
- return;
- }
-
- // allow for user to choose any permissionsa with umask
- const int mode = S_IRUSR | S_IWUSR |
- S_IRGRP | S_IWGRP |
- S_IROTH | S_IWOTH;
- if (flags & FsOpenReq::OM_CREATE_IF_NONE)
- {
- Uint32 tmp_flags = new_flags;
-#ifdef O_DIRECT
- tmp_flags &= ~O_DIRECT;
-#endif
- if ((theFd = ::open(theFileName.c_str(), tmp_flags, mode)) != -1)
- {
- close(theFd);
- request->error = FsRef::fsErrFileExists;
- return;
- }
- new_flags |= O_CREAT;
- }
-
-no_odirect:
- if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode)))
- {
- PRINT_ERRORANDFLAGS(new_flags);
- if ((errno == ENOENT) && (new_flags & O_CREAT))
- {
- createDirectories();
- if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode)))
- {
-#ifdef O_DIRECT
- if (new_flags & O_DIRECT)
- {
- new_flags &= ~O_DIRECT;
- goto no_odirect;
- }
-#endif
- PRINT_ERRORANDFLAGS(new_flags);
- request->error = errno;
- return;
- }
- }
-#ifdef O_DIRECT
- else if (new_flags & O_DIRECT)
- {
- new_flags &= ~O_DIRECT;
- goto no_odirect;
- }
-#endif
- else
- {
- request->error = errno;
- return;
- }
- }
-
- if (flags & FsOpenReq::OM_CHECK_SIZE)
- {
- struct stat buf;
- if ((fstat(theFd, &buf) == -1))
- {
- request->error = errno;
- }
- else if((Uint64)buf.st_size != request->par.open.file_size)
- {
- request->error = FsRef::fsErrInvalidFileSize;
- }
- if (request->error)
- return;
- }
-
- if (flags & FsOpenReq::OM_INIT)
- {
- off_t off = 0;
- const off_t sz = request->par.open.file_size;
- Uint32 tmp[sizeof(SignalHeader)+25];
- Signal * signal = (Signal*)(&tmp[0]);
- FsReadWriteReq* req = (FsReadWriteReq*)signal->getDataPtrSend();
-
- Uint32 index = 0;
- Uint32 block = refToBlock(request->theUserReference);
-
-#ifdef HAVE_XFS_XFS_H
- if(platform_test_xfs_fd(theFd))
- {
- ndbout_c("Using xfsctl(XFS_IOC_RESVSP64) to allocate disk space");
- xfs_flock64_t fl;
- fl.l_whence= 0;
- fl.l_start= 0;
- fl.l_len= (off64_t)sz;
- if(xfsctl(NULL, theFd, XFS_IOC_RESVSP64, &fl) < 0)
- ndbout_c("failed to optimally allocate disk space");
- }
-#endif
-#ifdef HAVE_POSIX_FALLOCATE
- posix_fallocate(theFd, 0, sz);
-#endif
-
- while(off < sz)
- {
- req->filePointer = 0; // DATA 0
- req->userPointer = request->theUserPointer; // DATA 2
- req->numberOfPages = 1; // DATA 5
- req->varIndex = index++;
- req->data.pageData[0] = m_page_ptr.i;
-
- m_fs.EXECUTE_DIRECT(block, GSN_FSWRITEREQ, signal,
- FsReadWriteReq::FixedLength + 1);
- retry:
- Uint32 size = request->par.open.page_size;
- char* buf = (char*)m_page_ptr.p;
- while(size > 0){
- const int n = write(theFd, buf, size);
- if(n == -1 && errno == EINTR)
- {
- continue;
- }
- if(n == -1 || n == 0)
- {
- break;
- }
- size -= n;
- buf += n;
- }
- if(size != 0)
- {
- int err = errno;
-#ifdef O_DIRECT
- if ((new_flags & O_DIRECT) && off == 0)
- {
- ndbout_c("error on first write(%d), disable O_DIRECT", err);
- new_flags &= ~O_DIRECT;
- close(theFd);
- theFd = ::open(theFileName.c_str(), new_flags, mode);
- if (theFd != -1)
- goto retry;
- }
-#endif
- close(theFd);
- unlink(theFileName.c_str());
- request->error = err;
- return;
- }
- off += request->par.open.page_size;
- }
- if(lseek(theFd, 0, SEEK_SET) != 0)
- request->error = errno;
- }
- else if (flags & FsOpenReq::OM_DIRECT)
- {
-#ifdef O_DIRECT
- if (flags & (FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE))
- {
- request->error = check_odirect_write(flags, new_flags, mode);
- }
- else
- {
- request->error = check_odirect_read(flags, new_flags, mode);
- }
-
- if (request->error)
- return;
-#endif
- }
-#ifdef VM_TRACE
- if (flags & FsOpenReq::OM_DIRECT)
- {
-#ifdef O_DIRECT
- ndbout_c("%s %s O_DIRECT: %d",
- theFileName.c_str(), rw,
- !!(new_flags & O_DIRECT));
-#else
- ndbout_c("%s %s O_DIRECT: 0",
- theFileName.c_str(), rw);
-#endif
- }
-#endif
- if ((flags & FsOpenReq::OM_SYNC) && (flags & FsOpenReq::OM_INIT))
- {
-#ifdef O_SYNC
- /**
- * reopen file with O_SYNC
- */
- close(theFd);
- new_flags &= ~(O_CREAT | O_TRUNC);
- new_flags |= O_SYNC;
- theFd = ::open(theFileName.c_str(), new_flags, mode);
- if (theFd == -1)
- {
- request->error = errno;
- }
-#endif
- }
-#endif
-}
-
-int
-AsyncFile::readBuffer(Request* req, char * buf, size_t size, off_t offset){
- int return_value;
- req->par.readWrite.pages[0].size = 0;
-#ifdef NDB_WIN32
- DWORD dwSFP = SetFilePointer(hFile, offset, 0, FILE_BEGIN);
- if(dwSFP != offset) {
- return GetLastError();
- }
-#elif ! defined(HAVE_PREAD)
- off_t seek_val;
- while((seek_val= lseek(theFd, offset, SEEK_SET)) == (off_t)-1
- && errno == EINTR);
- if(seek_val == (off_t)-1)
- {
- return errno;
- }
-#endif
-
- while (size > 0) {
- size_t bytes_read = 0;
-
-#ifdef NDB_WIN32
- DWORD dwBytesRead;
- BOOL bRead = ReadFile(hFile,
- buf,
- size,
- &dwBytesRead,
- 0);
- if(!bRead){
- return GetLastError();
- }
- bytes_read = dwBytesRead;
-#elif ! defined(HAVE_PREAD)
- return_value = ::read(theFd, buf, size);
-#else // UNIX
- return_value = ::pread(theFd, buf, size, offset);
-#endif
-#ifndef NDB_WIN32
- if (return_value == -1 && errno == EINTR) {
- DEBUG(ndbout_c("EINTR in read"));
- continue;
- } else if (return_value == -1){
- return errno;
- } else {
- bytes_read = return_value;
- }
-#endif
-
- req->par.readWrite.pages[0].size += bytes_read;
- if(bytes_read == 0){
- if(req->action == Request::readPartial)
- {
- return 0;
- }
- DEBUG(ndbout_c("Read underflow %d %d\n %x\n%d %d",
- size, offset, buf, bytes_read, return_value));
- return ERR_ReadUnderflow;
- }
-
- if(bytes_read != size){
- DEBUG(ndbout_c("Warning partial read %d != %d",
- bytes_read, size));
- }
-
- buf += bytes_read;
- size -= bytes_read;
- offset += bytes_read;
- }
- return 0;
-}
-
-void
-AsyncFile::readReq( Request * request)
-{
- for(int i = 0; i < request->par.readWrite.numberOfPages ; i++) {
- off_t offset = request->par.readWrite.pages[i].offset;
- size_t size = request->par.readWrite.pages[i].size;
- char * buf = request->par.readWrite.pages[i].buf;
-
- int err = readBuffer(request, buf, size, offset);
- if(err != 0){
- request->error = err;
- return;
- }
- }
-}
-
-void
-AsyncFile::readvReq( Request * request)
-{
-#if ! defined(HAVE_PREAD)
- readReq(request);
- return;
-#elif defined NDB_WIN32
- // ReadFileScatter?
- readReq(request);
- return;
-#else
- int return_value;
- int length = 0;
- struct iovec iov[20]; // the parameter in the signal restricts this to 20 deep
- for(int i=0; i < request->par.readWrite.numberOfPages ; i++) {
- iov[i].iov_base= request->par.readWrite.pages[i].buf;
- iov[i].iov_len= request->par.readWrite.pages[i].size;
- length = length + iov[i].iov_len;
- }
- lseek( theFd, request->par.readWrite.pages[0].offset, SEEK_SET );
- return_value = ::readv(theFd, iov, request->par.readWrite.numberOfPages);
- if (return_value == -1) {
- request->error = errno;
- return;
- } else if (return_value != length) {
- request->error = 1011;
- return;
- }
-#endif
-}
-
-int
-AsyncFile::extendfile(Request* request) {
-#if ! defined(HAVE_PWRITE)
- // Find max size of this file in this request
- int maxOffset = 0;
- int maxSize = 0;
- for(int i=0; i < request->par.readWrite.numberOfPages ; i++) {
- if (request->par.readWrite.pages[i].offset > maxOffset) {
- maxOffset = request->par.readWrite.pages[i].offset;
- maxSize = request->par.readWrite.pages[i].size;
- }
- }
- DEBUG(ndbout_c("extendfile: maxOffset=%d, size=%d", maxOffset, maxSize));
-
- // Allocate a buffer and fill it with zeros
- void* pbuf = ndbd_malloc(maxSize);
- memset(pbuf, 0, maxSize);
- for (int p = 0; p <= maxOffset; p = p + maxSize) {
- int return_value;
- return_value = lseek(theFd,
- 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;
- }
- }
- ndbd_free(pbuf,maxSize);
-
- DEBUG(ndbout_c("extendfile: \"%s\" OK!", theFileName.c_str()));
- return 0;
-#else
- request = request;
- DEBUG(ndbout_c("no pwrite"));
- abort();
- return -1;
-#endif
-}
-
-void
-AsyncFile::writeReq( Request * request)
-{
- int page_num = 0;
- bool write_not_complete = true;
-
- while(write_not_complete) {
- int totsize = 0;
- off_t offset = request->par.readWrite.pages[page_num].offset;
- char* bufptr = theWriteBuffer;
-
- write_not_complete = false;
- if (request->par.readWrite.numberOfPages > 1) {
- off_t page_offset = offset;
-
- // Multiple page write, copy to buffer for one write
- for(int i=page_num; i < request->par.readWrite.numberOfPages; i++) {
- memcpy(bufptr,
- request->par.readWrite.pages[i].buf,
- request->par.readWrite.pages[i].size);
- bufptr += request->par.readWrite.pages[i].size;
- totsize += request->par.readWrite.pages[i].size;
- if (((i + 1) < request->par.readWrite.numberOfPages)) {
- // There are more pages to write
- // Check that offsets are consequtive
- off_t tmp = page_offset + request->par.readWrite.pages[i].size;
- if (tmp != request->par.readWrite.pages[i+1].offset) {
- // Next page is not aligned with previous, not allowed
- DEBUG(ndbout_c("Page offsets are not aligned"));
- request->error = EINVAL;
- return;
- }
- if ((unsigned)(totsize + request->par.readWrite.pages[i+1].size) > (unsigned)theWriteBufferSize) {
- // We are not finished and the buffer is full
- write_not_complete = true;
- // Start again with next page
- page_num = i + 1;
- break;
- }
- }
- page_offset += request->par.readWrite.pages[i].size;
- }
- bufptr = theWriteBuffer;
- } else {
- // One page write, write page directly
- bufptr = request->par.readWrite.pages[0].buf;
- totsize = request->par.readWrite.pages[0].size;
- }
- int err = writeBuffer(bufptr, totsize, offset);
- if(err != 0){
- request->error = err;
- return;
- }
- } // while(write_not_complete)
-
- if(m_auto_sync_freq && m_write_wo_sync > m_auto_sync_freq){
- syncReq(request);
- }
-}
-
-int
-AsyncFile::writeBuffer(const char * buf, size_t size, off_t offset,
- size_t chunk_size)
-{
- size_t bytes_to_write = chunk_size;
- int return_value;
-
- m_write_wo_sync += size;
-
-#ifdef NDB_WIN32
- DWORD dwSFP = SetFilePointer(hFile, offset, 0, FILE_BEGIN);
- if(dwSFP != offset) {
- return GetLastError();
- }
-#elif ! defined(HAVE_PWRITE)
- off_t seek_val;
- while((seek_val= lseek(theFd, offset, SEEK_SET)) == (off_t)-1
- && errno == EINTR);
- if(seek_val == (off_t)-1)
- {
- return errno;
- }
-#endif
-
- while (size > 0) {
- if (size < bytes_to_write){
- // We are at the last chunk
- bytes_to_write = size;
- }
- size_t bytes_written = 0;
-
-#ifdef NDB_WIN32
- DWORD dwWritten;
- BOOL bWrite = WriteFile(hFile, buf, bytes_to_write, &dwWritten, 0);
- if(!bWrite) {
- return GetLastError();
- }
- bytes_written = dwWritten;
- if (bytes_written != bytes_to_write) {
- DEBUG(ndbout_c("Warning partial write %d != %d", bytes_written, bytes_to_write));
- }
-
-#elif ! defined(HAVE_PWRITE)
- return_value = ::write(theFd, buf, bytes_to_write);
-#else // UNIX
- return_value = ::pwrite(theFd, buf, bytes_to_write, offset);
-#endif
-#ifndef NDB_WIN32
- if (return_value == -1 && errno == EINTR) {
- bytes_written = 0;
- DEBUG(ndbout_c("EINTR in write"));
- } else if (return_value == -1){
- return errno;
- } else {
- bytes_written = return_value;
-
- if(bytes_written == 0){
- DEBUG(ndbout_c("no bytes written"));
- abort();
- }
-
- if(bytes_written != bytes_to_write){
- DEBUG(ndbout_c("Warning partial write %d != %d",
- bytes_written, bytes_to_write));
- }
- }
-#endif
-
- buf += bytes_written;
- size -= bytes_written;
- offset += bytes_written;
- }
- return 0;
-}
-
-void
-AsyncFile::writevReq( Request * request)
-{
- // WriteFileGather on WIN32?
- writeReq(request);
-}
-
-
-void
-AsyncFile::closeReq(Request * request)
-{
- if (m_open_flags & (
- FsOpenReq::OM_WRITEONLY |
- FsOpenReq::OM_READWRITE |
- FsOpenReq::OM_APPEND )) {
- syncReq(request);
- }
-#ifdef NDB_WIN32
- if(!CloseHandle(hFile)) {
- request->error = GetLastError();
- }
- hFile = INVALID_HANDLE_VALUE;
-#else
- if (-1 == ::close(theFd)) {
-#ifndef DBUG_OFF
- if (theFd == -1) {
- DEBUG(ndbout_c("close on fd = -1"));
- abort();
- }
-#endif
- request->error = errno;
- }
- theFd = -1;
-#endif
-}
-
-bool AsyncFile::isOpen(){
-#ifdef NDB_WIN32
- return (hFile != INVALID_HANDLE_VALUE);
-#else
- return (theFd != -1);
-#endif
-}
-
-
-void
-AsyncFile::syncReq(Request * request)
-{
- if(m_auto_sync_freq && m_write_wo_sync == 0){
- return;
- }
-#ifdef NDB_WIN32
- if(!FlushFileBuffers(hFile)) {
- request->error = GetLastError();
- return;
- }
-#else
- if (-1 == ::fsync(theFd)){
- request->error = errno;
- return;
- }
-#endif
- m_write_wo_sync = 0;
-}
-
-void
-AsyncFile::appendReq(Request * request){
-
- const char * buf = request->par.append.buf;
- Uint32 size = request->par.append.size;
-
- m_write_wo_sync += size;
-
-#ifdef NDB_WIN32
- DWORD dwWritten = 0;
- while(size > 0){
- if(!WriteFile(hFile, buf, size, &dwWritten, 0)){
- request->error = GetLastError();
- return ;
- }
-
- buf += dwWritten;
- size -= dwWritten;
- }
-#else
- while(size > 0){
- const int n = write(theFd, buf, size);
- if(n == -1 && errno == EINTR){
- continue;
- }
- if(n == -1){
- request->error = errno;
- return;
- }
- if(n == 0){
- DEBUG(ndbout_c("append with n=0"));
- abort();
- }
- size -= n;
- buf += n;
- }
-#endif
-
- if(m_auto_sync_freq && m_write_wo_sync > m_auto_sync_freq){
- syncReq(request);
- }
-}
-
-void
-AsyncFile::removeReq(Request * request)
-{
-#ifdef NDB_WIN32
- if(!DeleteFile(theFileName.c_str())) {
- request->error = GetLastError();
- }
-#else
- if (-1 == ::remove(theFileName.c_str())) {
- request->error = errno;
-
- }
-#endif
-}
-
-void
-AsyncFile::rmrfReq(Request * request, char * path, bool removePath){
- Uint32 path_len = strlen(path);
- Uint32 path_max_copy = PATH_MAX - path_len;
- char* path_add = &path[path_len];
-#ifndef NDB_WIN32
- if(!request->par.rmrf.directory){
- // Remove file
- if(unlink((const char *)path) != 0 && errno != ENOENT)
- request->error = errno;
- return;
- }
- // Remove directory
- DIR* dirp = opendir((const char *)path);
- if(dirp == 0){
- if(errno != ENOENT)
- request->error = errno;
- return;
- }
- struct dirent * dp;
- while ((dp = readdir(dirp)) != NULL){
- if ((strcmp(".", dp->d_name) != 0) && (strcmp("..", dp->d_name) != 0)) {
- BaseString::snprintf(path_add, (size_t)path_max_copy, "%s%s",
- DIR_SEPARATOR, dp->d_name);
- if(remove((const char*)path) == 0){
- path[path_len] = 0;
- continue;
- }
-
- rmrfReq(request, path, true);
- path[path_len] = 0;
- if(request->error != 0){
- closedir(dirp);
- return;
- }
- }
- }
- closedir(dirp);
- if(removePath && rmdir((const char *)path) != 0){
- request->error = errno;
- }
- return;
-#else
-
- if(!request->par.rmrf.directory){
- // Remove file
- if(!DeleteFile(path)){
- DWORD dwError = GetLastError();
- if(dwError!=ERROR_FILE_NOT_FOUND)
- request->error = dwError;
- }
- return;
- }
-
- strcat(path, "\\*");
- WIN32_FIND_DATA ffd;
- HANDLE hFindFile = FindFirstFile(path, &ffd);
- path[path_len] = 0;
- if(INVALID_HANDLE_VALUE==hFindFile){
- DWORD dwError = GetLastError();
- if(dwError!=ERROR_PATH_NOT_FOUND)
- request->error = dwError;
- return;
- }
-
- do {
- if(0!=strcmp(".", ffd.cFileName) && 0!=strcmp("..", ffd.cFileName)){
- strcat(path, "\\");
- strcat(path, ffd.cFileName);
- if(DeleteFile(path)) {
- path[path_len] = 0;
- continue;
- }//if
-
- rmrfReq(request, path, true);
- path[path_len] = 0;
- if(request->error != 0){
- FindClose(hFindFile);
- return;
- }
- }
- } while(FindNextFile(hFindFile, &ffd));
-
- FindClose(hFindFile);
-
- if(removePath && !RemoveDirectory(path))
- request->error = GetLastError();
-
-#endif
-}
-
-void AsyncFile::endReq()
-{
- // Thread is ended with return
- if (theWriteBufferUnaligned)
- ndbd_free(theWriteBufferUnaligned, theWriteBufferSize);
-}
-
-
-void AsyncFile::createDirectories()
-{
- char* tmp;
- const char * name = theFileName.c_str();
- const char * base = theFileName.get_base_name();
- while((tmp = (char *)strstr(base, DIR_SEPARATOR)))
- {
- char t = tmp[0];
- tmp[0] = 0;
-#ifdef NDB_WIN32
- CreateDirectory(name, 0);
-#else
- mkdir(name, S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
-#endif
- tmp[0] = t;
- base = tmp + sizeof(DIR_SEPARATOR);
- }
-}
-
-#ifdef DEBUG_ASYNCFILE
-void printErrorAndFlags(Uint32 used_flags) {
- char buf[255];
- sprintf(buf, "PEAF: errno=%d \"", errno);
-
- switch(errno) {
- case EACCES:
- strcat(buf, "EACCES");
- break;
- case EDQUOT:
- strcat(buf, "EDQUOT");
- break;
- case EEXIST :
- strcat(buf, "EEXIST");
- break;
- case EINTR :
- strcat(buf, "EINTR");
- break;
- case EFAULT :
- strcat(buf, "EFAULT");
- break;
- case EIO :
- strcat(buf, "EIO");
- break;
- case EISDIR :
- strcat(buf, "EISDIR");
- break;
- case ELOOP :
- strcat(buf, "ELOOP");
- break;
- case EMFILE :
- strcat(buf, "EMFILE");
- break;
- case ENFILE :
- strcat(buf, "ENFILE");
- break;
- case ENOENT :
- strcat(buf, "ENOENT ");
- break;
- case ENOSPC :
- strcat(buf, "ENOSPC");
- break;
- case ENOTDIR :
- strcat(buf, "ENOTDIR");
- break;
- case ENXIO :
- strcat(buf, "ENXIO");
- break;
- case EOPNOTSUPP:
- strcat(buf, "EOPNOTSUPP");
- break;
- case EMULTIHOP :
- strcat(buf, "EMULTIHOP");
- break;
- case ENOLINK :
- strcat(buf, "ENOLINK");
- break;
- case ENOSR :
- strcat(buf, "ENOSR");
- break;
- case EOVERFLOW :
- strcat(buf, "EOVERFLOW");
- break;
- case EROFS :
- strcat(buf, "EROFS");
- break;
- case EAGAIN :
- strcat(buf, "EAGAIN");
- break;
- case EINVAL :
- strcat(buf, "EINVAL");
- break;
- case ENOMEM :
- strcat(buf, "ENOMEM");
- break;
- case ETXTBSY :
- strcat(buf, "ETXTBSY");
- break;
- case ENAMETOOLONG:
- strcat(buf, "ENAMETOOLONG");
- break;
- case EBADF:
- strcat(buf, "EBADF");
- break;
- case ESPIPE:
- strcat(buf, "ESPIPE");
- break;
- case ESTALE:
- strcat(buf, "ESTALE");
- break;
- default:
- strcat(buf, "EOTHER");
- break;
- }
- strcat(buf, "\" ");
- strcat(buf, " flags: ");
- switch(used_flags & 3){
- case O_RDONLY:
- strcat(buf, "O_RDONLY, ");
- break;
- case O_WRONLY:
- strcat(buf, "O_WRONLY, ");
- break;
- case O_RDWR:
- strcat(buf, "O_RDWR, ");
- break;
- default:
- strcat(buf, "Unknown!!, ");
- }
-
- if((used_flags & O_APPEND)==O_APPEND)
- strcat(buf, "O_APPEND, ");
- if((used_flags & O_CREAT)==O_CREAT)
- strcat(buf, "O_CREAT, ");
- if((used_flags & O_EXCL)==O_EXCL)
- strcat(buf, "O_EXCL, ");
- if((used_flags & O_NOCTTY) == O_NOCTTY)
- strcat(buf, "O_NOCTTY, ");
- if((used_flags & O_NONBLOCK)==O_NONBLOCK)
- strcat(buf, "O_NONBLOCK, ");
- if((used_flags & O_TRUNC)==O_TRUNC)
- strcat(buf, "O_TRUNC, ");
- if((used_flags & O_DSYNC)==O_DSYNC)
- strcat(buf, "O_DSYNC, ");
- if((used_flags & O_NDELAY)==O_NDELAY)
- strcat(buf, "O_NDELAY, ");
- if((used_flags & O_RSYNC)==O_RSYNC)
- strcat(buf, "O_RSYNC, ");
-#ifdef O_SYNC
- if((used_flags & O_SYNC)==O_SYNC)
- strcat(buf, "O_SYNC, ");
-#endif
- DEBUG(ndbout_c(buf));
-
-}
-#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/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
deleted file mode 100644
index 71b6b34e2c0..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef AsyncFile_H
-#define AsyncFile_H
-
-//===========================================================================
-//
-// .DESCRIPTION
-// Asynchronous file, All actions are executed concurrently with other
-// activity of the process.
-// Because all action are performed in a seperated thread the result of
-// of a action is send back tru a memory channel.
-// For the asyncronise notivication of a finished request all the calls
-// have a request as paramater, the user can use the userData pointer
-// to add information it needs when the request is send back.
-//
-//
-// .TYPICAL USE:
-// Writing or reading data to/from disk concurrently to other activities.
-//
-//===========================================================================
-//=============================================================================
-//
-// .PUBLIC
-//
-//=============================================================================
-///////////////////////////////////////////////////////////////////////////////
-//
-// AsyncFile( );
-// Description:
-// Initialisation of the class.
-// Parameters:
-// -
-///////////////////////////////////////////////////////////////////////////////
-//
-// ~AsyncFile( );
-// Description:
-// Tell the thread to stop and wait for it to return
-// Parameters:
-// -
-///////////////////////////////////////////////////////////////////////////////
-//
-// doStart( );
-// Description:
-// Spawns the new thread.
-// Parameters:
-// Base path of filesystem
-//
-///////////////////////////////////////////////////////////////////////////////
-//
-// void execute(Request *request);
-// Description:
-// performens the requered action.
-// Parameters:
-// request: request to be called when open is finished.
-// action= open|close|read|write|sync
-// if action is open then:
-// par.open.flags= UNIX open flags, see man open
-// par.open.name= name of the file to open
-// if action is read or write then:
-// par.readWrite.buf= user provided buffer to read/write
-// the data from/to
-// par.readWrite.size= how many bytes must be read/written
-// par.readWrite.offset= absolute offset in file in bytes
-// return:
-// return values are stored in the request error field:
-// error= return state of the action, UNIX error see man open/errno
-// userData= is untouched can be used be user.
-//
-///////////////////////////////////////////////////////////////////////////////
-//
-// void reportTo( MemoryChannel<Request> *reportTo );
-// Description:
-// set the channel where the file must report the result of the
-// actions back to.
-// Parameters:
-// reportTo: the memory channel to use use MemoryChannelMultipleWriter
-// if more
-// than one file uses this channel to report back.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include <kernel_types.h>
-#include "MemoryChannel.hpp"
-#include "Filename.hpp"
-
-const int ERR_ReadUnderflow = 1000;
-
-const int WRITECHUNK = 262144;
-
-class AsyncFile;
-
-class Request
-{
-public:
- Request() {}
-
- enum Action {
- open,
- close,
- closeRemove,
- read, // Allways leave readv directly after
- // read because SimblockAsyncFileSystem depends on it
- readv,
- write,// Allways leave writev directly after
- // write because SimblockAsyncFileSystem depends on it
- writev,
- writeSync,// Allways leave writevSync directly after
- // writeSync because SimblockAsyncFileSystem depends on it
- writevSync,
- sync,
- end,
- append,
- append_synch,
- rmrf,
- readPartial
- };
- Action action;
- union {
- struct {
- Uint32 flags;
- Uint32 page_size;
- Uint64 file_size;
- Uint32 auto_sync_size;
- } open;
- struct {
- int numberOfPages;
- struct{
- char *buf;
- size_t size;
- off_t offset;
- } pages[16];
- } readWrite;
- struct {
- const char * buf;
- size_t size;
- } append;
- struct {
- bool directory;
- bool own_directory;
- } rmrf;
- } par;
- int error;
-
- void set(BlockReference userReference,
- Uint32 userPointer,
- Uint16 filePointer);
- BlockReference theUserReference;
- Uint32 theUserPointer;
- Uint16 theFilePointer;
- // Information for open, needed if the first open action fails.
- AsyncFile* file;
- Uint32 theTrace;
-};
-
-NdbOut& operator <<(NdbOut&, const Request&);
-
-inline
-void
-Request::set(BlockReference userReference,
- Uint32 userPointer, Uint16 filePointer)
-{
- theUserReference= userReference;
- theUserPointer= userPointer;
- theFilePointer= filePointer;
-}
-
-class AsyncFile
-{
- friend class Ndbfs;
-public:
- AsyncFile(SimulatedBlock& fs);
- ~AsyncFile();
-
- void reportTo( MemoryChannel<Request> *reportTo );
-
- void execute( Request* request );
-
- void doStart();
- // its a thread so its always running
- void run();
-
- bool isOpen();
-
- Filename theFileName;
- Request *m_current_request, *m_last_request;
-private:
-
- void openReq(Request *request);
- void readReq(Request *request);
- void readvReq(Request *request);
- void writeReq(Request *request);
- void writevReq(Request *request);
-
- void closeReq(Request *request);
- void syncReq(Request *request);
- void removeReq(Request *request);
- void appendReq(Request *request);
- void rmrfReq(Request *request, char * path, bool removePath);
- void endReq();
-
- int readBuffer(Request*, char * buf, size_t size, off_t offset);
- int writeBuffer(const char * buf, size_t size, off_t offset,
- size_t chunk_size = WRITECHUNK);
-
- int extendfile(Request* request);
- void createDirectories();
-
-#ifdef NDB_WIN32
- HANDLE hFile;
-#else
- int theFd;
-#endif
-
- Uint32 m_open_flags; // OM_ flags from request to open file
-
- MemoryChannel<Request> *theReportTo;
- MemoryChannel<Request>* theMemoryChannelPtr;
-
- struct NdbThread* theThreadPtr;
- NdbMutex* theStartMutexPtr;
- NdbCondition* theStartConditionPtr;
- bool theStartFlag;
- int theWriteBufferSize;
- char* theWriteBuffer;
- void* theWriteBufferUnaligned;
-
- size_t m_write_wo_sync; // Writes wo/ sync
- size_t m_auto_sync_freq; // Auto sync freq in bytes
-
- int check_odirect_read(Uint32 flags, int&new_flags, int mode);
- int check_odirect_write(Uint32 flags, int&new_flags, int mode);
-public:
- SimulatedBlock& m_fs;
- Ptr<GlobalPage> m_page_ptr;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/AsyncFileTest.cpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/AsyncFileTest.cpp
deleted file mode 100644
index cb7896fb144..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/AsyncFileTest.cpp
+++ /dev/null
@@ -1,695 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-//#define TESTDEBUG 1
-
-#include <ndb_global.h>
-
-#include <kernel_types.h>
-#include <Pool.hpp>
-#include "AsyncFile.hpp"
-#include "NdbOut.hpp"
-#include "NdbTick.h"
-#include "NdbThread.h"
-#include "NdbMain.h"
-
-// Test and benchmark functionality of AsyncFile
-// -n Number of files
-// -r Number of simultaneous requests
-// -s Filesize, number of pages
-// -l Number of iterations
-// -remove, remove files after close
-// -reverse, write files in reverse order, start with the last page
-
-#define MAXFILES 255
-#define DEFAULT_NUM_FILES 1
-#define MAXREQUESTS 256
-#define DEFAULT_NUM_REQUESTS 1
-#define MAXFILESIZE 4096
-#define DEFAULT_FILESIZE 2048
-#define FVERSION 0x01000000
-#define PAGESIZE 8192
-
-#define TIMER_START { Uint64 starttick = NdbTick_CurrentMillisecond()
-#define TIMER_PRINT(str, ops) Uint64 stoptick = NdbTick_CurrentMillisecond();\
- Uint64 totaltime = (stoptick-starttick); \
- ndbout << ops << " " << str << \
- " total time " << (int)totaltime << "ms" << endl;\
- char buf[255];\
- sprintf(buf, "%d %s/sec\n",(int)((ops*1000)/totaltime), str);\
- ndbout <<buf << endl;}
-
-static int numberOfFiles = DEFAULT_NUM_FILES;
-static int numberOfRequests = DEFAULT_NUM_REQUESTS;
-static int fileSize = DEFAULT_FILESIZE;
-static int removeFiles = 0;
-static int writeFilesReverse = 0;
-static int numberOfIterations = 1;
-Uint32 FileNameArray[4];
-
-Pool<AsyncFile>* files;
-AsyncFile* openFiles[MAXFILES];
-Pool<Request>* theRequestPool;
-MemoryChannelMultipleWriter<Request>* theReportChannel;
-
-char WritePages[MAXFILES][PAGESIZE];
-char ReadPages[MAXFILES][PAGESIZE];
-
-int readArguments(int argc, const char** argv);
-int openFile(int fileNum);
-int openFileWait();
-int closeFile(int fileNum);
-int closeFileWait();
-int writeFile( int fileNum, int pagenum);
-int writeFileWait();
-int writeSyncFile( int fileNum, int pagenum);
-int writeSyncFileWait();
-int readFile( int fileNum, int pagenum);
-int readFileWait();
-
-
-NDB_COMMAND(aftest, "aftest", "aftest [-n <Number of files>] [-r <Number of simultaneous requests>] [-s <Filesize, number of pages>] [-l <Number of iterations>] [-remove, remove files after close] [-reverse, write files in reverse order, start with the last page]", "Test the AsyncFile class of Ndb", 8192)
-{
- int s, numReq, numOps;
-
- readArguments(argc, argv);
-
- files = new Pool<AsyncFile>(numberOfFiles, 2);
- theRequestPool = new Pool<Request>;
- theReportChannel = new MemoryChannelMultipleWriter<Request>;
-
- ndbout << "AsyncFileTest starting" << endl;
- ndbout << " " << numberOfFiles << " files" << endl;
- ndbout << " " << numberOfRequests << " requests" << endl;
- ndbout << " " << fileSize << " * 8k files" << endl << endl;
- ndbout << " " << numberOfIterations << " iterations" << endl << endl;
-
- NdbThread_SetConcurrencyLevel(numberOfFiles+2);
-
- // initialize data to write to files
- for (int i = 0; i < MAXFILES; i++) {
- for (int j = 0; j < PAGESIZE; j++){
- WritePages[i][j] = (64+i+j)%256;
- }
- // memset(&WritePages[i][0], i+64, PAGESIZE);
- }
-
- // Set file directory and name
- // /T27/F27/NDBFS/S27Pnn.data
- FileNameArray[0] = 27; // T27
- FileNameArray[1] = 27; // F27
- FileNameArray[2] = 27; // S27
- FileNameArray[3] = FVERSION; // Version
-
- for (int l = 0; l < numberOfIterations; l++)
- {
-
- ndbout << "Opening files" << endl;
- // Open files
- for (int f = 0; f < numberOfFiles; f++)
- {
- openFile(f);
-
- }
-
- // Wait for answer
- openFileWait();
-
- ndbout << "Files opened!" << endl<< endl;
-
- // Write to files
- ndbout << "Started writing" << endl;
- TIMER_START;
- s = 0;
- numReq = 0;
- numOps = 0;
- while ( s < fileSize)
- {
- for (int r = 0; r < numberOfRequests; r++)
- {
- for (int f = 0; f < numberOfFiles; f++)
- {
- writeFile(f, s);
- numReq++;
- numOps++;
- }
-
- s++;
- }
-
- while (numReq > 0)
- {
- writeFileWait();
- numReq--;
- }
-
- }
-
- TIMER_PRINT("writes", numOps);
-
-
- ndbout << "Started reading" << endl;
- TIMER_START;
-
- // Read from files
- s = 0;
- numReq = 0;
- numOps = 0;
- while ( s < fileSize)
- {
- for (int r = 0; r < numberOfRequests; r++)
- {
- for (int f = 0; f < numberOfFiles; f++)
- {
- readFile(f, s);
- numReq++;
- numOps++;
- }
-
- s++;
-
- }
-
- while (numReq > 0)
- {
- readFileWait();
- numReq--;
- }
-
- }
- TIMER_PRINT("reads", numOps);
-
- ndbout << "Started writing with sync" << endl;
- TIMER_START;
-
- // Write to files
- s = 0;
- numReq = 0;
- numOps = 0;
- while ( s < fileSize)
- {
- for (int r = 0; r < numberOfRequests; r++)
- {
- for (int f = 0; f < numberOfFiles; f++)
- {
- writeSyncFile(f, s);
- numReq++;
- numOps++;
- }
-
- s++;
- }
-
- while (numReq > 0)
- {
- writeSyncFileWait();
- numReq--;
- }
-
- }
-
- TIMER_PRINT("writeSync", numOps);
-
- // Close files
- ndbout << "Closing files" << endl;
- for (int f = 0; f < numberOfFiles; f++)
- {
- closeFile(f);
-
- }
-
- // Wait for answer
- closeFileWait();
-
- ndbout << "Files closed!" << endl<< endl;
- }
-
- // Deallocate memory
- delete files;
- delete theReportChannel;
- delete theRequestPool;
-
- return 0;
-
-}
-
-
-
-int forward( AsyncFile * file, Request* request )
-{
- file->execute(request);
- ERROR_CHECK 0;
- return 1;
-}
-
-int openFile( int fileNum)
-{
- AsyncFile* file = (AsyncFile *)files->get();
-
- FileNameArray[3] = fileNum | FVERSION;
- file->fileName().set( NDBFS_REF, &FileNameArray[0] );
- ndbout << "openFile: " << file->fileName().c_str() << endl;
-
- if( ERROR_STATE ) {
- ERROR_RESET;
- files->put( file );
- ndbout << "Failed to set filename" << endl;
- return 1;
- }
- file->reportTo(theReportChannel);
-
- Request* request = theRequestPool->get();
- request->action= Request::open;
- request->error= 0;
- request->par.open.flags = 0x302; //O_RDWR | O_CREAT | O_TRUNC ; // 770
- request->set(NDBFS_REF, 0x23456789, fileNum );
- request->file = file;
-
- if (!forward(file,request)) {
- // Something went wrong
- ndbout << "Could not forward open request" << endl;
- theRequestPool->put(request);
- return 1;
- }
- return 0;
-}
-
-int closeFile( int fileNum)
-{
-
- AsyncFile* file = openFiles[fileNum];
-
- Request* request = theRequestPool->get();
- if (removeFiles == 1)
- request->action = Request::closeRemove;
- else
- request->action= Request::close;
-
- request->error= 0;
- request->set(NDBFS_REF, 0x23456789, fileNum );
- request->file = file;
-
- if (!forward(file,request)) {
- // Something went wrong
- ndbout << "Could not forward close request" << endl;
- theRequestPool->put(request);
- return 1;
- }
- return 0;
-}
-
-int writeFile( int fileNum, int pagenum)
-{
- AsyncFile* file = openFiles[fileNum];
-#ifdef TESTDEBUG
- ndbout << "writeFile" << fileNum <<": "<<pagenum<<", " << file->fileName().c_str()<< endl;
-#endif
- Request *request = theRequestPool->get();
- request->action = Request::write;
- request->error = 0;
- request->set(NDBFS_REF, pagenum, fileNum);
- request->file = openFiles[fileNum];
-
- // Write only one page, choose the correct page for each file using fileNum
- request->par.readWrite.pages[0].buf = &WritePages[fileNum][0];
- request->par.readWrite.pages[0].size = PAGESIZE;
- if (writeFilesReverse == 1)
- {
- // write the last page in the files first
- // This is a normal way for the Blocks in Ndb to write to a file
- request->par.readWrite.pages[0].offset = (fileSize - pagenum - 1) * PAGESIZE;
- }
- else
- {
- request->par.readWrite.pages[0].offset = pagenum * PAGESIZE;
- }
- request->par.readWrite.numberOfPages = 1;
-
- if (!forward(file,request)) {
- // Something went wrong
- ndbout << "Could not forward write request" << endl;
- theRequestPool->put(request);
- return 1;
- }
- return 0;
-
-}
-
-int writeSyncFile( int fileNum, int pagenum)
-{
- AsyncFile* file = openFiles[fileNum];
-#ifdef TESTDEBUG
- ndbout << "writeFile" << fileNum <<": "<<pagenum<<", " << file->fileName().c_str() << endl;
-#endif
- Request *request = theRequestPool->get();
- request->action = Request::writeSync;
- request->error = 0;
- request->set(NDBFS_REF, pagenum, fileNum);
- request->file = openFiles[fileNum];
-
- // Write only one page, choose the correct page for each file using fileNum
- request->par.readWrite.pages[0].buf = &WritePages[fileNum][0];
- request->par.readWrite.pages[0].size = PAGESIZE;
- request->par.readWrite.pages[0].offset = pagenum * PAGESIZE;
- request->par.readWrite.numberOfPages = 1;
-
- if (!forward(file,request)) {
- // Something went wrong
- ndbout << "Could not forward write request" << endl;
- theRequestPool->put(request);
- return 1;
- }
- return 0;
-
-}
-
-int readFile( int fileNum, int pagenum)
-{
- AsyncFile* file = openFiles[fileNum];
-#ifdef TESTDEBUG
- ndbout << "readFile" << fileNum <<": "<<pagenum<<", " << file->fileName().c_str() << endl;
-#endif
- Request *request = theRequestPool->get();
- request->action = Request::read;
- request->error = 0;
- request->set(NDBFS_REF, pagenum, fileNum);
- request->file = openFiles[fileNum];
-
- // Read only one page, choose the correct page for each file using fileNum
- request->par.readWrite.pages[0].buf = &ReadPages[fileNum][0];
- request->par.readWrite.pages[0].size = PAGESIZE;
- request->par.readWrite.pages[0].offset = pagenum * PAGESIZE;
- request->par.readWrite.numberOfPages = 1;
-
- if (!forward(file,request)) {
- // Something went wrong
- ndbout << "Could not forward read request" << endl;
- theRequestPool->put(request);
- return 1;
- }
- return 0;
-
-}
-
-int openFileWait()
-{
- int openedFiles = 0;
- while (openedFiles < numberOfFiles)
- {
- Request* request = theReportChannel->readChannel();
- if (request)
- {
- if (request->action == Request::open)
- {
- if (request->error ==0)
- {
-#ifdef TESTDEBUG
- ndbout << "Opened file " << request->file->fileName().c_str() << endl;
-#endif
- openFiles[request->theFilePointer] = request->file;
- }
- else
- {
- ndbout << "error while opening file" << endl;
- exit(1);
- }
- theRequestPool->put(request);
- openedFiles++;
- }
- else
- {
- ndbout << "Unexpected request received" << endl;
- }
- }
- else
- {
- ndbout << "Nothing read from theReportChannel" << endl;
- }
- }
- return 0;
-}
-
-int closeFileWait()
-{
- int closedFiles = 0;
- while (closedFiles < numberOfFiles)
- {
- Request* request = theReportChannel->readChannel();
- if (request)
- {
- if (request->action == Request::close || request->action == Request::closeRemove)
- {
- if (request->error ==0)
- {
-#ifdef TESTDEBUG
- ndbout << "Closed file " << request->file->fileName().c_str() << endl;
-#endif
- openFiles[request->theFilePointer] = NULL;
- files->put(request->file);
- }
- else
- {
- ndbout << "error while closing file" << endl;
- exit(1);
- }
- theRequestPool->put(request);
- closedFiles++;
- }
- else
- {
- ndbout << "Unexpected request received" << endl;
- }
- }
- else
- {
- ndbout << "Nothing read from theReportChannel" << endl;
- }
- }
- return 0;
-}
-
-int writeFileWait()
-{
- Request* request = theReportChannel->readChannel();
- if (request)
- {
- if (request->action == Request::write)
- {
- if (request->error == 0)
- {
-#ifdef TESTDEBUG
- ndbout << "writeFileWait"<<request->theFilePointer<<", " << request->theUserPointer<<" "<< request->file->fileName().c_str() << endl;
-#endif
-
- }
- else
- {
- ndbout << "error while writing file, error=" << request->error << endl;
- exit(1);
- }
- theRequestPool->put(request);
- }
- else
- {
- ndbout << "Unexpected request received" << endl;
- }
- }
- else
- {
- ndbout << "Nothing read from theReportChannel" << endl;
- }
- return 0;
-}
-
-int writeSyncFileWait()
-{
- Request* request = theReportChannel->readChannel();
- if (request)
- {
- if (request->action == Request::writeSync)
- {
- if (request->error == 0)
- {
-#ifdef TESTDEBUG
- ndbout << "writeFileWait"<<request->theFilePointer<<", " << request->theUserPointer<<" "<< request->file->fileName().c_str() << endl;
-#endif
-
- }
- else
- {
- ndbout << "error while writing file" << endl;
- exit(1);
- }
- theRequestPool->put(request);
- }
- else
- {
- ndbout << "Unexpected request received" << endl;
- }
- }
- else
- {
- ndbout << "Nothing read from theReportChannel" << endl;
- }
- return 0;
-}
-
-int readFileWait()
-{
- Request* request = theReportChannel->readChannel();
- if (request)
- {
- if (request->action == Request::read)
- {
- if (request->error == 0)
- {
-#ifdef TESTDEBUG
- ndbout << "readFileWait"<<request->theFilePointer<<", " << request->theUserPointer<<" "<< request->file->fileName().c_str() << endl;
-#endif
- if (memcmp(&(ReadPages[request->theFilePointer][0]), &(WritePages[request->theFilePointer][0]), PAGESIZE)!=0)
- {
- ndbout <<"Verification error!" << endl;
- for (int i = 0; i < PAGESIZE; i++ ){
- ndbout <<" Compare Page " << i << " : " << ReadPages[request->theFilePointer][i] <<", " <<WritePages[request->theFilePointer][i] << endl;;
- if( ReadPages[request->theFilePointer][i] !=WritePages[request->theFilePointer][i])
-
- exit(1);
- }
- }
-
- }
- else
- {
- ndbout << "error while reading file" << endl;
- exit(1);
- }
- theRequestPool->put(request);
- }
- else
- {
- ndbout << "Unexpected request received" << endl;
- }
- }
- else
- {
- ndbout << "Nothing read from theReportChannel" << endl;
- }
- return 0;
-}
-
-int readArguments(int argc, const char** argv)
-{
-
- int i = 1;
- while (argc > 1)
- {
- if (strcmp(argv[i], "-n") == 0)
- {
- numberOfFiles = atoi(argv[i+1]);
- if ((numberOfFiles < 1) || (numberOfFiles > MAXFILES))
- {
- ndbout << "Wrong number of files, default = "<<DEFAULT_NUM_FILES << endl;
- numberOfFiles = DEFAULT_NUM_FILES;
- }
- }
- else if (strcmp(argv[i], "-r") == 0)
- {
- numberOfRequests = atoi(argv[i+1]);
- if ((numberOfRequests < 1) || (numberOfRequests > MAXREQUESTS))
- {
- ndbout << "Wrong number of requests, default = "<<DEFAULT_NUM_REQUESTS << endl;
- numberOfRequests = DEFAULT_NUM_REQUESTS;
- }
- }
- else if (strcmp(argv[i], "-s") == 0)
- {
- fileSize = atoi(argv[i+1]);
- if ((fileSize < 1) || (fileSize > MAXFILESIZE))
- {
- ndbout << "Wrong number of 8k pages, default = "<<DEFAULT_FILESIZE << endl;
- fileSize = DEFAULT_FILESIZE;
- }
- }
- else if (strcmp(argv[i], "-l") == 0)
- {
- numberOfIterations = atoi(argv[i+1]);
- if ((numberOfIterations < 1))
- {
- ndbout << "Wrong number of iterations, default = 1" << endl;
- numberOfIterations = 1;
- }
- }
- else if (strcmp(argv[i], "-remove") == 0)
- {
- removeFiles = 1;
- argc++;
- i--;
- }
- else if (strcmp(argv[i], "-reverse") == 0)
- {
- ndbout << "Writing files reversed" << endl;
- writeFilesReverse = 1;
- argc++;
- i--;
- }
-
- argc -= 2;
- i = i + 2;
- }
-
- if ((fileSize % numberOfRequests)!= 0)
- {
- numberOfRequests = numberOfRequests - (fileSize % numberOfRequests);
- ndbout <<"numberOfRequest must be modulo of filesize" << endl;
- ndbout << "New numberOfRequest="<<numberOfRequests<<endl;
- }
- return 0;
-}
-
-
-// Needed for linking...
-
-void ErrorReporter::handleError(ErrorCategory type, int messageID,
- const char* problemData, const char* objRef, NdbShutdownType stype)
-{
-
- ndbout << "ErrorReporter::handleError activated" << endl;
- ndbout << "type= " << type << endl;
- ndbout << "messageID= " << messageID << endl;
- ndbout << "problemData= " << problemData << endl;
- ndbout << "objRef= " << objRef << endl;
-
- exit(1);
-}
-
-void ErrorReporter::handleAssert(const char* message, const char* file, int line)
-{
- ndbout << "ErrorReporter::handleAssert activated" << endl;
- ndbout << "message= " << message << endl;
- ndbout << "file= " << file << endl;
- ndbout << "line= " << line << endl;
- exit(1);
-}
-
-
-GlobalData globalData;
-
-
-Signal::Signal()
-{
-
-}
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/Makefile b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/Makefile
deleted file mode 100644
index b0356e6da68..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFileTest/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-BIN_TARGET := aftest
-BIN_TARGET_ARCHIVES := ndbfs portlib trace signaldataprint
-
-SOURCES = AsyncFileTest.cpp
-
-CFLAGS_AsyncFileTest.cpp = -I../
-
-include $(NDB_TOP)/Epilogue.mk
-
-
-# run basic tests
-run_test :
- $(NDB_TOP)/bin/$(BIN_TARGET)
- $(NDB_TOP)/bin/$(BIN_TARGET) -n 8 -r 8 -l 10 -remove
- $(NDB_TOP)/bin/$(BIN_TARGET) -n 8 -r 8 -l 10 -reverse -remove
- $(NDB_TOP)/bin/$(BIN_TARGET) -n 8 -r 8 -l 10 -s 512 -remove
- $(NDB_TOP)/bin/$(BIN_TARGET) -n 8 -r 4 -l 1000
-
-
-
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.cpp b/storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.cpp
deleted file mode 100644
index d0e078a27a7..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "CircularIndex.hpp"
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp b/storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
deleted file mode 100644
index 9f604e64156..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef CircularIndex_H
-#define CircularIndex_H
-
-//===========================================================================
-//
-// .DESCRIPTION
-// Building block for circular buffers. It increment as a normal index.
-// untill it it becomes the maximum size then it becomes zero.
-//
-// .TYPICAL USE:
-// to implement a circular buffer.
-//
-// .EXAMPLE:
-// See MemoryChannel.C
-//===========================================================================
-
-///////////////////////////////////////////////////////////////////////////////
-// CircularIndex( int start= 0,int size=256 );
-// Constuctor
-// Parameters:
-// start: where to start to index
-// size : range of the index, will be from 0 to size-1
-///////////////////////////////////////////////////////////////////////////////
-// operator int ();
-// returns the index
-///////////////////////////////////////////////////////////////////////////////
-// void operator ++ ();
-// increments the index with one, of size is reached it is set to zero
-///////////////////////////////////////////////////////////////////////////////
-// friend int full( const CircularIndex& write, const CircularIndex& read );
-// Taken the write index and the read index from a buffer it is calculated
-// if the buffer is full
-// Parameters:
-// write: index used a write index for the buffer
-// read : index used a read index for the buffer
-// return
-// 0 : not full
-// 1 : full
-///////////////////////////////////////////////////////////////////////////////
-// friend int empty( const CircularIndex& write, const CircularIndex& read );
-// Taken the write index and the read index from a buffer it is calculated
-// if the buffer is empty
-// Parameters:
-// write: index used a write index for the buffer
-// read : index used a read index for the buffer
-// return
-// 0 : not empty
-// 1 : empty
-///////////////////////////////////////////////////////////////////////////////
-
-class CircularIndex
-{
-public:
- inline CircularIndex( int start= 0,int size=256 );
- operator int () const;
- CircularIndex& operator ++ ();
- friend int full( const CircularIndex& write, const CircularIndex& read );
- friend int empty( const CircularIndex& write, const CircularIndex& read );
-private:
- int theSize;
- int theIndex;
-};
-
-inline CircularIndex::operator int () const
-{
- return theIndex;
-}
-
-inline CircularIndex& CircularIndex::operator ++ ()
-{
- ++theIndex;
- if( theIndex >= theSize ){
- theIndex= 0;
- }
- return *this;
-}
-
-
-inline int full( const CircularIndex& write, const CircularIndex& read )
-{
- int readTmp= read.theIndex;
-
- if( read.theIndex < write.theIndex )
- readTmp += read.theSize;
-
- return ( readTmp - write.theIndex) == 1;
-}
-
-inline int empty( const CircularIndex& write, const CircularIndex& read )
-{
- return read.theIndex == write.theIndex;
-}
-
-
-inline CircularIndex::CircularIndex( int start,int size ):
- theSize(size),
- theIndex(start)
-{
-}
-#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp b/storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp
deleted file mode 100644
index 27200ebfbda..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include <NdbOut.hpp>
-
-#include "Filename.hpp"
-#include "ErrorHandlingMacros.hpp"
-#include "RefConvert.hpp"
-#include "DebuggerNames.hpp"
-
-#include <signaldata/FsOpenReq.hpp>
-
-static const char* fileExtension[] = {
- ".Data",
- ".FragLog",
- ".LocLog",
- ".FragList",
- ".TableList",
- ".SchemaLog",
- ".sysfile",
- ".log",
- ".ctl"
-};
-
-static const Uint32 noOfExtensions = sizeof(fileExtension)/sizeof(char*);
-
-Filename::Filename()
-{
-}
-
-Filename::~Filename(){
-}
-
-void
-Filename::set(Filename::NameSpec& spec,
- BlockReference blockReference,
- const Uint32 filenumber[4], bool dir)
-{
- char buf[PATH_MAX];
-
- const Uint32 type = FsOpenReq::getSuffix(filenumber);
- const Uint32 version = FsOpenReq::getVersion(filenumber);
-
- size_t sz;
- if (version == 2)
- {
- sz = BaseString::snprintf(theName, sizeof(theName), "%s",
- spec.backup_path.c_str());
- m_base_name = theName + spec.backup_path.length();
- }
- else
- {
- sz = BaseString::snprintf(theName, sizeof(theName), "%s",
- spec.fs_path.c_str());
- m_base_name = theName + spec.fs_path.length();
- }
-
- switch(version){
- case 1 :{
- const Uint32 diskNo = FsOpenReq::v1_getDisk(filenumber);
- const Uint32 table = FsOpenReq::v1_getTable(filenumber);
- const Uint32 frag = FsOpenReq::v1_getFragment(filenumber);
- const Uint32 S_val = FsOpenReq::v1_getS(filenumber);
- const Uint32 P_val = FsOpenReq::v1_getP(filenumber);
-
- if (diskNo < 0xff){
- BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
- strcat(theName, buf);
- }
-
- {
- const char* blockName = getBlockName( refToBlock(blockReference) );
- if (blockName == NULL){
- ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","No Block Name");
- return;
- }
- BaseString::snprintf(buf, sizeof(buf), "%s%s", blockName, DIR_SEPARATOR);
- strcat(theName, buf);
- }
-
- if (table < 0xffffffff){
- BaseString::snprintf(buf, sizeof(buf), "T%d%s", table, DIR_SEPARATOR);
- strcat(theName, buf);
- }
-
- if (frag < 0xffffffff){
- BaseString::snprintf(buf, sizeof(buf), "F%d%s", frag, DIR_SEPARATOR);
- strcat(theName, buf);
- }
-
-
- if (S_val < 0xffffffff){
- BaseString::snprintf(buf, sizeof(buf), "S%d", S_val);
- strcat(theName, buf);
- }
-
- if (P_val < 0xff){
- BaseString::snprintf(buf, sizeof(buf), "P%d", P_val);
- strcat(theName, buf);
- }
-
- }
- break;
- case 2:{
- const Uint32 seq = FsOpenReq::v2_getSequence(filenumber);
- const Uint32 nodeId = FsOpenReq::v2_getNodeId(filenumber);
- const Uint32 count = FsOpenReq::v2_getCount(filenumber);
-
- BaseString::snprintf(buf, sizeof(buf), "BACKUP%sBACKUP-%d%s",
- DIR_SEPARATOR, seq, DIR_SEPARATOR);
- strcat(theName, buf);
- if(count == 0xffffffff) {
- BaseString::snprintf(buf, sizeof(buf), "BACKUP-%d.%d",
- seq, nodeId); strcat(theName, buf);
- } else {
- BaseString::snprintf(buf, sizeof(buf), "BACKUP-%d-%d.%d",
- seq, count, nodeId); strcat(theName, buf);
- }
- break;
- }
- break;
- case 3:{
- const Uint32 diskNo = FsOpenReq::v1_getDisk(filenumber);
-
- if(diskNo == 0xFF){
- ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Invalid disk specification");
- }
-
- BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
- strcat(theName, buf);
- }
- break;
- case 5:
- {
- Uint32 tableId = FsOpenReq::v5_getTableId(filenumber);
- Uint32 lcpNo = FsOpenReq::v5_getLcpNo(filenumber);
- Uint32 fragId = FsOpenReq::v5_getFragmentId(filenumber);
- BaseString::snprintf(buf, sizeof(buf), "LCP/%d/T%dF%d", lcpNo, tableId, fragId);
- strcat(theName, buf);
- break;
- }
- default:
- ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Wrong version");
- }
- if (type >= noOfExtensions){
- ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","File Type doesn't exist");
- return;
- }
- strcat(theName, fileExtension[type]);
-
- if(dir == true){
- for(int l = strlen(theName) - 1; l >= 0; l--){
- if(theName[l] == DIR_SEPARATOR[0]){
- theName[l] = 0;
- break;
- }
- }
- }
-}
-
-void
-Filename::set(Filename::NameSpec& spec,
- SegmentedSectionPtr ptr, class SectionSegmentPool& pool)
-{
- char buf[PATH_MAX];
- copy((Uint32*)&buf[0], ptr);
- if(buf[0] == DIR_SEPARATOR[0])
- {
- strncpy(theName, buf, PATH_MAX);
- m_base_name = theName;
- }
- else
- {
- snprintf(theName, sizeof(theName), "%s%s", spec.fs_path.c_str(), buf);
- m_base_name = theName + spec.fs_path.length();
- }
-}
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp b/storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp
deleted file mode 100644
index 37c79c3970f..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef Filename_H
-#define Filename_H
-
-//===========================================================================
-//
-// .DESCRIPTION
-// Takes a 128 bits value (done as a array of four longs) and
-// makes a filename out of it acording the following schema
-// Bits 0-31 T
-// Bits 32-63 F
-// Bits 64-95 S
-// Bits 96-103 P
-// Bits 104-111 D
-// Bits 112-119 File Type
-// Bits 120-127 Version number of Filename
-//
-// T, is used to find/create a directory. If T = 0xFFFF then the
-// file is on top level. In that case the F is of no relevance.
-// F, same as T.
-// S, is used to find/create a filename. If S= 0xFFFF then it is ignored.
-// P, same as S
-// D, is used to find/create the root directory, this is the
-// directory before the blockname. If D= 0xFF then it is ignored.
-// File Type
-// 0 => .Data
-// 1 => .FragLog
-// 2 => .LocLog
-// 3 => .FragList
-// 4 => .TableList
-// 5 => .SchemaLog
-// 6 => .sysfile
-// 15=> ignored
-// Version number of Filename, current version is 0x1, must be
-// used for the this style of options.
-//
-//
-//===========================================================================
-
-#include <ndb_global.h>
-#include <kernel_types.h>
-#include <SimulatedBlock.hpp>
-
-class Filename
-{
-public:
- // filenumber is 64 bits but is split in to 4 32bits words
- Filename();
- ~Filename();
-
- struct NameSpec {
- NameSpec(BaseString& f, BaseString&b) :
- fs_path(f), backup_path(b) {}
- BaseString& fs_path;
- BaseString& backup_path;
- };
-
- void set(NameSpec& spec,
- BlockReference, const Uint32 fileno[4], bool = false);
- void set(NameSpec& spec,
- SegmentedSectionPtr ptr, class SectionSegmentPool&);
-
- const char* c_str() const; // Complete name including dirname
- const char* get_base_name() const; // Exclude fs (or backup) path
-private:
- char theName[PATH_MAX];
- char * m_base_name;
-};
-
-// inline methods
-inline const char* Filename::c_str() const {
- return theName;
-}
-
-inline const char* Filename::get_base_name() const {
- return m_base_name;
-}
-
-#endif
-
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.cpp b/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.cpp
deleted file mode 100644
index 4bd5a06debe..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-//#include "MemoryChannel.hpp"
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
deleted file mode 100644
index 279b69703ec..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef MemoryChannel_H
-#define MemoryChannel_H
-
-//===========================================================================
-//
-// .DESCRIPTION
-// Pointer based communication channel for communication between two
-// thread. It does not copy any data in or out the channel so the
-// item that is put in can not be used untill the other thread has
-// given it back. There is no support for detecting the return of a
-// item. The channel is half-duplex.
-// For comminication between 1 writer and 1 reader use the MemoryChannel
-// class, for comminication between multiple writer and 1 reader use the
-// MemoryChannelMultipleWriter. There is no support for multiple readers.
-//
-// .TYPICAL USE:
-// to communicate between threads.
-//
-// .EXAMPLE:
-// See AsyncFile.C
-//===========================================================================
-//
-//
-// MemoryChannel( int size= 256);
-// Constuctor
-// Parameters:
-// size : amount of pointer it can hold
-//
-// void operator ++ ();
-// increments the index with one, if size is reached it is set to zero
-//
-// virtual void write( T *t);
-// Puts the item in the channel if the channel is full an error is reported.
-// Parameters:
-// t: pointer to item to put in the channel, after this the item
-// is shared with the other thread.
-// errors
-// AFS_ERROR_CHANNALFULL, channel is full
-//
-// T* read();
-// Reads a itemn from the channel, if channel is empty it blocks untill
-// an item can be read.
-// return
-// T : item from the channel
-//
-// T* tryRead();
-// Reads a item from the channel, if channel is empty it returns zero.
-// return
-// T : item from the channel or zero if channel is empty.
-//
-
-#include "ErrorHandlingMacros.hpp"
-#include "CircularIndex.hpp"
-#include "NdbMutex.h"
-#include "NdbCondition.h"
-#include <NdbOut.hpp>
-
-
-template <class T>
-class MemoryChannel
-{
-public:
- MemoryChannel( int size= 512);
- virtual ~MemoryChannel( );
-
- void writeChannel( T *t);
- void writeChannelNoSignal( T *t);
- T* readChannel();
- T* tryReadChannel();
-
-private:
- int theSize;
- T **theChannel;
- CircularIndex theWriteIndex;
- CircularIndex theReadIndex;
- 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),
- theChannel(new T*[size] ),
- theWriteIndex(0, size),
- theReadIndex(0, size)
-{
- theMutexPtr = NdbMutex_Create();
- theConditionPtr = NdbCondition_Create();
-}
-
-template <class T> MemoryChannel<T>::~MemoryChannel( )
-{
- NdbMutex_Destroy(theMutexPtr);
- NdbCondition_Destroy(theConditionPtr);
- delete [] theChannel;
-}
-
-template <class T> void MemoryChannel<T>::writeChannel( T *t)
-{
-
- NdbMutex_Lock(theMutexPtr);
- if(full(theWriteIndex, theReadIndex) || theChannel == NULL) abort();
- theChannel[theWriteIndex]= t;
- ++theWriteIndex;
- NdbMutex_Unlock(theMutexPtr);
- NdbCondition_Signal(theConditionPtr);
-}
-
-template <class T> void MemoryChannel<T>::writeChannelNoSignal( T *t)
-{
-
- NdbMutex_Lock(theMutexPtr);
- if(full(theWriteIndex, theReadIndex) || theChannel == NULL) abort();
- theChannel[theWriteIndex]= t;
- ++theWriteIndex;
- NdbMutex_Unlock(theMutexPtr);
-}
-
-template <class T> T* MemoryChannel<T>::readChannel()
-{
- T* tmp;
-
- NdbMutex_Lock(theMutexPtr);
- while ( empty(theWriteIndex, theReadIndex) )
- {
- NdbCondition_Wait(theConditionPtr,
- theMutexPtr);
- }
-
- tmp= theChannel[theReadIndex];
- ++theReadIndex;
- NdbMutex_Unlock(theMutexPtr);
- return tmp;
-}
-
-template <class T> T* MemoryChannel<T>::tryReadChannel()
-{
- T* tmp= 0;
- NdbMutex_Lock(theMutexPtr);
- if ( !empty(theWriteIndex, theReadIndex) )
- {
- tmp= theChannel[theReadIndex];
- ++theReadIndex;
- }
- NdbMutex_Unlock(theMutexPtr);
- return tmp;
-}
-
-#endif // MemoryChannel_H
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/Makefile b/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/Makefile
deleted file mode 100644
index 68f71bfc4cd..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-BIN_TARGET := mctest
-BIN_TARGET_ARCHIVES := portlib
-
-SOURCES = MemoryChannelTest.cpp
-
-CFLAGS_MemoryChannelTest.cpp = -I../
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/MemoryChannelTest.cpp b/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/MemoryChannelTest.cpp
deleted file mode 100644
index 26707969975..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/MemoryChannelTest.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "MemoryChannel.hpp"
-#include "NdbThread.h"
-#include "NdbSleep.h"
-#include "NdbOut.hpp"
-#include "NdbMain.h"
-
-
-
-MemoryChannel<int>* theMemoryChannel;
-
-
-extern "C" void* runProducer(void*arg)
-{
- // The producer will items into the MemoryChannel
- int count = *(int*)arg;
- int* p;
- int i = 0;
- while (i <= count)
- {
- p = new int(i);
- ndbout << "P: " << *p << endl;
- theMemoryChannel->writeChannel(p);
- if (i%5==0)
- NdbSleep_MilliSleep(i);
- i++;
- }
- return NULL;
-}
-
-extern "C" void* runConsumer(void* arg)
-{
- // The producer will read items from MemoryChannel and print on screen
- int count = *(int*)arg;
- int* p;
- int i = 0;
- while (i < count)
- {
- p = theMemoryChannel->readChannel();
- ndbout << "C: " << *p << endl;
- i = *p;
- delete p;
-
- }
- return NULL;
-}
-
-
-
-class ArgStruct
-{
-public:
- ArgStruct(int _items, int _no){
- items=_items;
- no=_no;
- };
- int items;
- int no;
-};
-
-MemoryChannelMultipleWriter<ArgStruct>* theMemoryChannel2;
-
-extern "C" void* runProducer2(void*arg)
-{
- // The producer will items into the MemoryChannel
- ArgStruct* pArg = (ArgStruct*)arg;
- int count = pArg->items;
- ArgStruct* p;
- int i = 0;
- while (i < count)
- {
- p = new ArgStruct(i, pArg->no);
- ndbout << "P"<<pArg->no<<": " << i << endl;
- theMemoryChannel2->writeChannel(p);
- NdbSleep_MilliSleep(i);
- i++;
- }
- return NULL;
-}
-
-extern "C" void* runConsumer2(void* arg)
-{
- // The producer will read items from MemoryChannel and print on screen
- ArgStruct* pArg = (ArgStruct*)arg;
- int count = pArg->items * pArg->no;
- ArgStruct* p;
- int i = 0;
- while (i < count)
- {
- p = theMemoryChannel2->readChannel();
- ndbout << "C: "<< p->no << ", " << p->items << endl;
- i++;
- delete p;
- }
- ndbout << "Consumer2: " << count << " received" << endl;
- return NULL;
-}
-
-
-
-
-//#if defined MEMORYCHANNELTEST
-
-//int main(int argc, char **argv)
-NDB_COMMAND(mctest, "mctest", "mctest", "Test the memory channel used in Ndb", 32768)
-{
-
- ndbout << "==== testing MemoryChannel ====" << endl;
-
- theMemoryChannel = new MemoryChannel<int>;
- theMemoryChannel2 = new MemoryChannelMultipleWriter<ArgStruct>;
-
- NdbThread* consumerThread;
- NdbThread* producerThread;
-
- NdbThread_SetConcurrencyLevel(2);
-
- int numItems = 100;
- producerThread = NdbThread_Create(runProducer,
- (void**)&numItems,
- 4096,
- (char*)"producer");
-
- consumerThread = NdbThread_Create(runConsumer,
- (void**)&numItems,
- 4096,
- (char*)"consumer");
-
-
- void *status;
- NdbThread_WaitFor(consumerThread, &status);
- NdbThread_WaitFor(producerThread, &status);
-
- ndbout << "==== testing MemoryChannelMultipleWriter ====" << endl;
-#define NUM_THREADS2 5
- NdbThread_SetConcurrencyLevel(NUM_THREADS2+2);
- NdbThread* producerThreads[NUM_THREADS2];
-
- ArgStruct *pArg;
- for (int j = 0; j < NUM_THREADS2; j++)
- {
- char buf[25];
- sprintf((char*)&buf, "producer%d", j);
- pArg = new ArgStruct(numItems, j);
- producerThreads[j] = NdbThread_Create(runProducer2,
- (void**)pArg,
- 4096,
- (char*)&buf);
- }
-
- pArg = new ArgStruct(numItems, NUM_THREADS2);
- consumerThread = NdbThread_Create(runConsumer2,
- (void**)pArg,
- 4096,
- (char*)"consumer");
-
-
- NdbThread_WaitFor(consumerThread, &status);
- for (int j = 0; j < NUM_THREADS2; j++)
- {
- NdbThread_WaitFor(producerThreads[j], &status);
- }
-
-
- return 0;
-
-}
-
-void ErrorReporter::handleError(ErrorCategory type, int messageID,
- const char* problemData, const char* objRef,
- NdbShutdownType nst)
-{
-
- ndbout << "ErrorReporter::handleError activated" << endl;
- exit(1);
-}
-
-//#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
deleted file mode 100644
index 779d44d4176..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
+++ /dev/null
@@ -1,1109 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include "Ndbfs.hpp"
-#include "AsyncFile.hpp"
-#include "Filename.hpp"
-
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsCloseReq.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-#include <signaldata/FsAppendReq.hpp>
-#include <signaldata/FsRemoveReq.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/NdbfsContinueB.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-
-#include <RefConvert.hpp>
-#include <NdbSleep.h>
-#include <NdbOut.hpp>
-#include <Configuration.hpp>
-
-#define DEBUG(x) { ndbout << "FS::" << x << endl; }
-
-inline
-int pageSize( const NewVARIABLE* baseAddrRef )
-{
- int log_psize;
- int log_qsize = baseAddrRef->bits.q;
- int log_vsize = baseAddrRef->bits.v;
- if (log_vsize < 3)
- log_vsize = 3;
- log_psize = log_qsize + log_vsize - 3;
- return (1 << log_psize);
-}
-
-
-Ndbfs::Ndbfs(Block_context& ctx) :
- SimulatedBlock(NDBFS, ctx),
- scanningInProgress(false),
- theLastId(0),
- theRequestPool(0),
- m_maxOpenedFiles(0)
-{
- 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);
- addRecSignal(GSN_FSCLOSEREQ, &Ndbfs::execFSCLOSEREQ);
- addRecSignal(GSN_FSWRITEREQ, &Ndbfs::execFSWRITEREQ);
- addRecSignal(GSN_FSREADREQ, &Ndbfs::execFSREADREQ);
- addRecSignal(GSN_FSSYNCREQ, &Ndbfs::execFSSYNCREQ);
- addRecSignal(GSN_CONTINUEB, &Ndbfs::execCONTINUEB);
- addRecSignal(GSN_FSAPPENDREQ, &Ndbfs::execFSAPPENDREQ);
- addRecSignal(GSN_FSREMOVEREQ, &Ndbfs::execFSREMOVEREQ);
- // Set send signals
-}
-
-Ndbfs::~Ndbfs()
-{
- // Delete all files
- // AsyncFile destuctor will take care of deleting
- // the thread it has created
- for (unsigned i = 0; i < theFiles.size(); i++){
- AsyncFile* file = theFiles[i];
- delete file;
- theFiles[i] = NULL;
- }//for
- theFiles.clear();
- 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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
- theFileSystemPath.assfmt("%sndb_%u_fs%s", m_ctx.m_config.fileSystemPath(),
- getOwnNodeId(), DIR_SEPARATOR);
- theBackupFilePath.assign(m_ctx.m_config.backupFilePath());
-
- theRequestPool = new Pool<Request>;
-
- m_maxFiles = 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_MAX_OPEN_FILES, &m_maxFiles);
- Uint32 noIdleFiles = 27;
- ndb_mgm_get_int_parameter(p, CFG_DB_INITIAL_OPEN_FILES, &noIdleFiles);
- if (noIdleFiles > m_maxFiles && m_maxFiles != 0)
- m_maxFiles = noIdleFiles;
- // Create idle AsyncFiles
- 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.
- * Answer it like any other block
- * PR0 : StartCase
- * DR0 : StartPhase
- * DR1 : ?
- * DR2 : ?
- * DR3 : ?
- * DR4 : ?
- * DR5 : SignalKey
- */
-void
-Ndbfs::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- if(signal->theData[1] == 0){ // StartPhase 0
- jam();
-
- {
-#ifdef NDB_WIN32
- CreateDirectory(theFileSystemPath.c_str(), 0);
-#else
- mkdir(theFileSystemPath.c_str(),
- S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
-#endif
- }
-
- cownref = NDBFS_REF;
- // close all open files
- ndbrequire(theOpenFiles.size() == 0);
-
- scanningInProgress = false;
-
- signal->theData[0] = NdbfsContinueB::ZSCAN_MEMORYCHANNEL_10MS_DELAY;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 1);
-
- signal->theData[3] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal,4, JBB);
- return;
- }
- ndbrequire(0);
-}
-
-int
-Ndbfs::forward( AsyncFile * file, Request* request)
-{
- jam();
- file->execute(request);
- return 1;
-}
-
-void
-Ndbfs::execFSOPENREQ(Signal* signal)
-{
- jamEntry();
- const FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
- const BlockReference userRef = fsOpenReq->userReference;
- AsyncFile* file = getIdleFile();
- ndbrequire(file != NULL);
- Filename::NameSpec spec(theFileSystemPath, theBackupFilePath);
-
- Uint32 userPointer = fsOpenReq->userPointer;
-
- if(fsOpenReq->fileFlags & FsOpenReq::OM_INIT)
- {
- Ptr<GlobalPage> page_ptr;
- if(m_global_page_pool.seize(page_ptr) == false)
- {
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = userPointer;
- fsRef->setErrorCode(fsRef->errorCode, FsRef::fsErrOutOfMemory);
- fsRef->osErrorCode = ~0; // Indicate local error
- sendSignal(userRef, GSN_FSOPENREF, signal, 3, JBB);
- return;
- }
- file->m_page_ptr = page_ptr;
- }
- else
- {
- ndbassert(file->m_page_ptr.isNull());
- file->m_page_ptr.setNull();
- }
-
- if(signal->getNoOfSections() == 0){
- jam();
- file->theFileName.set(spec, userRef, fsOpenReq->fileNumber);
- } else {
- jam();
- SegmentedSectionPtr ptr;
- signal->getSection(ptr, FsOpenReq::FILENAME);
- file->theFileName.set(spec, ptr, g_sectionSegmentPool);
- releaseSections(signal);
- }
- file->reportTo(&theFromThreads);
- if (getenv("NDB_TRACE_OPEN"))
- ndbout_c("open(%s)", file->theFileName.c_str());
-
- Request* request = theRequestPool->get();
- request->action = Request::open;
- request->error = 0;
- request->set(userRef, userPointer, newId() );
- request->file = file;
- request->theTrace = signal->getTrace();
- request->par.open.flags = fsOpenReq->fileFlags;
- request->par.open.page_size = fsOpenReq->page_size;
- request->par.open.file_size = fsOpenReq->file_size_hi;
- request->par.open.file_size <<= 32;
- request->par.open.file_size |= fsOpenReq->file_size_lo;
- request->par.open.auto_sync_size = fsOpenReq->auto_sync_size;
-
- ndbrequire(forward(file, request));
-}
-
-void
-Ndbfs::execFSREMOVEREQ(Signal* signal)
-{
- jamEntry();
- const FsRemoveReq * const req = (FsRemoveReq *)signal->getDataPtr();
- const BlockReference userRef = req->userReference;
- AsyncFile* file = getIdleFile();
- ndbrequire(file != NULL);
-
- Filename::NameSpec spec(theFileSystemPath, theBackupFilePath);
- file->theFileName.set(spec, userRef, req->fileNumber, req->directory);
- file->reportTo(&theFromThreads);
-
- Request* request = theRequestPool->get();
- request->action = Request::rmrf;
- request->par.rmrf.directory = req->directory;
- request->par.rmrf.own_directory = req->ownDirectory;
- request->error = 0;
- request->set(userRef, req->userPointer, newId() );
- request->file = file;
- request->theTrace = signal->getTrace();
-
- ndbrequire(forward(file, request));
-}
-
-/*
- * PR0: File Pointer DR0: User reference DR1: User Pointer DR2: Flag bit 0= 1
- * remove file
- */
-void
-Ndbfs::execFSCLOSEREQ(Signal * signal)
-{
- jamEntry();
- const FsCloseReq * const fsCloseReq = (FsCloseReq *)&signal->theData[0];
- const BlockReference userRef = fsCloseReq->userReference;
- const Uint16 filePointer = (Uint16)fsCloseReq->filePointer;
- const UintR userPointer = fsCloseReq->userPointer;
-
- AsyncFile* openFile = theOpenFiles.find(filePointer);
- if (openFile == NULL) {
- // The file was not open, send error back to sender
- jam();
- // Initialise FsRef signal
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = userPointer;
- fsRef->setErrorCode(fsRef->errorCode, FsRef::fsErrFileDoesNotExist);
- fsRef->osErrorCode = ~0; // Indicate local error
- sendSignal(userRef, GSN_FSCLOSEREF, signal, 3, JBB);
- return;
- }
-
- Request *request = theRequestPool->get();
- if( fsCloseReq->getRemoveFileFlag(fsCloseReq->fileFlag) == true ) {
- jam();
- request->action = Request::closeRemove;
- } else {
- jam();
- request->action = Request::close;
- }
- request->set(userRef, fsCloseReq->userPointer, filePointer);
- request->file = openFile;
- request->error = 0;
- request->theTrace = signal->getTrace();
-
- ndbrequire(forward(openFile, request));
-}
-
-void
-Ndbfs::readWriteRequest(int action, Signal * signal)
-{
- const FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
- Uint16 filePointer = (Uint16)fsRWReq->filePointer;
- const UintR userPointer = fsRWReq->userPointer;
- const BlockReference userRef = fsRWReq->userReference;
- const BlockNumber blockNumber = refToBlock(userRef);
-
- AsyncFile* openFile = theOpenFiles.find(filePointer);
-
- const NewVARIABLE *myBaseAddrRef = &getBat(blockNumber)[fsRWReq->varIndex];
- UintPtr tPageSize;
- UintPtr tClusterSize;
- UintPtr tNRR;
- UintPtr tPageOffset;
- char* tWA;
- FsRef::NdbfsErrorCodeType errorCode;
-
- Request *request = theRequestPool->get();
- request->error = 0;
- request->set(userRef, userPointer, filePointer);
- request->file = openFile;
- request->action = (Request::Action) action;
- request->theTrace = signal->getTrace();
-
- Uint32 format = fsRWReq->getFormatFlag(fsRWReq->operationFlag);
-
- if (fsRWReq->numberOfPages == 0) { //Zero pages not allowed
- jam();
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }
-
- if(format != FsReadWriteReq::fsFormatGlobalPage &&
- format != FsReadWriteReq::fsFormatSharedPage)
- {
- if (fsRWReq->varIndex >= getBatSize(blockNumber)) {
- jam();// Ensure that a valid variable is used
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }
- if (myBaseAddrRef == NULL) {
- jam(); // Ensure that a valid variable is used
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }
- if (openFile == NULL) {
- jam(); //file not open
- errorCode = FsRef::fsErrFileDoesNotExist;
- goto error;
- }
- tPageSize = pageSize(myBaseAddrRef);
- tClusterSize = myBaseAddrRef->ClusterSize;
- tNRR = myBaseAddrRef->nrr;
- tWA = (char*)myBaseAddrRef->WA;
-
- switch (format) {
-
- // List of memory and file pages pairs
- case FsReadWriteReq::fsFormatListOfPairs: {
- jam();
- for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) {
- jam();
- const UintPtr varIndex = fsRWReq->data.listOfPair[i].varIndex;
- const UintPtr fileOffset = fsRWReq->data.listOfPair[i].fileOffset;
- if (varIndex >= tNRR) {
- jam();
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }//if
- request->par.readWrite.pages[i].buf = &tWA[varIndex * tClusterSize];
- request->par.readWrite.pages[i].size = tPageSize;
- request->par.readWrite.pages[i].offset = fileOffset * tPageSize;
- }//for
- request->par.readWrite.numberOfPages = fsRWReq->numberOfPages;
- break;
- }//case
-
- // Range of memory page with one file page
- case FsReadWriteReq::fsFormatArrayOfPages: {
- if ((fsRWReq->numberOfPages + fsRWReq->data.arrayOfPages.varIndex) > tNRR) {
- jam();
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }//if
- const UintPtr varIndex = fsRWReq->data.arrayOfPages.varIndex;
- const UintPtr fileOffset = fsRWReq->data.arrayOfPages.fileOffset;
-
- request->par.readWrite.pages[0].offset = fileOffset * tPageSize;
- request->par.readWrite.pages[0].size = tPageSize * fsRWReq->numberOfPages;
- request->par.readWrite.numberOfPages = 1;
- request->par.readWrite.pages[0].buf = &tWA[varIndex * tPageSize];
- break;
- }//case
-
- // List of memory pages followed by one file page
- case FsReadWriteReq::fsFormatListOfMemPages: {
-
- tPageOffset = fsRWReq->data.listOfMemPages.varIndex[fsRWReq->numberOfPages];
- tPageOffset *= tPageSize;
-
- for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) {
- jam();
- UintPtr varIndex = fsRWReq->data.listOfMemPages.varIndex[i];
-
- if (varIndex >= tNRR) {
- jam();
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }//if
- request->par.readWrite.pages[i].buf = &tWA[varIndex * tClusterSize];
- request->par.readWrite.pages[i].size = tPageSize;
- request->par.readWrite.pages[i].offset = tPageOffset + (i*tPageSize);
- }//for
- request->par.readWrite.numberOfPages = fsRWReq->numberOfPages;
- break;
- // make it a writev or readv
- }//case
-
- default: {
- jam();
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }//default
- }//switch
- }
- else if (format == FsReadWriteReq::fsFormatGlobalPage)
- {
- Ptr<GlobalPage> ptr;
- m_global_page_pool.getPtr(ptr, fsRWReq->data.pageData[0]);
- request->par.readWrite.pages[0].buf = (char*)ptr.p;
- request->par.readWrite.pages[0].size = ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->numberOfPages;
- request->par.readWrite.pages[0].offset= ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->varIndex;
- request->par.readWrite.numberOfPages = 1;
- }
- else
- {
- ndbrequire(format == FsReadWriteReq::fsFormatSharedPage);
- Ptr<GlobalPage> ptr;
- m_shared_page_pool.getPtr(ptr, fsRWReq->data.pageData[0]);
- request->par.readWrite.pages[0].buf = (char*)ptr.p;
- request->par.readWrite.pages[0].size = ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->numberOfPages;
- request->par.readWrite.pages[0].offset= ((UintPtr)GLOBAL_PAGE_SIZE)*fsRWReq->varIndex;
- request->par.readWrite.numberOfPages = 1;
- }
-
- ndbrequire(forward(openFile, request));
- return;
-
-error:
- theRequestPool->put(request);
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = userPointer;
- fsRef->setErrorCode(fsRef->errorCode, errorCode);
- fsRef->osErrorCode = ~0; // Indicate local error
- switch (action) {
- case Request:: write:
- case Request:: writeSync: {
- jam();
- sendSignal(userRef, GSN_FSWRITEREF, signal, 3, JBB);
- break;
- }//case
- case Request:: readPartial:
- case Request:: read: {
- jam();
- sendSignal(userRef, GSN_FSREADREF, signal, 3, JBB);
- }//case
- }//switch
- return;
-}
-
-/*
- PR0: File Pointer , theData[0]
- DR0: User reference, theData[1]
- DR1: User Pointer, etc.
- DR2: Flag
- DR3: Var number
- DR4: amount of pages
- DR5->: Memory Page id and File page id according to Flag
-*/
-void
-Ndbfs::execFSWRITEREQ(Signal* signal)
-{
- jamEntry();
- const FsReadWriteReq * const fsWriteReq = (FsReadWriteReq *)&signal->theData[0];
-
- if (fsWriteReq->getSyncFlag(fsWriteReq->operationFlag) == true){
- jam();
- readWriteRequest( Request::writeSync, signal );
- } else {
- jam();
- readWriteRequest( Request::write, signal );
- }
-}
-
-/*
- PR0: File Pointer
- DR0: User reference
- DR1: User Pointer
- DR2: Flag
- DR3: Var number
- DR4: amount of pages
- DR5->: Memory Page id and File page id according to Flag
-*/
-void
-Ndbfs::execFSREADREQ(Signal* signal)
-{
- jamEntry();
- FsReadWriteReq * req = (FsReadWriteReq *)signal->getDataPtr();
- if (FsReadWriteReq::getPartialReadFlag(req->operationFlag))
- readWriteRequest( Request::readPartial, signal );
- else
- readWriteRequest( Request::read, signal );
-}
-
-/*
- * PR0: File Pointer DR0: User reference DR1: User Pointer
- */
-void
-Ndbfs::execFSSYNCREQ(Signal * signal)
-{
- jamEntry();
- Uint16 filePointer = (Uint16)signal->theData[0];
- BlockReference userRef = signal->theData[1];
- const UintR userPointer = signal->theData[2];
- AsyncFile* openFile = theOpenFiles.find(filePointer);
-
- if (openFile == NULL) {
- jam(); //file not open
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = userPointer;
- fsRef->setErrorCode(fsRef->errorCode, FsRef::fsErrFileDoesNotExist);
- fsRef->osErrorCode = ~0; // Indicate local error
- sendSignal(userRef, GSN_FSSYNCREF, signal, 3, JBB);
- return;
- }
-
- Request *request = theRequestPool->get();
- request->error = 0;
- request->action = Request::sync;
- request->set(userRef, userPointer, filePointer);
- request->file = openFile;
- request->theTrace = signal->getTrace();
-
- ndbrequire(forward(openFile,request));
-}
-
-void
-Ndbfs::execFSAPPENDREQ(Signal * signal)
-{
- const FsAppendReq * const fsReq = (FsAppendReq *)&signal->theData[0];
- const Uint16 filePointer = (Uint16)fsReq->filePointer;
- const UintR userPointer = fsReq->userPointer;
- const BlockReference userRef = fsReq->userReference;
- const BlockNumber blockNumber = refToBlock(userRef);
-
- FsRef::NdbfsErrorCodeType errorCode;
-
- AsyncFile* openFile = theOpenFiles.find(filePointer);
- const NewVARIABLE *myBaseAddrRef = &getBat(blockNumber)[fsReq->varIndex];
-
- const Uint32* tWA = (const Uint32*)myBaseAddrRef->WA;
- const Uint32 tSz = myBaseAddrRef->nrr;
- const Uint32 offset = fsReq->offset;
- const Uint32 size = fsReq->size;
- const Uint32 synch_flag = fsReq->synch_flag;
- Request *request = theRequestPool->get();
-
- if (openFile == NULL) {
- jam();
- errorCode = FsRef::fsErrFileDoesNotExist;
- goto error;
- }
-
- if (myBaseAddrRef == NULL) {
- jam(); // Ensure that a valid variable is used
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }
-
- if (fsReq->varIndex >= getBatSize(blockNumber)) {
- jam();// Ensure that a valid variable is used
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }
-
- if(offset + size > tSz){
- jam(); // Ensure that a valid variable is used
- errorCode = FsRef::fsErrInvalidParameters;
- goto error;
- }
-
- request->error = 0;
- request->set(userRef, userPointer, filePointer);
- request->file = openFile;
- request->theTrace = signal->getTrace();
-
- request->par.append.buf = (const char *)(tWA + offset);
- request->par.append.size = size << 2;
-
- if (!synch_flag)
- request->action = Request::append;
- else
- request->action = Request::append_synch;
- ndbrequire(forward(openFile, request));
- return;
-
-error:
- jam();
- theRequestPool->put(request);
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = userPointer;
- fsRef->setErrorCode(fsRef->errorCode, errorCode);
- fsRef->osErrorCode = ~0; // Indicate local error
-
- jam();
- sendSignal(userRef, GSN_FSAPPENDREF, signal, 3, JBB);
- return;
-}
-
-Uint16
-Ndbfs::newId()
-{
- // finds a new key, eg a new filepointer
- for (int i = 1; i < SHRT_MAX; i++)
- {
- if (theLastId == SHRT_MAX) {
- jam();
- theLastId = 1;
- } else {
- jam();
- theLastId++;
- }
-
- if(theOpenFiles.find(theLastId) == NULL) {
- jam();
- return theLastId;
- }
- }
- ndbrequire(1 == 0);
- // The program will not reach this point
- return 0;
-}
-
-AsyncFile*
-Ndbfs::createAsyncFile(){
-
- // Check limit of open files
- if (m_maxFiles !=0 && theFiles.size() == m_maxFiles) {
- // Print info about all open files
- for (unsigned i = 0; i < theFiles.size(); i++){
- AsyncFile* file = theFiles[i];
- ndbout_c("%2d (0x%lx): %s", i, (long) file, file->isOpen()?"OPEN":"CLOSED");
- }
- ERROR_SET(fatal, NDBD_EXIT_AFS_MAXOPEN,""," Ndbfs::createAsyncFile");
- }
-
- AsyncFile* file = new AsyncFile(* this);
- file->doStart();
-
- // Put the file in list of all files
- theFiles.push_back(file);
-
-#ifdef VM_TRACE
- infoEvent("NDBFS: Created new file thread %d", theFiles.size());
-#endif
-
- return file;
-}
-
-AsyncFile*
-Ndbfs::getIdleFile(){
- AsyncFile* file;
- if (theIdleFiles.size() > 0){
- file = theIdleFiles[0];
- theIdleFiles.erase(0);
- } else {
- file = createAsyncFile();
- }
- return file;
-}
-
-
-
-void
-Ndbfs::report(Request * request, Signal* signal)
-{
- const Uint32 orgTrace = signal->getTrace();
- signal->setTrace(request->theTrace);
- const BlockReference ref = request->theUserReference;
-
- if(!request->file->m_page_ptr.isNull())
- {
- m_global_page_pool.release(request->file->m_page_ptr);
- request->file->m_page_ptr.setNull();
- }
-
- if (request->error) {
- jam();
- // Initialise FsRef signal
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = request->theUserPointer;
- if(request->error & FsRef::FS_ERR_BIT)
- {
- fsRef->errorCode = request->error;
- fsRef->osErrorCode = 0;
- }
- else
- {
- fsRef->setErrorCode(fsRef->errorCode, translateErrno(request->error));
- fsRef->osErrorCode = request->error;
- }
- switch (request->action) {
- case Request:: open: {
- jam();
- // Put the file back in idle files list
- theIdleFiles.push_back(request->file);
- sendSignal(ref, GSN_FSOPENREF, signal, FsRef::SignalLength, JBB);
- break;
- }
- case Request:: closeRemove:
- case Request:: close: {
- jam();
- sendSignal(ref, GSN_FSCLOSEREF, signal, FsRef::SignalLength, JBB);
- break;
- }
- case Request:: writeSync:
- case Request:: writevSync:
- case Request:: write:
- case Request:: writev: {
- jam();
- sendSignal(ref, GSN_FSWRITEREF, signal, FsRef::SignalLength, JBB);
- break;
- }
- case Request:: read:
- case Request:: readPartial:
- case Request:: readv: {
- jam();
- sendSignal(ref, GSN_FSREADREF, signal, FsRef::SignalLength, JBB);
- break;
- }
- case Request:: sync: {
- jam();
- sendSignal(ref, GSN_FSSYNCREF, signal, FsRef::SignalLength, JBB);
- break;
- }
- case Request::append:
- case Request::append_synch:
- {
- jam();
- sendSignal(ref, GSN_FSAPPENDREF, signal, FsRef::SignalLength, JBB);
- break;
- }
- case Request::rmrf: {
- jam();
- // Put the file back in idle files list
- theIdleFiles.push_back(request->file);
- sendSignal(ref, GSN_FSREMOVEREF, signal, FsRef::SignalLength, JBB);
- break;
- }
-
- case Request:: end: {
- // Report nothing
- break;
- }
- }//switch
- } else {
- jam();
- FsConf * const fsConf = (FsConf *)&signal->theData[0];
- fsConf->userPointer = request->theUserPointer;
- switch (request->action) {
- case Request:: open: {
- jam();
- theOpenFiles.insert(request->file, request->theFilePointer);
-
- // Keep track on max number of opened files
- if (theOpenFiles.size() > m_maxOpenedFiles)
- m_maxOpenedFiles = theOpenFiles.size();
-
- fsConf->filePointer = request->theFilePointer;
- sendSignal(ref, GSN_FSOPENCONF, signal, 3, JBB);
- break;
- }
- case Request:: closeRemove:
- case Request:: close: {
- jam();
- // removes the file from OpenFiles list
- theOpenFiles.erase(request->theFilePointer);
- // Put the file in idle files list
- theIdleFiles.push_back(request->file);
- sendSignal(ref, GSN_FSCLOSECONF, signal, 1, JBB);
- break;
- }
- case Request:: writeSync:
- case Request:: writevSync:
- case Request:: write:
- case Request:: writev: {
- jam();
- sendSignal(ref, GSN_FSWRITECONF, signal, 1, JBB);
- break;
- }
- case Request:: read:
- case Request:: readv: {
- jam();
- sendSignal(ref, GSN_FSREADCONF, signal, 1, JBB);
- break;
- }
- case Request:: readPartial: {
- jam();
- fsConf->bytes_read = request->par.readWrite.pages[0].size;
- sendSignal(ref, GSN_FSREADCONF, signal, 2, JBB);
- break;
- }
- case Request:: sync: {
- jam();
- sendSignal(ref, GSN_FSSYNCCONF, signal, 1, JBB);
- break;
- }//case
- case Request::append:
- case Request::append_synch:
- {
- jam();
- signal->theData[1] = request->par.append.size;
- sendSignal(ref, GSN_FSAPPENDCONF, signal, 2, JBB);
- break;
- }
- case Request::rmrf: {
- jam();
- // Put the file in idle files list
- theIdleFiles.push_back(request->file);
- sendSignal(ref, GSN_FSREMOVECONF, signal, 1, JBB);
- break;
- }
- case Request:: end: {
- // Report nothing
- break;
- }
- }
- }//if
- signal->setTrace(orgTrace);
-}
-
-
-bool
-Ndbfs::scanIPC(Signal* signal)
-{
- Request* request = theFromThreads.tryReadChannel();
- jam();
- if (request) {
- jam();
- report(request, signal);
- theRequestPool->put(request);
- return true;
- }
- return false;
-}
-
-#if defined NDB_WIN32
-Uint32 Ndbfs::translateErrno(int aErrno)
-{
- switch (aErrno)
- {
- //permission denied
- case ERROR_ACCESS_DENIED:
-
- return FsRef::fsErrPermissionDenied;
- //temporary not accessible
- case ERROR_PATH_BUSY:
- case ERROR_NO_MORE_SEARCH_HANDLES:
-
- return FsRef::fsErrTemporaryNotAccessible;
- //no space left on device
- case ERROR_HANDLE_DISK_FULL:
- case ERROR_DISK_FULL:
-
- return FsRef::fsErrNoSpaceLeftOnDevice;
- //none valid parameters
- case ERROR_INVALID_HANDLE:
- case ERROR_INVALID_DRIVE:
- case ERROR_INVALID_ACCESS:
- case ERROR_HANDLE_EOF:
- case ERROR_BUFFER_OVERFLOW:
-
- return FsRef::fsErrInvalidParameters;
- //environment error
- case ERROR_CRC:
- case ERROR_ARENA_TRASHED:
- case ERROR_BAD_ENVIRONMENT:
- case ERROR_INVALID_BLOCK:
- case ERROR_WRITE_FAULT:
- case ERROR_READ_FAULT:
- case ERROR_OPEN_FAILED:
-
- return FsRef::fsErrEnvironmentError;
-
- //no more process resources
- case ERROR_TOO_MANY_OPEN_FILES:
- case ERROR_NOT_ENOUGH_MEMORY:
- case ERROR_OUTOFMEMORY:
- return FsRef::fsErrNoMoreResources;
- //no file
- case ERROR_FILE_NOT_FOUND:
- return FsRef::fsErrFileDoesNotExist;
-
- case ERR_ReadUnderflow:
- return FsRef::fsErrReadUnderflow;
-
- default:
- return FsRef::fsErrUnknown;
- }
-}
-#else
-Uint32 Ndbfs::translateErrno(int aErrno)
-{
- switch (aErrno)
- {
- //permission denied
- case EACCES:
- case EROFS:
- case ENXIO:
- return FsRef::fsErrPermissionDenied;
- //temporary not accessible
- case EAGAIN:
- case ETIMEDOUT:
- case ENOLCK:
- case EINTR:
- case EIO:
- return FsRef::fsErrTemporaryNotAccessible;
- //no space left on device
- case ENFILE:
- case EDQUOT:
-#ifdef ENOSR
- case ENOSR:
-#endif
- case ENOSPC:
- case EFBIG:
- return FsRef::fsErrNoSpaceLeftOnDevice;
- //none valid parameters
- case EINVAL:
- case EBADF:
- case ENAMETOOLONG:
- case EFAULT:
- case EISDIR:
- case ENOTDIR:
- case EEXIST:
- case ETXTBSY:
- return FsRef::fsErrInvalidParameters;
- //environment error
- case ELOOP:
-#ifdef ENOLINK
- case ENOLINK:
-#endif
-#ifdef EMULTIHOP
- case EMULTIHOP:
-#endif
-#ifdef EOPNOTSUPP
- case EOPNOTSUPP:
-#endif
-#ifdef ESPIPE
- case ESPIPE:
-#endif
- case EPIPE:
- return FsRef::fsErrEnvironmentError;
-
- //no more process resources
- case EMFILE:
- case ENOMEM:
- return FsRef::fsErrNoMoreResources;
- //no file
- case ENOENT:
- return FsRef::fsErrFileDoesNotExist;
-
- case ERR_ReadUnderflow:
- return FsRef::fsErrReadUnderflow;
-
- default:
- return FsRef::fsErrUnknown;
- }
-}
-#endif
-
-
-
-void
-Ndbfs::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- if (signal->theData[0] == NdbfsContinueB::ZSCAN_MEMORYCHANNEL_10MS_DELAY) {
- jam();
-
- // Also send CONTINUEB to ourself in order to scan for
- // incoming answers from AsyncFile on MemoryChannel theFromThreads
- signal->theData[0] = NdbfsContinueB::ZSCAN_MEMORYCHANNEL_10MS_DELAY;
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 10, 1);
- if (scanningInProgress == true) {
- jam();
- return;
- }
- }
- if (scanIPC(signal)) {
- jam();
- scanningInProgress = true;
- signal->theData[0] = NdbfsContinueB::ZSCAN_MEMORYCHANNEL_NO_DELAY;
- sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
- } else {
- jam();
- scanningInProgress = false;
- }
- return;
-}
-
-void
-Ndbfs::execDUMP_STATE_ORD(Signal* signal)
-{
- if(signal->theData[0] == 19){
- return;
- }
- if(signal->theData[0] == DumpStateOrd::NdbfsDumpFileStat){
- infoEvent("NDBFS: Files: %d Open files: %d",
- theFiles.size(),
- theOpenFiles.size());
- infoEvent(" Idle files: %d Max opened files: %d",
- theIdleFiles.size(),
- m_maxOpenedFiles);
- infoEvent(" Max files: %d",
- m_maxFiles);
- infoEvent(" Requests: %d",
- theRequestPool->size());
-
- return;
- }
- if(signal->theData[0] == DumpStateOrd::NdbfsDumpOpenFiles){
- infoEvent("NDBFS: Dump open files: %d", theOpenFiles.size());
-
- for (unsigned i = 0; i < theOpenFiles.size(); i++){
- AsyncFile* file = theOpenFiles.getFile(i);
- infoEvent("%2d (0x%x): %s", i,file, file->theFileName.c_str());
- }
- return;
- }
- if(signal->theData[0] == DumpStateOrd::NdbfsDumpAllFiles){
- infoEvent("NDBFS: Dump all files: %d", theFiles.size());
-
- for (unsigned i = 0; i < theFiles.size(); i++){
- AsyncFile* file = theFiles[i];
- infoEvent("%2d (0x%x): %s", i,file, file->isOpen()?"OPEN":"CLOSED");
- }
- return;
- }
- if(signal->theData[0] == DumpStateOrd::NdbfsDumpIdleFiles){
- infoEvent("NDBFS: Dump idle files: %d", theIdleFiles.size());
-
- for (unsigned i = 0; i < theIdleFiles.size(); i++){
- AsyncFile* file = theIdleFiles[i];
- infoEvent("%2d (0x%x): %s", i,file, file->isOpen()?"OPEN":"CLOSED");
- }
- return;
- }
-
- if(signal->theData[0] == 404)
- {
- ndbrequire(signal->getLength() == 2);
- Uint32 file= signal->theData[1];
- AsyncFile* openFile = theOpenFiles.find(file);
- ndbrequire(openFile != 0);
- 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%lx): %s", i, (long) file, file->isOpen()?"OPEN":"CLOSED");
- }
- }
-}//Ndbfs::execDUMP_STATE_ORD()
-
-const char*
-Ndbfs::get_filename(Uint32 fd) const
-{
- jamEntry();
- const AsyncFile* openFile = theOpenFiles.find(fd);
- if(openFile)
- return openFile->theFileName.get_base_name();
- return "";
-}
-
-
-BLOCK_FUNCTIONS(Ndbfs)
-
-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/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
deleted file mode 100644
index df39890af49..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SIMBLOCKASYNCFILESYSTEM_H
-#define SIMBLOCKASYNCFILESYSTEM_H
-
-#include <pc.hpp>
-#include <SimulatedBlock.hpp>
-#include "Pool.hpp"
-#include "AsyncFile.hpp"
-#include "OpenFiles.hpp"
-
-
-
-// Because one NDB Signal request can result in multiple requests to
-// AsyncFile one class must be made responsible to keep track
-// of all out standing request and when all are finished the result
-// must be reported to the sending block.
-
-
-class Ndbfs : public SimulatedBlock
-{
-public:
- Ndbfs(Block_context&);
- virtual ~Ndbfs();
-
- virtual const char* get_filename(Uint32 fd) const;
-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);
- void execFSWRITEREQ(Signal* signal);
- void execFSREADREQ(Signal* signal);
- void execFSSYNCREQ(Signal* signal);
- void execFSAPPENDREQ(Signal* signal);
- void execFSREMOVEREQ(Signal* signal);
- void execSTTOR(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- bool scanningInProgress;
- Uint16 newId();
-
-private:
- int forward(AsyncFile *file, Request* Request);
- void report(Request* request, Signal* signal);
- bool scanIPC(Signal* signal);
-
- // Declared but not defined
- Ndbfs(Ndbfs & );
- void operator = (Ndbfs &);
-
- // Used for uniqe number generation
- Uint16 theLastId;
- BlockReference cownref;
-
- // Communication from files
- MemoryChannel<Request> theFromThreads;
-
- Pool<Request>* theRequestPool;
-
- AsyncFile* createAsyncFile();
- AsyncFile* getIdleFile();
-
- Vector<AsyncFile*> theFiles; // List all created AsyncFiles
- Vector<AsyncFile*> theIdleFiles; // List of idle AsyncFiles
- OpenFiles theOpenFiles; // List of open AsyncFiles
-
- BaseString theFileSystemPath;
- BaseString theBackupFilePath;
-
- // Statistics variables
- Uint32 m_maxOpenedFiles;
-
- // Limit for max number of AsyncFiles created
- Uint32 m_maxFiles;
-
- void readWriteRequest( int action, Signal * signal );
-
- static Uint32 translateErrno(int aErrno);
-};
-
-class VoidFs : public SimulatedBlock
-{
-public:
- VoidFs(Block_context&);
- virtual ~VoidFs();
-
-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);
- void execFSWRITEREQ(Signal* signal);
- void execFSREADREQ(Signal* signal);
- void execFSSYNCREQ(Signal* signal);
- void execFSAPPENDREQ(Signal* signal);
- void execFSREMOVEREQ(Signal* signal);
- void execSTTOR(Signal* signal);
-
-private:
- // Declared but not defined
- VoidFs(VoidFs & );
- void operator = (VoidFs &);
-
- // Used for uniqe number generation
- Uint32 c_maxFileNo;
-};
-
-#endif
-
-
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp b/storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
deleted file mode 100644
index ed1e99a1409..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef OPENFILES_H
-#define OPENFILES_H
-
-#include <Vector.hpp>
-
-class OpenFiles
-{
-public:
- OpenFiles(){ }
-
- /* Get a pointer to the file with id */
- AsyncFile* find(Uint16 id) const;
- /* Insert file with id */
- bool insert(AsyncFile* file, Uint16 id);
- /* Erase file with id */
- bool erase(Uint16 id);
- /* Get number of open files */
- unsigned size();
-
- Uint16 getId(unsigned i);
- AsyncFile* getFile(unsigned i);
-
-
-private:
-
- class OpenFileItem {
- public:
- OpenFileItem(): m_file(NULL), m_id(0){};
-
- AsyncFile* m_file;
- Uint16 m_id;
- };
-
- Vector<OpenFileItem> m_files;
-};
-
-
-//*****************************************************************************
-inline AsyncFile* OpenFiles::find(Uint16 id) const {
- for (unsigned i = 0; i < m_files.size(); i++){
- if (m_files[i].m_id == id){
- return m_files[i].m_file;
- }
- }
- return NULL;
-}
-
-//*****************************************************************************
-inline bool OpenFiles::erase(Uint16 id){
- for (unsigned i = 0; i < m_files.size(); i++){
- if (m_files[i].m_id == id){
- m_files.erase(i);
- return true;
- }
- }
- // Item was not found in list
- return false;
-}
-
-
-//*****************************************************************************
-inline bool OpenFiles::insert(AsyncFile* file, Uint16 id){
- // Check if file has already been opened
- for (unsigned i = 0; i < m_files.size(); i++){
- if(m_files[i].m_file == NULL)
- continue;
-
- if(strcmp(m_files[i].m_file->theFileName.c_str(),
- file->theFileName.c_str()) == 0)
- {
- BaseString names;
- names.assfmt("open: >%s< existing: >%s<",
- file->theFileName.c_str(),
- m_files[i].m_file->theFileName.c_str());
- ERROR_SET(fatal, NDBD_EXIT_AFS_ALREADY_OPEN, names.c_str(),
- "OpenFiles::insert()");
- }
- }
-
- // Insert the file into vector
- OpenFileItem openFile;
- openFile.m_id = id;
- openFile.m_file = file;
- m_files.push_back(openFile);
-
- return true;
-}
-
-//*****************************************************************************
-inline Uint16 OpenFiles::getId(unsigned i){
- return m_files[i].m_id;
-}
-
-//*****************************************************************************
-inline AsyncFile* OpenFiles::getFile(unsigned i){
- return m_files[i].m_file;
-}
-
-//*****************************************************************************
-inline unsigned OpenFiles::size(){
- return m_files.size();
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp b/storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp
deleted file mode 100644
index e78167d2350..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/Pool.hpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef FOR_LIB_POOL_H
-#define FOR_LIB_POOL_H
-
-
-//===========================================================================
-//
-// .PUBLIC
-//
-//===========================================================================
-
-////////////////////////////////////////////////////////////////
-//
-// enum { defInitSize = 256, defIncSize = 64 };
-// Description: type to store initial and incremental size in.
-//
-////////////////////////////////////////////////////////////////
-//
-// Pool(int anInitSize = defInitSize, int anIncSize = defIncSize);
-// Description:
-// Constructor. Allocates anInitSize of objects <template argument>.
-// When the pool runs out of elements, anIncSize elements are added to the
-// pool. (When the pool is not optimized to allocate multiple elements
-// more efficient, the anIncSize MUST be set to 1 to get the best
-// performance...
-//
-// Parameters:
-// defInitSize: Initial size of the pool (# of elements in the pool)
-// defIncSize: # of elements added to the pool when a request to an empty
-// pool is made.
-// Return value:
-// _
-// Errors:
-// -
-// Asserts:
-// _
-//
-////////////////////////////////////////////////////////////////
-//
-// virtual ~Pool();
-// Description:
-// Elements in the pool are all deallocated.
-// Parameters:
-// _
-// Return value:
-// _
-// Errors:
-// -
-// Asserts:
-// theEmptyNodeList==0. No elements are in still in use.
-//
-////////////////////////////////////////////////////////////////
-//
-// T& get();
-// Description:
-// get's an element from the Pool.
-// Parameters:
-// _
-// Return value:
-// T& the element extracted from the Pool. (element must be cleared to
-// mimick newly created element)
-// Errors:
-// -
-// Asserts:
-// _
-//
-////////////////////////////////////////////////////////////////
-//
-// void put(T& aT);
-// Description:
-// Returns an element to the pool.
-// Parameters:
-// aT The element to put back in the pool
-// Return value:
-// void
-// Errors:
-// -
-// Asserts:
-// The pool has "empty" elements, to put element back in...
-//
-//===========================================================================
-//
-// .PRIVATE
-//
-//===========================================================================
-
-////////////////////////////////////////////////////////////////
-//
-// void allocate(int aSize);
-// Description:
-// add aSize elements to the pool
-// Parameters:
-// aSize: # of elements to add to the pool
-// Return value:
-// void
-// Errors:
-// -
-// Asserts:
-// _
-//
-////////////////////////////////////////////////////////////////
-//
-// void deallocate();
-// Description:
-// frees all elements kept in the pool.
-// Parameters:
-// _
-// Return value:
-// void
-// Errors:
-// -
-// Asserts:
-// No elements are "empty" i.e. in use.
-//
-//===========================================================================
-//
-// .PRIVATE
-//
-//===========================================================================
-
-////////////////////////////////////////////////////////////////
-//
-// Pool<T>& operator=(const Pool<T>& cp);
-// Description:
-// Prohibit use of assignement operator.
-// Parameters:
-// cp
-// Return value:
-// Pool<T>&
-// Asserts:
-// _
-//
-////////////////////////////////////////////////////////////////
-//
-// Pool(const Pool<T>& cp);
-// Description:
-// Prohibit use of default copy constructor.
-// Parameters:
-// cp
-// Return value:
-// _
-// Errors:
-// -
-// Asserts:
-// _
-//
-////////////////////////////////////////////////////////////////
-//
-// int initSize;
-// Description: size of the initial size of the pool
-//
-////////////////////////////////////////////////////////////////
-//
-// int incSize;
-// Description: # of elements added to the pool when pool is exhausted.
-//
-////////////////////////////////////////////////////////////////
-//
-// PoolElement<T>* theFullNodeList;
-// Description: List to contain all "unused" elements in the pool
-//
-////////////////////////////////////////////////////////////////
-//
-// PoolElement<T>* theEmptyNodeList;
-// Description: List to contain all "in use" elements in the pool
-//
-//-------------------------------------------------------------------------
-
-template <class T>
-class Pool
-{
-public:
- enum { defInitSize = 256, defIncSize = 64 };
-
- Pool(int anInitSize = defInitSize, int anIncSize = defIncSize) :
- theIncSize(anIncSize),
- theTop(0),
- theCurrentSize(0),
- theList(0)
- {
- allocate(anInitSize);
- }
-
- virtual ~Pool(void)
- {
- for (int i=0; i <theTop ; ++i)
- delete theList[i];
-
- delete []theList;
- }
-
- T* get();
- void put(T* aT);
-
- unsigned size(){ return theTop; };
-
-protected:
- void allocate(int aSize)
- {
- T** tList = theList;
- int i;
- theList = new T*[aSize+theCurrentSize];
- // allocate full list
- for (i = 0; i < theTop; i++) {
- theList[i] = tList[i];
- }
- delete []tList;
- for (; (theTop < aSize); theTop++){
- theList[theTop] = (T*)new T;
- }
- theCurrentSize += aSize;
- }
-
-private:
- Pool<T>& operator=(const Pool<T>& cp);
- Pool(const Pool<T>& cp);
-
- int theIncSize;
- int theTop;
- int theCurrentSize;
-
- T** theList;
-};
-
-//******************************************************************************
-template <class T> inline T* Pool<T>::get()
-{
- T* tmp;
- if( theTop == 0 )
- {
- allocate(theIncSize);
- }
- --theTop;
- tmp = theList[theTop];
- return tmp;
-}
-
-//
-//******************************************************************************
-template <class T> inline void Pool<T>::put(T* aT)
-{
- theList[theTop]= aT;
- ++theTop;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp b/storage/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp
deleted file mode 100644
index f2bf41b64b6..00000000000
--- a/storage/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <limits.h>
-#include <errno.h>
-
-#include "Ndbfs.hpp"
-#include "AsyncFile.hpp"
-#include "Filename.hpp"
-
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsCloseReq.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-#include <signaldata/FsAppendReq.hpp>
-#include <signaldata/FsRemoveReq.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRef.hpp>
-#include <signaldata/NdbfsContinueB.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-
-#include <RefConvert.hpp>
-#include <NdbSleep.h>
-#include <NdbOut.hpp>
-#include <Configuration.hpp>
-
-#define DEBUG(x) { ndbout << "FS::" << x << endl; }
-
-VoidFs::VoidFs(Block_context & ctx) :
- SimulatedBlock(NDBFS, ctx)
-{
- 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);
- addRecSignal(GSN_FSCLOSEREQ, &VoidFs::execFSCLOSEREQ);
- addRecSignal(GSN_FSWRITEREQ, &VoidFs::execFSWRITEREQ);
- addRecSignal(GSN_FSREADREQ, &VoidFs::execFSREADREQ);
- addRecSignal(GSN_FSSYNCREQ, &VoidFs::execFSSYNCREQ);
- addRecSignal(GSN_FSAPPENDREQ, &VoidFs::execFSAPPENDREQ);
- addRecSignal(GSN_FSREMOVEREQ, &VoidFs::execFSREMOVEREQ);
- // Set send signals
-}
-
-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)
-{
- jamEntry();
-
- if(signal->theData[1] == 0){ // StartPhase 0
- jam();
- signal->theData[3] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 4, JBB);
- return;
- }
- ndbrequire(0);
-}
-
-void
-VoidFs::execFSOPENREQ(Signal* signal)
-{
- jamEntry();
- const FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
- const BlockReference userRef = fsOpenReq->userReference;
- const Uint32 userPointer = fsOpenReq->userPointer;
-
- Uint32 flags = fsOpenReq->fileFlags;
- if(flags == FsOpenReq::OM_READONLY){
- // Initialise FsRef signal
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = userPointer;
- fsRef->errorCode = FsRef::fsErrFileDoesNotExist;
- fsRef->osErrorCode = ~0;
- sendSignal(userRef, GSN_FSOPENREF, signal, 3, JBB);
- return;
- }
-
- if(flags & FsOpenReq::OM_WRITEONLY || flags & FsOpenReq::OM_READWRITE){
- signal->theData[0] = userPointer;
- signal->theData[1] = c_maxFileNo++;
- sendSignal(userRef, GSN_FSOPENCONF, signal, 2, JBB);
- }
-}
-
-void
-VoidFs::execFSREMOVEREQ(Signal* signal)
-{
- jamEntry();
- const FsRemoveReq * const req = (FsRemoveReq *)signal->getDataPtr();
- const Uint32 userRef = req->userReference;
- const Uint32 userPointer = req->userPointer;
-
- signal->theData[0] = userPointer;
- sendSignal(userRef, GSN_FSREMOVECONF, signal, 1, JBB);
-}
-
-/*
- * PR0: File Pointer DR0: User reference DR1: User Pointer DR2: Flag bit 0= 1
- * remove file
- */
-void
-VoidFs::execFSCLOSEREQ(Signal * signal)
-{
- jamEntry();
-
- const FsCloseReq * const req = (FsCloseReq *)signal->getDataPtr();
- const Uint32 userRef = req->userReference;
- const Uint32 userPointer = req->userPointer;
-
- signal->theData[0] = userPointer;
- sendSignal(userRef, GSN_FSCLOSECONF, signal, 1, JBB);
-}
-
-void
-VoidFs::execFSWRITEREQ(Signal* signal)
-{
- jamEntry();
- const FsReadWriteReq * const req = (FsReadWriteReq *)signal->getDataPtr();
- const Uint32 userRef = req->userReference;
- const Uint32 userPointer = req->userPointer;
-
- signal->theData[0] = userPointer;
- sendSignal(userRef, GSN_FSWRITECONF, signal, 1, JBB);
-}
-
-void
-VoidFs::execFSREADREQ(Signal* signal)
-{
- jamEntry();
-
- const FsReadWriteReq * const req = (FsReadWriteReq *)signal->getDataPtr();
- const Uint32 userRef = req->userReference;
- const Uint32 userPointer = req->userPointer;
-
- signal->theData[0] = userPointer;
- sendSignal(userRef, GSN_FSREADCONF, signal, 1, JBB);
-#if 0
- FsRef * const fsRef = (FsRef *)&signal->theData[0];
- fsRef->userPointer = userPointer;
- fsRef->errorCode = FsRef::fsErrEnvironmentError;
- fsRef->osErrorCode = ~0; // Indicate local error
- sendSignal(userRef, GSN_FSREADREF, signal, 3, JBB);
-#endif
-}
-
-void
-VoidFs::execFSSYNCREQ(Signal * signal)
-{
- jamEntry();
-
- BlockReference userRef = signal->theData[1];
- const UintR userPointer = signal->theData[2];
-
- signal->theData[0] = userPointer;
- sendSignal(userRef, GSN_FSSYNCCONF, signal, 1, JBB);
-
- return;
-}
-
-void
-VoidFs::execFSAPPENDREQ(Signal * signal)
-{
- const FsAppendReq * const fsReq = (FsAppendReq *)&signal->theData[0];
- const UintR userPointer = fsReq->userPointer;
- const BlockReference userRef = fsReq->userReference;
- const Uint32 size = fsReq->size;
-
- signal->theData[0] = userPointer;
- signal->theData[1] = size << 2;
- sendSignal(userRef, GSN_FSAPPENDCONF, signal, 2, JBB);
-}
-
-void
-VoidFs::execDUMP_STATE_ORD(Signal* signal)
-{
-}//VoidFs::execDUMP_STATE_ORD()
-
-
-
-BLOCK_FUNCTIONS(VoidFs)
-
diff --git a/storage/ndb/src/kernel/blocks/new-block.tar.gz b/storage/ndb/src/kernel/blocks/new-block.tar.gz
deleted file mode 100644
index 327503ea0b1..00000000000
--- a/storage/ndb/src/kernel/blocks/new-block.tar.gz
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp
deleted file mode 100644
index 9d184f7401b..00000000000
--- a/storage/ndb/src/kernel/blocks/pgman.cpp
+++ /dev/null
@@ -1,2514 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "pgman.hpp"
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-#include <signaldata/PgmanContinueB.hpp>
-#include <signaldata/LCP.hpp>
-
-#include <dbtup/Dbtup.hpp>
-
-#include <DebuggerNames.hpp>
-
-/**
- * Requests that make page dirty
- */
-#define DIRTY_FLAGS (Page_request::COMMIT_REQ | \
- Page_request::DIRTY_REQ | \
- Page_request::ALLOC_REQ)
-
-// todo use this
-#ifdef VM_TRACE
-#define dbg(x) \
- do { if (! debugFlag) break; debugOut << "PGMAN: " << x << endl; } while (0)
-#else
-#define dbg(x)
-#endif
-
-static bool g_dbg_lcp = false;
-#if 1
-#define DBG_LCP(x)
-#else
-#define DBG_LCP(x) if(g_dbg_lcp) ndbout << x
-#endif
-
-Pgman::Pgman(Block_context& ctx) :
- SimulatedBlock(PGMAN, ctx),
- m_file_map(m_data_buffer_pool),
- m_page_hashlist(m_page_entry_pool),
- m_page_stack(m_page_entry_pool),
- m_page_queue(m_page_entry_pool)
-#ifdef VM_TRACE
- ,debugOut(* new NullOutputStream())
- ,debugFlag(false)
-#endif
-{
- BLOCK_CONSTRUCTOR(Pgman);
-
- // Add received signals
- addRecSignal(GSN_STTOR, &Pgman::execSTTOR);
- addRecSignal(GSN_READ_CONFIG_REQ, &Pgman::execREAD_CONFIG_REQ);
- addRecSignal(GSN_DUMP_STATE_ORD, &Pgman::execDUMP_STATE_ORD);
- addRecSignal(GSN_CONTINUEB, &Pgman::execCONTINUEB);
- addRecSignal(GSN_FSREADREF, &Pgman::execFSREADREF, true);
- addRecSignal(GSN_FSREADCONF, &Pgman::execFSREADCONF);
- addRecSignal(GSN_FSWRITEREF, &Pgman::execFSWRITEREF, true);
- addRecSignal(GSN_FSWRITECONF, &Pgman::execFSWRITECONF);
-
- addRecSignal(GSN_LCP_FRAG_ORD, &Pgman::execLCP_FRAG_ORD);
- addRecSignal(GSN_END_LCP_REQ, &Pgman::execEND_LCP_REQ);
-
- // loop status
- m_stats_loop_on = false;
- m_busy_loop_on = false;
- m_cleanup_loop_on = false;
- m_lcp_loop_on = false;
-
- // LCP variables
- m_last_lcp = 0;
- m_last_lcp_complete = 0;
- m_lcp_curr_bucket = ~(Uint32)0;
- m_lcp_outstanding = 0;
-
- // clean-up variables
- m_cleanup_ptr.i = RNIL;
-
- // should be a factor larger than number of pool pages
- m_data_buffer_pool.setSize(16);
- m_page_hashlist.setSize(512);
-
- for (Uint32 k = 0; k < Page_entry::SUBLIST_COUNT; k++)
- m_page_sublist[k] = new Page_sublist(m_page_entry_pool);
-}
-
-Pgman::~Pgman()
-{
- for (Uint32 k = 0; k < Page_entry::SUBLIST_COUNT; k++)
- delete m_page_sublist[k];
-}
-
-BLOCK_FUNCTIONS(Pgman)
-
-void
-Pgman::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Uint64 page_buffer = 64*1024*1024;
- ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY, &page_buffer);
-
- if (page_buffer > 0)
- {
- page_buffer = (page_buffer + GLOBAL_PAGE_SIZE - 1) / GLOBAL_PAGE_SIZE; // in pages
- m_param.m_max_pages = page_buffer;
- m_page_entry_pool.setSize(m_param.m_lirs_stack_mult * page_buffer);
- m_param.m_max_hot_pages = (page_buffer * 9) / 10;
- }
-
- Pool_context pc;
- pc.m_block = this;
- m_page_request_pool.wo_pool_init(RT_PGMAN_PAGE_REQUEST, pc);
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
-Pgman::Param::Param() :
- m_max_pages(64), // smallish for testing
- m_lirs_stack_mult(10),
- m_max_hot_pages(56),
- m_max_loop_count(256),
- m_max_io_waits(256),
- m_stats_loop_delay(1000),
- m_cleanup_loop_delay(200),
- m_lcp_loop_delay(0)
-{
-}
-
-Pgman::Stats::Stats() :
- m_num_pages(0),
- m_page_hits(0),
- m_page_faults(0),
- m_current_io_waits(0)
-{
-}
-
-void
-Pgman::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- const Uint32 startPhase = signal->theData[1];
-
- switch (startPhase) {
- case 1:
- {
- Lgman* lgman = (Lgman*)globalData.getBlock(LGMAN);
- new (&m_lgman) Logfile_client(this, lgman, 0);
- c_tup = (Dbtup*)globalData.getBlock(DBTUP);
- }
- break;
- case 3:
- {
- // start forever loops
- do_stats_loop(signal);
- do_cleanup_loop(signal);
- m_stats_loop_on = true;
- m_cleanup_loop_on = true;
- }
- break;
- case 7:
- break;
- default:
- break;
- }
-
- sendSTTORRY(signal);
-}
-
-void
-Pgman::sendSTTORRY(Signal* signal)
-{
- signal->theData[0] = 0;
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 7;
- signal->theData[6] = 255; // No more start phases from missra
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
-}
-
-void
-Pgman::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- Uint32 data1 = signal->theData[1];
-
- switch (signal->theData[0]) {
- case PgmanContinueB::STATS_LOOP:
- jam();
- do_stats_loop(signal);
- break;
- case PgmanContinueB::BUSY_LOOP:
- jam();
- do_busy_loop(signal);
- break;
- case PgmanContinueB::CLEANUP_LOOP:
- jam();
- do_cleanup_loop(signal);
- break;
- case PgmanContinueB::LCP_LOOP:
- jam();
- do_lcp_loop(signal);
- break;
- case PgmanContinueB::LCP_LOCKED:
- {
- jam();
- Ptr<Page_entry> ptr;
- Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
- if (data1 != RNIL)
- {
- pl.getPtr(ptr, data1);
- process_lcp_locked(signal, ptr);
- }
- else
- {
- if (ERROR_INSERTED(11007))
- {
- ndbout << "No more writes..." << endl;
- SET_ERROR_INSERT_VALUE(11008);
- signal->theData[0] = 9999;
- sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 10000, 1);
- }
- signal->theData[0] = m_end_lcp_req.senderData;
- sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF, signal, 1, JBB);
- }
- return;
- }
- default:
- ndbrequire(false);
- break;
- }
-}
-
-// page entry
-
-Pgman::Page_entry::Page_entry(Uint32 file_no, Uint32 page_no) :
- m_file_no(file_no),
- m_state(0),
- m_page_no(page_no),
- m_real_page_i(RNIL),
- m_lsn(0),
- m_last_lcp(0),
- m_dirty_count(0),
- m_copy_page_i(RNIL),
- m_busy_count(0),
- m_requests()
-{
-}
-
-// page lists
-
-Uint32
-Pgman::get_sublist_no(Page_state state)
-{
- if (state == 0)
- {
- return ZNIL;
- }
- if (state & Page_entry::REQUEST)
- {
- if (! (state & Page_entry::BOUND))
- {
- return Page_entry::SL_BIND;
- }
- if (! (state & Page_entry::MAPPED))
- {
- if (! (state & Page_entry::PAGEIN))
- {
- return Page_entry::SL_MAP;
- }
- return Page_entry::SL_MAP_IO;
- }
- if (! (state & Page_entry::PAGEOUT))
- {
- return Page_entry::SL_CALLBACK;
- }
- return Page_entry::SL_CALLBACK_IO;
- }
- if (state & Page_entry::BUSY)
- {
- return Page_entry::SL_BUSY;
- }
- if (state & Page_entry::LOCKED)
- {
- return Page_entry::SL_LOCKED;
- }
- if (state == Page_entry::ONSTACK) {
- return Page_entry::SL_IDLE;
- }
- return Page_entry::SL_OTHER;
-}
-
-void
-Pgman::set_page_state(Ptr<Page_entry> ptr, Page_state new_state)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >set_page_state: state=" << hex << new_state << endl;
- debugOut << "PGMAN: " << ptr << ": before" << endl;
-#endif
-
- Page_state old_state = ptr.p->m_state;
- if (old_state != new_state)
- {
- Uint32 old_list_no = get_sublist_no(old_state);
- Uint32 new_list_no = get_sublist_no(new_state);
- if (old_state != 0)
- {
- ndbrequire(old_list_no != ZNIL);
- if (old_list_no != new_list_no)
- {
- Page_sublist& old_list = *m_page_sublist[old_list_no];
- old_list.remove(ptr);
- }
- }
- if (new_state != 0)
- {
- ndbrequire(new_list_no != ZNIL);
- if (old_list_no != new_list_no)
- {
- Page_sublist& new_list = *m_page_sublist[new_list_no];
- new_list.add(ptr);
- }
- }
- ptr.p->m_state = new_state;
- }
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << ": after" << endl;
- debugOut << "PGMAN: <set_page_state" << endl;
-#endif
-}
-
-// seize/release pages and entries
-
-bool
-Pgman::seize_cache_page(Ptr<GlobalPage>& gptr)
-{
- // page cache has no own pool yet
- bool ok = m_global_page_pool.seize(gptr);
-
- // zero is reserved as return value for queued request
- if (ok && gptr.i == 0)
- ok = m_global_page_pool.seize(gptr);
-
- if (ok)
- {
- ndbrequire(m_stats.m_num_pages < m_param.m_max_pages);
- m_stats.m_num_pages++;
- }
- return ok;
-}
-
-void
-Pgman::release_cache_page(Uint32 i)
-{
- m_global_page_pool.release(i);
-
- ndbrequire(m_stats.m_num_pages != 0);
- m_stats.m_num_pages--;
-}
-
-bool
-Pgman::find_page_entry(Ptr<Page_entry>& ptr, Uint32 file_no, Uint32 page_no)
-{
- Page_entry key;
- key.m_file_no = file_no;
- key.m_page_no = page_no;
-
- if (m_page_hashlist.find(ptr, key))
- {
-#ifdef VM_TRACE
- debugOut << "PGMAN: find_page_entry" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
- return true;
- }
- return false;
-}
-
-Uint32
-Pgman::seize_page_entry(Ptr<Page_entry>& ptr, Uint32 file_no, Uint32 page_no)
-{
- if (m_page_entry_pool.seize(ptr))
- {
- new (ptr.p) Page_entry(file_no, page_no);
- m_page_hashlist.add(ptr);
-
-#ifdef VM_TRACE
- ptr.p->m_this = this;
- debugOut << "PGMAN: seize_page_entry" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
-
- return true;
- }
- return false;
-}
-
-bool
-Pgman::get_page_entry(Ptr<Page_entry>& ptr, Uint32 file_no, Uint32 page_no)
-{
- if (find_page_entry(ptr, file_no, page_no))
- {
- jam();
- ndbrequire(ptr.p->m_state != 0);
- m_stats.m_page_hits++;
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: get_page_entry: found" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
- return true;
- }
-
- if (m_page_entry_pool.getNoOfFree() == 0)
- {
- jam();
- Page_sublist& pl_idle = *m_page_sublist[Page_entry::SL_IDLE];
- Ptr<Page_entry> idle_ptr;
- if (pl_idle.first(idle_ptr))
- {
- jam();
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: get_page_entry: re-use idle entry" << endl;
- debugOut << "PGMAN: " << idle_ptr << endl;
-#endif
-
- Page_state state = idle_ptr.p->m_state;
- ndbrequire(state == Page_entry::ONSTACK);
-
- Page_stack& pl_stack = m_page_stack;
- ndbrequire(pl_stack.hasPrev(idle_ptr));
- pl_stack.remove(idle_ptr);
- state &= ~ Page_entry::ONSTACK;
- set_page_state(idle_ptr, state);
- ndbrequire(idle_ptr.p->m_state == 0);
-
- release_page_entry(idle_ptr);
- }
- }
-
- if (seize_page_entry(ptr, file_no, page_no))
- {
- jam();
- ndbrequire(ptr.p->m_state == 0);
- m_stats.m_page_faults++;
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: get_page_entry: seize" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
- return true;
- }
-
- ndbrequire(false);
-
- return false;
-}
-
-void
-Pgman::release_page_entry(Ptr<Page_entry>& ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: release_page_entry" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
- Page_state state = ptr.p->m_state;
-
- ndbrequire(ptr.p->m_requests.isEmpty());
-
- ndbrequire(! (state & Page_entry::ONSTACK));
- ndbrequire(! (state & Page_entry::ONQUEUE));
- ndbrequire(ptr.p->m_real_page_i == RNIL);
-
- if (! (state & Page_entry::LOCKED))
- ndbrequire(! (state & Page_entry::REQUEST));
-
- if (ptr.p->m_copy_page_i != RNIL)
- {
- m_global_page_pool.release(ptr.p->m_copy_page_i);
- }
-
- set_page_state(ptr, 0);
- m_page_hashlist.remove(ptr);
- m_page_entry_pool.release(ptr);
-}
-
-// LIRS
-
-/*
- * After the hot entry at stack bottom is removed, additional entries
- * are removed until next hot entry is found. There are 3 cases for the
- * removed entry: 1) a bound entry is already on queue 2) an unbound
- * entry with open requests enters queue at bind time 3) an unbound
- * entry without requests is returned to entry pool.
- */
-void
-Pgman::lirs_stack_prune()
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >lirs_stack_prune" << endl;
-#endif
- Page_stack& pl_stack = m_page_stack;
- Ptr<Page_entry> ptr;
-
- while (pl_stack.first(ptr)) // first is stack bottom
- {
- Page_state state = ptr.p->m_state;
- if (state & Page_entry::HOT)
- {
- jam();
- break;
- }
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << ": prune from stack" << endl;
-#endif
-
- pl_stack.remove(ptr);
- state &= ~ Page_entry::ONSTACK;
- set_page_state(ptr, state);
-
- if (state & Page_entry::BOUND)
- {
- jam();
- ndbrequire(state & Page_entry::ONQUEUE);
- }
- else if (state & Page_entry::REQUEST)
- {
- // enters queue at bind
- jam();
- ndbrequire(! (state & Page_entry::ONQUEUE));
- }
- else
- {
- jam();
- release_page_entry(ptr);
- }
- }
-#ifdef VM_TRACE
- debugOut << "PGMAN: <lirs_stack_prune" << endl;
-#endif
-}
-
-/*
- * Remove the hot entry at stack bottom and make it cold and do stack
- * pruning. There are 2 cases for the removed entry: 1) a bound entry
- * is moved to queue 2) an unbound entry must have requests and enters
- * queue at bind time.
- */
-void
-Pgman::lirs_stack_pop()
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: lirs_stack_pop" << endl;
-#endif
- Page_stack& pl_stack = m_page_stack;
- Page_queue& pl_queue = m_page_queue;
-
- Ptr<Page_entry> ptr;
- bool ok = pl_stack.first(ptr);
- ndbrequire(ok);
- Page_state state = ptr.p->m_state;
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << ": pop from stack" << endl;
-#endif
-
- ndbrequire(state & Page_entry::HOT);
- ndbrequire(state & Page_entry::ONSTACK);
- pl_stack.remove(ptr);
- state &= ~ Page_entry::HOT;
- state &= ~ Page_entry::ONSTACK;
- ndbrequire(! (state & Page_entry::ONQUEUE));
-
- if (state & Page_entry::BOUND)
- {
- jam();
- pl_queue.add(ptr);
- state |= Page_entry::ONQUEUE;
- }
- else
- {
- // enters queue at bind
- jam();
- ndbrequire(state & Page_entry::REQUEST);
- }
-
- set_page_state(ptr, state);
- lirs_stack_prune();
-}
-
-/*
- * Update LIRS lists when page is referenced.
- */
-void
-Pgman::lirs_reference(Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >lirs_reference" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
- Page_stack& pl_stack = m_page_stack;
- Page_queue& pl_queue = m_page_queue;
-
- Page_state state = ptr.p->m_state;
- ndbrequire(! (state & Page_entry::LOCKED));
-
- // even non-LIRS cache pages are counted on l.h.s.
- if (m_stats.m_num_pages >= m_param.m_max_hot_pages)
- {
- if (state & Page_entry::HOT)
- {
- // case 1
- jam();
- ndbrequire(state & Page_entry::ONSTACK);
- bool at_bottom = ! pl_stack.hasPrev(ptr);
- pl_stack.remove(ptr);
- pl_stack.add(ptr);
- if (at_bottom)
- {
- jam();
- lirs_stack_prune();
- }
- }
- else if (state & Page_entry::ONSTACK)
- {
- // case 2a 3a
- jam();
- pl_stack.remove(ptr);
- if (! pl_stack.isEmpty())
- {
- jam();
- lirs_stack_pop();
- }
- pl_stack.add(ptr);
- state |= Page_entry::HOT;
- if (state & Page_entry::ONQUEUE)
- {
- jam();
- move_cleanup_ptr(ptr);
- pl_queue.remove(ptr);
- state &= ~ Page_entry::ONQUEUE;
- }
- }
- else
- {
- // case 2b 3b
- jam();
- pl_stack.add(ptr);
- state |= Page_entry::ONSTACK;
- if (state & Page_entry::ONQUEUE)
- {
- jam();
- move_cleanup_ptr(ptr);
- pl_queue.remove(ptr);
- state &= ~ Page_entry::ONQUEUE;
- }
- if (state & Page_entry::BOUND)
- {
- jam();
- pl_queue.add(ptr);
- state |= Page_entry::ONQUEUE;
- }
- else
- {
- // enters queue at bind
- jam();
- }
- }
- }
- else
- {
-#ifdef VM_TRACE
- debugOut << "PGMAN: filling up initial hot pages: "
- << m_stats.m_num_pages << " of "
- << m_param.m_max_hot_pages << endl;
-#endif
- jam();
- if (state & Page_entry::ONSTACK)
- {
- jam();
- bool at_bottom = ! pl_stack.hasPrev(ptr);
- pl_stack.remove(ptr);
- if (at_bottom)
- {
- jam();
- ndbassert(state & Page_entry::HOT);
- lirs_stack_prune();
- }
- }
- pl_stack.add(ptr);
- state |= Page_entry::ONSTACK;
- state |= Page_entry::HOT;
- // it could be on queue already
- if (state & Page_entry::ONQUEUE) {
- jam();
- pl_queue.remove(ptr);
- state &= ~Page_entry::ONQUEUE;
- }
- }
-
- set_page_state(ptr, state);
-#ifdef VM_TRACE
- debugOut << "PGMAN: <lirs_reference" << endl;
-#endif
-}
-
-// continueB loops
-
-void
-Pgman::do_stats_loop(Signal* signal)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: do_stats_loop" << endl;
- verify_all();
-#endif
- Uint32 delay = m_param.m_stats_loop_delay;
- signal->theData[0] = PgmanContinueB::STATS_LOOP;
- sendSignalWithDelay(PGMAN_REF, GSN_CONTINUEB, signal, delay, 1);
-}
-
-void
-Pgman::do_busy_loop(Signal* signal, bool direct)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >do_busy_loop on=" << m_busy_loop_on
- << " direct=" << direct << endl;
-#endif
- Uint32 restart = false;
- if (direct)
- {
- // may not cover the calling entry
- (void)process_bind(signal);
- (void)process_map(signal);
- // callback must be queued
- if (! m_busy_loop_on)
- {
- restart = true;
- m_busy_loop_on = true;
- }
- }
- else
- {
- ndbrequire(m_busy_loop_on);
- restart += process_bind(signal);
- restart += process_map(signal);
- restart += process_callback(signal);
- if (! restart)
- {
- m_busy_loop_on = false;
- }
- }
- if (restart)
- {
- signal->theData[0] = PgmanContinueB::BUSY_LOOP;
- sendSignal(PGMAN_REF, GSN_CONTINUEB, signal, 1, JBB);
- }
-#ifdef VM_TRACE
- debugOut << "PGMAN: <do_busy_loop on=" << m_busy_loop_on
- << " restart=" << restart << endl;
-#endif
-}
-
-void
-Pgman::do_cleanup_loop(Signal* signal)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: do_cleanup_loop" << endl;
-#endif
- process_cleanup(signal);
-
- Uint32 delay = m_param.m_cleanup_loop_delay;
- signal->theData[0] = PgmanContinueB::CLEANUP_LOOP;
- sendSignalWithDelay(PGMAN_REF, GSN_CONTINUEB, signal, delay, 1);
-}
-
-void
-Pgman::do_lcp_loop(Signal* signal, bool direct)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >do_lcp_loop on=" << m_lcp_loop_on
- << " direct=" << direct << endl;
-#endif
- Uint32 restart = false;
- if (direct)
- {
- ndbrequire(! m_lcp_loop_on);
- restart = true;
- m_lcp_loop_on = true;
- }
- else
- {
- ndbrequire(m_lcp_loop_on);
- restart += process_lcp(signal);
- if (! restart)
- {
- m_lcp_loop_on = false;
- }
- }
- if (restart)
- {
- Uint32 delay = m_param.m_lcp_loop_delay;
- signal->theData[0] = PgmanContinueB::LCP_LOOP;
- if (delay)
- sendSignalWithDelay(PGMAN_REF, GSN_CONTINUEB, signal, delay, 1);
- else
- sendSignal(PGMAN_REF, GSN_CONTINUEB, signal, 1, JBB);
- }
-#ifdef VM_TRACE
- debugOut << "PGMAN: <do_lcp_loop on=" << m_lcp_loop_on
- << " restart=" << restart << endl;
-#endif
-}
-
-// busy loop
-
-bool
-Pgman::process_bind(Signal* signal)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >process_bind" << endl;
-#endif
- int max_count = 32;
- Page_sublist& pl_bind = *m_page_sublist[Page_entry::SL_BIND];
-
- while (! pl_bind.isEmpty() && --max_count >= 0)
- {
- jam();
- Ptr<Page_entry> ptr;
- pl_bind.first(ptr);
- if (! process_bind(signal, ptr))
- {
- jam();
- break;
- }
- }
-#ifdef VM_TRACE
- debugOut << "PGMAN: <process_bind" << endl;
-#endif
- return ! pl_bind.isEmpty();
-}
-
-bool
-Pgman::process_bind(Signal* signal, Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << " : process_bind" << endl;
-#endif
- Page_queue& pl_queue = m_page_queue;
- Ptr<GlobalPage> gptr;
-
- if (m_stats.m_num_pages < m_param.m_max_pages)
- {
- jam();
- bool ok = seize_cache_page(gptr);
- // to handle failure requires some changes in LIRS
- ndbrequire(ok);
- }
- else
- {
- jam();
- Ptr<Page_entry> clean_ptr;
- if (! pl_queue.first(clean_ptr))
- {
- jam();
-#ifdef VM_TRACE
- debugOut << "PGMAN: bind failed: queue empty" << endl;
-#endif
- // XXX busy loop
- return false;
- }
- Page_state clean_state = clean_ptr.p->m_state;
- // under unusual circumstances it could still be paging in
- if (! (clean_state & Page_entry::MAPPED) ||
- clean_state & Page_entry::DIRTY ||
- clean_state & Page_entry::REQUEST)
- {
- jam();
-#ifdef VM_TRACE
- debugOut << "PGMAN: bind failed: queue front not evictable" << endl;
- debugOut << "PGMAN: " << clean_ptr << endl;
-#endif
- // XXX busy loop
- return false;
- }
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << clean_ptr << " : evict" << endl;
-#endif
-
- ndbassert(clean_ptr.p->m_dirty_count == 0);
- ndbrequire(clean_state & Page_entry::ONQUEUE);
- ndbrequire(clean_state & Page_entry::BOUND);
- ndbrequire(clean_state & Page_entry::MAPPED);
-
- move_cleanup_ptr(clean_ptr);
- pl_queue.remove(clean_ptr);
- clean_state &= ~ Page_entry::ONQUEUE;
-
- gptr.i = clean_ptr.p->m_real_page_i;
-
- clean_ptr.p->m_real_page_i = RNIL;
- clean_state &= ~ Page_entry::BOUND;
- clean_state &= ~ Page_entry::MAPPED;
-
- set_page_state(clean_ptr, clean_state);
-
- if (! (clean_state & Page_entry::ONSTACK))
- release_page_entry(clean_ptr);
-
- m_global_page_pool.getPtr(gptr);
- }
-
- Page_state state = ptr.p->m_state;
-
- ptr.p->m_real_page_i = gptr.i;
- state |= Page_entry::BOUND;
- if (state & Page_entry::EMPTY)
- {
- jam();
- state |= Page_entry::MAPPED;
- }
-
- if (! (state & Page_entry::LOCKED) &&
- ! (state & Page_entry::ONQUEUE) &&
- ! (state & Page_entry::HOT))
- {
- jam();
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << " : add to queue at bind" << endl;
-#endif
-
- pl_queue.add(ptr);
- state |= Page_entry::ONQUEUE;
- }
-
- set_page_state(ptr, state);
- return true;
-}
-
-bool
-Pgman::process_map(Signal* signal)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >process_map" << endl;
-#endif
- int max_count = 0;
- if (m_param.m_max_io_waits > m_stats.m_current_io_waits) {
- max_count = m_param.m_max_io_waits - m_stats.m_current_io_waits;
- max_count = max_count / 2 + 1;
- }
- Page_sublist& pl_map = *m_page_sublist[Page_entry::SL_MAP];
-
- while (! pl_map.isEmpty() && --max_count >= 0)
- {
- jam();
- Ptr<Page_entry> ptr;
- pl_map.first(ptr);
- if (! process_map(signal, ptr))
- {
- jam();
- break;
- }
- }
-#ifdef VM_TRACE
- debugOut << "PGMAN: <process_map" << endl;
-#endif
- return ! pl_map.isEmpty();
-}
-
-bool
-Pgman::process_map(Signal* signal, Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << " : process_map" << endl;
-#endif
- pagein(signal, ptr);
- return true;
-}
-
-bool
-Pgman::process_callback(Signal* signal)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >process_callback" << endl;
-#endif
- int max_count = 1;
- Page_sublist& pl_callback = *m_page_sublist[Page_entry::SL_CALLBACK];
-
- Ptr<Page_entry> ptr;
- pl_callback.first(ptr);
-
- while (! ptr.isNull() && --max_count >= 0)
- {
- jam();
- Ptr<Page_entry> curr = ptr;
- pl_callback.next(ptr);
-
- if (! process_callback(signal, curr))
- {
- jam();
- break;
- }
- }
-#ifdef VM_TRACE
- debugOut << "PGMAN: <process_callback" << endl;
-#endif
- return ! pl_callback.isEmpty();
-}
-
-bool
-Pgman::process_callback(Signal* signal, Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << " : process_callback" << endl;
-#endif
- int max_count = 1;
- Page_state state = ptr.p->m_state;
-
- while (! ptr.p->m_requests.isEmpty() && --max_count >= 0)
- {
- jam();
- SimulatedBlock* b;
- Callback callback;
- {
- /**
- * Make sure list is in own scope if callback will access this
- * list again (destructor restores list head).
- */
- Local_page_request_list req_list(m_page_request_pool, ptr.p->m_requests);
- Ptr<Page_request> req_ptr;
-
- req_list.first(req_ptr);
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << req_ptr << " : process_callback" << endl;
-#endif
-
-#ifdef ERROR_INSERT
- if (req_ptr.p->m_flags & Page_request::DELAY_REQ)
- {
- Uint64 now = NdbTick_CurrentMillisecond();
- if (now < req_ptr.p->m_delay_until_time)
- {
- break;
- }
- }
-#endif
-
- b = globalData.getBlock(req_ptr.p->m_block);
- callback = req_ptr.p->m_callback;
-
- if (req_ptr.p->m_flags & DIRTY_FLAGS)
- {
- jam();
- state |= Page_entry::DIRTY;
- ndbassert(ptr.p->m_dirty_count);
- ptr.p->m_dirty_count --;
- }
-
- req_list.releaseFirst(req_ptr);
- }
- ndbrequire(state & Page_entry::BOUND);
- ndbrequire(state & Page_entry::MAPPED);
-
- // callback may re-enter PGMAN and change page state
- set_page_state(ptr, state);
- b->execute(signal, callback, ptr.p->m_real_page_i);
- state = ptr.p->m_state;
- }
-
- if (ptr.p->m_requests.isEmpty())
- {
- jam();
- state &= ~ Page_entry::REQUEST;
- }
- set_page_state(ptr, state);
- return true;
-}
-
-// cleanup loop
-
-bool
-Pgman::process_cleanup(Signal* signal)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: >process_cleanup" << endl;
-#endif
- Page_queue& pl_queue = m_page_queue;
-
- // XXX for now start always from beginning
- m_cleanup_ptr.i = RNIL;
-
- if (m_cleanup_ptr.i == RNIL && ! pl_queue.first(m_cleanup_ptr))
- {
- jam();
-#ifdef VM_TRACE
- debugOut << "PGMAN: <process_cleanup: empty queue" << endl;
-#endif
- return false;
- }
-
- int max_loop_count = m_param.m_max_loop_count;
- int max_count = 0;
- if (m_param.m_max_io_waits > m_stats.m_current_io_waits) {
- max_count = m_param.m_max_io_waits - m_stats.m_current_io_waits;
- max_count = max_count / 2 + 1;
- }
-
- Ptr<Page_entry> ptr = m_cleanup_ptr;
- while (max_loop_count != 0 && max_count != 0)
- {
- Page_state state = ptr.p->m_state;
- ndbrequire(! (state & Page_entry::LOCKED));
- if (state & Page_entry::BUSY)
- {
-#ifdef VM_TRACE
- debugOut << "PGMAN: process_cleanup: break on busy page" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
- break;
- }
- if (state & Page_entry::DIRTY &&
- ! (state & Page_entry::PAGEIN) &&
- ! (state & Page_entry::PAGEOUT))
- {
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << " : process_cleanup" << endl;
-#endif
- c_tup->disk_page_unmap_callback(0,
- ptr.p->m_real_page_i,
- ptr.p->m_dirty_count);
- pageout(signal, ptr);
- max_count--;
- }
- if (! pl_queue.hasNext(ptr))
- break;
- pl_queue.next(ptr);
- max_loop_count--;
- }
- m_cleanup_ptr = ptr;
-#ifdef VM_TRACE
- debugOut << "PGMAN: <process_cleanup" << endl;
-#endif
- return true;
-}
-
-/*
- * Call this before queue.remove(ptr). If the removed entry is the
- * clean-up pointer, move it towards front.
- */
-void
-Pgman::move_cleanup_ptr(Ptr<Page_entry> ptr)
-{
- Page_queue& pl_queue = m_page_queue;
- if (ptr.i == m_cleanup_ptr.i)
- {
- jam();
- pl_queue.prev(m_cleanup_ptr);
- }
-}
-
-// LCP
-
-
-void
-Pgman::execLCP_FRAG_ORD(Signal* signal)
-{
- if (ERROR_INSERTED(11008))
- {
- ndbout_c("Ignore LCP_FRAG_ORD");
- return;
- }
- LcpFragOrd* ord = (LcpFragOrd*)signal->getDataPtr();
- ndbrequire(ord->lcpId >= m_last_lcp_complete + 1 || m_last_lcp_complete == 0);
- m_last_lcp = ord->lcpId;
- DBG_LCP("Pgman::execLCP_FRAG_ORD lcp: " << m_last_lcp << endl);
-
-#ifdef VM_TRACE
- debugOut
- << "PGMAN: execLCP_FRAG_ORD"
- << " this=" << m_last_lcp << " last_complete=" << m_last_lcp_complete
- << " bucket=" << m_lcp_curr_bucket << endl;
-#endif
-}
-
-void
-Pgman::execEND_LCP_REQ(Signal* signal)
-{
- if (ERROR_INSERTED(11008))
- {
- ndbout_c("Ignore END_LCP");
- return;
- }
-
- EndLcpReq* req = (EndLcpReq*)signal->getDataPtr();
- m_end_lcp_req = *req;
-
- DBG_LCP("execEND_LCP_REQ" << endl);
-
- ndbrequire(!m_lcp_outstanding);
- m_lcp_curr_bucket = 0;
-
-#ifdef VM_TRACE
- debugOut
- << "PGMAN: execEND_LCP_REQ"
- << " this=" << m_last_lcp << " last_complete=" << m_last_lcp_complete
- << " bucket=" << m_lcp_curr_bucket
- << " outstanding=" << m_lcp_outstanding << endl;
-#endif
-
- m_last_lcp_complete = m_last_lcp;
-
- do_lcp_loop(signal, true);
-}
-
-bool
-Pgman::process_lcp(Signal* signal)
-{
- Page_hashlist& pl_hash = m_page_hashlist;
-
- int max_count = 0;
- if (m_param.m_max_io_waits > m_stats.m_current_io_waits) {
- max_count = m_param.m_max_io_waits - m_stats.m_current_io_waits;
- max_count = max_count / 2 + 1;
- }
-
-#ifdef VM_TRACE
- debugOut
- << "PGMAN: process_lcp"
- << " this=" << m_last_lcp << " last_complete=" << m_last_lcp_complete
- << " bucket=" << m_lcp_curr_bucket
- << " outstanding=" << m_lcp_outstanding << endl;
-#endif
-
- // start or re-start from beginning of current hash bucket
- if (m_lcp_curr_bucket != ~(Uint32)0)
- {
- Page_hashlist::Iterator iter;
- pl_hash.next(m_lcp_curr_bucket, iter);
- Uint32 loop = 0;
- while (iter.curr.i != RNIL &&
- m_lcp_outstanding < (Uint32) max_count &&
- (loop ++ < 32 || iter.bucket == m_lcp_curr_bucket))
- {
- Ptr<Page_entry>& ptr = iter.curr;
- Page_state state = ptr.p->m_state;
-
- DBG_LCP("LCP " << ptr << " - ");
-
- if (ptr.p->m_last_lcp < m_last_lcp &&
- (state & Page_entry::DIRTY) &&
- (! (state & Page_entry::LOCKED)))
- {
- if(! (state & Page_entry::BOUND))
- {
- ndbout << ptr << endl;
- ndbrequire(false);
- }
- if (state & Page_entry::BUSY)
- {
- DBG_LCP(" BUSY" << endl);
- break; // wait for it
- }
- else if (state & Page_entry::PAGEOUT)
- {
- DBG_LCP(" PAGEOUT -> state |= LCP" << endl);
- set_page_state(ptr, state | Page_entry::LCP);
- }
- else
- {
- DBG_LCP(" pageout()" << endl);
- ptr.p->m_state |= Page_entry::LCP;
- c_tup->disk_page_unmap_callback(0,
- ptr.p->m_real_page_i,
- ptr.p->m_dirty_count);
- pageout(signal, ptr);
- }
- ptr.p->m_last_lcp = m_last_lcp;
- m_lcp_outstanding++;
- }
- else
- {
- DBG_LCP(" NOT DIRTY" << endl);
- }
- pl_hash.next(iter);
- }
-
- m_lcp_curr_bucket = (iter.curr.i != RNIL ? iter.bucket : ~(Uint32)0);
- }
-
- if (m_lcp_curr_bucket == ~(Uint32)0 && !m_lcp_outstanding)
- {
- Ptr<Page_entry> ptr;
- Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
- if (pl.first(ptr))
- {
- process_lcp_locked(signal, ptr);
- }
- else
- {
- if (ERROR_INSERTED(11007))
- {
- ndbout << "No more writes..." << endl;
- signal->theData[0] = 9999;
- sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 10000, 1);
- SET_ERROR_INSERT_VALUE(11008);
- }
- signal->theData[0] = m_end_lcp_req.senderData;
- sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF, signal, 1, JBB);
- }
- return false;
- }
-
- return true;
-}
-
-void
-Pgman::process_lcp_locked(Signal* signal, Ptr<Page_entry> ptr)
-{
- CRASH_INSERTION(11006);
-
- ptr.p->m_last_lcp = m_last_lcp;
- if (ptr.p->m_state & Page_entry::DIRTY)
- {
- Ptr<GlobalPage> org, copy;
- ndbrequire(m_global_page_pool.seize(copy));
- m_global_page_pool.getPtr(org, ptr.p->m_real_page_i);
- memcpy(copy.p, org.p, sizeof(GlobalPage));
- ptr.p->m_copy_page_i = copy.i;
-
- m_lcp_outstanding++;
- ptr.p->m_state |= Page_entry::LCP;
- pageout(signal, ptr);
- return;
- }
-
- Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
- pl.next(ptr);
-
- signal->theData[0] = PgmanContinueB::LCP_LOCKED;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Pgman::process_lcp_locked_fswriteconf(Signal* signal, Ptr<Page_entry> ptr)
-{
- Ptr<GlobalPage> org, copy;
- m_global_page_pool.getPtr(copy, ptr.p->m_copy_page_i);
- m_global_page_pool.getPtr(org, ptr.p->m_real_page_i);
- memcpy(org.p, copy.p, sizeof(GlobalPage));
- m_global_page_pool.release(copy);
-
- ptr.p->m_copy_page_i = RNIL;
-
- Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
- pl.next(ptr);
-
- signal->theData[0] = PgmanContinueB::LCP_LOCKED;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-// page read and write
-
-void
-Pgman::pagein(Signal* signal, Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: pagein" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
-
- ndbrequire(! (ptr.p->m_state & Page_entry::PAGEIN));
- set_page_state(ptr, ptr.p->m_state | Page_entry::PAGEIN);
-
- fsreadreq(signal, ptr);
- m_stats.m_current_io_waits++;
-}
-
-void
-Pgman::fsreadconf(Signal* signal, Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: fsreadconf" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
- ndbrequire(ptr.p->m_state & Page_entry::PAGEIN);
- Page_state state = ptr.p->m_state;
-
- state &= ~ Page_entry::PAGEIN;
- state &= ~ Page_entry::EMPTY;
- state |= Page_entry::MAPPED;
- set_page_state(ptr, state);
-
- {
- /**
- * Update lsn record on page
- * as it can be modified/flushed wo/ update_lsn has been called
- * (e.g. prealloc) and it then would get lsn 0, which is bad
- * when running undo and following SR
- */
- Ptr<GlobalPage> pagePtr;
- m_global_page_pool.getPtr(pagePtr, ptr.p->m_real_page_i);
- File_formats::Datafile::Data_page* page =
- (File_formats::Datafile::Data_page*)pagePtr.p;
-
- Uint64 lsn = 0;
- lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32;
- lsn += page->m_page_header.m_page_lsn_lo;
- ptr.p->m_lsn = lsn;
- }
-
- ndbrequire(m_stats.m_current_io_waits > 0);
- m_stats.m_current_io_waits--;
-
- ptr.p->m_last_lcp = m_last_lcp_complete;
- do_busy_loop(signal, true);
-}
-
-void
-Pgman::pageout(Signal* signal, Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: pageout" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
-
- Page_state state = ptr.p->m_state;
- ndbrequire(state & Page_entry::BOUND);
- ndbrequire(state & Page_entry::MAPPED);
- ndbrequire(! (state & Page_entry::BUSY));
- ndbrequire(! (state & Page_entry::PAGEOUT));
-
- state |= Page_entry::PAGEOUT;
-
- // update lsn on page prior to write
- Ptr<GlobalPage> pagePtr;
- m_global_page_pool.getPtr(pagePtr, ptr.p->m_real_page_i);
- File_formats::Datafile::Data_page* page =
- (File_formats::Datafile::Data_page*)pagePtr.p;
- page->m_page_header.m_page_lsn_hi = ptr.p->m_lsn >> 32;
- page->m_page_header.m_page_lsn_lo = ptr.p->m_lsn & 0xFFFFFFFF;
-
- // undo WAL
- Logfile_client::Request req;
- req.m_callback.m_callbackData = ptr.i;
- req.m_callback.m_callbackFunction = safe_cast(&Pgman::logsync_callback);
- int ret = m_lgman.sync_lsn(signal, ptr.p->m_lsn, &req, 0);
- if (ret > 0)
- {
- fswritereq(signal, ptr);
- m_stats.m_current_io_waits++;
- }
- else
- {
- ndbrequire(ret == 0);
- state |= Page_entry::LOGSYNC;
- }
- set_page_state(ptr, state);
-}
-
-void
-Pgman::logsync_callback(Signal* signal, Uint32 ptrI, Uint32 res)
-{
- Ptr<Page_entry> ptr;
- m_page_entry_pool.getPtr(ptr, ptrI);
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: logsync_callback" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
-
- // it is OK to be "busy" at this point (the commit is queued)
- Page_state state = ptr.p->m_state;
- ndbrequire(state & Page_entry::PAGEOUT);
- ndbrequire(state & Page_entry::LOGSYNC);
- state &= ~ Page_entry::LOGSYNC;
- set_page_state(ptr, state);
-
- fswritereq(signal, ptr);
- m_stats.m_current_io_waits++;
-}
-
-void
-Pgman::fswriteconf(Signal* signal, Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: fswriteconf" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
-
- Page_state state = ptr.p->m_state;
- ndbrequire(state & Page_entry::PAGEOUT);
-
- c_tup->disk_page_unmap_callback(1,
- ptr.p->m_real_page_i,
- ptr.p->m_dirty_count);
-
- state &= ~ Page_entry::PAGEOUT;
- state &= ~ Page_entry::EMPTY;
- state &= ~ Page_entry::DIRTY;
-
- ndbrequire(m_stats.m_current_io_waits > 0);
- m_stats.m_current_io_waits--;
-
- if (state & Page_entry::LCP)
- {
- ndbrequire(m_lcp_outstanding);
- m_lcp_outstanding--;
- state &= ~ Page_entry::LCP;
-
- if (ptr.p->m_copy_page_i != RNIL)
- {
- process_lcp_locked_fswriteconf(signal, ptr);
- }
- }
-
- set_page_state(ptr, state);
- do_busy_loop(signal, true);
-}
-
-// file system interface
-
-void
-Pgman::fsreadreq(Signal* signal, Ptr<Page_entry> ptr)
-{
- File_map::ConstDataBufferIterator it;
- bool ret = m_file_map.first(it) && m_file_map.next(it, ptr.p->m_file_no);
- ndbrequire(ret);
- Uint32 fd = * it.data;
-
- ndbrequire(ptr.p->m_page_no > 0);
-
- FsReadWriteReq* req = (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = fd;
- req->userReference = reference();
- req->userPointer = ptr.i;
- req->varIndex = ptr.p->m_page_no;
- req->numberOfPages = 1;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatGlobalPage);
- req->data.pageData[0] = ptr.p->m_real_page_i;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
-}
-
-void
-Pgman::execFSREADCONF(Signal* signal)
-{
- jamEntry();
- FsConf* conf = (FsConf*)signal->getDataPtr();
- Ptr<Page_entry> ptr;
- m_page_entry_pool.getPtr(ptr, conf->userPointer);
-
- fsreadconf(signal, ptr);
-}
-
-void
-Pgman::execFSREADREF(Signal* signal)
-{
- jamEntry();
- SimulatedBlock::execFSREADREF(signal);
- ndbrequire(false);
-}
-
-void
-Pgman::fswritereq(Signal* signal, Ptr<Page_entry> ptr)
-{
- File_map::ConstDataBufferIterator it;
- m_file_map.first(it);
- m_file_map.next(it, ptr.p->m_file_no);
- Uint32 fd = * it.data;
-
- ndbrequire(ptr.p->m_page_no > 0);
-
- FsReadWriteReq* req = (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = fd;
- req->userReference = reference();
- req->userPointer = ptr.i;
- req->varIndex = ptr.p->m_page_no;
- req->numberOfPages = 1;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatGlobalPage);
- req->data.pageData[0] = ptr.p->m_real_page_i;
-
-#if ERROR_INSERT_CODE
- if (ptr.p->m_state & Page_entry::LOCKED)
- {
- sendSignalWithDelay(NDBFS_REF, GSN_FSWRITEREQ, signal,
- 3000, FsReadWriteReq::FixedLength + 1);
- ndbout_c("pageout locked (3s)");
- return;
- }
-#endif
-
- if (!ERROR_INSERTED(11008))
- {
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBA);
- }
-}
-
-void
-Pgman::execFSWRITECONF(Signal* signal)
-{
- jamEntry();
- FsConf* conf = (FsConf*)signal->getDataPtr();
- Ptr<Page_entry> ptr;
- m_page_entry_pool.getPtr(ptr, conf->userPointer);
-
- fswriteconf(signal, ptr);
-}
-
-
-void
-Pgman::execFSWRITEREF(Signal* signal)
-{
- jamEntry();
- SimulatedBlock::execFSWRITEREF(signal);
- ndbrequire(false);
-}
-
-// client methods
-
-int
-Pgman::get_page(Signal* signal, Ptr<Page_entry> ptr, Page_request page_req)
-{
- jamEntry();
-#ifdef VM_TRACE
- Ptr<Page_request> tmp = { &page_req, RNIL};
- debugOut << "PGMAN: >get_page" << endl;
- debugOut << "PGMAN: " << ptr << endl;
- debugOut << "PGMAN: " << tmp << endl;
-#endif
- Uint32 req_flags = page_req.m_flags;
-
- if (req_flags & Page_request::EMPTY_PAGE)
- {
- // Only one can "init" a page at a time
- //ndbrequire(ptr.p->m_requests.isEmpty());
- }
-
- Page_state state = ptr.p->m_state;
- bool is_new = (state == 0);
- bool busy_count = false;
-
- if (req_flags & Page_request::LOCK_PAGE)
- {
- jam();
- state |= Page_entry::LOCKED;
- }
-
- if (req_flags & Page_request::ALLOC_REQ)
- {
- jam();
- }
- else if (req_flags & Page_request::COMMIT_REQ)
- {
- busy_count = true;
- state |= Page_entry::BUSY;
- }
- else if ((req_flags & Page_request::OP_MASK) != ZREAD)
- {
- jam();
- }
-
- // update LIRS
- if (! (state & Page_entry::LOCKED) &&
- ! (req_flags & Page_request::CORR_REQ))
- {
- jam();
- set_page_state(ptr, state);
- lirs_reference(ptr);
- state = ptr.p->m_state;
- }
-
- const Page_state LOCKED = Page_entry::LOCKED | Page_entry::MAPPED;
- if ((state & LOCKED) == LOCKED &&
- ! (req_flags & Page_request::UNLOCK_PAGE))
- {
- ptr.p->m_state |= (req_flags & DIRTY_FLAGS ? Page_entry::DIRTY : 0);
- if (ptr.p->m_copy_page_i != RNIL)
- {
- return ptr.p->m_copy_page_i;
- }
-
- return ptr.p->m_real_page_i;
- }
-
- bool only_request = ptr.p->m_requests.isEmpty();
-#ifdef ERROR_INSERT
- if (req_flags & Page_request::DELAY_REQ)
- {
- jam();
- only_request = false;
- }
-#endif
- if (only_request &&
- state & Page_entry::MAPPED)
- {
- if (! (state & Page_entry::PAGEOUT))
- {
- if (req_flags & DIRTY_FLAGS)
- state |= Page_entry::DIRTY;
-
- ptr.p->m_busy_count += busy_count;
- set_page_state(ptr, state);
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: <get_page: immediate" << endl;
-#endif
-
- ndbrequire(ptr.p->m_real_page_i != RNIL);
- return ptr.p->m_real_page_i;
- }
- }
-
- if (! (req_flags & (Page_request::LOCK_PAGE | Page_request::UNLOCK_PAGE)))
- {
- ndbrequire(! (state & Page_entry::LOCKED));
- }
-
- // queue the request
- Ptr<Pgman::Page_request> req_ptr;
- {
- Local_page_request_list req_list(m_page_request_pool, ptr.p->m_requests);
- if (! (req_flags & Page_request::ALLOC_REQ))
- req_list.seizeLast(req_ptr);
- else
- req_list.seizeFirst(req_ptr);
- }
-
- if (req_ptr.i == RNIL)
- {
- if (is_new)
- {
- release_page_entry(ptr);
- }
- return -1;
- }
-
- req_ptr.p->m_block = page_req.m_block;
- req_ptr.p->m_flags = page_req.m_flags;
- req_ptr.p->m_callback = page_req.m_callback;
-#ifdef ERROR_INSERT
- req_ptr.p->m_delay_until_time = page_req.m_delay_until_time;
-#endif
-
- state |= Page_entry::REQUEST;
- if (only_request && (req_flags & Page_request::EMPTY_PAGE))
- {
- state |= Page_entry::EMPTY;
- }
-
- if (req_flags & Page_request::UNLOCK_PAGE)
- {
- // keep it locked
- }
-
- ptr.p->m_busy_count += busy_count;
- ptr.p->m_dirty_count += !!(req_flags & DIRTY_FLAGS);
- set_page_state(ptr, state);
-
- do_busy_loop(signal, true);
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << req_ptr << endl;
- debugOut << "PGMAN: <get_page: queued" << endl;
-#endif
- return 0;
-}
-
-void
-Pgman::update_lsn(Ptr<Page_entry> ptr, Uint32 block, Uint64 lsn)
-{
- jamEntry();
-#ifdef VM_TRACE
- const char* bname = getBlockName(block, "?");
- debugOut << "PGMAN: >update_lsn: block=" << bname << " lsn=" << lsn << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
-
- Page_state state = ptr.p->m_state;
- ptr.p->m_lsn = lsn;
-
- if (state & Page_entry::BUSY)
- {
- ndbrequire(ptr.p->m_busy_count != 0);
- if (--ptr.p->m_busy_count == 0)
- {
- state &= ~ Page_entry::BUSY;
- }
- }
-
- state |= Page_entry::DIRTY;
- set_page_state(ptr, state);
-
-#ifdef VM_TRACE
- debugOut << "PGMAN: " << ptr << endl;
- debugOut << "PGMAN: <update_lsn" << endl;
-#endif
-}
-
-Uint32
-Pgman::create_data_file()
-{
- File_map::DataBufferIterator it;
- if(m_file_map.first(it))
- {
- do
- {
- if(*it.data == RNIL)
- {
- *it.data = (1u << 31) | it.pos;
- return it.pos;
- }
- } while(m_file_map.next(it));
- }
-
- Uint32 file_no = m_file_map.getSize();
- Uint32 fd = (1u << 31) | file_no;
-
- if (m_file_map.append(&fd, 1))
- {
- return file_no;
- }
- return RNIL;
-}
-
-Uint32
-Pgman::alloc_data_file(Uint32 file_no)
-{
- Uint32 sz = m_file_map.getSize();
- if (file_no >= sz)
- {
- Uint32 len = file_no - sz + 1;
- Uint32 fd = RNIL;
- while (len--)
- {
- if (! m_file_map.append(&fd, 1))
- return RNIL;
- }
- }
-
- File_map::DataBufferIterator it;
- m_file_map.first(it);
- m_file_map.next(it, file_no);
- if (* it.data != RNIL)
- return RNIL;
-
- *it.data = (1u << 31) | file_no;
- return file_no;
-}
-
-void
-Pgman::map_file_no(Uint32 file_no, Uint32 fd)
-{
- File_map::DataBufferIterator it;
- m_file_map.first(it);
- m_file_map.next(it, file_no);
-
- assert(*it.data == ((1u << 31) | file_no));
- *it.data = fd;
-}
-
-void
-Pgman::free_data_file(Uint32 file_no, Uint32 fd)
-{
- File_map::DataBufferIterator it;
- m_file_map.first(it);
- m_file_map.next(it, file_no);
-
- if (fd == RNIL)
- {
- ndbrequire(*it.data == ((1u << 31) | file_no));
- }
- else
- {
- ndbrequire(*it.data == fd);
- }
- *it.data = RNIL;
-}
-
-int
-Pgman::drop_page(Ptr<Page_entry> ptr)
-{
-#ifdef VM_TRACE
- debugOut << "PGMAN: drop_page" << endl;
- debugOut << "PGMAN: " << ptr << endl;
-#endif
-
- Page_stack& pl_stack = m_page_stack;
- Page_queue& pl_queue = m_page_queue;
-
- Page_state state = ptr.p->m_state;
- if (! (state & (Page_entry::PAGEIN | Page_entry::PAGEOUT)))
- {
- ndbrequire(state & Page_entry::BOUND);
- ndbrequire(state & Page_entry::MAPPED);
-
- if (state & Page_entry::ONSTACK)
- {
- jam();
- bool at_bottom = ! pl_stack.hasPrev(ptr);
- pl_stack.remove(ptr);
- state &= ~ Page_entry::ONSTACK;
- if (at_bottom)
- {
- jam();
- ndbassert(state & Page_entry::HOT);
- lirs_stack_prune();
- }
- }
-
- if (state & Page_entry::ONQUEUE)
- {
- jam();
- pl_queue.remove(ptr);
- state &= ~ Page_entry::ONQUEUE;
- }
-
- ndbassert(ptr.p->m_real_page_i != RNIL);
- if (ptr.p->m_real_page_i != RNIL)
- {
- jam();
- release_cache_page(ptr.p->m_real_page_i);
- ptr.p->m_real_page_i = RNIL;
- }
-
- set_page_state(ptr, state);
- release_page_entry(ptr);
- return 1;
- }
-
- ndbrequire(false);
- return -1;
-}
-
-// debug
-
-#ifdef VM_TRACE
-
-void
-Pgman::verify_page_entry(Ptr<Page_entry> ptr)
-{
- Uint32 ptrI = ptr.i;
- Page_state state = ptr.p->m_state;
-
- bool has_req = state & Page_entry::REQUEST;
- bool has_req2 = ! ptr.p->m_requests.isEmpty();
- ndbrequire(has_req == has_req2 || dump_page_lists(ptrI));
-
- bool is_bound = state & Page_entry::BOUND;
- bool is_bound2 = ptr.p->m_real_page_i != RNIL;
- ndbrequire(is_bound == is_bound2 || dump_page_lists(ptrI));
-
- bool is_mapped = state & Page_entry::MAPPED;
- // mapped implies bound
- ndbrequire(! is_mapped || is_bound || dump_page_lists(ptrI));
- // bound is mapped or has open requests
- ndbrequire(! is_bound || is_mapped || has_req || dump_page_lists(ptrI));
-
- bool on_stack = state & Page_entry::ONSTACK;
- bool is_hot = state & Page_entry::HOT;
- // hot entry must be on stack
- ndbrequire(! is_hot || on_stack || dump_page_lists(ptrI));
-
- bool on_queue = state & Page_entry::ONQUEUE;
- // hot entry is not on queue
- ndbrequire(! is_hot || ! on_queue || dump_page_lists(ptrI));
-
- bool is_locked = state & Page_entry::LOCKED;
- bool on_queue2 = ! is_locked && ! is_hot && is_bound;
- ndbrequire(on_queue == on_queue2 || dump_page_lists(ptrI));
-
- // entries waiting to enter queue
- bool to_queue = ! is_locked && ! is_hot && ! is_bound && has_req;
-
- // page is either LOCKED or under LIRS
- bool is_lirs = on_stack || to_queue || on_queue;
- ndbrequire(is_locked == ! is_lirs || dump_page_lists(ptrI));
-
- bool pagein = state & Page_entry::PAGEIN;
- bool pageout = state & Page_entry::PAGEOUT;
- // cannot read and write at same time
- ndbrequire(! pagein || ! pageout || dump_page_lists(ptrI));
-
- Uint32 no = get_sublist_no(state);
- switch (no) {
- case Page_entry::SL_BIND:
- ndbrequire(! pagein && ! pageout || dump_page_lists(ptrI));
- break;
- case Page_entry::SL_MAP:
- ndbrequire(! pagein && ! pageout || dump_page_lists(ptrI));
- break;
- case Page_entry::SL_MAP_IO:
- ndbrequire(pagein && ! pageout || dump_page_lists(ptrI));
- break;
- case Page_entry::SL_CALLBACK:
- ndbrequire(! pagein && ! pageout || dump_page_lists(ptrI));
- break;
- case Page_entry::SL_CALLBACK_IO:
- ndbrequire(! pagein && pageout || dump_page_lists(ptrI));
- break;
- case Page_entry::SL_BUSY:
- break;
- case Page_entry::SL_LOCKED:
- break;
- case Page_entry::SL_IDLE:
- break;
- case Page_entry::SL_OTHER:
- break;
- default:
- ndbrequire(false || dump_page_lists(ptrI));
- break;
- }
-}
-
-void
-Pgman::verify_page_lists()
-{
- Page_hashlist& pl_hash = m_page_hashlist;
- Page_stack& pl_stack = m_page_stack;
- Page_queue& pl_queue = m_page_queue;
- Ptr<Page_entry> ptr;
-
- Uint32 stack_count = 0;
- Uint32 queue_count = 0;
- Uint32 queuewait_count = 0;
- Uint32 locked_bound_count = 0;
-
- Page_hashlist::Iterator iter;
- pl_hash.next(0, iter);
- while (iter.curr.i != RNIL)
- {
- verify_page_entry(iter.curr);
-
- Page_state state = iter.curr.p->m_state;
- if (state & Page_entry::ONSTACK)
- stack_count++;
- if (state & Page_entry::ONQUEUE)
- queue_count++;
- if (! (state & Page_entry::LOCKED) &&
- ! (state & Page_entry::HOT) &&
- (state & Page_entry::REQUEST) &&
- ! (state & Page_entry::BOUND))
- queuewait_count++;
- if (state & Page_entry::LOCKED &&
- state & Page_entry::BOUND)
- locked_bound_count++;
- pl_hash.next(iter);
- }
-
- ndbrequire(stack_count == pl_stack.count() || dump_page_lists());
- ndbrequire(queue_count == pl_queue.count() || dump_page_lists());
-
- Uint32 hot_count = 0;
- Uint32 hot_bound_count = 0;
- Uint32 cold_bound_count = 0;
- Uint32 stack_request_count = 0;
- Uint32 queue_request_count = 0;
-
- Uint32 i1 = RNIL;
- for (pl_stack.first(ptr); ptr.i != RNIL; pl_stack.next(ptr))
- {
- ndbrequire(i1 != ptr.i);
- i1 = ptr.i;
- Page_state state = ptr.p->m_state;
- ndbrequire(state & Page_entry::ONSTACK || dump_page_lists());
- if (! pl_stack.hasPrev(ptr))
- ndbrequire(state & Page_entry::HOT || dump_page_lists());
- if (state & Page_entry::HOT) {
- hot_count++;
- if (state & Page_entry::BOUND)
- hot_bound_count++;
- }
- if (state & Page_entry::REQUEST)
- stack_request_count++;
- }
-
- Uint32 i2 = RNIL;
- for (pl_queue.first(ptr); ptr.i != RNIL; pl_queue.next(ptr))
- {
- ndbrequire(i2 != ptr.i);
- i2 = ptr.i;
- Page_state state = ptr.p->m_state;
- ndbrequire(state & Page_entry::ONQUEUE || dump_page_lists());
- ndbrequire(state & Page_entry::BOUND || dump_page_lists());
- cold_bound_count++;
- if (state & Page_entry::REQUEST)
- queue_request_count++;
- }
-
- Uint32 tot_bound_count =
- locked_bound_count + hot_bound_count + cold_bound_count;
- ndbrequire(m_stats.m_num_pages == tot_bound_count || dump_page_lists());
-
- Uint32 k;
- Uint32 entry_count = 0;
-
- for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
- {
- const Page_sublist& pl = *m_page_sublist[k];
- for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
- {
- ndbrequire(get_sublist_no(ptr.p->m_state) == k || dump_page_lists());
- entry_count++;
- }
- }
-
- ndbrequire(entry_count == pl_hash.count() || dump_page_lists());
-
- debugOut << "PGMAN: loop"
- << " stats=" << m_stats_loop_on
- << " busy=" << m_busy_loop_on
- << " cleanup=" << m_cleanup_loop_on
- << " lcp=" << m_lcp_loop_on << endl;
-
- debugOut << "PGMAN:"
- << " entry:" << pl_hash.count()
- << " cache:" << m_stats.m_num_pages
- << "(" << locked_bound_count << "L)"
- << " stack:" << pl_stack.count()
- << " hot:" << hot_count
- << " hot_bound:" << hot_bound_count
- << " stack_request:" << stack_request_count
- << " queue:" << pl_queue.count()
- << " queue_request:" << queue_request_count
- << " queuewait:" << queuewait_count << endl;
-
- debugOut << "PGMAN:";
- for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
- {
- const Page_sublist& pl = *m_page_sublist[k];
- debugOut << " " << get_sublist_name(k) << ":" << pl.count();
- }
- debugOut << endl;
-}
-
-void
-Pgman::verify_all()
-{
- Page_sublist& pl_bind = *m_page_sublist[Page_entry::SL_BIND];
- Page_sublist& pl_map = *m_page_sublist[Page_entry::SL_MAP];
- Page_sublist& pl_callback = *m_page_sublist[Page_entry::SL_CALLBACK];
-
- if (! pl_bind.isEmpty() || ! pl_map.isEmpty() || ! pl_callback.isEmpty())
- {
- ndbrequire(m_busy_loop_on || dump_page_lists());
- }
- verify_page_lists();
-}
-
-bool
-Pgman::dump_page_lists(Uint32 ptrI)
-{
- if (! debugFlag)
- open_debug_file(1);
-
- debugOut << "PGMAN: page list dump" << endl;
- if (ptrI != RNIL)
- debugOut << "PGMAN: error on PE [" << ptrI << "]" << endl;
-
- Page_hashlist& pl_hash = m_page_hashlist;
- Page_stack& pl_stack = m_page_stack;
- Page_queue& pl_queue = m_page_queue;
- Ptr<Page_entry> ptr;
- Uint32 n;
- char buf[40];
-
- debugOut << "hash:" << endl;
- Page_hashlist::Iterator iter;
- pl_hash.next(0, iter);
- n = 0;
- while (iter.curr.i != RNIL)
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << iter.curr << endl;
- pl_hash.next(iter);
- }
-
- debugOut << "stack:" << endl;
- n = 0;
- for (pl_stack.first(ptr); ptr.i != RNIL; pl_stack.next(ptr))
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << ptr << endl;
- }
-
- debugOut << "queue:" << endl;
- n = 0;
- for (pl_queue.first(ptr); ptr.i != RNIL; pl_queue.next(ptr))
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << ptr << endl;
- }
-
- Uint32 k;
- for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
- {
- debugOut << get_sublist_name(k) << ":" << endl;
- const Page_sublist& pl = *m_page_sublist[k];
- for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << ptr << endl;
- }
- }
-
- if (! debugFlag)
- open_debug_file(0);
-
- return false;
-}
-
-#endif
-
-const char*
-Pgman::get_sublist_name(Uint32 list_no)
-{
- switch (list_no) {
- case Page_entry::SL_BIND:
- return "bind";
- case Page_entry::SL_MAP:
- return "map";
- case Page_entry::SL_MAP_IO:
- return "map_io";
- case Page_entry::SL_CALLBACK:
- return "callback";
- case Page_entry::SL_CALLBACK_IO:
- return "callback_io";
- case Page_entry::SL_BUSY:
- return "busy";
- case Page_entry::SL_LOCKED:
- return "locked";
- case Page_entry::SL_IDLE:
- return "idle";
- case Page_entry::SL_OTHER:
- return "other";
- }
- return "?";
-}
-
-NdbOut&
-operator<<(NdbOut& out, Ptr<Pgman::Page_request> ptr)
-{
- const Pgman::Page_request& pr = *ptr.p;
- const char* bname = getBlockName(pr.m_block, "?");
- out << "PR";
- if (ptr.i != RNIL)
- out << " [" << dec << ptr.i << "]";
- out << " block=" << bname;
- out << " flags=" << hex << pr.m_flags;
- out << "," << dec << (pr.m_flags & Pgman::Page_request::OP_MASK);
- {
- if (pr.m_flags & Pgman::Page_request::LOCK_PAGE)
- out << ",lock_page";
- if (pr.m_flags & Pgman::Page_request::EMPTY_PAGE)
- out << ",empty_page";
- if (pr.m_flags & Pgman::Page_request::ALLOC_REQ)
- out << ",alloc_req";
- if (pr.m_flags & Pgman::Page_request::COMMIT_REQ)
- out << ",commit_req";
- if (pr.m_flags & Pgman::Page_request::DIRTY_REQ)
- out << ",dirty_req";
- if (pr.m_flags & Pgman::Page_request::CORR_REQ)
- out << ",corr_req";
- }
- return out;
-}
-
-NdbOut&
-operator<<(NdbOut& out, Ptr<Pgman::Page_entry> ptr)
-{
- const Pgman::Page_entry pe = *ptr.p;
- Uint32 list_no = Pgman::get_sublist_no(pe.m_state);
- out << "PE [" << dec << ptr.i << "]";
- out << " state=" << hex << pe.m_state;
- {
- if (pe.m_state & Pgman::Page_entry::REQUEST)
- out << ",request";
- if (pe.m_state & Pgman::Page_entry::EMPTY)
- out << ",empty";
- if (pe.m_state & Pgman::Page_entry::BOUND)
- out << ",bound";
- if (pe.m_state & Pgman::Page_entry::MAPPED)
- out << ",mapped";
- if (pe.m_state & Pgman::Page_entry::DIRTY)
- out << ",dirty";
- if (pe.m_state & Pgman::Page_entry::USED)
- out << ",used";
- if (pe.m_state & Pgman::Page_entry::BUSY)
- out << ",busy";
- if (pe.m_state & Pgman::Page_entry::LOCKED)
- out << ",locked";
- if (pe.m_state & Pgman::Page_entry::PAGEIN)
- out << ",pagein";
- if (pe.m_state & Pgman::Page_entry::PAGEOUT)
- out << ",pageout";
- if (pe.m_state & Pgman::Page_entry::LOGSYNC)
- out << ",logsync";
- if (pe.m_state & Pgman::Page_entry::LCP)
- out << ",lcp";
- if (pe.m_state & Pgman::Page_entry::HOT)
- out << ",hot";
- if (pe.m_state & Pgman::Page_entry::ONSTACK)
- out << ",onstack";
- if (pe.m_state & Pgman::Page_entry::ONQUEUE)
- out << ",onqueue";
- }
- out << " list=";
- if (list_no == ZNIL)
- out << "NONE";
- else
- {
- out << dec << list_no;
- out << "," << Pgman::get_sublist_name(list_no);
- }
- out << " diskpage=" << dec << pe.m_file_no << "," << pe.m_page_no;
- if (pe.m_real_page_i == RNIL)
- out << " realpage=RNIL";
- else
- out << " realpage=" << dec << pe.m_real_page_i;
- out << " lsn=" << dec << pe.m_lsn;
- out << " busy_count=" << dec << pe.m_busy_count;
-#ifdef VM_TRACE
- {
- Pgman::Page_stack& pl_stack = pe.m_this->m_page_stack;
- if (! pl_stack.hasNext(ptr))
- out << " top";
- if (! pl_stack.hasPrev(ptr))
- out << " bottom";
- }
- {
- Pgman::Local_page_request_list
- req_list(ptr.p->m_this->m_page_request_pool, ptr.p->m_requests);
- if (! req_list.isEmpty())
- {
- Ptr<Pgman::Page_request> req_ptr;
- out << " req:";
- for (req_list.first(req_ptr); req_ptr.i != RNIL; req_list.next(req_ptr))
- {
- out << " " << req_ptr;
- }
- }
- }
-#endif
- return out;
-}
-
-#ifdef VM_TRACE
-void
-Pgman::open_debug_file(Uint32 flag)
-{
- if (flag)
- {
- FILE* f = globalSignalLoggers.getOutputStream();
- debugOut = *new NdbOut(*new FileOutputStream(f));
- }
- else
- {
- debugOut = *new NdbOut(*new NullOutputStream());
- }
-}
-#endif
-
-void
-Pgman::execDUMP_STATE_ORD(Signal* signal)
-{
- jamEntry();
- Page_hashlist& pl_hash = m_page_hashlist;
-#ifdef VM_TRACE
- if (signal->theData[0] == 11000 && signal->getLength() == 2)
- {
- Uint32 flag = signal->theData[1];
- open_debug_file(flag);
- debugFlag = flag;
- }
-#endif
-
- if (signal->theData[0] == 11001)
- {
- // XXX print hash list if no sublist
- Uint32 list = 0;
- if (signal->getLength() > 1)
- list = signal->theData[1];
-
- Page_sublist& pl = *m_page_sublist[list];
- Ptr<Page_entry> ptr;
-
- for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
- {
- ndbout << ptr << endl;
- infoEvent(" PE [ file: %d page: %d ] state: %x lsn: %lld lcp: %d busy: %d req-list: %d",
- ptr.p->m_file_no, ptr.p->m_page_no,
- ptr.p->m_state, ptr.p->m_lsn, ptr.p->m_last_lcp,
- ptr.p->m_busy_count,
- !ptr.p->m_requests.isEmpty());
- }
- }
-
- if (signal->theData[0] == 11002 && signal->getLength() == 3)
- {
- Page_entry key;
- key.m_file_no = signal->theData[1];
- key.m_page_no = signal->theData[2];
-
- Ptr<Page_entry> ptr;
- if (pl_hash.find(ptr, key))
- {
- ndbout << "pageout " << ptr << endl;
- c_tup->disk_page_unmap_callback(0,
- ptr.p->m_real_page_i,
- ptr.p->m_dirty_count);
- pageout(signal, ptr);
- }
- }
-
-
- if (signal->theData[0] == 11003)
- {
-#ifdef VM_TRACE
- verify_page_lists();
- dump_page_lists();
-#else
- ndbout << "Only in VM_TRACE builds" << endl;
-#endif
- }
-
- if (signal->theData[0] == 11004)
- {
- ndbout << "Dump LCP bucket m_lcp_outstanding: " << m_lcp_outstanding;
- if (m_lcp_curr_bucket != ~(Uint32)0)
- {
- Page_hashlist::Iterator iter;
- pl_hash.next(m_lcp_curr_bucket, iter);
-
- ndbout_c(" %d", m_lcp_curr_bucket);
-
- while (iter.curr.i != RNIL && iter.bucket == m_lcp_curr_bucket)
- {
- Ptr<Page_entry>& ptr = iter.curr;
- ndbout << ptr << endl;
- pl_hash.next(iter);
- }
-
- ndbout_c("-- done");
- }
- else
- {
- ndbout_c(" == ~0");
- }
- }
-
- if (signal->theData[0] == 11005)
- {
- g_dbg_lcp = ~g_dbg_lcp;
- }
-
- if (signal->theData[0] == 11006)
- {
- SET_ERROR_INSERT_VALUE(11006);
- }
-
- if (signal->theData[0] == 11007)
- {
- SET_ERROR_INSERT_VALUE(11007);
- }
-
- if (signal->theData[0] == 11008)
- {
- SET_ERROR_INSERT_VALUE(11008);
- }
-}
-
-// page cache client
-
-Page_cache_client::Page_cache_client(SimulatedBlock* block, Pgman* pgman)
-{
- m_block = block->number();
- m_pgman = pgman;
-}
diff --git a/storage/ndb/src/kernel/blocks/pgman.hpp b/storage/ndb/src/kernel/blocks/pgman.hpp
deleted file mode 100644
index aaff8ca03c4..00000000000
--- a/storage/ndb/src/kernel/blocks/pgman.hpp
+++ /dev/null
@@ -1,682 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef PGMAN_H
-#define PGMAN_H
-
-#include <SimulatedBlock.hpp>
-
-#include <DLCHashTable.hpp>
-#include <DLCFifoList.hpp>
-#include <NodeBitmask.hpp>
-#include <signaldata/LCP.hpp>
-#include "lgman.hpp"
-
-#include <NdbOut.hpp>
-#include <OutputStream.hpp>
-
-/*
- * PGMAN
- *
- * PAGE ENTRIES AND REQUESTS
- *
- * Central structure is "page entry". It corresponds to a disk page
- * identified by file and page number (file_no, page_no).
- *
- * A page entry is created by first request for the disk page.
- * Subsequent requests are queued under the same page entry.
- *
- * There is a limited number of in-memory "cache pages", also called
- * "buffer pages" or "real pages". These are used by the more numerous
- * page entries to buffer the disk pages.
- *
- * A new or non-resident page entry must first be "bound" to an
- * available cache page. Next the disk page must be "mapped" to the
- * cache page. If the page is empty (never written) it is considered
- * mapped trivially. Otherwise the cache page must be updated via
- * "pagein" from disk. A bound and mapped page is called "resident".
- *
- * Updating a resident cache page makes it "dirty". A background
- * clean-up process makes dirty pages "clean" via "pageout" to disk.
- * Write ahead logging (WAL) of the page is done first i.e. UNDO log is
- * flushed up to the page log sequence number (LSN) by calling a TSMAN
- * method. The reason for this is obvious but not relevant to PGMAN.
- *
- * A local check point (LCP) periodically performs a complete pageout of
- * dirty pages. It must iterate over a list which will cover all pages
- * which had been dirty since LCP start.
- *
- * A clean page is a candidate ("victim") for being "unmapped" and
- * "evicted" from the cache, to allow another page to become resident.
- * This process is called "page replacement".
- *
- * PAGE REPLACEMENT
- *
- * Page replacement uses the LIRS algorithm (Jiang-Zhang).
- *
- * The "recency" of a page is the time between now and the last request
- * for the page. The "inter-reference recency" (IRR) of a page is the
- * time between the last 2 requests for the page. "Time" is advanced by
- * request for any page.
- *
- * Page entries are divided into "hot" ("lir") and "cold" ("hir"). Here
- * lir/hir refers to low/high IRR. Hot pages are always resident but
- * cold pages need not be.
- *
- * Number of hot pages is limited to slightly less than number of cache
- * pages. Until this number is reached, all used cache pages are hot.
- * Then the algorithm described next is applied. The algorithm avoids
- * storing any of the actual recency values.
- *
- * Primary data structure is the "stack". It contains all hot entries
- * and recently referenced cold entries (resident or not). The stack is
- * in recency order with most recent (lowest recency) entry on top.
- * Entries which are less recent than the least recent hot page are
- * removed ("stack pruning"). So the bottom page is always hot.
- *
- * The cold entries on the stack are undergoing a "trial period". If
- * they are referenced soon again (see IRR), they become hot. Otherwise
- * they fall off the bottom of the stack.
- *
- * Secondary data structure is the "queue". It contains all resident
- * cold pages (on stack or not). When a hot page is removed from the
- * stack it is added to the end of the queue. When page replacement
- * needs a page it removes it from the front of the queue.
- *
- * Page requests cause the input entry to be inserted and updated in
- * LIRS lists. Remember that an entry can be present on both stack and
- * queue. The rules per type of input entry are:
- *
- * 1. Hot. Move input entry to stack top. If input entry was at stack
- * bottom, do stack pruning.
- *
- * 2. Cold resident. Move input entry to stack top. Then:
- *
- * 2a. If input entry was on stack, change it to hot, remove it from
- * queue, change stack bottom entry to cold and move the bottom entry to
- * queue end, and do stack pruning.
- *
- * 2b. If input entry was on queue only, leave it cold but move it to
- * end of queue.
- *
- * 3. Cold non-resident. Remove entry at queue front and evict it from
- * the cache. If the evicted entry was on stack, it remains as unbound
- * entry on stack, to continue its trial period. Map input entry to the
- * freed cache page. Move input entry to stack top. Then:
- *
- * 3a. If input entry was on stack, change it to hot, change stack
- * bottom entry to cold and move the bottom entry to queue end, and do
- * stack pruning.
- *
- * 3b. If input entry was new, leave it cold but move it to end of
- * queue.
- *
- * LIRS CHANGES
- *
- * In LIRS the 'resident' requirement is changed as follows:
- *
- * Stack entries, including hot ones, can have any state. Unbound stack
- * entries are created by new requests and by pages evicted from queue
- * front which are still on stack.
- *
- * Queue entries must be bound. They become resident and evictable
- * within a finite time. A page is "evictable" if it is mapped, clean,
- * and has no requests.
- *
- * An unbound entry which should be on queue is added there at bind
- * time. Such entries are created when an unbound entry with open
- * requests is popped (hot) or pruned (cold) from the stack. This can
- * happen if the cache is too small.
- *
- * CLEANUP PROCESS
- *
- * LIRS (and related algorithms) do not address dirty pages. From above
- * it is obvious that the clean-up process should process dirty queue
- * entries proceeding from front to end. This also favors pages with
- * lower LSN numbers which minimizes amount of WAL to write.
- *
- * In fact the clean-up process holds a permanent pointer into the queue
- * where all entries strictly towards the front are clean. For such an
- * entry to become dirty it must be referenced again which moves it to
- * queue end and past the clean-up pointer. (In practice, until this
- * works, cleanup recycles back to queue front).
- *
- * PAGE LISTS
- *
- * Page entries are put on a number of lists.
- *
- * 1. Hash table on (file_no, page_no). Used for fast lookup and for
- * LCP to iterate over.
- *
- * The other lists are doubly-linked FIFOs. In general entries are
- * added to the end (last entry) and processed from the front (first
- * entry). When used as stack, end is top and front is bottom.
- *
- * 2. The LIRS stack and queue. These control page replacement.
- *
- * 3. Page entries are divided into disjoint "sublists" based on page
- * "state" i.e. the set of page properties. Some sublists drive page
- * processing and have next entry to process at the front.
- *
- * Current sublists are as follows. Those that drive processing are
- * marked with a plus (+).
- *
- * SL_BIND + waiting for available buffer page
- * SL_MAP + waiting to start pagein from disk
- * SL_MAP_IO - above in i/o wait (the pagein)
- * SL_CALLBACK + request done, waiting to invoke callbacks
- * SL_CALLBACK_IO - above in i/o wait (pageout by cleanup)
- * SL_BUSY - being written to by PGMAN client
- * SL_LOCKED - permanently locked to cache
- * SL_OTHER - default sublist
- *
- * PAGE PROCESSING
- *
- * Page processing uses a number independent continueB loops.
- *
- * 1. The "stats loop". Started at node start. Checks lists in debug
- * mode. In the future could gather statistics and adjust parameters
- * based on load. Continues via delay signal.
- *
- * 2. The "busy loop". Started by page request. Each loop does bind,
- * map, and callback of a number of entries. Continues via no-delay
- * signal until nothing to do.
- *
- * 3. The "cleanup loop". Started at node start. Each loop starts
- * pageout of a number of dirty queue entries. Continues via delay
- * signal.
- *
- * 4. The "LCP loop". Started periodically by NDB. Each loop starts
- * pageout of a number of hash list entries. Continues via delay signal
- * until done.
- *
- * SPECIAL CASES
- *
- * LOCKED pages are not put on stack or queue. They are flushed to disk
- * by LCP but not by clean-up.
- *
- * A TUP scan is likely to access a page repeatedly within a short time.
- * This can make the page hot when it should not be. Such "correlated
- * requests" are handled by a request flag which modifies default LIRS
- * processing. [fill in details later]
- *
- * Also PK operations make 2 rapid page references. The 2nd one is for
- * commit. This too should be handled as a correlated request.
- *
- * CLIENT TSMAN
- *
- * TSMAN reads "meta" pages such as extent headers. There are currently
- * "locked" forever in PGMAN cache.
- *
- * CLIENT DBTUP
- *
- * DBTUP works with copy pages (or UNDO buffers) in memory. The real
- * page is updated only between page request with COMMIT_REQ flag and
- * a subsequent LSN update. These need not occur in same timeslice
- * since DBTUP may need to flush UNDO log in-between.
- *
- * The page is "busy" if any transaction is between COMMIT_REQ and LSN
- * update. A busy page must be locked in buffer cache. No pageout of
- * a busy page can be started by clean-up or LCP.
- */
-
-class Pgman : public SimulatedBlock
-{
-public:
- Pgman(Block_context& ctx);
- virtual ~Pgman();
- BLOCK_DEFINES(Pgman);
-
-private:
- friend class Page_cache_client;
-
- struct Page_entry; // CC
- friend struct Page_entry;
-
- struct Page_request {
- enum Flags {
- OP_MASK = 0x000F // 4 bits for TUP operation
- ,LOCK_PAGE = 0x0020 // lock page in memory
- ,EMPTY_PAGE = 0x0040 // empty (new) page
- ,ALLOC_REQ = 0x0080 // part of alloc
- ,COMMIT_REQ = 0x0100 // part of commit
- ,DIRTY_REQ = 0x0200 // make page dirty wo/ update_lsn
- ,UNLOCK_PAGE = 0x0400
- ,CORR_REQ = 0x0800 // correlated request (no LIRS update)
-#ifdef ERROR_INSERT
- ,DELAY_REQ = 0x1000 // Force request to be delayed
-#endif
- };
-
- Uint16 m_block;
- Uint16 m_flags;
- SimulatedBlock::Callback m_callback;
-
-#ifdef ERROR_INSERT
- Uint64 m_delay_until_time;
-#endif
- Uint32 nextList;
- Uint32 m_magic;
- };
-
- typedef RecordPool<Page_request, WOPool> Page_request_pool;
- typedef SLFifoListImpl<Page_request_pool, Page_request> Page_request_list;
- typedef LocalSLFifoListImpl<Page_request_pool, Page_request> Local_page_request_list;
-
- struct Page_entry_stack_ptr {
- Uint32 nextList;
- Uint32 prevList;
- };
-
- struct Page_entry_queue_ptr {
- Uint32 nextList;
- Uint32 prevList;
- };
-
- struct Page_entry_sublist_ptr {
- Uint32 nextList;
- Uint32 prevList;
- };
-
- typedef Uint16 Page_state;
-
- struct Page_entry : Page_entry_stack_ptr,
- Page_entry_queue_ptr,
- Page_entry_sublist_ptr {
- Page_entry() {}
- Page_entry(Uint32 file_no, Uint32 page_no);
-
- enum State {
- NO_STATE = 0x0000
- ,REQUEST = 0x0001 // has outstanding request
- ,EMPTY = 0x0002 // empty (never written) page
- ,BOUND = 0x0004 // m_real_page_ptr assigned
- ,MAPPED = 0x0008 // bound, and empty or paged in
- ,DIRTY = 0x0010 // page is modified
- ,USED = 0x0020 // used by some tx (not set currently)
- ,BUSY = 0x0040 // page is being written to
- ,LOCKED = 0x0080 // locked in cache (forever)
- ,PAGEIN = 0x0100 // paging in
- ,PAGEOUT = 0x0200 // paging out
- ,LOGSYNC = 0x0400 // undo WAL as part of pageout
- ,LCP = 0x1000 // page is LCP flushed
- ,HOT = 0x2000 // page is hot
- ,ONSTACK = 0x4000 // page is on LIRS stack
- ,ONQUEUE = 0x8000 // page is on LIRS queue
- };
-
- enum Sublist {
- SL_BIND = 0
- ,SL_MAP = 1
- ,SL_MAP_IO = 2
- ,SL_CALLBACK = 3
- ,SL_CALLBACK_IO = 4
- ,SL_BUSY = 5
- ,SL_LOCKED = 6
- ,SL_IDLE = 7
- ,SL_OTHER = 8
- ,SUBLIST_COUNT = 9
- };
-
- Uint16 m_file_no; // disk page address set at seize
- Page_state m_state; // flags (0 for new entry)
-
- Uint32 m_page_no;
- Uint32 m_real_page_i;
- Uint64 m_lsn;
-
- Uint32 m_last_lcp;
- Uint32 m_dirty_count;
- Uint32 m_copy_page_i;
- union {
- Uint32 m_busy_count; // non-zero means BUSY
- Uint32 nextPool;
- };
-
- Page_request_list::Head m_requests;
-
- Uint32 nextHash;
- Uint32 prevHash;
-
- Uint32 hashValue() const { return m_file_no << 16 | m_page_no; }
- bool equal(const Page_entry& obj) const {
- return
- m_file_no == obj.m_file_no && m_page_no == obj.m_page_no;
- }
-
-#ifdef VM_TRACE
- Pgman* m_this;
-#endif
- };
-
- typedef DLCHashTable<Page_entry> Page_hashlist;
- typedef DLCFifoList<Page_entry, Page_entry_stack_ptr> Page_stack;
- typedef DLCFifoList<Page_entry, Page_entry_queue_ptr> Page_queue;
- typedef DLCFifoList<Page_entry, Page_entry_sublist_ptr> Page_sublist;
-
- class Dbtup *c_tup;
- Logfile_client m_lgman;
-
- // loop status
- bool m_stats_loop_on;
- bool m_busy_loop_on;
- bool m_cleanup_loop_on;
- bool m_lcp_loop_on;
-
- // LCP variables
- Uint32 m_last_lcp;
- Uint32 m_last_lcp_complete;
- Uint32 m_lcp_curr_bucket;
- Uint32 m_lcp_outstanding; // remaining i/o waits
- EndLcpReq m_end_lcp_req;
-
- // clean-up variables
- Ptr<Page_entry> m_cleanup_ptr;
-
- // file map
- typedef DataBuffer<15> File_map;
- File_map m_file_map;
- File_map::DataBufferPool m_data_buffer_pool;
-
- // page entries and requests
- Page_request_pool m_page_request_pool;
- ArrayPool<Page_entry> m_page_entry_pool;
- Page_hashlist m_page_hashlist;
- Page_stack m_page_stack;
- Page_queue m_page_queue;
- Page_sublist* m_page_sublist[Page_entry::SUBLIST_COUNT];
-
- // configuration
- struct Param {
- Param();
- Uint32 m_max_pages; // max number of cache pages
- Uint32 m_lirs_stack_mult; // in m_max_pages (around 3-10)
- Uint32 m_max_hot_pages; // max hot cache pages (up to 99%)
- Uint32 m_max_loop_count; // limit purely local loops
- Uint32 m_max_io_waits;
- Uint32 m_stats_loop_delay;
- Uint32 m_cleanup_loop_delay;
- Uint32 m_lcp_loop_delay;
- } m_param;
-
- // runtime sizes and statistics
- struct Stats {
- Stats();
- Uint32 m_num_pages; // current number of cache pages
- Uint32 m_page_hits;
- Uint32 m_page_faults;
- Uint32 m_current_io_waits;
- } m_stats;
-
-protected:
- void execSTTOR(Signal* signal);
- void sendSTTORRY(Signal*);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- void execLCP_FRAG_ORD(Signal*);
- void execEND_LCP_REQ(Signal*);
-
- void execFSREADCONF(Signal*);
- void execFSREADREF(Signal*);
- void execFSWRITECONF(Signal*);
- void execFSWRITEREF(Signal*);
-
- void execDUMP_STATE_ORD(Signal* signal);
-
-private:
- static Uint32 get_sublist_no(Page_state state);
- void set_page_state(Ptr<Page_entry> ptr, Page_state new_state);
-
- bool seize_cache_page(Ptr<GlobalPage>& gptr);
- void release_cache_page(Uint32 i);
-
- bool find_page_entry(Ptr<Page_entry>&, Uint32 file_no, Uint32 page_no);
- Uint32 seize_page_entry(Ptr<Page_entry>&, Uint32 file_no, Uint32 page_no);
- bool get_page_entry(Ptr<Page_entry>&, Uint32 file_no, Uint32 page_no);
- void release_page_entry(Ptr<Page_entry>&);
-
- void lirs_stack_prune();
- void lirs_stack_pop();
- void lirs_reference(Ptr<Page_entry> ptr);
-
- void do_stats_loop(Signal*);
- void do_busy_loop(Signal*, bool direct = false);
- void do_cleanup_loop(Signal*);
- void do_lcp_loop(Signal*, bool direct = false);
-
- bool process_bind(Signal*);
- bool process_bind(Signal*, Ptr<Page_entry> ptr);
- bool process_map(Signal*);
- bool process_map(Signal*, Ptr<Page_entry> ptr);
- bool process_callback(Signal*);
- bool process_callback(Signal*, Ptr<Page_entry> ptr);
-
- bool process_cleanup(Signal*);
- void move_cleanup_ptr(Ptr<Page_entry> ptr);
-
- bool process_lcp(Signal*);
- void process_lcp_locked(Signal* signal, Ptr<Page_entry> ptr);
- void process_lcp_locked_fswriteconf(Signal* signal, Ptr<Page_entry> ptr);
-
- void pagein(Signal*, Ptr<Page_entry>);
- void fsreadreq(Signal*, Ptr<Page_entry>);
- void fsreadconf(Signal*, Ptr<Page_entry>);
- void pageout(Signal*, Ptr<Page_entry>);
- void logsync_callback(Signal*, Uint32 ptrI, Uint32 res);
- void fswritereq(Signal*, Ptr<Page_entry>);
- void fswriteconf(Signal*, Ptr<Page_entry>);
-
- int get_page(Signal*, Ptr<Page_entry>, Page_request page_req);
- void update_lsn(Ptr<Page_entry>, Uint32 block, Uint64 lsn);
- Uint32 create_data_file();
- Uint32 alloc_data_file(Uint32 file_no);
- void map_file_no(Uint32 file_no, Uint32 fd);
- void free_data_file(Uint32 file_no, Uint32 fd = RNIL);
- int drop_page(Ptr<Page_entry>);
-
-#ifdef VM_TRACE
- NdbOut debugOut;
- bool debugFlag;
- void verify_page_entry(Ptr<Page_entry> ptr);
- void verify_page_lists();
- void verify_all();
- bool dump_page_lists(Uint32 ptrI = RNIL);
- void open_debug_file(Uint32 flag);
-#endif
- static const char* get_sublist_name(Uint32 list_no);
- friend class NdbOut& operator<<(NdbOut&, Ptr<Page_request>);
- friend class NdbOut& operator<<(NdbOut&, Ptr<Page_entry>);
-};
-
-class NdbOut& operator<<(NdbOut&, Ptr<Pgman::Page_request>);
-class NdbOut& operator<<(NdbOut&, Ptr<Pgman::Page_entry>);
-
-class Page_cache_client
-{
- Uint32 m_block;
- Pgman* m_pgman;
-
-public:
- Page_cache_client(SimulatedBlock* block, Pgman*);
-
- struct Request {
- Local_key m_page;
- SimulatedBlock::Callback m_callback;
-
-#ifdef ERROR_INSERT
- Uint64 m_delay_until_time;
-#endif
- };
-
- Ptr<GlobalPage> m_ptr; // TODO remove
-
- enum RequestFlags {
- LOCK_PAGE = Pgman::Page_request::LOCK_PAGE
- ,EMPTY_PAGE = Pgman::Page_request::EMPTY_PAGE
- ,ALLOC_REQ = Pgman::Page_request::ALLOC_REQ
- ,COMMIT_REQ = Pgman::Page_request::COMMIT_REQ
- ,DIRTY_REQ = Pgman::Page_request::DIRTY_REQ
- ,UNLOCK_PAGE = Pgman::Page_request::UNLOCK_PAGE
- ,CORR_REQ = Pgman::Page_request::CORR_REQ
-#ifdef ERROR_INSERT
- ,DELAY_REQ = Pgman::Page_request::DELAY_REQ
-#endif
- };
-
- /**
- * Get a page
- * @note This request may return true even if previous request
- * for same page return false, and it's callback has not been called
- * @return -1, on error
- * 0, request is queued
- * >0, real_page_id
- */
- int get_page(Signal*, Request&, Uint32 flags);
-
- void update_lsn(Local_key, Uint64 lsn);
-
- /**
- * Drop page
- *
- * @return -1 on error
- * 0 is request is queued
- * >0 is ok
- */
- int drop_page(Local_key, Uint32 page_id);
-
- /**
- * Create file record
- */
- Uint32 create_data_file();
-
- /**
- * Alloc datafile record
- */
- Uint32 alloc_data_file(Uint32 file_no);
-
- /**
- * Map file_no to m_fd
- */
- void map_file_no(Uint32 m_file_no, Uint32 m_fd);
-
- /**
- * Free file
- */
- void free_data_file(Uint32 file_no, Uint32 fd = RNIL);
-};
-
-inline int
-Page_cache_client::get_page(Signal* signal, Request& req, Uint32 flags)
-{
- Ptr<Pgman::Page_entry> entry_ptr;
- Uint32 file_no = req.m_page.m_file_no;
- Uint32 page_no = req.m_page.m_page_no;
-
-#ifdef VM_TRACE
- m_pgman->debugOut
- << "PGCLI: get_page " << file_no << "," << page_no
- << " flags=" << hex << flags << endl;
-#endif
-
- // find or seize
- bool ok = m_pgman->get_page_entry(entry_ptr, file_no, page_no);
- if (! ok)
- {
- return -1;
- }
-
- Pgman::Page_request page_req;
- page_req.m_block = m_block;
- page_req.m_flags = flags;
- page_req.m_callback = req.m_callback;
-#ifdef ERROR_INSERT
- page_req.m_delay_until_time = req.m_delay_until_time;
-#endif
-
- int i = m_pgman->get_page(signal, entry_ptr, page_req);
- if (i > 0)
- {
- // TODO remove
- m_pgman->m_global_page_pool.getPtr(m_ptr, (Uint32)i);
- }
- return i;
-}
-
-inline void
-Page_cache_client::update_lsn(Local_key key, Uint64 lsn)
-{
- Ptr<Pgman::Page_entry> entry_ptr;
- Uint32 file_no = key.m_file_no;
- Uint32 page_no = key.m_page_no;
-
-#ifdef VM_TRACE
- m_pgman->debugOut
- << "PGCLI: update_lsn " << file_no << "," << page_no
- << " lsn=" << lsn << endl;
-#endif
-
- bool found = m_pgman->find_page_entry(entry_ptr, file_no, page_no);
- assert(found);
-
- m_pgman->update_lsn(entry_ptr, m_block, lsn);
-}
-
-inline
-int
-Page_cache_client::drop_page(Local_key key, Uint32 page_id)
-{
- Ptr<Pgman::Page_entry> entry_ptr;
- Uint32 file_no = key.m_file_no;
- Uint32 page_no = key.m_page_no;
-
-#ifdef VM_TRACE
- m_pgman->debugOut
- << "PGCLI: drop_page " << file_no << "," << page_no << endl;
-#endif
-
- bool found = m_pgman->find_page_entry(entry_ptr, file_no, page_no);
- assert(found);
- assert(entry_ptr.p->m_real_page_i == page_id);
-
- return m_pgman->drop_page(entry_ptr);
-}
-
-inline Uint32
-Page_cache_client::create_data_file()
-{
- return m_pgman->create_data_file();
-}
-
-inline Uint32
-Page_cache_client::alloc_data_file(Uint32 file_no)
-{
- return m_pgman->alloc_data_file(file_no);
-}
-
-inline void
-Page_cache_client::map_file_no(Uint32 file_no, Uint32 fd)
-{
- m_pgman->map_file_no(file_no, fd);
-}
-
-inline void
-Page_cache_client::free_data_file(Uint32 file_no, Uint32 fd)
-{
- m_pgman->free_data_file(file_no, fd);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/print_file.cpp b/storage/ndb/src/kernel/blocks/print_file.cpp
deleted file mode 100644
index acaf9dd48e6..00000000000
--- a/storage/ndb/src/kernel/blocks/print_file.cpp
+++ /dev/null
@@ -1,417 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include <NdbOut.hpp>
-#include <UtilBuffer.hpp>
-#include "diskpage.hpp"
-#include <ndb_limits.h>
-#include <dbtup/tuppage.hpp>
-
-static void print_usage(const char*);
-static int print_zero_page(int, void *, Uint32 sz);
-static int print_extent_page(int, void*, Uint32 sz);
-static int print_undo_page(int, void*, Uint32 sz);
-static int print_data_page(int, void*, Uint32 sz);
-static bool print_page(int page_no)
-{
- return false;
-}
-
-int g_verbosity = 1;
-int g_page_size = File_formats::NDB_PAGE_SIZE;
-int (* g_print_page)(int count, void*, Uint32 sz) = print_zero_page;
-
-File_formats::Undofile::Zero_page g_uf_zero;
-File_formats::Datafile::Zero_page g_df_zero;
-
-int main(int argc, char ** argv)
-{
- for(int i = 1; i<argc; i++){
- if(!strncmp(argv[i], "-v", 2))
- {
- int pos= 2;
- do {
- g_verbosity++;
- } while(argv[i][pos++] == 'v');
- continue;
- }
- else if(!strcmp(argv[i], "-q"))
- {
- g_verbosity--;
- continue;
- }
- else if(!strcmp(argv[i], "-?") ||
- !strcmp(argv[i], "--?") ||
- !strcmp(argv[i], "-h") ||
- !strcmp(argv[i], "--help"))
- {
- print_usage(argv[0]);
- exit(0);
- }
-
- const char * filename = argv[i];
-
- struct stat sbuf;
- const int res = stat(filename, &sbuf);
- if(res != 0){
- ndbout << "Could not find file: \"" << filename << "\"" << endl;
- continue;
- }
- const Uint32 bytes = sbuf.st_size;
-
- UtilBuffer buffer;
-
- FILE * f = fopen(filename, "rb");
- if(f == 0){
- ndbout << "Failed to open file" << endl;
- continue;
- }
-
- Uint32 sz;
- Uint32 j = 0;
- do {
- buffer.grow(g_page_size);
- sz = fread(buffer.get_data(), 1, g_page_size, f);
- if((* g_print_page)(j++, buffer.get_data(), sz))
- break;
- } while(sz == g_page_size);
-
- fclose(f);
- continue;
- }
- return 0;
-}
-
-void
-print_usage(const char* prg)
-{
- ndbout << prg << " [-v]+ [-q]+ <file>+" << endl;
-}
-
-int
-print_zero_page(int i, void * ptr, Uint32 sz){
- File_formats::Zero_page_header* page = (File_formats::Zero_page_header*)ptr;
- if(memcmp(page->m_magic, "NDBDISK", 8) != 0)
- {
- ndbout << "Invalid magic: file is not ndb disk data file" << endl;
- return 1;
- }
-
- if(page->m_byte_order != 0x12345678)
- {
- ndbout << "Unhandled byteorder" << endl;
- return 1;
- }
-
- switch(page->m_file_type)
- {
- case File_formats::FT_Datafile:
- {
- g_df_zero = (* (File_formats::Datafile::Zero_page*)ptr);
- ndbout << "-- Datafile -- " << endl;
- ndbout << g_df_zero << endl;
- g_print_page = print_extent_page;
- return 0;
- }
- break;
- case File_formats::FT_Undofile:
- {
- g_uf_zero = (* (File_formats::Undofile::Zero_page*)ptr);
- ndbout << "-- Undofile -- " << endl;
- ndbout << g_uf_zero << endl;
- g_print_page = print_undo_page;
- return 0;
- }
- break;
- default:
- ndbout << "Unhandled file type: " << page->m_file_type << endl;
- return 1;
- }
-
- if(page->m_page_size !=g_page_size)
- {
- /**
- * Todo
- * lseek
- * g_page_size = page->m_page_size;
- */
- ndbout << "Unhandled page size: " << page->m_page_size << endl;
- return 1;
- }
-
- return 0;
-}
-
-NdbOut&
-operator<<(NdbOut& out, const File_formats::Datafile::Extent_header& obj)
-{
- if(obj.m_table == RNIL)
- {
- if(obj.m_next_free_extent != RNIL)
- out << " FREE, next free: " << obj.m_next_free_extent;
- else
- out << " FREE, next free: RNIL";
- }
- else
- {
- out << "table: " << obj.m_table
- << " fragment: " << obj.m_fragment_id << " ";
- for(Uint32 i = 0; i<g_df_zero.m_extent_size; i++)
- {
- char t[2];
- BaseString::snprintf(t, sizeof(t), "%x", obj.get_free_bits(i));
- out << t;
- }
- }
- return out;
-}
-
-int
-print_extent_page(int count, void* ptr, Uint32 sz){
- if(count == g_df_zero.m_extent_pages)
- {
- g_print_page = print_data_page;
- }
- Uint32 header_words =
- File_formats::Datafile::extent_header_words(g_df_zero.m_extent_size);
- Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS / header_words;
-
- int no = count * per_page;
-
- const int max = count < g_df_zero.m_extent_pages ?
- per_page : g_df_zero.m_extent_count % per_page;
-
- File_formats::Datafile::Extent_page * page =
- (File_formats::Datafile::Extent_page*)ptr;
-
- ndbout << "Extent page: " << count
- << ", lsn = [ "
- << page->m_page_header.m_page_lsn_hi << " "
- << page->m_page_header.m_page_lsn_lo << "]"
- << endl;
- for(int i = 0; i<max; i++)
- {
- ndbout << " extent " << no+i << ": "
- << (* page->get_header(i, g_df_zero.m_extent_size)) << endl;
- }
- return 0;
-}
-
-int
-print_data_page(int count, void* ptr, Uint32 sz){
-
- File_formats::Datafile::Data_page * page =
- (File_formats::Datafile::Data_page*)ptr;
-
- ndbout << "Data page: " << count
- << ", lsn = [ "
- << page->m_page_header.m_page_lsn_hi << " "
- << page->m_page_header.m_page_lsn_lo << "]" ;
-
- if(g_verbosity > 1 || print_page(count))
- {
- switch(page->m_page_header.m_page_type){
- case File_formats::PT_Unallocated:
- break;
- case File_formats::PT_Tup_fixsize_page:
- ndbout << " fix ";
- if(g_verbosity > 2 || print_page(count))
- ndbout << (* (Tup_fixsize_page*)page);
- break;
- case File_formats::PT_Tup_varsize_page:
- ndbout << " var ";
- if(g_verbosity > 2 || print_page(count))
- ndbout << endl << (* (Tup_varsize_page*)page);
- break;
- default:
- ndbout << " unknown page type: %d" << page->m_page_header.m_page_type;
- }
- }
- ndbout << endl;
- return 0;
-}
-
-#define DBTUP_C
-#include "dbtup/Dbtup.hpp"
-
-int
-print_undo_page(int count, void* ptr, Uint32 sz){
- if(count > g_uf_zero.m_undo_pages + 1)
- {
- ndbout_c(" ERROR to many pages in file!!");
- return 1;
- }
-
- File_formats::Undofile::Undo_page * page =
- (File_formats::Undofile::Undo_page*)ptr;
-
- if(page->m_page_header.m_page_lsn_hi != 0 ||
- page->m_page_header.m_page_lsn_lo != 0)
- {
- ndbout << "Undo page: " << count
- << ", lsn = [ "
- << page->m_page_header.m_page_lsn_hi << " "
- << page->m_page_header.m_page_lsn_lo << "] "
- << "words used: " << page->m_words_used << endl;
-
- Uint64 lsn= 0;
- lsn += page->m_page_header.m_page_lsn_hi;
- lsn <<= 32;
- lsn += page->m_page_header.m_page_lsn_lo;
- lsn++;
-
- if(g_verbosity >= 3)
- {
- Uint32 pos= page->m_words_used - 1;
- while(pos + 1 != 0)
- {
- Uint32 len= page->m_data[pos] & 0xFFFF;
- Uint32 type= page->m_data[pos] >> 16;
- const Uint32* src= page->m_data + pos - len + 1;
- Uint32 next_pos= pos - len;
- if(type & File_formats::Undofile::UNDO_NEXT_LSN)
- {
- type &= ~(Uint32)File_formats::Undofile::UNDO_NEXT_LSN;
- lsn--;
- }
- else
- {
- lsn = 0;
- lsn += * (src - 2);
- lsn <<= 32;
- lsn += * (src - 1);
- next_pos -= 2;
- }
- if(g_verbosity > 3)
- printf(" %.4d - %.4d : ", pos - len + 1, pos);
- switch(type){
- case File_formats::Undofile::UNDO_LCP_FIRST:
- case File_formats::Undofile::UNDO_LCP:
- printf("[ %lld LCP %d tab: %d frag: %d ]", lsn,
- src[0], src[1] >> 16, src[1] & 0xFFFF);
- if(g_verbosity <= 3)
- printf("\n");
- break;
- case File_formats::Undofile::UNDO_TUP_ALLOC:
- if(g_verbosity > 3)
- {
- Dbtup::Disk_undo::Alloc *req= (Dbtup::Disk_undo::Alloc*)src;
- printf("[ %lld A %d %d %d ]",
- lsn,
- req->m_file_no_page_idx >> 16,
- req->m_file_no_page_idx & 0xFFFF,
- req->m_page_no);
- }
- break;
- case File_formats::Undofile::UNDO_TUP_UPDATE:
- if(g_verbosity > 3)
- {
- Dbtup::Disk_undo::Update *req= (Dbtup::Disk_undo::Update*)src;
- printf("[ %lld U %d %d %d gci: %d ]",
- lsn,
- req->m_file_no_page_idx >> 16,
- req->m_file_no_page_idx & 0xFFFF,
- req->m_page_no,
- req->m_gci);
- }
- break;
- case File_formats::Undofile::UNDO_TUP_FREE:
- if(g_verbosity > 3)
- {
- Dbtup::Disk_undo::Free *req= (Dbtup::Disk_undo::Free*)src;
- printf("[ %lld F %d %d %d gci: %d ]",
- lsn,
- req->m_file_no_page_idx >> 16,
- req->m_file_no_page_idx & 0xFFFF,
- req->m_page_no,
- req->m_gci);
- }
- break;
- case File_formats::Undofile::UNDO_TUP_CREATE:
- {
- Dbtup::Disk_undo::Create *req = (Dbtup::Disk_undo::Create*)src;
- printf("[ %lld Create %d ]", lsn, req->m_table);
- if(g_verbosity <= 3)
- printf("\n");
- break;
- }
- case File_formats::Undofile::UNDO_TUP_DROP:
- {
- Dbtup::Disk_undo::Drop *req = (Dbtup::Disk_undo::Drop*)src;
- printf("[ %lld Drop %d ]", lsn, req->m_table);
- if(g_verbosity <= 3)
- printf("\n");
- break;
- }
- case File_formats::Undofile::UNDO_TUP_ALLOC_EXTENT:
- {
- Dbtup::Disk_undo::AllocExtent *req = (Dbtup::Disk_undo::AllocExtent*)src;
- printf("[ %lld AllocExtent tab: %d frag: %d file: %d page: %d ]",
- lsn,
- req->m_table,
- req->m_fragment,
- req->m_file_no,
- req->m_page_no);
- if(g_verbosity <= 3)
- printf("\n");
- break;
- }
- case File_formats::Undofile::UNDO_TUP_FREE_EXTENT:
- {
- Dbtup::Disk_undo::FreeExtent *req = (Dbtup::Disk_undo::FreeExtent*)src;
- printf("[ %lld FreeExtent tab: %d frag: %d file: %d page: %d ]",
- lsn,
- req->m_table,
- req->m_fragment,
- req->m_file_no,
- req->m_page_no);
- if(g_verbosity <= 3)
- printf("\n");
- break;
- }
- default:
- ndbout_c("[ Unknown type %d len: %d, pos: %d ]", type, len, pos);
- if(!(len && type))
- {
- pos= 0;
- while(pos < page->m_words_used)
- {
- printf("%.8x ", page->m_data[pos]);
- if((pos + 1) % 7 == 0)
- ndbout_c("");
- pos++;
- }
- }
- assert(len && type);
- }
- pos = next_pos;
- if(g_verbosity > 3)
- printf("\n");
- }
- }
- }
-
- if(count == g_uf_zero.m_undo_pages + 1)
- {
- }
-
- return 0;
-}
-
-// hp3750
-Signal::Signal(){}
diff --git a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp b/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
deleted file mode 100644
index 79de0715d01..00000000000
--- a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
+++ /dev/null
@@ -1,471 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef QMGR_H
-#define QMGR_H
-
-
-#include <pc.hpp>
-#include <NdbTick.h>
-#include <SimulatedBlock.hpp>
-#include <NodeBitmask.hpp>
-#include <SignalCounter.hpp>
-
-#include <signaldata/EventReport.hpp>
-#include <signaldata/ArbitSignalData.hpp>
-#include <signaldata/CmRegSignalData.hpp>
-#include <signaldata/ApiRegSignalData.hpp>
-#include <signaldata/FailRep.hpp>
-#include <signaldata/AllocNodeId.hpp>
-
-#include <SafeCounter.hpp>
-#include <RequestTracker.hpp>
-#include <signaldata/StopReq.hpp>
-
-#include "timer.hpp"
-
-#ifdef QMGR_C
-
-#define NO_REG_APP 1
-
-/* Delay values, ms -----------------------------*/
-#define ZDELAY_REGREQ 1000
-
-/* Type of refuse in CM_NODEINFOREF -------------*/
-#define ZNOT_RUNNING 0
-
-/* Type of continue in CONTINUEB ----------------*/
-#define ZREGREQ_TIMELIMIT 0
-#define ZHB_HANDLING 1
-#define ZREGREQ_MASTER_TIMELIMIT 2
-#define ZAPI_HB_HANDLING 3
-#define ZTIMER_HANDLING 4
-#define ZARBIT_HANDLING 5
-#define ZSTART_FAILURE_LIMIT 6
-
-/* Error Codes ------------------------------*/
-#define ZERRTOOMANY 1101
-#define ZERRALREADYREG 1102
-#define ZERRNHMISSING 1103
-#define ZERRNLMISSING 1104
-#define ZERRAPPMISSING 1105
-#define ZERROR_NOT_IN_CFGFILE 1106
-#define ZERROR_TIMEOUT 1107
-#define ZERROR_NOT_ZINIT 1108
-#define ZERROR_NODEINFOREF 1109
-#define ZERROR_NOTLOCALQMGR 1110
-#define ZERROR_NOTRUNNING 1111
-#define ZCOULD_NOT_OCCUR_ERROR 1112
-#define ZTIME_OUT_ERROR 1113
-#define ZERROR_NOT_DEAD 1114
-#define ZDECLARED_FAIL_ERROR 1115
-#define ZOWN_NODE_ERROR 1116
-#define ZWRONG_STATE_ERROR 1117
-#define ZNODE_ZERO_ERROR 1118
-#define ZWRONG_NODE_ERROR 1119
-
-#endif
-
-
-class Qmgr : public SimulatedBlock {
-public:
- // State values
- enum QmgrState {
- Q_NOT_ACTIVE = 0,
- Q_ACTIVE = 1
- };
-
- enum FailState {
- NORMAL = 0,
- WAITING_FOR_FAILCONF1 = 1,
- WAITING_FOR_FAILCONF2 = 2,
- WAITING_FOR_NDB_FAILCONF = 3
- };
-
- enum Phase {
- ZINIT = 1, /* All nodes start in phase INIT */
- ZSTARTING = 2, /* Node is connecting to cluster */
- ZRUNNING = 3, /* Node is running in the cluster */
- ZPREPARE_FAIL = 4, /* PREPARATION FOR FAILURE */
- ZFAIL_CLOSING = 5, /* API/NDB IS DISCONNECTING */
- ZAPI_ACTIVE = 6, /* API IS RUNNING IN NODE */
- ZAPI_INACTIVE = 7 /* Inactive API */
- };
-
- struct StartRecord {
- StartRecord() {}
- void reset(){
- m_startKey++;
- m_startNode = 0;
- m_gsn = RNIL;
- m_nodes.clearWaitingFor();
- }
- Uint32 m_startKey;
- Uint32 m_startNode;
- Uint64 m_startTimeout;
-
- Uint32 m_gsn;
- SignalCounter m_nodes;
- 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;
- Uint32 m_node_gci[MAX_NDB_NODES];
- } c_start;
-
- NdbNodeBitmask c_definedNodes; // DB nodes in config
- NdbNodeBitmask c_clusterNodes; // DB nodes in cluster
- NodeBitmask c_connectedNodes; // All kinds of connected nodes
-
- /**
- * Nodes which we're checking for partitioned cluster
- *
- * 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;
-
- QmgrState sendPrepFailReqStatus;
- QmgrState sendCommitFailReqStatus;
- QmgrState sendPresToStatus;
- FailState failState;
- BlockReference rcv[2]; // remember which failconf we have received
- BlockReference blockRef;
-
- NodeRec() { }
- }; /* p2c: size = 52 bytes */
-
- typedef Ptr<NodeRec> NodeRecPtr;
-
- enum ArbitState {
- ARBIT_NULL = 0,
- ARBIT_INIT = 1, // create new ticket
- ARBIT_FIND = 2, // find candidate arbitrator node
- ARBIT_PREP1 = 3, // PREP db nodes with null ticket
- ARBIT_PREP2 = 4, // PREP db nodes with current ticket
- ARBIT_START = 5, // START arbitrator API thread
- ARBIT_RUN = 6, // running with arbitrator
- ARBIT_CHOOSE = 7, // ask arbitrator after network partition
- ARBIT_CRASH = 8 // crash ourselves
- };
-
- struct ArbitRec {
- ArbitRec() {}
- ArbitState state; // state
- bool newstate; // flag to initialize new state
- unsigned thread; // identifies a continueB "thread"
- NodeId node; // current arbitrator candidate
- ArbitTicket ticket; // ticket
- NodeBitmask apiMask[1+2]; // arbitrators 0=all 1,2=per rank
- NodeBitmask newMask; // new nodes to process in RUN state
- Uint8 sendCount; // control send/recv of signals
- Uint8 recvCount;
- NodeBitmask recvMask; // left to recv
- Uint32 code; // code field from signal
- Uint32 failureNr; // cfailureNr at arbitration start
- Uint32 timeout; // timeout for CHOOSE state
- NDB_TICKS timestamp; // timestamp for checking timeouts
-
- inline bool match(ArbitSignalData* sd) {
- return
- node == sd->node &&
- ticket.match(sd->ticket);
- }
-
- inline void setTimestamp() {
- timestamp = NdbTick_CurrentMillisecond();
- }
-
- inline NDB_TICKS getTimediff() {
- NDB_TICKS now = NdbTick_CurrentMillisecond();
- return now < timestamp ? 0 : now - timestamp;
- }
- };
-
-public:
- Qmgr(Block_context&);
- virtual ~Qmgr();
-
-private:
- BLOCK_DEFINES(Qmgr);
-
- // Transit signals
- void execDEBUG_SIG(Signal* signal);
- void execCONTINUEB(Signal* signal);
- void execCM_HEARTBEAT(Signal* signal);
- void execCM_ADD(Signal* signal);
- void execCM_ACKADD(Signal* signal);
- void execCM_REGREQ(Signal* signal);
- void execCM_REGCONF(Signal* signal);
- void execCM_REGREF(Signal* signal);
- void execCM_NODEINFOREQ(Signal* signal);
- void execCM_NODEINFOCONF(Signal* signal);
- void execCM_NODEINFOREF(Signal* signal);
- void execPREP_FAILREQ(Signal* signal);
- void execPREP_FAILCONF(Signal* signal);
- void execPREP_FAILREF(Signal* signal);
- void execCOMMIT_FAILREQ(Signal* signal);
- void execCOMMIT_FAILCONF(Signal* signal);
- void execFAIL_REP(Signal* signal);
- void execPRES_TOREQ(Signal* signal);
- void execPRES_TOCONF(Signal* signal);
- void execDISCONNECT_REP(Signal* signal);
- void execSYSTEM_ERROR(Signal* signal);
- void execSTOP_REQ(Signal* signal);
-
- // Received signals
- 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);
- void execAPI_REGREQ(Signal* signal);
- void execAPI_FAILCONF(Signal* signal);
- void execREAD_NODESREQ(Signal* signal);
- void execAPI_FAILREQ(Signal* signal);
-
- 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);
-
- void execNODE_FAILREP(Signal *);
- void execALLOC_NODEID_REQ(Signal *);
- void execALLOC_NODEID_CONF(Signal *);
- void execALLOC_NODEID_REF(Signal *);
- void completeAllocNodeIdReq(Signal *);
-
- void execSTART_ORD(Signal*);
-
- // Arbitration signals
- void execARBIT_CFG(Signal* signal);
- void execARBIT_PREPREQ(Signal* signal);
- void execARBIT_PREPCONF(Signal* signal);
- void execARBIT_PREPREF(Signal* signal);
- void execARBIT_STARTCONF(Signal* signal);
- void execARBIT_STARTREF(Signal* signal);
- void execARBIT_CHOOSECONF(Signal* signal);
- void execARBIT_CHOOSEREF(Signal* signal);
- void execARBIT_STOPREP(Signal* signal);
-
- // Statement blocks
- void check_readnodes_reply(Signal* signal, Uint32 nodeId, Uint32 gsn);
- Uint32 check_startup(Signal* signal);
-
- void api_failed(Signal* signal, Uint32 aFailedNode);
- void node_failed(Signal* signal, Uint16 aFailedNode);
- void checkStartInterface(Signal* signal);
- void failReport(Signal* signal,
- Uint16 aFailedNode,
- UintR aSendFailRep,
- FailRep::FailCause failCause);
- void findNeighbours(Signal* signal);
- Uint16 translateDynamicIdToNodeId(Signal* signal, UintR TdynamicId);
-
- void initData(Signal* signal);
- void sendCloseComReq(Signal* signal, BlockReference TBRef, Uint16 TfailNo);
- void sendPrepFailReq(Signal* signal, Uint16 aNode);
- void sendApiFailReq(Signal* signal, Uint16 aFailedNode);
- void sendApiRegRef(Signal*, Uint32 ref, ApiRegRef::ErrorCode);
-
- // Generated statement blocks
- void startphase1(Signal* signal);
- void electionWon(Signal* signal);
- void cmInfoconf010Lab(Signal* signal);
-
- void apiHbHandlingLab(Signal* signal);
- void timerHandlingLab(Signal* signal);
- void hbReceivedLab(Signal* signal);
- void sendCmRegrefLab(Signal* signal, BlockReference ref,
- CmRegRef::ErrorCode);
- void systemErrorBecauseOtherNodeFailed(Signal* signal, Uint32 line, NodeId);
- void systemErrorLab(Signal* signal, Uint32 line,
- const char* message = NULL);
- void prepFailReqLab(Signal* signal);
- void prepFailConfLab(Signal* signal);
- void prepFailRefLab(Signal* signal);
- void commitFailReqLab(Signal* signal);
- void commitFailConfLab(Signal* signal);
- void failReportLab(Signal* signal, Uint16 aFailedNode,
- FailRep::FailCause aFailCause);
- void sendCommitFailReq(Signal* signal);
- void presToConfLab(Signal* signal);
- void sendSttorryLab(Signal* signal);
- void sttor020Lab(Signal* signal);
- void closeComConfLab(Signal* signal);
- void apiRegReqLab(Signal* signal);
- void regreqTimeLimitLab(Signal* signal);
- void regreqTimeMasterLimitLab(Signal* signal);
- void cmRegreq010Lab(Signal* signal);
- void cmRegconf010Lab(Signal* signal);
- void sttor010Lab(Signal* signal);
- void sendHeartbeat(Signal* signal);
- void checkHeartbeat(Signal* signal);
- void setHbDelay(UintR aHbDelay);
- void setHbApiDelay(UintR aHbApiDelay);
- void setArbitTimeout(UintR aArbitTimeout);
-
- // Interface to arbitration module
- void handleArbitStart(Signal* signal);
- void handleArbitApiFail(Signal* signal, Uint16 nodeId);
- void handleArbitNdbAdd(Signal* signal, Uint16 nodeId);
- void handleArbitCheck(Signal* signal);
-
- // Private arbitration routines
- Uint32 getArbitDelay();
- Uint32 getArbitTimeout();
- void startArbitThread(Signal* signal);
- void runArbitThread(Signal* signal);
- void stateArbitInit(Signal* signal);
- void stateArbitFind(Signal* signal);
- void stateArbitPrep(Signal* signal);
- void stateArbitStart(Signal* signal);
- void stateArbitRun(Signal* signal);
- void stateArbitChoose(Signal* signal);
- void stateArbitCrash(Signal* signal);
- void computeArbitNdbMask(NodeBitmask& aMask);
- void reportArbitEvent(Signal* signal, Ndb_logevent_type type);
-
- // Initialisation
- void initData();
- void initRecords();
-
- // Transit signals
- // Variables
-
- bool checkAPIVersion(NodeId, Uint32 nodeVersion, Uint32 ownVersion) const;
- bool checkNDBVersion(NodeId, Uint32 nodeVersion, Uint32 ownVersion) const;
-
- void cmAddPrepare(Signal* signal, NodeRecPtr nodePtr, const NodeRec* self);
- void sendCmAckAdd(Signal *, Uint32 nodeId, CmAdd::RequestType);
- void joinedCluster(Signal* signal, NodeRecPtr nodePtr);
- void sendCmRegReq(Signal * signal, Uint32 nodeId);
- void sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self);
-
-private:
- void sendPrepFailReqRef(Signal* signal,
- Uint32 dstBlockRef,
- GlobalSignalNumber gsn,
- Uint32 blockRef,
- Uint32 failNo,
- Uint32 noOfNodes,
- const NodeId theNodes[]);
-
-
-
- /* Wait this time until we try to join the */
- /* cluster again */
-
- /**** Common stored variables ****/
-
- NodeRec *nodeRec;
- ArbitRec arbitRec;
-
- /* Block references ------------------------------*/
- BlockReference cpdistref; /* Dist. ref of president */
-
- /* Node numbers. ---------------------------------*/
- Uint16 cneighbourl; /* Node no. of lower neighbour */
- Uint16 cneighbourh; /* Node no. of higher neighbour */
- Uint16 cpresident; /* Node no. of president */
-
- /* Counters --------------------------------------*/
- Uint16 cnoOfNodes; /* Static node counter */
- /* Status flags ----------------------------------*/
-
- Uint32 c_restartPartialTimeout;
- Uint32 c_restartPartionedTimeout;
- Uint32 c_restartFailureTimeout;
- Uint64 c_start_election_time;
-
- Uint16 creadyDistCom;
-
- Uint16 cdelayRegreq;
- Uint16 cpresidentAlive;
- Uint16 cnoFailedNodes;
- Uint16 cnoPrepFailedNodes;
- Uint16 cnoCommitFailedNodes;
- Uint16 cactivateApiCheck;
- UintR chbApiDelay;
-
- UintR ccommitFailureNr;
- UintR cprepareFailureNr;
- UintR ctoFailureNr;
- UintR cfailureNr;
-
- QmgrState ctoStatus;
- UintR cLqhTimeSignalCount;
- bool cHbSent;
- NDB_TICKS clatestTransactionCheck;
-
- class Timer interface_check_timer;
- class Timer hb_check_timer;
- class Timer hb_send_timer;
- class Timer hb_api_timer;
-
-
- Uint16 cfailedNodes[MAX_NDB_NODES];
- Uint16 cprepFailedNodes[MAX_NDB_NODES];
- Uint16 ccommitFailedNodes[MAX_NDB_NODES];
-
- struct OpAllocNodeIdReq {
- RequestTracker m_tracker;
- AllocNodeIdReq m_req;
- Uint32 m_connectCount;
- Uint32 m_error;
- };
-
- struct OpAllocNodeIdReq opAllocNodeIdReq;
-
- StopReq c_stopReq;
- bool check_multi_node_shutdown(Signal* signal);
-
-#ifdef ERROR_INSERT
- Uint32 c_error_insert_extra;
-#endif
-
- void recompute_version_info(Uint32 type);
- void recompute_version_info(Uint32 type, Uint32 version);
- void execNODE_VERSION_REP(Signal* signal);
- void sendApiVersionRep(Signal* signal, NodeRecPtr nodePtr);
- void sendVersionedDb(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Uint32 minversion);
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
deleted file mode 100644
index ce93b889d92..00000000000
--- a/storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-
-#define QMGR_C
-#include "Qmgr.hpp"
-
-#define DEBUG(x) { ndbout << "Qmgr::" << x << endl; }
-
-
-void Qmgr::initData()
-{
- creadyDistCom = ZFALSE;
-
- // Records with constant sizes
- nodeRec = new NodeRec[MAX_NODES];
-
- cnoCommitFailedNodes = 0;
- c_maxDynamicId = 0;
- c_clusterNodes.clear();
- c_stopReq.senderRef = 0;
-
- /**
- * Check sanity for NodeVersion
- */
- ndbrequire((Uint32)NodeInfo::DB == 0);
- ndbrequire((Uint32)NodeInfo::API == 1);
- ndbrequire((Uint32)NodeInfo::MGM == 2);
-
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrAss(nodePtr, nodeRec);
- nodePtr.p->blockRef = reference();
-
- c_connectedNodes.set(getOwnNodeId());
- setNodeInfo(getOwnNodeId()).m_version = NDB_VERSION;
-
-
- /**
- * Timeouts
- */
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Uint32 hbDBAPI = 1500;
- ndb_mgm_get_int_parameter(p, CFG_DB_API_HEARTBEAT_INTERVAL, &hbDBAPI);
-
- setHbApiDelay(hbDBAPI);
-}//Qmgr::initData()
-
-void Qmgr::initRecords()
-{
- // Records with dynamic sizes
-}//Qmgr::initRecords()
-
-Qmgr::Qmgr(Block_context& ctx)
- : SimulatedBlock(QMGR, ctx)
-{
- BLOCK_CONSTRUCTOR(Qmgr);
-
- // Transit signals
- addRecSignal(GSN_DUMP_STATE_ORD, &Qmgr::execDUMP_STATE_ORD);
- addRecSignal(GSN_STOP_REQ, &Qmgr::execSTOP_REQ);
- addRecSignal(GSN_DEBUG_SIG, &Qmgr::execDEBUG_SIG);
- addRecSignal(GSN_CONTINUEB, &Qmgr::execCONTINUEB);
- addRecSignal(GSN_CM_HEARTBEAT, &Qmgr::execCM_HEARTBEAT);
- addRecSignal(GSN_CM_ADD, &Qmgr::execCM_ADD);
- addRecSignal(GSN_CM_ACKADD, &Qmgr::execCM_ACKADD);
- addRecSignal(GSN_CM_REGREQ, &Qmgr::execCM_REGREQ);
- addRecSignal(GSN_CM_REGCONF, &Qmgr::execCM_REGCONF);
- addRecSignal(GSN_CM_REGREF, &Qmgr::execCM_REGREF);
- addRecSignal(GSN_CM_NODEINFOREQ, &Qmgr::execCM_NODEINFOREQ);
- addRecSignal(GSN_CM_NODEINFOCONF, &Qmgr::execCM_NODEINFOCONF);
- addRecSignal(GSN_CM_NODEINFOREF, &Qmgr::execCM_NODEINFOREF);
- addRecSignal(GSN_PREP_FAILREQ, &Qmgr::execPREP_FAILREQ);
- addRecSignal(GSN_PREP_FAILCONF, &Qmgr::execPREP_FAILCONF);
- addRecSignal(GSN_PREP_FAILREF, &Qmgr::execPREP_FAILREF);
- addRecSignal(GSN_COMMIT_FAILREQ, &Qmgr::execCOMMIT_FAILREQ);
- addRecSignal(GSN_COMMIT_FAILCONF, &Qmgr::execCOMMIT_FAILCONF);
- addRecSignal(GSN_FAIL_REP, &Qmgr::execFAIL_REP);
- addRecSignal(GSN_PRES_TOREQ, &Qmgr::execPRES_TOREQ);
- addRecSignal(GSN_PRES_TOCONF, &Qmgr::execPRES_TOCONF);
-
- // 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);
- addRecSignal(GSN_API_VERSION_REQ, &Qmgr::execAPI_VERSION_REQ);
- addRecSignal(GSN_DISCONNECT_REP, &Qmgr::execDISCONNECT_REP);
- addRecSignal(GSN_API_FAILREQ, &Qmgr::execAPI_FAILREQ);
- addRecSignal(GSN_API_FAILCONF, &Qmgr::execAPI_FAILCONF);
- addRecSignal(GSN_READ_NODESREQ, &Qmgr::execREAD_NODESREQ);
- addRecSignal(GSN_API_BROADCAST_REP, &Qmgr::execAPI_BROADCAST_REP);
-
- addRecSignal(GSN_NODE_FAILREP, &Qmgr::execNODE_FAILREP);
- addRecSignal(GSN_ALLOC_NODEID_REQ, &Qmgr::execALLOC_NODEID_REQ);
- addRecSignal(GSN_ALLOC_NODEID_CONF, &Qmgr::execALLOC_NODEID_CONF);
- addRecSignal(GSN_ALLOC_NODEID_REF, &Qmgr::execALLOC_NODEID_REF);
-
- // Arbitration signals
- addRecSignal(GSN_ARBIT_PREPREQ, &Qmgr::execARBIT_PREPREQ);
- addRecSignal(GSN_ARBIT_PREPCONF, &Qmgr::execARBIT_PREPCONF);
- addRecSignal(GSN_ARBIT_PREPREF, &Qmgr::execARBIT_PREPREF);
- addRecSignal(GSN_ARBIT_STARTCONF, &Qmgr::execARBIT_STARTCONF);
- addRecSignal(GSN_ARBIT_STARTREF, &Qmgr::execARBIT_STARTREF);
- addRecSignal(GSN_ARBIT_CHOOSECONF, &Qmgr::execARBIT_CHOOSECONF);
- addRecSignal(GSN_ARBIT_CHOOSEREF, &Qmgr::execARBIT_CHOOSEREF);
- addRecSignal(GSN_ARBIT_STOPREP, &Qmgr::execARBIT_STOPREP);
-
- 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);
- addRecSignal(GSN_NODE_VERSION_REP, &Qmgr::execNODE_VERSION_REP);
- addRecSignal(GSN_START_ORD, &Qmgr::execSTART_ORD);
-
- initData();
-}//Qmgr::Qmgr()
-
-Qmgr::~Qmgr()
-{
- delete []nodeRec;
-}//Qmgr::~Qmgr()
-
-
-BLOCK_FUNCTIONS(Qmgr)
diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
deleted file mode 100644
index 1a309e34c2d..00000000000
--- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ /dev/null
@@ -1,5268 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#define QMGR_C
-#include "Qmgr.hpp"
-#include <pc.hpp>
-#include <NdbTick.h>
-#include <signaldata/EventReport.hpp>
-#include <signaldata/StartOrd.hpp>
-#include <signaldata/CmInit.hpp>
-#include <signaldata/CloseComReqConf.hpp>
-#include <signaldata/PrepFailReqRef.hpp>
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/NFCompleteRep.hpp>
-#include <signaldata/CheckNodeGroups.hpp>
-#include <signaldata/ArbitSignalData.hpp>
-#include <signaldata/ApiRegSignalData.hpp>
-#include <signaldata/ApiVersion.hpp>
-#include <signaldata/BlockCommitOrd.hpp>
-#include <signaldata/FailRep.hpp>
-#include <signaldata/DisconnectRep.hpp>
-#include <signaldata/ApiBroadcast.hpp>
-
-#include <ndb_version.h>
-
-#ifdef DEBUG_ARBIT
-#include <NdbOut.hpp>
-#endif
-
-//#define DEBUG_QMGR_START
-#ifdef DEBUG_QMGR_START
-#include <DebuggerNames.hpp>
-#define DEBUG(x) ndbout << "QMGR " << __LINE__ << ": " << x << endl
-#define DEBUG_START(gsn, node, msg) DEBUG(getSignalName(gsn) << " to: " << node << " - " << msg)
-#define DEBUG_START2(gsn, rg, msg) { char nodes[255]; DEBUG(getSignalName(gsn) << " to: " << rg.m_nodes.getText(nodes) << " - " << msg); }
-#define DEBUG_START3(signal, msg) DEBUG(getSignalName(signal->header.theVerId_signalNumber) << " from " << refToNode(signal->getSendersBlockRef()) << " - " << msg);
-#else
-#define DEBUG(x)
-#define DEBUG_START(gsn, node, msg)
-#define DEBUG_START2(gsn, rg, msg)
-#define DEBUG_START3(signal, msg)
-#endif
-
-/**
- * c_start.m_gsn = GSN_CM_REGREQ
- * Possible for all nodes
- * c_start.m_nodes contains all nodes in config
- *
- * c_start.m_gsn = GSN_CM_NODEINFOREQ;
- * Set when receiving CM_REGCONF
- * State possible for starting node only (not in cluster)
- *
- * c_start.m_nodes contains all node in alive cluster that
- * that has not replied to GSN_CM_NODEINFOREQ
- * passed by president in GSN_CM_REGCONF
- *
- * c_start.m_gsn = GSN_CM_ADD
- * Possible for president only
- * Set when receiving and accepting CM_REGREQ (to include node)
- *
- * c_start.m_nodes contains all nodes in alive cluster + starting node
- * that has not replied to GSN_CM_ADD
- * by sending GSN_CM_ACKADD
- *
- * c_start.m_gsn = GSN_CM_NODEINFOCONF
- * Possible for non presidents only
- * c_start.m_nodes contains a node that has been accepted by president
- * but has not connected to us yet
- */
-
-// Signal entries and statement blocks
-/* 4 P R O G R A M */
-/*******************************/
-/* CMHEART_BEAT */
-/*******************************/
-void Qmgr::execCM_HEARTBEAT(Signal* signal)
-{
- NodeRecPtr hbNodePtr;
- jamEntry();
- hbNodePtr.i = signal->theData[0];
- ptrCheckGuard(hbNodePtr, MAX_NDB_NODES, nodeRec);
- setNodeInfo(hbNodePtr.i).m_heartbeat_cnt= 0;
- return;
-}//Qmgr::execCM_HEARTBEAT()
-
-/*******************************/
-/* CM_NODEINFOREF */
-/*******************************/
-void Qmgr::execCM_NODEINFOREF(Signal* signal)
-{
- jamEntry();
- systemErrorLab(signal, __LINE__);
- return;
-}//Qmgr::execCM_NODEINFOREF()
-
-/*******************************/
-/* CONTINUEB */
-/*******************************/
-void Qmgr::execCONTINUEB(Signal* signal)
-{
- jamEntry();
- const Uint32 tcontinuebType = signal->theData[0];
- const Uint32 tdata0 = signal->theData[1];
- const Uint32 tdata1 = signal->theData[2];
- switch (tcontinuebType) {
- case ZREGREQ_TIMELIMIT:
- jam();
- if (c_start.m_startKey != tdata0 || c_start.m_startNode != tdata1) {
- jam();
- return;
- }//if
- regreqTimeLimitLab(signal);
- break;
- case ZREGREQ_MASTER_TIMELIMIT:
- jam();
- if (c_start.m_startKey != tdata0 || c_start.m_startNode != tdata1) {
- jam();
- return;
- }//if
- //regreqMasterTimeLimitLab(signal);
- failReportLab(signal, c_start.m_startNode, FailRep::ZSTART_IN_REGREQ);
- return;
- break;
- case ZTIMER_HANDLING:
- jam();
- timerHandlingLab(signal);
- return;
- break;
- case ZARBIT_HANDLING:
- jam();
- 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 == (Uint32) ~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;
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
- return;
-}//Qmgr::execCONTINUEB()
-
-
-void Qmgr::execDEBUG_SIG(Signal* signal)
-{
- NodeRecPtr debugNodePtr;
- jamEntry();
- debugNodePtr.i = signal->theData[0];
- ptrCheckGuard(debugNodePtr, MAX_NODES, nodeRec);
- return;
-}//Qmgr::execDEBUG_SIG()
-
-/*******************************/
-/* FAIL_REP */
-/*******************************/
-void Qmgr::execFAIL_REP(Signal* signal)
-{
- const FailRep * const failRep = (FailRep *)&signal->theData[0];
- const NodeId failNodeId = failRep->failNodeId;
- const FailRep::FailCause failCause = (FailRep::FailCause)failRep->failCause;
-
- jamEntry();
- failReportLab(signal, failNodeId, failCause);
- return;
-}//Qmgr::execFAIL_REP()
-
-/*******************************/
-/* PRES_TOREQ */
-/*******************************/
-void Qmgr::execPRES_TOREQ(Signal* signal)
-{
- jamEntry();
- BlockReference Tblockref = signal->theData[0];
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = ccommitFailureNr;
- sendSignal(Tblockref, GSN_PRES_TOCONF, signal, 2, JBA);
- 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 =
- m_ctx.m_config.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
-Qmgr::execSTART_ORD(Signal* signal)
-{
- /**
- * Start timer handling
- */
- signal->theData[0] = ZTIMER_HANDLING;
- sendSignal(QMGR_REF, GSN_CONTINUEB, signal, 1, JBB);
-
- NodeRecPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++)
- {
- ptrAss(nodePtr, nodeRec);
- nodePtr.p->ndynamicId = 0;
- if(getNodeInfo(nodePtr.i).m_type == NodeInfo::DB)
- {
- nodePtr.p->phase = ZINIT;
- c_definedNodes.set(nodePtr.i);
- } else {
- nodePtr.p->phase = ZAPI_INACTIVE;
- }
-
- 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;
- nodePtr.p->failState = NORMAL;
- nodePtr.p->rcv[0] = 0;
- nodePtr.p->rcv[1] = 0;
- }//for
-}
-
-/*
-4.2 ADD NODE MODULE*/
-/*##########################################################################*/
-/*
-4.2.1 STTOR */
-/**--------------------------------------------------------------------------
- * Start phase signal, must be handled by all blocks.
- * QMGR is only interested in the first phase.
- * During phase one we clear all registered applications.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* STTOR */
-/*******************************/
-void Qmgr::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- switch(signal->theData[1]){
- case 1:
- initData(signal);
- startphase1(signal);
- recompute_version_info(NodeInfo::DB);
- recompute_version_info(NodeInfo::API);
- recompute_version_info(NodeInfo::MGM);
- return;
- case 7:
- cactivateApiCheck = 1;
- /**
- * Start arbitration thread. This could be done as soon as
- * we have all nodes (or a winning majority).
- */
- if (cpresident == getOwnNodeId())
- handleArbitStart(signal);
- break;
- }
-
- sendSttorryLab(signal);
- return;
-}//Qmgr::execSTTOR()
-
-void Qmgr::sendSttorryLab(Signal* signal)
-{
-/****************************<*/
-/*< STTORRY <*/
-/****************************<*/
- signal->theData[3] = 7;
- signal->theData[4] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
- return;
-}//Qmgr::sendSttorryLab()
-
-void Qmgr::startphase1(Signal* signal)
-{
- jamEntry();
-
-
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrAss(nodePtr, nodeRec);
- nodePtr.p->phase = ZSTARTING;
-
- signal->theData[0] = reference();
- sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB);
- return;
-}
-
-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);
-}
-
-void Qmgr::setHbDelay(UintR aHbDelay)
-{
- hb_send_timer.setDelay(aHbDelay < 10 ? 10 : aHbDelay);
- hb_send_timer.reset();
- hb_check_timer.setDelay(aHbDelay < 10 ? 10 : aHbDelay);
- hb_check_timer.reset();
-}
-
-void Qmgr::setHbApiDelay(UintR aHbApiDelay)
-{
- chbApiDelay = (aHbApiDelay < 100 ? 100 : aHbApiDelay);
- hb_api_timer.setDelay(chbApiDelay);
- hb_api_timer.reset();
-}
-
-void Qmgr::setArbitTimeout(UintR aArbitTimeout)
-{
- arbitRec.timeout = (aArbitTimeout < 10 ? 10 : aArbitTimeout);
-}
-
-void Qmgr::execCONNECT_REP(Signal* signal)
-{
- jamEntry();
- const Uint32 nodeId = signal->theData[0];
-
- if (ERROR_INSERTED(931))
- {
- jam();
- ndbout_c("Discarding CONNECT_REP(%d)", nodeId);
- infoEvent("Discarding CONNECT_REP(%d)", nodeId);
- return;
- }
-
- c_connectedNodes.set(nodeId);
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrCheckGuard(nodePtr, MAX_NODES, nodeRec);
- switch(nodePtr.p->phase){
- case ZRUNNING:
- ndbrequire(!c_clusterNodes.get(nodeId));
- case ZSTARTING:
- jam();
- break;
- case ZPREPARE_FAIL:
- case ZFAIL_CLOSING:
- jam();
- return;
- case ZAPI_ACTIVE:
- case ZAPI_INACTIVE:
- return;
- case ZINIT:
- ndbrequire(getNodeInfo(nodeId).m_type == NodeInfo::MGM);
- break;
- default:
- ndbrequire(false);
- }
-
- if (getNodeInfo(nodeId).getType() != NodeInfo::DB)
- {
- jam();
- return;
- }
-
- switch(c_start.m_gsn){
- case GSN_CM_REGREQ:
- jam();
- sendCmRegReq(signal, nodeId);
-
- /**
- * We're waiting for CM_REGCONF c_start.m_nodes contains all configured
- * nodes
- */
- ndbrequire(nodePtr.p->phase == ZSTARTING);
- ndbrequire(c_start.m_nodes.isWaitingFor(nodeId));
- return;
- case GSN_CM_NODEINFOREQ:
- jam();
-
- if (c_start.m_nodes.isWaitingFor(nodeId))
- {
- jam();
- ndbrequire(getOwnNodeId() != cpresident);
- ndbrequire(nodePtr.p->phase == ZSTARTING);
- sendCmNodeInfoReq(signal, nodeId, nodePtr.p);
- return;
- }
- return;
- case GSN_CM_NODEINFOCONF:{
- jam();
-
- ndbrequire(getOwnNodeId() != cpresident);
- ndbrequire(nodePtr.p->phase == ZRUNNING);
- if (c_start.m_nodes.isWaitingFor(nodeId))
- {
- jam();
- c_start.m_nodes.clearWaitingFor(nodeId);
- c_start.m_gsn = RNIL;
-
- NodeRecPtr addNodePtr;
- addNodePtr.i = nodeId;
- ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
- cmAddPrepare(signal, addNodePtr, nodePtr.p);
- return;
- }
- }
- default:
- (void)1;
- }
-
- ndbrequire(!c_start.m_nodes.isWaitingFor(nodeId));
- ndbrequire(!c_readnodes_nodes.get(nodeId));
- c_readnodes_nodes.set(nodeId);
- signal->theData[0] = reference();
- sendSignal(calcQmgrBlockRef(nodeId), GSN_READ_NODESREQ, signal, 1, JBA);
- return;
-}//Qmgr::execCONNECT_REP()
-
-void
-Qmgr::execREAD_NODESCONF(Signal* signal)
-{
- jamEntry();
- check_readnodes_reply(signal,
- refToNode(signal->getSendersBlockRef()),
- GSN_READ_NODESCONF);
-}
-
-void
-Qmgr::execREAD_NODESREF(Signal* signal)
-{
- jamEntry();
- check_readnodes_reply(signal,
- refToNode(signal->getSendersBlockRef()),
- GSN_READ_NODESREF);
-}
-
-/*******************************/
-/* CM_INFOCONF */
-/*******************************/
-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;
- cpresidentAlive = ZFALSE;
- 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;
- cnoOfNodes = 0;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
-
- if(getNodeInfo(nodePtr.i).getType() != NodeInfo::DB)
- continue;
-
- c_start.m_nodes.setWaitingFor(nodePtr.i);
- cnoOfNodes++;
-
- if(!c_connectedNodes.get(nodePtr.i))
- continue;
-
- sendCmRegReq(signal, nodePtr.i);
- }
-
- //----------------------------------------
- /* Wait for a while. When it returns */
- /* we will check if we got any CM_REGREF*/
- /* or CM_REGREQ (lower nodeid than our */
- /* own). */
- //----------------------------------------
- signal->theData[0] = ZREGREQ_TIMELIMIT;
- signal->theData[1] = c_start.m_startKey;
- signal->theData[2] = c_start.m_startNode;
- sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 3000, 3);
-
- creadyDistCom = ZTRUE;
- return;
-}//Qmgr::cmInfoconf010Lab()
-
-void
-Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){
- 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++;
-}
-
-/*
-4.4.11 CM_REGREQ */
-/**--------------------------------------------------------------------------
- * If this signal is received someone tries to get registrated.
- * Only the president have the authority make decissions about new nodes,
- * so only a president or a node that claims to be the president may send a
- * reply to this signal.
- * This signal can occur any time after that STTOR was received.
- * CPRESIDENT: Timelimit has expired and someone has
- * decided to enter the president role
- * CPRESIDENT_CANDIDATE:
- * Assigned when we receive a CM_REGREF, if we got more than one REF
- * then we always keep the lowest nodenumber.
- * We accept this nodeno as president when our timelimit expires
- * We should consider the following cases:
- * 1- We are the president. If we are busy by adding new nodes to cluster,
- * then we have to refuse this node to be added.
- * The refused node will try in ZREFUSE_ADD_TIME seconds again.
- * If we are not busy then we confirm
- *
- * 2- We know the president, we dont bother us about this REQ.
- * The president has also got this REQ and will take care of it.
- *
- * 3- The president are not known. We have received CM_INIT, so we compare the
- * senders node number to GETOWNNODEID().
- * If we have a lower number than the sender then we will claim
- * that we are the president so we send him a refuse signal back.
- * We have to wait for the CONTINUEB signal before we can enter the
- * president role. If our GETOWNNODEID() if larger than sender node number,
- * we are not the president and just have to wait for the
- * reply signal (REF) to our CM_REGREQ_2.
- * 4- We havent received the CM_INIT signal so we don't know who we are.
- * Ignore the request.
- *--------------------------------------------------------------------------*/
-/*******************************/
-/* 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, "");
-
- NodeRecPtr addNodePtr;
- jamEntry();
-
- CmRegReq * const cmRegReq = (CmRegReq *)&signal->theData[0];
- 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();
- /* NOT READY FOR DISTRIBUTED COMMUNICATION.*/
- return;
- }//if
-
- if (!ndbCompatible_ndb_ndb(NDB_VERSION, startingVersion)) {
- jam();
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZINCOMPATIBLE_VERSION);
- return;
- }
-
- 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)
- {
- /***
- * We don't know the president.
- * If the node to be added has lower node id
- * than our president cancidate. Set it as
- * candidate
- */
- jam();
- if (gci > c_start.m_president_candidate_gci ||
- (gci == c_start.m_president_candidate_gci &&
- addNodePtr.i < c_start.m_president_candidate))
- {
- jam();
- 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.
- * President will answer.
- */
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_PRESIDENT);
- return;
- }//if
-
- if (c_start.m_startNode != 0)
- {
- jam();
- /**
- * President busy by adding another node
- */
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZBUSY_PRESIDENT);
- return;
- }//if
-
- if (ctoStatus == Q_ACTIVE)
- {
- jam();
- /**
- * Active taking over as president
- */
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZBUSY_TO_PRES);
- return;
- }//if
-
- if (getNodeInfo(addNodePtr.i).m_type != NodeInfo::DB)
- {
- jam();
- /**
- * The new node is not in config file
- */
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_IN_CFG);
- return;
- }
-
- if (getNodeState().getSingleUserMode())
- {
- /**
- * The cluster is in single user mode.
- * Data node is not allowed to get added in the cluster
- * while in single user mode.
- */
- // handle rolling upgrade
- {
- unsigned int get_major = getMajor(startingVersion);
- unsigned int get_minor = getMinor(startingVersion);
- unsigned int get_build = getBuild(startingVersion);
-
- if (startingVersion < NDBD_QMGR_SINGLEUSER_VERSION_5) {
- jam();
-
- infoEvent("QMGR: detect upgrade: new node %u old version %u.%u.%u",
- (unsigned int)addNodePtr.i, get_major, get_minor, get_build);
- /**
- * The new node is old version, send ZINCOMPATIBLE_VERSION instead
- * of ZSINGLE_USER_MODE.
- */
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZINCOMPATIBLE_VERSION);
- } else {
- jam();
-
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZSINGLE_USER_MODE);
- }//if
- }
-
- return;
- }//if
-
- ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
- Phase phase = addNodePtr.p->phase;
- if (phase != ZINIT)
- {
- jam();
- DEBUG("phase = " << phase);
- sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_DEAD);
- return;
- }
-
- jam();
- /**
- * WE ARE PRESIDENT AND WE ARE NOT BUSY ADDING ANOTHER NODE.
- * WE WILL TAKE CARE OF THE INCLUSION OF THIS NODE INTO THE CLUSTER.
- * WE NEED TO START TIME SUPERVISION OF THIS. SINCE WE CANNOT STOP
- * TIMED SIGNAL IF THE INCLUSION IS INTERRUPTED WE IDENTIFY
- * EACH INCLUSION WITH A UNIQUE IDENTITY. THIS IS CHECKED WHEN
- * THE SIGNAL ARRIVES. IF IT HAS CHANGED THEN WE SIMPLY IGNORE
- * THE TIMED SIGNAL.
- */
-
- /**
- * Update start record
- */
- c_start.m_startKey++;
- c_start.m_startNode = addNodePtr.i;
-
- /**
- * Assign dynamic id
- */
- UintR TdynId = ++c_maxDynamicId;
- setNodeInfo(addNodePtr.i).m_version = startingVersion;
- recompute_version_info(NodeInfo::DB, startingVersion);
- addNodePtr.p->ndynamicId = TdynId;
-
- /**
- * Reply with CM_REGCONF
- */
- CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0];
- cmRegConf->presidentBlockRef = reference();
- cmRegConf->presidentNodeId = getOwnNodeId();
- cmRegConf->presidentVersion = getNodeInfo(getOwnNodeId()).m_version;
- cmRegConf->dynamicId = TdynId;
- c_clusterNodes.copyto(NdbNodeBitmask::Size, cmRegConf->allNdbNodes);
- sendSignal(Tblockref, GSN_CM_REGCONF, signal,
- CmRegConf::SignalLength, JBA);
- DEBUG_START(GSN_CM_REGCONF, refToNode(Tblockref), "");
-
- /**
- * Send CmAdd to all nodes (including starting)
- */
- c_start.m_nodes = c_clusterNodes;
- c_start.m_nodes.setWaitingFor(addNodePtr.i);
- c_start.m_gsn = GSN_CM_ADD;
-
- NodeReceiverGroup rg(QMGR, c_start.m_nodes);
- CmAdd * const cmAdd = (CmAdd*)signal->getDataPtrSend();
- cmAdd->requestType = CmAdd::Prepare;
- cmAdd->startingNodeId = addNodePtr.i;
- cmAdd->startingVersion = startingVersion;
- sendSignal(rg, GSN_CM_ADD, signal, CmAdd::SignalLength, JBA);
- DEBUG_START2(GSN_CM_ADD, rg, "Prepare");
-
- /**
- * Set timer
- */
- return;
- signal->theData[0] = ZREGREQ_MASTER_TIMELIMIT;
- signal->theData[1] = c_start.m_startKey;
- sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 30000, 2);
-
- return;
-}//Qmgr::execCM_REGREQ()
-
-void Qmgr::sendCmRegrefLab(Signal* signal, BlockReference TBRef,
- CmRegRef::ErrorCode Terror)
-{
- CmRegRef* ref = (CmRegRef*)signal->getDataPtrSend();
- ref->blockRef = reference();
- ref->nodeId = getOwnNodeId();
- ref->errorCode = Terror;
- 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), "");
- return;
-}//Qmgr::sendCmRegrefLab()
-
-/*
-4.4.11 CM_REGCONF */
-/**--------------------------------------------------------------------------
- * President gives permission to a node which wants to join the cluster.
- * The president will prepare the cluster that a new node will be added to
- * cluster. When the new node has set up all connections to the cluster,
- * the president will send commit to all clusternodes so the phase of the
- * new node can be changed to ZRUNNING.
- *--------------------------------------------------------------------------*/
-/*******************************/
-/* CM_REGCONF */
-/*******************************/
-void Qmgr::execCM_REGCONF(Signal* signal)
-{
- DEBUG_START3(signal, "");
-
- NodeRecPtr myNodePtr;
- NodeRecPtr nodePtr;
- jamEntry();
-
- const CmRegConf * const cmRegConf = (CmRegConf *)&signal->theData[0];
-
- if (!ndbCompatible_ndb_ndb(NDB_VERSION, cmRegConf->presidentVersion)) {
- jam();
- char buf[128];
- BaseString::snprintf(buf,sizeof(buf),
- "incompatible version own=0x%x other=0x%x, "
- " shutting down",
- NDB_VERSION, cmRegConf->presidentVersion);
- systemErrorLab(signal, __LINE__, buf);
- return;
- }
-
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
-
- ndbrequire(c_start.m_gsn == GSN_CM_REGREQ);
- ndbrequire(myNodePtr.p->phase == ZSTARTING);
-
- cpdistref = cmRegConf->presidentBlockRef;
- cpresident = cmRegConf->presidentNodeId;
- UintR TdynamicId = cmRegConf->dynamicId;
- c_maxDynamicId = TdynamicId;
- c_clusterNodes.assign(NdbNodeBitmask::Size, cmRegConf->allNdbNodes);
-
- myNodePtr.p->ndynamicId = TdynamicId;
-
-/*--------------------------------------------------------------*/
-// Send this as an EVENT REPORT to inform about hearing about
-// other NDB node proclaiming to be president.
-/*--------------------------------------------------------------*/
- signal->theData[0] = NDB_LE_CM_REGCONF;
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = cpresident;
- signal->theData[3] = TdynamicId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
-
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- if (c_clusterNodes.get(nodePtr.i)){
- jam();
- ptrAss(nodePtr, nodeRec);
-
- ndbrequire(nodePtr.p->phase == ZINIT);
- nodePtr.p->phase = ZRUNNING;
-
- if(c_connectedNodes.get(nodePtr.i)){
- jam();
- sendCmNodeInfoReq(signal, nodePtr.i, myNodePtr.p);
- }
- }
- }
-
- c_start.m_gsn = GSN_CM_NODEINFOREQ;
- c_start.m_nodes = c_clusterNodes;
-
- return;
-}//Qmgr::execCM_REGCONF()
-
-void
-Qmgr::check_readnodes_reply(Signal* signal, Uint32 nodeId, Uint32 gsn)
-{
- NodeRecPtr myNodePtr;
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
-
- NodeRecPtr nodePtr;
- nodePtr.i = nodeId;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
-
- ndbrequire(c_readnodes_nodes.get(nodeId));
- ReadNodesConf* conf = (ReadNodesConf*)signal->getDataPtr();
- if (gsn == GSN_READ_NODESREF)
- {
- jam();
-retry:
- signal->theData[0] = reference();
- sendSignal(calcQmgrBlockRef(nodeId), GSN_READ_NODESREQ, signal, 1, JBA);
- return;
- }
-
- if (conf->masterNodeId == ZNIL)
- {
- jam();
- goto retry;
- }
-
- Uint32 president = conf->masterNodeId;
- if (president == cpresident)
- {
- jam();
- c_readnodes_nodes.clear(nodeId);
- return;
- }
-
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "check StartPartialTimeout, "
- "node %d thinks %d is president, "
- "I think president is: %d",
- nodeId, president, cpresident);
-
- ndbout_c(buf);
- CRASH_INSERTION(933);
-
- if (getNodeState().startLevel == NodeState::SL_STARTED)
- {
- jam();
- NdbNodeBitmask part;
- part.assign(NdbNodeBitmask::Size, conf->clusterNodes);
- FailRep* rep = (FailRep*)signal->getDataPtrSend();
- rep->failCause = FailRep::ZPARTITIONED_CLUSTER;
- rep->president = cpresident;
- c_clusterNodes.copyto(NdbNodeBitmask::Size, rep->partition);
- Uint32 ref = calcQmgrBlockRef(nodeId);
- Uint32 i = 0;
- while((i = part.find(i + 1)) != NdbNodeBitmask::NotFound)
- {
- if (i == nodeId)
- continue;
- rep->failNodeId = i;
- sendSignal(ref, GSN_FAIL_REP, signal, FailRep::SignalLength, JBA);
- }
- rep->failNodeId = nodeId;
- sendSignal(ref, GSN_FAIL_REP, signal, FailRep::SignalLength, JBB);
- return;
- }
-
- CRASH_INSERTION(932);
-
- progError(__LINE__,
- NDBD_EXIT_PARTITIONED_SHUTDOWN,
- buf);
-
- ndbrequire(false);
-}
-
-void
-Qmgr::sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self){
- CmNodeInfoReq * const req = (CmNodeInfoReq*)signal->getDataPtrSend();
- req->nodeId = getOwnNodeId();
- req->dynamicId = self->ndynamicId;
- req->version = getNodeInfo(getOwnNodeId()).m_version;
- const Uint32 ref = calcQmgrBlockRef(nodeId);
- sendSignal(ref,GSN_CM_NODEINFOREQ, signal, CmNodeInfoReq::SignalLength, JBB);
- DEBUG_START(GSN_CM_NODEINFOREQ, nodeId, "");
-}
-
-/*
-4.4.11 CM_REGREF */
-/**--------------------------------------------------------------------------
- * Only a president or a president candidate can refuse a node to get added to
- * the cluster.
- * Refuse reasons:
- * ZBUSY We know that the sender is the president and we have to
- * make a new CM_REGREQ.
- * ZNOT_IN_CFG This node number is not specified in the configfile,
- * SYSTEM ERROR
- * ZELECTION Sender is a president candidate, his timelimit
- * hasn't expired so maybe someone else will show up.
- * Update the CPRESIDENT_CANDIDATE, then wait for our
- * timelimit to expire.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* 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();
-
- 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);
-
- 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 != c_start.m_president_candidate)
- {
- jam();
- 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);
- }
- c_start.m_node_gci[TaddNodeno] = node_gci;
-
- 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");
- 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:
- case CmRegRef::ZBUSY_PRESIDENT:
- jam();
- cpresidentAlive = ZTRUE;
- signal->theData[3] = 0;
- break;
- case CmRegRef::ZNOT_IN_CFG:
- jam();
- progError(__LINE__, NDBD_EXIT_NODE_NOT_IN_CONFIG);
- break;
- case CmRegRef::ZNOT_DEAD:
- jam();
- progError(__LINE__, NDBD_EXIT_NODE_NOT_DEAD);
- break;
- case CmRegRef::ZSINGLE_USER_MODE:
- jam();
- progError(__LINE__, NDBD_EXIT_SINGLE_USER_MODE);
- break;
- /**
- * For generic refuse error.
- * e.g. in online upgrade, we can use this error code instead
- * of the incompatible error code.
- */
- case CmRegRef::ZGENERIC:
- jam();
- progError(__LINE__, NDBD_EXIT_GENERIC);
- break;
- case CmRegRef::ZELECTION:
- jam();
- 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;
- c_start.m_president_candidate = candidate;
- c_start.m_president_candidate_gci = candidate_gci;
- } else {
- signal->theData[3] = 4;
- }//if
- break;
- case CmRegRef::ZNOT_PRESIDENT:
- jam();
- cpresidentAlive = ZTRUE;
- signal->theData[3] = 3;
- break;
- default:
- jam();
- signal->theData[3] = 5;
- /*empty*/;
- break;
- }//switch
-/*--------------------------------------------------------------*/
-// Send this as an EVENT REPORT to inform about hearing about
-// other NDB node proclaiming not to be president.
-/*--------------------------------------------------------------*/
- signal->theData[0] = NDB_LE_CM_REGREF;
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = TaddNodeno;
-//-----------------------------------------
-// signal->theData[3] filled in above
-//-----------------------------------------
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
-
- if(cpresidentAlive == ZTRUE)
- {
- jam();
- DEBUG("cpresidentAlive");
- return;
- }
-
- if(c_start.m_regReqReqSent != c_start.m_regReqReqRecv)
- {
- jam();
- DEBUG(c_start.m_regReqReqSent << " != " << c_start.m_regReqReqRecv);
- return;
- }
-
- if(c_start.m_president_candidate != getOwnNodeId())
- {
- jam();
- DEBUG("i'm not the candidate");
- return;
- }
-
- /**
- * All connected nodes has agreed
- */
- if(check_startup(signal))
- {
- jam();
- electionWon(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;
- Uint32 incompleteng = MAX_NDB_NODES; // Illegal value
- 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
- */
- 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 check_log;
- 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 check_log;
- }
- }
-
- if (now < partial_timeout)
- {
- jam();
- signal->theData[1] = c_restartPartialTimeout == (Uint32) ~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)
- {
- goto missinglog;
- }
- // 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 = 2;
- goto check_log;
- }
- }
- ndbrequire(false);
-
-check_log:
- jam();
- {
- Uint32 save[4+4*NdbNodeBitmask::Size];
- memcpy(save, signal->theData, sizeof(save));
-
- signal->theData[0] = 0;
- c_start.m_starting_nodes.copyto(NdbNodeBitmask::Size, signal->theData+1);
- memcpy(signal->theData+1+NdbNodeBitmask::Size, c_start.m_node_gci,
- 4*MAX_NDB_NODES);
- EXECUTE_DIRECT(DBDIH, GSN_DIH_RESTARTREQ, signal,
- 1+NdbNodeBitmask::Size+MAX_NDB_NODES);
-
- incompleteng = signal->theData[0];
- memcpy(signal->theData, save, sizeof(save));
-
- if (incompleteng != MAX_NDB_NODES)
- {
- jam();
- if (retVal == 1)
- {
- jam();
- goto incomplete_log;
- }
- else if (retVal == 2)
- {
- if (now <= partitioned_timeout)
- {
- jam();
- goto missinglog;
- }
- else
- {
- goto incomplete_log;
- }
- }
- ndbrequire(false);
- }
- }
- goto start_report;
-
-missinglog:
- signal->theData[1] = c_restartPartionedTimeout == (Uint32) ~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;
-
-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_INSUFFICENT_NODES, buf);
- return 0; // Deadcode
- }
-
-incomplete_log:
- jam();
- {
- char buf[100], mask1[100];
- c_start.m_starting_nodes.getText(mask1);
- BaseString::snprintf(buf, sizeof(buf),
- "Incomplete log for node group: %d! "
- " starting nodes: %s",
- incompleteng, mask1);
- progError(__LINE__, NDBD_EXIT_INSUFFICENT_NODES, buf);
- return 0; // Deadcode
- }
-}
-
-void
-Qmgr::electionWon(Signal* signal){
- NodeRecPtr myNodePtr;
- cpresident = getOwnNodeId(); /* This node becomes president. */
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
-
- myNodePtr.p->phase = ZRUNNING;
-
- cpdistref = reference();
- cneighbourl = ZNIL;
- cneighbourh = ZNIL;
- myNodePtr.p->ndynamicId = 1;
- c_maxDynamicId = 1;
- c_clusterNodes.clear();
- c_clusterNodes.set(getOwnNodeId());
-
- cpresidentAlive = ZTRUE;
- c_start_election_time = ~0;
- c_start.reset();
-
- 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);
- }
-}
-
-/*
-4.4.11 CONTINUEB */
-/*--------------------------------------------------------------------------*/
-/* */
-/*--------------------------------------------------------------------------*/
-/****************************>---------------------------------------------*/
-/* CONTINUEB > SENDER: Own block, Own node */
-/****************************>-------+INPUT : TCONTINUEB_TYPE */
-/*--------------------------------------------------------------*/
-void Qmgr::regreqTimeLimitLab(Signal* signal)
-{
- if(cpresident == ZNIL)
- {
- if (c_start.m_president_candidate == ZNIL)
- {
- jam();
- c_start.m_president_candidate = getOwnNodeId();
- }
-
- cmInfoconf010Lab(signal);
- }
-}//Qmgr::regreqTimelimitLab()
-
-/**---------------------------------------------------------------------------
- * The new node will take care of giving information about own node and ask
- * all other nodes for nodeinfo. The new node will use CM_NODEINFOREQ for
- * that purpose. When the setup of connections to all running, the president
- * will send a commit to all running nodes + the new node
- * INPUT: NODE_PTR1, must be set as ZNIL if we don't enter CONNECT_NODES)
- * from signal CM_NODEINFOCONF.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* CM_NODEINFOCONF */
-/*******************************/
-void Qmgr::execCM_NODEINFOCONF(Signal* signal)
-{
- DEBUG_START3(signal, "");
-
- jamEntry();
-
- CmNodeInfoConf * const conf = (CmNodeInfoConf*)signal->getDataPtr();
-
- const Uint32 nodeId = conf->nodeId;
- const Uint32 dynamicId = conf->dynamicId;
- const Uint32 version = conf->version;
-
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrAss(nodePtr, nodeRec);
- ndbrequire(nodePtr.p->phase == ZSTARTING);
- ndbrequire(c_start.m_gsn == GSN_CM_NODEINFOREQ);
- c_start.m_nodes.clearWaitingFor(nodeId);
-
- /**
- * Update node info
- */
- NodeRecPtr replyNodePtr;
- replyNodePtr.i = nodeId;
- ptrCheckGuard(replyNodePtr, MAX_NDB_NODES, nodeRec);
- replyNodePtr.p->ndynamicId = dynamicId;
- replyNodePtr.p->blockRef = signal->getSendersBlockRef();
- setNodeInfo(replyNodePtr.i).m_version = version;
- recompute_version_info(NodeInfo::DB, version);
-
- if(!c_start.m_nodes.done()){
- jam();
- return;
- }
-
- /**********************************************<*/
- /* Send an ack. back to the president. */
- /* CM_ACKADD */
- /* The new node has been registered by all */
- /* running nodes and has stored nodeinfo about */
- /* all running nodes. The new node has to wait */
- /* for CM_ADD (commit) from president to become */
- /* a running node in the cluster. */
- /**********************************************<*/
- sendCmAckAdd(signal, getOwnNodeId(), CmAdd::Prepare);
- return;
-}//Qmgr::execCM_NODEINFOCONF()
-
-/**---------------------------------------------------------------------------
- * A new node sends nodeinfo about himself. The new node asks for
- * corresponding nodeinfo back in the CM_NODEINFOCONF.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* CM_NODEINFOREQ */
-/*******************************/
-void Qmgr::execCM_NODEINFOREQ(Signal* signal)
-{
- jamEntry();
-
- const Uint32 Tblockref = signal->getSendersBlockRef();
-
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrAss(nodePtr, nodeRec);
- if(nodePtr.p->phase != ZRUNNING){
- jam();
- signal->theData[0] = reference();
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = ZNOT_RUNNING;
- sendSignal(Tblockref, GSN_CM_NODEINFOREF, signal, 3, JBB);
- return;
- }
-
- NodeRecPtr addNodePtr;
- CmNodeInfoReq * const req = (CmNodeInfoReq*)signal->getDataPtr();
- addNodePtr.i = req->nodeId;
- ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
- addNodePtr.p->ndynamicId = req->dynamicId;
- addNodePtr.p->blockRef = signal->getSendersBlockRef();
- setNodeInfo(addNodePtr.i).m_version = req->version;
- c_maxDynamicId = req->dynamicId;
-
- cmAddPrepare(signal, addNodePtr, nodePtr.p);
-}//Qmgr::execCM_NODEINFOREQ()
-
-void
-Qmgr::cmAddPrepare(Signal* signal, NodeRecPtr nodePtr, const NodeRec * self){
- jam();
-
- switch(nodePtr.p->phase){
- case ZINIT:
- jam();
- nodePtr.p->phase = ZSTARTING;
- return;
- case ZFAIL_CLOSING:
- jam();
-
-#if 1
- warningEvent("Recieved request to incorperate node %u, "
- "while error handling has not yet completed",
- nodePtr.i);
-
- ndbrequire(getOwnNodeId() != cpresident);
- ndbrequire(signal->header.theVerId_signalNumber == GSN_CM_ADD);
- c_start.m_nodes.clearWaitingFor();
- c_start.m_nodes.setWaitingFor(nodePtr.i);
- c_start.m_gsn = GSN_CM_NODEINFOCONF;
-#else
- warningEvent("Enabling communication to CM_ADD node %u state=%d",
- nodePtr.i,
- nodePtr.p->phase);
- nodePtr.p->phase = ZSTARTING;
- nodePtr.p->failState = NORMAL;
- signal->theData[0] = 0;
- signal->theData[1] = nodePtr.i;
- sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 2, JBA);
-#endif
- return;
- case ZSTARTING:
- break;
- case ZRUNNING:
- case ZPREPARE_FAIL:
- case ZAPI_ACTIVE:
- case ZAPI_INACTIVE:
- ndbrequire(false);
- }
-
- sendCmAckAdd(signal, nodePtr.i, CmAdd::Prepare);
- sendApiVersionRep(signal, nodePtr);
-
- /* President have prepared us */
- CmNodeInfoConf * conf = (CmNodeInfoConf*)signal->getDataPtrSend();
- conf->nodeId = getOwnNodeId();
- conf->dynamicId = self->ndynamicId;
- conf->version = getNodeInfo(getOwnNodeId()).m_version;
- sendSignal(nodePtr.p->blockRef, GSN_CM_NODEINFOCONF, signal,
- CmNodeInfoConf::SignalLength, JBB);
- DEBUG_START(GSN_CM_NODEINFOCONF, refToNode(nodePtr.p->blockRef), "");
-}
-
-void
-Qmgr::sendApiVersionRep(Signal* signal, NodeRecPtr nodePtr)
-{
- if (getNodeInfo(nodePtr.i).m_version >= NDBD_NODE_VERSION_REP)
- {
- jam();
- Uint32 ref = calcQmgrBlockRef(nodePtr.i);
- for(Uint32 i = 1; i<MAX_NODES; i++)
- {
- jam();
- Uint32 version = getNodeInfo(i).m_version;
- Uint32 type = getNodeInfo(i).m_type;
- if (type != NodeInfo::DB && version)
- {
- jam();
- signal->theData[0] = i;
- signal->theData[1] = version;
- sendSignal(ref, GSN_NODE_VERSION_REP, signal, 2, JBB);
- }
- }
- }
-}
-
-void
-Qmgr::sendCmAckAdd(Signal * signal, Uint32 nodeId, CmAdd::RequestType type){
-
- CmAckAdd * cmAckAdd = (CmAckAdd*)signal->getDataPtrSend();
- cmAckAdd->requestType = type;
- cmAckAdd->startingNodeId = nodeId;
- cmAckAdd->senderNodeId = getOwnNodeId();
- sendSignal(cpdistref, GSN_CM_ACKADD, signal, CmAckAdd::SignalLength, JBA);
- DEBUG_START(GSN_CM_ACKADD, cpresident, "");
-
- switch(type){
- case CmAdd::Prepare:
- return;
- case CmAdd::AddCommit:
- case CmAdd::CommitNew:
- break;
- }
-
- signal->theData[0] = nodeId;
- EXECUTE_DIRECT(NDBCNTR, GSN_CM_ADD_REP, signal, 1);
- jamEntry();
-}
-
-/*
-4.4.11 CM_ADD */
-/**--------------------------------------------------------------------------
- * Prepare a running node to add a new node to the cluster. The running node
- * will change phase of the new node fron ZINIT to ZWAITING. The running node
- * will also mark that we have received a prepare. When the new node has sent
- * us nodeinfo we can send an acknowledgement back to the president. When all
- * running nodes has acknowledged the new node, the president will send a
- * commit and we can change phase of the new node to ZRUNNING. The president
- * will also send CM_ADD to himself.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* CM_ADD */
-/*******************************/
-void Qmgr::execCM_ADD(Signal* signal)
-{
- NodeRecPtr addNodePtr;
- jamEntry();
-
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
-
- CmAdd * const cmAdd = (CmAdd*)signal->getDataPtr();
- const CmAdd::RequestType type = (CmAdd::RequestType)cmAdd->requestType;
- addNodePtr.i = cmAdd->startingNodeId;
- //const Uint32 startingVersion = cmAdd->startingVersion;
- ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
-
- DEBUG_START3(signal, type);
-
- if(nodePtr.p->phase == ZSTARTING){
- jam();
- /**
- * We are joining...
- */
- ndbrequire(addNodePtr.i == nodePtr.i);
- switch(type){
- case CmAdd::Prepare:
- ndbrequire(c_start.m_gsn == GSN_CM_NODEINFOREQ);
- /**
- * Wait for CM_NODEINFO_CONF
- */
- return;
- case CmAdd::CommitNew:
- /**
- * Tata. we're in the cluster
- */
- joinedCluster(signal, addNodePtr);
- return;
- case CmAdd::AddCommit:
- ndbrequire(false);
- }
- }
-
- switch (type) {
- case CmAdd::Prepare:
- cmAddPrepare(signal, addNodePtr, nodePtr.p);
- break;
- case CmAdd::AddCommit:{
- jam();
- ndbrequire(addNodePtr.p->phase == ZSTARTING);
- addNodePtr.p->phase = ZRUNNING;
- setNodeInfo(addNodePtr.i).m_heartbeat_cnt= 0;
- c_clusterNodes.set(addNodePtr.i);
- findNeighbours(signal);
-
- /**
- * SEND A HEARTBEAT IMMEDIATELY TO DECREASE THE RISK THAT WE MISS EARLY
- * HEARTBEATS.
- */
- sendHeartbeat(signal);
-
- /**
- * ENABLE COMMUNICATION WITH ALL BLOCKS WITH THE NEWLY ADDED NODE
- */
- signal->theData[0] = addNodePtr.i;
- sendSignal(CMVMI_REF, GSN_ENABLE_COMORD, signal, 1, JBA);
-
- sendCmAckAdd(signal, addNodePtr.i, CmAdd::AddCommit);
- if(getOwnNodeId() != cpresident){
- jam();
- c_start.reset();
- }
- break;
- }
- case CmAdd::CommitNew:
- jam();
- ndbrequire(false);
- }
-
-}//Qmgr::execCM_ADD()
-
-void
-Qmgr::joinedCluster(Signal* signal, NodeRecPtr nodePtr){
- /**
- * WE HAVE BEEN INCLUDED IN THE CLUSTER WE CAN START BEING PART OF THE
- * HEARTBEAT PROTOCOL AND WE WILL ALSO ENABLE COMMUNICATION WITH ALL
- * NODES IN THE CLUSTER.
- */
- nodePtr.p->phase = ZRUNNING;
- setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
- findNeighbours(signal);
- c_clusterNodes.set(nodePtr.i);
- c_start.reset();
-
- /**
- * SEND A HEARTBEAT IMMEDIATELY TO DECREASE THE RISK
- * THAT WE MISS EARLY HEARTBEATS.
- */
- sendHeartbeat(signal);
-
- /**
- * ENABLE COMMUNICATION WITH ALL BLOCKS IN THE CURRENT CLUSTER AND SET
- * THE NODES IN THE CLUSTER TO BE RUNNING.
- */
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if ((nodePtr.p->phase == ZRUNNING) && (nodePtr.i != getOwnNodeId())) {
- /*-------------------------------------------------------------------*/
- // Enable full communication to all other nodes. Not really necessary
- // to open communication to ourself.
- /*-------------------------------------------------------------------*/
- jam();
- signal->theData[0] = nodePtr.i;
- sendSignal(CMVMI_REF, GSN_ENABLE_COMORD, signal, 1, JBA);
- }//if
- }//for
-
- sendSttorryLab(signal);
-
- sendCmAckAdd(signal, getOwnNodeId(), CmAdd::CommitNew);
-}
-
-/* 4.10.7 CM_ACKADD - PRESIDENT IS RECEIVER - */
-/*---------------------------------------------------------------------------*/
-/* Entry point for an ack add signal.
- * The TTYPE defines if it is a prepare or a commit. */
-/*---------------------------------------------------------------------------*/
-void Qmgr::execCM_ACKADD(Signal* signal)
-{
- NodeRecPtr addNodePtr;
- NodeRecPtr senderNodePtr;
- jamEntry();
-
- CmAckAdd * const cmAckAdd = (CmAckAdd*)signal->getDataPtr();
- const CmAdd::RequestType type = (CmAdd::RequestType)cmAckAdd->requestType;
- addNodePtr.i = cmAckAdd->startingNodeId;
- senderNodePtr.i = cmAckAdd->senderNodeId;
-
- DEBUG_START3(signal, type);
-
- if (cpresident != getOwnNodeId()) {
- jam();
- /*-----------------------------------------------------------------------*/
- /* IF WE ARE NOT PRESIDENT THEN WE SHOULD NOT RECEIVE THIS MESSAGE. */
- /*------------------------------------------------------------_----------*/
- warningEvent("Received CM_ACKADD from %d president=%d",
- senderNodePtr.i, cpresident);
- return;
- }//if
-
- if (addNodePtr.i != c_start.m_startNode) {
- jam();
- /*----------------------------------------------------------------------*/
- /* THIS IS NOT THE STARTING NODE. WE ARE ACTIVE NOW WITH ANOTHER START. */
- /*----------------------------------------------------------------------*/
- warningEvent("Received CM_ACKADD from %d with startNode=%d != own %d",
- senderNodePtr.i, addNodePtr.i, c_start.m_startNode);
- return;
- }//if
-
- ndbrequire(c_start.m_gsn == GSN_CM_ADD);
- c_start.m_nodes.clearWaitingFor(senderNodePtr.i);
- if(!c_start.m_nodes.done()){
- jam();
- return;
- }
-
- switch (type) {
- case CmAdd::Prepare:{
- jam();
-
- /*----------------------------------------------------------------------*/
- /* ALL RUNNING NODES HAVE PREPARED THE INCLUSION OF THIS NEW NODE. */
- /*----------------------------------------------------------------------*/
- c_start.m_gsn = GSN_CM_ADD;
- c_start.m_nodes = c_clusterNodes;
-
- CmAdd * const cmAdd = (CmAdd*)signal->getDataPtrSend();
- cmAdd->requestType = CmAdd::AddCommit;
- cmAdd->startingNodeId = addNodePtr.i;
- cmAdd->startingVersion = getNodeInfo(addNodePtr.i).m_version;
- NodeReceiverGroup rg(QMGR, c_clusterNodes);
- sendSignal(rg, GSN_CM_ADD, signal, CmAdd::SignalLength, JBA);
- DEBUG_START2(GSN_CM_ADD, rg, "AddCommit");
- return;
- }
- case CmAdd::AddCommit:{
- jam();
-
- /****************************************/
- /* Send commit to the new node so he */
- /* will change PHASE into ZRUNNING */
- /****************************************/
- c_start.m_gsn = GSN_CM_ADD;
- c_start.m_nodes.clearWaitingFor();
- c_start.m_nodes.setWaitingFor(addNodePtr.i);
-
- CmAdd * const cmAdd = (CmAdd*)signal->getDataPtrSend();
- cmAdd->requestType = CmAdd::CommitNew;
- cmAdd->startingNodeId = addNodePtr.i;
- cmAdd->startingVersion = getNodeInfo(addNodePtr.i).m_version;
-
- sendSignal(calcQmgrBlockRef(addNodePtr.i), GSN_CM_ADD, signal,
- CmAdd::SignalLength, JBA);
- DEBUG_START(GSN_CM_ADD, addNodePtr.i, "CommitNew");
- return;
- }
- case CmAdd::CommitNew:
- jam();
- /**
- * Tell arbitration about new node.
- */
- 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);
-}//Qmgr::execCM_ACKADD()
-
-/**-------------------------------------------------------------------------
- * WE HAVE BEEN INCLUDED INTO THE CLUSTER. IT IS NOW TIME TO CALCULATE WHICH
- * ARE OUR LEFT AND RIGHT NEIGHBOURS FOR THE HEARTBEAT PROTOCOL.
- *--------------------------------------------------------------------------*/
-void Qmgr::findNeighbours(Signal* signal)
-{
- UintR toldLeftNeighbour;
- UintR tfnLeftFound;
- UintR tfnMaxFound;
- UintR tfnMinFound;
- UintR tfnRightFound;
- NodeRecPtr fnNodePtr;
- NodeRecPtr fnOwnNodePtr;
-
- toldLeftNeighbour = cneighbourl;
- tfnLeftFound = 0;
- tfnMaxFound = 0;
- tfnMinFound = (UintR)-1;
- tfnRightFound = (UintR)-1;
- fnOwnNodePtr.i = getOwnNodeId();
- ptrCheckGuard(fnOwnNodePtr, MAX_NDB_NODES, nodeRec);
- for (fnNodePtr.i = 1; fnNodePtr.i < MAX_NDB_NODES; fnNodePtr.i++) {
- jam();
- ptrAss(fnNodePtr, nodeRec);
- if (fnNodePtr.i != fnOwnNodePtr.i) {
- if (fnNodePtr.p->phase == ZRUNNING) {
- if (tfnMinFound > fnNodePtr.p->ndynamicId) {
- jam();
- tfnMinFound = fnNodePtr.p->ndynamicId;
- }//if
- if (tfnMaxFound < fnNodePtr.p->ndynamicId) {
- jam();
- tfnMaxFound = fnNodePtr.p->ndynamicId;
- }//if
- if (fnOwnNodePtr.p->ndynamicId > fnNodePtr.p->ndynamicId) {
- jam();
- if (fnNodePtr.p->ndynamicId > tfnLeftFound) {
- jam();
- tfnLeftFound = fnNodePtr.p->ndynamicId;
- }//if
- } else {
- jam();
- if (fnNodePtr.p->ndynamicId < tfnRightFound) {
- jam();
- tfnRightFound = fnNodePtr.p->ndynamicId;
- }//if
- }//if
- }//if
- }//if
- }//for
- if (tfnLeftFound == 0) {
- if (tfnMinFound == (UintR)-1) {
- jam();
- cneighbourl = ZNIL;
- } else {
- jam();
- cneighbourl = translateDynamicIdToNodeId(signal, tfnMaxFound);
- }//if
- } else {
- jam();
- cneighbourl = translateDynamicIdToNodeId(signal, tfnLeftFound);
- }//if
- if (tfnRightFound == (UintR)-1) {
- if (tfnMaxFound == 0) {
- jam();
- cneighbourh = ZNIL;
- } else {
- jam();
- cneighbourh = translateDynamicIdToNodeId(signal, tfnMinFound);
- }//if
- } else {
- jam();
- cneighbourh = translateDynamicIdToNodeId(signal, tfnRightFound);
- }//if
- if (toldLeftNeighbour != cneighbourl) {
- jam();
- if (cneighbourl != ZNIL) {
- jam();
- /**-------------------------------------------------------------------*/
- /* WE ARE SUPERVISING A NEW LEFT NEIGHBOUR. WE START WITH ALARM COUNT
- * EQUAL TO ZERO.
- *---------------------------------------------------------------------*/
- fnNodePtr.i = cneighbourl;
- ptrCheckGuard(fnNodePtr, MAX_NDB_NODES, nodeRec);
- setNodeInfo(fnNodePtr.i).m_heartbeat_cnt= 0;
- }//if
- }//if
-
- signal->theData[0] = NDB_LE_FIND_NEIGHBOURS;
- signal->theData[1] = getOwnNodeId();
- signal->theData[2] = cneighbourl;
- signal->theData[3] = cneighbourh;
- signal->theData[4] = fnOwnNodePtr.p->ndynamicId;
- UintR Tlen = 5;
- for (fnNodePtr.i = 1; fnNodePtr.i < MAX_NDB_NODES; fnNodePtr.i++) {
- jam();
- ptrAss(fnNodePtr, nodeRec);
- if (fnNodePtr.i != fnOwnNodePtr.i) {
- if (fnNodePtr.p->phase == ZRUNNING) {
- jam();
- signal->theData[Tlen] = fnNodePtr.i;
- signal->theData[Tlen + 1] = fnNodePtr.p->ndynamicId;
- if (Tlen < 25) {
- /*----------------------------------------------------------------*/
- // This code can only report 11 nodes.
- // We need to update this when increasing the number of nodes
- // supported.
- /*-----------------------------------------------------------------*/
- Tlen += 2;
- }
- }//if
- }//if
- }//for
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, Tlen, JBB);
-}//Qmgr::findNeighbours()
-
-/*
-4.10.7 INIT_DATA */
-/*---------------------------------------------------------------------------*/
-/*---------------------------------------------------------------------------*/
-void Qmgr::initData(Signal* signal)
-{
- cfailureNr = 1;
- ccommitFailureNr = 1;
- cprepareFailureNr = 1;
- cnoFailedNodes = 0;
- cnoPrepFailedNodes = 0;
- creadyDistCom = ZFALSE;
- cpresident = ZNIL;
- c_start.m_president_candidate = ZNIL;
- c_start.m_president_candidate_gci = 0;
- cpdistref = 0;
- cneighbourh = ZNIL;
- cneighbourl = ZNIL;
- cdelayRegreq = ZDELAY_REGREQ;
- cactivateApiCheck = 0;
- ctoStatus = Q_NOT_ACTIVE;
-
- interface_check_timer.setDelay(1000);
- interface_check_timer.reset();
- clatestTransactionCheck = 0;
-
- cLqhTimeSignalCount = 0;
-
- // catch-all for missing initializations
- memset(&arbitRec, 0, sizeof(arbitRec));
-
- /**
- * Timeouts
- */
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Uint32 hbDBDB = 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_ARBIT_TIMEOUT, &arbitTimeout);
- ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT,
- &c_restartPartialTimeout);
- 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);
- setArbitTimeout(arbitTimeout);
-
- arbitRec.state = ARBIT_NULL; // start state for all nodes
- arbitRec.apiMask[0].clear(); // prepare for ARBIT_CFG
-
- ArbitSignalData* const sd = (ArbitSignalData*)&signal->theData[0];
- for (unsigned rank = 1; rank <= 2; rank++) {
- sd->sender = getOwnNodeId();
- sd->code = rank;
- sd->node = 0;
- sd->ticket.clear();
- sd->mask.clear();
- ndb_mgm_configuration_iterator * iter =
- m_ctx.m_config.getClusterConfigIterator();
- for (ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)) {
- Uint32 tmp = 0;
- if (ndb_mgm_get_int_parameter(iter, CFG_NODE_ARBIT_RANK, &tmp) == 0 &&
- tmp == rank){
- Uint32 nodeId = 0;
- ndbrequire(!ndb_mgm_get_int_parameter(iter, CFG_NODE_ID, &nodeId));
- sd->mask.set(nodeId);
- }
- }
-
- execARBIT_CFG(signal);
- }
-}//Qmgr::initData()
-
-
-/**---------------------------------------------------------------------------
- * HERE WE RECEIVE THE JOB TABLE SIGNAL EVERY 10 MILLISECONDS.
- * WE WILL USE THIS TO CHECK IF IT IS TIME TO CHECK THE NEIGHBOUR NODE.
- * WE WILL ALSO SEND A SIGNAL TO BLOCKS THAT NEED A TIME SIGNAL AND
- * DO NOT WANT TO USE JOB TABLE SIGNALS.
- *---------------------------------------------------------------------------*/
-void Qmgr::timerHandlingLab(Signal* signal)
-{
- NDB_TICKS TcurrentTime = NdbTick_CurrentMillisecond();
- NodeRecPtr myNodePtr;
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
-
- if (myNodePtr.p->phase == ZRUNNING) {
- jam();
- /**---------------------------------------------------------------------
- * WE ARE ONLY PART OF HEARTBEAT CLUSTER IF WE ARE UP AND RUNNING.
- *---------------------------------------------------------------------*/
- if (hb_send_timer.check(TcurrentTime)) {
- jam();
- sendHeartbeat(signal);
- hb_send_timer.reset();
- }
- if (hb_check_timer.check(TcurrentTime)) {
- jam();
- checkHeartbeat(signal);
- hb_check_timer.reset();
- }
- }
-
- if (interface_check_timer.check(TcurrentTime)) {
- jam();
- interface_check_timer.reset();
- checkStartInterface(signal);
- }
-
- if (hb_api_timer.check(TcurrentTime))
- {
- jam();
- hb_api_timer.reset();
- apiHbHandlingLab(signal);
- }
-
- if (cactivateApiCheck != 0) {
- jam();
- if (clatestTransactionCheck == 0) {
- //-------------------------------------------------------------
- // Initialise the Transaction check timer.
- //-------------------------------------------------------------
- clatestTransactionCheck = TcurrentTime;
- }//if
- int counter = 0;
- while (TcurrentTime > ((NDB_TICKS)10 + clatestTransactionCheck)) {
- jam();
- clatestTransactionCheck += (NDB_TICKS)10;
- sendSignal(DBTC_REF, GSN_TIME_SIGNAL, signal, 1, JBB);
- cLqhTimeSignalCount++;
- if (cLqhTimeSignalCount >= 100) {
- cLqhTimeSignalCount = 0;
- sendSignal(DBLQH_REF, GSN_TIME_SIGNAL, signal, 1, JBB);
- }//if
- counter++;
- if (counter > 1) {
- jam();
- break;
- } else {
- ;
- }//if
- }//while
- }//if
-
- //--------------------------------------------------
- // Resend this signal with 10 milliseconds delay.
- //--------------------------------------------------
- signal->theData[0] = ZTIMER_HANDLING;
- sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, 10, 1);
- return;
-}//Qmgr::timerHandlingLab()
-
-/*---------------------------------------------------------------------------*/
-/* THIS MODULE HANDLES THE SENDING AND RECEIVING OF HEARTBEATS. */
-/*---------------------------------------------------------------------------*/
-void Qmgr::sendHeartbeat(Signal* signal)
-{
- NodeRecPtr localNodePtr;
- localNodePtr.i = cneighbourh;
- if (localNodePtr.i == ZNIL) {
- jam();
- /**---------------------------------------------------------------------
- * THERE ARE NO NEIGHBOURS. THIS IS POSSIBLE IF WE ARE THE ONLY NODE IN
- * THE CLUSTER.IN THIS CASE WE DO NOT NEED TO SEND ANY HEARTBEAT SIGNALS.
- *-----------------------------------------------------------------------*/
- return;
- }//if
- ptrCheckGuard(localNodePtr, MAX_NDB_NODES, nodeRec);
- signal->theData[0] = getOwnNodeId();
-
- sendSignal(localNodePtr.p->blockRef, GSN_CM_HEARTBEAT, signal, 1, JBA);
-#ifdef VM_TRACE
- signal->theData[0] = NDB_LE_SentHeartbeat;
- signal->theData[1] = localNodePtr.i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-#endif
-}//Qmgr::sendHeartbeat()
-
-void Qmgr::checkHeartbeat(Signal* signal)
-{
- NodeRecPtr nodePtr;
-
- nodePtr.i = cneighbourl;
- if (nodePtr.i == ZNIL) {
- jam();
- /**---------------------------------------------------------------------
- * THERE ARE NO NEIGHBOURS. THIS IS POSSIBLE IF WE ARE THE ONLY NODE IN
- * THE CLUSTER. IN THIS CASE WE DO NOT NEED TO CHECK ANY HEARTBEATS.
- *-----------------------------------------------------------------------*/
- return;
- }//if
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
-
- setNodeInfo(nodePtr.i).m_heartbeat_cnt++;
- ndbrequire(nodePtr.p->phase == ZRUNNING);
- ndbrequire(getNodeInfo(nodePtr.i).m_type == NodeInfo::DB);
-
- if(getNodeInfo(nodePtr.i).m_heartbeat_cnt > 2){
- signal->theData[0] = NDB_LE_MissedHeartbeat;
- signal->theData[1] = nodePtr.i;
- signal->theData[2] = getNodeInfo(nodePtr.i).m_heartbeat_cnt - 1;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
- }
-
- 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] = NDB_LE_DeadDueToHeartbeat;
- signal->theData[1] = nodePtr.i;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- failReportLab(signal, nodePtr.i, FailRep::ZHEARTBEAT_FAILURE);
- return;
- }//if
-}//Qmgr::checkHeartbeat()
-
-void Qmgr::apiHbHandlingLab(Signal* signal)
-{
- NodeRecPtr TnodePtr;
-
- for (TnodePtr.i = 1; TnodePtr.i < MAX_NODES; TnodePtr.i++) {
- const Uint32 nodeId = TnodePtr.i;
- ptrAss(TnodePtr, nodeRec);
-
- const NodeInfo::NodeType type = getNodeInfo(nodeId).getType();
- if(type == NodeInfo::DB)
- continue;
-
- if(type == NodeInfo::INVALID)
- continue;
-
- if (c_connectedNodes.get(nodeId))
- {
- jam();
- setNodeInfo(TnodePtr.i).m_heartbeat_cnt++;
-
- if(getNodeInfo(TnodePtr.i).m_heartbeat_cnt > 2)
- {
- signal->theData[0] = NDB_LE_MissedHeartbeat;
- signal->theData[1] = nodeId;
- signal->theData[2] = getNodeInfo(TnodePtr.i).m_heartbeat_cnt - 1;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
- }
-
- if (getNodeInfo(TnodePtr.i).m_heartbeat_cnt > 4)
- {
- jam();
- /*------------------------------------------------------------------*/
- /* THE API NODE HAS NOT SENT ANY HEARTBEAT FOR THREE SECONDS.
- * WE WILL DISCONNECT FROM IT NOW.
- *------------------------------------------------------------------*/
- /*------------------------------------------------------------------*/
- /* We call node_failed to release all connections for this api node */
- /*------------------------------------------------------------------*/
- signal->theData[0] = NDB_LE_DeadDueToHeartbeat;
- signal->theData[1] = nodeId;
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
-
- api_failed(signal, nodeId);
- }//if
- }//if
- }//for
- return;
-}//Qmgr::apiHbHandlingLab()
-
-void Qmgr::checkStartInterface(Signal* signal)
-{
- NodeRecPtr nodePtr;
- /*------------------------------------------------------------------------*/
- // This method is called once per second. After a disconnect we wait at
- // least three seconds before allowing new connects. We will also ensure
- // that handling of the failure is completed before we allow new connections.
- /*------------------------------------------------------------------------*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++) {
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZFAIL_CLOSING) {
- jam();
- 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.
- /*-------------------------------------------------------------------*/
- setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
- }//if
- 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.
- * WE WILL NOT ALLOW CONNECTIONS OF API NODES UNTIL API FAIL HANDLING
- * IS COMPLETE.
- *-------------------------------------------------------------------*/
- nodePtr.p->failState = NORMAL;
- if (getNodeInfo(nodePtr.i).m_type != NodeInfo::DB){
- jam();
- nodePtr.p->phase = ZAPI_INACTIVE;
- } else {
- jam();
- nodePtr.p->phase = ZINIT;
- }//if
-
- 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(((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,
- (getNodeInfo(nodePtr.i).m_heartbeat_cnt + 1)/60,
- nodePtr.p->failState);
- warningEvent(buf);
- }
- }
- }//if
- }//for
- return;
-}//Qmgr::checkStartInterface()
-
-/**-------------------------------------------------------------------------
- * This method is called when a DISCONNECT_REP signal arrived which means that
- * the API node is gone and we want to release resources in TC/DICT blocks.
- *---------------------------------------------------------------------------*/
-void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo)
-{
- NodeRecPtr failedNodePtr;
-
- jamEntry();
- failedNodePtr.i = failedNodeNo;
- signal->theData[0] = failedNodePtr.i;
- signal->theData[1] = QMGR_REF;
-
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
-
- ndbrequire(failedNodePtr.p->failState == NORMAL);
-
- failedNodePtr.p->failState = WAITING_FOR_FAILCONF1;
- NodeReceiverGroup rg(QMGR, c_clusterNodes);
- sendSignal(rg, GSN_API_FAILREQ, signal, 2, JBA);
- 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);
-}//Qmgr::sendApiFailReq()
-
-void Qmgr::execAPI_FAILREQ(Signal* signal)
-{
- jamEntry();
- NodeRecPtr failedNodePtr;
- failedNodePtr.i = signal->theData[0];
- // signal->theData[1] == QMGR_REF
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
-
- ndbrequire(getNodeInfo(failedNodePtr.i).getType() != NodeInfo::DB);
-
- api_failed(signal, signal->theData[0]);
-}
-
-void Qmgr::execAPI_FAILCONF(Signal* signal)
-{
- NodeRecPtr failedNodePtr;
-
- jamEntry();
- failedNodePtr.i = signal->theData[0];
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
-
- if (failedNodePtr.p->failState == WAITING_FOR_FAILCONF1){
- jam();
-
- failedNodePtr.p->rcv[0] = signal->theData[1];
- failedNodePtr.p->failState = WAITING_FOR_FAILCONF2;
-
- } else if (failedNodePtr.p->failState == WAITING_FOR_FAILCONF2) {
- failedNodePtr.p->rcv[1] = signal->theData[1];
- failedNodePtr.p->failState = NORMAL;
-
- if (failedNodePtr.p->rcv[0] == failedNodePtr.p->rcv[1]) {
- jam();
- systemErrorLab(signal, __LINE__);
- } else {
- jam();
- failedNodePtr.p->rcv[0] = 0;
- failedNodePtr.p->rcv[1] = 0;
- }//if
- } else {
- jam();
-#ifdef VM_TRACE
- ndbout << "failedNodePtr.p->failState = "
- << (Uint32)(failedNodePtr.p->failState) << endl;
-#endif
- systemErrorLab(signal, __LINE__);
- }//if
- return;
-}//Qmgr::execAPI_FAILCONF()
-
-void Qmgr::execNDB_FAILCONF(Signal* signal)
-{
- NodeRecPtr failedNodePtr;
- NodeRecPtr nodePtr;
-
- jamEntry();
- failedNodePtr.i = signal->theData[0];
-
- if (ERROR_INSERTED(930))
- {
- CLEAR_ERROR_INSERT_VALUE;
- infoEvent("Discarding NDB_FAILCONF for %u", failedNodePtr.i);
- return;
- }
-
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
- if (failedNodePtr.p->failState == WAITING_FOR_NDB_FAILCONF){
- failedNodePtr.p->failState = NORMAL;
- } else {
- jam();
-
- char buf[100];
- BaseString::snprintf(buf, 100,
- "Received NDB_FAILCONF for node %u with state: %d %d",
- failedNodePtr.i,
- failedNodePtr.p->phase,
- failedNodePtr.p->failState);
- progError(__LINE__, 0, buf);
- systemErrorLab(signal, __LINE__);
- }//if
- if (cpresident == getOwnNodeId()) {
- jam();
- /**
- * Prepare a NFCompleteRep and send to all connected API's
- * They can then abort all transaction waiting for response from
- * the failed node
- */
- NFCompleteRep * const nfComp = (NFCompleteRep *)&signal->theData[0];
- nfComp->blockNo = QMGR_REF;
- nfComp->nodeId = getOwnNodeId();
- nfComp->failedNodeId = failedNodePtr.i;
-
- for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZAPI_ACTIVE){
- jam();
- sendSignal(nodePtr.p->blockRef, GSN_NF_COMPLETEREP, signal,
- NFCompleteRep::SignalLength, JBA);
- }//if
- }//for
- }
- return;
-}//Qmgr::execNDB_FAILCONF()
-
-/*******************************/
-/* 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);
- }
-
- if (getNodeInfo(nodeId).getType() != NodeInfo::DB)
- {
- jam();
- api_failed(signal, nodeId);
- return;
- }
-
- 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:
- {
- BaseString::snprintf(buf, 100, "Node %u disconnected", nodeId);
- progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
- ndbrequire(false);
- }
- }
- node_failed(signal, nodeId);
-}//DISCONNECT_REP
-
-void Qmgr::node_failed(Signal* signal, Uint16 aFailedNode)
-{
- NodeRecPtr failedNodePtr;
- /**------------------------------------------------------------------------
- * A COMMUNICATION LINK HAS BEEN DISCONNECTED. WE MUST TAKE SOME ACTION
- * DUE TO THIS.
- *-----------------------------------------------------------------------*/
- failedNodePtr.i = aFailedNode;
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
-
- ndbrequire(getNodeInfo(failedNodePtr.i).getType() == NodeInfo::DB);
-
- /**---------------------------------------------------------------------
- * THE OTHER NODE IS AN NDB NODE, WE HANDLE IT AS IF A HEARTBEAT
- * FAILURE WAS DISCOVERED.
- *---------------------------------------------------------------------*/
- switch(failedNodePtr.p->phase){
- case ZRUNNING:
- jam();
- failReportLab(signal, aFailedNode, FailRep::ZLINK_FAILURE);
- return;
- case ZFAIL_CLOSING:
- jam();
- return;
- case ZSTARTING:
- c_start.reset();
- // Fall-through
- default:
- jam();
- /*---------------------------------------------------------------------*/
- // The other node is still not in the cluster but disconnected.
- // We must restart communication in three seconds.
- /*---------------------------------------------------------------------*/
- failedNodePtr.p->failState = NORMAL;
- failedNodePtr.p->phase = ZFAIL_CLOSING;
- setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
-
- CloseComReqConf * const closeCom =
- (CloseComReqConf *)&signal->theData[0];
-
- closeCom->xxxBlockRef = reference();
- closeCom->failNo = 0;
- closeCom->noOfNodes = 1;
- NodeBitmask::clear(closeCom->theNodes);
- NodeBitmask::set(closeCom->theNodes, failedNodePtr.i);
- sendSignal(CMVMI_REF, GSN_CLOSE_COMREQ, signal,
- CloseComReqConf::SignalLength, JBA);
- }//if
- return;
-}
-
-void
-Qmgr::api_failed(Signal* signal, Uint32 nodeId)
-{
- NodeRecPtr failedNodePtr;
- /**------------------------------------------------------------------------
- * A COMMUNICATION LINK HAS BEEN DISCONNECTED. WE MUST TAKE SOME ACTION
- * DUE TO THIS.
- *-----------------------------------------------------------------------*/
- failedNodePtr.i = nodeId;
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
-
- if (failedNodePtr.p->phase == ZFAIL_CLOSING)
- {
- /**
- * Failure handling already in progress
- */
- jam();
- return;
- }
-
- if (failedNodePtr.p->phase == ZAPI_ACTIVE)
- {
- jam();
- sendApiFailReq(signal, nodeId);
- arbitRec.code = ArbitCode::ApiFail;
- handleArbitApiFail(signal, nodeId);
- }
- else
- {
- /**
- * Always inform SUMA
- */
- jam();
- signal->theData[0] = nodeId;
- signal->theData[1] = QMGR_REF;
- sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBA);
- failedNodePtr.p->failState = NORMAL;
- }
-
- failedNodePtr.p->phase = ZFAIL_CLOSING;
- setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
- setNodeInfo(failedNodePtr.i).m_version = 0;
- recompute_version_info(getNodeInfo(failedNodePtr.i).m_type);
-
- CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
- closeCom->xxxBlockRef = reference();
- closeCom->failNo = 0;
- closeCom->noOfNodes = 1;
- NodeBitmask::clear(closeCom->theNodes);
- NodeBitmask::set(closeCom->theNodes, failedNodePtr.i);
- sendSignal(CMVMI_REF, GSN_CLOSE_COMREQ, signal,
- CloseComReqConf::SignalLength, JBA);
-
- if (getNodeInfo(failedNodePtr.i).getType() == NodeInfo::MGM)
- {
- /**
- * Allow MGM do reconnect "directly"
- */
- jam();
- setNodeInfo(failedNodePtr.i).m_heartbeat_cnt = 3;
- }
-}
-
-/**--------------------------------------------------------------------------
- * AN API NODE IS REGISTERING. IF FOR THE FIRST TIME WE WILL ENABLE
- * COMMUNICATION WITH ALL NDB BLOCKS.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* API_REGREQ */
-/*******************************/
-void Qmgr::execAPI_REGREQ(Signal* signal)
-{
- jamEntry();
-
- ApiRegReq* req = (ApiRegReq*)signal->getDataPtr();
- const Uint32 version = req->version;
- const BlockReference ref = req->ref;
-
- NodeRecPtr apiNodePtr;
- apiNodePtr.i = refToNode(ref);
- ptrCheckGuard(apiNodePtr, MAX_NODES, nodeRec);
-
-#if 0
- ndbout_c("Qmgr::execAPI_REGREQ: Recd API_REGREQ (NodeId=%d)", apiNodePtr.i);
-#endif
-
- bool compatability_check;
- NodeInfo::NodeType type= getNodeInfo(apiNodePtr.i).getType();
- switch(type){
- case NodeInfo::API:
- compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
- break;
- case NodeInfo::MGM:
- compatability_check = ndbCompatible_ndb_mgmt(NDB_VERSION, version);
- break;
- case NodeInfo::DB:
- case NodeInfo::INVALID:
- default:
- sendApiRegRef(signal, ref, ApiRegRef::WrongType);
- infoEvent("Invalid connection attempt with type %d", type);
- return;
- }
-
- if (!compatability_check) {
- jam();
- char buf[NDB_VERSION_STRING_BUF_SZ];
- infoEvent("Connection attempt from %s id=%d with %s "
- "incompatible with %s",
- type == NodeInfo::API ? "api or mysqld" : "management server",
- apiNodePtr.i,
- ndbGetVersionString(version,"",buf,sizeof(buf)),
- NDB_VERSION_STRING);
- apiNodePtr.p->phase = ZAPI_INACTIVE;
- sendApiRegRef(signal, ref, ApiRegRef::UnsupportedVersion);
- return;
- }
-
- setNodeInfo(apiNodePtr.i).m_version = version;
- setNodeInfo(apiNodePtr.i).m_heartbeat_cnt= 0;
-
- ApiRegConf * const apiRegConf = (ApiRegConf *)&signal->theData[0];
- apiRegConf->qmgrRef = reference();
- apiRegConf->apiHeartbeatFrequency = (chbApiDelay / 10);
- apiRegConf->version = NDB_VERSION;
- NodeState state= apiRegConf->nodeState = getNodeState();
- {
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- Uint32 dynamicId = nodePtr.p->ndynamicId;
-
- if(apiRegConf->nodeState.masterNodeId != getOwnNodeId()){
- jam();
- apiRegConf->nodeState.dynamicId = dynamicId;
- } else {
- apiRegConf->nodeState.dynamicId = -dynamicId;
- }
- }
- NodeVersionInfo info = getNodeVersionInfo();
- apiRegConf->minDbVersion = info.m_type[NodeInfo::DB].m_min_version;
- apiRegConf->nodeState.m_connected_nodes.assign(c_connectedNodes);
- sendSignal(ref, GSN_API_REGCONF, signal, ApiRegConf::SignalLength, JBB);
-
- if (apiNodePtr.p->phase == ZAPI_INACTIVE &&
- (state.startLevel == NodeState::SL_STARTED ||
- state.getSingleUserMode() ||
- (state.startLevel == NodeState::SL_STARTING &&
- state.starting.startPhase >= 100)))
- {
- jam();
- /**----------------------------------------------------------------------
- * THE API NODE IS REGISTERING. WE WILL ACCEPT IT BY CHANGING STATE AND
- * SENDING A CONFIRM.
- *----------------------------------------------------------------------*/
- apiNodePtr.p->phase = ZAPI_ACTIVE;
- apiNodePtr.p->blockRef = ref;
- signal->theData[0] = apiNodePtr.i;
- sendSignal(CMVMI_REF, GSN_ENABLE_COMORD, signal, 1, JBA);
-
- recompute_version_info(type, version);
-
- signal->theData[0] = apiNodePtr.i;
- signal->theData[1] = version;
- NodeReceiverGroup rg(QMGR, c_clusterNodes);
- rg.m_nodes.clear(getOwnNodeId());
- sendVersionedDb(rg, GSN_NODE_VERSION_REP, signal, 2, JBB,
- NDBD_NODE_VERSION_REP);
-
- signal->theData[0] = apiNodePtr.i;
- EXECUTE_DIRECT(NDBCNTR, GSN_API_START_REP, signal, 1);
- }
- return;
-}//Qmgr::execAPI_REGREQ()
-
-void
-Qmgr::sendVersionedDb(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Uint32 minversion)
-{
- jam();
- NodeVersionInfo info = getNodeVersionInfo();
- if (info.m_type[NodeInfo::DB].m_min_version >= minversion)
- {
- jam();
- sendSignal(rg, gsn, signal, length, jbuf);
- }
- else
- {
- jam();
- Uint32 i = 0, cnt = 0;
- while((i = rg.m_nodes.find(i + 1)) != NodeBitmask::NotFound)
- {
- jam();
- if (getNodeInfo(i).m_version >= minversion)
- {
- jam();
- cnt++;
- sendSignal(numberToRef(rg.m_block, i), gsn, signal, length, jbuf);
- }
- }
- ndbassert((cnt == 0 && rg.m_nodes.count() == 0) ||
- (cnt < rg.m_nodes.count()));
- }
-}
-
-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;
-
- sendSignal(senderRef,
- GSN_API_VERSION_CONF,
- signal,
- ApiVersionConf::SignalLength, JBB);
-}
-
-void
-Qmgr::execNODE_VERSION_REP(Signal* signal)
-{
- jamEntry();
- Uint32 nodeId = signal->theData[0];
- Uint32 version = signal->theData[1];
-
- if (nodeId < MAX_NODES)
- {
- jam();
- Uint32 type = getNodeInfo(nodeId).m_type;
- setNodeInfo(nodeId).m_version = version;
- recompute_version_info(type, version);
- }
-}
-
-void
-Qmgr::recompute_version_info(Uint32 type, Uint32 version)
-{
- NodeVersionInfo& info = setNodeVersionInfo();
- switch(type){
- case NodeInfo::DB:
- case NodeInfo::API:
- case NodeInfo::MGM:
- break;
- default:
- return;
- }
-
- if (info.m_type[type].m_min_version == 0 ||
- version < info.m_type[type].m_min_version)
- info.m_type[type].m_min_version = version;
- if (version > info.m_type[type].m_max_version)
- info.m_type[type].m_max_version = version;
-}
-
-void
-Qmgr::recompute_version_info(Uint32 type)
-{
- switch(type){
- case NodeInfo::DB:
- case NodeInfo::API:
- case NodeInfo::MGM:
- break;
- default:
- return;
- }
-
- Uint32 min = ~0, max = 0;
- Uint32 cnt = type == NodeInfo::DB ? MAX_NDB_NODES : MAX_NODES;
- for (Uint32 i = 1; i<cnt; i++)
- {
- if (getNodeInfo(i).m_type == type)
- {
- Uint32 version = getNodeInfo(i).m_version;
-
- if (version)
- {
- if (version < min)
- min = version;
- if (version > max)
- max = version;
- }
- }
- }
-
- NodeVersionInfo& info = setNodeVersionInfo();
- info.m_type[type].m_min_version = min == ~(Uint32)0 ? 0 : min;
- info.m_type[type].m_max_version = max;
-}
-
-#if 0
-bool
-Qmgr::checkAPIVersion(NodeId nodeId,
- Uint32 apiVersion, Uint32 ownVersion) const {
- bool ret=true;
- /**
- * First implementation...
- */
- if ((getMajor(apiVersion) < getMajor(ownVersion) ||
- getMinor(apiVersion) < getMinor(ownVersion)) &&
- apiVersion >= API_UPGRADE_VERSION) {
- jam();
- if ( getNodeInfo(nodeId).getType() != NodeInfo::MGM ) {
- jam();
- ret = false;
- } else {
- jam();
- /* we have a software upgrade situation, mgmtsrvr should be
- * the highest, let him decide what to do
- */
- ;
- }
- }
- return ret;
-}
-#endif
-
-void
-Qmgr::sendApiRegRef(Signal* signal, Uint32 Tref, ApiRegRef::ErrorCode err){
- ApiRegRef* ref = (ApiRegRef*)signal->getDataPtrSend();
- ref->ref = reference();
- ref->version = NDB_VERSION;
- ref->errorCode = err;
- sendSignal(Tref, GSN_API_REGREF, signal, ApiRegRef::SignalLength, JBB);
-}
-
-/**--------------------------------------------------------------------------
- * A NODE HAS BEEN DECLARED AS DOWN. WE WILL CLOSE THE COMMUNICATION TO THIS
- * NODE IF NOT ALREADY DONE. IF WE ARE PRESIDENT OR BECOMES PRESIDENT BECAUSE
- * OF A FAILED PRESIDENT THEN WE WILL TAKE FURTHER ACTION.
- *---------------------------------------------------------------------------*/
-void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
- FailRep::FailCause aFailCause)
-{
- NodeRecPtr nodePtr;
- NodeRecPtr failedNodePtr;
- NodeRecPtr myNodePtr;
- UintR TnoFailedNodes;
-
- failedNodePtr.i = aFailedNode;
- ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
- FailRep* rep = (FailRep*)signal->getDataPtr();
-
- if (check_multi_node_shutdown(signal))
- {
- jam();
- return;
- }
-
- if (failedNodePtr.i == getOwnNodeId()) {
- jam();
-
- Uint32 code = NDBD_EXIT_NODE_DECLARED_DEAD;
- const char * msg = 0;
- char extra[100];
- switch(aFailCause){
- case FailRep::ZOWN_FAILURE:
- msg = "Own failure";
- break;
- case FailRep::ZOTHER_NODE_WHEN_WE_START:
- case FailRep::ZOTHERNODE_FAILED_DURING_START:
- msg = "Other node died during start";
- break;
- case FailRep::ZIN_PREP_FAIL_REQ:
- msg = "Prep fail";
- break;
- case FailRep::ZSTART_IN_REGREQ:
- msg = "Start timeout";
- break;
- case FailRep::ZHEARTBEAT_FAILURE:
- msg = "Hearbeat failure";
- break;
- case FailRep::ZLINK_FAILURE:
- msg = "Connection failure";
- break;
- case FailRep::ZPARTITIONED_CLUSTER:
- {
- code = NDBD_EXIT_PARTITIONED_SHUTDOWN;
- char buf1[100], buf2[100];
- c_clusterNodes.getText(buf1);
- if (signal->getLength()== FailRep::SignalLength + FailRep::ExtraLength &&
- signal->header.theVerId_signalNumber == GSN_FAIL_REP)
- {
- jam();
- NdbNodeBitmask part;
- part.assign(NdbNodeBitmask::Size, rep->partition);
- part.getText(buf2);
- BaseString::snprintf(extra, sizeof(extra),
- "Our cluster: %s other cluster: %s",
- buf1, buf2);
- }
- else
- {
- jam();
- BaseString::snprintf(extra, sizeof(extra),
- "Our cluster: %s", buf1);
- }
- msg = extra;
- break;
- }
- case FailRep::ZMULTI_NODE_SHUTDOWN:
- msg = "Multi node shutdown";
- break;
- default:
- msg = "<UNKNOWN>";
- }
-
- CRASH_INSERTION(932);
-
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf),
- "We(%u) have been declared dead by %u reason: %s(%u)",
- getOwnNodeId(),
- refToNode(signal->getSendersBlockRef()),
- msg ? msg : "<Unknown>",
- aFailCause);
-
- progError(__LINE__, code, buf);
- return;
- }//if
-
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
- if (myNodePtr.p->phase != ZRUNNING) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
-
- if (getNodeState().startLevel < NodeState::SL_STARTED)
- {
- jam();
- CRASH_INSERTION(932);
- char buf[100];
- BaseString::snprintf(buf, 100, "Node failure during restart");
- progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
- ndbrequire(false);
- }
-
- TnoFailedNodes = cnoFailedNodes;
- failReport(signal, failedNodePtr.i, (UintR)ZTRUE, aFailCause);
- if (cpresident == getOwnNodeId()) {
- jam();
- if (ctoStatus == Q_NOT_ACTIVE) {
- jam();
- /**--------------------------------------------------------------------
- * AS PRESIDENT WE ARE REQUIRED TO START THE EXCLUSION PROCESS SUCH THAT
- * THE APPLICATION SEE NODE FAILURES IN A CONSISTENT ORDER.
- * IF WE HAVE BECOME PRESIDENT NOW (CTO_STATUS = ACTIVE) THEN WE HAVE
- * TO COMPLETE THE PREVIOUS COMMIT FAILED NODE PROCESS BEFORE STARTING
- * A NEW.
- * CTO_STATUS = ACTIVE CAN ALSO MEAN THAT WE ARE PRESIDENT AND ARE
- * CURRENTLY COMMITTING A SET OF NODE CRASHES. IN THIS CASE IT IS NOT
- * ALLOWED TO START PREPARING NEW NODE CRASHES.
- *---------------------------------------------------------------------*/
- if (TnoFailedNodes != cnoFailedNodes) {
- jam();
- cfailureNr = cfailureNr + 1;
- for (nodePtr.i = 1;
- nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- sendPrepFailReq(signal, nodePtr.i);
- }//if
- }//for
- }//if
- }//if
- }//if
- return;
-}//Qmgr::failReportLab()
-
-/**-------------------------------------------------------------------------
- * WE HAVE RECEIVED A PREPARE TO EXCLUDE A NUMBER OF NODES FROM THE CLUSTER.
- * WE WILL FIRST CHECK THAT WE HAVE NOT ANY MORE NODES THAT
- * WE ALSO HAVE EXCLUDED
- *--------------------------------------------------------------------------*/
-/*******************************/
-/* PREP_FAILREQ */
-/*******************************/
-void Qmgr::execPREP_FAILREQ(Signal* signal)
-{
- NodeRecPtr myNodePtr;
- jamEntry();
-
- if (check_multi_node_shutdown(signal))
- {
- jam();
- return;
- }
-
- PrepFailReqRef * const prepFail = (PrepFailReqRef *)&signal->theData[0];
-
- BlockReference Tblockref = prepFail->xxxBlockRef;
- Uint16 TfailureNr = prepFail->failNo;
- cnoPrepFailedNodes = prepFail->noOfNodes;
- UintR arrayIndex = 0;
- Uint32 Tindex;
- for (Tindex = 0; Tindex < MAX_NDB_NODES; Tindex++) {
- if (NodeBitmask::get(prepFail->theNodes, Tindex)){
- cprepFailedNodes[arrayIndex] = Tindex;
- arrayIndex++;
- }//if
- }//for
- UintR guard0;
-
- /**
- * Block commit until node failures has stabilized
- *
- * @See RT352
- */
- BlockCommitOrd* const block = (BlockCommitOrd *)&signal->theData[0];
- block->failNo = TfailureNr;
- EXECUTE_DIRECT(DBDIH, GSN_BLOCK_COMMIT_ORD, signal,
- BlockCommitOrd::SignalLength);
-
- myNodePtr.i = getOwnNodeId();
- ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
- if (myNodePtr.p->phase != ZRUNNING) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
-
- if (getNodeState().startLevel < NodeState::SL_STARTED)
- {
- jam();
- CRASH_INSERTION(932);
- char buf[100];
- BaseString::snprintf(buf, 100, "Node failure during restart");
- progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
- ndbrequire(false);
- }
-
- guard0 = cnoPrepFailedNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Tindex = 0; Tindex <= guard0; Tindex++) {
- jam();
- failReport(signal,
- cprepFailedNodes[Tindex],
- (UintR)ZFALSE,
- FailRep::ZIN_PREP_FAIL_REQ);
- }//for
- sendCloseComReq(signal, Tblockref, TfailureNr);
- cnoCommitFailedNodes = 0;
- cprepareFailureNr = TfailureNr;
- return;
-}//Qmgr::execPREP_FAILREQ()
-
-/**---------------------------------------------------------------------------
- * THE CRASHED NODES HAS BEEN EXCLUDED FROM COMMUNICATION.
- * WE WILL CHECK WHETHER ANY MORE NODES HAVE FAILED DURING THE PREPARE PROCESS.
- * IF SO WE WILL REFUSE THE PREPARE PHASE AND EXPECT A NEW PREPARE MESSAGE
- * WITH ALL FAILED NODES INCLUDED.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* CLOSE_COMCONF */
-/*******************************/
-void Qmgr::execCLOSE_COMCONF(Signal* signal)
-{
- jamEntry();
-
- CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
-
- BlockReference Tblockref = closeCom->xxxBlockRef;
- Uint16 TfailureNr = closeCom->failNo;
-
- cnoPrepFailedNodes = closeCom->noOfNodes;
- UintR arrayIndex = 0;
- UintR Tindex = 0;
- for(Tindex = 0; Tindex < MAX_NDB_NODES; Tindex++){
- if(NodeBitmask::get(closeCom->theNodes, Tindex)){
- cprepFailedNodes[arrayIndex] = Tindex;
- arrayIndex++;
- }
- }
- UintR tprepFailConf;
- UintR Tindex2;
- UintR guard0;
- UintR guard1;
- UintR Tfound;
- Uint16 TfailedNodeNo;
-
- tprepFailConf = ZTRUE;
- if (cnoFailedNodes > 0) {
- jam();
- guard0 = cnoFailedNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Tindex = 0; Tindex <= guard0; Tindex++) {
- jam();
- TfailedNodeNo = cfailedNodes[Tindex];
- Tfound = ZFALSE;
- guard1 = cnoPrepFailedNodes - 1;
- arrGuard(guard1, MAX_NDB_NODES);
- for (Tindex2 = 0; Tindex2 <= guard1; Tindex2++) {
- jam();
- if (TfailedNodeNo == cprepFailedNodes[Tindex2]) {
- jam();
- Tfound = ZTRUE;
- }//if
- }//for
- if (Tfound == ZFALSE) {
- jam();
- tprepFailConf = ZFALSE;
- arrGuard(cnoPrepFailedNodes, MAX_NDB_NODES);
- cprepFailedNodes[cnoPrepFailedNodes] = TfailedNodeNo;
- cnoPrepFailedNodes = cnoPrepFailedNodes + 1;
- }//if
- }//for
- }//if
- if (tprepFailConf == ZFALSE) {
- jam();
- for (Tindex = 1; Tindex < MAX_NDB_NODES; Tindex++) {
- cfailedNodes[Tindex] = cprepFailedNodes[Tindex];
- }//for
- cnoFailedNodes = cnoPrepFailedNodes;
- sendPrepFailReqRef(signal,
- Tblockref,
- GSN_PREP_FAILREF,
- reference(),
- cfailureNr,
- cnoPrepFailedNodes,
- cprepFailedNodes);
- } else {
- jam();
- cnoCommitFailedNodes = cnoPrepFailedNodes;
- guard0 = cnoPrepFailedNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Tindex = 0; Tindex <= guard0; Tindex++) {
- jam();
- arrGuard(Tindex, MAX_NDB_NODES);
- ccommitFailedNodes[Tindex] = cprepFailedNodes[Tindex];
- }//for
- signal->theData[0] = getOwnNodeId();
- signal->theData[1] = TfailureNr;
- sendSignal(Tblockref, GSN_PREP_FAILCONF, signal, 2, JBA);
- }//if
- return;
-}//Qmgr::execCLOSE_COMCONF()
-
-/*---------------------------------------------------------------------------*/
-/* WE HAVE RECEIVED A CONFIRM OF THAT THIS NODE HAVE PREPARED THE FAILURE. */
-/*---------------------------------------------------------------------------*/
-/*******************************/
-/* PREP_FAILCONF */
-/*******************************/
-void Qmgr::execPREP_FAILCONF(Signal* signal)
-{
- NodeRecPtr nodePtr;
- NodeRecPtr replyNodePtr;
- jamEntry();
- replyNodePtr.i = signal->theData[0];
- Uint16 TfailureNr = signal->theData[1];
- if (TfailureNr != cfailureNr) {
- jam();
- /**----------------------------------------------------------------------
- * WE HAVE ALREADY STARTING A NEW ATTEMPT TO EXCLUDE A NUMBER OF NODES.
- * IGNORE
- *----------------------------------------------------------------------*/
- return;
- }//if
- ptrCheckGuard(replyNodePtr, MAX_NDB_NODES, nodeRec);
- replyNodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- if (nodePtr.p->sendPrepFailReqStatus == Q_ACTIVE) {
- jam();
- return;
- }//if
- }//if
- }//for
- /**
- * Check node count and groups and invoke arbitrator if necessary.
- * Continues via sendCommitFailReq() if successful.
- */
- arbitRec.failureNr = cfailureNr;
- const NodeState & s = getNodeState();
- if(s.startLevel == NodeState::SL_STOPPING_3 && s.stopping.systemShutdown){
- jam();
- /**
- * We're performing a system shutdown,
- * don't let artibtrator shut us down
- */
- return;
- }
- handleArbitCheck(signal);
- return;
-}//Qmgr::execPREP_FAILCONF()
-
-void
-Qmgr::sendCommitFailReq(Signal* signal)
-{
- NodeRecPtr nodePtr;
- jam();
- if (arbitRec.failureNr != cfailureNr) {
- jam();
- /**----------------------------------------------------------------------
- * WE HAVE ALREADY STARTING A NEW ATTEMPT TO EXCLUDE A NUMBER OF NODES.
- * IGNORE
- *----------------------------------------------------------------------*/
- return;
- }//if
- /**-----------------------------------------------------------------------
- * WE HAVE SUCCESSFULLY PREPARED A SET OF NODE FAILURES. WE WILL NOW COMMIT
- * THESE NODE FAILURES.
- *-------------------------------------------------------------------------*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
-
-#ifdef ERROR_INSERT
- if (ERROR_INSERTED(935) && nodePtr.i == c_error_insert_extra)
- {
- ndbout_c("skipping node %d", c_error_insert_extra);
- CLEAR_ERROR_INSERT_VALUE;
- signal->theData[0] = 9999;
- sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
- continue;
- }
-#endif
-
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- nodePtr.p->sendCommitFailReqStatus = Q_ACTIVE;
- signal->theData[0] = cpdistref;
- signal->theData[1] = cfailureNr;
- sendSignal(nodePtr.p->blockRef, GSN_COMMIT_FAILREQ, signal, 2, JBA);
- }//if
- }//for
- ctoStatus = Q_ACTIVE;
- cnoFailedNodes = 0;
- return;
-}//sendCommitFailReq()
-
-/*---------------------------------------------------------------------------*/
-/* SOME NODE HAVE DISCOVERED A NODE FAILURE THAT WE HAVE NOT YET DISCOVERED. */
-/* WE WILL START ANOTHER ROUND OF PREPARING A SET OF NODE FAILURES. */
-/*---------------------------------------------------------------------------*/
-/*******************************/
-/* PREP_FAILREF */
-/*******************************/
-void Qmgr::execPREP_FAILREF(Signal* signal)
-{
- NodeRecPtr nodePtr;
- jamEntry();
-
- PrepFailReqRef * const prepFail = (PrepFailReqRef *)&signal->theData[0];
-
- Uint16 TfailureNr = prepFail->failNo;
- cnoPrepFailedNodes = prepFail->noOfNodes;
-
- UintR arrayIndex = 0;
- UintR Tindex = 0;
- for(Tindex = 0; Tindex < MAX_NDB_NODES; Tindex++) {
- jam();
- if(NodeBitmask::get(prepFail->theNodes, Tindex)){
- jam();
- cprepFailedNodes[arrayIndex] = Tindex;
- arrayIndex++;
- }//if
- }//for
- if (TfailureNr != cfailureNr) {
- jam();
- /**---------------------------------------------------------------------
- * WE HAVE ALREADY STARTING A NEW ATTEMPT TO EXCLUDE A NUMBER OF NODES.
- * IGNORE
- *----------------------------------------------------------------------*/
- return;
- }//if
- UintR guard0;
- UintR Ti;
-
- cnoFailedNodes = cnoPrepFailedNodes;
- guard0 = cnoPrepFailedNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- for (Ti = 0; Ti <= guard0; Ti++) {
- jam();
- cfailedNodes[Ti] = cprepFailedNodes[Ti];
- }//for
- cfailureNr = cfailureNr + 1;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- sendPrepFailReq(signal, nodePtr.i);
- }//if
- }//for
- return;
-}//Qmgr::execPREP_FAILREF()
-
-static
-Uint32
-clear_nodes(Uint32 dstcnt, Uint16 dst[], Uint32 srccnt, const Uint16 src[])
-{
- if (srccnt == 0)
- return dstcnt;
-
- Uint32 pos = 0;
- for (Uint32 i = 0; i<dstcnt; i++)
- {
- Uint32 node = dst[i];
- for (Uint32 j = 0; j<srccnt; j++)
- {
- if (node == dst[j])
- {
- node = RNIL;
- break;
- }
- }
- if (node != RNIL)
- {
- dst[pos++] = node;
- }
- }
- return pos;
-}
-
-/*---------------------------------------------------------------------------*/
-/* THE PRESIDENT IS NOW COMMITTING THE PREVIOUSLY PREPARED NODE FAILURE. */
-/*---------------------------------------------------------------------------*/
-/***********************/
-/* COMMIT_FAILREQ */
-/***********************/
-void Qmgr::execCOMMIT_FAILREQ(Signal* signal)
-{
- NodeRecPtr nodePtr;
- jamEntry();
- BlockReference Tblockref = signal->theData[0];
- UintR TfailureNr = signal->theData[1];
- if (Tblockref != cpdistref) {
- jam();
- return;
- }//if
- UintR guard0;
- UintR Tj;
-
- /**
- * Block commit until node failures has stabilized
- *
- * @See RT352
- */
- UnblockCommitOrd* const unblock = (UnblockCommitOrd *)&signal->theData[0];
- unblock->failNo = TfailureNr;
- EXECUTE_DIRECT(DBDIH, GSN_UNBLOCK_COMMIT_ORD, signal,
- UnblockCommitOrd::SignalLength);
-
- if ((ccommitFailureNr != TfailureNr) &&
- (cnoCommitFailedNodes > 0)) {
- jam();
- /**-----------------------------------------------------------------------
- * WE ONLY DO THIS PART OF THE COMMIT HANDLING THE FIRST TIME WE HEAR THIS
- * SIGNAL. WE CAN HEAR IT SEVERAL TIMES IF THE PRESIDENTS KEEP FAILING.
- *-----------------------------------------------------------------------*/
- ccommitFailureNr = TfailureNr;
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
-
- nodeFail->failNo = ccommitFailureNr;
- nodeFail->noOfNodes = cnoCommitFailedNodes;
- nodeFail->masterNodeId = cpresident;
- NodeBitmask::clear(nodeFail->theNodes);
- for(unsigned i = 0; i < cnoCommitFailedNodes; i++) {
- jam();
- NodeBitmask::set(nodeFail->theNodes, ccommitFailedNodes[i]);
- }//if
- sendSignal(NDBCNTR_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
- guard0 = cnoCommitFailedNodes - 1;
- arrGuard(guard0, MAX_NDB_NODES);
- /**--------------------------------------------------------------------
- * WE MUST PREPARE TO ACCEPT THE CRASHED NODE INTO THE CLUSTER AGAIN BY
- * SETTING UP CONNECTIONS AGAIN AFTER THREE SECONDS OF DELAY.
- *--------------------------------------------------------------------*/
- for (Tj = 0; Tj <= guard0; Tj++) {
- jam();
- nodePtr.i = ccommitFailedNodes[Tj];
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- nodePtr.p->phase = ZFAIL_CLOSING;
- nodePtr.p->failState = WAITING_FOR_NDB_FAILCONF;
- setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
- setNodeInfo(nodePtr.i).m_version = 0;
- c_clusterNodes.clear(nodePtr.i);
- }//for
- recompute_version_info(NodeInfo::DB);
- /*----------------------------------------------------------------------*/
- /* WE INFORM THE API'S WE HAVE CONNECTED ABOUT THE FAILED NODES. */
- /*----------------------------------------------------------------------*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZAPI_ACTIVE) {
- jam();
-
- NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
-
- nodeFail->failNo = ccommitFailureNr;
- nodeFail->noOfNodes = cnoCommitFailedNodes;
- NodeBitmask::clear(nodeFail->theNodes);
- for(unsigned i = 0; i < cnoCommitFailedNodes; i++) {
- jam();
- NodeBitmask::set(nodeFail->theNodes, ccommitFailedNodes[i]);
- }//for
- sendSignal(nodePtr.p->blockRef, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
- }//if
- }//for
-
- /**
- * Remove committed nodes from failed/prepared
- */
- cnoFailedNodes = clear_nodes(cnoFailedNodes,
- cfailedNodes,
- cnoCommitFailedNodes,
- ccommitFailedNodes);
- cnoPrepFailedNodes = clear_nodes(cnoPrepFailedNodes,
- cprepFailedNodes,
- cnoCommitFailedNodes,
- ccommitFailedNodes);
- cnoCommitFailedNodes = 0;
- }//if
- /**-----------------------------------------------------------------------
- * WE WILL ALWAYS ACKNOWLEDGE THE COMMIT EVEN WHEN RECEIVING IT MULTIPLE
- * TIMES SINCE IT WILL ALWAYS COME FROM A NEW PRESIDENT.
- *------------------------------------------------------------------------*/
- signal->theData[0] = getOwnNodeId();
- sendSignal(Tblockref, GSN_COMMIT_FAILCONF, signal, 1, JBA);
- return;
-}//Qmgr::execCOMMIT_FAILREQ()
-
-/*--------------------------------------------------------------------------*/
-/* WE HAVE RECEIVED A CONFIRM OF THAT THIS NODE HAVE COMMITTED THE FAILURES.*/
-/*--------------------------------------------------------------------------*/
-/*******************************/
-/* COMMIT_FAILCONF */
-/*******************************/
-void Qmgr::execCOMMIT_FAILCONF(Signal* signal)
-{
- NodeRecPtr nodePtr;
- NodeRecPtr replyNodePtr;
- jamEntry();
- replyNodePtr.i = signal->theData[0];
-
- ptrCheckGuard(replyNodePtr, MAX_NDB_NODES, nodeRec);
- replyNodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- if (nodePtr.p->sendCommitFailReqStatus == Q_ACTIVE) {
- jam();
- return;
- }//if
- }//if
- }//for
- /*-----------------------------------------------------------------------*/
- /* WE HAVE SUCCESSFULLY COMMITTED A SET OF NODE FAILURES. */
- /*-----------------------------------------------------------------------*/
- ctoStatus = Q_NOT_ACTIVE;
- if (cnoFailedNodes != 0) {
- jam();
- /**----------------------------------------------------------------------
- * A FAILURE OCCURRED IN THE MIDDLE OF THE COMMIT PROCESS. WE ARE NOW
- * READY TO START THE FAILED NODE PROCESS FOR THIS NODE.
- *----------------------------------------------------------------------*/
- cfailureNr = cfailureNr + 1;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- sendPrepFailReq(signal, nodePtr.i);
- }//if
- }//for
- }//if
- return;
-}//Qmgr::execCOMMIT_FAILCONF()
-
-/**--------------------------------------------------------------------------
- * IF THE PRESIDENT FAILS IN THE MIDDLE OF THE COMMIT OF A FAILED NODE THEN
- * THE NEW PRESIDENT NEEDS TO QUERY THE COMMIT STATUS IN THE RUNNING NODES.
- *---------------------------------------------------------------------------*/
-/*******************************/
-/* PRES_TOCONF */
-/*******************************/
-void Qmgr::execPRES_TOCONF(Signal* signal)
-{
- NodeRecPtr nodePtr;
- NodeRecPtr replyNodePtr;
- jamEntry();
- replyNodePtr.i = signal->theData[0];
- UintR TfailureNr = signal->theData[1];
- if (ctoFailureNr < TfailureNr) {
- jam();
- ctoFailureNr = TfailureNr;
- }//if
- ptrCheckGuard(replyNodePtr, MAX_NDB_NODES, nodeRec);
- replyNodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->sendPresToStatus == Q_ACTIVE) {
- jam();
- return;
- }//if
- }//for
- /*-------------------------------------------------------------------------*/
- /* WE ARE NOW READY TO DISCOVER WHETHER THE FAILURE WAS COMMITTED OR NOT. */
- /*-------------------------------------------------------------------------*/
- if (ctoFailureNr > ccommitFailureNr) {
- jam();
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- nodePtr.p->sendCommitFailReqStatus = Q_ACTIVE;
- signal->theData[0] = cpdistref;
- signal->theData[1] = ctoFailureNr;
- sendSignal(nodePtr.p->blockRef, GSN_COMMIT_FAILREQ, signal, 2, JBA);
- }//if
- }//for
- return;
- }//if
- /*-------------------------------------------------------------------------*/
- /* WE ARE NOW READY TO START THE NEW NODE FAILURE PROCESS. */
- /*-------------------------------------------------------------------------*/
- ctoStatus = Q_NOT_ACTIVE;
- cfailureNr = cfailureNr + 1;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- sendPrepFailReq(signal, nodePtr.i);
- }//if
- }//for
- return;
-}//Qmgr::execPRES_TOCONF()
-
-/*--------------------------------------------------------------------------*/
-// Provide information about the configured NDB nodes in the system.
-/*--------------------------------------------------------------------------*/
-void Qmgr::execREAD_NODESREQ(Signal* signal)
-{
- jamEntry();
-
- BlockReference TBref = signal->theData[0];
-
- ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
-
- NodeRecPtr nodePtr;
- nodePtr.i = getOwnNodeId();
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
-
- NdbNodeBitmask tmp = c_definedNodes;
- tmp.bitANDC(c_clusterNodes);
-
- readNodes->noOfNodes = c_definedNodes.count();
- readNodes->masterNodeId = cpresident;
- readNodes->ndynamicId = nodePtr.p->ndynamicId;
- c_definedNodes.copyto(NdbNodeBitmask::Size, readNodes->definedNodes);
- c_clusterNodes.copyto(NdbNodeBitmask::Size, readNodes->clusterNodes);
- tmp.copyto(NdbNodeBitmask::Size, readNodes->inactiveNodes);
- NdbNodeBitmask::clear(readNodes->startingNodes);
- NdbNodeBitmask::clear(readNodes->startedNodes);
-
- sendSignal(TBref, GSN_READ_NODESCONF, signal,
- ReadNodesConf::SignalLength, JBB);
-}//Qmgr::execREAD_NODESREQ()
-
-void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, Uint32 line,
- NodeId failedNodeId) {
- jam();
-
- // Broadcast that this node is failing to other nodes
- failReport(signal, getOwnNodeId(), (UintR)ZTRUE, FailRep::ZOWN_FAILURE);
-
- char buf[100];
- BaseString::snprintf(buf, 100,
- "Node was shutdown during startup because node %d failed",
- failedNodeId);
-
- progError(line, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
-}
-
-
-void Qmgr::systemErrorLab(Signal* signal, Uint32 line, const char * message)
-{
- jam();
- // Broadcast that this node is failing to other nodes
- failReport(signal, getOwnNodeId(), (UintR)ZTRUE, FailRep::ZOWN_FAILURE);
-
- // If it's known why shutdown occured
- // an error message has been passed to this function
- progError(line, NDBD_EXIT_NDBREQUIRE, message);
-
- return;
-}//Qmgr::systemErrorLab()
-
-
-/**---------------------------------------------------------------------------
- * A FAILURE HAVE BEEN DISCOVERED ON A NODE. WE NEED TO CLEAR A
- * NUMBER OF VARIABLES.
- *---------------------------------------------------------------------------*/
-void Qmgr::failReport(Signal* signal,
- Uint16 aFailedNode,
- UintR aSendFailRep,
- FailRep::FailCause aFailCause)
-{
- UintR tfrMinDynamicId;
- NodeRecPtr failedNodePtr;
- NodeRecPtr nodePtr;
- NodeRecPtr presidentNodePtr;
-
-
- failedNodePtr.i = aFailedNode;
- ptrCheckGuard(failedNodePtr, MAX_NDB_NODES, nodeRec);
- if (failedNodePtr.p->phase == ZRUNNING) {
- jam();
-/* WE ALSO NEED TO ADD HERE SOME CODE THAT GETS OUR NEW NEIGHBOURS. */
- if (cpresident == getOwnNodeId()) {
- jam();
- if (failedNodePtr.p->sendCommitFailReqStatus == Q_ACTIVE) {
- jam();
- signal->theData[0] = failedNodePtr.i;
- sendSignal(QMGR_REF, GSN_COMMIT_FAILCONF, signal, 1, JBA);
- }//if
- if (failedNodePtr.p->sendPresToStatus == Q_ACTIVE) {
- jam();
- signal->theData[0] = failedNodePtr.i;
- signal->theData[1] = ccommitFailureNr;
- sendSignal(QMGR_REF, GSN_PRES_TOCONF, signal, 2, JBA);
- }//if
- }//if
- failedNodePtr.p->phase = ZPREPARE_FAIL;
- failedNodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
- failedNodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
- failedNodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
- setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
- if (aSendFailRep == ZTRUE) {
- jam();
- if (failedNodePtr.i != getOwnNodeId()) {
- jam();
- FailRep * const failRep = (FailRep *)&signal->theData[0];
- failRep->failNodeId = failedNodePtr.i;
- failRep->failCause = aFailCause;
- sendSignal(failedNodePtr.p->blockRef, GSN_FAIL_REP, signal,
- FailRep::SignalLength, JBA);
- }//if
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- FailRep * const failRep = (FailRep *)&signal->theData[0];
- failRep->failNodeId = failedNodePtr.i;
- failRep->failCause = aFailCause;
- sendSignal(nodePtr.p->blockRef, GSN_FAIL_REP, signal,
- FailRep::SignalLength, JBA);
- }//if
- }//for
- }//if
- if (failedNodePtr.i == getOwnNodeId()) {
- jam();
- return;
- }//if
- failedNodePtr.p->ndynamicId = 0;
- findNeighbours(signal);
- if (failedNodePtr.i == cpresident) {
- jam();
- /**--------------------------------------------------------------------
- * IF PRESIDENT HAVE FAILED WE MUST CALCULATE THE NEW PRESIDENT BY
- * FINDING THE NODE WITH THE MINIMUM DYNAMIC IDENTITY.
- *---------------------------------------------------------------------*/
- tfrMinDynamicId = (UintR)-1;
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- if (nodePtr.p->ndynamicId < tfrMinDynamicId) {
- jam();
- tfrMinDynamicId = nodePtr.p->ndynamicId;
- cpresident = nodePtr.i;
- }//if
- }//if
- }//for
- presidentNodePtr.i = cpresident;
- ptrCheckGuard(presidentNodePtr, MAX_NDB_NODES, nodeRec);
- cpdistref = presidentNodePtr.p->blockRef;
- if (cpresident == getOwnNodeId()) {
- CRASH_INSERTION(920);
- cfailureNr = cprepareFailureNr;
- ctoFailureNr = 0;
- ctoStatus = Q_ACTIVE;
- c_start.reset(); // Don't take over nodes being started
- if (cnoCommitFailedNodes > 0) {
- jam();
- /**-----------------------------------------------------------------
- * IN THIS SITUATION WE ARE UNCERTAIN OF WHETHER THE NODE FAILURE
- * PROCESS WAS COMMITTED. WE NEED TO QUERY THE OTHER NODES ABOUT
- * THEIR STATUS.
- *-----------------------------------------------------------------*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES;
- nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- nodePtr.p->sendPresToStatus = Q_ACTIVE;
- signal->theData[0] = cpdistref;
- signal->theData[1] = cprepareFailureNr;
- sendSignal(nodePtr.p->blockRef, GSN_PRES_TOREQ,
- signal, 1, JBA);
- }//if
- }//for
- } else {
- jam();
- /*-----------------------------------------------------------------*/
- // In this case it could be that a commit process is still ongoing.
- // If so we must conclude it as the new master.
- /*-----------------------------------------------------------------*/
- for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES;
- nodePtr.i++) {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZRUNNING) {
- jam();
- nodePtr.p->sendCommitFailReqStatus = Q_ACTIVE;
- signal->theData[0] = cpdistref;
- signal->theData[1] = ccommitFailureNr;
- sendSignal(nodePtr.p->blockRef, GSN_COMMIT_FAILREQ, signal,
- 2, JBA);
- }//if
- }//for
- }//if
- }//if
- }//if
- arrGuard(cnoFailedNodes, MAX_NDB_NODES);
- cfailedNodes[cnoFailedNodes] = failedNodePtr.i;
- cnoFailedNodes = cnoFailedNodes + 1;
- }//if
-}//Qmgr::failReport()
-
-/*---------------------------------------------------------------------------*/
-/* INPUT: TTDI_DYN_ID */
-/* OUTPUT: TTDI_NODE_ID */
-/*---------------------------------------------------------------------------*/
-Uint16 Qmgr::translateDynamicIdToNodeId(Signal* signal, UintR TdynamicId)
-{
- NodeRecPtr tdiNodePtr;
- Uint16 TtdiNodeId = ZNIL;
-
- for (tdiNodePtr.i = 1; tdiNodePtr.i < MAX_NDB_NODES; tdiNodePtr.i++) {
- jam();
- ptrAss(tdiNodePtr, nodeRec);
- if (tdiNodePtr.p->ndynamicId == TdynamicId) {
- jam();
- TtdiNodeId = tdiNodePtr.i;
- break;
- }//if
- }//for
- if (TtdiNodeId == ZNIL) {
- jam();
- systemErrorLab(signal, __LINE__);
- }//if
- return TtdiNodeId;
-}//Qmgr::translateDynamicIdToNodeId()
-
-/**--------------------------------------------------------------------------
- * WHEN RECEIVING PREPARE FAILURE REQUEST WE WILL IMMEDIATELY CLOSE
- * COMMUNICATION WITH ALL THOSE NODES.
- *--------------------------------------------------------------------------*/
-void Qmgr::sendCloseComReq(Signal* signal, BlockReference TBRef, Uint16 aFailNo)
-{
- CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
-
- closeCom->xxxBlockRef = TBRef;
- closeCom->failNo = aFailNo;
- closeCom->noOfNodes = cnoPrepFailedNodes;
-
- NodeBitmask::clear(closeCom->theNodes);
-
- for(int i = 0; i < cnoPrepFailedNodes; i++) {
- const NodeId nodeId = cprepFailedNodes[i];
- jam();
- NodeBitmask::set(closeCom->theNodes, nodeId);
- }
-
- sendSignal(CMVMI_REF, GSN_CLOSE_COMREQ, signal,
- CloseComReqConf::SignalLength, JBA);
-
-}//Qmgr::sendCloseComReq()
-
-void
-Qmgr::sendPrepFailReqRef(Signal* signal,
- Uint32 dstBlockRef,
- GlobalSignalNumber gsn,
- Uint32 blockRef,
- Uint32 failNo,
- Uint32 noOfNodes,
- const NodeId theNodes[]){
-
- PrepFailReqRef * const prepFail = (PrepFailReqRef *)&signal->theData[0];
- prepFail->xxxBlockRef = blockRef;
- prepFail->failNo = failNo;
- prepFail->noOfNodes = noOfNodes;
-
- NodeBitmask::clear(prepFail->theNodes);
-
- for(Uint32 i = 0; i<noOfNodes; i++){
- const NodeId nodeId = theNodes[i];
- NodeBitmask::set(prepFail->theNodes, nodeId);
- }
-
- sendSignal(dstBlockRef, gsn, signal, PrepFailReqRef::SignalLength, JBA);
-}
-
-
-/**--------------------------------------------------------------------------
- * SEND PREPARE FAIL REQUEST FROM PRESIDENT.
- *---------------------------------------------------------------------------*/
-void Qmgr::sendPrepFailReq(Signal* signal, Uint16 aNode)
-{
- NodeRecPtr sendNodePtr;
- sendNodePtr.i = aNode;
- ptrCheckGuard(sendNodePtr, MAX_NDB_NODES, nodeRec);
- sendNodePtr.p->sendPrepFailReqStatus = Q_ACTIVE;
-
- sendPrepFailReqRef(signal,
- sendNodePtr.p->blockRef,
- GSN_PREP_FAILREQ,
- reference(),
- cfailureNr,
- cnoFailedNodes,
- cfailedNodes);
-}//Qmgr::sendPrepFailReq()
-
-/**
- * Arbitration module. Rest of QMGR calls us only via
- * the "handle" routines.
- */
-
-/**
- * Should < 1/2 nodes die unconditionally. Affects only >= 3-way
- * replication.
- */
-static const bool g_ndb_arbit_one_half_rule = false;
-
-/**
- * Config signals are logically part of CM_INIT.
- */
-void
-Qmgr::execARBIT_CFG(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- unsigned rank = sd->code;
- ndbrequire(1 <= rank && rank <= 2);
- arbitRec.apiMask[0].bitOR(sd->mask);
- arbitRec.apiMask[rank] = sd->mask;
-}
-
-/**
- * ContinueB delay (0=JBA 1=JBB)
- */
-Uint32 Qmgr::getArbitDelay()
-{
- switch (arbitRec.state) {
- case ARBIT_NULL:
- jam();
- break;
- case ARBIT_INIT:
- jam();
- case ARBIT_FIND:
- jam();
- case ARBIT_PREP1:
- jam();
- case ARBIT_PREP2:
- jam();
- case ARBIT_START:
- jam();
- return 100;
- case ARBIT_RUN:
- jam();
- return 1000;
- case ARBIT_CHOOSE:
- jam();
- return 10;
- case ARBIT_CRASH: // if we could wait
- jam();
- return 100;
- }
- ndbrequire(false);
- return (Uint32)-1;
-}
-
-/**
- * Time to wait for reply. There is only 1 config parameter
- * (timeout for CHOOSE). XXX The rest are guesses.
- */
-Uint32 Qmgr::getArbitTimeout()
-{
- switch (arbitRec.state) {
- case ARBIT_NULL:
- jam();
- break;
- case ARBIT_INIT: // not used
- jam();
- case ARBIT_FIND: // not used
- jam();
- return 1000;
- case ARBIT_PREP1:
- jam();
- case ARBIT_PREP2:
- jam();
- return 1000 + cnoOfNodes * hb_send_timer.getDelay();
- case ARBIT_START:
- jam();
- return 1000 + arbitRec.timeout;
- case ARBIT_RUN: // not used (yet)
- jam();
- return 1000;
- case ARBIT_CHOOSE:
- jam();
- return arbitRec.timeout;
- case ARBIT_CRASH: // if we could wait
- jam();
- return 100;
- }
- ndbrequire(false);
- return (Uint32)-1;
-}
-
-/**
- * Start arbitration thread when we are president and database
- * is opened for the first time.
- *
- * XXX Do arbitration check just like on node failure. Since
- * there is no arbitrator yet, must win on counts alone.
- */
-void
-Qmgr::handleArbitStart(Signal* signal)
-{
- jam();
- ndbrequire(cpresident == getOwnNodeId());
- ndbrequire(arbitRec.state == ARBIT_NULL);
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- startArbitThread(signal);
-}
-
-/**
- * Handle API node failure. Called also by non-president nodes.
- * If we are president go back to INIT state, otherwise to NULL.
- * Start new thread to save time.
- */
-void
-Qmgr::handleArbitApiFail(Signal* signal, Uint16 nodeId)
-{
- if (arbitRec.node != nodeId) {
- jam();
- return;
- }
- reportArbitEvent(signal, NDB_LE_ArbitState);
- arbitRec.node = 0;
- switch (arbitRec.state) {
- case ARBIT_NULL: // should not happen
- jam();
- case ARBIT_INIT:
- jam();
- case ARBIT_FIND:
- jam();
- break;
- case ARBIT_PREP1: // start from beginning
- jam();
- case ARBIT_PREP2:
- jam();
- case ARBIT_START:
- jam();
- case ARBIT_RUN:
- if (cpresident == getOwnNodeId()) {
- jam();
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- startArbitThread(signal);
- } else {
- jam();
- arbitRec.state = ARBIT_NULL;
- }
- break;
- case ARBIT_CHOOSE: // XXX too late
- jam();
- case ARBIT_CRASH:
- jam();
- break;
- default:
- ndbrequire(false);
- break;
- }
-}
-
-/**
- * Handle NDB node add. Ignore if arbitration thread not yet
- * started. If PREP is not ready, go back to INIT. Otherwise
- * the new node gets arbitrator and ticket once we reach RUN state.
- * Start new thread to save time.
- */
-void
-Qmgr::handleArbitNdbAdd(Signal* signal, Uint16 nodeId)
-{
- jam();
- ndbrequire(cpresident == getOwnNodeId());
- switch (arbitRec.state) {
- case ARBIT_NULL: // before db opened
- jam();
- break;
- case ARBIT_INIT: // start from beginning
- jam();
- case ARBIT_FIND:
- jam();
- case ARBIT_PREP1:
- jam();
- case ARBIT_PREP2:
- jam();
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- startArbitThread(signal);
- break;
- case ARBIT_START: // process in RUN state
- jam();
- case ARBIT_RUN:
- jam();
- arbitRec.newMask.set(nodeId);
- break;
- case ARBIT_CHOOSE: // XXX too late
- jam();
- case ARBIT_CRASH:
- jam();
- break;
- default:
- ndbrequire(false);
- break;
- }
-}
-
-/**
- * Check if current nodeset can survive. The decision is
- * based on node count, node groups, and on external arbitrator
- * (if we have one). Always starts a new thread because
- * 1) CHOOSE cannot wait 2) if we are new president we need
- * a thread 3) if we are old president it does no harm.
- */
-void
-Qmgr::handleArbitCheck(Signal* signal)
-{
- jam();
- ndbrequire(cpresident == getOwnNodeId());
- NodeBitmask ndbMask;
- computeArbitNdbMask(ndbMask);
- if (g_ndb_arbit_one_half_rule &&
- 2 * ndbMask.count() < cnoOfNodes) {
- jam();
- arbitRec.code = ArbitCode::LoseNodes;
- } else {
- jam();
- CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
- sd->blockRef = reference();
- sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
- sd->mask = ndbMask;
- EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
- CheckNodeGroups::SignalLength);
- jamEntry();
- switch (sd->output) {
- case CheckNodeGroups::Win:
- jam();
- arbitRec.code = ArbitCode::WinGroups;
- break;
- case CheckNodeGroups::Lose:
- jam();
- arbitRec.code = ArbitCode::LoseGroups;
- break;
- case CheckNodeGroups::Partitioning:
- jam();
- arbitRec.code = ArbitCode::Partitioning;
- if (g_ndb_arbit_one_half_rule &&
- 2 * ndbMask.count() > cnoOfNodes) {
- jam();
- arbitRec.code = ArbitCode::WinNodes;
- }
- break;
- default:
- ndbrequire(false);
- break;
- }
- }
- switch (arbitRec.code) {
- case ArbitCode::LoseNodes:
- jam();
- case ArbitCode::LoseGroups:
- jam();
- goto crashme;
- case ArbitCode::WinNodes:
- jam();
- case ArbitCode::WinGroups:
- jam();
- if (arbitRec.state == ARBIT_RUN) {
- jam();
- break;
- }
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- break;
- case ArbitCode::Partitioning:
- if (arbitRec.state == ARBIT_RUN) {
- jam();
- arbitRec.state = ARBIT_CHOOSE;
- arbitRec.newstate = true;
- break;
- }
- if (arbitRec.apiMask[0].count() != 0) {
- jam();
- arbitRec.code = ArbitCode::LoseNorun;
- } else {
- jam();
- arbitRec.code = ArbitCode::LoseNocfg;
- }
- goto crashme;
- default:
- crashme:
- jam();
- arbitRec.state = ARBIT_CRASH;
- arbitRec.newstate = true;
- break;
- }
- reportArbitEvent(signal, NDB_LE_ArbitResult);
- switch (arbitRec.state) {
- default:
- jam();
- arbitRec.newMask.bitAND(ndbMask); // delete failed nodes
- arbitRec.recvMask.bitAND(ndbMask);
- sendCommitFailReq(signal); // start commit of failed nodes
- break;
- case ARBIT_CHOOSE:
- jam();
- case ARBIT_CRASH:
- jam();
- break;
- }
- startArbitThread(signal);
-}
-
-/**
- * Start a new continueB thread. The thread id is incremented
- * so that any old thread will exit.
- */
-void
-Qmgr::startArbitThread(Signal* signal)
-{
- jam();
- ndbrequire(cpresident == getOwnNodeId());
- arbitRec.code = ArbitCode::ThreadStart;
- reportArbitEvent(signal, NDB_LE_ArbitState);
- signal->theData[1] = ++arbitRec.thread;
- runArbitThread(signal);
-}
-
-/**
- * Handle arbitration thread. The initial thread normally ends
- * up in RUN state. New thread can be started to save time.
- */
-void
-Qmgr::runArbitThread(Signal* signal)
-{
-#ifdef DEBUG_ARBIT
- NodeBitmask ndbMask;
- computeArbitNdbMask(ndbMask);
- ndbout << "arbit thread:";
- ndbout << " state=" << arbitRec.state;
- ndbout << " newstate=" << arbitRec.newstate;
- ndbout << " thread=" << arbitRec.thread;
- ndbout << " node=" << arbitRec.node;
- ndbout << " ticket=" << arbitRec.ticket.getText();
- ndbout << " ndbmask=" << ndbMask.getText();
- ndbout << " sendcount=" << arbitRec.sendCount;
- ndbout << " recvcount=" << arbitRec.recvCount;
- ndbout << " recvmask=" << arbitRec.recvMask.getText();
- ndbout << " code=" << arbitRec.code;
- ndbout << endl;
-#endif
- if (signal->theData[1] != arbitRec.thread) {
- jam();
- return; // old thread dies
- }
- switch (arbitRec.state) {
- case ARBIT_INIT: // main thread
- jam();
- stateArbitInit(signal);
- break;
- case ARBIT_FIND:
- jam();
- stateArbitFind(signal);
- break;
- case ARBIT_PREP1:
- jam();
- case ARBIT_PREP2:
- jam();
- stateArbitPrep(signal);
- break;
- case ARBIT_START:
- jam();
- stateArbitStart(signal);
- break;
- case ARBIT_RUN:
- jam();
- stateArbitRun(signal);
- break;
- case ARBIT_CHOOSE: // partitition thread
- jam();
- stateArbitChoose(signal);
- break;
- case ARBIT_CRASH:
- jam();
- stateArbitCrash(signal);
- break;
- default:
- ndbrequire(false);
- break;
- }
- signal->theData[0] = ZARBIT_HANDLING;
- signal->theData[1] = arbitRec.thread;
- signal->theData[2] = arbitRec.state; // just for signal log
- Uint32 delay = getArbitDelay();
- if (delay == 0) {
- jam();
- sendSignal(QMGR_REF, GSN_CONTINUEB, signal, 3, JBA);
- } else if (delay == 1) {
- jam();
- sendSignal(QMGR_REF, GSN_CONTINUEB, signal, 3, JBB);
- } else {
- jam();
- sendSignalWithDelay(QMGR_REF, GSN_CONTINUEB, signal, delay, 3);
- }//if
-}
-
-/**
- * Handle INIT state. Generate next ticket. Switch to FIND
- * state without delay.
- */
-void
-Qmgr::stateArbitInit(Signal* signal)
-{
- if (arbitRec.newstate) {
- jam();
- CRASH_INSERTION((Uint32)910 + arbitRec.state);
-
- arbitRec.node = 0;
- arbitRec.ticket.update();
- arbitRec.newMask.clear();
- arbitRec.code = 0;
- arbitRec.newstate = false;
- }
- arbitRec.state = ARBIT_FIND;
- arbitRec.newstate = true;
- stateArbitFind(signal);
-}
-
-/**
- * Handle FIND state. Find first arbitrator which is alive
- * and invoke PREP state without delay. If none are found,
- * loop in FIND state. This is forever if no arbitrators
- * are configured (not the normal case).
- *
- * XXX Add adaptive behaviour to avoid getting stuck on API
- * nodes which are alive but do not respond or die too soon.
- */
-void
-Qmgr::stateArbitFind(Signal* signal)
-{
- if (arbitRec.newstate) {
- jam();
- CRASH_INSERTION((Uint32)910 + arbitRec.state);
-
- arbitRec.code = 0;
- arbitRec.newstate = false;
- }
- NodeRecPtr aPtr;
- for (unsigned rank = 1; rank <= 2; rank++) {
- jam();
- aPtr.i = 0;
- const unsigned stop = NodeBitmask::NotFound;
- while ((aPtr.i = arbitRec.apiMask[rank].find(aPtr.i + 1)) != stop) {
- jam();
- ptrAss(aPtr, nodeRec);
- if (aPtr.p->phase != ZAPI_ACTIVE)
- continue;
- arbitRec.node = aPtr.i;
- arbitRec.state = ARBIT_PREP1;
- arbitRec.newstate = true;
- stateArbitPrep(signal);
- return;
- }
- }
-}
-
-/**
- * Handle PREP states. First round nulls any existing tickets.
- * Second round sends new ticket. When all confirms have been
- * received invoke START state immediately.
- */
-void
-Qmgr::stateArbitPrep(Signal* signal)
-{
- if (arbitRec.newstate) {
- jam();
- CRASH_INSERTION((Uint32)910 + arbitRec.state);
-
- arbitRec.sendCount = 0; // send all at once
- computeArbitNdbMask(arbitRec.recvMask); // to send and recv
- arbitRec.recvMask.clear(getOwnNodeId());
- arbitRec.code = 0;
- arbitRec.newstate = false;
- }
- if (! arbitRec.sendCount) {
- jam();
- NodeRecPtr aPtr;
- aPtr.i = 0;
- const unsigned stop = NodeBitmask::NotFound;
- while ((aPtr.i = arbitRec.recvMask.find(aPtr.i + 1)) != stop) {
- jam();
- ptrAss(aPtr, nodeRec);
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- sd->sender = getOwnNodeId();
- if (arbitRec.state == ARBIT_PREP1) {
- jam();
- sd->code = ArbitCode::PrepPart1;
- } else {
- jam();
- sd->code = ArbitCode::PrepPart2;
- }
- sd->node = arbitRec.node;
- sd->ticket = arbitRec.ticket;
- sd->mask.clear();
- sendSignal(aPtr.p->blockRef, GSN_ARBIT_PREPREQ, signal,
- ArbitSignalData::SignalLength, JBB);
- }
- arbitRec.setTimestamp(); // send time
- arbitRec.sendCount = 1;
- return;
- }
- if (arbitRec.code != 0) { // error
- jam();
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- return;
- }
- if (arbitRec.recvMask.count() == 0) { // recv all
- if (arbitRec.state == ARBIT_PREP1) {
- jam();
- arbitRec.state = ARBIT_PREP2;
- arbitRec.newstate = true;
- } else {
- jam();
- arbitRec.state = ARBIT_START;
- arbitRec.newstate = true;
- stateArbitStart(signal);
- }
- return;
- }
- if (arbitRec.getTimediff() > getArbitTimeout()) {
- jam();
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- return;
- }
-}
-
-void
-Qmgr::execARBIT_PREPREQ(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (getOwnNodeId() == cpresident) {
- jam();
- return; // wrong state
- }
- if (sd->sender != cpresident) {
- jam();
- return; // wrong state
- }
- NodeRecPtr aPtr;
- aPtr.i = sd->sender;
- ptrAss(aPtr, nodeRec);
- switch (sd->code) {
- case ArbitCode::PrepPart1: // zero them just to be sure
- jam();
- arbitRec.node = 0;
- arbitRec.ticket.clear();
- break;
- case ArbitCode::PrepPart2: // non-president enters RUN state
- jam();
- case ArbitCode::PrepAtrun:
- jam();
- arbitRec.node = sd->node;
- arbitRec.ticket = sd->ticket;
- arbitRec.code = sd->code;
- reportArbitEvent(signal, NDB_LE_ArbitState);
- arbitRec.state = ARBIT_RUN;
- arbitRec.newstate = true;
- if (sd->code == ArbitCode::PrepAtrun) {
- jam();
- return;
- }
- break;
- default:
- jam();
- ndbrequire(false);
- }
- sd->sender = getOwnNodeId();
- sd->code = 0;
- sendSignal(aPtr.p->blockRef, GSN_ARBIT_PREPCONF, signal,
- ArbitSignalData::SignalLength, JBB);
-}
-
-void
-Qmgr::execARBIT_PREPCONF(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (! arbitRec.match(sd)) {
- jam();
- return; // stray signal
- }
- if (arbitRec.state != ARBIT_PREP1 && arbitRec.state != ARBIT_PREP2) {
- jam();
- return; // wrong state
- }
- if (! arbitRec.recvMask.get(sd->sender)) {
- jam();
- return; // wrong state
- }
- arbitRec.recvMask.clear(sd->sender);
- if (arbitRec.code == 0 && sd->code != 0) {
- jam();
- arbitRec.code = sd->code;
- }//if
-}
-
-void
-Qmgr::execARBIT_PREPREF(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (sd->code == 0) {
- jam();
- sd->code = ArbitCode::ErrUnknown;
- }
- execARBIT_PREPCONF(signal);
-}
-
-/**
- * Handle START state. On first call send start request to
- * the chosen arbitrator. Then wait for a CONF.
- */
-void
-Qmgr::stateArbitStart(Signal* signal)
-{
- if (arbitRec.newstate) {
- jam();
- CRASH_INSERTION((Uint32)910 + arbitRec.state);
-
- arbitRec.sendCount = 0;
- arbitRec.recvCount = 0;
- arbitRec.code = 0;
- arbitRec.newstate = false;
- }
- if (! arbitRec.sendCount) {
- jam();
- BlockReference blockRef = calcApiClusterMgrBlockRef(arbitRec.node);
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- sd->sender = getOwnNodeId();
- sd->code = 0;
- sd->node = arbitRec.node;
- sd->ticket = arbitRec.ticket;
- sd->mask.clear();
- sendSignal(blockRef, GSN_ARBIT_STARTREQ, signal,
- ArbitSignalData::SignalLength, JBB);
- arbitRec.sendCount = 1;
- arbitRec.setTimestamp(); // send time
- return;
- }
- if (arbitRec.recvCount) {
- jam();
- reportArbitEvent(signal, NDB_LE_ArbitState);
- if (arbitRec.code == ArbitCode::ApiStart) {
- jam();
- arbitRec.state = ARBIT_RUN;
- arbitRec.newstate = true;
- return;
- }
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- return;
- }
- if (arbitRec.getTimediff() > getArbitTimeout()) {
- jam();
- arbitRec.code = ArbitCode::ErrTimeout;
- reportArbitEvent(signal, NDB_LE_ArbitState);
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- return;
- }
-}
-
-void
-Qmgr::execARBIT_STARTCONF(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (! arbitRec.match(sd)) {
- jam();
- return; // stray signal
- }
- if (arbitRec.state != ARBIT_START) {
- jam();
- return; // wrong state
- }
- if (arbitRec.recvCount) {
- jam();
- return; // wrong state
- }
- arbitRec.code = sd->code;
- arbitRec.recvCount = 1;
-}
-
-void
-Qmgr::execARBIT_STARTREF(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (sd->code == 0) {
- jam();
- sd->code = ArbitCode::ErrUnknown;
- }
- execARBIT_STARTCONF(signal);
-}
-
-/**
- * Handle RUN state. Send ticket to any new nodes which have
- * appeared after PREP state. We don't care about a CONF.
- */
-void
-Qmgr::stateArbitRun(Signal* signal)
-{
- if (arbitRec.newstate) {
- jam();
- CRASH_INSERTION((Uint32)910 + arbitRec.state);
-
- arbitRec.code = 0;
- arbitRec.newstate = false;
- }
- NodeRecPtr aPtr;
- aPtr.i = 0;
- const unsigned stop = NodeBitmask::NotFound;
- while ((aPtr.i = arbitRec.newMask.find(aPtr.i + 1)) != stop) {
- jam();
- arbitRec.newMask.clear(aPtr.i);
- ptrAss(aPtr, nodeRec);
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- sd->sender = getOwnNodeId();
- sd->code = ArbitCode::PrepAtrun;
- sd->node = arbitRec.node;
- sd->ticket = arbitRec.ticket;
- sd->mask.clear();
- sendSignal(aPtr.p->blockRef, GSN_ARBIT_PREPREQ, signal,
- ArbitSignalData::SignalLength, JBB);
- }
-}
-
-/**
- * Handle CHOOSE state. Entered only from RUN state when
- * there is a possible network partitioning. Send CHOOSE to
- * the arbitrator. On win switch to INIT state because a new
- * ticket must be created.
- */
-void
-Qmgr::stateArbitChoose(Signal* signal)
-{
- if (arbitRec.newstate) {
- jam();
- CRASH_INSERTION((Uint32)910 + arbitRec.state);
-
- arbitRec.sendCount = 0;
- arbitRec.recvCount = 0;
- arbitRec.code = 0;
- arbitRec.newstate = false;
- }
- if (! arbitRec.sendCount) {
- jam();
- BlockReference blockRef = calcApiClusterMgrBlockRef(arbitRec.node);
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- sd->sender = getOwnNodeId();
- sd->code = 0;
- sd->node = arbitRec.node;
- sd->ticket = arbitRec.ticket;
- computeArbitNdbMask(sd->mask);
- sendSignal(blockRef, GSN_ARBIT_CHOOSEREQ, signal,
- ArbitSignalData::SignalLength, JBA);
- arbitRec.sendCount = 1;
- arbitRec.setTimestamp(); // send time
- return;
- }
- if (arbitRec.recvCount) {
- jam();
- reportArbitEvent(signal, NDB_LE_ArbitResult);
- if (arbitRec.code == ArbitCode::WinChoose) {
- jam();
- sendCommitFailReq(signal); // start commit of failed nodes
- arbitRec.state = ARBIT_INIT;
- arbitRec.newstate = true;
- return;
- }
- arbitRec.state = ARBIT_CRASH;
- arbitRec.newstate = true;
- stateArbitCrash(signal); // do it at once
- return;
- }
- if (arbitRec.getTimediff() > getArbitTimeout()) {
- jam();
- arbitRec.code = ArbitCode::ErrTimeout;
- reportArbitEvent(signal, NDB_LE_ArbitState);
- arbitRec.state = ARBIT_CRASH;
- arbitRec.newstate = true;
- stateArbitCrash(signal); // do it at once
- return;
- }
-}
-
-void
-Qmgr::execARBIT_CHOOSECONF(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (!arbitRec.match(sd)) {
- jam();
- return; // stray signal
- }
- if (arbitRec.state != ARBIT_CHOOSE) {
- jam();
- return; // wrong state
- }
- if (arbitRec.recvCount) {
- jam();
- return; // wrong state
- }
- arbitRec.recvCount = 1;
- arbitRec.code = sd->code;
-}
-
-void
-Qmgr::execARBIT_CHOOSEREF(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (sd->code == 0) {
- jam();
- sd->code = ArbitCode::ErrUnknown;
- }
- execARBIT_CHOOSECONF(signal);
-}
-
-/**
- * Handle CRASH state. We must crash immediately.
- * XXX tell other nodes in our party to crash too.
- */
-void
-Qmgr::stateArbitCrash(Signal* signal)
-{
- jam();
- if (arbitRec.newstate) {
- jam();
- CRASH_INSERTION((Uint32)910 + arbitRec.state);
- arbitRec.setTimestamp();
- arbitRec.code = 0;
- arbitRec.newstate = false;
- }
-#ifdef ndb_arbit_crash_wait_for_event_report_to_get_out
- if (! (arbitRec.getTimediff() > getArbitTimeout()))
- return;
-#endif
- CRASH_INSERTION(932);
- progError(__LINE__, NDBD_EXIT_ARBIT_SHUTDOWN,
- "Arbitrator decided to shutdown this node");
-}
-
-/**
- * Arbitrator may inform us that it will exit. This lets us
- * start looking sooner for a new one. Handle it like API node
- * failure.
- */
-void
-Qmgr::execARBIT_STOPREP(Signal* signal)
-{
- jamEntry();
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- if (! arbitRec.match(sd)) {
- jam();
- return; // stray signal
- }
- arbitRec.code = ArbitCode::ApiExit;
- handleArbitApiFail(signal, arbitRec.node);
-}
-
-void
-Qmgr::computeArbitNdbMask(NodeBitmask& aMask)
-{
- NodeRecPtr aPtr;
- aMask.clear();
- for (aPtr.i = 1; aPtr.i < MAX_NDB_NODES; aPtr.i++) {
- jam();
- ptrAss(aPtr, nodeRec);
- if (getNodeInfo(aPtr.i).getType() == NodeInfo::DB && aPtr.p->phase == ZRUNNING){
- jam();
- aMask.set(aPtr.i);
- }
- }
-}
-
-/**
- * Report arbitration event. We use arbitration signal format
- * where sender (word 0) is event type.
- */
-void
-Qmgr::reportArbitEvent(Signal* signal, Ndb_logevent_type type)
-{
- ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
- sd->sender = type;
- sd->code = arbitRec.code | (arbitRec.state << 16);
- sd->node = arbitRec.node;
- sd->ticket = arbitRec.ticket;
- sd->mask.clear();
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal,
- ArbitSignalData::SignalLength, JBB);
-}
-
-// end of arbitration module
-
-void
-Qmgr::execDUMP_STATE_ORD(Signal* signal)
-{
- switch (signal->theData[0]) {
- case 1:
- infoEvent("creadyDistCom = %d, cpresident = %d\n",
- creadyDistCom, cpresident);
- 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++){
- NodeRecPtr nodePtr;
- nodePtr.i = i;
- ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- char buf[100];
- switch(nodePtr.p->phase){
- case ZINIT:
- sprintf(buf, "Node %d: ZINIT(%d)", i, nodePtr.p->phase);
- break;
- case ZSTARTING:
- sprintf(buf, "Node %d: ZSTARTING(%d)", i, nodePtr.p->phase);
- break;
- case ZRUNNING:
- sprintf(buf, "Node %d: ZRUNNING(%d)", i, nodePtr.p->phase);
- break;
- case ZPREPARE_FAIL:
- sprintf(buf, "Node %d: ZPREPARE_FAIL(%d)", i, nodePtr.p->phase);
- break;
- case ZFAIL_CLOSING:
- sprintf(buf, "Node %d: ZFAIL_CLOSING(%d)", i, nodePtr.p->phase);
- break;
- case ZAPI_INACTIVE:
- sprintf(buf, "Node %d: ZAPI_INACTIVE(%d)", i, nodePtr.p->phase);
- break;
- case ZAPI_ACTIVE:
- sprintf(buf, "Node %d: ZAPI_ACTIVE(%d)", i, nodePtr.p->phase);
- break;
- default:
- sprintf(buf, "Node %d: <UNKNOWN>(%d)", i, nodePtr.p->phase);
- break;
- }
- infoEvent(buf);
- }
- }
-
-#ifdef ERROR_INSERT
- if (signal->theData[0] == 935 && signal->getLength() == 2)
- {
- SET_ERROR_INSERT_VALUE(935);
- c_error_insert_extra = signal->theData[1];
- }
-#endif
-}//Qmgr::execDUMP_STATE_ORD()
-
-
-void
-Qmgr::execAPI_BROADCAST_REP(Signal* signal)
-{
- jamEntry();
- ApiBroadcastRep api= *(const ApiBroadcastRep*)signal->getDataPtr();
-
- Uint32 len = signal->getLength() - ApiBroadcastRep::SignalLength;
- memmove(signal->theData, signal->theData+ApiBroadcastRep::SignalLength,
- 4*len);
-
- NodeBitmask mask;
- NodeRecPtr nodePtr;
- for (nodePtr.i = 1; nodePtr.i < MAX_NODES; nodePtr.i++)
- {
- jam();
- ptrAss(nodePtr, nodeRec);
- if (nodePtr.p->phase == ZAPI_ACTIVE &&
- getNodeInfo(nodePtr.i).m_version >= api.minVersion)
- {
- mask.set(nodePtr.i);
- }
- }
-
- NodeReceiverGroup rg(API_CLUSTERMGR, mask);
- sendSignal(rg, api.gsn, signal, len, JBB); // forward sections
-}
-
-void
-Qmgr::execNODE_FAILREP(Signal * signal)
-{
- jamEntry();
- // make sure any distributed signals get acknowledged
- // destructive of the signal
- c_counterMgr.execNODE_FAILREP(signal);
-}
-
-void
-Qmgr::execALLOC_NODEID_REQ(Signal * signal)
-{
- jamEntry();
- const AllocNodeIdReq * req = (AllocNodeIdReq*)signal->getDataPtr();
- Uint32 senderRef = req->senderRef;
- Uint32 nodeId = req->nodeId;
- Uint32 nodeType = req->nodeType;
- Uint32 error = 0;
-
- if (refToBlock(senderRef) != QMGR) // request from management server
- {
- /* master */
-
- if (getOwnNodeId() != cpresident)
- error = AllocNodeIdRef::NotMaster;
- else if (!opAllocNodeIdReq.m_tracker.done())
- error = AllocNodeIdRef::Busy;
- else if (c_connectedNodes.get(nodeId))
- error = AllocNodeIdRef::NodeConnected;
-
- if (error)
- {
- jam();
- AllocNodeIdRef * ref = (AllocNodeIdRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = error;
- ref->masterRef = numberToRef(QMGR, cpresident);
- sendSignal(senderRef, GSN_ALLOC_NODEID_REF, signal,
- AllocNodeIdRef::SignalLength, JBB);
- return;
- }
-
- if (ERROR_INSERTED(934) && nodeId != getOwnNodeId())
- {
- CRASH_INSERTION(934);
- }
-
- opAllocNodeIdReq.m_req = *req;
- opAllocNodeIdReq.m_error = 0;
- opAllocNodeIdReq.m_connectCount = getNodeInfo(refToNode(senderRef)).m_connectCount;
-
- jam();
- AllocNodeIdReq * req = (AllocNodeIdReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- NodeReceiverGroup rg(QMGR, c_clusterNodes);
- RequestTracker & p = opAllocNodeIdReq.m_tracker;
- p.init<AllocNodeIdRef>(c_counterMgr, rg, GSN_ALLOC_NODEID_REF, 0);
-
- sendSignal(rg, GSN_ALLOC_NODEID_REQ, signal,
- AllocNodeIdReq::SignalLength, JBB);
- return;
- }
-
- /* participant */
-
- if (c_connectedNodes.get(nodeId))
- error = AllocNodeIdRef::NodeConnected;
- else
- {
- NodeRecPtr nodePtr;
- nodePtr.i = nodeId;
- ptrAss(nodePtr, nodeRec);
- if (nodeType != getNodeInfo(nodeId).m_type)
- error = AllocNodeIdRef::NodeTypeMismatch;
- else if (nodePtr.p->failState != NORMAL)
- error = AllocNodeIdRef::NodeFailureHandlingNotCompleted;
- }
-
- if (error)
- {
- AllocNodeIdRef * ref = (AllocNodeIdRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = error;
- sendSignal(senderRef, GSN_ALLOC_NODEID_REF, signal,
- AllocNodeIdRef::SignalLength, JBB);
- return;
- }
-
- AllocNodeIdConf * conf = (AllocNodeIdConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_ALLOC_NODEID_CONF, signal,
- AllocNodeIdConf::SignalLength, JBB);
-}
-
-void
-Qmgr::execALLOC_NODEID_CONF(Signal * signal)
-{
- /* master */
-
- jamEntry();
- const AllocNodeIdConf * conf = (AllocNodeIdConf*)signal->getDataPtr();
- opAllocNodeIdReq.m_tracker.reportConf(c_counterMgr,
- refToNode(conf->senderRef));
- completeAllocNodeIdReq(signal);
-}
-
-
-void
-Qmgr::execALLOC_NODEID_REF(Signal * signal)
-{
- /* master */
-
- jamEntry();
- const AllocNodeIdRef * ref = (AllocNodeIdRef*)signal->getDataPtr();
- if (ref->errorCode == AllocNodeIdRef::NF_FakeErrorREF)
- {
- opAllocNodeIdReq.m_tracker.ignoreRef(c_counterMgr,
- refToNode(ref->senderRef));
- }
- else
- {
- opAllocNodeIdReq.m_tracker.reportRef(c_counterMgr,
- refToNode(ref->senderRef));
- if (opAllocNodeIdReq.m_error == 0)
- opAllocNodeIdReq.m_error = ref->errorCode;
- }
- completeAllocNodeIdReq(signal);
-}
-
-void
-Qmgr::completeAllocNodeIdReq(Signal *signal)
-{
- /* master */
-
- if (!opAllocNodeIdReq.m_tracker.done())
- {
- jam();
- return;
- }
-
- if (opAllocNodeIdReq.m_connectCount !=
- getNodeInfo(refToNode(opAllocNodeIdReq.m_req.senderRef)).m_connectCount)
- {
- // management server not same version as the original requester
- jam();
- return;
- }
-
- if (opAllocNodeIdReq.m_tracker.hasRef())
- {
- jam();
- AllocNodeIdRef * ref = (AllocNodeIdRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = opAllocNodeIdReq.m_req.senderData;
- ref->nodeId = opAllocNodeIdReq.m_req.nodeId;
- ref->errorCode = opAllocNodeIdReq.m_error;
- ref->masterRef = numberToRef(QMGR, cpresident);
- ndbassert(AllocNodeIdRef::SignalLength == 5);
- sendSignal(opAllocNodeIdReq.m_req.senderRef, GSN_ALLOC_NODEID_REF, signal,
- AllocNodeIdRef::SignalLength, JBB);
- return;
- }
- jam();
- AllocNodeIdConf * conf = (AllocNodeIdConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = opAllocNodeIdReq.m_req.senderData;
- conf->nodeId = opAllocNodeIdReq.m_req.nodeId;
- ndbassert(AllocNodeIdConf::SignalLength == 3);
- sendSignal(opAllocNodeIdReq.m_req.senderRef, GSN_ALLOC_NODEID_CONF, signal,
- AllocNodeIdConf::SignalLength, JBB);
-}
-
-void
-Qmgr::execSTOP_REQ(Signal* signal)
-{
- jamEntry();
- c_stopReq = * (StopReq*)signal->getDataPtr();
-
- if (c_stopReq.senderRef)
- {
- jam();
- ndbrequire(NdbNodeBitmask::get(c_stopReq.nodes, getOwnNodeId()));
-
- StopConf *conf = (StopConf*)signal->getDataPtrSend();
- conf->senderData = c_stopReq.senderData;
- conf->nodeState = getOwnNodeId();
- sendSignal(c_stopReq.senderRef,
- GSN_STOP_CONF, signal, StopConf::SignalLength, JBA);
- }
-}
-
-bool
-Qmgr::check_multi_node_shutdown(Signal* signal)
-{
- if (c_stopReq.senderRef &&
- NdbNodeBitmask::get(c_stopReq.nodes, getOwnNodeId()))
- {
- jam();
- if(StopReq::getPerformRestart(c_stopReq.requestInfo))
- {
- jam();
- StartOrd * startOrd = (StartOrd *)&signal->theData[0];
- startOrd->restartInfo = c_stopReq.requestInfo;
- EXECUTE_DIRECT(CMVMI, GSN_START_ORD, signal, 2);
- } else {
- EXECUTE_DIRECT(CMVMI, GSN_STOP_ORD, signal, 1);
- }
- return true;
- }
- return false;
-}
diff --git a/storage/ndb/src/kernel/blocks/qmgr/timer.hpp b/storage/ndb/src/kernel/blocks/qmgr/timer.hpp
deleted file mode 100644
index 5668e788a64..00000000000
--- a/storage/ndb/src/kernel/blocks/qmgr/timer.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-/**
- * @class Timer
- * @brief A timer class that can't be fooled by NTP:ing the system clock to old time
- */
-class Timer {
-public:
- Timer() {
- m_delay = 10;
- };
-
- Timer(NDB_TICKS delay_time) {
- m_delay = delay_time;
- }
-
- /**
- * Set/Get alarm time of timer
- */
- inline void setDelay(NDB_TICKS delay_time) { m_delay = delay_time; }
- inline NDB_TICKS getDelay() { return m_delay; }
-
- /**
- * Start timer
- */
- inline void reset() {
- m_current_time = NdbTick_CurrentMillisecond();
- m_alarm_time = m_current_time + m_delay;
- }
-
- /**
- * Check for alarm
- */
- inline bool check() { return check(NdbTick_CurrentMillisecond()); }
-
- inline bool check(NDB_TICKS check_time) {
- /**
- * Standard alarm check
- */
- if (check_time > m_alarm_time) return true;
-
- /**
- * Time progressing, but it is not alarm time yet
- */
- if (check_time >= m_current_time) return false;
-
- /**
- * Time has moved backwards
- */
- reset();
- return false;
- }
-
-private:
- NDB_TICKS m_current_time;
- NDB_TICKS m_alarm_time;
- NDB_TICKS m_delay;
-};
diff --git a/storage/ndb/src/kernel/blocks/record_types.hpp b/storage/ndb/src/kernel/blocks/record_types.hpp
deleted file mode 100644
index 0c5ff3b5b2b..00000000000
--- a/storage/ndb/src/kernel/blocks/record_types.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (c) 2003, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef KERNEL_RECORDS_HPP
-#define KERNEL_RECORDS_HPP
-
-/**
- * Resource groups
- */
-
-/**
- * Operations for dd
- * PGMAN_PAGE_REQUEST
- * LGMAN_LOG_WAITER
- * DBTUP_PAGE_REQUEST
- */
-#define RG_DISK_OPERATIONS 1
-
-/**
- * Records for dd
- * DBTUP_EXTENT_INFO
- */
-#define RG_DISK_RECORDS 2
-
-/**
- *
- */
-#define RG_RESERVED 0
-#define RG_COUNT 3
-
-/**
- * Record types
- */
-#define RT_PGMAN_PAGE_REQUEST MAKE_TID( 1, RG_DISK_OPERATIONS)
-#define RT_LGMAN_LOG_WAITER MAKE_TID( 2, RG_DISK_OPERATIONS)
-#define RT_DBTUP_PAGE_REQUEST MAKE_TID( 3, RG_DISK_OPERATIONS)
-
-#define RT_DBTUP_EXTENT_INFO MAKE_TID( 4, RG_DISK_RECORDS)
-#define RT_DBDICT_FILE MAKE_TID( 5, RG_DISK_RECORDS)
-#define RT_DBDICT_FILEGROUP MAKE_TID( 6, RG_DISK_RECORDS)
-#define RT_LGMAN_FILE MAKE_TID( 7, RG_DISK_RECORDS)
-#define RT_LGMAN_FILEGROUP MAKE_TID( 8, RG_DISK_RECORDS)
-#define RT_TSMAN_FILE MAKE_TID( 9, RG_DISK_RECORDS)
-#define RT_TSMAN_FILEGROUP MAKE_TID(10, RG_DISK_RECORDS)
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/restore.cpp b/storage/ndb/src/kernel/blocks/restore.cpp
deleted file mode 100644
index c090139c181..00000000000
--- a/storage/ndb/src/kernel/blocks/restore.cpp
+++ /dev/null
@@ -1,1286 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "restore.hpp"
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsCloseReq.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-#include <signaldata/RestoreImpl.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/KeyInfo.hpp>
-#include <signaldata/AttrInfo.hpp>
-#include <signaldata/LqhKey.hpp>
-#include <AttributeHeader.hpp>
-#include <md5_hash.hpp>
-#include <Dblqh.hpp>
-#include <dbtup/Dbtup.hpp>
-#include <KeyDescriptor.hpp>
-
-#define PAGES LCP_RESTORE_BUFFER
-
-Restore::Restore(Block_context& ctx) :
- SimulatedBlock(RESTORE, ctx),
- m_file_list(m_file_pool),
- m_file_hash(m_file_pool)
-{
- BLOCK_CONSTRUCTOR(Restore);
-
- // Add received signals
- addRecSignal(GSN_STTOR, &Restore::execSTTOR);
- addRecSignal(GSN_DUMP_STATE_ORD, &Restore::execDUMP_STATE_ORD);
- addRecSignal(GSN_CONTINUEB, &Restore::execCONTINUEB);
- addRecSignal(GSN_READ_CONFIG_REQ, &Restore::execREAD_CONFIG_REQ, true);
-
- addRecSignal(GSN_RESTORE_LCP_REQ, &Restore::execRESTORE_LCP_REQ);
-
- addRecSignal(GSN_FSOPENREF, &Restore::execFSOPENREF, true);
- addRecSignal(GSN_FSOPENCONF, &Restore::execFSOPENCONF);
- addRecSignal(GSN_FSREADREF, &Restore::execFSREADREF, true);
- addRecSignal(GSN_FSREADCONF, &Restore::execFSREADCONF);
- addRecSignal(GSN_FSCLOSEREF, &Restore::execFSCLOSEREF, true);
- addRecSignal(GSN_FSCLOSECONF, &Restore::execFSCLOSECONF);
-
- addRecSignal(GSN_LQHKEYREF, &Restore::execLQHKEYREF);
- addRecSignal(GSN_LQHKEYCONF, &Restore::execLQHKEYCONF);
-
- ndbrequire(sizeof(Column) == 8);
-}
-
-Restore::~Restore()
-{
-}
-
-BLOCK_FUNCTIONS(Restore)
-
-void
-Restore::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- c_lqh = (Dblqh*)globalData.getBlock(DBLQH);
- c_tup = (Dbtup*)globalData.getBlock(DBTUP);
- sendSTTORRY(signal);
-
- return;
-}//Restore::execNDB_STTOR()
-
-void
-Restore::execREAD_CONFIG_REQ(Signal* signal)
-{
- jamEntry();
- const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
- Uint32 ref = req->senderRef;
- Uint32 senderData = req->senderData;
- ndbrequire(req->noOfParameters == 0);
-
- const ndb_mgm_configuration_iterator * p =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
-#if 0
- Uint32 noBackups = 0, noTables = 0, noAttribs = 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));
-
- 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);
-
- // 2 = no of replicas
- c_fragmentPool.setSize(noBackups * NO_OF_FRAG_PER_NODE * noTables);
-
- 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;
- 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);
-
- c_defaults.m_logBufferSize = szLogBuf;
- c_defaults.m_dataBufferSize = szDataBuf;
- c_defaults.m_minWriteSize = szWrite;
- c_defaults.m_maxWriteSize = szWrite;
-
- { // 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);
- }
-#endif
- m_file_pool.setSize(1);
- Uint32 cnt = 2*MAX_ATTRIBUTES_IN_TABLE;
- cnt += PAGES;
- cnt += List::getSegmentSize()-1;
- cnt /= List::getSegmentSize();
- cnt += 2;
- m_databuffer_pool.setSize(cnt);
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
-void
-Restore::sendSTTORRY(Signal* signal){
- signal->theData[0] = 0;
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 255; // No more start phases from missra
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
-}
-
-void
-Restore::execCONTINUEB(Signal* signal){
- jamEntry();
-
- switch(signal->theData[0]){
- case RestoreContinueB::RESTORE_NEXT:
- {
- FilePtr file_ptr;
- m_file_pool.getPtr(file_ptr, signal->theData[1]);
- restore_next(signal, file_ptr);
- return;
- }
- case RestoreContinueB::READ_FILE:
- {
- FilePtr file_ptr;
- m_file_pool.getPtr(file_ptr, signal->theData[1]);
- read_file(signal, file_ptr);
- return;
- }
- default:
- ndbrequire(false);
- }
-}
-
-void
-Restore::execDUMP_STATE_ORD(Signal* signal){
- jamEntry();
-}
-
-void
-Restore::execRESTORE_LCP_REQ(Signal* signal){
- jamEntry();
-
- Uint32 err= 0;
- RestoreLcpReq* req= (RestoreLcpReq*)signal->getDataPtr();
- Uint32 senderRef= req->senderRef;
- Uint32 senderData= req->senderData;
- do
- {
- FilePtr file_ptr;
- if(!m_file_list.seize(file_ptr))
- {
- err= RestoreLcpRef::NoFileRecord;
- break;
- }
-
- if((err= init_file(req, file_ptr)))
- {
- break;
- }
-
- open_file(signal, file_ptr);
- return;
- } while(0);
-
- RestoreLcpRef* ref= (RestoreLcpRef*)signal->getDataPtrSend();
- ref->senderData= senderData;
- ref->senderRef= reference();
- ref->errorCode = err;
- sendSignal(senderRef, GSN_RESTORE_LCP_REF, signal,
- RestoreLcpRef::SignalLength, JBB);
-}
-
-Uint32
-Restore::init_file(const RestoreLcpReq* req, FilePtr file_ptr)
-{
- new (file_ptr.p) File();
- file_ptr.p->m_sender_ref = req->senderRef;
- file_ptr.p->m_sender_data = req->senderData;
-
- file_ptr.p->m_fd = RNIL;
- file_ptr.p->m_file_type = BackupFormat::LCP_FILE;
- file_ptr.p->m_status = File::FIRST_READ;
-
- file_ptr.p->m_lcp_no = req->lcpNo;
- file_ptr.p->m_table_id = req->tableId;
- file_ptr.p->m_fragment_id = req->fragmentId;
- file_ptr.p->m_table_version = RNIL;
-
- file_ptr.p->m_bytes_left = 0; // Bytes read from FS
- file_ptr.p->m_current_page_ptr_i = RNIL;
- file_ptr.p->m_current_page_pos = 0;
- file_ptr.p->m_current_page_index = 0;
- file_ptr.p->m_current_file_page = 0;
- file_ptr.p->m_outstanding_reads = 0;
- file_ptr.p->m_outstanding_operations = 0;
- file_ptr.p->m_rows_restored = 0;
- LocalDataBuffer<15> pages(m_databuffer_pool, file_ptr.p->m_pages);
- LocalDataBuffer<15> columns(m_databuffer_pool, file_ptr.p->m_columns);
-
- ndbassert(columns.isEmpty());
- columns.release();
-
- ndbassert(pages.isEmpty());
- pages.release();
-
- Uint32 buf_size= PAGES*GLOBAL_PAGE_SIZE;
- Uint32 page_count= (buf_size+GLOBAL_PAGE_SIZE-1)/GLOBAL_PAGE_SIZE;
- if(!pages.seize(page_count))
- {
- return RestoreLcpRef::OutOfDataBuffer;
- }
-
- List::Iterator it;
- for(pages.first(it); !it.isNull(); pages.next(it))
- {
- * it.data = RNIL;
- }
-
- Uint32 err= 0;
- for(pages.first(it); !it.isNull(); pages.next(it))
- {
- Ptr<GlobalPage> page_ptr;
- if(!m_global_page_pool.seize(page_ptr))
- {
- err= RestoreLcpRef::OutOfReadBufferPages;
- break;
- }
- * it.data = page_ptr.i;
- }
-
- if(err)
- {
- for(pages.first(it); !it.isNull(); pages.next(it))
- {
- if(* it.data == RNIL)
- break;
- m_global_page_pool.release(* it.data);
- }
- }
- else
- {
- pages.first(it);
- file_ptr.p->m_current_page_ptr_i = *it.data;
- }
- return err;
-}
-
-void
-Restore::release_file(FilePtr file_ptr)
-{
- LocalDataBuffer<15> pages(m_databuffer_pool, file_ptr.p->m_pages);
- LocalDataBuffer<15> columns(m_databuffer_pool, file_ptr.p->m_columns);
-
- List::Iterator it;
- for(pages.first(it); !it.isNull(); pages.next(it))
- {
- if(* it.data == RNIL)
- continue;
- m_global_page_pool.release(* it.data);
- }
-
- ndbout_c("RESTORE table: %d %lld rows applied",
- file_ptr.p->m_table_id,
- file_ptr.p->m_rows_restored);
-
- columns.release();
- pages.release();
- m_file_list.release(file_ptr);
-}
-
-void
-Restore::open_file(Signal* signal, FilePtr file_ptr)
-{
- FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
- req->userReference = reference();
- req->fileFlags = FsOpenReq::OM_READONLY ;
- req->userPointer = file_ptr.i;
-
- FsOpenReq::setVersion(req->fileNumber, 5);
- FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
- FsOpenReq::v5_setLcpNo(req->fileNumber, file_ptr.p->m_lcp_no);
- FsOpenReq::v5_setTableId(req->fileNumber, file_ptr.p->m_table_id);
- FsOpenReq::v5_setFragmentId(req->fileNumber, file_ptr.p->m_fragment_id);
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
-}
-
-void
-Restore::execFSOPENREF(Signal* signal)
-{
- FsRef* ref= (FsRef*)signal->getDataPtr();
- FilePtr file_ptr;
- jamEntry();
- m_file_pool.getPtr(file_ptr, ref->userPointer);
-
- Uint32 errCode= ref->errorCode;
- Uint32 osError= ref->osErrorCode;
-
- RestoreLcpRef* rep= (RestoreLcpRef*)signal->getDataPtrSend();
- rep->senderData= file_ptr.p->m_sender_data;
- rep->errorCode = errCode;
- rep->extra[0] = osError;
- sendSignal(file_ptr.p->m_sender_ref,
- GSN_RESTORE_LCP_REF, signal, RestoreLcpRef::SignalLength+1, JBB);
-
- release_file(file_ptr);
-}
-
-void
-Restore::execFSOPENCONF(Signal* signal)
-{
- jamEntry();
- FilePtr file_ptr;
- FsConf* conf= (FsConf*)signal->getDataPtr();
- m_file_pool.getPtr(file_ptr, conf->userPointer);
-
- file_ptr.p->m_fd = conf->filePointer;
-
- /**
- * Start thread's
- */
-
- file_ptr.p->m_status |= File::FILE_THREAD_RUNNING;
- signal->theData[0] = RestoreContinueB::READ_FILE;
- signal->theData[1] = file_ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-
- file_ptr.p->m_status |= File::RESTORE_THREAD_RUNNING;
- signal->theData[0] = RestoreContinueB::RESTORE_NEXT;
- signal->theData[1] = file_ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Restore::restore_next(Signal* signal, FilePtr file_ptr)
-{
- Uint32 *data, len= 0;
- Uint32 status = file_ptr.p->m_status;
- Uint32 page_count = file_ptr.p->m_pages.getSize();
- do
- {
- Uint32 left= file_ptr.p->m_bytes_left;
- if(left < 8)
- {
- /**
- * Not enought bytes to read header
- */
- break;
- }
- Ptr<GlobalPage> page_ptr, next_page_ptr = { 0, 0 };
- m_global_page_pool.getPtr(page_ptr, file_ptr.p->m_current_page_ptr_i);
- List::Iterator it;
-
- Uint32 pos= file_ptr.p->m_current_page_pos;
- if(status & File::READING_RECORDS)
- {
- /**
- * We are reading records
- */
- len= ntohl(* (page_ptr.p->data + pos)) + 1;
- }
- else
- {
- /**
- * Section length is in 2 word
- */
- if(pos + 1 == GLOBAL_PAGE_SIZE_WORDS)
- {
- /**
- * But that's stored on next page...
- * and since we have atleast 8 bytes left in buffer
- * we can be sure that that's in buffer
- */
- LocalDataBuffer<15> pages(m_databuffer_pool, file_ptr.p->m_pages);
- Uint32 next_page = file_ptr.p->m_current_page_index + 1;
- pages.position(it, next_page % page_count);
- m_global_page_pool.getPtr(next_page_ptr, * it.data);
- len= ntohl(* next_page_ptr.p->data);
- }
- else
- {
- len= ntohl(* (page_ptr.p->data + pos + 1));
- }
- }
-
- if(file_ptr.p->m_status & File::FIRST_READ)
- {
- len= 3;
- file_ptr.p->m_status &= ~(Uint32)File::FIRST_READ;
- }
-
- if(4 * len > left)
- {
- /**
- * Not enought bytes to read "record"
- */
- ndbout_c("records: %d len: %x left: %d",
- status & File::READING_RECORDS, 4*len, left);
-
- if (unlikely((status & File:: FILE_THREAD_RUNNING) == 0))
- {
- ndbrequire(false);
- }
- len= 0;
- break;
- }
-
- /**
- * Entire record is in buffer
- */
-
- if(pos + len >= GLOBAL_PAGE_SIZE_WORDS)
- {
- /**
- * But it's split over pages
- */
- if(next_page_ptr.p == 0)
- {
- LocalDataBuffer<15> pages(m_databuffer_pool, file_ptr.p->m_pages);
- Uint32 next_page = file_ptr.p->m_current_page_index + 1;
- pages.position(it, next_page % page_count);
- m_global_page_pool.getPtr(next_page_ptr, * it.data);
- }
- file_ptr.p->m_current_page_ptr_i = next_page_ptr.i;
- file_ptr.p->m_current_page_pos = (pos + len) - GLOBAL_PAGE_SIZE_WORDS;
- file_ptr.p->m_current_page_index =
- (file_ptr.p->m_current_page_index + 1) % page_count;
-
- Uint32 first = (GLOBAL_PAGE_SIZE_WORDS - pos);
- memcpy(page_ptr.p, page_ptr.p->data+pos, 4 * first);
- memcpy(page_ptr.p->data+first, next_page_ptr.p, 4 * (len - first));
- data= page_ptr.p->data;
- }
- else
- {
- file_ptr.p->m_current_page_pos = pos + len;
- data= page_ptr.p->data+pos;
- }
-
- file_ptr.p->m_bytes_left -= 4*len;
-
- if(status & File::READING_RECORDS)
- {
- if(len == 1)
- {
- file_ptr.p->m_status = status & ~(Uint32)File::READING_RECORDS;
- }
- else
- {
- parse_record(signal, file_ptr, data, len);
- }
- }
- else
- {
- switch(ntohl(* data)){
- case BackupFormat::FILE_HEADER:
- parse_file_header(signal, file_ptr, data-3, len+3);
- break;
- case BackupFormat::FRAGMENT_HEADER:
- file_ptr.p->m_status = status | File::READING_RECORDS;
- parse_fragment_header(signal, file_ptr, data, len);
- break;
- case BackupFormat::FRAGMENT_FOOTER:
- parse_fragment_footer(signal, file_ptr, data, len);
- break;
- case BackupFormat::TABLE_LIST:
- parse_table_list(signal, file_ptr, data, len);
- break;
- case BackupFormat::TABLE_DESCRIPTION:
- parse_table_description(signal, file_ptr, data, len);
- break;
- case BackupFormat::GCP_ENTRY:
- parse_gcp_entry(signal, file_ptr, data, len);
- break;
- case BackupFormat::EMPTY_ENTRY:
- // skip
- break;
- case 0x4e444242: // 'NDBB'
- if (check_file_version(signal, ntohl(* (data+2))) == 0)
- {
- break;
- }
- default:
- parse_error(signal, file_ptr, __LINE__, ntohl(* data));
- }
- }
- } while(0);
-
- if(file_ptr.p->m_bytes_left == 0 && status & File::FILE_EOF)
- {
- file_ptr.p->m_status &= ~(Uint32)File::RESTORE_THREAD_RUNNING;
- /**
- * File is finished...
- */
- close_file(signal, file_ptr);
- return;
- }
-
- signal->theData[0] = RestoreContinueB::RESTORE_NEXT;
- signal->theData[1] = file_ptr.i;
-
- if(len)
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- else
- sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
-}
-
-void
-Restore::read_file(Signal* signal, FilePtr file_ptr)
-{
- Uint32 left= file_ptr.p->m_bytes_left;
- Uint32 page_count = file_ptr.p->m_pages.getSize();
- Uint32 free= GLOBAL_PAGE_SIZE * page_count - left;
- Uint32 read_count= free/GLOBAL_PAGE_SIZE;
-
- if(read_count <= file_ptr.p->m_outstanding_reads)
- {
- signal->theData[0] = RestoreContinueB::READ_FILE;
- signal->theData[1] = file_ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- }
-
- read_count -= file_ptr.p->m_outstanding_reads;
- Uint32 curr_page= file_ptr.p->m_current_page_index;
- LocalDataBuffer<15> pages(m_databuffer_pool, file_ptr.p->m_pages);
-
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = file_ptr.p->m_fd;
- req->userReference = reference();
- req->userPointer = file_ptr.i;
- req->numberOfPages = 1;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatGlobalPage);
- FsReadWriteReq::setPartialReadFlag(req->operationFlag, 1);
-
- Uint32 start= (curr_page + page_count - read_count) % page_count;
-
- List::Iterator it;
- pages.position(it, start);
- do
- {
- file_ptr.p->m_outstanding_reads++;
- req->varIndex = file_ptr.p->m_current_file_page++;
- req->data.pageData[0] = *it.data;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBB);
-
- start++;
- if(start == page_count)
- {
- start= 0;
- pages.position(it, start);
- }
- else
- {
- pages.next(it);
- }
- } while(start != curr_page);
-}
-
-void
-Restore::execFSREADREF(Signal * signal)
-{
- jamEntry();
- SimulatedBlock::execFSREADREF(signal);
- ndbrequire(false);
-}
-
-void
-Restore::execFSREADCONF(Signal * signal)
-{
- jamEntry();
- FilePtr file_ptr;
- FsConf* conf= (FsConf*)signal->getDataPtr();
- m_file_pool.getPtr(file_ptr, conf->userPointer);
-
- file_ptr.p->m_bytes_left += conf->bytes_read;
-
- ndbassert(file_ptr.p->m_outstanding_reads);
- file_ptr.p->m_outstanding_reads--;
-
- if(file_ptr.p->m_outstanding_reads == 0)
- {
- ndbassert(conf->bytes_read <= GLOBAL_PAGE_SIZE);
- if(conf->bytes_read == GLOBAL_PAGE_SIZE)
- {
- read_file(signal, file_ptr);
- }
- else
- {
- file_ptr.p->m_status |= File::FILE_EOF;
- file_ptr.p->m_status &= ~(Uint32)File::FILE_THREAD_RUNNING;
- }
- }
-}
-
-void
-Restore::close_file(Signal* signal, FilePtr file_ptr)
-{
- FsCloseReq * req = (FsCloseReq *)signal->getDataPtrSend();
- req->filePointer = file_ptr.p->m_fd;
- req->userPointer = file_ptr.i;
- req->userReference = reference();
- req->fileFlag = 0;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
-}
-
-void
-Restore::execFSCLOSEREF(Signal * signal)
-{
- jamEntry();
- SimulatedBlock::execFSCLOSEREF(signal);
- ndbrequire(false);
-}
-
-void
-Restore::execFSCLOSECONF(Signal * signal)
-{
- jamEntry();
- FilePtr file_ptr;
- FsConf* conf= (FsConf*)signal->getDataPtr();
- m_file_pool.getPtr(file_ptr, conf->userPointer);
-
- file_ptr.p->m_fd = RNIL;
-
- if(file_ptr.p->m_outstanding_operations == 0)
- {
- RestoreLcpConf* rep= (RestoreLcpConf*)signal->getDataPtrSend();
- rep->senderData= file_ptr.p->m_sender_data;
- sendSignal(file_ptr.p->m_sender_ref,
- GSN_RESTORE_LCP_CONF, signal,
- RestoreLcpConf::SignalLength, JBB);
- release_file(file_ptr);
- }
-}
-
-void
-Restore::parse_file_header(Signal* signal,
- FilePtr file_ptr,
- const Uint32* data, Uint32 len)
-{
- const BackupFormat::FileHeader* fh= (BackupFormat::FileHeader*)data;
-
- if(memcmp(fh->Magic, "NDBBCKUP", 8) != 0)
- {
- parse_error(signal, file_ptr, __LINE__, *data);
- return;
- }
-
- if (check_file_version(signal, ntohl(fh->NdbVersion)))
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->NdbVersion));
- return;
- }
- ndbassert(ntohl(fh->SectionType) == BackupFormat::FILE_HEADER);
-
- if(ntohl(fh->SectionLength) != len-3)
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->SectionLength));
- return;
- }
-
- if(ntohl(fh->FileType) != BackupFormat::LCP_FILE)
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->FileType));
- return;
- }
-
- if(fh->ByteOrder != 0x12345678)
- {
- parse_error(signal, file_ptr, __LINE__, fh->ByteOrder);
- return;
- }
-}
-
-void
-Restore::parse_table_list(Signal* signal, FilePtr file_ptr,
- const Uint32 *data, Uint32 len)
-{
- const BackupFormat::CtlFile::TableList* fh=
- (BackupFormat::CtlFile::TableList*)data;
-
- if(ntohl(fh->TableIds[0]) != file_ptr.p->m_table_id)
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->TableIds[0]));
- return;
- }
-}
-
-void
-Restore::parse_table_description(Signal* signal, FilePtr file_ptr,
- const Uint32 *data, Uint32 len)
-{
- bool lcp = file_ptr.p->is_lcp();
- Uint32 disk= 0;
- const BackupFormat::CtlFile::TableDescription* fh=
- (BackupFormat::CtlFile::TableDescription*)data;
-
- LocalDataBuffer<15> columns(m_databuffer_pool, file_ptr.p->m_columns);
-
- SimplePropertiesLinearReader it(fh->DictTabInfo, len);
- it.first();
-
- DictTabInfo::Table tmpTab; tmpTab.init();
- SimpleProperties::UnpackStatus stat;
- stat = SimpleProperties::unpack(it, &tmpTab,
- DictTabInfo::TableMapping,
- DictTabInfo::TableMappingSize,
- true, true);
- ndbrequire(stat == SimpleProperties::Break);
-
- if(tmpTab.TableId != file_ptr.p->m_table_id)
- {
- parse_error(signal, file_ptr, __LINE__, tmpTab.TableId);
- return;
- }
-
- Column c;
- Uint32 colstore[sizeof(Column)/sizeof(Uint32)];
-
- for(Uint32 i = 0; i<tmpTab.NoOfAttributes; i++) {
- jam();
- DictTabInfo::Attribute tmp; tmp.init();
- stat = SimpleProperties::unpack(it, &tmp,
- DictTabInfo::AttributeMapping,
- DictTabInfo::AttributeMappingSize,
- true, true);
-
- ndbrequire(stat == SimpleProperties::Break);
- it.next(); // Move Past EndOfAttribute
-
- const Uint32 arr = tmp.AttributeArraySize;
- const Uint32 sz = 1 << tmp.AttributeSize;
- const Uint32 sz32 = (sz * arr + 31) >> 5;
- const bool varsize = tmp.AttributeArrayType != NDB_ARRAYTYPE_FIXED;
-
- c.m_id = tmp.AttributeId;
- c.m_size = sz32;
- c.m_flags = (tmp.AttributeKeyFlag ? Column::COL_KEY : 0);
- c.m_flags |= (tmp.AttributeStorageType == NDB_STORAGETYPE_DISK ?
- Column::COL_DISK : 0);
-
- if(lcp && (c.m_flags & Column::COL_DISK))
- {
- /**
- * Restore does not currently handle disk attributes
- * which is fine as restore LCP shouldn't
- */
- disk++;
- continue;
- }
-
- if(!tmp.AttributeNullableFlag && !varsize)
- {
- }
- else if (true) // null mask dropped in 5.1
- {
- c.m_flags |= (varsize ? Column::COL_VAR : 0);
- c.m_flags |= (tmp.AttributeNullableFlag ? Column::COL_NULL : 0);
- }
-
- memcpy(colstore, &c, sizeof(Column));
- if(!columns.append(colstore, sizeof(Column)/sizeof(Uint32)))
- {
- parse_error(signal, file_ptr, __LINE__, i);
- return;
- }
- }
-
- if(lcp)
- {
- if (disk)
- {
- c.m_id = AttributeHeader::DISK_REF;
- c.m_size = 2;
- c.m_flags = 0;
- memcpy(colstore, &c, sizeof(Column));
- if(!columns.append(colstore, sizeof(Column)/sizeof(Uint32)))
- {
- parse_error(signal, file_ptr, __LINE__, 0);
- return;
- }
- }
-
- {
- c.m_id = AttributeHeader::ROWID;
- c.m_size = 2;
- c.m_flags = 0;
- memcpy(colstore, &c, sizeof(Column));
- if(!columns.append(colstore, sizeof(Column)/sizeof(Uint32)))
- {
- parse_error(signal, file_ptr, __LINE__, 0);
- return;
- }
- }
-
- if (tmpTab.RowGCIFlag)
- {
- c.m_id = AttributeHeader::ROW_GCI;
- c.m_size = 2;
- c.m_flags = 0;
- memcpy(colstore, &c, sizeof(Column));
- if(!columns.append(colstore, sizeof(Column)/sizeof(Uint32)))
- {
- parse_error(signal, file_ptr, __LINE__, 0);
- return;
- }
- }
- }
-
- file_ptr.p->m_table_version = tmpTab.TableVersion;
-}
-
-void
-Restore::parse_fragment_header(Signal* signal, FilePtr file_ptr,
- const Uint32 *data, Uint32 len)
-{
- const BackupFormat::DataFile::FragmentHeader* fh=
- (BackupFormat::DataFile::FragmentHeader*)data;
- if(ntohl(fh->TableId) != file_ptr.p->m_table_id)
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->TableId));
- return;
- }
-
- if(ntohl(fh->ChecksumType) != 0)
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->SectionLength));
- return;
- }
-
- file_ptr.p->m_fragment_id = ntohl(fh->FragmentNo);
-
- if(file_ptr.p->is_lcp())
- {
- /**
- * Temporary reset DBTUP's #disk attributes on table
- */
- c_tup->start_restore_lcp(file_ptr.p->m_table_id,
- file_ptr.p->m_fragment_id);
- }
-}
-
-void
-Restore::parse_record(Signal* signal, FilePtr file_ptr,
- const Uint32 *data, Uint32 len)
-{
- List::Iterator it;
- LocalDataBuffer<15> columns(m_databuffer_pool, file_ptr.p->m_columns);
-
- Uint32 * const key_start = signal->getDataPtrSend()+24;
- Uint32 * const attr_start = key_start + MAX_KEY_SIZE_IN_WORDS;
-
- data += 1;
- const Uint32* const dataStart = data;
-
- Uint32 *keyData = key_start;
- Uint32 *attrData = attr_start;
- union {
- Column c;
- Uint32 _align[sizeof(Column)/sizeof(Uint32)];
- };
- bool disk = false;
- bool rowid = false;
- bool gci = false;
- Uint32 tableId = file_ptr.p->m_table_id;
-
- Uint64 gci_val;
- Local_key rowid_val;
- columns.first(it);
- while(!it.isNull())
- {
- _align[0] = *it.data; ndbrequire(columns.next(it));
- _align[1] = *it.data; columns.next(it);
-
- if (c.m_id == AttributeHeader::ROWID)
- {
- rowid_val.m_page_no = data[0];
- rowid_val.m_page_idx = data[1];
- data += 2;
- rowid = true;
- continue;
- }
-
- if (c.m_id == AttributeHeader::ROW_GCI)
- {
- memcpy(&gci_val, data, 8);
- data += 2;
- gci = true;
- continue;
- }
-
- if (! (c.m_flags & (Column::COL_VAR | Column::COL_NULL)))
- {
- ndbrequire(data < dataStart + len);
-
- if(c.m_flags & Column::COL_KEY)
- {
- memcpy(keyData, data, 4*c.m_size);
- keyData += c.m_size;
- }
-
- AttributeHeader::init(attrData++, c.m_id, c.m_size << 2);
- memcpy(attrData, data, 4*c.m_size);
- attrData += c.m_size;
- data += c.m_size;
- }
-
- if(c.m_flags & Column::COL_DISK)
- disk= true;
- }
-
- // second part is data driven
- while (data + 2 < dataStart + len) {
- Uint32 sz= ntohl(*data); data++;
- Uint32 id= ntohl(*data); data++; // column_no
-
- ndbrequire(columns.position(it, 2 * id));
-
- _align[0] = *it.data; ndbrequire(columns.next(it));
- _align[1] = *it.data;
-
- Uint32 sz32 = (sz + 3) >> 2;
- ndbassert(c.m_flags & (Column::COL_VAR | Column::COL_NULL));
- if (c.m_flags & Column::COL_KEY)
- {
- memcpy(keyData, data, 4 * sz32);
- keyData += sz32;
- }
-
- AttributeHeader::init(attrData++, c.m_id, sz);
- memcpy(attrData, data, sz);
-
- attrData += sz32;
- data += sz32;
- }
-
- ndbrequire(data == dataStart + len - 1);
-
- ndbrequire(disk == false); // Not supported...
- ndbrequire(rowid == true);
- Uint32 keyLen = keyData - key_start;
- Uint32 attrLen = attrData - attr_start;
- LqhKeyReq * req = (LqhKeyReq *)signal->getDataPtrSend();
-
- const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tableId);
- if (desc->noOfKeyAttr != desc->noOfVarKeys)
- {
- reorder_key(desc, key_start, keyLen);
- }
-
- Uint32 hashValue;
- if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
- hashValue = calulate_hash(tableId, key_start);
- else
- hashValue = md5_hash((Uint64*)key_start, keyLen);
-
- Uint32 tmp= 0;
- LqhKeyReq::setAttrLen(tmp, attrLen);
- req->attrLen = tmp;
-
- tmp= 0;
- LqhKeyReq::setKeyLen(tmp, keyLen);
- LqhKeyReq::setLastReplicaNo(tmp, 0);
- /* ---------------------------------------------------------------------- */
- // Indicate Application Reference is present in bit 15
- /* ---------------------------------------------------------------------- */
- LqhKeyReq::setApplicationAddressFlag(tmp, 0);
- LqhKeyReq::setDirtyFlag(tmp, 1);
- LqhKeyReq::setSimpleFlag(tmp, 1);
- LqhKeyReq::setOperation(tmp, ZINSERT);
- LqhKeyReq::setSameClientAndTcFlag(tmp, 0);
- LqhKeyReq::setAIInLqhKeyReq(tmp, 0);
- LqhKeyReq::setNoDiskFlag(tmp, disk ? 0 : 1);
- LqhKeyReq::setRowidFlag(tmp, 1);
- LqhKeyReq::setGCIFlag(tmp, gci);
- req->clientConnectPtr = file_ptr.i;
- req->hashValue = hashValue;
- req->requestInfo = tmp;
- req->tcBlockref = reference();
- req->savePointId = 0;
- req->tableSchemaVersion = file_ptr.p->m_table_id +
- (file_ptr.p->m_table_version << 16);
- req->fragmentData = file_ptr.p->m_fragment_id;
- req->transId1 = 0;
- req->transId2 = 0;
- req->scanInfo = 0;
- memcpy(req->variableData, key_start, 16);
- Uint32 pos = keyLen > 4 ? 4 : keyLen;
- req->variableData[pos++] = rowid_val.m_page_no;
- req->variableData[pos++] = rowid_val.m_page_idx;
- if (gci)
- req->variableData[pos++] = (Uint32)gci_val;
- file_ptr.p->m_outstanding_operations++;
- EXECUTE_DIRECT(DBLQH, GSN_LQHKEYREQ, signal,
- LqhKeyReq::FixedSignalLength+pos);
-
- if(keyLen > 4)
- {
- c_lqh->receive_keyinfo(signal,
- key_start + 4,
- keyLen - 4);
- }
-
- c_lqh->receive_attrinfo(signal, attr_start, attrLen);
-}
-
-void
-Restore::reorder_key(const KeyDescriptor* desc,
- Uint32 *data, Uint32 len)
-{
- Uint32 i;
- Uint32 *var= data;
- Uint32 Tmp[MAX_KEY_SIZE_IN_WORDS];
- for(i = 0; i<desc->noOfKeyAttr; i++)
- {
- Uint32 attr = desc->keyAttr[i].attributeDescriptor;
- switch(AttributeDescriptor::getArrayType(attr)){
- case NDB_ARRAYTYPE_FIXED:
- var += AttributeDescriptor::getSizeInWords(attr);
- }
- }
-
- Uint32 *dst = Tmp;
- Uint32 *src = data;
- for(i = 0; i<desc->noOfKeyAttr; i++)
- {
- Uint32 sz;
- Uint32 attr = desc->keyAttr[i].attributeDescriptor;
- switch(AttributeDescriptor::getArrayType(attr)){
- case NDB_ARRAYTYPE_FIXED:
- sz = AttributeDescriptor::getSizeInWords(attr);
- memcpy(dst, src, 4 * sz);
- src += sz;
- break;
- case NDB_ARRAYTYPE_SHORT_VAR:
- sz = (1 + ((char*)var)[0] + 3) >> 2;
- memcpy(dst, var, 4 * sz);
- var += sz;
- break;
- case NDB_ARRAYTYPE_MEDIUM_VAR:
- sz = (2 + ((char*)var)[0] + 256*((char*)var)[1] + 3) >> 2;
- memcpy(dst, var, 4 * sz);
- var += sz;
- break;
- default:
- ndbrequire(false);
- sz = 0;
- }
- dst += sz;
- }
- ndbassert((Uint32) (dst - Tmp) == len);
- memcpy(data, Tmp, 4*len);
-}
-
-Uint32
-Restore::calulate_hash(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);
-}
-
-void
-Restore::execLQHKEYREF(Signal* signal)
-{
- FilePtr file_ptr;
- LqhKeyRef* ref = (LqhKeyRef*)signal->getDataPtr();
- m_file_pool.getPtr(file_ptr, ref->connectPtr);
-
- char buf[255], name[100];
- BaseString::snprintf(name, sizeof(name), "%u/T%dF%d",
- file_ptr.p->m_lcp_no,
- file_ptr.p->m_table_id,
- file_ptr.p->m_fragment_id);
-
- BaseString::snprintf(buf, sizeof(buf),
- "Error %d during restore of %s",
- ref->errorCode, name);
-
- progError(__LINE__, NDBD_EXIT_INVALID_LCP_FILE, buf);
- ndbrequire(false);
-}
-
-void
-Restore::execLQHKEYCONF(Signal* signal)
-{
- FilePtr file_ptr;
- LqhKeyConf * conf = (LqhKeyConf *)signal->getDataPtr();
- m_file_pool.getPtr(file_ptr, conf->connectPtr);
-
- ndbassert(file_ptr.p->m_outstanding_operations);
- file_ptr.p->m_outstanding_operations--;
- file_ptr.p->m_rows_restored++;
- if(file_ptr.p->m_outstanding_operations == 0 && file_ptr.p->m_fd == RNIL)
- {
- RestoreLcpConf* rep= (RestoreLcpConf*)signal->getDataPtrSend();
- rep->senderData= file_ptr.p->m_sender_data;
- sendSignal(file_ptr.p->m_sender_ref,
- GSN_RESTORE_LCP_CONF, signal,
- RestoreLcpConf::SignalLength, JBB);
- release_file(file_ptr);
- }
-}
-
-void
-Restore::parse_fragment_footer(Signal* signal, FilePtr file_ptr,
- const Uint32 *data, Uint32 len)
-{
- const BackupFormat::DataFile::FragmentFooter* fh=
- (BackupFormat::DataFile::FragmentFooter*)data;
- if(ntohl(fh->TableId) != file_ptr.p->m_table_id)
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->TableId));
- return;
- }
-
- if(ntohl(fh->Checksum) != 0)
- {
- parse_error(signal, file_ptr, __LINE__, ntohl(fh->SectionLength));
- return;
- }
-
- if(file_ptr.p->is_lcp())
- {
- /**
- * Temporary reset DBTUP's #disk attributes on table
- */
- c_tup->complete_restore_lcp(file_ptr.p->m_table_id,
- file_ptr.p->m_fragment_id);
- }
-
- file_ptr.p->m_fragment_id = RNIL;
-}
-
-void
-Restore::parse_gcp_entry(Signal* signal, FilePtr file_ptr,
- const Uint32 *data, Uint32 len)
-{
-
-}
-
-void
-Restore::parse_error(Signal* signal,
- FilePtr file_ptr, Uint32 line, Uint32 extra)
-{
- char buf[255], name[100];
- BaseString::snprintf(name, sizeof(name), "%u/T%dF%d",
- file_ptr.p->m_lcp_no,
- file_ptr.p->m_table_id,
- file_ptr.p->m_fragment_id);
-
- BaseString::snprintf(buf, sizeof(buf),
- "Parse error in file: %s, extra: %d",
- name, extra);
-
- progError(line, NDBD_EXIT_INVALID_LCP_FILE, buf);
- ndbrequire(false);
-}
-
-NdbOut&
-operator << (NdbOut& ndbout, const Restore::Column& col)
-{
- ndbout << "[ Col: id: " << col.m_id
- << " size: " << col.m_size
- << " key: " << (Uint32)(col.m_flags & Restore::Column::COL_KEY)
- << " variable: " << (Uint32)(col.m_flags & Restore::Column::COL_VAR)
- << " null: " << (Uint32)(col.m_flags & Restore::Column::COL_NULL)
- << " disk: " << (Uint32)(col.m_flags & Restore::Column::COL_DISK)
- << "]";
-
- return ndbout;
-}
-
-int
-Restore::check_file_version(Signal* signal, Uint32 file_version)
-{
- if (file_version < MAKE_VERSION(5,1,6))
- {
- char buf[255];
- char verbuf[255];
- ndbGetVersionString(file_version, 0, verbuf, sizeof(verbuf));
- BaseString::snprintf(buf, sizeof(buf),
- "Unsupported version of LCP files found on disk, "
- " found: %s", verbuf);
-
- progError(__LINE__,
- NDBD_EXIT_SR_RESTARTCONFLICT,
- buf);
- return -1;
- }
- return 0;
-}
diff --git a/storage/ndb/src/kernel/blocks/restore.hpp b/storage/ndb/src/kernel/blocks/restore.hpp
deleted file mode 100644
index eadb8712bd2..00000000000
--- a/storage/ndb/src/kernel/blocks/restore.hpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef Restore_H
-#define Restore_H
-
-#include <SimulatedBlock.hpp>
-
-#include <SLList.hpp>
-#include <DLList.hpp>
-#include <KeyTable.hpp>
-#include <DLHashTable.hpp>
-#include <DataBuffer.hpp>
-#include <NodeBitmask.hpp>
-#include <backup/BackupFormat.hpp>
-
-class Restore : public SimulatedBlock
-{
-public:
- Restore(Block_context& ctx);
- virtual ~Restore();
- BLOCK_DEFINES(Restore);
-
-protected:
-
- void execSTTOR(Signal* signal);
- void sendSTTORRY(Signal*);
- void execREAD_CONFIG_REQ(Signal*);
- void execDUMP_STATE_ORD(Signal* signal);
- void execCONTINUEB(Signal* signal);
- void execRESTORE_LCP_REQ(Signal* signal);
-
- void execFSOPENREF(Signal*);
- void execFSOPENCONF(Signal*);
- void execFSREADREF(Signal*);
- void execFSREADCONF(Signal*);
- void execFSCLOSEREF(Signal*);
- void execFSCLOSECONF(Signal*);
-
- void execLQHKEYREF(Signal*);
- void execLQHKEYCONF(Signal*);
-
- typedef DataBuffer<15> List;
-
-public:
- struct Column
- {
- Uint16 m_id;
- Uint16 m_size;
- Uint16 m_unused;
- Uint16 m_flags;
-
- enum Flags
- {
- COL_KEY = 0x1,
- COL_VAR = 0x2,
- COL_DISK = 0x4,
- COL_NULL = 0x8
- };
- };
-private:
-
- struct File; // CC
- friend struct File;
-
- struct File
- {
- File() {}
- Uint32 m_sender_ref;
- Uint32 m_sender_data;
-
- Uint32 m_fd; // File pointer
- Uint32 m_file_type; // File type
- Uint32 m_status;
-
- enum StatusFlags
- {
- FILE_EOF = 1,
- FILE_THREAD_RUNNING = 2,
- RESTORE_THREAD_RUNNING = 4,
- FIRST_READ = 8,
- READING_RECORDS = 16
- };
-
- Uint32 m_table_id;
- Uint32 m_table_version;
- Uint32 m_fragment_id;
- List::Head m_columns;
-
- Uint32 m_current_page_ptr_i;
- Uint32 m_current_page_pos;
- Uint32 m_bytes_left; // Bytes read from FS
- Uint32 m_current_file_page; // Where in file
- Uint32 m_outstanding_reads; //
- Uint32 m_outstanding_operations;
- Uint64 m_rows_restored;
-
- Uint32 m_current_page_index; // Where in page list are we
- List::Head m_pages;
-
- Uint32 nextHash;
- Uint32 prevHash;
- Uint32 nextList;
- Uint32 prevList;
- Uint32 nextPool;
- Uint32 m_lcp_no;
-
- bool is_lcp() const { return m_file_type == BackupFormat::LCP_FILE;}
- };
- typedef Ptr<File> FilePtr;
-
- Uint32 init_file(const struct RestoreLcpReq*, FilePtr);
- void release_file(FilePtr);
-
- void open_file(Signal*, FilePtr);
- void read_file(Signal*, FilePtr);
- void restore_next(Signal*, FilePtr);
- void parse_file_header(Signal*, FilePtr, const Uint32*, Uint32 len);
- void parse_table_list(Signal*, FilePtr, const Uint32*, Uint32 len);
- void parse_table_description(Signal*, FilePtr, const Uint32*, Uint32 len);
- void parse_fragment_header(Signal*, FilePtr, const Uint32*, Uint32 len);
- void parse_record(Signal*, FilePtr, const Uint32*, Uint32 len);
- void parse_fragment_footer(Signal*, FilePtr, const Uint32*, Uint32 len);
- void parse_gcp_entry(Signal*, FilePtr, const Uint32*, Uint32 len);
- void close_file(Signal*, FilePtr);
-
- void reorder_key(const struct KeyDescriptor*, Uint32* data, Uint32 len);
- Uint32 calulate_hash(Uint32 tableId, const Uint32 *src);
-
- void parse_error(Signal*, FilePtr, Uint32 line, Uint32 extra);
- int check_file_version(Signal*, Uint32 file_version);
-public:
-
-private:
- class Dblqh* c_lqh;
- class Dbtup* c_tup;
- DLList<File> m_file_list;
- KeyTable<File> m_file_hash;
- ArrayPool<File> m_file_pool;
-
- List::DataBufferPool m_databuffer_pool;
-};
-
-NdbOut& operator << (NdbOut&, const Restore::Column&);
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp
deleted file mode 100644
index 40d0bb16406..00000000000
--- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp
+++ /dev/null
@@ -1,5202 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <my_config.h>
-#include "Suma.hpp"
-
-#include <ndb_version.h>
-
-#include <NdbTCP.h>
-#include <Bitmask.hpp>
-#include <SimpleProperties.hpp>
-
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-
-#include <signaldata/ListTables.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/GetTableId.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <signaldata/ScanFrag.hpp>
-#include <signaldata/TransIdAI.hpp>
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/AlterTrig.hpp>
-#include <signaldata/DropTrig.hpp>
-#include <signaldata/FireTrigOrd.hpp>
-#include <signaldata/TrigAttrInfo.hpp>
-#include <signaldata/CheckNodeGroups.hpp>
-#include <signaldata/GCPSave.hpp>
-#include <signaldata/CreateTab.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/AlterTable.hpp>
-#include <signaldata/AlterTab.hpp>
-#include <signaldata/DihFragCount.hpp>
-#include <signaldata/SystemError.hpp>
-
-#include <ndbapi/NdbDictionary.hpp>
-
-#include <DebuggerNames.hpp>
-#include <../dbtup/Dbtup.hpp>
-#include <../dbdih/Dbdih.hpp>
-
-//#define HANDOVER_DEBUG
-//#define NODEFAIL_DEBUG
-//#define NODEFAIL_DEBUG2
-//#define DEBUG_SUMA_SEQUENCE
-//#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:
- * SUMA crashes if an index is created at the same time as
- * global replication. Very easy to reproduce using testIndex.
- * Note: This only happens occasionally, but is quite easy to reprod.
- */
-
-Uint32 g_subPtrI = RNIL;
-static const Uint32 SUMA_SEQUENCE = 0xBABEBABE;
-
-static const Uint32 MAX_CONCURRENT_GCP = 2;
-
-/**************************************************************
- *
- * Start of suma
- *
- */
-
-#define PRINT_ONLY 0
-
-void
-Suma::getNodeGroupMembers(Signal* signal)
-{
- jam();
- DBUG_ENTER("Suma::getNodeGroupMembers");
- /**
- * Ask DIH for nodeGroupMembers
- */
- 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_nodeGroup = sd->output;
- c_nodes_in_nodegroup_mask.assign(sd->mask);
- c_noNodesInGroup = c_nodes_in_nodegroup_mask.count();
- Uint32 i, pos= 0;
-
- for (i = 0; i < MAX_NDB_NODES; i++) {
- if (sd->mask.get(i))
- {
- c_nodesInGroup[pos++] = i;
- }
- }
-
- const Uint32 replicas= c_noNodesInGroup;
-
- Uint32 buckets= 1;
- for(i = 1; i <= replicas; i++)
- buckets *= i;
-
- for(i = 0; i<buckets; i++)
- {
- Bucket* ptr= c_buckets+i;
- for(Uint32 j= 0; j< replicas; j++)
- {
- ptr->m_nodes[j] = c_nodesInGroup[(i + j) % replicas];
- }
- }
-
- c_no_of_buckets= buckets;
- ndbrequire(c_noNodesInGroup > 0); // at least 1 node in the nodegroup
-
-#ifndef DBUG_OFF
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- DBUG_PRINT("exit",("Suma: NodeGroup %u, me %u, "
- "member[%u] %u",
- c_nodeGroup, getOwnNodeId(),
- i, c_nodesInGroup[i]));
- }
-#endif
-
- DBUG_VOID_RETURN;
-}
-
-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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- // SumaParticipant
- Uint32 noTables, noAttrs;
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_TABLES,
- &noTables);
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_ATTRIBUTES,
- &noAttrs);
-
- c_tablePool.setSize(noTables);
- c_tables.setSize(noTables);
-
- c_subscriptions.setSize(noTables);
- c_subscriberPool.setSize(2*noTables);
-
- c_subscriptionPool.setSize(noTables);
- c_syncPool.setSize(2);
- c_dataBufferPool.setSize(noAttrs);
-
- // Calculate needed gcp pool as 10 records + the ones needed
- // during a possible api timeout
- Uint32 dbApiHbInterval, gcpInterval;
- ndb_mgm_get_int_parameter(p, CFG_DB_API_HEARTBEAT_INTERVAL,
- &dbApiHbInterval);
- ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL,
- &gcpInterval);
- c_gcp_pool.setSize(10 + (4*dbApiHbInterval)/gcpInterval);
-
- c_page_chunk_pool.setSize(50);
-
- {
- SLList<SyncRecord> tmp(c_syncPool);
- Ptr<SyncRecord> ptr;
- while(tmp.seize(ptr))
- new (ptr.p) SyncRecord(* this, c_dataBufferPool);
- tmp.release();
- }
-
- // Suma
- c_masterNodeId = getOwnNodeId();
-
- c_nodeGroup = c_noNodesInGroup = 0;
- for (int i = 0; i < MAX_REPLICAS; i++) {
- c_nodesInGroup[i] = 0;
- }
-
- m_first_free_page= RNIL;
-
- c_no_of_buckets = 0;
- memset(c_buckets, 0, sizeof(c_buckets));
- for(Uint32 i = 0; i<NO_OF_BUCKETS; i++)
- {
- Bucket* bucket= c_buckets+i;
- bucket->m_buffer_tail = RNIL;
- bucket->m_buffer_head.m_page_id = RNIL;
- bucket->m_buffer_head.m_page_pos = Buffer_page::DATA_WORDS;
- }
-
- m_max_seen_gci = 0; // FIRE_TRIG_ORD
- m_max_sent_gci = 0; // FIRE_TRIG_ORD -> send
- m_last_complete_gci = 0; // SUB_GCP_COMPLETE_REP
- m_gcp_complete_rep_count = 0;
- m_out_of_buffer_gci = 0;
-
- c_startup.m_wait_handover= false;
- c_failedApiNodes.clear();
-
- 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];
-
- DBUG_PRINT("info",("startphase = %u, typeOfStart = %u",
- startphase, typeOfStart));
-
- if(startphase == 3)
- {
- jam();
- ndbrequire((m_tup = (Dbtup*)globalData.getBlock(DBTUP)) != 0);
- signal->theData[0] = reference();
- sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
- DBUG_VOID_RETURN;
- }
-
- if(startphase == 5)
- {
- if (ERROR_INSERTED(13029)) /* Hold startphase 5 */
- {
- sendSignalWithDelay(SUMA_REF, GSN_STTOR, signal,
- 30, signal->getLength());
- DBUG_VOID_RETURN;
- }
-
- c_startup.m_restart_server_node_id = 0;
- getNodeGroupMembers(signal);
- if (typeOfStart == NodeState::ST_NODE_RESTART ||
- typeOfStart == NodeState::ST_INITIAL_NODE_RESTART)
- {
- jam();
-
- send_start_me_req(signal);
- DBUG_VOID_RETURN;
- }
- }
-
- if(startphase == 7)
- {
- if (typeOfStart != NodeState::ST_NODE_RESTART &&
- typeOfStart != NodeState::ST_INITIAL_NODE_RESTART)
- {
- for( Uint32 i = 0; i < c_no_of_buckets; i++)
- {
- if (get_responsible_node(i) == getOwnNodeId())
- {
- // I'm running this bucket
- DBUG_PRINT("info",("bucket %u set to true", i));
- m_active_buckets.set(i);
- ndbout_c("m_active_buckets.set(%d)", i);
- }
- }
- }
-
- if(!m_active_buckets.isclear())
- {
- NdbNodeBitmask tmp;
- Uint32 bucket = 0;
- while ((bucket = m_active_buckets.find(bucket)) != Bucket_mask::NotFound)
- {
- tmp.set(get_responsible_node(bucket, c_nodes_in_nodegroup_mask));
- bucket++;
- }
-
- ndbassert(tmp.get(getOwnNodeId()));
- m_gcp_complete_rep_count = tmp.count();// I contribute 1 gcp complete rep
- }
- else
- m_gcp_complete_rep_count = 0; // I contribute 1 gcp complete rep
-
- if(typeOfStart == NodeState::ST_INITIAL_START &&
- c_masterNodeId == getOwnNodeId())
- {
- jam();
- createSequence(signal);
- DBUG_VOID_RETURN;
- }//if
-
- if (ERROR_INSERTED(13030))
- {
- ndbout_c("Dont start handover");
- DBUG_VOID_RETURN;
- }
- }//if
-
- if(startphase == 100)
- {
- /**
- * Allow API's to connect
- */
- sendSTTORRY(signal);
- DBUG_VOID_RETURN;
- }
-
- if(startphase == 101)
- {
- if (typeOfStart == NodeState::ST_NODE_RESTART ||
- typeOfStart == NodeState::ST_INITIAL_NODE_RESTART)
- {
- /**
- * Handover code here
- */
- c_startup.m_wait_handover= true;
- check_start_handover(signal);
- DBUG_VOID_RETURN;
- }
- }
- sendSTTORRY(signal);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::send_start_me_req(Signal* signal)
-{
- Uint32 nodeId= c_startup.m_restart_server_node_id;
- do {
- nodeId = c_alive_nodes.find(nodeId + 1);
-
- if(nodeId == getOwnNodeId())
- continue;
- if(nodeId == NdbNodeBitmask::NotFound)
- {
- nodeId = 0;
- continue;
- }
- break;
- } while(true);
-
-
- infoEvent("Suma: asking node %d to recreate subscriptions on me", nodeId);
- c_startup.m_restart_server_node_id= nodeId;
- sendSignal(calcSumaBlockRef(nodeId),
- GSN_SUMA_START_ME_REQ, signal, 1, JBB);
-}
-
-void
-Suma::execSUMA_START_ME_REF(Signal* signal)
-{
- const SumaStartMeRef* ref= (SumaStartMeRef*)signal->getDataPtr();
- ndbrequire(ref->errorCode == SumaStartMeRef::Busy);
-
- infoEvent("Suma: node %d refused %d",
- c_startup.m_restart_server_node_id, ref->errorCode);
-
- c_startup.m_restart_server_node_id++;
- send_start_me_req(signal);
-}
-
-void
-Suma::execSUMA_START_ME_CONF(Signal* signal)
-{
- infoEvent("Suma: node %d has completed restoring me",
- c_startup.m_restart_server_node_id);
- sendSTTORRY(signal);
- c_startup.m_restart_server_node_id= 0;
-}
-
-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;
- sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
- signal, UtilSequenceReq::SignalLength, JBB);
- // execUTIL_SEQUENCE_CONF will call createSequenceReply()
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::createSequenceReply(Signal* signal,
- UtilSequenceConf * conf,
- UtilSequenceRef * ref)
-{
- jam();
-
- if (ref != NULL)
- {
- switch ((UtilSequenceRef::ErrorCode)ref->errorCode)
- {
- case UtilSequenceRef::NoSuchSequence:
- ndbrequire(false);
- case UtilSequenceRef::TCError:
- {
- char buf[128];
- snprintf(buf, sizeof(buf),
- "Startup failed during sequence creation. TC error %d",
- ref->TCErrorCode);
- progError(__LINE__, NDBD_EXIT_RESOURCE_ALLOC_ERROR, buf);
- }
- }
- ndbrequire(false);
- }
-
- sendSTTORRY(signal);
-}
-
-void
-Suma::execREAD_NODESCONF(Signal* signal){
- jamEntry();
- ReadNodesConf * const conf = (ReadNodesConf *)signal->getDataPtr();
-
- if(getNodeState().getNodeRestartInProgress())
- {
- c_alive_nodes.assign(NdbNodeBitmask::Size, conf->startedNodes);
- c_alive_nodes.set(getOwnNodeId());
- }
- else
- {
- c_alive_nodes.assign(NdbNodeBitmask::Size, conf->startingNodes);
- NdbNodeBitmask tmp;
- tmp.assign(NdbNodeBitmask::Size, conf->startedNodes);
- ndbrequire(tmp.isclear()); // No nodes can be started during SR
- }
-
- c_masterNodeId = conf->masterNodeId;
-
- sendSTTORRY(signal);
-}
-
-void
-Suma::execAPI_START_REP(Signal* signal)
-{
- Uint32 nodeId = signal->theData[0];
- c_connected_nodes.set(nodeId);
-
- check_start_handover(signal);
-}
-
-void
-Suma::check_start_handover(Signal* signal)
-{
- if(c_startup.m_wait_handover)
- {
- NodeBitmask tmp;
- tmp.assign(c_connected_nodes);
- tmp.bitAND(c_subscriber_nodes);
- if(!c_subscriber_nodes.equal(tmp))
- {
- return;
- }
-
- c_startup.m_wait_handover= false;
- send_handover_req(signal);
- }
-}
-
-void
-Suma::send_handover_req(Signal* signal)
-{
- c_startup.m_handover_nodes.assign(c_alive_nodes);
- c_startup.m_handover_nodes.bitAND(c_nodes_in_nodegroup_mask);
- c_startup.m_handover_nodes.clear(getOwnNodeId());
- Uint32 gci= m_last_complete_gci + 3;
-
- SumaHandoverReq* req= (SumaHandoverReq*)signal->getDataPtrSend();
- char buf[255];
- c_startup.m_handover_nodes.getText(buf);
- infoEvent("Suma: initiate handover with nodes %s GCI: %d",
- buf, gci);
-
- req->gci = gci;
- req->nodeId = getOwnNodeId();
-
- NodeReceiverGroup rg(SUMA, c_startup.m_handover_nodes);
- sendSignal(rg, GSN_SUMA_HANDOVER_REQ, signal,
- SumaHandoverReq::SignalLength, JBB);
-}
-
-void
-Suma::sendSTTORRY(Signal* signal){
- signal->theData[0] = 0;
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 5;
- signal->theData[6] = 7;
- signal->theData[7] = 100;
- signal->theData[8] = 101;
- signal->theData[9] = 255; // No more start phases from missra
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 10, JBB);
-}
-
-void
-Suma::execNDB_STTOR(Signal* signal)
-{
- jamEntry();
-}
-
-void
-Suma::execCONTINUEB(Signal* signal){
- jamEntry();
- Uint32 type= signal->theData[0];
- switch(type){
- case SumaContinueB::RELEASE_GCI:
- release_gci(signal, signal->theData[1], signal->theData[2]);
- return;
- case SumaContinueB::RESEND_BUCKET:
- resend_bucket(signal,
- signal->theData[1],
- signal->theData[2],
- signal->theData[3],
- signal->theData[4]);
- return;
- case SumaContinueB::OUT_OF_BUFFER_RELEASE:
- out_of_buffer_release(signal, signal->theData[1]);
- return;
- }
-}
-
-/*****************************************************************************
- *
- * Node state handling
- *
- *****************************************************************************/
-
-void Suma::execAPI_FAILREQ(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execAPI_FAILREQ");
- Uint32 failedApiNode = signal->theData[0];
- //BlockReference retRef = signal->theData[1];
-
- if (c_startup.m_restart_server_node_id &&
- c_startup.m_restart_server_node_id != RNIL)
- {
- jam();
- sendSignalWithDelay(reference(), GSN_API_FAILREQ, signal,
- 200, signal->getLength());
- DBUG_VOID_RETURN;
- }
-
- if (c_failedApiNodes.get(failedApiNode))
- {
- jam();
- DBUG_VOID_RETURN;
- }
-
- if (!c_subscriber_nodes.get(failedApiNode))
- {
- jam();
- DBUG_VOID_RETURN;
- }
-
- c_failedApiNodes.set(failedApiNode);
- c_connected_nodes.clear(failedApiNode);
- bool found = removeSubscribersOnNode(signal, failedApiNode);
-
- if(!found){
- jam();
- c_failedApiNodes.clear(failedApiNode);
- }
-
- SubGcpCompleteAck * const ack = (SubGcpCompleteAck*)signal->getDataPtr();
- Ptr<Gcp_record> gcp;
- for(c_gcp_list.first(gcp); !gcp.isNull(); c_gcp_list.next(gcp))
- {
- jam();
- ack->rep.gci = gcp.p->m_gci;
- if(gcp.p->m_subscribers.get(failedApiNode))
- {
- jam();
- gcp.p->m_subscribers.clear(failedApiNode);
- ack->rep.senderRef = numberToRef(0, failedApiNode);
- sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_ACK, signal,
- SubGcpCompleteAck::SignalLength, JBB);
- }
- }
-
- c_subscriber_nodes.clear(failedApiNode);
-
- check_start_handover(signal);
-
- DBUG_VOID_RETURN;
-}//execAPI_FAILREQ()
-
-bool
-Suma::removeSubscribersOnNode(Signal *signal, Uint32 nodeId)
-{
- DBUG_ENTER("Suma::removeSubscribersOnNode");
- bool found = false;
-
- KeyTable<Table>::Iterator it;
- LINT_INIT(it.bucket);
- LINT_INIT(it.curr.p);
- for(c_tables.first(it);!it.isNull();c_tables.next(it))
- {
- LocalDLList<Subscriber> subbs(c_subscriberPool,it.curr.p->c_subscribers);
- SubscriberPtr i_subbPtr;
- for(subbs.first(i_subbPtr);!i_subbPtr.isNull();)
- {
- SubscriberPtr subbPtr = i_subbPtr;
- subbs.next(i_subbPtr);
- jam();
- if (refToNode(subbPtr.p->m_senderRef) == nodeId) {
- jam();
- subbs.remove(subbPtr);
- c_removeDataSubscribers.add(subbPtr);
- found = true;
- }
- }
- if (subbs.isEmpty())
- {
- // ToDo handle this
- }
- }
- if(found){
- jam();
- sendSubStopReq(signal);
- }
- DBUG_RETURN(found);
-}
-
-void
-Suma::sendSubStopReq(Signal *signal, bool unlock){
- static bool remove_lock = false;
- jam();
- DBUG_ENTER("Suma::sendSubStopReq");
-
- 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;
- DBUG_VOID_RETURN;
- }
-
- if(remove_lock && !unlock) {
- jam();
- DBUG_VOID_RETURN;
- }
- remove_lock = true;
-
- 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_senderRef;
- req->subscriberData = subbPtr.p->m_senderData;
- 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);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_STOP_CONF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execSUB_STOP_CONF");
- ndbassert(signal->getNoOfSections() == 0);
- sendSubStopReq(signal,true);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_STOP_REF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execSUB_STOP_REF");
- ndbassert(signal->getNoOfSections() == 0);
-
- SubStopRef * const ref = (SubStopRef*)signal->getDataPtr();
-
- Uint32 senderData = ref->senderData;
- Uint32 subscriptionId = ref->subscriptionId;
- Uint32 subscriptionKey = ref->subscriptionKey;
- Uint32 part = ref->part;
- Uint32 subscriberData = ref->subscriberData;
- Uint32 subscriberRef = ref->subscriberRef;
-
- if(ref->errorCode != 1411){
- ndbrequire(false);
- }
-
- SubStopReq * const req = (SubStopReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = senderData;
- 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);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execNODE_FAILREP(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execNODE_FAILREP");
- ndbassert(signal->getNoOfSections() == 0);
-
- const NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
- NdbNodeBitmask failed; failed.assign(NdbNodeBitmask::Size, rep->theNodes);
-
- if(failed.get(Restart.nodeId))
- {
- Restart.resetRestart(signal);
- }
-
- if (ERROR_INSERTED(13032))
- {
- Uint32 node = c_subscriber_nodes.find(0);
- if (node != NodeBitmask::NotFound)
- {
- ndbout_c("Inserting API_FAILREQ node: %u", node);
- signal->theData[0] = node;
- EXECUTE_DIRECT(QMGR, GSN_API_FAILREQ, signal, 1);
- }
- }
-
- signal->theData[0] = SumaContinueB::RESEND_BUCKET;
-
- NdbNodeBitmask tmp;
- tmp.assign(c_alive_nodes);
- tmp.bitANDC(failed);
-
- NdbNodeBitmask takeover_nodes;
-
- if(c_nodes_in_nodegroup_mask.overlaps(failed))
- {
- for( Uint32 i = 0; i < c_no_of_buckets; i++)
- {
- if(m_active_buckets.get(i))
- continue;
- else if(m_switchover_buckets.get(i))
- {
- Uint32 state= c_buckets[i].m_state;
- if((state & Bucket::BUCKET_HANDOVER) &&
- failed.get(get_responsible_node(i)))
- {
- m_active_buckets.set(i);
- m_switchover_buckets.clear(i);
- ndbout_c("aborting handover");
- }
- else if(state & Bucket::BUCKET_STARTING)
- {
- progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
- "Nodefailure during SUMA takeover");
- }
- }
- else if(get_responsible_node(i, tmp) == getOwnNodeId())
- {
- start_resend(signal, i);
- }
- }
- }
-
- c_alive_nodes.assign(tmp);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execINCL_NODEREQ(Signal* signal){
- jamEntry();
-
- const Uint32 senderRef = signal->theData[0];
- const Uint32 nodeId = signal->theData[1];
-
- ndbrequire(!c_alive_nodes.get(nodeId));
- c_alive_nodes.set(nodeId);
-
- signal->theData[0] = nodeId;
- signal->theData[1] = reference();
- sendSignal(senderRef, GSN_INCL_NODECONF, signal, 2, JBB);
-}
-
-void
-Suma::execSIGNAL_DROPPED_REP(Signal* signal){
- jamEntry();
- ndbrequire(false);
-}
-
-/********************************************************************
- *
- * Dump state
- *
- */
-
-static unsigned
-count_subscribers(const DLList<Suma::Subscriber> &subs)
-{
- unsigned n= 0;
- Suma::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();
-
- Uint32 tCase = signal->theData[0];
-#if 0
- if(tCase >= 8000 && tCase <= 8003){
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, g_subPtrI);
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
-
- if(tCase == 8000){
- syncPtr.p->startMeta(signal);
- }
-
- if(tCase == 8001){
- syncPtr.p->startScan(signal);
- }
-
- if(tCase == 8002){
- syncPtr.p->startTrigger(signal);
- }
-
- if(tCase == 8003){
- subPtr.p->m_subscriptionType = SubCreateReq::SingleTableScan;
- LocalDataBuffer<15> attrs(c_dataBufferPool, syncPtr.p->m_attributeList);
- Uint32 tab = 0;
- Uint32 att[] = { 0, 1, 1 };
- syncPtr.p->m_tableList.append(&tab, 1);
- attrs.append(att, 3);
- }
- }
-#endif
- if(tCase == 8004){
- infoEvent("Suma: c_subscriberPool size: %d free: %d",
- c_subscriberPool.getSize(),
- c_subscriberPool.getNoOfFree());
-
- infoEvent("Suma: c_tablePool size: %d free: %d",
- c_tablePool.getSize(),
- c_tablePool.getNoOfFree());
-
- infoEvent("Suma: c_subscriptionPool size: %d free: %d",
- c_subscriptionPool.getSize(),
- c_subscriptionPool.getNoOfFree());
-
- infoEvent("Suma: c_syncPool size: %d free: %d",
- c_syncPool.getSize(),
- c_syncPool.getNoOfFree());
-
- infoEvent("Suma: c_dataBufferPool size: %d free: %d",
- c_dataBufferPool.getSize(),
- c_dataBufferPool.getNoOfFree());
-
- infoEvent("Suma: c_metaSubscribers count: %d",
- count_subscribers(c_metaSubscribers));
-#if 0
- infoEvent("Suma: c_dataSubscribers count: %d",
- count_subscribers(c_dataSubscribers));
- infoEvent("Suma: c_prepDataSubscribers count: %d",
- count_subscribers(c_prepDataSubscribers));
-#endif
- infoEvent("Suma: c_removeDataSubscribers count: %d",
- count_subscribers(c_removeDataSubscribers));
- }
-
- if(tCase == 8005)
- {
- for(Uint32 i = 0; i<c_no_of_buckets; i++)
- {
- Bucket* ptr= c_buckets + i;
- infoEvent("Bucket %d %d%d-%x switch gci: %d max_acked_gci: %d max_gci: %d tail: %d head: %d",
- i,
- m_active_buckets.get(i),
- m_switchover_buckets.get(i),
- ptr->m_state,
- ptr->m_switchover_gci,
- ptr->m_max_acked_gci,
- ptr->m_buffer_head.m_max_gci,
- ptr->m_buffer_tail,
- ptr->m_buffer_head.m_page_id);
- }
- }
-
- if (tCase == 8006)
- {
- SET_ERROR_INSERT_VALUE(13029);
- }
-
- if (tCase == 8007)
- {
- c_startup.m_restart_server_node_id = MAX_NDB_NODES + 1;
- SET_ERROR_INSERT_VALUE(13029);
- }
-
- if (tCase == 8008)
- {
- CLEAR_ERROR_INSERT_VALUE;
- }
-
- if (tCase == 8010)
- {
- char buf1[255], buf2[255];
- c_subscriber_nodes.getText(buf1);
- c_connected_nodes.getText(buf2);
- infoEvent("c_subscriber_nodes: %s", buf1);
- infoEvent("c_connected_nodes: %s", buf2);
- }
-
- if (tCase == 8009)
- {
- if (ERROR_INSERTED(13030))
- {
- CLEAR_ERROR_INSERT_VALUE;
- sendSTTORRY(signal);
- }
- else
- {
- SET_ERROR_INSERT_VALUE(13030);
- }
- return;
- }
-
- if (tCase == 8011)
- {
- jam();
- Uint32 bucket = signal->theData[1];
- KeyTable<Table>::Iterator it;
- if (signal->getLength() == 1)
- {
- jam();
- bucket = 0;
- infoEvent("-- Starting dump of subscribers --");
- }
-
- c_tables.next(bucket, it);
- const Uint32 RT_BREAK = 16;
- for(Uint32 i = 0; i<RT_BREAK || it.bucket == bucket; i++)
- {
- jam();
- if(it.curr.i == RNIL)
- {
- jam();
- infoEvent("-- Ending dump of subscribers --");
- return;
- }
-
- infoEvent("Table: %u ver: %u #n: %u (ref,data,subscritopn)",
- it.curr.p->m_tableId,
- it.curr.p->m_schemaVersion,
- it.curr.p->n_subscribers);
-
- Ptr<Subscriber> ptr;
- LocalDLList<Subscriber> list(c_subscriberPool, it.curr.p->c_subscribers);
- for (list.first(ptr); !ptr.isNull(); list.next(ptr), i++)
- {
- jam();
- infoEvent(" [ %x %u %u ]",
- ptr.p->m_senderRef,
- ptr.p->m_senderData,
- ptr.p->m_subPtrI);
- }
- c_tables.next(it);
- }
-
- signal->theData[0] = tCase;
- signal->theData[1] = it.bucket;
- sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 100, 2);
- return;
- }
-}
-
-/*************************************************************
- *
- * Creation of subscription id's
- *
- ************************************************************/
-
-void
-Suma::execCREATE_SUBID_REQ(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execCREATE_SUBID_REQ");
- ndbassert(signal->getNoOfSections() == 0);
- CRASH_INSERTION(13001);
-
- CreateSubscriptionIdReq const * req =
- (CreateSubscriptionIdReq*)signal->getDataPtr();
- SubscriberPtr subbPtr;
- if(!c_subscriberPool.seize(subbPtr)){
- jam();
- sendSubIdRef(signal, req->senderRef, req->senderData, 1412);
- DBUG_VOID_RETURN;
- }
- DBUG_PRINT("info",("c_subscriberPool size: %d free: %d",
- c_subscriberPool.getSize(),
- c_subscriberPool.getNoOfFree()));
-
- subbPtr.p->m_senderRef = req->senderRef;
- subbPtr.p->m_senderData = req->senderData;
-
- UtilSequenceReq * utilReq = (UtilSequenceReq*)signal->getDataPtrSend();
- utilReq->senderData = subbPtr.i;
- utilReq->sequenceId = SUMA_SEQUENCE;
- utilReq->requestType = UtilSequenceReq::NextVal;
- sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
- signal, UtilSequenceReq::SignalLength, JBB);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execUTIL_SEQUENCE_CONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execUTIL_SEQUENCE_CONF");
- ndbassert(signal->getNoOfSections() == 0);
- CRASH_INSERTION(13002);
-
- UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr();
- if(conf->requestType == UtilSequenceReq::Create) {
- jam();
- createSequenceReply(signal, conf, NULL);
- DBUG_VOID_RETURN;
- }
-
- Uint64 subId;
- memcpy(&subId,conf->sequenceValue,8);
- SubscriberPtr subbPtr;
- c_subscriberPool.getPtr(subbPtr,conf->senderData);
-
- CreateSubscriptionIdConf * subconf = (CreateSubscriptionIdConf*)conf;
- subconf->senderRef = reference();
- subconf->senderData = subbPtr.p->m_senderData;
- subconf->subscriptionId = (Uint32)subId;
- subconf->subscriptionKey =(getOwnNodeId() << 16) | (Uint32)(subId & 0xFFFF);
-
- sendSignal(subbPtr.p->m_senderRef, GSN_CREATE_SUBID_CONF, signal,
- CreateSubscriptionIdConf::SignalLength, JBB);
-
- c_subscriberPool.release(subbPtr);
- DBUG_PRINT("info",("c_subscriberPool size: %d free: %d",
- c_subscriberPool.getSize(),
- c_subscriberPool.getNoOfFree()));
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execUTIL_SEQUENCE_REF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execUTIL_SEQUENCE_REF");
- ndbassert(signal->getNoOfSections() == 0);
- UtilSequenceRef * ref = (UtilSequenceRef*)signal->getDataPtr();
- Uint32 err= ref->errorCode;
-
- if(ref->requestType == UtilSequenceReq::Create) {
- jam();
- createSequenceReply(signal, NULL, ref);
- DBUG_VOID_RETURN;
- }
-
- Uint32 subData = ref->senderData;
-
- SubscriberPtr subbPtr;
- c_subscriberPool.getPtr(subbPtr,subData);
- sendSubIdRef(signal, subbPtr.p->m_senderRef, subbPtr.p->m_senderData, err);
- c_subscriberPool.release(subbPtr);
- DBUG_PRINT("info",("c_subscriberPool size: %d free: %d",
- c_subscriberPool.getSize(),
- c_subscriberPool.getNoOfFree()));
- DBUG_VOID_RETURN;
-}//execUTIL_SEQUENCE_REF()
-
-
-void
-Suma::sendSubIdRef(Signal* signal,
- Uint32 senderRef, Uint32 senderData, Uint32 errCode)
-{
- jam();
- DBUG_ENTER("Suma::sendSubIdRef");
- CreateSubscriptionIdRef * ref =
- (CreateSubscriptionIdRef *)signal->getDataPtrSend();
-
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->errorCode = errCode;
- sendSignal(senderRef,
- GSN_CREATE_SUBID_REF,
- signal,
- CreateSubscriptionIdRef::SignalLength,
- JBB);
-
- releaseSections(signal);
- DBUG_VOID_RETURN;
-}
-
-/**********************************************************
- * Suma participant interface
- *
- * Creation of subscriptions
- */
-
-void
-Suma::addTableId(Uint32 tableId,
- SubscriptionPtr subPtr, SyncRecord *psyncRec)
-{
- DBUG_ENTER("Suma::addTableId");
- DBUG_PRINT("enter",("tableId: %u subPtr.i: %u", tableId, subPtr.i));
- subPtr.p->m_tableId= tableId;
- if(psyncRec != NULL)
- psyncRec->m_tableList.append(&tableId, 1);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_CREATE_REQ(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execSUB_CREATE_REQ");
- ndbassert(signal->getNoOfSections() == 0);
- CRASH_INSERTION(13003);
-
- const SubCreateReq req = *(SubCreateReq*)signal->getDataPtr();
-
- const Uint32 subRef = req.senderRef;
- const Uint32 subData = req.senderData;
- const Uint32 subId = req.subscriptionId;
- const Uint32 subKey = req.subscriptionKey;
- const Uint32 type = req.subscriptionType & SubCreateReq::RemoveFlags;
- const Uint32 flags = req.subscriptionType & SubCreateReq::GetFlags;
- const bool addTableFlag = (flags & SubCreateReq::AddTableFlag) != 0;
- const bool restartFlag = (flags & SubCreateReq::RestartFlag) != 0;
- const Uint32 reportAll = (flags & SubCreateReq::ReportAll) ?
- Subscription::REPORT_ALL : 0;
- const Uint32 reportSubscribe = (flags & SubCreateReq::ReportSubscribe) ?
- Subscription::REPORT_SUBSCRIBE : 0;
- const Uint32 tableId = req.tableId;
- Subscription::State state = (Subscription::State) req.state;
- if (signal->getLength() != SubCreateReq::SignalLength2)
- {
- /*
- api or restarted by older version
- if restarted by old version, do the best we can
- */
- state = Subscription::DEFINED;
- }
-
- Subscription key;
- key.m_subscriptionId = subId;
- key.m_subscriptionKey = subKey;
-
- DBUG_PRINT("enter",("key.m_subscriptionId: %u, key.m_subscriptionKey: %u",
- key.m_subscriptionId, key.m_subscriptionKey));
-
- SubscriptionPtr subPtr;
-
- if (addTableFlag) {
- ndbrequire(restartFlag); //TODO remove this
-
- if(!c_subscriptions.find(subPtr, key)) {
- jam();
- sendSubCreateRef(signal, 1407);
- DBUG_VOID_RETURN;
- }
- jam();
- if (restartFlag)
- {
- ndbrequire(type != SubCreateReq::SingleTableScan);
- ndbrequire(req.tableId != subPtr.p->m_tableId);
- ndbrequire(type != SubCreateReq::TableEvent);
- addTableId(req.tableId, subPtr, 0);
- }
- } else {
- if (c_startup.m_restart_server_node_id &&
- subRef != calcSumaBlockRef(c_startup.m_restart_server_node_id))
- {
- /**
- * only allow "restart_server" Suma's to come through
- * for restart purposes
- */
- jam();
- sendSubCreateRef(signal, 1415);
- DBUG_VOID_RETURN;
- }
- // Check that id/key is unique
- if(c_subscriptions.find(subPtr, key)) {
- jam();
- sendSubCreateRef(signal, 1415);
- DBUG_VOID_RETURN;
- }
- if(!c_subscriptions.seize(subPtr)) {
- jam();
- sendSubCreateRef(signal, 1412);
- DBUG_VOID_RETURN;
- }
- DBUG_PRINT("info",("c_subscriptionPool size: %d free: %d",
- c_subscriptionPool.getSize(),
- c_subscriptionPool.getNoOfFree()));
- jam();
- subPtr.p->m_senderRef = subRef;
- subPtr.p->m_senderData = subData;
- subPtr.p->m_subscriptionId = subId;
- subPtr.p->m_subscriptionKey = subKey;
- subPtr.p->m_subscriptionType = type;
- subPtr.p->m_options = reportSubscribe | reportAll;
- subPtr.p->m_tableId = tableId;
- subPtr.p->m_table_ptrI = RNIL;
- subPtr.p->m_state = state;
- subPtr.p->n_subscribers = 0;
- subPtr.p->m_current_sync_ptrI = RNIL;
-
- fprintf(stderr, "table %d options %x\n", subPtr.p->m_tableId, subPtr.p->m_options);
- DBUG_PRINT("info",("Added: key.m_subscriptionId: %u, key.m_subscriptionKey: %u",
- key.m_subscriptionId, key.m_subscriptionKey));
-
- c_subscriptions.add(subPtr);
- }
-
- SubCreateConf * const conf = (SubCreateConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = subPtr.p->m_senderData;
- sendSignal(subRef, GSN_SUB_CREATE_CONF, signal, SubCreateConf::SignalLength, JBB);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::sendSubCreateRef(Signal* signal, Uint32 errCode)
-{
- jam();
- SubCreateRef * ref = (SubCreateRef *)signal->getDataPtrSend();
- ref->errorCode = errCode;
- sendSignal(signal->getSendersBlockRef(), GSN_SUB_CREATE_REF, signal,
- SubCreateRef::SignalLength, JBB);
- return;
-}
-
-/**********************************************************
- *
- * Setting upp trigger for subscription
- *
- */
-
-void
-Suma::execSUB_SYNC_REQ(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execSUB_SYNC_REQ");
- ndbassert(signal->getNoOfSections() <= 1);
- CRASH_INSERTION(13004);
-
- SubSyncReq * const req = (SubSyncReq*)signal->getDataPtr();
-
- SubscriptionPtr subPtr;
- Subscription key;
- key.m_subscriptionId = req->subscriptionId;
- key.m_subscriptionKey = req->subscriptionKey;
-
- DBUG_PRINT("enter",("key.m_subscriptionId: %u, key.m_subscriptionKey: %u",
- key.m_subscriptionId, key.m_subscriptionKey));
-
- if(!c_subscriptions.find(subPtr, key))
- {
- jam();
- DBUG_PRINT("info",("Not found"));
- sendSubSyncRef(signal, 1407);
- DBUG_VOID_RETURN;
- }
-
- bool ok = false;
- SubscriptionData::Part part = (SubscriptionData::Part)req->part;
-
- Ptr<SyncRecord> syncPtr;
- if(!c_syncPool.seize(syncPtr))
- {
- jam();
- sendSubSyncRef(signal, 1416);
- DBUG_VOID_RETURN;
- }
- DBUG_PRINT("info",("c_syncPool size: %d free: %d",
- c_syncPool.getSize(),
- c_syncPool.getNoOfFree()));
-
- syncPtr.p->m_senderRef = req->senderRef;
- syncPtr.p->m_senderData = req->senderData;
- syncPtr.p->m_subscriptionPtrI = subPtr.i;
- syncPtr.p->ptrI = syncPtr.i;
- syncPtr.p->m_error = 0;
-
- subPtr.p->m_current_sync_ptrI = syncPtr.i;
-
- {
- jam();
- syncPtr.p->m_tableList.append(&subPtr.p->m_tableId, 1);
- if(signal->getNoOfSections() > 0){
- SegmentedSectionPtr ptr(0,0,0);
- signal->getSection(ptr, SubSyncReq::ATTRIBUTE_LIST);
- LocalDataBuffer<15> attrBuf(c_dataBufferPool,syncPtr.p->m_attributeList);
- append(attrBuf, ptr, getSectionSegmentPool());
- releaseSections(signal);
- }
- }
-
- TablePtr tabPtr;
- initTable(signal,subPtr.p->m_tableId,tabPtr,syncPtr);
- tabPtr.p->n_subscribers++;
- if (subPtr.p->m_options & Subscription::REPORT_ALL)
- tabPtr.p->m_reportAll = true;
- DBUG_PRINT("info",("Suma::Table[%u]::n_subscribers: %u",
- tabPtr.p->m_tableId, tabPtr.p->n_subscribers));
- DBUG_VOID_RETURN;
-
- switch(part){
- case SubscriptionData::MetaData:
- ndbrequire(false);
-#if 0
- 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);
-#endif
- break;
- case SubscriptionData::TableData: {
- ok = true;
- jam();
- syncPtr.p->startScan(signal);
- break;
- }
- }
- ndbrequire(ok);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::sendSubSyncRef(Signal* signal, Uint32 errCode){
- jam();
- SubSyncRef * ref= (SubSyncRef *)signal->getDataPtrSend();
- ref->errorCode = errCode;
- releaseSections(signal);
- sendSignal(signal->getSendersBlockRef(),
- GSN_SUB_SYNC_REF,
- signal,
- SubSyncRef::SignalLength,
- JBB);
- return;
-}
-
-/**********************************************************
- * Dict interface
- */
-
-#if 0
-void
-Suma::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);
-}
-#endif
-
-
-/*************************************************************************
- *
- *
- */
-#if 0
-void
-Suma::Table::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);
-}
-#endif
-
-
-int
-Suma::initTable(Signal *signal, Uint32 tableId, TablePtr &tabPtr,
- SubscriberPtr subbPtr)
-{
- DBUG_ENTER("Suma::initTable SubscriberPtr");
- DBUG_PRINT("enter",("tableId: %d", tableId));
-
- int r= initTable(signal,tableId,tabPtr);
-
- {
- LocalDLList<Subscriber> subscribers(c_subscriberPool,
- tabPtr.p->c_subscribers);
- subscribers.add(subbPtr);
- }
-
- DBUG_PRINT("info",("added subscriber: %i", subbPtr.i));
-
- if (r)
- {
- jam();
- // we have to wait getting tab info
- DBUG_RETURN(1);
- }
-
- if (tabPtr.p->setupTrigger(signal, *this))
- {
- jam();
- // we have to wait for triggers to be setup
- DBUG_RETURN(1);
- }
-
- int ret = completeOneSubscriber(signal, tabPtr, subbPtr);
- if (ret == -1)
- {
- jam();
- LocalDLList<Subscriber> subscribers(c_subscriberPool,
- tabPtr.p->c_subscribers);
- subscribers.release(subbPtr);
- }
- completeInitTable(signal, tabPtr);
- DBUG_RETURN(0);
-}
-
-int
-Suma::initTable(Signal *signal, Uint32 tableId, TablePtr &tabPtr,
- Ptr<SyncRecord> syncPtr)
-{
- jam();
- DBUG_ENTER("Suma::initTable Ptr<SyncRecord>");
- DBUG_PRINT("enter",("tableId: %d", tableId));
-
- int r= initTable(signal,tableId,tabPtr);
-
- {
- LocalDLList<SyncRecord> syncRecords(c_syncPool,tabPtr.p->c_syncRecords);
- syncRecords.add(syncPtr);
- }
-
- if (r)
- {
- // we have to wait getting tab info
- DBUG_RETURN(1);
- }
- completeInitTable(signal, tabPtr);
- DBUG_RETURN(0);
-}
-
-int
-Suma::initTable(Signal *signal, Uint32 tableId, TablePtr &tabPtr)
-{
- jam();
- DBUG_ENTER("Suma::initTable");
-
- if (!c_tables.find(tabPtr, tableId) ||
- tabPtr.p->m_state == Table::DROPPED ||
- tabPtr.p->m_state == Table::ALTERED)
- {
- // table not being prepared
- // seize a new table, initialize and add to c_tables
- ndbrequire(c_tablePool.seize(tabPtr));
- DBUG_PRINT("info",("c_tablePool size: %d free: %d",
- c_tablePool.getSize(),
- c_tablePool.getNoOfFree()));
- new (tabPtr.p) Table;
-
- tabPtr.p->m_tableId= tableId;
- tabPtr.p->m_ptrI= tabPtr.i;
- tabPtr.p->n_subscribers = 0;
- DBUG_PRINT("info",("Suma::Table[%u,i=%u]::n_subscribers: %u",
- tabPtr.p->m_tableId, tabPtr.i, tabPtr.p->n_subscribers));
-
- tabPtr.p->m_reportAll = false;
-
- tabPtr.p->m_error = 0;
- tabPtr.p->m_schemaVersion = RNIL;
- tabPtr.p->m_state = Table::DEFINING;
- tabPtr.p->m_drop_subbPtr.p = 0;
- for (int j= 0; j < 3; j++)
- {
- tabPtr.p->m_hasTriggerDefined[j] = 0;
- tabPtr.p->m_hasOutstandingTriggerReq[j] = 0;
- tabPtr.p->m_triggerIds[j] = ILLEGAL_TRIGGER_ID;
- }
-
- c_tables.add(tabPtr);
-
- GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = tabPtr.i;
- req->requestType =
- GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
- req->tableId = tableId;
-
- DBUG_PRINT("info",("GET_TABINFOREQ id %d", req->tableId));
-
- if (ERROR_INSERTED(13031))
- {
- jam();
- CLEAR_ERROR_INSERT_VALUE;
- GetTabInfoRef* ref = (GetTabInfoRef*)signal->getDataPtrSend();
- ref->tableId = tableId;
- ref->senderData = tabPtr.i;
- ref->errorCode = GetTabInfoRef::TableNotDefined;
- sendSignal(reference(), GSN_GET_TABINFOREF, signal,
- GetTabInfoRef::SignalLength, JBB);
- DBUG_RETURN(1);
- }
-
- sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
- GetTabInfoReq::SignalLength, JBB);
- DBUG_RETURN(1);
- }
- if (tabPtr.p->m_state == Table::DEFINING)
- {
- DBUG_RETURN(1);
- }
- // ToDo should be a ref signal instead
- ndbrequire(tabPtr.p->m_state == Table::DEFINED);
- DBUG_RETURN(0);
-}
-
-int
-Suma::completeOneSubscriber(Signal *signal, TablePtr tabPtr, SubscriberPtr subbPtr)
-{
- jam();
- DBUG_ENTER("Suma::completeOneSubscriber");
-
- if (tabPtr.p->m_error &&
- (c_startup.m_restart_server_node_id == 0 ||
- tabPtr.p->m_state != Table::DROPPED))
- {
- jam();
- sendSubStartRef(signal,subbPtr,tabPtr.p->m_error,
- SubscriptionData::TableData);
- tabPtr.p->n_subscribers--;
- DBUG_RETURN(-1);
- }
- else
- {
- jam();
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
- subPtr.p->m_table_ptrI= tabPtr.i;
- sendSubStartComplete(signal,subbPtr, m_last_complete_gci + 3,
- SubscriptionData::TableData);
- }
- DBUG_RETURN(0);
-}
-
-void
-Suma::completeAllSubscribers(Signal *signal, TablePtr tabPtr)
-{
- jam();
- DBUG_ENTER("Suma::completeAllSubscribers");
- // handle all subscribers
- {
- LocalDLList<Subscriber> subscribers(c_subscriberPool,
- tabPtr.p->c_subscribers);
- SubscriberPtr subbPtr;
- for(subscribers.first(subbPtr); !subbPtr.isNull();)
- {
- jam();
- Ptr<Subscriber> tmp = subbPtr;
- subscribers.next(subbPtr);
- int ret = completeOneSubscriber(signal, tabPtr, tmp);
- if (ret == -1)
- {
- jam();
- subscribers.release(tmp);
- }
- }
- }
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::completeInitTable(Signal *signal, TablePtr tabPtr)
-{
- jam();
- DBUG_ENTER("Suma::completeInitTable");
-
- // handle all syncRecords
- while (!tabPtr.p->c_syncRecords.isEmpty())
- {
- Ptr<SyncRecord> syncPtr;
- {
- LocalDLList<SyncRecord> syncRecords(c_syncPool,
- tabPtr.p->c_syncRecords);
- syncRecords.first(syncPtr);
- syncRecords.remove(syncPtr);
- }
- syncPtr.p->ptrI = syncPtr.i;
- if (tabPtr.p->m_error == 0)
- {
- jam();
- syncPtr.p->startScan(signal);
- }
- else
- {
- jam();
- syncPtr.p->completeScan(signal, tabPtr.p->m_error);
- tabPtr.p->n_subscribers--;
- }
- }
-
- if (tabPtr.p->m_error)
- {
- DBUG_PRINT("info",("Suma::Table[%u]::n_subscribers: %u",
- tabPtr.p->m_tableId, tabPtr.p->n_subscribers));
- tabPtr.p->checkRelease(*this);
- }
- else
- {
- tabPtr.p->m_state = Table::DEFINED;
- }
-
- DBUG_VOID_RETURN;
-}
-
-
-void
-Suma::execGET_TABINFOREF(Signal* signal){
- jamEntry();
- GetTabInfoRef* ref = (GetTabInfoRef*)signal->getDataPtr();
- Uint32 tableId = ref->tableId;
- Uint32 senderData = ref->senderData;
- GetTabInfoRef::ErrorCode errorCode =
- (GetTabInfoRef::ErrorCode) ref->errorCode;
- int do_resend_request = 0;
- TablePtr tabPtr;
- c_tablePool.getPtr(tabPtr, senderData);
- switch (errorCode)
- {
- case GetTabInfoRef::TableNotDefined:
- // wrong state
- break;
- case GetTabInfoRef::InvalidTableId:
- // no such table
- break;
- case GetTabInfoRef::Busy:
- do_resend_request = 1;
- break;
- case GetTabInfoRef::TableNameTooLong:
- ndbrequire(false);
- break;
- case GetTabInfoRef::NoFetchByName:
- break;
- }
- if (do_resend_request)
- {
- GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = senderData;
- req->requestType =
- GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
- req->tableId = tableId;
- sendSignalWithDelay(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
- 30, GetTabInfoReq::SignalLength);
- return;
- }
- tabPtr.p->m_state = Table::DROPPED;
- tabPtr.p->m_error = errorCode;
- completeAllSubscribers(signal, tabPtr);
- completeInitTable(signal, tabPtr);
-}
-
-void
-Suma::execGET_TABINFO_CONF(Signal* signal){
- jamEntry();
-
- CRASH_INSERTION(13006);
-
- if(!assembleFragments(signal)){
- return;
- }
-
- GetTabInfoConf* conf = (GetTabInfoConf*)signal->getDataPtr();
- Uint32 tableId = conf->tableId;
- TablePtr tabPtr;
- c_tablePool.getPtr(tabPtr, conf->senderData);
- SegmentedSectionPtr ptr(0,0,0);
- signal->getSection(ptr, GetTabInfoConf::DICT_TAB_INFO);
- ndbrequire(tabPtr.p->parseTable(ptr, *this));
- releaseSections(signal);
- /**
- * We need to gather fragment info
- */
- jam();
- DihFragCountReq* req = (DihFragCountReq*)signal->getDataPtrSend();
- req->m_connectionData = RNIL;
- req->m_tableRef = tableId;
- req->m_senderData = tabPtr.i;
- sendSignal(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
- DihFragCountReq::SignalLength, JBB);
-}
-
-bool
-Suma::Table::parseTable(SegmentedSectionPtr ptr,
- Suma &suma)
-{
- DBUG_ENTER("Suma::Table::parseTable");
-
- SimplePropertiesSectionReader it(ptr, suma.getSectionSegmentPool());
-
- SimpleProperties::UnpackStatus s;
- DictTabInfo::Table tableDesc; tableDesc.init();
- s = SimpleProperties::unpack(it, &tableDesc,
- DictTabInfo::TableMapping,
- DictTabInfo::TableMappingSize,
- true, true);
-
- jam();
- suma.suma_ndbrequire(s == SimpleProperties::Break);
-
-#if 0
-ToDo handle this
- if(m_schemaVersion != tableDesc.TableVersion){
- jam();
-
- release(* this);
-
- // oops wrong schema version in stored tabledesc
- // we need to find all subscriptions with old table desc
- // and all subscribers to this
- // hopefully none
- c_tables.release(tabPtr);
- DBUG_PRINT("info",("c_tablePool size: %d free: %d",
- suma.c_tablePool.getSize(),
- suma.c_tablePool.getNoOfFree()));
- tabPtr.setNull();
- DLHashTable<Suma::Subscription>::Iterator i_subPtr;
- c_subscriptions.first(i_subPtr);
- SubscriptionPtr subPtr;
- for(;!i_subPtr.isNull();c_subscriptions.next(i_subPtr)){
- jam();
- c_subscriptions.getPtr(subPtr, i_subPtr.curr.i);
- SyncRecord* tmp = c_syncPool.getPtr(subPtr.p->m_syncPtrI);
- if (tmp == syncPtr_p) {
- jam();
- continue;
- }
- if (subPtr.p->m_tables.get(tableId)) {
- jam();
- subPtr.p->m_tables.clear(tableId); // remove this old table reference
- TableList::DataBufferIterator it;
- for(tmp->m_tableList.first(it);!it.isNull();tmp->m_tableList.next(it)) {
- jam();
- if (*it.data == tableId){
- jam();
- Uint32 *pdata = it.data;
- tmp->m_tableList.next(it);
- for(;!it.isNull();tmp->m_tableList.next(it)) {
- jam();
- *pdata = *it.data;
- pdata = it.data;
- }
- *pdata = RNIL; // todo remove this last item...
- break;
- }
- }
- }
- }
- }
-#endif
-
- if(m_attributes.getSize() != 0){
- jam();
- DBUG_RETURN(true);
- }
-
- /**
- * Initialize table object
- */
- Uint32 noAttribs = tableDesc.NoOfAttributes;
- Uint32 notFixed = (tableDesc.NoOfNullable+tableDesc.NoOfVariable);
- m_schemaVersion = tableDesc.TableVersion;
-
- // The attribute buffer
- LocalDataBuffer<15> attrBuf(suma.c_dataBufferPool, m_attributes);
-
- // Temporary buffer
- DataBuffer<15> theRest(suma.c_dataBufferPool);
-
- if(!attrBuf.seize(noAttribs)){
- jam();
- suma.suma_ndbrequire(false);
- DBUG_RETURN(false);
- }
-
- if(!theRest.seize(notFixed)){
- jam();
- suma.suma_ndbrequire(false);
- DBUG_RETURN(false);
- }
-
- DataBuffer<15>::DataBufferIterator attrIt; // Fixed not nullable
- DataBuffer<15>::DataBufferIterator restIt; // variable + nullable
- attrBuf.first(attrIt);
- theRest.first(restIt);
-
- for(Uint32 i = 0; i < noAttribs; i++) {
- DictTabInfo::Attribute attrDesc; attrDesc.init();
- s = SimpleProperties::unpack(it, &attrDesc,
- DictTabInfo::AttributeMapping,
- DictTabInfo::AttributeMappingSize,
- true, true);
- jam();
- suma.suma_ndbrequire(s == SimpleProperties::Break);
-
- if (!attrDesc.AttributeNullableFlag
- /* && !attrDesc.AttributeVariableFlag */) {
- jam();
- * attrIt.data = attrDesc.AttributeId;
- attrBuf.next(attrIt);
- } else {
- jam();
- * restIt.data = attrDesc.AttributeId;
- theRest.next(restIt);
- }
-
- // Move to next attribute
- it.next();
- }
-
- /**
- * Put the rest in end of attrBuf
- */
- theRest.first(restIt);
- for(; !restIt.isNull(); theRest.next(restIt)){
- * attrIt.data = * restIt.data;
- attrBuf.next(attrIt);
- }
-
- theRest.release();
-
- DBUG_RETURN(true);
-}
-
-void
-Suma::execDI_FCOUNTREF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execDI_FCOUNTREF");
- DihFragCountRef * const ref = (DihFragCountRef*)signal->getDataPtr();
- switch ((DihFragCountRef::ErrorCode) ref->m_error)
- {
- case DihFragCountRef::ErroneousTableState:
- jam();
- if (ref->m_tableStatus == Dbdih::TabRecord::TS_CREATING)
- {
- const Uint32 tableId = ref->m_senderData;
- const Uint32 tabPtr_i = ref->m_tableRef;
- DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
-
- req->m_connectionData = RNIL;
- req->m_tableRef = tabPtr_i;
- req->m_senderData = tableId;
- sendSignalWithDelay(DBDIH_REF, GSN_DI_FCOUNTREQ, signal,
- DihFragCountReq::SignalLength,
- DihFragCountReq::RetryInterval);
- DBUG_VOID_RETURN;
- }
- ndbrequire(false);
- default:
- ndbrequire(false);
- }
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execDI_FCOUNTCONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execDI_FCOUNTCONF");
- ndbassert(signal->getNoOfSections() == 0);
- DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
- const Uint32 userPtr = conf->m_connectionData;
- const Uint32 fragCount = conf->m_fragmentCount;
- const Uint32 tableId = conf->m_tableRef;
-
- ndbrequire(userPtr == RNIL && signal->length() == 5);
-
- TablePtr tabPtr;
- tabPtr.i= conf->m_senderData;
- ndbrequire((tabPtr.p= c_tablePool.getPtr(tabPtr.i)) != 0);
- ndbrequire(tabPtr.p->m_tableId == tableId);
-
- LocalDataBuffer<15> fragBuf(c_dataBufferPool, tabPtr.p->m_fragments);
- ndbrequire(fragBuf.getSize() == 0);
-
- tabPtr.p->m_fragCount = fragCount;
-
- signal->theData[0] = RNIL;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = tableId;
- signal->theData[3] = 0; // Frag no
- sendSignal(DBDIH_REF, GSN_DIGETPRIMREQ, signal, 4, JBB);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execDIGETPRIMCONF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execDIGETPRIMCONF");
- ndbassert(signal->getNoOfSections() == 0);
-
- const Uint32 userPtr = signal->theData[0];
- const Uint32 nodeCount = signal->theData[6];
- const Uint32 tableId = signal->theData[7];
- const Uint32 fragNo = signal->theData[8];
-
- ndbrequire(userPtr == RNIL && signal->length() == 9);
- ndbrequire(nodeCount > 0 && nodeCount <= MAX_REPLICAS);
-
- TablePtr tabPtr;
- tabPtr.i= signal->theData[1];
- ndbrequire((tabPtr.p= c_tablePool.getPtr(tabPtr.i)) != 0);
- ndbrequire(tabPtr.p->m_tableId == tableId);
-
- {
- LocalDataBuffer<15> fragBuf(c_dataBufferPool,tabPtr.p->m_fragments);
-
- /**
- * Add primary node for fragment to list
- */
- FragmentDescriptor fd;
- fd.m_fragDesc.m_nodeId = signal->theData[2];
- fd.m_fragDesc.m_fragmentNo = fragNo;
- signal->theData[2] = fd.m_dummy;
- fragBuf.append(&signal->theData[2], 1);
- }
-
- const Uint32 nextFrag = fragNo + 1;
- if(nextFrag == tabPtr.p->m_fragCount)
- {
- /**
- * Complete frag info for table
- * table is not up to date
- */
-
- if (tabPtr.p->c_subscribers.isEmpty())
- {
- completeInitTable(signal,tabPtr);
- DBUG_VOID_RETURN;
- }
- tabPtr.p->setupTrigger(signal, *this);
- DBUG_VOID_RETURN;
- }
- signal->theData[0] = RNIL;
- signal->theData[1] = tabPtr.i;
- signal->theData[2] = tableId;
- signal->theData[3] = nextFrag; // Frag no
- sendSignal(DBDIH_REF, GSN_DIGETPRIMREQ, signal, 4, JBB);
-
- DBUG_VOID_RETURN;
-}
-
-#if 0
-void
-Suma::SyncRecord::completeTableInit(Signal* signal)
-{
- jam();
- SubscriptionPtr subPtr;
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
-
-#if PRINT_ONLY
- ndbout_c("GSN_SUB_SYNC_CONF (meta)");
-#else
-
- suma.releaseSections(signal);
-
- if (m_error) {
- SubSyncRef * const ref = (SubSyncRef*)signal->getDataPtrSend();
- ref->senderRef = suma.reference();
- ref->senderData = subPtr.p->m_senderData;
- ref->errorCode = SubSyncRef::Undefined;
- suma.sendSignal(subPtr.p->m_senderRef, GSN_SUB_SYNC_REF, signal,
- SubSyncRef::SignalLength, JBB);
- } else {
- SubSyncConf * const conf = (SubSyncConf*)signal->getDataPtrSend();
- conf->senderRef = suma.reference();
- conf->senderData = subPtr.p->m_senderData;
- suma.sendSignal(subPtr.p->m_senderRef, GSN_SUB_SYNC_CONF, signal,
- SubSyncConf::SignalLength, JBB);
- }
-#endif
-}
-#endif
-
-/**********************************************************
- *
- * Scan interface
- *
- */
-
-void
-Suma::SyncRecord::startScan(Signal* signal)
-{
- jam();
- DBUG_ENTER("Suma::SyncRecord::startScan");
-
- /**
- * Get fraginfo
- */
- m_currentTable = 0;
- m_currentFragment = 0;
- nextScan(signal);
- DBUG_VOID_RETURN;
-}
-
-bool
-Suma::SyncRecord::getNextFragment(TablePtr * tab,
- FragmentDescriptor * fd)
-{
- jam();
- SubscriptionPtr subPtr;
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
- TableList::DataBufferIterator tabIt;
- DataBuffer<15>::DataBufferIterator fragIt;
-
- m_tableList.position(tabIt, m_currentTable);
- for(; !tabIt.curr.isNull(); m_tableList.next(tabIt), m_currentTable++)
- {
- TablePtr tabPtr;
- ndbrequire(suma.c_tables.find(tabPtr, * tabIt.data));
- LocalDataBuffer<15> fragBuf(suma.c_dataBufferPool, tabPtr.p->m_fragments);
-
- fragBuf.position(fragIt, m_currentFragment);
- for(; !fragIt.curr.isNull(); fragBuf.next(fragIt), m_currentFragment++)
- {
- FragmentDescriptor tmp;
- tmp.m_dummy = * fragIt.data;
- if(tmp.m_fragDesc.m_nodeId == suma.getOwnNodeId()){
- * fd = tmp;
- * tab = tabPtr;
- return true;
- }
- }
- m_currentFragment = 0;
-
- tabPtr.p->n_subscribers--;
- DBUG_PRINT("info",("Suma::Table[%u]::n_subscribers: %u",
- tabPtr.p->m_tableId, tabPtr.p->n_subscribers));
- tabPtr.p->checkRelease(suma);
- }
- return false;
-}
-
-void
-Suma::SyncRecord::nextScan(Signal* signal)
-{
- jam();
- DBUG_ENTER("Suma::SyncRecord::nextScan");
- TablePtr tabPtr;
- FragmentDescriptor fd;
- SubscriptionPtr subPtr;
- if(!getNextFragment(&tabPtr, &fd)){
- jam();
- completeScan(signal);
- DBUG_VOID_RETURN;
- }
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
-
- DataBuffer<15>::Head head = m_attributeList;
- if(head.getSize() == 0){
- head = tabPtr.p->m_attributes;
- }
- LocalDataBuffer<15> attrBuf(suma.c_dataBufferPool, head);
-
- ScanFragReq * req = (ScanFragReq *)signal->getDataPtrSend();
- const Uint32 parallelism = 16;
- const Uint32 attrLen = 5 + attrBuf.getSize();
-
- req->senderData = ptrI;
- req->resultRef = suma.reference();
- req->tableId = tabPtr.p->m_tableId;
- req->requestInfo = 0;
- req->savePointId = 0;
- ScanFragReq::setLockMode(req->requestInfo, 0);
- ScanFragReq::setHoldLockFlag(req->requestInfo, 1);
- ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
- ScanFragReq::setAttrLen(req->requestInfo, attrLen);
- req->fragmentNoKeyLen = fd.m_fragDesc.m_fragmentNo;
- req->schemaVersion = tabPtr.p->m_schemaVersion;
- req->transId1 = 0;
- req->transId2 = (SUMA << 20) + (suma.getOwnNodeId() << 8);
- req->clientOpPtr = (ptrI << 16);
- req->batch_size_rows= parallelism;
- req->batch_size_bytes= 0;
- suma.sendSignal(DBLQH_REF, GSN_SCAN_FRAGREQ, signal,
- ScanFragReq::SignalLength, JBB);
-
- signal->theData[0] = ptrI;
- signal->theData[1] = 0;
- signal->theData[2] = (SUMA << 20) + (suma.getOwnNodeId() << 8);
-
- // Return all
- signal->theData[3] = attrBuf.getSize();
- signal->theData[4] = 0;
- signal->theData[5] = 0;
- signal->theData[6] = 0;
- signal->theData[7] = 0;
-
- Uint32 dataPos = 8;
- DataBuffer<15>::DataBufferIterator it;
- for(attrBuf.first(it); !it.curr.isNull(); attrBuf.next(it)){
- AttributeHeader::init(&signal->theData[dataPos++], * it.data, 0);
- if(dataPos == 25){
- suma.sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, 25, JBB);
- dataPos = 3;
- }
- }
- if(dataPos != 3){
- suma.sendSignal(DBLQH_REF, GSN_ATTRINFO, signal, dataPos, JBB);
- }
-
- m_currentTableId = tabPtr.p->m_tableId;
- m_currentNoOfAttributes = attrBuf.getSize();
-
- DBUG_VOID_RETURN;
-}
-
-
-void
-Suma::execSCAN_FRAGREF(Signal* signal){
- jamEntry();
-
-// ScanFragRef * const ref = (ScanFragRef*)signal->getDataPtr();
- ndbrequire(false);
-}
-
-void
-Suma::execSCAN_FRAGCONF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execSCAN_FRAGCONF");
- ndbassert(signal->getNoOfSections() == 0);
- CRASH_INSERTION(13011);
-
- ScanFragConf * const conf = (ScanFragConf*)signal->getDataPtr();
-
- const Uint32 completed = conf->fragmentCompleted;
- const Uint32 senderData = conf->senderData;
- const Uint32 completedOps = conf->completedOps;
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, senderData);
-
- if(completed != 2){
- jam();
-
-#if PRINT_ONLY
- SubSyncContinueConf * const conf =
- (SubSyncContinueConf*)signal->getDataPtrSend();
- conf->subscriptionId = subPtr.p->m_subscriptionId;
- conf->subscriptionKey = subPtr.p->m_subscriptionKey;
- execSUB_SYNC_CONTINUE_CONF(signal);
-#else
- SubSyncContinueReq * const req = (SubSyncContinueReq*)signal->getDataPtrSend();
- req->subscriberData = syncPtr.p->m_senderData;
- req->noOfRowsSent = completedOps;
- sendSignal(syncPtr.p->m_senderRef, GSN_SUB_SYNC_CONTINUE_REQ, signal,
- SubSyncContinueReq::SignalLength, JBB);
-#endif
- DBUG_VOID_RETURN;
- }
-
- ndbrequire(completedOps == 0);
-
- syncPtr.p->m_currentFragment++;
- syncPtr.p->nextScan(signal);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_SYNC_CONTINUE_CONF(Signal* signal){
- jamEntry();
- ndbassert(signal->getNoOfSections() == 0);
-
- CRASH_INSERTION(13012);
-
- SubSyncContinueConf * const conf =
- (SubSyncContinueConf*)signal->getDataPtr();
-
- SubscriptionPtr subPtr;
- Subscription key;
- key.m_subscriptionId = conf->subscriptionId;
- key.m_subscriptionKey = conf->subscriptionKey;
-
- ndbrequire(c_subscriptions.find(subPtr, key));
-
- ScanFragNextReq * req = (ScanFragNextReq *)signal->getDataPtrSend();
- req->senderData = subPtr.p->m_current_sync_ptrI;
- req->closeFlag = 0;
- req->transId1 = 0;
- req->transId2 = (SUMA << 20) + (getOwnNodeId() << 8);
- req->batch_size_rows = 16;
- req->batch_size_bytes = 0;
- sendSignal(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
-}
-
-void
-Suma::SyncRecord::completeScan(Signal* signal, int error)
-{
- jam();
- DBUG_ENTER("Suma::SyncRecord::completeScan");
- // m_tableList.release();
-
-#if PRINT_ONLY
- ndbout_c("GSN_SUB_SYNC_CONF (data)");
-#else
- if (error == 0)
- {
- SubSyncConf * const conf = (SubSyncConf*)signal->getDataPtrSend();
- conf->senderRef = suma.reference();
- conf->senderData = m_senderData;
- suma.sendSignal(m_senderRef, GSN_SUB_SYNC_CONF, signal,
- SubSyncConf::SignalLength, JBB);
- }
- else
- {
- SubSyncRef * const ref = (SubSyncRef*)signal->getDataPtrSend();
- ref->senderRef = suma.reference();
- ref->senderData = m_senderData;
- suma.sendSignal(m_senderRef, GSN_SUB_SYNC_REF, signal,
- SubSyncRef::SignalLength, JBB);
- }
-#endif
-
- release();
-
- Ptr<Subscription> subPtr;
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
- ndbrequire(subPtr.p->m_current_sync_ptrI == ptrI);
- subPtr.p->m_current_sync_ptrI = RNIL;
-
- suma.c_syncPool.release(ptrI);
- DBUG_PRINT("info",("c_syncPool size: %d free: %d",
- suma.c_syncPool.getSize(),
- suma.c_syncPool.getNoOfFree()));
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSCAN_HBREP(Signal* signal){
- jamEntry();
-#if 0
- ndbout << "execSCAN_HBREP" << endl << hex;
- for(int i = 0; i<signal->length(); i++){
- ndbout << signal->theData[i] << " ";
- if(((i + 1) % 8) == 0)
- ndbout << endl << hex;
- }
- ndbout << endl;
-#endif
-}
-
-/**********************************************************
- *
- * Suma participant interface
- *
- * Creation of subscriber
- *
- */
-
-void
-Suma::execSUB_START_REQ(Signal* signal){
- jamEntry();
- ndbassert(signal->getNoOfSections() == 0);
- DBUG_ENTER("Suma::execSUB_START_REQ");
- SubStartReq * const req = (SubStartReq*)signal->getDataPtr();
-
- CRASH_INSERTION(13013);
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- Uint32 subscriberData = req->subscriberData;
- Uint32 subscriberRef = req->subscriberRef;
- SubscriptionData::Part part = (SubscriptionData::Part)req->part;
-
- Subscription key;
- key.m_subscriptionId = req->subscriptionId;
- key.m_subscriptionKey = req->subscriptionKey;
-
- if (c_startup.m_restart_server_node_id &&
- senderRef != calcSumaBlockRef(c_startup.m_restart_server_node_id))
- {
- /**
- * only allow "restart_server" Suma's to come through
- * for restart purposes
- */
- jam();
- Uint32 err = c_startup.m_restart_server_node_id != RNIL ? 1405 :
- SubStartRef::NF_FakeErrorREF;
-
- sendSubStartRef(signal, err);
- DBUG_VOID_RETURN;
- }
-
- SubscriptionPtr subPtr;
- if(!c_subscriptions.find(subPtr, key)){
- jam();
- sendSubStartRef(signal, 1407);
- DBUG_VOID_RETURN;
- }
-
- if (subPtr.p->m_state == Subscription::LOCKED) {
- jam();
- DBUG_PRINT("info",("Locked"));
- sendSubStartRef(signal, 1411);
- DBUG_VOID_RETURN;
- }
-
- if (subPtr.p->m_state == Subscription::DROPPED &&
- c_startup.m_restart_server_node_id == 0) {
- jam();
- DBUG_PRINT("info",("Dropped"));
- sendSubStartRef(signal, 1418);
- DBUG_VOID_RETURN;
- }
-
- ndbrequire(subPtr.p->m_state == Subscription::DEFINED ||
- c_startup.m_restart_server_node_id);
-
- SubscriberPtr subbPtr;
- if(!c_subscriberPool.seize(subbPtr)){
- jam();
- sendSubStartRef(signal, 1412);
- DBUG_VOID_RETURN;
- }
-
- if (c_startup.m_restart_server_node_id == 0 &&
- !c_connected_nodes.get(refToNode(subscriberRef)))
-
- {
- jam();
- c_subscriberPool.release(subbPtr);
- sendSubStartRef(signal, SubStartRef::PartiallyConnected);
- DBUG_VOID_RETURN;
- }
-
- DBUG_PRINT("info",("c_subscriberPool size: %d free: %d",
- c_subscriberPool.getSize(),
- c_subscriberPool.getNoOfFree()));
-
- c_subscriber_nodes.set(refToNode(subscriberRef));
-
- // setup subscription record
- if (subPtr.p->m_state == Subscription::DEFINED)
- subPtr.p->m_state = Subscription::LOCKED;
- // store these here for later use
- subPtr.p->m_senderRef = senderRef;
- subPtr.p->m_senderData = senderData;
-
- // setup subscriber record
- subbPtr.p->m_senderRef = subscriberRef;
- subbPtr.p->m_senderData = subscriberData;
- subbPtr.p->m_subPtrI= subPtr.i;
-
- DBUG_PRINT("info",("subscriber: %u[%u,%u] subscription: %u[%u,%u] "
- "tableId: %u id: %u key: %u",
- subbPtr.i, subbPtr.p->m_senderRef, subbPtr.p->m_senderData,
- subPtr.i, subPtr.p->m_senderRef, subPtr.p->m_senderData,
- subPtr.p->m_tableId,
- subPtr.p->m_subscriptionId,subPtr.p->m_subscriptionKey));
-
- TablePtr tabPtr;
- switch(part){
- case SubscriptionData::MetaData:
- jam();
- c_metaSubscribers.add(subbPtr);
- sendSubStartComplete(signal, subbPtr, 0, part);
- DBUG_VOID_RETURN;
- case SubscriptionData::TableData:
- jam();
- initTable(signal,subPtr.p->m_tableId,tabPtr,subbPtr);
- tabPtr.p->n_subscribers++;
- if (subPtr.p->m_options & Subscription::REPORT_ALL)
- tabPtr.p->m_reportAll = true;
- DBUG_PRINT("info",("Suma::Table[%u]::n_subscribers: %u",
- tabPtr.p->m_tableId, tabPtr.p->n_subscribers));
- DBUG_VOID_RETURN;
- }
- ndbrequire(false);
-}
-
-void
-Suma::sendSubStartComplete(Signal* signal,
- SubscriberPtr subbPtr,
- Uint32 firstGCI,
- SubscriptionData::Part part)
-{
- jam();
- DBUG_ENTER("Suma::sendSubStartComplete");
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
- ndbrequire(subPtr.p->m_state == Subscription::LOCKED ||
- (subPtr.p->m_state == Subscription::DROPPED &&
- c_startup.m_restart_server_node_id));
- if (subPtr.p->m_state == Subscription::LOCKED)
- {
- jam();
- subPtr.p->m_state = Subscription::DEFINED;
- }
- subPtr.p->n_subscribers++;
-
- DBUG_PRINT("info",("subscriber: %u[%u,%u] subscription: %u[%u,%u] "
- "tableId: %u[i=%u] id: %u key: %u",
- subbPtr.i, subbPtr.p->m_senderRef, subbPtr.p->m_senderData,
- subPtr.i, subPtr.p->m_senderRef, subPtr.p->m_senderData,
- subPtr.p->m_tableId, subPtr.p->m_table_ptrI,
- subPtr.p->m_subscriptionId,subPtr.p->m_subscriptionKey));
-
- SubStartConf * const conf = (SubStartConf*)signal->getDataPtrSend();
-
- conf->senderRef = reference();
- conf->senderData = subPtr.p->m_senderData;
- conf->subscriptionId = subPtr.p->m_subscriptionId;
- conf->subscriptionKey = subPtr.p->m_subscriptionKey;
- conf->firstGCI = firstGCI;
- conf->part = (Uint32) part;
-
- DBUG_PRINT("info",("subscriber: %u id: %u key: %u", subbPtr.i,
- subPtr.p->m_subscriptionId,subPtr.p->m_subscriptionKey));
- sendSignal(subPtr.p->m_senderRef, GSN_SUB_START_CONF, signal,
- SubStartConf::SignalLength, JBB);
-
- reportAllSubscribers(signal, NdbDictionary::Event::_TE_SUBSCRIBE,
- subPtr, subbPtr);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::sendSubStartRef(Signal* signal, Uint32 errCode)
-{
- jam();
- SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = errCode;
- releaseSections(signal);
- sendSignal(signal->getSendersBlockRef(), GSN_SUB_START_REF, signal,
- SubStartRef::SignalLength, JBB);
-}
-void
-Suma::sendSubStartRef(Signal* signal,
- SubscriberPtr subbPtr, Uint32 error,
- SubscriptionData::Part part)
-{
- jam();
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
-
- ndbrequire(subPtr.p->m_state == Subscription::LOCKED ||
- (subPtr.p->m_state == Subscription::DROPPED &&
- c_startup.m_restart_server_node_id));
- if (subPtr.p->m_state == Subscription::LOCKED)
- {
- jam();
- subPtr.p->m_state = Subscription::DEFINED;
- }
-
- SubStartRef * ref= (SubStartRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = subPtr.p->m_senderData;
- ref->subscriptionId = subPtr.p->m_subscriptionId;
- ref->subscriptionKey = subPtr.p->m_subscriptionKey;
- ref->part = (Uint32) part;
- ref->errorCode = error;
-
- sendSignal(subPtr.p->m_senderRef, GSN_SUB_START_REF, signal,
- SubStartRef::SignalLength, JBB);
-}
-
-/**********************************************************
- * Suma participant interface
- *
- * Stopping and removing of subscriber
- *
- */
-
-void
-Suma::execSUB_STOP_REQ(Signal* signal){
- jamEntry();
- ndbassert(signal->getNoOfSections() == 0);
- DBUG_ENTER("Suma::execSUB_STOP_REQ");
-
- CRASH_INSERTION(13019);
-
- SubStopReq * const req = (SubStopReq*)signal->getDataPtr();
- Uint32 senderRef = req->senderRef;
- 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(senderRef));
- DBUG_VOID_RETURN;
- }
-
- if (c_startup.m_restart_server_node_id &&
- senderRef != calcSumaBlockRef(c_startup.m_restart_server_node_id))
- {
- /**
- * only allow "restart_server" Suma's to come through
- * for restart purposes
- */
- jam();
- Uint32 err = c_startup.m_restart_server_node_id != RNIL ? 1405 :
- SubStopRef::NF_FakeErrorREF;
-
- sendSubStopRef(signal, err);
- DBUG_VOID_RETURN;
- }
-
- if(!c_subscriptions.find(subPtr, key)){
- jam();
- DBUG_PRINT("error", ("not found"));
- sendSubStopRef(signal, 1407);
- DBUG_VOID_RETURN;
- }
-
- if (subPtr.p->m_state == Subscription::LOCKED) {
- jam();
- DBUG_PRINT("error", ("locked"));
- sendSubStopRef(signal, 1411);
- DBUG_VOID_RETURN;
- }
-
- ndbrequire(part == SubscriptionData::TableData);
-
- TablePtr tabPtr;
- tabPtr.i = subPtr.p->m_table_ptrI;
- if (tabPtr.i == RNIL ||
- !(tabPtr.p = c_tables.getPtr(tabPtr.i)) ||
- tabPtr.p->m_tableId != subPtr.p->m_tableId)
- {
- jam();
- DBUG_PRINT("error", ("no such table id %u[i=%u]",
- subPtr.p->m_tableId, subPtr.p->m_table_ptrI));
- sendSubStopRef(signal, 1417);
- DBUG_VOID_RETURN;
- }
-
- if (tabPtr.p->m_drop_subbPtr.p != 0) {
- jam();
- DBUG_PRINT("error", ("table locked"));
- sendSubStopRef(signal, 1420);
- DBUG_VOID_RETURN;
- }
-
- DBUG_PRINT("info",("subscription: %u tableId: %u[i=%u] id: %u key: %u",
- subPtr.i, subPtr.p->m_tableId, tabPtr.i,
- subPtr.p->m_subscriptionId,subPtr.p->m_subscriptionKey));
-
- SubscriberPtr subbPtr;
- if (senderRef == reference()){
- jam();
- c_subscriberPool.getPtr(subbPtr, senderData);
- ndbrequire(subbPtr.p->m_subPtrI == subPtr.i &&
- subbPtr.p->m_senderRef == subscriberRef &&
- subbPtr.p->m_senderData == subscriberData);
- c_removeDataSubscribers.remove(subbPtr);
- }
- else
- {
- jam();
- LocalDLList<Subscriber>
- subscribers(c_subscriberPool,tabPtr.p->c_subscribers);
-
- DBUG_PRINT("info",("search: subscription: %u, ref: %u, data: %d",
- subPtr.i, subscriberRef, subscriberData));
- for (subscribers.first(subbPtr);!subbPtr.isNull();subscribers.next(subbPtr))
- {
- jam();
- DBUG_PRINT("info",
- ("search: subscription: %u, ref: %u, data: %u, subscriber %u",
- subbPtr.p->m_subPtrI, subbPtr.p->m_senderRef,
- subbPtr.p->m_senderData, subbPtr.i));
- if (subbPtr.p->m_subPtrI == subPtr.i &&
- subbPtr.p->m_senderRef == subscriberRef &&
- subbPtr.p->m_senderData == subscriberData)
- {
- jam();
- DBUG_PRINT("info",("found"));
- break;
- }
- }
- /**
- * If we didn't find anyone, send ref
- */
- if (subbPtr.isNull()) {
- jam();
- DBUG_PRINT("error", ("subscriber not found"));
- sendSubStopRef(signal, 1407);
- DBUG_VOID_RETURN;
- }
- subscribers.remove(subbPtr);
- }
-
- subPtr.p->m_senderRef = senderRef; // store ref to requestor
- subPtr.p->m_senderData = senderData; // store ref to requestor
-
- tabPtr.p->m_drop_subbPtr = subbPtr;
-
- if (subPtr.p->m_state == Subscription::DEFINED)
- {
- jam();
- subPtr.p->m_state = Subscription::LOCKED;
- }
-
- if (tabPtr.p->m_state == Table::DROPPED)
- // not ALTERED here since trigger must be removed
- {
- jam();
- tabPtr.p->n_subscribers--;
- DBUG_PRINT("info",("Suma::Table[%u]::n_subscribers: %u",
- tabPtr.p->m_tableId, tabPtr.p->n_subscribers));
- tabPtr.p->checkRelease(*this);
- sendSubStopComplete(signal, tabPtr.p->m_drop_subbPtr);
- tabPtr.p->m_drop_subbPtr.p = 0;
- }
- else
- {
- jam();
- tabPtr.p->dropTrigger(signal,*this);
- }
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::sendSubStopComplete(Signal* signal, SubscriberPtr subbPtr)
-{
- jam();
- DBUG_ENTER("Suma::sendSubStopComplete");
- CRASH_INSERTION(13020);
-
- DBUG_PRINT("info",("removed subscriber: %i", subbPtr.i));
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
-
- Uint32 senderRef= subPtr.p->m_senderRef;
- Uint32 senderData= subPtr.p->m_senderData;
-
- subPtr.p->n_subscribers--;
- ndbassert( subPtr.p->m_state == Subscription::LOCKED ||
- subPtr.p->m_state == Subscription::DROPPED );
- if ( subPtr.p->m_state == Subscription::LOCKED )
- {
- jam();
- subPtr.p->m_state = Subscription::DEFINED;
- if (subPtr.p->n_subscribers == 0)
- {
- jam();
-#if 1
- subPtr.p->m_table_ptrI = RNIL;
-#else
- TablePtr tabPtr;
- tabPtr.i = subPtr.p->m_table_ptrI;
- if ((tabPtr.p= c_tablePool.getPtr(tabPtr.i)) &&
- (tabPtr.p->m_state == Table::DROPPED ||
- tabPtr.p->m_state == Table::ALTERED) &&
- false)
- {
- // last subscriber, and table is dropped
- // safe to drop subscription
- c_subscriptions.release(subPtr);
- DBUG_PRINT("info",("c_subscriptionPool size: %d free: %d",
- c_subscriptionPool.getSize(),
- c_subscriptionPool.getNoOfFree()));
- }
- else
- {
- subPtr.p->m_table_ptrI = RNIL;
- }
- ndbassert(tabPtr.p != 0);
-#endif
- }
- }
- else if ( subPtr.p->n_subscribers == 0 )
- {
- // subscription is marked to be removed
- // and there are no subscribers left
- jam();
- ndbassert(subPtr.p->m_state == Subscription::DROPPED);
- completeSubRemove(subPtr);
- }
-
- // let subscriber know that subscrber is stopped
- {
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();
- data->gci = m_last_complete_gci + 1; // XXX ???
- data->tableId = 0;
- data->requestInfo = 0;
- SubTableData::setOperation(data->requestInfo,
- NdbDictionary::Event::_TE_STOP);
- SubTableData::setNdbdNodeId(data->requestInfo,
- getOwnNodeId());
- data->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB);
- }
-
- SubStopConf * const conf = (SubStopConf*)signal->getDataPtrSend();
-
- conf->senderRef= reference();
- conf->senderData= senderData;
-
- sendSignal(senderRef, GSN_SUB_STOP_CONF, signal,
- SubStopConf::SignalLength, JBB);
-
- c_subscriberPool.release(subbPtr);
- DBUG_PRINT("info",("c_subscriberPool size: %d free: %d",
- c_subscriberPool.getSize(),
- c_subscriberPool.getNoOfFree()));
-
- reportAllSubscribers(signal, NdbDictionary::Event::_TE_UNSUBSCRIBE,
- subPtr, subbPtr);
-
- DBUG_VOID_RETURN;
-}
-
-// report new started subscriber to all other subscribers
-void
-Suma::reportAllSubscribers(Signal *signal,
- NdbDictionary::Event::_TableEvent table_event,
- SubscriptionPtr subPtr,
- SubscriberPtr subbPtr)
-{
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();
-
- if (table_event == NdbDictionary::Event::_TE_SUBSCRIBE &&
- !c_startup.m_restart_server_node_id)
- {
- data->gci = m_last_complete_gci + 1;
- data->tableId = subPtr.p->m_tableId;
- data->requestInfo = 0;
- SubTableData::setOperation(data->requestInfo,
- NdbDictionary::Event::_TE_ACTIVE);
- SubTableData::setNdbdNodeId(data->requestInfo, getOwnNodeId());
- SubTableData::setReqNodeId(data->requestInfo,
- refToNode(subbPtr.p->m_senderRef));
- data->changeMask = 0;
- data->totalLen = 0;
- data->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB);
- }
-
- if (!(subPtr.p->m_options & Subscription::REPORT_SUBSCRIBE))
- {
- return;
- }
- if (subPtr.p->n_subscribers == 0)
- {
- ndbrequire(table_event != NdbDictionary::Event::_TE_SUBSCRIBE);
- return;
- }
-
-//#ifdef VM_TRACE
- ndbout_c("reportAllSubscribers subPtr.i: %d subPtr.p->n_subscribers: %d",
- subPtr.i, subPtr.p->n_subscribers);
-//#endif
- data->gci = m_last_complete_gci + 1;
- data->tableId = subPtr.p->m_tableId;
- data->requestInfo = 0;
- SubTableData::setOperation(data->requestInfo, table_event);
- SubTableData::setNdbdNodeId(data->requestInfo, getOwnNodeId());
- data->changeMask = 0;
- data->totalLen = 0;
-
- TablePtr tabPtr;
- c_tables.getPtr(tabPtr, subPtr.p->m_table_ptrI);
- LocalDLList<Subscriber> subbs(c_subscriberPool, tabPtr.p->c_subscribers);
- SubscriberPtr i_subbPtr;
- for(subbs.first(i_subbPtr); !i_subbPtr.isNull(); subbs.next(i_subbPtr))
- {
- if (i_subbPtr.p->m_subPtrI == subPtr.i)
- {
- SubTableData::setReqNodeId(data->requestInfo,
- refToNode(subbPtr.p->m_senderRef));
- data->senderData = i_subbPtr.p->m_senderData;
- sendSignal(i_subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB);
-//#ifdef VM_TRACE
- ndbout_c("sent %s(%d) to node %d, req_nodeid: %d senderData: %d",
- table_event == NdbDictionary::Event::_TE_SUBSCRIBE ?
- "SUBSCRIBE" : "UNSUBSCRIBE", (int) table_event,
- refToNode(i_subbPtr.p->m_senderRef),
- refToNode(subbPtr.p->m_senderRef), data->senderData
- );
-//#endif
- if (i_subbPtr.i != subbPtr.i)
- {
- SubTableData::setReqNodeId(data->requestInfo,
- refToNode(i_subbPtr.p->m_senderRef));
-
- data->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB);
-//#ifdef VM_TRACE
- ndbout_c("sent %s(%d) to node %d, req_nodeid: %d senderData: %d",
- table_event == NdbDictionary::Event::_TE_SUBSCRIBE ?
- "SUBSCRIBE" : "UNSUBSCRIBE", (int) table_event,
- refToNode(subbPtr.p->m_senderRef),
- refToNode(i_subbPtr.p->m_senderRef), data->senderData
- );
-//#endif
- }
- }
- }
-}
-
-void
-Suma::sendSubStopRef(Signal* signal, Uint32 errCode)
-{
- jam();
- DBUG_ENTER("Suma::sendSubStopRef");
- SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = errCode;
- sendSignal(signal->getSendersBlockRef(),
- GSN_SUB_STOP_REF,
- signal,
- SubStopRef::SignalLength,
- JBB);
- DBUG_VOID_RETURN;
-}
-
-/**********************************************************
- *
- * Trigger admin interface
- *
- */
-
-int
-Suma::Table::setupTrigger(Signal* signal,
- Suma &suma)
-{
- jam();
- DBUG_ENTER("Suma::Table::setupTrigger");
-
- int ret= 0;
-
- AttributeMask attrMask;
- createAttributeMask(attrMask, suma);
-
- for(Uint32 j = 0; j<3; j++)
- {
- Uint32 triggerId = (m_schemaVersion << 18) | (j << 16) | m_ptrI;
- if(m_hasTriggerDefined[j] == 0)
- {
- suma.suma_ndbrequire(m_triggerIds[j] == ILLEGAL_TRIGGER_ID);
- DBUG_PRINT("info",("DEFINING trigger on table %u[%u]", m_tableId, j));
- CreateTrigReq * const req = (CreateTrigReq*)signal->getDataPtrSend();
- req->setUserRef(SUMA_REF);
- req->setConnectionPtr(m_ptrI);
- req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE);
- req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
- req->setMonitorReplicas(true);
- req->setMonitorAllAttributes(j == TriggerEvent::TE_DELETE);
- req->setReceiverRef(SUMA_REF);
- req->setTriggerId(triggerId);
- req->setTriggerEvent((TriggerEvent::Value)j);
- req->setTableId(m_tableId);
- req->setAttributeMask(attrMask);
- req->setReportAllMonitoredAttributes(m_reportAll);
- suma.sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB);
- ret= 1;
- }
- else
- {
- m_hasTriggerDefined[j]++;
- DBUG_PRINT("info",("REFCOUNT trigger on table %u[%u] %u",
- m_tableId, j, m_hasTriggerDefined[j]));
- }
- }
- DBUG_RETURN(ret);
-}
-
-void
-Suma::Table::createAttributeMask(AttributeMask& mask,
- Suma &suma)
-{
- jam();
- mask.clear();
- DataBuffer<15>::DataBufferIterator it;
- LocalDataBuffer<15> attrBuf(suma.c_dataBufferPool, m_attributes);
- for(attrBuf.first(it); !it.curr.isNull(); attrBuf.next(it)){
- mask.set(* it.data);
- }
-}
-
-void
-Suma::execCREATE_TRIG_CONF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execCREATE_TRIG_CONF");
- ndbassert(signal->getNoOfSections() == 0);
- CreateTrigConf * const conf = (CreateTrigConf*)signal->getDataPtr();
- const Uint32 triggerId = conf->getTriggerId();
- Uint32 type = (triggerId >> 16) & 0x3;
- Uint32 tableId = conf->getTableId();
-
-
- DBUG_PRINT("enter", ("type: %u tableId: %u[i=%u==%u]",
- type, tableId,conf->getConnectionPtr(),triggerId & 0xFFFF));
-
- TablePtr tabPtr;
- c_tables.getPtr(tabPtr, conf->getConnectionPtr());
- ndbrequire(tabPtr.p->m_tableId == tableId);
- ndbrequire(tabPtr.p->m_state == Table::DEFINING);
-
- ndbrequire(type < 3);
- tabPtr.p->m_triggerIds[type] = triggerId;
- ndbrequire(tabPtr.p->m_hasTriggerDefined[type] == 0);
- tabPtr.p->m_hasTriggerDefined[type] = 1;
-
- if (type == 2)
- {
- completeAllSubscribers(signal, tabPtr);
- completeInitTable(signal,tabPtr);
- DBUG_VOID_RETURN;
- }
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execCREATE_TRIG_REF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execCREATE_TRIG_REF");
- ndbassert(signal->getNoOfSections() == 0);
- CreateTrigRef * const ref = (CreateTrigRef*)signal->getDataPtr();
- const Uint32 triggerId = ref->getTriggerId();
- Uint32 type = (triggerId >> 16) & 0x3;
- Uint32 tableId = ref->getTableId();
-
- DBUG_PRINT("enter", ("type: %u tableId: %u[i=%u==%u]",
- type, tableId,ref->getConnectionPtr(),triggerId & 0xFFFF));
-
- TablePtr tabPtr;
- c_tables.getPtr(tabPtr, ref->getConnectionPtr());
- ndbrequire(tabPtr.p->m_tableId == tableId);
- ndbrequire(tabPtr.p->m_state == Table::DEFINING);
-
- tabPtr.p->m_error= ref->getErrorCode();
-
- ndbrequire(type < 3);
-
- if (type == 2)
- {
- completeAllSubscribers(signal, tabPtr);
- completeInitTable(signal,tabPtr);
- DBUG_VOID_RETURN;
- }
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Table::dropTrigger(Signal* signal,Suma& suma)
-{
- jam();
- DBUG_ENTER("Suma::dropTrigger");
-
- m_hasOutstandingTriggerReq[0] =
- m_hasOutstandingTriggerReq[1] =
- m_hasOutstandingTriggerReq[2] = 1;
- for(Uint32 j = 0; j<3; j++){
- jam();
- suma.suma_ndbrequire(m_triggerIds[j] != ILLEGAL_TRIGGER_ID);
- if(m_hasTriggerDefined[j] == 1) {
- jam();
-
- DropTrigReq * const req = (DropTrigReq*)signal->getDataPtrSend();
- req->setConnectionPtr(m_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(m_tableId);
- req->setTriggerId(m_triggerIds[j]);
- req->setTriggerEvent((TriggerEvent::Value)j);
-
- DBUG_PRINT("info",("DROPPING trigger %u = %u %u %u on table %u[%u]",
- m_triggerIds[j],
- TriggerType::SUBSCRIPTION_BEFORE,
- TriggerActionTime::TA_DETACHED,
- j,
- m_tableId, j));
- suma.sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- } else {
- jam();
- suma.suma_ndbrequire(m_hasTriggerDefined[j] > 1);
- runDropTrigger(signal,m_triggerIds[j],suma);
- }
- }
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execDROP_TRIG_REF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execDROP_TRIG_REF");
- ndbassert(signal->getNoOfSections() == 0);
- DropTrigRef * const ref = (DropTrigRef*)signal->getDataPtr();
- if (ref->getErrorCode() != DropTrigRef::TriggerNotFound)
- {
- ndbrequire(false);
- }
- TablePtr tabPtr;
- c_tables.getPtr(tabPtr, ref->getConnectionPtr());
- ndbrequire(ref->getTableId() == tabPtr.p->m_tableId);
-
- tabPtr.p->runDropTrigger(signal, ref->getTriggerId(), *this);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execDROP_TRIG_CONF(Signal* signal){
- jamEntry();
- DBUG_ENTER("Suma::execDROP_TRIG_CONF");
- ndbassert(signal->getNoOfSections() == 0);
-
- DropTrigConf * const conf = (DropTrigConf*)signal->getDataPtr();
- TablePtr tabPtr;
- c_tables.getPtr(tabPtr, conf->getConnectionPtr());
- ndbrequire(conf->getTableId() == tabPtr.p->m_tableId);
-
- tabPtr.p->runDropTrigger(signal, conf->getTriggerId(),*this);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Table::runDropTrigger(Signal* signal,
- Uint32 triggerId,
- Suma &suma)
-{
- jam();
- Uint32 type = (triggerId >> 16) & 0x3;
-
- suma.suma_ndbrequire(type < 3);
- suma.suma_ndbrequire(m_triggerIds[type] == triggerId);
- suma.suma_ndbrequire(m_hasTriggerDefined[type] > 0);
- suma.suma_ndbrequire(m_hasOutstandingTriggerReq[type] == 1);
- m_hasTriggerDefined[type]--;
- m_hasOutstandingTriggerReq[type] = 0;
- if (m_hasTriggerDefined[type] == 0)
- {
- jam();
- m_triggerIds[type] = ILLEGAL_TRIGGER_ID;
- }
- if( m_hasOutstandingTriggerReq[0] ||
- m_hasOutstandingTriggerReq[1] ||
- m_hasOutstandingTriggerReq[2])
- {
- // more to come
- jam();
- return;
- }
-
-#if 0
- ndbout_c("trigger completed");
-#endif
-
-
- n_subscribers--;
- DBUG_PRINT("info",("Suma::Table[%u]::n_subscribers: %u",
- m_tableId, n_subscribers));
- checkRelease(suma);
-
- suma.sendSubStopComplete(signal, m_drop_subbPtr);
- m_drop_subbPtr.p = 0;
-}
-
-void Suma::suma_ndbrequire(bool v) { ndbrequire(v); }
-
-void
-Suma::Table::checkRelease(Suma &suma)
-{
- jam();
- DBUG_ENTER("Suma::Table::checkRelease");
- if (n_subscribers == 0)
- {
- jam();
- suma.suma_ndbrequire(m_hasTriggerDefined[0] == 0);
- suma.suma_ndbrequire(m_hasTriggerDefined[1] == 0);
- suma.suma_ndbrequire(m_hasTriggerDefined[2] == 0);
- if (!c_subscribers.isEmpty())
- {
- LocalDLList<Subscriber>
- subscribers(suma.c_subscriberPool,c_subscribers);
- SubscriberPtr subbPtr;
- for (subscribers.first(subbPtr);!subbPtr.isNull();
- subscribers.next(subbPtr))
- {
- jam();
- DBUG_PRINT("info",("subscriber: %u", subbPtr.i));
- }
- suma.suma_ndbrequire(false);
- }
- if (!c_syncRecords.isEmpty())
- {
- LocalDLList<SyncRecord>
- syncRecords(suma.c_syncPool,c_syncRecords);
- Ptr<SyncRecord> syncPtr;
- for (syncRecords.first(syncPtr);!syncPtr.isNull();
- syncRecords.next(syncPtr))
- {
- jam();
- DBUG_PRINT("info",("syncRecord: %u", syncPtr.i));
- }
- suma.suma_ndbrequire(false);
- }
- release(suma);
- suma.c_tables.remove(m_ptrI);
- suma.c_tablePool.release(m_ptrI);
- DBUG_PRINT("info",("c_tablePool size: %d free: %d",
- suma.c_tablePool.getSize(),
- suma.c_tablePool.getNoOfFree()));
- }
- else
- {
- DBUG_PRINT("info",("n_subscribers: %d", n_subscribers));
- }
- DBUG_VOID_RETURN;
-}
-
-/**********************************************************
- * Scan data interface
- *
- * Assumption: one execTRANSID_AI contains all attr info
- *
- */
-
-#define SUMA_BUF_SZ1 MAX_KEY_SIZE_IN_WORDS + MAX_TUPLE_SIZE_IN_WORDS
-#define SUMA_BUF_SZ MAX_ATTRIBUTES_IN_TABLE + SUMA_BUF_SZ1
-
-static Uint32 f_bufferLock = 0;
-static Uint32 f_buffer[SUMA_BUF_SZ];
-static Uint32 f_trigBufferSize = 0;
-static Uint32 b_bufferLock = 0;
-static Uint32 b_buffer[SUMA_BUF_SZ];
-static Uint32 b_trigBufferSize = 0;
-
-void
-Suma::execTRANSID_AI(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execTRANSID_AI");
-
- CRASH_INSERTION(13015);
- TransIdAI * const data = (TransIdAI*)signal->getDataPtr();
- const Uint32 opPtrI = data->connectPtr;
- const Uint32 length = signal->length() - 3;
-
- if(f_bufferLock == 0){
- f_bufferLock = opPtrI;
- } else {
- ndbrequire(f_bufferLock == opPtrI);
- }
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, (opPtrI >> 16));
-
- Uint32 sum = 0;
- Uint32 * dst = f_buffer + MAX_ATTRIBUTES_IN_TABLE;
- Uint32 * headers = f_buffer;
- const Uint32 * src = &data->attrData[0];
- const Uint32 * const end = &src[length];
-
- const Uint32 attribs = syncPtr.p->m_currentNoOfAttributes;
- for(Uint32 i = 0; i<attribs; i++){
- Uint32 tmp = * src++;
- * headers++ = tmp;
- Uint32 len = AttributeHeader::getDataSize(tmp);
-
- memcpy(dst, src, 4 * len);
- dst += len;
- src += len;
- sum += len;
- }
-
- ndbrequire(src == end);
-
- /**
- * Send data to subscriber
- */
- LinearSectionPtr ptr[3];
- ptr[0].p = f_buffer;
- ptr[0].sz = attribs;
-
- ptr[1].p = f_buffer + MAX_ATTRIBUTES_IN_TABLE;
- ptr[1].sz = sum;
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, syncPtr.p->m_subscriptionPtrI);
-
- /**
- * Initialize signal
- */
- SubTableData * sdata = (SubTableData*)signal->getDataPtrSend();
- Uint32 ref = subPtr.p->m_senderRef;
- sdata->tableId = syncPtr.p->m_currentTableId;
- sdata->senderData = subPtr.p->m_senderData;
- sdata->requestInfo = 0;
- SubTableData::setOperation(sdata->requestInfo,
- NdbDictionary::Event::_TE_SCAN); // Scan
- sdata->gci = 0; // Undefined
-#if PRINT_ONLY
- ndbout_c("GSN_SUB_TABLE_DATA (scan) #attr: %d len: %d", attribs, sum);
-#else
- sendSignal(ref,
- GSN_SUB_TABLE_DATA,
- signal,
- SubTableData::SignalLength, JBB,
- ptr, 2);
-#endif
-
- /**
- * Reset f_bufferLock
- */
- f_bufferLock = 0;
-
- DBUG_VOID_RETURN;
-}
-
-/**********************************************************
- *
- * Trigger data interface
- *
- */
-
-void
-Suma::execTRIG_ATTRINFO(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execTRIG_ATTRINFO");
-
- 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;
- }
-
-
- DBUG_VOID_RETURN;
-}
-
-#ifdef NODEFAIL_DEBUG2
-static int theCounts[64] = {0};
-#endif
-
-Uint32
-Suma::get_responsible_node(Uint32 bucket) const
-{
- // id will contain id to responsible suma or
- // RNIL if we don't have nodegroup info yet
-
- jam();
- Uint32 node;
- const Bucket* ptr= c_buckets + bucket;
- for(Uint32 i = 0; i<MAX_REPLICAS; i++)
- {
- node= ptr->m_nodes[i];
- if(c_alive_nodes.get(node))
- {
- break;
- }
- }
-
-
-#ifdef NODEFAIL_DEBUG2
- if(node != 0)
- {
- theCounts[node]++;
- ndbout_c("Suma:responsible n=%u, D=%u, id = %u, count=%u",
- n,D, id, theCounts[node]);
- }
-#endif
- return node;
-}
-
-Uint32
-Suma::get_responsible_node(Uint32 bucket, const NdbNodeBitmask& mask) const
-{
- jam();
- Uint32 node;
- const Bucket* ptr= c_buckets + bucket;
- for(Uint32 i = 0; i<MAX_REPLICAS; i++)
- {
- node= ptr->m_nodes[i];
- if(mask.get(node))
- {
- return node;
- }
- }
-
- return 0;
-}
-
-bool
-Suma::check_switchover(Uint32 bucket, Uint32 gci)
-{
- const Uint32 send_mask = (Bucket::BUCKET_STARTING | Bucket::BUCKET_TAKEOVER);
- bool send = c_buckets[bucket].m_state & send_mask;
- ndbassert(m_switchover_buckets.get(bucket));
- if(unlikely(gci >= c_buckets[bucket].m_switchover_gci))
- {
- return send;
- }
- return !send;
-}
-
-static
-Uint32
-reformat(Signal* signal, LinearSectionPtr ptr[3],
- Uint32 * src_1, Uint32 sz_1,
- Uint32 * src_2, Uint32 sz_2)
-{
- Uint32 noOfAttrs = 0, dataLen = 0;
- Uint32 * headers = signal->theData + 25;
- Uint32 * dst = signal->theData + 25 + MAX_ATTRIBUTES_IN_TABLE;
-
- ptr[0].p = headers;
- ptr[1].p = dst;
-
- while(sz_1 > 0){
- jam();
- Uint32 tmp = * src_1 ++;
- * headers ++ = tmp;
- Uint32 len = AttributeHeader::getDataSize(tmp);
- memcpy(dst, src_1, 4 * len);
- dst += len;
- src_1 += len;
-
- noOfAttrs++;
- dataLen += len;
- sz_1 -= (1 + len);
- }
- assert(sz_1 == 0);
-
- ptr[0].sz = noOfAttrs;
- ptr[1].sz = dataLen;
-
- ptr[2].p = src_2;
- ptr[2].sz = sz_2;
-
- return sz_2 > 0 ? 3 : 2;
-}
-
-void
-Suma::execFIRE_TRIG_ORD(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execFIRE_TRIG_ORD");
- ndbassert(signal->getNoOfSections() == 0);
-
- 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 any_value = trg->getAnyValue();
- TablePtr tabPtr;
- tabPtr.i = trigId & 0xFFFF;
-
- DBUG_PRINT("enter",("tabPtr.i=%u", tabPtr.i));
- ndbrequire(f_bufferLock == trigId);
- /**
- * Reset f_bufferLock
- */
- f_bufferLock = 0;
- b_bufferLock = 0;
-
- ndbrequire((tabPtr.p = c_tablePool.getPtr(tabPtr.i)) != 0);
- Uint32 tableId = tabPtr.p->m_tableId;
-
- Uint32 bucket= hashValue % c_no_of_buckets;
- m_max_seen_gci = (gci > m_max_seen_gci ? gci : m_max_seen_gci);
- if(m_active_buckets.get(bucket) ||
- (m_switchover_buckets.get(bucket) && (check_switchover(bucket, gci))))
- {
- m_max_sent_gci = (gci > m_max_sent_gci ? gci : m_max_sent_gci);
- Uint32 sz = trg->getNoOfPrimaryKeyWords()+trg->getNoOfAfterValueWords();
- ndbrequire(sz == f_trigBufferSize);
-
- LinearSectionPtr ptr[3];
- const Uint32 nptr= reformat(signal, ptr,
- f_buffer, sz, b_buffer, b_trigBufferSize);
- Uint32 ptrLen= 0;
- for(Uint32 i =0; i < nptr; i++)
- ptrLen+= ptr[i].sz;
- /**
- * Signal to subscriber(s)
- */
- ndbrequire((tabPtr.p = c_tablePool.getPtr(tabPtr.i)) != 0);
-
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg;
- data->gci = gci;
- data->tableId = tableId;
- data->requestInfo = 0;
- SubTableData::setOperation(data->requestInfo, event);
- data->logType = 0;
- data->anyValue = any_value;
- data->totalLen = ptrLen;
-
- {
- LocalDLList<Subscriber> list(c_subscriberPool,tabPtr.p->c_subscribers);
- SubscriberPtr subbPtr;
- for(list.first(subbPtr); !subbPtr.isNull(); list.next(subbPtr))
- {
- DBUG_PRINT("info",("GSN_SUB_TABLE_DATA to node %d",
- refToNode(subbPtr.p->m_senderRef)));
- data->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB, ptr, nptr);
- }
- }
- }
- else
- {
- const uint buffer_header_sz = 4;
- Uint32* dst;
- Uint32 sz = f_trigBufferSize + b_trigBufferSize + buffer_header_sz;
- if((dst = get_buffer_ptr(signal, bucket, gci, sz)))
- {
- * dst++ = tableId;
- * dst++ = tabPtr.p->m_schemaVersion;
- * dst++ = (event << 16) | f_trigBufferSize;
- * dst++ = any_value;
- memcpy(dst, f_buffer, f_trigBufferSize << 2);
- dst += f_trigBufferSize;
- memcpy(dst, b_buffer, b_trigBufferSize << 2);
- }
- }
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_GCP_COMPLETE_REP(Signal* signal)
-{
- jamEntry();
- ndbassert(signal->getNoOfSections() == 0);
-
- SubGcpCompleteRep * rep = (SubGcpCompleteRep*)signal->getDataPtrSend();
- Uint32 gci = m_last_complete_gci = rep->gci;
- m_max_seen_gci = (gci > m_max_seen_gci ? gci : m_max_seen_gci);
-
- /**
- *
- */
- if(!m_switchover_buckets.isclear())
- {
- NdbNodeBitmask takeover_nodes;
- NdbNodeBitmask handover_nodes;
- Uint32 i = m_switchover_buckets.find(0);
- for(; i != Bucket_mask::NotFound; i = m_switchover_buckets.find(i + 1))
- {
- if(c_buckets[i].m_switchover_gci == gci)
- {
- Uint32 state = c_buckets[i].m_state;
- m_switchover_buckets.clear(i);
- printf("switchover complete bucket %d state: %x", i, state);
- if(state & Bucket::BUCKET_STARTING)
- {
- /**
- * NR case
- */
- m_active_buckets.set(i);
- c_buckets[i].m_state &= ~(Uint32)Bucket::BUCKET_STARTING;
- ndbout_c("starting");
- m_gcp_complete_rep_count = 1;
- }
- else if(state & Bucket::BUCKET_TAKEOVER)
- {
- /**
- * NF case
- */
- Bucket* bucket= c_buckets + i;
- Page_pos pos= bucket->m_buffer_head;
- ndbrequire(pos.m_max_gci < gci);
-
- Buffer_page* page= (Buffer_page*)
- m_tup->c_page_pool.getPtr(pos.m_page_id);
- ndbout_c("takeover %d", pos.m_page_id);
- page->m_max_gci = pos.m_max_gci;
- page->m_words_used = pos.m_page_pos;
- page->m_next_page = RNIL;
- memset(&bucket->m_buffer_head, 0, sizeof(bucket->m_buffer_head));
- bucket->m_buffer_head.m_page_id = RNIL;
- bucket->m_buffer_head.m_page_pos = Buffer_page::DATA_WORDS + 1;
-
- m_active_buckets.set(i);
- c_buckets[i].m_state &= ~(Uint32)Bucket::BUCKET_TAKEOVER;
- takeover_nodes.set(c_buckets[i].m_switchover_node);
- }
- else
- {
- /**
- * NR, living node
- */
- ndbrequire(state & Bucket::BUCKET_HANDOVER);
- c_buckets[i].m_state &= ~(Uint32)Bucket::BUCKET_HANDOVER;
- handover_nodes.set(c_buckets[i].m_switchover_node);
- ndbout_c("handover");
- }
- }
- }
- ndbassert(handover_nodes.count() == 0 ||
- m_gcp_complete_rep_count > handover_nodes.count());
- m_gcp_complete_rep_count -= handover_nodes.count();
- m_gcp_complete_rep_count += takeover_nodes.count();
-
- if(getNodeState().startLevel == NodeState::SL_STARTING &&
- m_switchover_buckets.isclear() &&
- c_startup.m_handover_nodes.isclear())
- {
- sendSTTORRY(signal);
- }
- }
-
- if(ERROR_INSERTED(13010))
- {
- CLEAR_ERROR_INSERT_VALUE;
- ndbout_c("Don't send GCP_COMPLETE_REP(%d)", gci);
- return;
- }
-
- /**
- * Signal to subscribers
- */
- rep->gci = gci;
- rep->senderRef = reference();
- rep->gcp_complete_rep_count = m_gcp_complete_rep_count;
-
- if(m_gcp_complete_rep_count && !c_subscriber_nodes.isclear())
- {
- CRASH_INSERTION(13033);
-
- NodeReceiverGroup rg(API_CLUSTERMGR, c_subscriber_nodes);
- sendSignal(rg, GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength, JBB);
-
- Ptr<Gcp_record> gcp;
- if(c_gcp_list.seize(gcp))
- {
- gcp.p->m_gci = gci;
- gcp.p->m_subscribers = c_subscriber_nodes;
- }
- }
-
- /**
- * Add GCP COMPLETE REP to buffer
- */
- for(Uint32 i = 0; i<c_no_of_buckets; i++)
- {
- if(m_active_buckets.get(i))
- continue;
-
- if (!c_subscriber_nodes.isclear())
- {
- //Uint32* dst;
- get_buffer_ptr(signal, i, gci, 0);
- }
- }
-
- if(gci == m_out_of_buffer_gci)
- {
- infoEvent("Reenable event buffer");
- m_out_of_buffer_gci = 0;
- }
-}
-
-void
-Suma::execCREATE_TAB_CONF(Signal *signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execCREATE_TAB_CONF");
-
-#if 0
- CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
- Uint32 tableId = conf->senderData;
-
- TablePtr tabPtr;
- initTable(signal,tableId,tabPtr);
-#endif
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execDROP_TAB_CONF(Signal *signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execDROP_TAB_CONF");
- ndbassert(signal->getNoOfSections() == 0);
-
- DropTabConf * const conf = (DropTabConf*)signal->getDataPtr();
- Uint32 senderRef= conf->senderRef;
- Uint32 tableId= conf->tableId;
-
- TablePtr tabPtr;
- if (!c_tables.find(tabPtr, tableId) ||
- tabPtr.p->m_state == Table::DROPPED ||
- tabPtr.p->m_state == Table::ALTERED)
- {
- DBUG_VOID_RETURN;
- }
-
- DBUG_PRINT("info",("drop table id: %d[i=%u]", tableId, tabPtr.i));
-
- tabPtr.p->m_state = Table::DROPPED;
- for (int j= 0; j < 3; j++)
- {
- if (!tabPtr.p->m_hasOutstandingTriggerReq[j])
- {
- tabPtr.p->m_hasTriggerDefined[j] = 0;
- tabPtr.p->m_hasOutstandingTriggerReq[j] = 0;
- tabPtr.p->m_triggerIds[j] = ILLEGAL_TRIGGER_ID;
- }
- else
- tabPtr.p->m_hasTriggerDefined[j] = 1;
- }
- if (senderRef == 0)
- {
- DBUG_VOID_RETURN;
- }
- // dict coordinator sends info to API
-
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();
- data->gci = m_last_complete_gci+1;
- data->tableId = tableId;
- data->requestInfo = 0;
- SubTableData::setOperation(data->requestInfo,NdbDictionary::Event::_TE_DROP);
- SubTableData::setReqNodeId(data->requestInfo, refToNode(senderRef));
-
- {
- LocalDLList<Subscriber> subbs(c_subscriberPool,tabPtr.p->c_subscribers);
- SubscriberPtr subbPtr;
- for(subbs.first(subbPtr);!subbPtr.isNull();subbs.next(subbPtr))
- {
- jam();
- /*
- * get subscription ptr for this subscriber
- */
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
- if(subPtr.p->m_subscriptionType != SubCreateReq::TableEvent) {
- jam();
- continue;
- //continue in for-loop if the table is not part of
- //the subscription. Otherwise, send data to subscriber.
- }
- data->senderData= subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB);
- DBUG_PRINT("info",("sent to subscriber %d", subbPtr.i));
- }
- }
- DBUG_VOID_RETURN;
-}
-
-static Uint32 b_dti_buf[MAX_WORDS_META_FILE];
-
-void
-Suma::execALTER_TAB_REQ(Signal *signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execALTER_TAB_REQ");
- ndbassert(signal->getNoOfSections() == 1);
-
- AlterTabReq * const req = (AlterTabReq*)signal->getDataPtr();
- Uint32 senderRef= req->senderRef;
- Uint32 tableId= req->tableId;
- Uint32 changeMask= req->changeMask;
- TablePtr tabPtr;
- if (!c_tables.find(tabPtr, tableId) ||
- tabPtr.p->m_state == Table::DROPPED ||
- tabPtr.p->m_state == Table::ALTERED)
- {
- DBUG_VOID_RETURN;
- }
-
- DBUG_PRINT("info",("alter table id: %d[i=%u]", tableId, tabPtr.i));
- Table::State old_state = tabPtr.p->m_state;
- tabPtr.p->m_state = Table::ALTERED;
- // triggers must be removed, waiting for sub stop req for that
-
- if (senderRef == 0)
- {
- DBUG_VOID_RETURN;
- }
- // dict coordinator sends info to API
-
- // Copy DICT_TAB_INFO to local buffer
- SegmentedSectionPtr tabInfoPtr;
- signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
-#ifndef DBUG_OFF
- ndbout_c("DICT_TAB_INFO in SUMA, tabInfoPtr.sz = %d", tabInfoPtr.sz);
- SimplePropertiesSectionReader reader(tabInfoPtr, getSectionSegmentPool());
- reader.printAll(ndbout);
-#endif
- copy(b_dti_buf, tabInfoPtr);
- LinearSectionPtr ptr[3];
- ptr[0].p = b_dti_buf;
- ptr[0].sz = tabInfoPtr.sz;
-
- releaseSections(signal);
-
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();
- data->gci = m_last_complete_gci+1;
- data->tableId = tableId;
- data->requestInfo = 0;
- SubTableData::setOperation(data->requestInfo,
- NdbDictionary::Event::_TE_ALTER);
- SubTableData::setReqNodeId(data->requestInfo, refToNode(senderRef));
- data->logType = 0;
- data->changeMask = changeMask;
- data->totalLen = tabInfoPtr.sz;
- {
- LocalDLList<Subscriber> subbs(c_subscriberPool,tabPtr.p->c_subscribers);
- SubscriberPtr subbPtr;
- for(subbs.first(subbPtr);!subbPtr.isNull();subbs.next(subbPtr))
- {
- jam();
- /*
- * get subscription ptr for this subscriber
- */
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
- if(subPtr.p->m_subscriptionType != SubCreateReq::TableEvent) {
- jam();
- continue;
- //continue in for-loop if the table is not part of
- //the subscription. Otherwise, send data to subscriber.
- }
-
- data->senderData= subbPtr.p->m_senderData;
- Callback c = { 0, 0 };
- sendFragmentedSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB, ptr, 1, c);
- DBUG_PRINT("info",("sent to subscriber %d", subbPtr.i));
- }
- }
- if (AlterTableReq::getFrmFlag(changeMask))
- {
- // Frm changes only are handled on-line
- tabPtr.p->m_state = old_state;
- }
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_GCP_COMPLETE_ACK(Signal* signal)
-{
- jamEntry();
- ndbassert(signal->getNoOfSections() == 0);
-
- SubGcpCompleteAck * const ack = (SubGcpCompleteAck*)signal->getDataPtr();
- Uint32 gci = ack->rep.gci;
- Uint32 senderRef = ack->rep.senderRef;
- m_max_seen_gci = (gci > m_max_seen_gci ? gci : m_max_seen_gci);
-
- if (refToBlock(senderRef) == SUMA) {
- jam();
- // Ack from other SUMA
- Uint32 nodeId= refToNode(senderRef);
- for(Uint32 i = 0; i<c_no_of_buckets; i++)
- {
- if(m_active_buckets.get(i) ||
- (m_switchover_buckets.get(i) && (check_switchover(i, gci))) ||
- (!m_switchover_buckets.get(i) && get_responsible_node(i) == nodeId))
- {
- release_gci(signal, i, gci);
- }
- }
- return;
- }
-
- // Ack from User and not an ack from other SUMA, redistribute in nodegroup
-
- Uint32 nodeId = refToNode(senderRef);
-
- jam();
- Ptr<Gcp_record> gcp;
- for(c_gcp_list.first(gcp); !gcp.isNull(); c_gcp_list.next(gcp))
- {
- if(gcp.p->m_gci == gci)
- {
- gcp.p->m_subscribers.clear(nodeId);
- if(!gcp.p->m_subscribers.isclear())
- {
- jam();
- return;
- }
- break;
- }
- }
-
- if(gcp.isNull())
- {
- ndbout_c("ACK wo/ gcp record (gci: %d)", gci);
- }
- else
- {
- c_gcp_list.release(gcp);
- }
-
- CRASH_INSERTION(13011);
- if(ERROR_INSERTED(13012))
- {
- CLEAR_ERROR_INSERT_VALUE;
- ndbout_c("Don't redistribute SUB_GCP_COMPLETE_ACK");
- return;
- }
-
- ack->rep.senderRef = reference();
- NodeReceiverGroup rg(SUMA, c_nodes_in_nodegroup_mask);
- sendSignal(rg, GSN_SUB_GCP_COMPLETE_ACK, signal,
- SubGcpCompleteAck::SignalLength, JBB);
-}
-
-/**************************************************************
- *
- * Removing subscription
- *
- */
-
-void
-Suma::execSUB_REMOVE_REQ(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execSUB_REMOVE_REQ");
- ndbassert(signal->getNoOfSections() == 0);
-
- CRASH_INSERTION(13021);
-
- const SubRemoveReq req = *(SubRemoveReq*)signal->getDataPtr();
- SubscriptionPtr subPtr;
- Subscription key;
- key.m_subscriptionId = req.subscriptionId;
- key.m_subscriptionKey = req.subscriptionKey;
-
- DBUG_PRINT("enter",("key.m_subscriptionId: %u, key.m_subscriptionKey: %u",
- key.m_subscriptionId, key.m_subscriptionKey));
-
- if(!c_subscriptions.find(subPtr, key))
- {
- jam();
- DBUG_PRINT("info",("Not found"));
- sendSubRemoveRef(signal, req, 1407);
- DBUG_VOID_RETURN;
- }
- if (subPtr.p->m_state == Subscription::LOCKED)
- {
- /**
- * we are currently setting up triggers etc. for this event
- */
- jam();
- sendSubRemoveRef(signal, req, 1413);
- DBUG_VOID_RETURN;
- }
- if (subPtr.p->m_state == Subscription::DROPPED)
- {
- /**
- * already dropped
- */
- jam();
- sendSubRemoveRef(signal, req, 1419);
- DBUG_VOID_RETURN;
- }
-
- ndbrequire(subPtr.p->m_state == Subscription::DEFINED);
- DBUG_PRINT("info",("n_subscribers: %u", subPtr.p->n_subscribers));
-
- if (subPtr.p->n_subscribers == 0)
- {
- // no subscribers on the subscription
- // remove it
- jam();
- completeSubRemove(subPtr);
- }
- else
- {
- // subscribers left on the subscription
- // mark it to be removed once all subscribers
- // are removed
- jam();
- subPtr.p->m_state = Subscription::DROPPED;
- }
-
- SubRemoveConf * const conf = (SubRemoveConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = req.senderData;
- conf->subscriptionId = req.subscriptionId;
- conf->subscriptionKey = req.subscriptionKey;
-
- sendSignal(req.senderRef, GSN_SUB_REMOVE_CONF, signal,
- SubRemoveConf::SignalLength, JBB);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::completeSubRemove(SubscriptionPtr subPtr)
-{
- DBUG_ENTER("Suma::completeSubRemove");
- //Uint32 subscriptionId = subPtr.p->m_subscriptionId;
- //Uint32 subscriptionKey = subPtr.p->m_subscriptionKey;
-
- c_subscriptions.release(subPtr);
- DBUG_PRINT("info",("c_subscriptionPool size: %d free: %d",
- c_subscriptionPool.getSize(),
- c_subscriptionPool.getNoOfFree()));
-
- /**
- * I was the last subscription to be remove so clear c_tables
- */
-#if 0
- ndbout_c("c_subscriptionPool.getSize() %d c_subscriptionPool.getNoOfFree()%d",
- c_subscriptionPool.getSize(),c_subscriptionPool.getNoOfFree());
-#endif
-
- if(c_subscriptionPool.getSize() == c_subscriptionPool.getNoOfFree()) {
- jam();
-#if 0
- ndbout_c("SUB_REMOVE_REQ:Clearing c_tables");
-#endif
- int count= 0;
- KeyTable<Table>::Iterator it;
- for(c_tables.first(it); !it.isNull(); )
- {
- // ndbrequire(false);
-
- DBUG_PRINT("error",("trailing table id: %d[i=%d] n_subscribers: %d m_state: %d",
- it.curr.p->m_tableId,
- it.curr.p->m_ptrI,
- it.curr.p->n_subscribers,
- it.curr.p->m_state));
-
- LocalDLList<Subscriber> subbs(c_subscriberPool,it.curr.p->c_subscribers);
- SubscriberPtr subbPtr;
- for(subbs.first(subbPtr);!subbPtr.isNull();subbs.next(subbPtr))
- {
- DBUG_PRINT("error",("subscriber %d, m_subPtrI: %d", subbPtr.i, subbPtr.p->m_subPtrI));
- }
-
- it.curr.p->release(* this);
- TablePtr tabPtr = it.curr;
- c_tables.next(it);
- c_tables.remove(tabPtr);
- c_tablePool.release(tabPtr);
- DBUG_PRINT("info",("c_tablePool size: %d free: %d",
- c_tablePool.getSize(),
- c_tablePool.getNoOfFree()));
- count++;
- }
- DBUG_ASSERT(count == 0);
- }
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::sendSubRemoveRef(Signal* signal, const SubRemoveReq& req,
- Uint32 errCode)
-{
- jam();
- DBUG_ENTER("Suma::sendSubRemoveRef");
- SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = req.senderData;
- ref->subscriptionId = req.subscriptionId;
- ref->subscriptionKey = req.subscriptionKey;
- ref->errorCode = errCode;
- releaseSections(signal);
- sendSignal(signal->getSendersBlockRef(), GSN_SUB_REMOVE_REF,
- signal, SubRemoveRef::SignalLength, JBB);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Table::release(Suma & suma){
- jam();
-
- LocalDataBuffer<15> attrBuf(suma.c_dataBufferPool, m_attributes);
- attrBuf.release();
-
- LocalDataBuffer<15> fragBuf(suma.c_dataBufferPool, m_fragments);
- fragBuf.release();
-
- m_state = UNDEFINED;
-#ifndef DBUG_OFF
- if (n_subscribers != 0)
- abort();
-#endif
-}
-
-void
-Suma::SyncRecord::release(){
- jam();
- m_tableList.release();
-
- LocalDataBuffer<15> attrBuf(suma.c_dataBufferPool, m_attributeList);
- 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
- *
- */
-
-void
-Suma::execSUMA_START_ME_REQ(Signal* signal) {
- jamEntry();
- DBUG_ENTER("Suma::execSUMA_START_ME");
- ndbassert(signal->getNoOfSections() == 0);
- Restart.runSUMA_START_ME_REQ(signal, signal->getSendersBlockRef());
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_CREATE_REF(Signal* signal) {
- jamEntry();
- DBUG_ENTER("Suma::execSUB_CREATE_REF");
- ndbassert(signal->getNoOfSections() == 0);
- SubCreateRef *const ref= (SubCreateRef *)signal->getDataPtr();
- Uint32 error= ref->errorCode;
- if (error != 1415)
- {
- /*
- * This will happen if an api node connects during while other node
- * is restarting, and in this case the subscription will already
- * have been created.
- * ToDo: more complete handling of api nodes joining during
- * node restart
- */
- Uint32 senderRef = signal->getSendersBlockRef();
- BlockReference cntrRef = calcNdbCntrBlockRef(refToNode(senderRef));
- // for some reason we did not manage to create a subscription
- // on the starting node
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::CopySubscriptionRef;
- sysErr->errorRef = reference();
- sysErr->data1 = error;
- sysErr->data2 = 0;
- sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBB);
- Restart.resetRestart(signal);
- DBUG_VOID_RETURN;
- }
- // SubCreateConf has same signaldata as SubCreateRef
- Restart.runSUB_CREATE_CONF(signal);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_CREATE_CONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execSUB_CREATE_CONF");
- ndbassert(signal->getNoOfSections() == 0);
- Restart.runSUB_CREATE_CONF(signal);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_START_CONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execSUB_START_CONF");
- ndbassert(signal->getNoOfSections() == 0);
- Restart.runSUB_START_CONF(signal);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::execSUB_START_REF(Signal* signal) {
- jamEntry();
- DBUG_ENTER("Suma::execSUB_START_REF");
- ndbassert(signal->getNoOfSections() == 0);
- SubStartRef *const ref= (SubStartRef *)signal->getDataPtr();
- Uint32 error= ref->errorCode;
- {
- Uint32 senderRef = signal->getSendersBlockRef();
- BlockReference cntrRef = calcNdbCntrBlockRef(refToNode(senderRef));
- // for some reason we did not manage to start a subscriber
- // on the starting node
- SystemError * const sysErr = (SystemError*)&signal->theData[0];
- sysErr->errorCode = SystemError::CopySubscriberRef;
- sysErr->errorRef = reference();
- sysErr->data1 = error;
- sysErr->data2 = 0;
- sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal,
- SystemError::SignalLength, JBB);
- Restart.resetRestart(signal);
- }
- DBUG_VOID_RETURN;
-}
-
-Suma::Restart::Restart(Suma& s) : suma(s)
-{
- nodeId = 0;
-}
-
-void
-Suma::Restart::runSUMA_START_ME_REQ(Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::runSUMA_START_ME");
-
- if(nodeId != 0)
- {
- SumaStartMeRef* ref= (SumaStartMeRef*)signal->getDataPtrSend();
- ref->errorCode = SumaStartMeRef::Busy;
- suma.sendSignal(sumaRef, GSN_SUMA_START_ME_REF, signal,
- SumaStartMeRef::SignalLength, JBB);
- DBUG_VOID_RETURN;
- }
-
- nodeId = refToNode(sumaRef);
- startNode(signal, sumaRef);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::startNode(Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::startNode");
-
- // right now we can only handle restarting one node
- // at a time in a node group
-
- createSubscription(signal, sumaRef);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::createSubscription(Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::createSubscription");
- suma.c_subscriptions.first(c_subIt);
- nextSubscription(signal, sumaRef);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::nextSubscription(Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::nextSubscription");
-
- if (c_subIt.isNull())
- {
- jam();
- completeSubscription(signal, sumaRef);
- DBUG_VOID_RETURN;
- }
- SubscriptionPtr subPtr;
- subPtr.i = c_subIt.curr.i;
- subPtr.p = suma.c_subscriptions.getPtr(subPtr.i);
-
- suma.c_subscriptions.next(c_subIt);
-
- SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend();
-
- req->senderRef = suma.reference();
- req->senderData = 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:
- jam();
- req->tableId = subPtr.p->m_tableId;
- req->state = subPtr.p->m_state;
- suma.sendSignal(sumaRef, GSN_SUB_CREATE_REQ, signal,
- SubCreateReq::SignalLength2, JBB);
- DBUG_VOID_RETURN;
- case SubCreateReq::SingleTableScan:
- jam();
- nextSubscription(signal, sumaRef);
- DBUG_VOID_RETURN;
- case SubCreateReq::SelectiveTableSnapshot:
- case SubCreateReq::DatabaseSnapshot:
- ndbrequire(false);
- }
- ndbrequire(false);
-}
-
-void
-Suma::Restart::runSUB_CREATE_CONF(Signal* signal)
-{
- jam();
- DBUG_ENTER("Suma::Restart::runSUB_CREATE_CONF");
-
- const Uint32 senderRef = signal->senderBlockRef();
- Uint32 sumaRef = signal->getSendersBlockRef();
-
- SubCreateConf * const conf = (SubCreateConf *)signal->getDataPtr();
-
- SubscriptionPtr subPtr;
- suma.c_subscriptions.getPtr(subPtr,conf->senderData);
-
- switch(subPtr.p->m_subscriptionType) {
- case SubCreateReq::TableEvent:
- if (1)
- {
- jam();
- nextSubscription(signal, sumaRef);
- } else {
- jam();
- SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend();
-
- req->senderRef = suma.reference();
- req->senderData = 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 = 0;
-
- suma.sendSignal(senderRef, GSN_SUB_CREATE_REQ, signal,
- SubCreateReq::SignalLength, JBB);
- }
- DBUG_VOID_RETURN;
- case SubCreateReq::SingleTableScan:
- case SubCreateReq::SelectiveTableSnapshot:
- case SubCreateReq::DatabaseSnapshot:
- ndbrequire(false);
- }
- ndbrequire(false);
-}
-
-void
-Suma::Restart::completeSubscription(Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::completeSubscription");
- startSubscriber(signal, sumaRef);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::startSubscriber(Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::startSubscriber");
- suma.c_tables.first(c_tabIt);
- if (c_tabIt.isNull())
- {
- completeSubscriber(signal, sumaRef);
- DBUG_VOID_RETURN;
- }
- SubscriberPtr subbPtr;
- {
- LocalDLList<Subscriber>
- subbs(suma.c_subscriberPool,c_tabIt.curr.p->c_subscribers);
- subbs.first(subbPtr);
- }
- nextSubscriber(signal, sumaRef, subbPtr);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::nextSubscriber(Signal* signal, Uint32 sumaRef,
- SubscriberPtr subbPtr)
-{
- jam();
- DBUG_ENTER("Suma::Restart::nextSubscriber");
- while (subbPtr.isNull())
- {
- jam();
- DBUG_PRINT("info",("prev tableId %u",c_tabIt.curr.p->m_tableId));
- suma.c_tables.next(c_tabIt);
- if (c_tabIt.isNull())
- {
- completeSubscriber(signal, sumaRef);
- DBUG_VOID_RETURN;
- }
- DBUG_PRINT("info",("next tableId %u",c_tabIt.curr.p->m_tableId));
-
- LocalDLList<Subscriber>
- subbs(suma.c_subscriberPool,c_tabIt.curr.p->c_subscribers);
- subbs.first(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:
- jam();
- sendSubStartReq(subPtr, subbPtr, signal, sumaRef);
- DBUG_VOID_RETURN;
- case SubCreateReq::SelectiveTableSnapshot:
- case SubCreateReq::DatabaseSnapshot:
- case SubCreateReq::SingleTableScan:
- ndbrequire(false);
- }
- ndbrequire(false);
-}
-
-void
-Suma::Restart::sendSubStartReq(SubscriptionPtr subPtr, SubscriberPtr subbPtr,
- Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::sendSubStartReq");
- SubStartReq * req = (SubStartReq *)signal->getDataPtrSend();
-
- req->senderRef = suma.reference();
- req->senderData = subbPtr.i;
- req->subscriptionId = subPtr.p->m_subscriptionId;
- req->subscriptionKey = subPtr.p->m_subscriptionKey;
- req->part = SubscriptionData::TableData;
- req->subscriberData = subbPtr.p->m_senderData;
- req->subscriberRef = subbPtr.p->m_senderRef;
-
- // restarting suma will not respond to this until startphase 5
- // since it is not until then data copying has been completed
- DBUG_PRINT("info",("Restarting subscriber: %u on key: [%u,%u] %u",
- subbPtr.i,
- subPtr.p->m_subscriptionId,
- subPtr.p->m_subscriptionKey,
- subPtr.p->m_tableId));
-
- suma.sendSignal(sumaRef, GSN_SUB_START_REQ,
- signal, SubStartReq::SignalLength2, JBB);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::runSUB_START_CONF(Signal* signal)
-{
- jam();
- DBUG_ENTER("Suma::Restart::runSUB_START_CONF");
-
- SubStartConf * const conf = (SubStartConf*)signal->getDataPtr();
-
- Subscription key;
- SubscriptionPtr subPtr;
- key.m_subscriptionId = conf->subscriptionId;
- key.m_subscriptionKey = conf->subscriptionKey;
- ndbrequire(suma.c_subscriptions.find(subPtr, key));
-
- TablePtr tabPtr;
- ndbrequire(suma.c_tables.find(tabPtr, subPtr.p->m_tableId));
-
- SubscriberPtr subbPtr;
- {
- LocalDLList<Subscriber>
- subbs(suma.c_subscriberPool,tabPtr.p->c_subscribers);
- subbs.getPtr(subbPtr, conf->senderData);
- DBUG_PRINT("info",("Restarted subscriber: %u on key: [%u,%u] table: %u",
- subbPtr.i,key.m_subscriptionId,key.m_subscriptionKey,
- subPtr.p->m_tableId));
- subbs.next(subbPtr);
- }
-
- Uint32 sumaRef = signal->getSendersBlockRef();
- nextSubscriber(signal, sumaRef, subbPtr);
-
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::completeSubscriber(Signal* signal, Uint32 sumaRef)
-{
- DBUG_ENTER("Suma::Restart::completeSubscriber");
- completeRestartingNode(signal, sumaRef);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::completeRestartingNode(Signal* signal, Uint32 sumaRef)
-{
- jam();
- DBUG_ENTER("Suma::Restart::completeRestartingNode");
- //SumaStartMeConf *conf= (SumaStartMeConf*)signal->getDataPtrSend();
- suma.sendSignal(sumaRef, GSN_SUMA_START_ME_CONF, signal,
- SumaStartMeConf::SignalLength, JBB);
- resetRestart(signal);
- DBUG_VOID_RETURN;
-}
-
-void
-Suma::Restart::resetRestart(Signal* signal)
-{
- jam();
- DBUG_ENTER("Suma::Restart::resetRestart");
- nodeId = 0;
- DBUG_VOID_RETURN;
-}
-
-// only run on restarting suma
-
-void
-Suma::execSUMA_HANDOVER_REQ(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Suma::execSUMA_HANDOVER_REQ");
- // Uint32 sumaRef = signal->getSendersBlockRef();
- SumaHandoverReq const * req = (SumaHandoverReq *)signal->getDataPtr();
-
- Uint32 gci = req->gci;
- Uint32 nodeId = req->nodeId;
- Uint32 new_gci = m_last_complete_gci + MAX_CONCURRENT_GCP + 1;
-
- Uint32 start_gci = (gci > new_gci ? gci : new_gci);
- // mark all active buckets really belonging to restarting SUMA
-
- Bucket_mask tmp;
- for( Uint32 i = 0; i < c_no_of_buckets; i++)
- {
- if(get_responsible_node(i) == nodeId)
- {
- if (m_active_buckets.get(i))
- {
- // I'm running this bucket but it should really be the restarted node
- tmp.set(i);
- m_active_buckets.clear(i);
- m_switchover_buckets.set(i);
- c_buckets[i].m_switchover_gci = start_gci;
- c_buckets[i].m_state |= Bucket::BUCKET_HANDOVER;
- c_buckets[i].m_switchover_node = nodeId;
- ndbout_c("prepare to handover bucket: %d", i);
- }
- else if(m_switchover_buckets.get(i))
- {
- ndbout_c("dont handover bucket: %d %d", i, nodeId);
- }
- }
- }
-
- SumaHandoverConf* conf= (SumaHandoverConf*)signal->getDataPtrSend();
- tmp.copyto(BUCKET_MASK_SIZE, conf->theBucketMask);
- conf->gci = start_gci;
- conf->nodeId = getOwnNodeId();
- sendSignal(calcSumaBlockRef(nodeId), GSN_SUMA_HANDOVER_CONF, signal,
- SumaHandoverConf::SignalLength, JBB);
-
- DBUG_VOID_RETURN;
-}
-
-// only run on all but restarting suma
-void
-Suma::execSUMA_HANDOVER_REF(Signal* signal)
-{
- ndbrequire(false);
-}
-
-void
-Suma::execSUMA_HANDOVER_CONF(Signal* signal) {
- jamEntry();
- DBUG_ENTER("Suma::execSUMA_HANDOVER_CONF");
-
- SumaHandoverConf const * conf = (SumaHandoverConf *)signal->getDataPtr();
-
- Uint32 gci = conf->gci;
- Uint32 nodeId = conf->nodeId;
- Bucket_mask tmp;
- tmp.assign(BUCKET_MASK_SIZE, conf->theBucketMask);
-#ifdef HANDOVER_DEBUG
- ndbout_c("Suma::execSUMA_HANDOVER_CONF, gci = %u", gci);
-#endif
-
- for( Uint32 i = 0; i < c_no_of_buckets; i++)
- {
- if (tmp.get(i))
- {
- ndbrequire(get_responsible_node(i) == getOwnNodeId());
- // We should run this bucket, but _nodeId_ is
- c_buckets[i].m_switchover_gci = gci;
- c_buckets[i].m_state |= Bucket::BUCKET_STARTING;
- }
- }
-
- char buf[255];
- tmp.getText(buf);
- infoEvent("Suma: handover from node %d gci: %d buckets: %s (%d)",
- nodeId, gci, buf, c_no_of_buckets);
- m_switchover_buckets.bitOR(tmp);
- c_startup.m_handover_nodes.clear(nodeId);
- DBUG_VOID_RETURN;
-}
-
-#ifdef NOT_USED
-static
-NdbOut&
-operator<<(NdbOut & out, const Suma::Page_pos & pos)
-{
- out << "[ Page_pos:"
- << " m_page_id: " << pos.m_page_id
- << " m_page_pos: " << pos.m_page_pos
- << " m_max_gci: " << pos.m_max_gci
- << " ]";
- return out;
-}
-#endif
-
-Uint32*
-Suma::get_buffer_ptr(Signal* signal, Uint32 buck, Uint32 gci, Uint32 sz)
-{
- sz += 1; // len
- Bucket* bucket= c_buckets+buck;
- Page_pos pos= bucket->m_buffer_head;
-
- Buffer_page* page = 0;
- Uint32 *ptr = 0;
-
- if (likely(pos.m_page_id != RNIL))
- {
- page= (Buffer_page*)m_tup->c_page_pool.getPtr(pos.m_page_id);
- ptr= page->m_data + pos.m_page_pos;
- }
-
- const bool same_gci = (gci == pos.m_last_gci) && (!ERROR_INSERTED(13022));
-
- pos.m_page_pos += sz;
- pos.m_last_gci = gci;
- Uint32 max = pos.m_max_gci > gci ? pos.m_max_gci : gci;
-
- if(likely(same_gci && pos.m_page_pos <= Buffer_page::DATA_WORDS))
- {
- pos.m_max_gci = max;
- bucket->m_buffer_head = pos;
- * ptr++ = (0x8000 << 16) | sz; // Same gci
- return ptr;
- }
- else if(pos.m_page_pos + 1 <= Buffer_page::DATA_WORDS)
- {
-loop:
- pos.m_max_gci = max;
- pos.m_page_pos += 1;
- bucket->m_buffer_head = pos;
- * ptr++ = (sz + 1);
- * ptr++ = gci;
- return ptr;
- }
- else
- {
- /**
- * new page
- * 1) save header on last page
- * 2) seize new page
- */
- Uint32 next;
- if(unlikely((next= seize_page()) == RNIL))
- {
- /**
- * Out of buffer
- */
- out_of_buffer(signal);
- return 0;
- }
-
- if(likely(pos.m_page_id != RNIL))
- {
- page->m_max_gci = pos.m_max_gci;
- page->m_words_used = pos.m_page_pos - sz;
- page->m_next_page= next;
- }
- else
- {
- bucket->m_buffer_tail = next;
- }
-
- memset(&pos, 0, sizeof(pos));
- pos.m_page_id = next;
- pos.m_page_pos = sz;
- pos.m_last_gci = gci;
-
- page= (Buffer_page*)m_tup->c_page_pool.getPtr(pos.m_page_id);
- page->m_next_page= RNIL;
- ptr= page->m_data;
- goto loop; //
- }
-}
-
-void
-Suma::out_of_buffer(Signal* signal)
-{
- if(m_out_of_buffer_gci)
- {
- return;
- }
-
- m_out_of_buffer_gci = m_last_complete_gci - 1;
- infoEvent("Out of event buffer: nodefailure will cause event failures");
-
- out_of_buffer_release(signal, 0);
-}
-
-void
-Suma::out_of_buffer_release(Signal* signal, Uint32 buck)
-{
- Bucket* bucket= c_buckets+buck;
- Uint32 tail= bucket->m_buffer_tail;
-
- if(tail != RNIL)
- {
- Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
- bucket->m_buffer_tail = page->m_next_page;
- free_page(tail, page);
- signal->theData[0] = SumaContinueB::OUT_OF_BUFFER_RELEASE;
- signal->theData[1] = buck;
- sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 2, JBB);
- return;
- }
-
- /**
- * Clear head
- */
- bucket->m_buffer_head.m_page_id = RNIL;
- bucket->m_buffer_head.m_page_pos = Buffer_page::DATA_WORDS + 1;
-
- buck++;
- if(buck != c_no_of_buckets)
- {
- signal->theData[0] = SumaContinueB::OUT_OF_BUFFER_RELEASE;
- signal->theData[1] = buck;
- sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 2, JBB);
- return;
- }
-
- /**
- * Finished will all release
- * prepare for inclusion
- */
- m_out_of_buffer_gci = m_max_seen_gci > m_last_complete_gci
- ? m_max_seen_gci + 1 : m_last_complete_gci + 1;
-}
-
-Uint32
-Suma::seize_page()
-{
- if(unlikely(m_out_of_buffer_gci))
- {
- return RNIL;
- }
-loop:
- Ptr<Page_chunk> ptr;
- Uint32 ref= m_first_free_page;
- if(likely(ref != RNIL))
- {
- m_first_free_page = ((Buffer_page*)m_tup->c_page_pool.getPtr(ref))->m_next_page;
- Uint32 chunk = ((Buffer_page*)m_tup->c_page_pool.getPtr(ref))->m_page_chunk_ptr_i;
- c_page_chunk_pool.getPtr(ptr, chunk);
- ndbassert(ptr.p->m_free);
- ptr.p->m_free--;
- return ref;
- }
-
- if(!c_page_chunk_pool.seize(ptr))
- return RNIL;
-
- Uint32 count;
- m_tup->allocConsPages(16, count, ref);
- if (count == 0)
- return RNIL;
-
- ndbout_c("alloc_chunk(%d %d) - ", ref, count);
-
- m_first_free_page = ptr.p->m_page_id = ref;
- ptr.p->m_size = count;
- ptr.p->m_free = count;
-
- Buffer_page* page;
- LINT_INIT(page);
- for(Uint32 i = 0; i<count; i++)
- {
- page = (Buffer_page*)m_tup->c_page_pool.getPtr(ref);
- page->m_page_state= SUMA_SEQUENCE;
- page->m_page_chunk_ptr_i = ptr.i;
- page->m_next_page = ++ref;
- }
- page->m_next_page = RNIL;
-
- goto loop;
-}
-
-void
-Suma::free_page(Uint32 page_id, Buffer_page* page)
-{
- Ptr<Page_chunk> ptr;
- ndbrequire(page->m_page_state == SUMA_SEQUENCE);
-
- Uint32 chunk= page->m_page_chunk_ptr_i;
-
- c_page_chunk_pool.getPtr(ptr, chunk);
-
- ptr.p->m_free ++;
- page->m_next_page = m_first_free_page;
- ndbrequire(ptr.p->m_free <= ptr.p->m_size);
-
- m_first_free_page = page_id;
-}
-
-void
-Suma::release_gci(Signal* signal, Uint32 buck, Uint32 gci)
-{
- Bucket* bucket= c_buckets+buck;
- Uint32 tail= bucket->m_buffer_tail;
- Page_pos head= bucket->m_buffer_head;
- Uint32 max_acked = bucket->m_max_acked_gci;
-
- const Uint32 mask = Bucket::BUCKET_TAKEOVER | Bucket::BUCKET_RESEND;
- if(unlikely(bucket->m_state & mask))
- {
- jam();
- ndbout_c("release_gci(%d, %d) -> node failure -> abort", buck, gci);
- return;
- }
-
- bucket->m_max_acked_gci = (max_acked > gci ? max_acked : gci);
- if(unlikely(tail == RNIL))
- {
- return;
- }
-
- if(tail == head.m_page_id)
- {
- if(gci >= head.m_max_gci)
- {
- jam();
- if (ERROR_INSERTED(13034))
- {
- jam();
- SET_ERROR_INSERT_VALUE(13035);
- return;
- }
- if (ERROR_INSERTED(13035))
- {
- CLEAR_ERROR_INSERT_VALUE;
- NodeReceiverGroup rg(CMVMI, c_nodes_in_nodegroup_mask);
- rg.m_nodes.clear(getOwnNodeId());
- signal->theData[0] = 9999;
- sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBA);
- return;
- }
- head.m_page_pos = 0;
- head.m_max_gci = gci;
- head.m_last_gci = 0;
- bucket->m_buffer_head = head;
- }
- return;
- }
- else
- {
- jam();
- Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
- Uint32 max_gci = page->m_max_gci;
- Uint32 next_page = page->m_next_page;
-
- ndbassert(max_gci);
-
- if(gci >= max_gci)
- {
- jam();
- free_page(tail, page);
-
- bucket->m_buffer_tail = next_page;
- signal->theData[0] = SumaContinueB::RELEASE_GCI;
- signal->theData[1] = buck;
- signal->theData[2] = gci;
- sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 3, JBB);
- return;
- }
- else
- {
- //ndbout_c("do nothing...");
- }
- }
-}
-
-static Uint32 g_cnt = 0;
-
-void
-Suma::start_resend(Signal* signal, Uint32 buck)
-{
- printf("start_resend(%d, ", buck);
-
- if(m_out_of_buffer_gci)
- {
- progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
- "Nodefailure while out of event buffer");
- return;
- }
-
- /**
- * Resend from m_max_acked_gci + 1 until max_gci + 1
- */
- Bucket* bucket= c_buckets + buck;
- Page_pos pos= bucket->m_buffer_head;
-
- if(pos.m_page_id == RNIL)
- {
- jam();
- m_active_buckets.set(buck);
- m_gcp_complete_rep_count ++;
- ndbout_c("empty bucket(RNIL) -> active");
- return;
- }
-
- Uint32 min= bucket->m_max_acked_gci + 1;
- Uint32 max = pos.m_max_gci;
-
- ndbrequire(max <= m_max_seen_gci);
-
- if(min > max)
- {
- ndbrequire(pos.m_page_id == bucket->m_buffer_tail);
- m_active_buckets.set(buck);
- m_gcp_complete_rep_count ++;
- ndbout_c("empty bucket -> active");
- return;
- }
-
- g_cnt = 0;
- bucket->m_state |= (Bucket::BUCKET_TAKEOVER | Bucket::BUCKET_RESEND);
- bucket->m_switchover_node = get_responsible_node(buck);
- bucket->m_switchover_gci = max + 1;
-
- m_switchover_buckets.set(buck);
-
- signal->theData[1] = buck;
- signal->theData[2] = min;
- signal->theData[3] = 0;
- signal->theData[4] = 0;
- sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
-
- ndbout_c("min: %d - max: %d) page: %d", min, max, bucket->m_buffer_tail);
- ndbrequire(max >= min);
-}
-
-void
-Suma::resend_bucket(Signal* signal, Uint32 buck, Uint32 min_gci,
- Uint32 pos, Uint32 last_gci)
-{
- Bucket* bucket= c_buckets+buck;
- Uint32 tail= bucket->m_buffer_tail;
-
- Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
- Uint32 max_gci = page->m_max_gci;
- Uint32 next_page = page->m_next_page;
- Uint32 *ptr = page->m_data + pos;
- Uint32 *end = page->m_data + page->m_words_used;
- bool delay = false;
-
- ndbrequire(tail != RNIL);
-
- if(tail == bucket->m_buffer_head.m_page_id)
- {
- max_gci= bucket->m_buffer_head.m_max_gci;
- end= page->m_data + bucket->m_buffer_head.m_page_pos;
- next_page= RNIL;
-
- if(ptr == end)
- {
- delay = true;
- goto next;
- }
- }
- else if(pos == 0 && min_gci > max_gci)
- {
- free_page(tail, page);
- tail = bucket->m_buffer_tail = next_page;
- ndbout_c("pos==0 && min_gci(%d) > max_gci(%d) resend switching page to %d", min_gci, max_gci, tail);
- goto next;
- }
-
-#if 0
- for(Uint32 i = 0; i<page->m_words_used; i++)
- {
- printf("%.8x ", page->m_data[i]);
- if(((i + 1) % 8) == 0)
- printf("\n");
- }
- printf("\n");
-#endif
-
- while(ptr < end)
- {
- Uint32 *src = ptr;
- Uint32 tmp = * src++;
- Uint32 sz = tmp & 0xFFFF;
-
- ptr += sz;
-
- if(! (tmp & (0x8000 << 16)))
- {
- sz--;
- last_gci = * src ++;
- }
- else
- {
- ndbrequire(ptr - sz > page->m_data);
- }
-
- if(last_gci < min_gci)
- {
- continue;
- }
-
- ndbrequire(sz);
- sz --; // remove *len* part of sz
-
- if(sz == 0)
- {
- SubGcpCompleteRep * rep = (SubGcpCompleteRep*)signal->getDataPtrSend();
- rep->gci = last_gci;
- rep->senderRef = reference();
- rep->gcp_complete_rep_count = 1;
-
- char buf[255];
- c_subscriber_nodes.getText(buf);
- ndbout_c("resending GCI: %d rows: %d -> %s", last_gci, g_cnt, buf);
- g_cnt = 0;
-
- NodeReceiverGroup rg(API_CLUSTERMGR, c_subscriber_nodes);
- sendSignal(rg, GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength, JBB);
- }
- else
- {
- const uint buffer_header_sz = 4;
- g_cnt++;
- Uint32 table = * src++ ;
- Uint32 schemaVersion = * src++;
- Uint32 event = * src >> 16;
- Uint32 sz_1 = (* src ++) & 0xFFFF;
- Uint32 any_value = * src++;
-
- ndbassert(sz - buffer_header_sz >= sz_1);
-
- LinearSectionPtr ptr[3];
- const Uint32 nptr= reformat(signal, ptr,
- src, sz_1,
- src + sz_1, sz - buffer_header_sz - sz_1);
- Uint32 ptrLen= 0;
- for(Uint32 i =0; i < nptr; i++)
- ptrLen+= ptr[i].sz;
-
- /**
- * Signal to subscriber(s)
- */
- Ptr<Table> tabPtr;
- if (c_tables.find(tabPtr, table) &&
- tabPtr.p->m_schemaVersion == schemaVersion)
- {
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg;
- data->gci = last_gci;
- data->tableId = table;
- data->requestInfo = 0;
- SubTableData::setOperation(data->requestInfo, event);
- data->logType = 0;
- data->anyValue = any_value;
- data->totalLen = ptrLen;
-
- {
- LocalDLList<Subscriber>
- list(c_subscriberPool,tabPtr.p->c_subscribers);
- SubscriberPtr subbPtr;
- for(list.first(subbPtr); !subbPtr.isNull(); list.next(subbPtr))
- {
- DBUG_PRINT("info",("GSN_SUB_TABLE_DATA to node %d",
- refToNode(subbPtr.p->m_senderRef)));
- data->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB, ptr, nptr);
- }
- }
- }
- }
-
- break;
- }
-
- if(ptr == end && (tail != bucket->m_buffer_head.m_page_id))
- {
- /**
- * release...
- */
- free_page(tail, page);
- tail = bucket->m_buffer_tail = next_page;
- pos = 0;
- last_gci = 0;
- ndbout_c("ptr == end -> resend switching page to %d", tail);
- }
- else
- {
- pos = (ptr - page->m_data);
- }
-
-next:
- if(tail == RNIL)
- {
- bucket->m_state &= ~(Uint32)Bucket::BUCKET_RESEND;
- ndbassert(! (bucket->m_state & Bucket::BUCKET_TAKEOVER));
- ndbout_c("resend done...");
- return;
- }
-
- signal->theData[0] = SumaContinueB::RESEND_BUCKET;
- signal->theData[1] = buck;
- signal->theData[2] = min_gci;
- signal->theData[3] = pos;
- signal->theData[4] = last_gci;
- if(!delay)
- sendSignal(SUMA_REF, GSN_CONTINUEB, signal, 5, JBB);
- else
- sendSignalWithDelay(SUMA_REF, GSN_CONTINUEB, signal, 10, 5);
-}
-
-template void append(DataBuffer<11>&,SegmentedSectionPtr,SectionSegmentPool&);
-
diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.hpp b/storage/ndb/src/kernel/blocks/suma/Suma.hpp
deleted file mode 100644
index 095b7f93bb3..00000000000
--- a/storage/ndb/src/kernel/blocks/suma/Suma.hpp
+++ /dev/null
@@ -1,635 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SUMA_H
-#define SUMA_H
-
-#include <ndb_limits.h>
-#include <SimulatedBlock.hpp>
-
-#include <NodeBitmask.hpp>
-
-#include <SLList.hpp>
-#include <DLList.hpp>
-#include <DLFifoList.hpp>
-#include <KeyTable.hpp>
-#include <DataBuffer.hpp>
-#include <SignalCounter.hpp>
-#include <AttributeHeader.hpp>
-#include <AttributeList.hpp>
-
-#include <signaldata/UtilSequence.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <ndbapi/NdbDictionary.hpp>
-
-class Suma : public SimulatedBlock {
- BLOCK_DEFINES(Suma);
-public:
- Suma(Block_context& ctx);
- virtual ~Suma();
-
- /**
- * Private interface
- */
- void execSUB_CREATE_REQ(Signal* signal);
- void execSUB_REMOVE_REQ(Signal* signal);
-
- void execSUB_START_REQ(Signal* signal);
- void execSUB_STOP_REQ(Signal* signal);
-
- void execSUB_SYNC_REQ(Signal* signal);
- void execSUB_ABORT_SYNC_REQ(Signal* signal);
-
- void execSUB_STOP_CONF(Signal* signal);
- void execSUB_STOP_REF(Signal* signal);
-
- /**
- * Dict interface
- */
-#if 0
- void execLIST_TABLES_REF(Signal* signal);
- void execLIST_TABLES_CONF(Signal* signal);
-#endif
- void execGET_TABINFOREF(Signal* signal);
- void execGET_TABINFO_CONF(Signal* signal);
-
- void execGET_TABLEID_CONF(Signal* signal);
- void execGET_TABLEID_REF(Signal* signal);
-
- void execDROP_TAB_CONF(Signal* signal);
- void execALTER_TAB_REQ(Signal* signal);
- void execCREATE_TAB_CONF(Signal* signal);
- /**
- * Scan interface
- */
- void execSCAN_HBREP(Signal* signal);
- void execSCAN_FRAGREF(Signal* signal);
- void execSCAN_FRAGCONF(Signal* signal);
- void execTRANSID_AI(Signal* signal);
- void execSUB_SYNC_CONTINUE_REF(Signal* signal);
- 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);
-
- /**
- * DIH signals
- */
- void execDI_FCOUNTREF(Signal* signal);
- void execDI_FCOUNTCONF(Signal* signal);
- void execDIGETPRIMREF(Signal* signal);
- 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);
-
-public:
-
- void suma_ndbrequire(bool v);
-
- typedef DataBuffer<15> TableList;
-
- union FragmentDescriptor {
- struct {
- Uint16 m_fragmentNo;
- Uint16 m_nodeId;
- } m_fragDesc;
- Uint32 m_dummy;
- };
-
- /**
- * Used when sending SCAN_FRAG
- */
- union AttributeDescriptor {
- struct {
- Uint16 attrId;
- Uint16 unused;
- } m_attrDesc;
- Uint32 m_dummy;
- };
-
- struct Subscriber {
- Uint32 m_senderRef;
- Uint32 m_senderData;
- Uint32 m_subPtrI; //reference to subscription
- Uint32 nextList;
-
- union { Uint32 nextPool; Uint32 prevList; };
- };
- typedef Ptr<Subscriber> SubscriberPtr;
-
- /**
- * Subscriptions
- */
-
- struct Subscription {
- Subscription() {}
- Uint32 m_senderRef;
- Uint32 m_senderData;
- Uint32 m_subscriptionId;
- Uint32 m_subscriptionKey;
- Uint32 m_subscriptionType;
- Uint16 m_options;
-
- enum Options {
- REPORT_ALL = 0x1,
- REPORT_SUBSCRIBE = 0x2
- };
-
- enum State {
- UNDEFINED,
- LOCKED,
- DEFINED,
- DROPPED
- };
- State m_state;
- Uint32 n_subscribers;
-
- Uint32 nextHash;
- union { Uint32 prevHash; Uint32 nextPool; };
-
- Uint32 hashValue() const {
- return m_subscriptionId + m_subscriptionKey;
- }
-
- bool equal(const Subscription & s) const {
- return
- m_subscriptionId == s.m_subscriptionId &&
- m_subscriptionKey == s.m_subscriptionKey;
- }
- /**
- * The following holds the tables included
- * in the subscription.
- */
- Uint32 m_tableId;
- Uint32 m_table_ptrI;
- Uint32 m_current_sync_ptrI;
- };
- typedef Ptr<Subscription> SubscriptionPtr;
-
- class Table;
- friend class Table;
- typedef Ptr<Table> TablePtr;
-
- struct SyncRecord {
- SyncRecord(Suma& s, DataBuffer<15>::DataBufferPool & p)
- : m_tableList(p), suma(s)
-#ifdef ERROR_INSERT
- , cerrorInsert(s.cerrorInsert)
-#endif
- {}
-
- void release();
-
- Uint32 m_senderRef;
- Uint32 m_senderData;
-
- Uint32 m_subscriptionPtrI;
- Uint32 m_error;
- Uint32 m_currentTable;
- TableList m_tableList; // Tables to sync
- TableList::DataBufferIterator m_tableList_it;
-
- /**
- * Sync data
- */
- Uint32 m_currentFragment; // Index in tabPtr.p->m_fragments
- DataBuffer<15>::Head m_attributeList; // Attribute if other than default
- DataBuffer<15>::Head m_tabList; // tables if other than default
-
- Uint32 m_currentTableId; // Current table
- Uint32 m_currentNoOfAttributes; // No of attributes for current table
-
- void startScan(Signal*);
- void nextScan(Signal*);
- bool getNextFragment(TablePtr * tab, FragmentDescriptor * fd);
- void completeScan(Signal*, int error= 0);
-
- Suma & suma;
-#ifdef ERROR_INSERT
- UintR &cerrorInsert;
-#endif
- BlockNumber number() const { return suma.number(); }
- void progError(int line, int cause, const char * extra) {
- suma.progError(line, cause, extra);
- }
-
- Uint32 prevList; Uint32 ptrI;
- union { Uint32 nextPool; Uint32 nextList; };
- };
- friend struct SyncRecord;
-
- int initTable(Signal *signal,Uint32 tableId, TablePtr &tabPtr,
- Ptr<SyncRecord> syncPtr);
- int initTable(Signal *signal,Uint32 tableId, TablePtr &tabPtr,
- SubscriberPtr subbPtr);
- int initTable(Signal *signal,Uint32 tableId, TablePtr &tabPtr);
-
- int completeOneSubscriber(Signal* signal, TablePtr tabPtr, SubscriberPtr subbPtr);
- void completeAllSubscribers(Signal* signal, TablePtr tabPtr);
- void completeInitTable(Signal* signal, TablePtr tabPtr);
-
- struct Table {
- Table() { m_tableId = ~0; n_subscribers = 0; }
- void release(Suma&);
- void checkRelease(Suma &suma);
-
- DLList<Subscriber>::Head c_subscribers;
- DLList<SyncRecord>::Head c_syncRecords;
-
- enum State {
- UNDEFINED,
- DEFINING,
- DEFINED,
- DROPPED,
- ALTERED
- };
- State m_state;
-
- Uint32 m_ptrI;
- SubscriberPtr m_drop_subbPtr;
-
- Uint32 n_subscribers;
- bool m_reportAll;
-
- bool parseTable(SegmentedSectionPtr ptr, Suma &suma);
- /**
- * Create triggers
- */
- int setupTrigger(Signal* signal, Suma &suma);
- void completeTrigger(Signal* signal);
- void createAttributeMask(AttributeMask&, Suma &suma);
-
- /**
- * Drop triggers
- */
- void dropTrigger(Signal* signal,Suma&);
- void runDropTrigger(Signal* signal, Uint32 triggerId,Suma&);
-
- /**
- * Sync meta
- */
-#if 0
- void runLIST_TABLES_CONF(Signal* signal);
-#endif
-
- union { Uint32 m_tableId; Uint32 key; };
- Uint32 m_schemaVersion;
- Uint8 m_hasTriggerDefined[3]; // Insert/Update/Delete
- Uint8 m_hasOutstandingTriggerReq[3]; // Insert/Update/Delete
- Uint32 m_triggerIds[3]; // Insert/Update/Delete
-
- Uint32 m_error;
- /**
- * Default order in which to ask for attributes during scan
- * 1) Fixed, not nullable
- * 2) Rest
- */
- DataBuffer<15>::Head m_attributes; // Attribute id's
-
- /**
- * Fragments
- */
- Uint32 m_fragCount;
- DataBuffer<15>::Head m_fragments; // Fragment descriptors
-
- /**
- * Hash table stuff
- */
- Uint32 nextHash;
- union { Uint32 prevHash; Uint32 nextPool; };
- Uint32 hashValue() const {
- return m_tableId;
- }
- bool equal(const Table& rec) const {
- return m_tableId == rec.m_tableId;
- }
- };
-
- /**
- *
- */
- DLList<Subscriber> c_metaSubscribers;
- DLList<Subscriber> c_removeDataSubscribers;
-
- /**
- * Lists
- */
- KeyTable<Table> c_tables;
- DLHashTable<Subscription> c_subscriptions;
-
- /**
- * Pools
- */
- ArrayPool<Subscriber> c_subscriberPool;
- ArrayPool<Table> c_tablePool;
- ArrayPool<Subscription> c_subscriptionPool;
- ArrayPool<SyncRecord> c_syncPool;
- DataBuffer<15>::DataBufferPool c_dataBufferPool;
-
- NodeBitmask c_failedApiNodes;
-
- /**
- * Functions
- */
- bool removeSubscribersOnNode(Signal *signal, Uint32 nodeId);
-
- bool checkTableTriggers(SegmentedSectionPtr ptr);
-
- void addTableId(Uint32 TableId,
- SubscriptionPtr subPtr, SyncRecord *psyncRec);
-
- void sendSubIdRef(Signal* signal,Uint32 senderRef,Uint32 senderData,Uint32 errorCode);
- void sendSubCreateRef(Signal* signal, Uint32 errorCode);
- void sendSubStartRef(Signal*, SubscriberPtr, Uint32 errorCode, SubscriptionData::Part);
- void sendSubStartRef(Signal* signal, Uint32 errorCode);
- void sendSubStopRef(Signal* signal, Uint32 errorCode);
- void sendSubSyncRef(Signal* signal, Uint32 errorCode);
- void sendSubRemoveRef(Signal* signal, const SubRemoveReq& ref,
- Uint32 errorCode);
- void sendSubStartComplete(Signal*, SubscriberPtr, Uint32,
- SubscriptionData::Part);
- void sendSubStopComplete(Signal*, SubscriberPtr);
- void sendSubStopReq(Signal* signal, bool unlock= false);
-
- void completeSubRemove(SubscriptionPtr subPtr);
-
- void reportAllSubscribers(Signal *signal,
- NdbDictionary::Event::_TableEvent table_event,
- SubscriptionPtr subPtr,
- SubscriberPtr subbPtr);
-
- Uint32 getFirstGCI(Signal* signal);
-
- /**
- * Table admin
- */
- void convertNameToId( SubscriptionPtr subPtr, Signal * signal);
-
- /**
- * Public interface
- */
- void execCREATE_SUBSCRIPTION_REQ(Signal* signal);
- void execDROP_SUBSCRIPTION_REQ(Signal* signal);
-
- void execSTART_SUBSCRIPTION_REQ(Signal* signal);
- void execSTOP_SUBSCRIPTION_REQ(Signal* signal);
-
- void execSYNC_SUBSCRIPTION_REQ(Signal* signal);
- void execABORT_SYNC_REQ(Signal* signal);
-
- /**
- * Framework signals
- */
-
- void getNodeGroupMembers(Signal* signal);
-
- void execREAD_CONFIG_REQ(Signal* signal);
-
- void execSTTOR(Signal* signal);
- void sendSTTORRY(Signal*);
- void execNDB_STTOR(Signal* signal);
- void execDUMP_STATE_ORD(Signal* signal);
- void execREAD_NODESCONF(Signal* signal);
- void execNODE_FAILREP(Signal* signal);
- void execINCL_NODEREQ(Signal* signal);
- void execSIGNAL_DROPPED_REP(Signal* signal);
- void execAPI_START_REP(Signal* signal);
- void execAPI_FAILREQ(Signal* signal) ;
-
- void execSUB_GCP_COMPLETE_ACK(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_ABORT_SYNC_REF(Signal* signal);
- void execSUB_ABORT_SYNC_CONF(Signal* signal);
-
- void execSUMA_START_ME_REQ(Signal* signal);
- void execSUMA_START_ME_REF(Signal* signal);
- void execSUMA_START_ME_CONF(Signal* signal);
- void execSUMA_HANDOVER_REQ(Signal* signal);
- void execSUMA_HANDOVER_REF(Signal* signal);
- void execSUMA_HANDOVER_CONF(Signal* signal);
-
- /**
- * Subscription generation interface
- */
- void createSequence(Signal* signal);
- void createSequenceReply(Signal* signal,
- UtilSequenceConf* conf,
- UtilSequenceRef* ref);
- void execUTIL_SEQUENCE_CONF(Signal* signal);
- void execUTIL_SEQUENCE_REF(Signal* signal);
- void execCREATE_SUBID_REQ(Signal* signal);
-
- /**
- * for Suma that is restarting another
- */
-
- struct Restart {
- Restart(Suma& s);
-
- Suma & suma;
- Uint32 nodeId;
-
- DLHashTable<Subscription>::Iterator c_subIt;
- KeyTable<Table>::Iterator c_tabIt;
-
- void progError(int line, int cause, const char * extra) {
- suma.progError(line, cause, extra);
- }
-
- void resetNode(Uint32 sumaRef);
- void runSUMA_START_ME_REQ(Signal*, Uint32 sumaRef);
- void startNode(Signal*, Uint32 sumaRef);
-
- void createSubscription(Signal* signal, Uint32 sumaRef);
- void nextSubscription(Signal* signal, Uint32 sumaRef);
- void runSUB_CREATE_CONF(Signal* signal);
- void completeSubscription(Signal* signal, Uint32 sumaRef);
-
- void startSubscriber(Signal* signal, Uint32 sumaRef);
- void nextSubscriber(Signal* signal, Uint32 sumaRef, SubscriberPtr subbPtr);
- void sendSubStartReq(SubscriptionPtr subPtr, SubscriberPtr subbPtr,
- Signal* signal, Uint32 sumaRef);
- void runSUB_START_CONF(Signal* signal);
- void completeSubscriber(Signal* signal, Uint32 sumaRef);
-
- void completeRestartingNode(Signal* signal, Uint32 sumaRef);
- void resetRestart(Signal* signal);
- } Restart;
-
-private:
- friend class Restart;
- /**
- * Variables
- */
- NodeId c_masterNodeId;
- NdbNodeBitmask c_alive_nodes;
-
- /**
- * for restarting Suma not to start sending data too early
- */
- struct Startup
- {
- bool m_wait_handover;
- Uint32 m_restart_server_node_id;
- NdbNodeBitmask m_handover_nodes;
- } c_startup;
-
- NodeBitmask c_connected_nodes; // (NODE/API) START REP / (API/NODE) FAIL REQ
- NodeBitmask c_subscriber_nodes; //
-
- /**
- * for all Suma's to keep track of other Suma's in Node group
- */
- Uint32 c_nodeGroup;
- Uint32 c_noNodesInGroup;
- Uint32 c_nodesInGroup[MAX_REPLICAS];
- NdbNodeBitmask c_nodes_in_nodegroup_mask; // NodeId's of nodes in nodegroup
-
- void send_start_me_req(Signal* signal);
- void check_start_handover(Signal* signal);
- void send_handover_req(Signal* signal);
-
- Uint32 get_responsible_node(Uint32 B) const;
- Uint32 get_responsible_node(Uint32 B, const NdbNodeBitmask& mask) const;
- bool check_switchover(Uint32 bucket, Uint32 gci);
-
-public:
- struct Page_pos
- {
- Uint32 m_page_id;
- Uint32 m_page_pos;
- Uint32 m_max_gci; // max gci on page
- Uint32 m_last_gci; // last gci on page
- };
-private:
-
- struct Bucket
- {
- enum {
- BUCKET_STARTING = 0x1 // On starting node
- ,BUCKET_HANDOVER = 0x2 // On running node
- ,BUCKET_TAKEOVER = 0x4 // On takeing over node
- ,BUCKET_RESEND = 0x8 // On takeing over node
- };
- Uint16 m_state;
- Uint16 m_switchover_node;
- Uint16 m_nodes[MAX_REPLICAS];
- Uint32 m_switchover_gci;
- Uint32 m_max_acked_gci;
- Uint32 m_buffer_tail; // Page
- Page_pos m_buffer_head;
- };
-
- struct Buffer_page
- {
- STATIC_CONST( DATA_WORDS = 8192 - 9);
- Uint32 _tupdata1;
- Uint32 _tupdata2;
- Uint32 _tupdata3;
- Uint32 _tupdata4;
- Uint32 m_page_state; // Used by TUP buddy algorithm
- Uint32 m_page_chunk_ptr_i;
- Uint32 m_next_page;
- Uint32 m_words_used; //
- Uint32 m_max_gci; //
- Uint32 m_data[DATA_WORDS];
- };
-
- STATIC_CONST( NO_OF_BUCKETS = 24 ); // 24 = 4*3*2*1!
- Uint32 c_no_of_buckets;
- struct Bucket c_buckets[NO_OF_BUCKETS];
-
- STATIC_CONST( BUCKET_MASK_SIZE = (((NO_OF_BUCKETS+31)>> 5)) );
- typedef Bitmask<BUCKET_MASK_SIZE> Bucket_mask;
- Bucket_mask m_active_buckets;
- Bucket_mask m_switchover_buckets;
-
- class Dbtup* m_tup;
- void init_buffers();
- Uint32* get_buffer_ptr(Signal*, Uint32 buck, Uint32 gci, Uint32 sz);
- Uint32 seize_page();
- void free_page(Uint32 page_id, Buffer_page* page);
- void out_of_buffer(Signal*);
- void out_of_buffer_release(Signal* signal, Uint32 buck);
-
- void start_resend(Signal*, Uint32 bucket);
- void resend_bucket(Signal*, Uint32 bucket, Uint32 gci,
- Uint32 page_pos, Uint32 last_gci);
- void release_gci(Signal*, Uint32 bucket, Uint32 gci);
-
- Uint32 m_max_seen_gci; // FIRE_TRIG_ORD
- Uint32 m_max_sent_gci; // FIRE_TRIG_ORD -> send
- Uint32 m_last_complete_gci; // SUB_GCP_COMPLETE_REP
- Uint32 m_out_of_buffer_gci;
- Uint32 m_gcp_complete_rep_count;
-
- struct Gcp_record
- {
- Uint32 m_gci;
- NodeBitmask m_subscribers;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- ArrayPool<Gcp_record> c_gcp_pool;
- DLFifoList<Gcp_record> c_gcp_list;
-
- struct Page_chunk
- {
- Uint32 m_page_id;
- Uint32 m_size;
- Uint32 m_free;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
-
- Uint32 m_first_free_page;
- ArrayPool<Page_chunk> c_page_chunk_pool;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.txt b/storage/ndb/src/kernel/blocks/suma/Suma.txt
deleted file mode 100644
index eba031226ef..00000000000
--- a/storage/ndb/src/kernel/blocks/suma/Suma.txt
+++ /dev/null
@@ -1,192 +0,0 @@
-Protocols involving SUMA:
-
-
-
-USER SUMA UTIL
-========================================================
-CREATE_SUBID_REQ
-------------------------->
- UTIL_SEQUENCE
- ---------------------->
- <----------------------
-CREATE_SUBID_CONF
-<-------------------------
-
-
-
-
-USER SUMA DICT
-========================================================
-SUB_CREATE_REQ
-------------------------->
- case SelectiveTableSnapshot:
- GET_TABLEID
- ---------------------->
- <----------------------
-SUB_CREATE_CONF
-<-------------------------
-
-
-
-
-
-USER SUMA DICT
-========================================================
-SUB_SYNC_REQ::MetaData
-------------------------->
- case DatabaseSnapshot:
- LIST_TABLES
- ---------------------->
- <----------------------
-for each table...
- GET_TABINFO
- ---------------------->
- <----------------------
-SUB_META_DATA DIH
-<------------------------- =======
- DI_FCOUNT
- ---------------------->
- <----------------------
- DI_GETPRIM
- ---------------------->
- <----------------------
-..end for each table
-SUB_SYNC_CONF
-<-------------------------
-
-
-
-
-USER SUMA LQH
-========================================================
-SUB_SYNC_REQ::TableData
-------------------------->
-for each table...
- SCAN_FRAG_REQ
- ---------------------->
- ATTRINFO
- ---------------------->
- SCAN_FRAG_CONF
- <----------------------
-SUB_SYNC_CONTINUE
-<-------------------------
-------------------------->
- SCAN_NEXTREQ
- ---------------------->
-...end for each table
-
-
-
-??????????
- SCAN_HBREP
- <----------------------
-
-
-
-USER SUMA
-===============================
-SUB_START_REQ::MetaData
-------------------------->
-SUB_START_CONF
-<-------------------------
-
-
-
-USER SUMA TUP
-========================================================
-SUB_START_REQ::TableData
-------------------------->
-for each table...
- CREATE_TRIG
- ---------------------->
- <----------------------
-...end for each table
-SUB_START_CONF
-<-------------------------
-
-
-USER SUMA XXX
-========================================================
- TRANSID_AI
- <----------------------
-SUB_TABLE_DATA
-<-------------------------
-
-
-
-
-
-USER SUMA XXX
-========================================================
- TRIG_ATTRINFO
- <----------------------
- FIRE_TRIG_ORD
- <----------------------
-SUB_TABLE_DATA
-<-------------------------
-
-
-
-USER SUMA XXX
-========================================================
- SUB_GCP_COMPLETE_REP
- <----------------------
-SUB_GCP_COMPLETE_REP
-<-------------------------
-
-for event only:
-SUB_GCP_COMPLETE_ACK
-------------------------->
- when all subscribers have sent ACK on gci
- send to all other suma's in node group:
- SUB_GCP_COMPLETE_ACK
- ---------------------->
-
-
-USER SUMA
-===============================
-SUB_STOP_REQ
-------------------------->
-SUB_STOP_CONF
-<-------------------------
-
-
-
-USER SUMA
-===============================
-SUB_REMOVE_REQ
-------------------------->
-SUB_REMOVE_CONF
-<-------------------------
-
-
-
-MASTER SUMA RESTARTING SUMA
-=========================================
-INCL_NODEREQ
-<---------------------------------------------------------
-for each subscription...
-SUB_CREATE_REQ
-------------------------->...
-<-------------------------
-SUB_SYNC_REQ::MetaData
-------------------------->...
-<-------------------------
-... end for each subscription
-
-
- SUMA_START_ME (sent asynchronously in start phase 5 to all suma's in node group)
-<-------------------------
- ------------------------->
-
-for each subscriber...
-SUB_START_REQ (not before SUMA_START_ME)
-------------------------->
-<-------------------------
-... end for each subscriber
-
-SUMA_HANDOVER_REQ
-------------------------->
- SUMA_HANDOVER_CONF (to all suma's in node group)
-<-------------------------
- ------------------------->
diff --git a/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp b/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp
deleted file mode 100644
index 9d4e2c41907..00000000000
--- a/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (c) 2003-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "Suma.hpp"
-
-#include <Properties.hpp>
-#include <Configuration.hpp>
-
-Suma::Suma(Block_context& ctx) :
- SimulatedBlock(SUMA, ctx),
- c_metaSubscribers(c_subscriberPool),
- c_removeDataSubscribers(c_subscriberPool),
- c_tables(c_tablePool),
- c_subscriptions(c_subscriptionPool),
- Restart(*this),
- c_gcp_list(c_gcp_pool)
-{
- BLOCK_CONSTRUCTOR(Suma);
-
- // 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_START_REP, &Suma::execAPI_START_REP, true);
- 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_START_CONF, &Suma::execSUB_START_CONF);
- addRecSignal(GSN_SUB_START_REF, &Suma::execSUB_START_REF);
-
- addRecSignal(GSN_SUMA_START_ME_REQ, &Suma::execSUMA_START_ME_REQ);
- addRecSignal(GSN_SUMA_START_ME_REF, &Suma::execSUMA_START_ME_REF);
- addRecSignal(GSN_SUMA_START_ME_CONF, &Suma::execSUMA_START_ME_CONF);
- addRecSignal(GSN_SUMA_HANDOVER_REQ, &Suma::execSUMA_HANDOVER_REQ);
- addRecSignal(GSN_SUMA_HANDOVER_REF, &Suma::execSUMA_HANDOVER_REF);
- addRecSignal(GSN_SUMA_HANDOVER_CONF, &Suma::execSUMA_HANDOVER_CONF);
-
- addRecSignal(GSN_SUB_GCP_COMPLETE_ACK,
- &Suma::execSUB_GCP_COMPLETE_ACK);
-
- /**
- * SUMA participant if
- */
- addRecSignal(GSN_SUB_CREATE_REQ, &Suma::execSUB_CREATE_REQ);
- addRecSignal(GSN_SUB_REMOVE_REQ, &Suma::execSUB_REMOVE_REQ);
- addRecSignal(GSN_SUB_START_REQ, &Suma::execSUB_START_REQ);
- addRecSignal(GSN_SUB_STOP_REQ, &Suma::execSUB_STOP_REQ);
- addRecSignal(GSN_SUB_STOP_REF, &Suma::execSUB_STOP_REF);
- addRecSignal(GSN_SUB_STOP_CONF, &Suma::execSUB_STOP_CONF);
- addRecSignal(GSN_SUB_SYNC_REQ, &Suma::execSUB_SYNC_REQ);
-
- /**
- * Dict interface
- */
- addRecSignal(GSN_DROP_TAB_CONF, &Suma::execDROP_TAB_CONF);
- addRecSignal(GSN_ALTER_TAB_REQ, &Suma::execALTER_TAB_REQ);
- addRecSignal(GSN_CREATE_TAB_CONF, &Suma::execCREATE_TAB_CONF);
-
-#if 0
- addRecSignal(GSN_LIST_TABLES_CONF, &Suma::execLIST_TABLES_CONF);
-#endif
- addRecSignal(GSN_GET_TABINFO_CONF, &Suma::execGET_TABINFO_CONF);
- addRecSignal(GSN_GET_TABINFOREF, &Suma::execGET_TABINFOREF);
-#if 0
- addRecSignal(GSN_GET_TABLEID_CONF, &Suma::execGET_TABLEID_CONF);
- addRecSignal(GSN_GET_TABLEID_REF, &Suma::execGET_TABLEID_REF);
-#endif
- /**
- * Dih interface
- */
- addRecSignal(GSN_DI_FCOUNTCONF, &Suma::execDI_FCOUNTCONF);
- addRecSignal(GSN_DI_FCOUNTREF, &Suma::execDI_FCOUNTREF);
- addRecSignal(GSN_DIGETPRIMCONF, &Suma::execDIGETPRIMCONF);
-
- /**
- * Scan interface
- */
- addRecSignal(GSN_SCAN_HBREP, &Suma::execSCAN_HBREP);
- addRecSignal(GSN_TRANSID_AI, &Suma::execTRANSID_AI);
- addRecSignal(GSN_SCAN_FRAGREF, &Suma::execSCAN_FRAGREF);
- addRecSignal(GSN_SCAN_FRAGCONF, &Suma::execSCAN_FRAGCONF);
-#if 0
- addRecSignal(GSN_SUB_SYNC_CONTINUE_REF,
- &Suma::execSUB_SYNC_CONTINUE_REF);
-#endif
- addRecSignal(GSN_SUB_SYNC_CONTINUE_CONF,
- &Suma::execSUB_SYNC_CONTINUE_CONF);
-
- /**
- * Trigger stuff
- */
- addRecSignal(GSN_TRIG_ATTRINFO, &Suma::execTRIG_ATTRINFO);
- addRecSignal(GSN_FIRE_TRIG_ORD, &Suma::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,
- &Suma::execSUB_GCP_COMPLETE_REP);
-
- c_startup.m_restart_server_node_id = RNIL; // Server for my NR
-}
-
-Suma::~Suma()
-{
-}
-
-BLOCK_FUNCTIONS(Suma)
-
diff --git a/storage/ndb/src/kernel/blocks/trix/Trix.cpp b/storage/ndb/src/kernel/blocks/trix/Trix.cpp
deleted file mode 100644
index 5689e602ff0..00000000000
--- a/storage/ndb/src/kernel/blocks/trix/Trix.cpp
+++ /dev/null
@@ -1,997 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "Trix.hpp"
-
-#include <string.h>
-#include <kernel_types.h>
-#include <NdbOut.hpp>
-
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/NodeFailRep.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/BuildIndx.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <signaldata/UtilPrepare.hpp>
-#include <signaldata/UtilExecute.hpp>
-#include <signaldata/UtilRelease.hpp>
-#include <SectionReader.hpp>
-#include <AttributeHeader.hpp>
-
-#define CONSTRAINT_VIOLATION 893
-
-#define DEBUG(x) { ndbout << "TRIX::" << x << endl; }
-
-/**
- *
- */
-Trix::Trix(Block_context& ctx) :
- SimulatedBlock(TRIX, ctx),
- c_theNodes(c_theNodeRecPool),
- c_masterNodeId(0),
- c_masterTrixRef(0),
- c_noNodesFailed(0),
- c_noActiveNodes(0),
- c_theSubscriptions(c_theSubscriptionRecPool)
-{
- 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);
- addRecSignal(GSN_READ_NODESREF, &Trix::execREAD_NODESREF);
- addRecSignal(GSN_NODE_FAILREP, &Trix::execNODE_FAILREP);
- addRecSignal(GSN_INCL_NODEREQ, &Trix::execINCL_NODEREQ);
- addRecSignal(GSN_DUMP_STATE_ORD, &Trix::execDUMP_STATE_ORD);
-
- // Index build
- addRecSignal(GSN_BUILDINDXREQ, &Trix::execBUILDINDXREQ);
- // Dump testing
- addRecSignal(GSN_BUILDINDXCONF, &Trix::execBUILDINDXCONF);
- addRecSignal(GSN_BUILDINDXREF, &Trix::execBUILDINDXREF);
-
-
- addRecSignal(GSN_UTIL_PREPARE_CONF, &Trix::execUTIL_PREPARE_CONF);
- addRecSignal(GSN_UTIL_PREPARE_REF, &Trix::execUTIL_PREPARE_REF);
- addRecSignal(GSN_UTIL_EXECUTE_CONF, &Trix::execUTIL_EXECUTE_CONF);
- addRecSignal(GSN_UTIL_EXECUTE_REF, &Trix::execUTIL_EXECUTE_REF);
- addRecSignal(GSN_UTIL_RELEASE_CONF, &Trix::execUTIL_RELEASE_CONF);
- addRecSignal(GSN_UTIL_RELEASE_REF, &Trix::execUTIL_RELEASE_REF);
-
-
- // Suma signals
- addRecSignal(GSN_SUB_CREATE_CONF, &Trix::execSUB_CREATE_CONF);
- addRecSignal(GSN_SUB_CREATE_REF, &Trix::execSUB_CREATE_REF);
- addRecSignal(GSN_SUB_REMOVE_CONF, &Trix::execSUB_REMOVE_CONF);
- addRecSignal(GSN_SUB_REMOVE_REF, &Trix::execSUB_REMOVE_REF);
- addRecSignal(GSN_SUB_SYNC_CONF, &Trix::execSUB_SYNC_CONF);
- addRecSignal(GSN_SUB_SYNC_REF, &Trix::execSUB_SYNC_REF);
- addRecSignal(GSN_SUB_SYNC_CONTINUE_REQ, &Trix::execSUB_SYNC_CONTINUE_REQ);
- 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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- // Allocate pool sizes
- c_theAttrOrderBufferPool.setSize(100);
- c_theSubscriptionRecPool.setSize(100);
-
- DLList<SubscriptionRecord> subscriptions(c_theSubscriptionRecPool);
- SubscriptionRecPtr subptr;
- while(subscriptions.seize(subptr) == true) {
- new (subptr.p) SubscriptionRecord(c_theAttrOrderBufferPool);
- }
- subscriptions.release();
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
-/**
- *
- */
-void Trix::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- //const Uint32 startphase = signal->theData[1];
- const Uint32 theSignalKey = signal->theData[6];
-
- signal->theData[0] = theSignalKey;
- signal->theData[3] = 1;
- signal->theData[4] = 255; // No more start phases from missra
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
- return;
-}//Trix::execSTTOR()
-
-/**
- *
- */
-void Trix::execNDB_STTOR(Signal* signal)
-{
- jamEntry();
- BlockReference ndbcntrRef = signal->theData[0];
- Uint16 startphase = signal->theData[2]; /* RESTART PHASE */
- Uint16 mynode = signal->theData[1];
- //Uint16 restarttype = signal->theData[3];
- //UintR configInfo1 = signal->theData[6]; /* CONFIGRATION INFO PART 1 */
- //UintR configInfo2 = signal->theData[7]; /* CONFIGRATION INFO PART 2 */
- switch (startphase) {
- case 3:
- jam();
- /* SYMBOLIC START PHASE 4 */
- /* ABSOLUTE PHASE 5 */
- /* REQUEST NODE IDENTITIES FROM DBDIH */
- signal->theData[0] = calcTrixBlockRef(mynode);
- sendSignal(ndbcntrRef, GSN_READ_NODESREQ, signal, 1, JBB);
- return;
- break;
- case 6:
- break;
- default:
- break;
- }
-}
-
-/**
- *
- */
-void Trix::execREAD_NODESCONF(Signal* signal)
-{
- jamEntry();
-
- ReadNodesConf * const readNodes = (ReadNodesConf *)signal->getDataPtr();
- //Uint32 noOfNodes = readNodes->noOfNodes;
- NodeRecPtr nodeRecPtr;
-
- c_masterNodeId = readNodes->masterNodeId;
- c_masterTrixRef = RNIL;
- c_noNodesFailed = 0;
-
- for(unsigned i = 0; i < MAX_NDB_NODES; i++) {
- jam();
- if(NodeBitmask::get(readNodes->allNodes, i)) {
- // Node is defined
- jam();
- ndbrequire(c_theNodes.seizeId(nodeRecPtr, i));
- nodeRecPtr.p->trixRef = calcTrixBlockRef(i);
- if (i == c_masterNodeId) {
- c_masterTrixRef = nodeRecPtr.p->trixRef;
- }
- if(NodeBitmask::get(readNodes->inactiveNodes, i)){
- // Node is not active
- jam();
- /**-----------------------------------------------------------------
- * THIS NODE IS DEFINED IN THE CLUSTER BUT IS NOT ALIVE CURRENTLY.
- * WE ADD THE NODE TO THE SET OF FAILED NODES AND ALSO SET THE
- * BLOCKSTATE TO BUSY TO AVOID ADDING TRIGGERS OR INDEXES WHILE
- * NOT ALL NODES ARE ALIVE.
- *------------------------------------------------------------------*/
- arrGuard(c_noNodesFailed, MAX_NDB_NODES);
- nodeRecPtr.p->alive = false;
- c_noNodesFailed++;
- c_blockState = Trix::NODE_FAILURE;
- }
- else {
- // Node is active
- jam();
- c_noActiveNodes++;
- nodeRecPtr.p->alive = true;
- }
- }
- }
- if (c_noNodesFailed == 0) {
- c_blockState = Trix::STARTED;
- }
-}
-
-/**
- *
- */
-void Trix::execREAD_NODESREF(Signal* signal)
-{
- // NYI
-}
-
-/**
- *
- */
-void Trix::execNODE_FAILREP(Signal* signal)
-{
- jamEntry();
- NodeFailRep * const nodeFail = (NodeFailRep *) signal->getDataPtr();
-
- //Uint32 failureNr = nodeFail->failNo;
- //Uint32 numberNodes = nodeFail->noOfNodes;
- Uint32 masterNodeId = nodeFail->masterNodeId;
-
- NodeRecPtr nodeRecPtr;
-
- for(c_theNodes.first(nodeRecPtr);
- nodeRecPtr.i != RNIL;
- c_theNodes.next(nodeRecPtr)) {
- if(NodeBitmask::get(nodeFail->theNodes, nodeRecPtr.i)) {
- nodeRecPtr.p->alive = false;
- c_noNodesFailed++;
- c_noActiveNodes--;
- }
- }
- if (c_masterNodeId != masterNodeId) {
- c_masterNodeId = masterNodeId;
- NodeRecord* nodeRec = c_theNodes.getPtr(masterNodeId);
- c_masterTrixRef = nodeRec->trixRef;
- }
-}
-
-/**
- *
- */
-void Trix::execINCL_NODEREQ(Signal* signal)
-{
- jamEntry();
- UintR node_id = signal->theData[1];
- NodeRecord* nodeRec = c_theNodes.getPtr(node_id);
- nodeRec->alive = true;
- c_noNodesFailed--;
- c_noActiveNodes++;
- nodeRec->trixRef = calcTrixBlockRef(node_id);
- if (c_noNodesFailed == 0) {
- c_blockState = Trix::STARTED;
- }
-}
-
-// Debugging
-void
-Trix::execDUMP_STATE_ORD(Signal* signal)
-{
- jamEntry();
-
- DumpStateOrd * dumpStateOrd = (DumpStateOrd *)signal->getDataPtr();
-
- switch(dumpStateOrd->args[0]) {
- case(300): {// ok
- // index2 -T; index2 -I -n10000; index2 -c
- // all dump 300 0 0 0 0 0 4 2
- // select_count INDEX0000
- BuildIndxReq * buildIndxReq = (BuildIndxReq *)signal->getDataPtrSend();
-
- MEMCOPY_NO_WORDS(buildIndxReq,
- signal->theData + 1,
- BuildIndxReq::SignalLength);
- buildIndxReq->setUserRef(reference()); // return to me
- buildIndxReq->setParallelism(10);
- Uint32 indexColumns[1] = {1};
- Uint32 keyColumns[1] = {0};
- struct LinearSectionPtr orderPtr[2];
- buildIndxReq->setColumnOrder(indexColumns, 1, keyColumns, 1, orderPtr);
- sendSignal(reference(),
- GSN_BUILDINDXREQ,
- signal,
- BuildIndxReq::SignalLength,
- JBB,
- orderPtr,
- BuildIndxReq::NoOfSections);
- break;
- }
- case(301): { // ok
- // index2 -T; index2 -I -n10000; index2 -c -p
- // all dump 301 0 0 0 0 0 4 2
- // select_count INDEX0000
- BuildIndxReq * buildIndxReq = (BuildIndxReq *)signal->getDataPtrSend();
-
- MEMCOPY_NO_WORDS(buildIndxReq,
- signal->theData + 1,
- BuildIndxReq::SignalLength);
- buildIndxReq->setUserRef(reference()); // return to me
- buildIndxReq->setParallelism(10);
- Uint32 indexColumns[2] = {0, 1};
- Uint32 keyColumns[1] = {0};
- struct LinearSectionPtr orderPtr[2];
- buildIndxReq->setColumnOrder(indexColumns, 2, keyColumns, 1, orderPtr);
- sendSignal(reference(),
- GSN_BUILDINDXREQ,
- signal,
- BuildIndxReq::SignalLength,
- JBB,
- orderPtr,
- BuildIndxReq::NoOfSections);
- break;
- }
- case(302): { // ok
- // index -T; index -I -n1000; index -c -p
- // all dump 302 0 0 0 0 0 4 2
- // select_count PNUMINDEX0000
- BuildIndxReq * buildIndxReq = (BuildIndxReq *)signal->getDataPtrSend();
-
- MEMCOPY_NO_WORDS(buildIndxReq,
- signal->theData + 1,
- BuildIndxReq::SignalLength);
- buildIndxReq->setUserRef(reference()); // return to me
- buildIndxReq->setParallelism(10);
- Uint32 indexColumns[3] = {0, 3, 5};
- Uint32 keyColumns[1] = {0};
- struct LinearSectionPtr orderPtr[2];
- buildIndxReq->setColumnOrder(indexColumns, 3, keyColumns, 1, orderPtr);
- sendSignal(reference(),
- GSN_BUILDINDXREQ,
- signal,
- BuildIndxReq::SignalLength,
- JBB,
- orderPtr,
- BuildIndxReq::NoOfSections);
- break;
- }
- case(303): { // ok
- // index -T -2; index -I -2 -n1000; index -c -p
- // all dump 303 0 0 0 0 0 4 2
- // select_count PNUMINDEX0000
- BuildIndxReq * buildIndxReq = (BuildIndxReq *)signal->getDataPtrSend();
-
- MEMCOPY_NO_WORDS(buildIndxReq,
- signal->theData + 1,
- BuildIndxReq::SignalLength);
- buildIndxReq->setUserRef(reference()); // return to me
- buildIndxReq->setParallelism(10);
- Uint32 indexColumns[3] = {0, 3, 5};
- Uint32 keyColumns[2] = {0, 1};
- struct LinearSectionPtr orderPtr[2];
- buildIndxReq->setColumnOrder(indexColumns, 3, keyColumns, 2, orderPtr);
- sendSignal(reference(),
- GSN_BUILDINDXREQ,
- signal,
- BuildIndxReq::SignalLength,
- JBB,
- orderPtr,
- BuildIndxReq::NoOfSections);
- break;
- }
- case(304): { // ok
- // index -T -L; index -I -L -n1000; index -c -p
- // all dump 304 0 0 0 0 0 4 2
- // select_count PNUMINDEX0000
- BuildIndxReq * buildIndxReq = (BuildIndxReq *)signal->getDataPtrSend();
-
- MEMCOPY_NO_WORDS(buildIndxReq,
- signal->theData + 1,
- BuildIndxReq::SignalLength);
- buildIndxReq->setUserRef(reference()); // return to me
- buildIndxReq->setParallelism(10);
- Uint32 indexColumns[3] = {0, 3, 5};
- Uint32 keyColumns[1] = {0};
- struct LinearSectionPtr orderPtr[2];
- buildIndxReq->setColumnOrder(indexColumns, 3, keyColumns, 1, orderPtr);
- sendSignal(reference(),
- GSN_BUILDINDXREQ,
- signal,
- BuildIndxReq::SignalLength,
- JBB,
- orderPtr,
- BuildIndxReq::NoOfSections);
- break;
- }
- case(305): { // ok
- // index -T -2 -L; index -I -2 -L -n1000; index -c -p
- // all dump 305 0 0 0 0 0 4 2
- // select_count PNUMINDEX0000
- BuildIndxReq * buildIndxReq = (BuildIndxReq *)signal->getDataPtrSend();
-
- MEMCOPY_NO_WORDS(buildIndxReq,
- signal->theData + 1,
- BuildIndxReq::SignalLength);
- buildIndxReq->setUserRef(reference()); // return to me
- buildIndxReq->setParallelism(10);
- Uint32 indexColumns[3] = {0, 3, 5};
- Uint32 keyColumns[2] = {0, 1};
- struct LinearSectionPtr orderPtr[2];
- buildIndxReq->setColumnOrder(indexColumns, 3, keyColumns, 2, orderPtr);
- sendSignal(reference(),
- GSN_BUILDINDXREQ,
- signal,
- BuildIndxReq::SignalLength,
- JBB,
- orderPtr,
- BuildIndxReq::NoOfSections);
- break;
- }
- default: {
- // Ignore
- }
- }
-}
-
-// Build index
-/**
- *
- */
-void Trix:: execBUILDINDXREQ(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Trix:: execBUILDINDXREQ");
-
- BuildIndxReq * buildIndxReq = (BuildIndxReq *)signal->getDataPtr();
-
- // Seize a subscription record
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- if (!c_theSubscriptions.seizeId(subRecPtr, buildIndxReq->getBuildId())) {
- // Failed to allocate subscription record
- BuildIndxRef * buildIndxRef = (BuildIndxRef *)signal->getDataPtrSend();
-
- buildIndxRef->setErrorCode(BuildIndxRef::AllocationFailure);
- releaseSections(signal);
- sendSignal(buildIndxReq->getUserRef(),
- GSN_BUILDINDXREF, signal, BuildIndxRef::SignalLength, JBB);
- DBUG_VOID_RETURN;
- }
- subRec = subRecPtr.p;
- subRec->errorCode = BuildIndxRef::NoError;
- subRec->userReference = buildIndxReq->getUserRef();
- subRec->connectionPtr = buildIndxReq->getConnectionPtr();
- subRec->subscriptionId = buildIndxReq->getBuildId();
- subRec->subscriptionKey = buildIndxReq->getBuildKey();
- subRec->indexType = buildIndxReq->getIndexType();
- subRec->sourceTableId = buildIndxReq->getTableId();
- subRec->targetTableId = buildIndxReq->getIndexId();
- subRec->parallelism = buildIndxReq->getParallelism();
- subRec->expectedConf = 0;
- subRec->subscriptionCreated = false;
- subRec->pendingSubSyncContinueConf = false;
- subRec->prepareId = RNIL;
-
- // Get column order segments
- Uint32 noOfSections = signal->getNoOfSections();
- if(noOfSections > 0) {
- SegmentedSectionPtr ptr;
- signal->getSection(ptr, BuildIndxReq::INDEX_COLUMNS);
- append(subRec->attributeOrder, ptr, getSectionSegmentPool());
- subRec->noOfIndexColumns = ptr.sz;
- }
- if(noOfSections > 1) {
- SegmentedSectionPtr ptr;
- signal->getSection(ptr, BuildIndxReq::KEY_COLUMNS);
- append(subRec->attributeOrder, ptr, getSectionSegmentPool());
- subRec->noOfKeyColumns = ptr.sz;
- }
-#if 0
- // Debugging
- printf("Trix:: execBUILDINDXREQ: Attribute order:\n");
- subRec->attributeOrder.print(stdout);
-#endif
- releaseSections(signal);
- prepareInsertTransactions(signal, subRecPtr);
- DBUG_VOID_RETURN;
-}
-
-void Trix:: execBUILDINDXCONF(Signal* signal)
-{
- printf("Trix:: execBUILDINDXCONF\n");
-}
-
-void Trix:: execBUILDINDXREF(Signal* signal)
-{
- printf("Trix:: execBUILDINDXREF\n");
-}
-
-void Trix::execUTIL_PREPARE_CONF(Signal* signal)
-{
- jamEntry();
- UtilPrepareConf * utilPrepareConf = (UtilPrepareConf *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = utilPrepareConf->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execUTIL_PREPARE_CONF: Failed to find subscription data %u\n", subRecPtr.i);
- return;
- }
- subRecPtr.p = subRec;
- subRec->prepareId = utilPrepareConf->prepareId;
- setupSubscription(signal, subRecPtr);
-}
-
-void Trix::execUTIL_PREPARE_REF(Signal* signal)
-{
- jamEntry();
- UtilPrepareRef * utilPrepareRef = (UtilPrepareRef *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = utilPrepareRef->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execUTIL_PREPARE_REF: Failed to find subscription data %u\n", subRecPtr.i);
- return;
- }
- subRecPtr.p = subRec;
- subRec->errorCode = BuildIndxRef::InternalError;
-}
-
-void Trix::execUTIL_EXECUTE_CONF(Signal* signal)
-{
- jamEntry();
- UtilExecuteConf * utilExecuteConf = (UtilExecuteConf *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = utilExecuteConf->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("rix::execUTIL_EXECUTE_CONF: Failed to find subscription data %u\n", subRecPtr.i);
- return;
- }
- subRecPtr.p = subRec;
- subRec->expectedConf--;
- checkParallelism(signal, subRec);
- if (subRec->expectedConf == 0)
- buildComplete(signal, subRecPtr);
-}
-
-void Trix::execUTIL_EXECUTE_REF(Signal* signal)
-{
- jamEntry();
- UtilExecuteRef * utilExecuteRef = (UtilExecuteRef *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = utilExecuteRef->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execUTIL_EXECUTE_REF: Failed to find subscription data %u\n", subRecPtr.i);
- return;
- }
- subRecPtr.p = subRec;
- ndbrequire(utilExecuteRef->errorCode == UtilExecuteRef::TCError);
- if(utilExecuteRef->TCErrorCode == CONSTRAINT_VIOLATION)
- buildFailed(signal, subRecPtr, BuildIndxRef::IndexNotUnique);
- else
- buildFailed(signal, subRecPtr, BuildIndxRef::InternalError);
-}
-
-void Trix::execSUB_CREATE_CONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Trix::execSUB_CREATE_CONF");
- SubCreateConf * subCreateConf = (SubCreateConf *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = subCreateConf->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execSUB_CREATE_CONF: Failed to find subscription data %u\n", subRecPtr.i);
- DBUG_VOID_RETURN;
- }
- subRec->subscriptionCreated = true;
- subRecPtr.p = subRec;
-
- DBUG_PRINT("info",("i: %u subscriptionId: %u, subscriptionKey: %u",
- subRecPtr.i, subRecPtr.p->subscriptionId,
- subRecPtr.p->subscriptionKey));
-
- startTableScan(signal, subRecPtr);
- DBUG_VOID_RETURN;
-}
-
-void Trix::execSUB_CREATE_REF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Trix::execSUB_CREATE_REF");
- // THIS SIGNAL IS NEVER SENT FROM SUMA?
- /*
- SubCreateRef * subCreateRef = (SubCreateRef *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = subCreateRef->subscriberData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execSUB_CREATE_REF: Failed to find subscription data %u\n", subRecPtr.i);
- return;
- }
- subRecPtr.p = subRec;
- buildFailed(signal, subRecPtr, BuildIndxRef::InternalError);
- */
- DBUG_VOID_RETURN;
-}
-
-void Trix::execSUB_SYNC_CONF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Trix::execSUB_SYNC_CONF");
- SubSyncConf * subSyncConf = (SubSyncConf *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = subSyncConf->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execSUB_SYNC_CONF: Failed to find subscription data %u\n",
- subRecPtr.i);
- DBUG_VOID_RETURN;
- }
-
- subRecPtr.p = subRec;
- subRec->expectedConf--;
- checkParallelism(signal, subRec);
- if (subRec->expectedConf == 0)
- buildComplete(signal, subRecPtr);
- DBUG_VOID_RETURN;
-}
-
-void Trix::execSUB_SYNC_REF(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Trix::execSUB_SYNC_REF");
- SubSyncRef * subSyncRef = (SubSyncRef *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
-
- subRecPtr.i = subSyncRef->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execSUB_SYNC_REF: Failed to find subscription data %u\n", subRecPtr.i);
- DBUG_VOID_RETURN;
- }
- subRecPtr.p = subRec;
- buildFailed(signal, subRecPtr, BuildIndxRef::InternalError);
- DBUG_VOID_RETURN;
-}
-
-void Trix::execSUB_SYNC_CONTINUE_REQ(Signal* signal)
-{
- SubSyncContinueReq * subSyncContinueReq =
- (SubSyncContinueReq *) signal->getDataPtr();
-
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
- subRecPtr.i = subSyncContinueReq->subscriberData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execSUB_SYNC_CONTINUE_REQ: Failed to find subscription data %u\n", subRecPtr.i);
- return;
- }
- subRecPtr.p = subRec;
- subRec->pendingSubSyncContinueConf = true;
- checkParallelism(signal, subRec);
-}
-
-void Trix::execSUB_TABLE_DATA(Signal* signal)
-{
- jamEntry();
- DBUG_ENTER("Trix::execSUB_TABLE_DATA");
- SubTableData * subTableData = (SubTableData *)signal->getDataPtr();
- SubscriptionRecPtr subRecPtr;
- SubscriptionRecord* subRec;
- subRecPtr.i = subTableData->senderData;
- if ((subRec = c_theSubscriptions.getPtr(subRecPtr.i)) == NULL) {
- printf("Trix::execSUB_TABLE_DATA: Failed to find subscription data %u\n", subRecPtr.i);
- DBUG_VOID_RETURN;
- }
- subRecPtr.p = subRec;
- SegmentedSectionPtr headerPtr, dataPtr;
- if (!signal->getSection(headerPtr, 0)) {
- printf("Trix::execSUB_TABLE_DATA: Failed to get header section\n");
- }
- if (!signal->getSection(dataPtr, 1)) {
- printf("Trix::execSUB_TABLE_DATA: Failed to get data section\n");
- }
- executeInsertTransaction(signal, subRecPtr, headerPtr, dataPtr);
- DBUG_VOID_RETURN;
-}
-
-void Trix::setupSubscription(Signal* signal, SubscriptionRecPtr subRecPtr)
-{
- jam();
- DBUG_ENTER("Trix::setupSubscription");
- SubscriptionRecord* subRec = subRecPtr.p;
- SubCreateReq * subCreateReq = (SubCreateReq *)signal->getDataPtrSend();
-// Uint32 listLen = subRec->noOfIndexColumns + subRec->noOfKeyColumns;
- subCreateReq->senderRef = reference();
- subCreateReq->senderData = subRecPtr.i;
- subCreateReq->subscriptionId = subRec->subscriptionId;
- subCreateReq->subscriptionKey = subRec->subscriptionKey;
- subCreateReq->tableId = subRec->sourceTableId;
- subCreateReq->subscriptionType = SubCreateReq::SingleTableScan;
-
- DBUG_PRINT("info",("i: %u subscriptionId: %u, subscriptionKey: %u",
- subRecPtr.i, subCreateReq->subscriptionId,
- subCreateReq->subscriptionKey));
-
- sendSignal(SUMA_REF, GSN_SUB_CREATE_REQ,
- signal, SubCreateReq::SignalLength, JBB);
- DBUG_VOID_RETURN;
-}
-
-void Trix::startTableScan(Signal* signal, SubscriptionRecPtr subRecPtr)
-{
- jam();
-
- Uint32 attributeList[MAX_ATTRIBUTES_IN_TABLE * 2];
- SubscriptionRecord* subRec = subRecPtr.p;
- AttrOrderBuffer::DataBufferIterator iter;
- Uint32 i = 0;
-
- bool moreAttributes = subRec->attributeOrder.first(iter);
- while (moreAttributes) {
- attributeList[i++] = *iter.data;
- moreAttributes = subRec->attributeOrder.next(iter);
- }
- // Merge index and key column segments
- struct LinearSectionPtr orderPtr[3];
- orderPtr[0].p = attributeList;
- orderPtr[0].sz = subRec->attributeOrder.getSize();
-
- SubSyncReq * subSyncReq = (SubSyncReq *)signal->getDataPtrSend();
- subSyncReq->senderRef = reference();
- subSyncReq->senderData = subRecPtr.i;
- subSyncReq->subscriptionId = subRec->subscriptionId;
- subSyncReq->subscriptionKey = subRec->subscriptionKey;
- subSyncReq->part = SubscriptionData::TableData;
-
- subRecPtr.p->expectedConf = 1;
-
- DBUG_PRINT("info",("i: %u subscriptionId: %u, subscriptionKey: %u",
- subRecPtr.i, subSyncReq->subscriptionId,
- subSyncReq->subscriptionKey));
-
- sendSignal(SUMA_REF, GSN_SUB_SYNC_REQ,
- signal, SubSyncReq::SignalLength, JBB, orderPtr, 1);
-}
-
-void Trix::prepareInsertTransactions(Signal* signal,
- SubscriptionRecPtr subRecPtr)
-{
- SubscriptionRecord* subRec = subRecPtr.p;
- UtilPrepareReq * utilPrepareReq =
- (UtilPrepareReq *)signal->getDataPtrSend();
-
- jam();
- utilPrepareReq->senderRef = reference();
- utilPrepareReq->senderData = subRecPtr.i;
-
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Write);
- w.add(UtilPrepareReq::TableId, subRec->targetTableId);
- // Add index attributes in increasing order and one PK attribute
- for(Uint32 i = 0; i < subRec->noOfIndexColumns + 1; i++)
- w.add(UtilPrepareReq::AttributeId, i);
-
-#if 0
- // Debugging
- SimplePropertiesLinearReader reader(propPage, w.getWordsUsed());
- printf("Trix::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();
- sendSignal(DBUTIL_REF, GSN_UTIL_PREPARE_REQ, signal,
- UtilPrepareReq::SignalLength, JBB,
- sectionsPtr, UtilPrepareReq::NoOfSections);
-}
-
-void Trix::executeInsertTransaction(Signal* signal,
- SubscriptionRecPtr subRecPtr,
- SegmentedSectionPtr headerPtr,
- SegmentedSectionPtr dataPtr)
-{
- jam();
- SubscriptionRecord* subRec = subRecPtr.p;
- UtilExecuteReq * utilExecuteReq =
- (UtilExecuteReq *)signal->getDataPtrSend();
- Uint32* headerBuffer = signal->theData + 25;
- Uint32* dataBuffer = headerBuffer + headerPtr.sz;
-
- utilExecuteReq->senderRef = reference();
- utilExecuteReq->senderData = subRecPtr.i;
- utilExecuteReq->prepareId = subRec->prepareId;
-#if 0
- printf("Header size %u\n", headerPtr.sz);
- for(int i = 0; i < headerPtr.sz; i++)
- printf("H'%.8x ", headerBuffer[i]);
- printf("\n");
-
- printf("Data size %u\n", dataPtr.sz);
- for(int i = 0; i < dataPtr.sz; i++)
- printf("H'%.8x ", dataBuffer[i]);
- printf("\n");
-#endif
- // Save scan result in linear buffers
- copy(headerBuffer, headerPtr);
- copy(dataBuffer, dataPtr);
-
- // Calculate packed key size
- Uint32 noOfKeyData = 0;
- for(Uint32 i = 0; i < headerPtr.sz; i++) {
- AttributeHeader* keyAttrHead = (AttributeHeader *) headerBuffer + i;
-
- // Filter out NULL attributes
- if (keyAttrHead->isNULL())
- return;
-
- if (i < subRec->noOfIndexColumns)
- // Renumber index attributes in consequtive order
- keyAttrHead->setAttributeId(i);
- else
- // Calculate total size of PK attribute
- noOfKeyData += keyAttrHead->getDataSize();
- }
- // Increase expected CONF count
- subRec->expectedConf++;
-
- // Pack key attributes
- AttributeHeader::init(headerBuffer + subRec->noOfIndexColumns,
- subRec->noOfIndexColumns,
- noOfKeyData << 2);
-
- struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections];
- sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = headerBuffer;
- sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz =
- subRec->noOfIndexColumns + 1;
- sectionsPtr[UtilExecuteReq::DATA_SECTION].p = dataBuffer;
- sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataPtr.sz;
- sendSignal(DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal,
- UtilExecuteReq::SignalLength, JBB,
- sectionsPtr, UtilExecuteReq::NoOfSections);
-}
-
-void Trix::buildComplete(Signal* signal, SubscriptionRecPtr subRecPtr)
-{
- SubRemoveReq * const req = (SubRemoveReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = subRecPtr.i;
- req->subscriptionId = subRecPtr.p->subscriptionId;
- req->subscriptionKey = subRecPtr.p->subscriptionKey;
- sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal,
- SubRemoveReq::SignalLength, JBB);
-}
-
-void Trix::buildFailed(Signal* signal,
- SubscriptionRecPtr subRecPtr,
- BuildIndxRef::ErrorCode errorCode)
-{
- SubscriptionRecord* subRec = subRecPtr.p;
-
- subRec->errorCode = errorCode;
- // Continue accumulating since we currently cannot stop SUMA
- subRec->expectedConf--;
- checkParallelism(signal, subRec);
- if (subRec->expectedConf == 0)
- buildComplete(signal, subRecPtr);
-}
-
-void
-Trix::execSUB_REMOVE_REF(Signal* signal){
- jamEntry();
- //@todo
- ndbrequire(false);
-}
-
-void
-Trix::execSUB_REMOVE_CONF(Signal* signal){
- jamEntry();
-
- SubRemoveConf * const conf = (SubRemoveConf*)signal->getDataPtrSend();
-
- SubscriptionRecPtr subRecPtr;
- c_theSubscriptions.getPtr(subRecPtr, conf->senderData);
-
- if(subRecPtr.p->prepareId != RNIL){
- jam();
-
- UtilReleaseReq * const req = (UtilReleaseReq*)signal->getDataPtrSend();
- req->prepareId = subRecPtr.p->prepareId;
- req->senderData = subRecPtr.i;
-
- sendSignal(DBUTIL_REF, GSN_UTIL_RELEASE_REQ, signal,
- UtilReleaseReq::SignalLength , JBB);
- return;
- }
-
- {
- UtilReleaseConf * const conf = (UtilReleaseConf*)signal->getDataPtrSend();
- conf->senderData = subRecPtr.i;
- execUTIL_RELEASE_CONF(signal);
- }
-}
-
-void
-Trix::execUTIL_RELEASE_REF(Signal* signal){
- jamEntry();
- ndbrequire(false);
-}
-
-void
-Trix::execUTIL_RELEASE_CONF(Signal* signal){
-
- UtilReleaseConf * const conf = (UtilReleaseConf*)signal->getDataPtrSend();
-
- SubscriptionRecPtr subRecPtr;
- c_theSubscriptions.getPtr(subRecPtr, conf->senderData);
-
- if(subRecPtr.p->errorCode == BuildIndxRef::NoError){
- // Build is complete, reply to original sender
- BuildIndxConf * buildIndxConf = (BuildIndxConf *)signal->getDataPtrSend();
- buildIndxConf->setUserRef(subRecPtr.p->userReference);
- buildIndxConf->setConnectionPtr(subRecPtr.p->connectionPtr);
- buildIndxConf->setRequestType(BuildIndxReq::RT_TRIX);
- buildIndxConf->setIndexType(subRecPtr.p->indexType);
- buildIndxConf->setTableId(subRecPtr.p->sourceTableId);
- buildIndxConf->setIndexId(subRecPtr.p->targetTableId);
-
- sendSignal(subRecPtr.p->userReference, GSN_BUILDINDXCONF, signal,
- BuildIndxConf::SignalLength , JBB);
- } else {
- // Build failed, reply to original sender
- BuildIndxRef * buildIndxRef = (BuildIndxRef *)signal->getDataPtrSend();
- buildIndxRef->setUserRef(subRecPtr.p->userReference);
- buildIndxRef->setConnectionPtr(subRecPtr.p->connectionPtr);
- buildIndxRef->setRequestType(BuildIndxReq::RT_TRIX);
- buildIndxRef->setIndexType(subRecPtr.p->indexType);
- buildIndxRef->setTableId(subRecPtr.p->sourceTableId);
- buildIndxRef->setIndexId(subRecPtr.p->targetTableId);
- buildIndxRef->setErrorCode(subRecPtr.p->errorCode);
-
- sendSignal(subRecPtr.p->userReference, GSN_BUILDINDXREF, signal,
- BuildIndxRef::SignalLength , JBB);
- }
-
- // Release subscription record
- subRecPtr.p->attributeOrder.release();
- c_theSubscriptions.release(subRecPtr.i);
-}
-
-void Trix::checkParallelism(Signal* signal, SubscriptionRecord* subRec)
-{
- if ((subRec->pendingSubSyncContinueConf) &&
- (subRec->expectedConf < subRec->parallelism)) {
- SubSyncContinueConf * subSyncContinueConf =
- (SubSyncContinueConf *) signal->getDataPtrSend();
- subSyncContinueConf->subscriptionId = subRec->subscriptionId;
- subSyncContinueConf->subscriptionKey = subRec->subscriptionKey;
- sendSignal(SUMA_REF, GSN_SUB_SYNC_CONTINUE_CONF, signal,
- SubSyncContinueConf::SignalLength , JBB);
- subRec->pendingSubSyncContinueConf = false;
- }
-}
-
-BLOCK_FUNCTIONS(Trix)
-
-template void append(DataBuffer<15>&,SegmentedSectionPtr,SectionSegmentPool&);
diff --git a/storage/ndb/src/kernel/blocks/trix/Trix.hpp b/storage/ndb/src/kernel/blocks/trix/Trix.hpp
deleted file mode 100644
index f8163f64849..00000000000
--- a/storage/ndb/src/kernel/blocks/trix/Trix.hpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef TRIX_H
-#define TRIX_H
-
-#include <SimulatedBlock.hpp>
-#include <trigger_definitions.h>
-#include <DataBuffer.hpp>
-#include <SimpleProperties.hpp>
-#include <signaldata/DictTabInfo.hpp>
-#include <signaldata/CreateTrig.hpp>
-#include <signaldata/BuildIndx.hpp>
-
-// Error codes
-#define INTERNAL_ERROR_ILLEGAL_CALL 4344
-#define INTERNAL_ERROR_TRIX_BUSY 4345
-
-/**
- * TRIX - This block manages triggers and index (in coop with DICT)
- */
-class Trix : public SimulatedBlock
-{
-public:
- Trix(Block_context&);
- virtual ~Trix();
-
-public:
- // Subscription data, when communicating with SUMA
-
- enum RequestType {
- TABLE_REORG = 0,
- INDEX_BUILD = 1
- };
- typedef DataBuffer<11> AttrOrderBuffer;
-
-private:
- // Private attributes
-
- BLOCK_DEFINES(Trix);
-
- // Declared but not defined
- //DBtrix(const Trix &obj);
- //void operator = (const Trix &);
-
- // Block state
- enum BlockState {
- NOT_STARTED,
- STARTED,
- NODE_FAILURE,
- IDLE,
- BUSY
- };
-
- BlockState c_blockState;
-
- // Node data needed when communicating with remote TRIX:es
- struct NodeRecord {
- bool alive;
- BlockReference trixRef;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
-
- typedef Ptr<NodeRecord> NodeRecPtr;
-
- /**
- * The pool of node records
- */
- ArrayPool<NodeRecord> c_theNodeRecPool;
-
- /**
- * The list of other NDB nodes
- */
- DLList<NodeRecord> c_theNodes;
-
- Uint32 c_masterNodeId;
- BlockReference c_masterTrixRef;
- Uint16 c_noNodesFailed;
- Uint16 c_noActiveNodes;
-
- AttrOrderBuffer::DataBufferPool c_theAttrOrderBufferPool;
-
- struct SubscriptionRecord {
- SubscriptionRecord(AttrOrderBuffer::DataBufferPool & aop):
- attributeOrder(aop)
- {}
- RequestType requestType;
- BlockReference userReference; // For user
- Uint32 connectionPtr; // For user
- Uint32 subscriptionId; // For Suma
- Uint32 subscriptionKey; // For Suma
- Uint32 prepareId; // For DbUtil
- Uint32 indexType;
- Uint32 sourceTableId;
- Uint32 targetTableId;
- AttrOrderBuffer attributeOrder;
- Uint32 noOfIndexColumns;
- Uint32 noOfKeyColumns;
- Uint32 parallelism;
- BuildIndxRef::ErrorCode errorCode;
- bool subscriptionCreated;
- bool pendingSubSyncContinueConf;
- Uint32 expectedConf; // Count in n UTIL_EXECUTE_CONF + 1 SUB_SYNC_CONF
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
-
- typedef Ptr<SubscriptionRecord> SubscriptionRecPtr;
-
- /**
- * The pool of node records
- */
- ArrayPool<SubscriptionRecord> c_theSubscriptionRecPool;
-
- /**
- * The list of other subscriptions
- */
- DLList<SubscriptionRecord> c_theSubscriptions;
-
- // System start
- void execREAD_CONFIG_REQ(Signal* signal);
- void execSTTOR(Signal* signal);
- void execNDB_STTOR(Signal* signal);
-
- // Node management
- void execREAD_NODESCONF(Signal* signal);
- void execREAD_NODESREF(Signal* signal);
- void execNODE_FAILREP(Signal* signal);
- void execINCL_NODEREQ(Signal* signal);
- // Debugging
- void execDUMP_STATE_ORD(Signal* signal);
-
- // Build index
- void execBUILDINDXREQ(Signal* signal);
- void execBUILDINDXCONF(Signal* signal);
- void execBUILDINDXREF(Signal* signal);
-
- 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);
-
- // Suma signals
- void execSUB_CREATE_CONF(Signal* signal);
- void execSUB_CREATE_REF(Signal* signal);
- void execSUB_REMOVE_CONF(Signal* signal);
- void execSUB_REMOVE_REF(Signal* signal);
- void execSUB_SYNC_CONF(Signal* signal);
- void execSUB_SYNC_REF(Signal* signal);
- void execSUB_SYNC_CONTINUE_REQ(Signal* signal);
- void execSUB_TABLE_DATA(Signal* signal);
-
- // Utility functions
- void setupSubscription(Signal* signal, SubscriptionRecPtr subRecPtr);
- void startTableScan(Signal* signal, SubscriptionRecPtr subRecPtr);
- void prepareInsertTransactions(Signal* signal, SubscriptionRecPtr subRecPtr);
- void executeInsertTransaction(Signal* signal, SubscriptionRecPtr subRecPtr,
- SegmentedSectionPtr headerPtr,
- SegmentedSectionPtr dataPtr);
- void buildComplete(Signal* signal, SubscriptionRecPtr subRecPtr);
- void buildFailed(Signal* signal,
- SubscriptionRecPtr subRecPtr,
- BuildIndxRef::ErrorCode);
- void checkParallelism(Signal* signal, SubscriptionRecord* subRec);
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/blocks/tsman.cpp b/storage/ndb/src/kernel/blocks/tsman.cpp
deleted file mode 100644
index 90f83c8ac82..00000000000
--- a/storage/ndb/src/kernel/blocks/tsman.cpp
+++ /dev/null
@@ -1,2224 +0,0 @@
-/* Copyright (c) 2003, 2005-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "tsman.hpp"
-#include "pgman.hpp"
-#include "diskpage.hpp"
-#include <signaldata/FsRef.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsOpenReq.hpp>
-#include <signaldata/FsCloseReq.hpp>
-#include <signaldata/CreateFilegroupImpl.hpp>
-#include <signaldata/DropFilegroupImpl.hpp>
-#include <signaldata/FsReadWriteReq.hpp>
-#include <signaldata/Extent.hpp>
-#include <signaldata/DumpStateOrd.hpp>
-#include <signaldata/TsmanContinueB.hpp>
-#include <signaldata/GetTabInfo.hpp>
-#include <dbtup/Dbtup.hpp>
-
-#define JONAS 0
-
-#define COMMITTED_MASK ((1 << 0) | (1 << 1))
-#define UNCOMMITTED_MASK ((1 << 2) | (1 << 3))
-#define UNCOMMITTED_SHIFT 2
-
-#define DBG_UNDO 0
-
-Tsman::Tsman(Block_context& ctx,
- class Pgman* pg, class Lgman* lg) :
- SimulatedBlock(TSMAN, ctx),
- m_file_hash(m_file_pool),
- m_tablespace_list(m_tablespace_pool),
- m_tablespace_hash(m_tablespace_pool),
- m_page_cache_client(this, pg),
- m_lgman(lg)
-{
- BLOCK_CONSTRUCTOR(Tsman);
-
- Uint32 SZ = File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE;
- ndbrequire((COMMITTED_MASK & UNCOMMITTED_MASK) == 0);
- ndbrequire((COMMITTED_MASK | UNCOMMITTED_MASK) == ((1 << SZ) - 1));
-
- // Add received signals
- addRecSignal(GSN_STTOR, &Tsman::execSTTOR);
- addRecSignal(GSN_READ_CONFIG_REQ, &Tsman::execREAD_CONFIG_REQ);
- addRecSignal(GSN_DUMP_STATE_ORD, &Tsman::execDUMP_STATE_ORD);
- addRecSignal(GSN_CONTINUEB, &Tsman::execCONTINUEB);
-
- addRecSignal(GSN_CREATE_FILE_REQ, &Tsman::execCREATE_FILE_REQ);
- addRecSignal(GSN_CREATE_FILEGROUP_REQ, &Tsman::execCREATE_FILEGROUP_REQ);
-
- addRecSignal(GSN_DROP_FILE_REQ, &Tsman::execDROP_FILE_REQ);
- addRecSignal(GSN_DROP_FILEGROUP_REQ, &Tsman::execDROP_FILEGROUP_REQ);
-
- addRecSignal(GSN_FSWRITEREQ, &Tsman::execFSWRITEREQ);
-
- addRecSignal(GSN_FSOPENREF, &Tsman::execFSOPENREF, true);
- addRecSignal(GSN_FSOPENCONF, &Tsman::execFSOPENCONF);
-
- //addRecSignal(GSN_FSCLOSEREF, &Tsman::execFSCLOSEREF);
- addRecSignal(GSN_FSCLOSECONF, &Tsman::execFSCLOSECONF);
- addRecSignal(GSN_FSREADCONF, &Tsman::execFSREADCONF);
-
- addRecSignal(GSN_ALLOC_EXTENT_REQ, &Tsman::execALLOC_EXTENT_REQ);
- addRecSignal(GSN_FREE_EXTENT_REQ, &Tsman::execFREE_EXTENT_REQ);
-
- addRecSignal(GSN_START_RECREQ, &Tsman::execSTART_RECREQ);
-
- addRecSignal(GSN_LCP_FRAG_ORD, &Tsman::execLCP_FRAG_ORD);
- addRecSignal(GSN_END_LCP_REQ, &Tsman::execEND_LCP_REQ);
-
- addRecSignal(GSN_GET_TABINFOREQ, &Tsman::execGET_TABINFOREQ);
-
- m_tablespace_hash.setSize(10);
- m_file_hash.setSize(10);
- m_lcp_ongoing = false;
-}
-
-Tsman::~Tsman()
-{
-}
-
-BLOCK_FUNCTIONS(Tsman)
-
-void
-Tsman::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 =
- m_ctx.m_config.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Pool_context pc;
- pc.m_block = this;
-
- m_file_pool.init(RT_TSMAN_FILE, pc);
- m_tablespace_pool.init(RT_TSMAN_FILEGROUP, pc);
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
-void
-Tsman::execSTTOR(Signal* signal)
-{
- jamEntry();
-
- sendSTTORRY(signal);
-
- return;
-}
-
-void
-Tsman::sendSTTORRY(Signal* signal){
- signal->theData[0] = 0;
- signal->theData[3] = 1;
- signal->theData[4] = 3;
- signal->theData[5] = 255; // No more start phases from missra
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
-}
-
-void
-Tsman::execCONTINUEB(Signal* signal){
- jamEntry();
- Uint32 type = signal->theData[0];
- Uint32 ptrI = signal->theData[1];
- switch(type){
- case TsmanContinueB::SCAN_TABLESPACE_EXTENT_HEADERS:
- scan_tablespace(signal, ptrI);
- return;
- case TsmanContinueB::SCAN_DATAFILE_EXTENT_HEADERS:
- scan_datafile(signal, ptrI, signal->theData[2]);
- return;
- case TsmanContinueB::END_LCP:
- end_lcp(signal, ptrI, signal->theData[2], signal->theData[3]);
- return;
- case TsmanContinueB::RELEASE_EXTENT_PAGES:
- {
- Ptr<Datafile> ptr;
- m_file_pool.getPtr(ptr, ptrI);
- release_extent_pages(signal, ptr);
- return;
- }
- case TsmanContinueB::LOAD_EXTENT_PAGES:
- {
- Ptr<Datafile> ptr;
- m_file_pool.getPtr(ptr, ptrI);
- load_extent_pages(signal, ptr);
- return;
- }
- }
- ndbrequire(false);
-}
-
-#ifdef VM_TRACE
-struct TsmanChunk
-{
- Uint32 page_count;
- Local_key start_page;
- Vector<Uint32> bitmask;
-};
-template class Vector<TsmanChunk>;
-#endif
-
-void
-Tsman::execDUMP_STATE_ORD(Signal* signal){
- jamEntry();
-
- /**
- * 9000
- */
-
- if(signal->theData[0] == DumpStateOrd::DumpTsman + 0)
- {
- Uint32 id = signal->theData[1];
-
- AllocExtentReq* req = (AllocExtentReq*)signal->theData;
- req->request.tablespace_id = id;
- req->request.table_id = 0;
- req->request.fragment_id = 0;
- execALLOC_EXTENT_REQ(signal);
-
- if(req->reply.errorCode == 0){
- ndbout_c("Success");
- ndbout_c("page: %d %d count: %d",
- req->reply.page_id.m_file_no,
- req->reply.page_id.m_page_no,
- req->reply.page_count);
- } else {
- ndbout_c("Error: %d", req->reply.errorCode);
- }
- }
-
- if(signal->theData[0] == DumpStateOrd::DumpTsman + 1)
- {
- Uint32 id = signal->theData[1];
- Uint32 file= signal->theData[2];
- Uint32 page= signal->theData[3];
- Uint32 bits= signal->theData[4];
-
- AllocPageReq* req = (AllocPageReq*)signal->theData;
- req->request.tablespace_id = id;
- req->request.table_id = 0;
- req->request.fragment_id = 0;
- req->key.m_page_no= page;
- req->key.m_file_no= file;
- req->bits= bits;
- execALLOC_PAGE_REQ(signal);
-
- if(req->reply.errorCode == 0){
- ndbout_c("Success");
- ndbout_c("page: %d %d bits: %d",
- req->key.m_file_no,
- req->key.m_page_no,
- req->bits);
- } else {
- ndbout_c("Error: %d", req->reply.errorCode);
- }
- }
-
-#ifdef VM_TRACE
- if(signal->theData[0] == DumpStateOrd::DumpTsman + 2)
- {
- Uint32 id = signal->theData[1];
- Vector<TsmanChunk> chunks;
- for(size_t i = 0; i<1000; i++)
- {
- /**
- * 0) Alloc extent ok
- * 1) toggle page bits
- * 2) Free extent
- */
- Uint32 sz = chunks.size();
- switch((rand() * sz) % 2){
- case 0:
- {
- ndbout_c("case 0");
- AllocExtentReq* req = (AllocExtentReq*)signal->theData;
- req->request.tablespace_id = id;
- req->request.table_id = 0;
- req->request.fragment_id = 0;
- execALLOC_EXTENT_REQ(signal);
- if(req->reply.errorCode == 0){
- TsmanChunk c;
- c.start_page = req->reply.page_id;
- c.page_count = req->reply.page_count;
- Uint32 words = File_formats::Datafile::extent_header_words(c.page_count);
- ndbout_c("execALLOC_EXTENT_REQ - OK - [ %d %d ] count: %d(%d)",
- c.start_page.m_file_no,
- c.start_page.m_page_no,
- c.page_count,
- words);
- Uint32 zero = 0;
- chunks.push_back(c);
- chunks.back().bitmask.fill(words, zero);
-
- ndbout_c("execALLOC_EXTENT_REQ - OK - [ %d %d ] count: %d",
- chunks.back().start_page.m_file_no,
- chunks.back().start_page.m_page_no,
- chunks.back().page_count);
- } else {
- ndbout_c("Error: %d", req->reply.errorCode);
- }
- break;
- }
- case 1:
- {
- Uint32 chunk = rand() % sz;
- Uint32 count = chunks[chunk].page_count;
- Uint32 page = rand() % count;
- ndbout_c("case 1 - %d %d %d", chunk, count, page);
-
- File_formats::Datafile::Extent_header* header =
- (File_formats::Datafile::Extent_header*)
- (chunks[chunk].bitmask.getBase());
- Uint32 curr_bits = header->get_free_bits(page);
- Uint32 new_bits = curr_bits ^ rand();
- Local_key key = chunks[chunk].start_page;
- key.m_page_no += page;
- ndbrequire(update_page_free_bits(signal, &key, new_bits) == 0);
- }
- }
- }
- }
-#endif
-
- if(signal->theData[0] == DumpStateOrd::DumpTsman + 3)
- {
- GetTabInfoReq* req = (GetTabInfoReq*)signal->theData;
- req->requestType= GetTabInfoReq::RequestById;
- req->tableId= signal->theData[1];
-
- execGET_TABINFOREQ(signal);
-
- }
-
-}
-
-void
-Tsman::execCREATE_FILEGROUP_REQ(Signal* signal){
- jamEntry();
- CreateFilegroupImplReq* req= (CreateFilegroupImplReq*)signal->getDataPtr();
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
-
- Ptr<Tablespace> ptr;
- CreateFilegroupImplRef::ErrorCode err = CreateFilegroupImplRef::NoError;
- do {
- if (m_tablespace_hash.find(ptr, req->filegroup_id))
- {
- jam();
- err = CreateFilegroupImplRef::FilegroupAlreadyExists;
- break;
- }
-
- if (!m_tablespace_pool.seize(ptr))
- {
- jam();
- err = CreateFilegroupImplRef::OutOfFilegroupRecords;
- break;
- }
-
- new (ptr.p) Tablespace(this, m_lgman, req);
- m_tablespace_hash.add(ptr);
- m_tablespace_list.add(ptr);
-
- ptr.p->m_state = Tablespace::TS_ONLINE;
-
- CreateFilegroupImplConf* conf=
- (CreateFilegroupImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILEGROUP_CONF, signal,
- CreateFilegroupImplConf::SignalLength, JBB);
- return;
- } while(0);
-
- CreateFilegroupImplRef* ref= (CreateFilegroupImplRef*)signal->getDataPtr();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->errorCode = err;
- sendSignal(senderRef, GSN_CREATE_FILEGROUP_REF, signal,
- CreateFilegroupImplRef::SignalLength, JBB);
-}
-
-NdbOut&
-operator<<(NdbOut& out, const File_formats::Datafile::Extent_header & obj)
-{
- out << "table: " << obj.m_table
- << " fragment: " << obj.m_fragment_id << " ";
- for(Uint32 i = 0; i<32; i++)
- {
- char t[2];
- BaseString::snprintf(t, sizeof(t), "%x", obj.get_free_bits(i));
- out << t;
- }
- return out;
-}
-
-void
-Tsman::execDROP_FILEGROUP_REQ(Signal* signal){
- jamEntry();
-
- Uint32 errorCode = 0;
- DropFilegroupImplReq req = *(DropFilegroupImplReq*)signal->getDataPtr();
- Ptr<Tablespace> ptr;
- do
- {
- if (!m_tablespace_hash.find(ptr, req.filegroup_id))
- {
- errorCode = DropFilegroupImplRef::NoSuchFilegroup;
- break;
- }
-
- if (ptr.p->m_version != req.filegroup_version)
- {
- errorCode = DropFilegroupImplRef::InvalidFilegroupVersion;
- break;
- }
-
- if (! (ptr.p->m_meta_files.isEmpty() && ptr.p->m_free_files.isEmpty() &&
- ptr.p->m_full_files.isEmpty()))
- {
- errorCode = DropFilegroupImplRef::FilegroupInUse;
- break;
- }
-
- switch(req.requestInfo){
- case DropFilegroupImplReq::Prepare:
- ptr.p->m_state = Tablespace::TS_DROPPING;
- break;
- case DropFilegroupImplReq::Commit:
- m_tablespace_list.remove(ptr);
- m_tablespace_hash.release(ptr);
- break;
- case DropFilegroupImplReq::Abort:
- ptr.p->m_state = Tablespace::TS_ONLINE;
- break;
- default:
- ndbrequire(false);
- }
- } while(0);
-
- if (errorCode)
- {
- DropFilegroupImplRef* ref =
- (DropFilegroupImplRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = req.senderData;
- ref->errorCode = errorCode;
- sendSignal(req.senderRef, GSN_DROP_FILEGROUP_REF, signal,
- DropFilegroupImplRef::SignalLength, JBB);
- }
- else
- {
- DropFilegroupImplConf* conf =
- (DropFilegroupImplConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = req.senderData;
- sendSignal(req.senderRef, GSN_DROP_FILEGROUP_CONF, signal,
- DropFilegroupImplConf::SignalLength, JBB);
- }
-}
-
-bool
-Tsman::find_file_by_id(Ptr<Datafile>& ptr,
- Datafile_list::Head& head,
- Uint32 id)
-{
- Local_datafile_list list(m_file_pool, head);
- for(list.first(ptr); !ptr.isNull(); list.next(ptr))
- if(ptr.p->m_file_id == id)
- return true;
- return false;
-}
-
-void
-Tsman::execCREATE_FILE_REQ(Signal* signal){
- jamEntry();
- CreateFileImplReq* req= (CreateFileImplReq*)signal->getDataPtr();
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
-
- Ptr<Tablespace> ptr;
- CreateFileImplRef::ErrorCode err = CreateFileImplRef::NoError;
- do {
- if (!m_tablespace_hash.find(ptr, req->filegroup_id))
- {
- jam();
- err = CreateFileImplRef::InvalidFilegroup;
- break;
- }
-
- if (ptr.p->m_version != req->filegroup_version)
- {
- jam();
- err = CreateFileImplRef::InvalidFilegroupVersion;
- break;
- }
-
- if (ptr.p->m_state != Tablespace::TS_ONLINE)
- {
- jam();
- err = CreateFileImplRef::FilegroupNotOnline;
- break;
- }
-
- Ptr<Datafile> file_ptr;
- switch(req->requestInfo){
- case CreateFileImplReq::Commit:
- {
- ndbrequire(find_file_by_id(file_ptr, ptr.p->m_meta_files, req->file_id));
- file_ptr.p->m_create.m_senderRef = req->senderRef;
- file_ptr.p->m_create.m_senderData = req->senderData;
- file_ptr.p->m_create.m_requestInfo = req->requestInfo;
-
- m_page_cache_client.map_file_no(file_ptr.p->m_file_no, file_ptr.p->m_fd);
- file_ptr.p->m_create.m_loading_extent_page = 1;
- load_extent_pages(signal, file_ptr);
- return;
- }
- case CreateFileImplReq::Abort:
- {
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- if(find_file_by_id(file_ptr, ptr.p->m_meta_files, req->file_id))
- {
- file_ptr.p->m_create.m_senderRef = senderRef;
- file_ptr.p->m_create.m_senderData = senderData;
- file_ptr.p->m_create.m_requestInfo = req->requestInfo;
- create_file_abort(signal, file_ptr);
- return;
- }
- else
- {
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
- return;
- }
- }
- default:
- // Prepare
- break;
- }
-
- if (!m_file_pool.seize(file_ptr))
- {
- jam();
- err = CreateFileImplRef::OutOfFileRecords;
- break;
- }
-
- if(ERROR_INSERTED(16000) ||
- (sizeof(void*) == 4 && req->file_size_hi & 0xFFFFFFFF))
- {
- jam();
- if(signal->getNoOfSections())
- releaseSections(signal);
-
- CreateFileImplRef* ref= (CreateFileImplRef*)signal->getDataPtr();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->errorCode = CreateFileImplRef::FileSizeTooLarge;
- sendSignal(senderRef, GSN_CREATE_FILE_REF, signal,
- CreateFileImplRef::SignalLength, JBB);
- return;
- }
-
- new (file_ptr.p) Datafile(req);
- Local_datafile_list tmp(m_file_pool, ptr.p->m_meta_files);
- tmp.add(file_ptr);
-
- file_ptr.p->m_state = Datafile::FS_CREATING;
- file_ptr.p->m_tablespace_ptr_i = ptr.i;
- file_ptr.p->m_extent_size = ptr.p->m_extent_size;
-
- err = (CreateFileImplRef::ErrorCode)open_file(signal, ptr, file_ptr, req);
- if(err)
- break;
- return;
- } while(0);
-
- CreateFileImplRef* ref= (CreateFileImplRef*)signal->getDataPtr();
- ref->senderData = senderData;
- ref->senderRef = reference();
- ref->errorCode = err;
- sendSignal(senderRef, GSN_CREATE_FILE_REF, signal,
- CreateFileImplRef::SignalLength, JBB);
-}
-
-static inline Uint64 DIV(Uint64 a, Uint64 b){ return (a + b - 1) / b;}
-
-void
-Tsman::release_extent_pages(Signal* signal, Ptr<Datafile> ptr)
-{
- Uint32 page = ptr.p->m_create.m_extent_pages;
- if (page > 0)
- {
- Page_cache_client::Request preq;
- preq.m_page.m_file_no = ptr.p->m_file_no;
- preq.m_page.m_page_no = page;
-
- preq.m_callback.m_callbackData = ptr.i;
- preq.m_callback.m_callbackFunction =
- safe_cast(&Tsman::release_extent_pages_callback);
-
- int page_id;
- int flags = Page_cache_client::UNLOCK_PAGE;
- if((page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- execute(signal, preq.m_callback, page_id);
- }
- return;
- }
-
- create_file_abort(signal, ptr);
-}
-
-void
-Tsman::release_extent_pages_callback(Signal* signal,
- Uint32 ptrI,
- Uint32 page_id)
-{
- Ptr<Datafile> ptr;
- m_file_pool.getPtr(ptr, ptrI);
- Local_key key;
- key.m_file_no = ptr.p->m_file_no;
- key.m_page_no = ptr.p->m_create.m_extent_pages;
- ndbrequire(m_page_cache_client.drop_page(key, page_id));
- ptr.p->m_create.m_extent_pages--;
-
- signal->theData[0] = TsmanContinueB::RELEASE_EXTENT_PAGES;
- signal->theData[1] = ptr.i;
-
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Tsman::create_file_abort(Signal* signal, Ptr<Datafile> ptr)
-{
- if (ptr.p->m_fd == RNIL)
- {
- ((FsConf*)signal->getDataPtr())->userPointer = ptr.i;
- execFSCLOSECONF(signal);
- return;
- }
-
- FsCloseReq *req= (FsCloseReq*)signal->getDataPtrSend();
- req->filePointer = ptr.p->m_fd;
- req->userReference = reference();
- req->userPointer = ptr.i;
- req->fileFlag = 0;
- FsCloseReq::setRemoveFileFlag(req->fileFlag, true);
-
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal,
- FsCloseReq::SignalLength, JBB);
-}
-
-void
-Tsman::execFSCLOSECONF(Signal* signal)
-{
- Ptr<Datafile> ptr;
- Ptr<Tablespace> lg_ptr;
- Uint32 ptrI = ((FsConf*)signal->getDataPtr())->userPointer;
- m_file_pool.getPtr(ptr, ptrI);
-
- Uint32 senderRef = ptr.p->m_create.m_senderRef;
- Uint32 senderData = ptr.p->m_create.m_senderData;
-
- if (ptr.p->m_state == Datafile::FS_CREATING)
- {
- m_page_cache_client.free_data_file(ptr.p->m_file_no);
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
- }
- else if(ptr.p->m_state == Datafile::FS_DROPPING)
- {
- m_file_hash.remove(ptr);
- m_page_cache_client.free_data_file(ptr.p->m_file_no, ptr.p->m_fd);
- DropFileImplConf* conf= (DropFileImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_DROP_FILE_CONF, signal,
- DropFileImplConf::SignalLength, JBB);
-
- }
- else
- {
- ndbrequire(false);
- }
-
- {
- m_tablespace_pool.getPtr(lg_ptr, ptr.p->m_tablespace_ptr_i);
- Local_datafile_list list(m_file_pool, lg_ptr.p->m_meta_files);
- list.release(ptr);
- }
-}
-
-int
-Tsman::open_file(Signal* signal,
- Ptr<Tablespace> ts_ptr,
- Ptr<Datafile> ptr, CreateFileImplReq* org)
-{
- Uint32 requestInfo = org->requestInfo;
- Uint32 hi = org->file_size_hi;
- Uint32 lo = org->file_size_lo;
-
- if(requestInfo == CreateFileImplReq::Create ||
- requestInfo == CreateFileImplReq::CreateForce){
- jam();
- Uint32 file_no = m_page_cache_client.create_data_file();
- if(file_no == RNIL)
- {
- return CreateFileImplRef::OutOfFileRecords;
- }
- ptr.p->m_file_no = file_no;
- }
-
- FsOpenReq* req = (FsOpenReq*)signal->getDataPtrSend();
- req->userReference = reference();
- req->userPointer = ptr.i;
-
- memset(req->fileNumber, 0, sizeof(req->fileNumber));
- FsOpenReq::setVersion(req->fileNumber, 4); // Version 4 = specified filename
-
- req->fileFlags = 0;
- req->fileFlags |= FsOpenReq::OM_READWRITE;
- req->fileFlags |= FsOpenReq::OM_DIRECT;
- switch(requestInfo){
- case CreateFileImplReq::Create:
- req->fileFlags |= FsOpenReq::OM_CREATE_IF_NONE;
- req->fileFlags |= FsOpenReq::OM_INIT;
- break;
- case CreateFileImplReq::CreateForce:
- req->fileFlags |= FsOpenReq::OM_CREATE;
- req->fileFlags |= FsOpenReq::OM_INIT;
- break;
- case CreateFileImplReq::Open:
- req->fileFlags |= FsOpenReq::OM_CHECK_SIZE;
- break;
- default:
- ndbrequire(false);
- }
-
- req->page_size = File_formats::NDB_PAGE_SIZE;
- req->file_size_hi = hi;
- req->file_size_lo = lo;
-
- Uint64 pages = (Uint64(hi) << 32 | lo) / File_formats::NDB_PAGE_SIZE;
- Uint32 extent_size = ts_ptr.p->m_extent_size; // Extent size in #pages
- Uint64 extents = (pages + extent_size - 1) / extent_size;
- extents = extents ? extents : 1;
- Uint64 data_pages = extents * extent_size;
-
- Uint32 eh_words = File_formats::Datafile::extent_header_words(extent_size);
- ndbrequire(eh_words < File_formats::Datafile::EXTENT_PAGE_WORDS);
- Uint32 extents_per_page = File_formats::Datafile::EXTENT_PAGE_WORDS/eh_words;
- Uint64 extent_pages = (extents + extents_per_page - 1) / extents_per_page;
-
- ptr.p->m_create.m_extent_pages = extent_pages;
- ptr.p->m_create.m_data_pages = data_pages;
- // Forward filename
-
- /**
- * Update file size
- */
- pages = 1 + extent_pages + data_pages;
- Uint64 bytes = pages * File_formats::NDB_PAGE_SIZE;
- hi = bytes >> 32;
- lo = bytes & 0xFFFFFFFF;
- req->file_size_hi = hi;
- req->file_size_lo = lo;
-
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBB);
-
- return 0;
-}
-
-void
-Tsman::execFSWRITEREQ(Signal* signal)
-{
- /**
- * This is currently run in other thread -> no jam
- */
- //jamEntry();
- Ptr<Datafile> ptr;
- Ptr<GlobalPage> page_ptr;
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtr();
-
- m_file_pool.getPtr(ptr, req->userPointer);
- m_global_page_pool.getPtr(page_ptr, req->data.pageData[0]);
- memset(page_ptr.p, 0, File_formats::NDB_PAGE_SIZE);
-
- Uint32 page_no = req->varIndex;
- Uint32 size = ptr.p->m_extent_size;
- Uint32 extent_pages = ptr.p->m_create.m_extent_pages;
- Uint32 datapages = ptr.p->m_create.m_data_pages;
-
- Uint32 header_words = File_formats::Datafile::extent_header_words(size);
- Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS / header_words;
- Uint32 extents = datapages/size;
-
- if (page_no == 0)
- {
- //jam();
- Ptr<Tablespace> lg_ptr;
- m_tablespace_hash.getPtr(lg_ptr, ptr.p->m_tablespace_ptr_i);
-
- File_formats::Datafile::Zero_page* page =
- (File_formats::Datafile::Zero_page*)page_ptr.p;
- page->m_page_header.init(File_formats::FT_Datafile,
- getOwnNodeId(),
- ndbGetOwnVersion(),
- time(0));
- page->m_file_no = ptr.p->m_file_no;
- page->m_file_id = ptr.p->m_file_id;
- page->m_tablespace_id = lg_ptr.p->m_tablespace_id;
- page->m_tablespace_version = lg_ptr.p->m_version;
- page->m_data_pages = extents * size;
- page->m_extent_pages = extent_pages;
- page->m_extent_size = size;
- page->m_extent_count = extents;
- page->m_extent_headers_per_page = per_page;
- page->m_extent_header_words = header_words;
- page->m_extent_header_bits_per_page =
- File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE;
- }
- else if ((page_no-1) < extent_pages)
- {
- //jam();
-
- Uint32 curr_extent = page_no*per_page;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)page_ptr.p;
- page->m_page_header.m_page_lsn_hi = 0;
- page->m_page_header.m_page_lsn_lo = 0;
- page->m_page_header.m_page_type = File_formats::PT_Unallocated;
-
- for(Uint32 i = 0; i<per_page; i++)
- {
- File_formats::Datafile::Extent_header * head = page->get_header(i, size);
- memset(head, 0, 4*header_words);
- head->m_table = RNIL;
- head->m_next_free_extent = ++curr_extent;
- }
- if (page_no == extent_pages)
- {
- Uint32 last = extents % per_page;
- page->get_header(last - 1, size)->m_next_free_extent = RNIL;
- }
- }
- else
- {
- //jam();
- File_formats::Datafile::Data_page* page =
- (File_formats::Datafile::Data_page*)page_ptr.p;
- page->m_page_header.m_page_lsn_hi = 0;
- page->m_page_header.m_page_lsn_lo = 0;
- }
-}
-
-void
-Tsman::create_file_ref(Signal* signal,
- Ptr<Tablespace> lg_ptr,
- Ptr<Datafile> ptr,
- Uint32 error, Uint32 fsError, Uint32 osError)
-{
- CreateFileImplRef* ref= (CreateFileImplRef*)signal->getDataPtr();
- ref->senderData = ptr.p->m_create.m_senderData;
- ref->senderRef = reference();
- ref->errorCode = (CreateFileImplRef::ErrorCode)error;
- ref->fsErrCode = fsError;
- ref->osErrCode = osError;
- sendSignal(ptr.p->m_create.m_senderRef, GSN_CREATE_FILE_REF, signal,
- CreateFileImplRef::SignalLength, JBB);
-
- Local_datafile_list meta(m_file_pool, lg_ptr.p->m_meta_files);
- meta.release(ptr);
-}
-
-void
-Tsman::execFSOPENREF(Signal* signal)
-{
- jamEntry();
-
- Ptr<Datafile> ptr;
- Ptr<Tablespace> lg_ptr;
- FsRef* ref = (FsRef*)signal->getDataPtr();
-
- Uint32 errCode = ref->errorCode;
- Uint32 osErrCode = ref->osErrorCode;
-
- m_file_pool.getPtr(ptr, ref->userPointer);
- m_tablespace_hash.getPtr(lg_ptr, ptr.p->m_tablespace_ptr_i);
-
- create_file_ref(signal, lg_ptr, ptr,
- CreateFileImplRef::FileError, errCode, osErrCode);
-}
-
-void
-Tsman::execFSOPENCONF(Signal* signal)
-{
- jamEntry();
- Ptr<Datafile> ptr;
- Ptr<Tablespace> lg_ptr;
- FsConf* conf = (FsConf*)signal->getDataPtr();
-
- m_file_pool.getPtr(ptr, conf->userPointer);
- m_tablespace_hash.getPtr(lg_ptr, ptr.p->m_tablespace_ptr_i);
-
- Uint32 fd = ptr.p->m_fd = conf->filePointer;
-
- switch(ptr.p->m_create.m_requestInfo){
- case CreateFileImplReq::Create:
- case CreateFileImplReq::CreateForce:
- {
- jam();
-
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = ptr.p->m_create.m_senderData;
- conf->senderRef = reference();
- sendSignal(ptr.p->m_create.m_senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
- return;
- }
- case CreateFileImplReq::Open:
- {
- jam();
- /**
- * Read zero page and compare values
- * can't use page cache as file's file_no is not known
- */
- Ptr<GlobalPage> page_ptr;
- if(m_global_page_pool.seize(page_ptr) == false)
- {
- jam();
- create_file_ref(signal, lg_ptr, ptr,
- CreateFileImplRef::OutOfMemory, 0, 0);
- return;
- }
-
- ptr.p->m_create.m_page_ptr_i = page_ptr.i;
-
- FsReadWriteReq* req= (FsReadWriteReq*)signal->getDataPtrSend();
- req->filePointer = fd;
- req->userReference = reference();
- req->userPointer = ptr.i;
- req->varIndex = 0;
- req->numberOfPages = 1;
- req->operationFlag = 0;
- FsReadWriteReq::setFormatFlag(req->operationFlag,
- FsReadWriteReq::fsFormatGlobalPage);
- req->data.pageData[0] = page_ptr.i;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
- FsReadWriteReq::FixedLength + 1, JBB);
- return;
- }
- }
-}
-
-void
-Tsman::execFSREADCONF(Signal* signal){
- jamEntry();
- Ptr<Datafile> ptr;
- Ptr<Tablespace> lg_ptr;
- FsConf* conf = (FsConf*)signal->getDataPtr();
-
- /**
- * We currently on read pages here as part of CREATE_FILE
- * (other read is done using pgman)
- */
- m_file_pool.getPtr(ptr, conf->userPointer);
- m_tablespace_hash.getPtr(lg_ptr, ptr.p->m_tablespace_ptr_i);
-
- Ptr<GlobalPage> page_ptr;
- m_global_page_pool.getPtr(page_ptr, ptr.p->m_create.m_page_ptr_i);
-
- File_formats::Datafile::Zero_page* page =
- (File_formats::Datafile::Zero_page*)page_ptr.p;
-
- CreateFileImplRef::ErrorCode err = CreateFileImplRef::NoError;
- Uint32 fsError = 0;
- Uint32 osError = 0;
-
- do {
- err = CreateFileImplRef::InvalidFileMetadata;
- fsError = page->m_page_header.validate(File_formats::FT_Datafile,
- getOwnNodeId(),
- ndbGetOwnVersion(),
- time(0));
- if(fsError)
- break;
-
- osError = 1;
- if(page->m_file_id != ptr.p->m_file_id)
- break;
-
- osError = 2;
- if(page->m_tablespace_id != lg_ptr.p->m_tablespace_id)
- break;
-
- osError = 3;
- if(page->m_tablespace_version != lg_ptr.p->m_version)
- break;
-
- osError = 4;
- if(page->m_data_pages != ptr.p->m_create.m_data_pages)
- break;
-
- osError = 5;
- if(page->m_extent_pages != ptr.p->m_create.m_extent_pages)
- break;
-
- osError = 6;
- if(page->m_extent_size != ptr.p->m_extent_size)
- break;
-
- osError = 7;
- if(page->m_extent_header_bits_per_page !=
- File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE)
- break;
-
- osError = 8;
- Uint32 eh_words =
- File_formats::Datafile::extent_header_words(ptr.p->m_extent_size);
- if(page->m_extent_header_words != eh_words)
- break;
-
- osError = 9;
- Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS/eh_words;
- if(page->m_extent_headers_per_page != per_page)
- break;
-
- osError = 10;
- Uint32 extents = page->m_data_pages / ptr.p->m_extent_size;
- if(page->m_extent_count != extents)
- break;
-
- osError = 11;
- ptr.p->m_file_no = page->m_file_no;
- if(m_page_cache_client.alloc_data_file(ptr.p->m_file_no) == RNIL)
- {
- jam();
- break;
- }
-
- /**
- *
- */
- m_global_page_pool.release(page_ptr);
-
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = ptr.p->m_create.m_senderData;
- conf->senderRef = reference();
- sendSignal(ptr.p->m_create.m_senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
- return;
- } while(0);
-
- m_global_page_pool.release(page_ptr);
- create_file_ref(signal, lg_ptr, ptr, err, fsError, osError);
-}
-
-void
-Tsman::execFSREADREF(Signal* signal)
-{
- jamEntry();
- Ptr<Datafile> ptr;
- Ptr<Tablespace> lg_ptr;
- FsRef* ref = (FsRef*)signal->getDataPtr();
-
- m_file_pool.getPtr(ptr, ref->userPointer);
- m_tablespace_hash.find(lg_ptr, ptr.p->m_tablespace_ptr_i);
-
- m_global_page_pool.release(ptr.p->m_create.m_page_ptr_i);
- create_file_ref(signal, lg_ptr, ptr, CreateFileImplRef::FileReadError,
- ref->errorCode, ref->osErrorCode);
-}
-
-void
-Tsman::load_extent_pages(Signal* signal, Ptr<Datafile> ptr)
-{
- /**
- * Currently all extent header pages needs to be locked in memory
- */
- Page_cache_client::Request preq;
- preq.m_page.m_file_no = ptr.p->m_file_no;
- preq.m_page.m_page_no = ptr.p->m_create.m_loading_extent_page;
-
- preq.m_callback.m_callbackData = ptr.i;
- preq.m_callback.m_callbackFunction =
- safe_cast(&Tsman::load_extent_page_callback);
-
- int page_id;
- int flags = Page_cache_client::LOCK_PAGE;
- if((page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- load_extent_page_callback(signal, ptr.i, (Uint32)page_id);
- }
-
- if(page_id < 0)
- {
- ndbrequire(false);
- }
-}
-
-void
-Tsman::load_extent_page_callback(Signal* signal,
- Uint32 callback,
- Uint32 real_page_ptr_i)
-{
- jamEntry();
- Ptr<Datafile> ptr;
- m_file_pool.getPtr(ptr, callback);
-
- if(++ptr.p->m_create.m_loading_extent_page <= ptr.p->m_create.m_extent_pages)
- {
- signal->theData[0] = TsmanContinueB::LOAD_EXTENT_PAGES;
- signal->theData[1] = ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- return;
- }
-
- Uint32 senderRef = ptr.p->m_create.m_senderRef;
- Uint32 senderData = ptr.p->m_create.m_senderData;
- Uint32 extent_pages = ptr.p->m_create.m_extent_pages;
- Uint32 requestInfo = ptr.p->m_create.m_requestInfo;
- Uint32 data_pages = ptr.p->m_create.m_data_pages;
- ndbassert(requestInfo == CreateFileImplReq::Commit);
-
- Uint32 eh= File_formats::Datafile::extent_header_words(ptr.p->m_extent_size);
- Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS/eh;
-
- ptr.p->m_state = Datafile::FS_ONLINE;
- ptr.p->m_online.m_offset_data_pages = 1 + extent_pages;
- ptr.p->m_online.m_first_free_extent = per_page;
- ptr.p->m_online.m_lcp_free_extent_head = RNIL;
- ptr.p->m_online.m_lcp_free_extent_tail = RNIL;
- ptr.p->m_online.m_data_pages = data_pages;
- ptr.p->m_online.m_used_extent_cnt = 0;
- ptr.p->m_online.m_extent_headers_per_extent_page = per_page;
-
- Ptr<Tablespace> ts_ptr;
- m_tablespace_pool.getPtr(ts_ptr, ptr.p->m_tablespace_ptr_i);
- if (getNodeState().startLevel >= NodeState::SL_STARTED ||
- (getNodeState().getNodeRestartInProgress() &&
- getNodeState().starting.restartType == NodeState::ST_INITIAL_NODE_RESTART))
- {
- Local_datafile_list free(m_file_pool, ts_ptr.p->m_free_files);
- Local_datafile_list meta(m_file_pool, ts_ptr.p->m_meta_files);
- meta.remove(ptr);
- free.add(ptr);
- }
- m_file_hash.add(ptr);
-
- CreateFileImplConf* conf= (CreateFileImplConf*)signal->getDataPtr();
- conf->senderData = senderData;
- conf->senderRef = reference();
- sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
- CreateFileImplConf::SignalLength, JBB);
-}
-
-void
-Tsman::execSTART_RECREQ(Signal* signal)
-{
- Ptr<Tablespace> lg_ptr;
- m_tablespace_list.first(lg_ptr);
-
- signal->theData[0] = TsmanContinueB::SCAN_TABLESPACE_EXTENT_HEADERS;
- signal->theData[1] = lg_ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
-}
-
-void
-Tsman::scan_tablespace(Signal* signal, Uint32 ptrI)
-{
- Ptr<Tablespace> lg_ptr;
- if(ptrI == RNIL)
- {
- signal->theData[0] = reference();
- sendSignal(DBLQH_REF, GSN_START_RECCONF, signal, 1, JBB);
- return;
- }
-
- m_tablespace_pool.getPtr(lg_ptr, ptrI);
-
- Ptr<Datafile> file_ptr;
- {
- Local_datafile_list meta(m_file_pool, lg_ptr.p->m_meta_files);
- meta.first(file_ptr);
- }
-
- scan_datafile(signal, lg_ptr.i, file_ptr.i);
-}
-
-void
-Tsman::scan_datafile(Signal* signal, Uint32 ptrI, Uint32 filePtrI)
-{
- Ptr<Datafile> file_ptr;
- Ptr<Tablespace> lg_ptr;
- m_tablespace_pool.getPtr(lg_ptr, ptrI);
- if(filePtrI == RNIL)
- {
- m_tablespace_list.next(lg_ptr);
- signal->theData[0] = TsmanContinueB::SCAN_TABLESPACE_EXTENT_HEADERS;
- signal->theData[1] = lg_ptr.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
- }
- else
- {
- m_file_pool.getPtr(file_ptr, filePtrI);
- scan_extent_headers(signal, file_ptr);
- }
-}
-
-void
-Tsman::scan_extent_headers(Signal* signal, Ptr<Datafile> ptr)
-{
- Ptr<Tablespace> lg_ptr;
- m_tablespace_pool.getPtr(lg_ptr, ptr.p->m_tablespace_ptr_i);
-
- Uint32 firstFree= RNIL;
- Uint32 size = ptr.p->m_extent_size;
- Uint32 per_page = ptr.p->m_online.m_extent_headers_per_extent_page;
- Uint32 pages= ptr.p->m_online.m_offset_data_pages - 1;
- Uint32 datapages= ptr.p->m_online.m_data_pages;
- Dbtup* tup= (Dbtup*)globalData.getBlock(DBTUP);
- ndbrequire(tup != 0);
- for(Uint32 i = 0; i < pages; i++)
- {
- Uint32 page_no = pages - i;
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = page_no;
- preq.m_page.m_file_no = ptr.p->m_file_no;
-
- int flags = Page_cache_client::DIRTY_REQ;
- int real_page_id = m_page_cache_client.get_page(signal, preq, flags);
- ndbrequire(real_page_id > 0);
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)m_page_cache_client.m_ptr.p;
-
- Uint32 extents= per_page;
- if(page_no == pages)
- {
- /**
- * Last extent header page...
- * set correct no of extent headers
- */
- extents= (datapages / size) % per_page;
- }
- for(Uint32 j = 0; j<extents; j++)
- {
- Uint32 extent_no = extents - j - 1;
- File_formats::Datafile::Extent_header* header=
- page->get_header(extent_no, size);
- if (header->m_table == RNIL)
- {
- header->m_next_free_extent = firstFree;
- firstFree = page_no * per_page + extent_no;
- }
- else
- {
- Uint32 tableId= header->m_table;
- Uint32 fragmentId= header->m_fragment_id;
- Local_key key;
- key.m_file_no = ptr.p->m_file_no;
- key.m_page_no =
- pages + 1 + size * (page_no * per_page + extent_no - per_page);
- key.m_page_idx = page_no * per_page + extent_no;
- if(!tup->disk_restart_alloc_extent(tableId, fragmentId, &key, size))
- {
- ptr.p->m_online.m_used_extent_cnt++;
- for(Uint32 i = 0; i<size; i++, key.m_page_no++)
- {
- Uint32 bits= header->get_free_bits(i) & COMMITTED_MASK;
- header->update_free_bits(i, bits | (bits << UNCOMMITTED_SHIFT));
- tup->disk_restart_page_bits(tableId, fragmentId, &key, bits);
- }
- }
- else
- {
- header->m_table = RNIL;
- header->m_next_free_extent = firstFree;
- firstFree = page_no * per_page + extent_no;
- }
- }
- }
- }
- ptr.p->m_online.m_first_free_extent= firstFree;
-
- Local_datafile_list meta(m_file_pool, lg_ptr.p->m_meta_files);
- Ptr<Datafile> next = ptr;
- meta.next(next);
- if(firstFree != RNIL)
- {
- Local_datafile_list free(m_file_pool, lg_ptr.p->m_free_files);
- meta.remove(ptr);
- free.add(ptr);
- }
- else
- {
- Local_datafile_list full(m_file_pool, lg_ptr.p->m_full_files);
- meta.remove(ptr);
- full.add(ptr);
- }
-
- signal->theData[0] = TsmanContinueB::SCAN_DATAFILE_EXTENT_HEADERS;
- signal->theData[1] = lg_ptr.i;
- signal->theData[2] = next.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
-}
-
-void
-Tsman::execDROP_FILE_REQ(Signal* signal)
-{
- jamEntry();
- DropFileImplReq req = *(DropFileImplReq*)signal->getDataPtr();
- Ptr<Datafile> file_ptr;
- Ptr<Tablespace> fg_ptr;
-
- Uint32 errorCode = 0;
- do
- {
- if (!m_tablespace_hash.find(fg_ptr, req.filegroup_id))
- {
- errorCode = DropFileImplRef::InvalidFilegroup;
- break;
- }
-
- if (fg_ptr.p->m_version != req.filegroup_version)
- {
- errorCode = DropFileImplRef::InvalidFilegroupVersion;
- break;
- }
-
- switch(req.requestInfo){
- case DropFileImplReq::Prepare:{
- if (find_file_by_id(file_ptr, fg_ptr.p->m_full_files, req.file_id))
- {
- jam();
- Local_datafile_list full(m_file_pool, fg_ptr.p->m_full_files);
- full.remove(file_ptr);
- }
- else if(find_file_by_id(file_ptr, fg_ptr.p->m_free_files, req.file_id))
- {
- jam();
- Local_datafile_list free(m_file_pool, fg_ptr.p->m_free_files);
- free.remove(file_ptr);
- }
- else if(find_file_by_id(file_ptr, fg_ptr.p->m_meta_files, req.file_id))
- {
- jam();
- Local_datafile_list meta(m_file_pool, fg_ptr.p->m_meta_files);
- meta.remove(file_ptr);
- }
- else
- {
- errorCode = DropFileImplRef::NoSuchFile;
- break;
- }
-
- Local_datafile_list meta(m_file_pool, fg_ptr.p->m_meta_files);
- meta.add(file_ptr);
-
- if (file_ptr.p->m_online.m_used_extent_cnt ||
- file_ptr.p->m_state != Datafile::FS_ONLINE)
- {
- errorCode = DropFileImplRef::FileInUse;
- break;
- }
-
- file_ptr.p->m_state = Datafile::FS_DROPPING;
- break;
- }
- case DropFileImplReq::Commit:
- ndbrequire(find_file_by_id(file_ptr, fg_ptr.p->m_meta_files, req.file_id));
- file_ptr.p->m_create.m_extent_pages =
- file_ptr.p->m_online.m_offset_data_pages - 1;
- file_ptr.p->m_create.m_senderRef = req.senderRef;
- file_ptr.p->m_create.m_senderData = req.senderData;
- release_extent_pages(signal, file_ptr);
- return;
- case DropFileImplReq::Abort:{
- ndbrequire(find_file_by_id(file_ptr, fg_ptr.p->m_meta_files, req.file_id));
- file_ptr.p->m_state = Datafile::FS_ONLINE;
- Local_datafile_list meta(m_file_pool, fg_ptr.p->m_meta_files);
- meta.remove(file_ptr);
- if (file_ptr.p->m_online.m_first_free_extent != RNIL)
- {
- Local_datafile_list free(m_file_pool, fg_ptr.p->m_free_files);
- free.add(file_ptr);
- }
- else
- {
- Local_datafile_list full(m_file_pool, fg_ptr.p->m_full_files);
- full.add(file_ptr);
- }
- break;
- }
- }
- } while(0);
-
- if (errorCode)
- {
- DropFileImplRef* ref = (DropFileImplRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = req.senderData;
- ref->errorCode = errorCode;
- sendSignal(req.senderRef, GSN_DROP_FILE_REF, signal,
- DropFileImplRef::SignalLength, JBB);
- }
- else
- {
- DropFileImplConf* conf = (DropFileImplConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = req.senderData;
- sendSignal(req.senderRef, GSN_DROP_FILE_CONF, signal,
- DropFileImplConf::SignalLength, JBB);
- }
-}
-
-Tsman::Tablespace::Tablespace(Tsman* ts, Lgman* lg,
- const CreateFilegroupImplReq* req)
- : m_logfile_client(ts, lg, req->tablespace.logfile_group_id)
-{
- m_tablespace_id = req->filegroup_id;
- m_version = req->filegroup_version;
-
- m_extent_size = DIV(req->tablespace.extent_size, File_formats::NDB_PAGE_SIZE);}
-
-Tsman::Datafile::Datafile(const struct CreateFileImplReq* req)
-{
- m_file_id = req->file_id;
-
- m_file_no = RNIL;
- m_fd = RNIL;
- m_online.m_first_free_extent = RNIL;
-
- m_create.m_senderRef = req->senderRef; // During META
- m_create.m_senderData = req->senderData; // During META
- m_create.m_requestInfo = req->requestInfo;
-}
-
-void
-Tsman::execALLOC_EXTENT_REQ(Signal* signal)
-{
- jamEntry();
- Ptr<Tablespace> ts_ptr;
- Ptr<Datafile> file_ptr;
- AllocExtentReq req = *(AllocExtentReq*)signal->getDataPtr();
- AllocExtentReq::ErrorCode err;
-
- ndbrequire(m_tablespace_hash.find(ts_ptr, req.request.tablespace_id));
- Local_datafile_list tmp(m_file_pool, ts_ptr.p->m_free_files);
-
- if (tmp.first(file_ptr))
- {
- Uint32 size = file_ptr.p->m_extent_size;
- Uint32 extent = file_ptr.p->m_online.m_first_free_extent;
- Uint32 data_off = file_ptr.p->m_online.m_offset_data_pages;
- Uint32 eh_words = File_formats::Datafile::extent_header_words(size);
- Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS/eh_words;
- Uint32 page_no = extent / per_page;
- Uint32 extent_no = extent % per_page;
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = page_no;
- preq.m_page.m_file_no = file_ptr.p->m_file_no;
-
- /**
- * Handling of unmapped extent header pages is not implemented
- */
- int flags = Page_cache_client::DIRTY_REQ;
- int real_page_id;
- if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- File_formats::Datafile::Extent_header* header =
- page->get_header(extent_no, size);
-
- ndbrequire(header->m_table == RNIL);
- Uint32 next_free = header->m_next_free_extent;
-
- /**
- * Init header
- */
- bzero(header, 4*eh_words);
- header->m_table = req.request.table_id;
- header->m_fragment_id = req.request.fragment_id;
-
- /**
- * Check if file is full
- */
- file_ptr.p->m_online.m_used_extent_cnt++;
- file_ptr.p->m_online.m_first_free_extent = next_free;
- if (next_free == RNIL)
- {
- jam();
- Local_datafile_list full(m_file_pool, ts_ptr.p->m_full_files);
- tmp.remove(file_ptr);
- full.add(file_ptr);
- }
-
- /**
- * Pack return values
- */
- ndbassert(extent >= per_page);
- preq.m_page.m_page_no = data_off + size * (extent - /* zero */ per_page);
- preq.m_page.m_page_idx = extent; // extent_no
-
- AllocExtentReq* rep = (AllocExtentReq*)signal->getDataPtr();
- rep->reply.errorCode = 0;
- rep->reply.page_id = preq.m_page;
- rep->reply.page_count = size;
- return;
- }
- else
- {
- jam();
- err = AllocExtentReq::UnmappedExtentPageIsNotImplemented;
- }
- }
- else
- {
- jam();
- err = AllocExtentReq::NoExtentAvailable;
- Local_datafile_list full_tmp(m_file_pool, ts_ptr.p->m_full_files);
- if (tmp.isEmpty() && full_tmp.isEmpty())
- {
- jam();
- err = AllocExtentReq::NoDatafile;
- }
- }
-
- /**
- * Pack return values
- */
- AllocExtentReq* rep = (AllocExtentReq*)signal->getDataPtr();
- rep->reply.errorCode = err;
- return;
-}
-
-void
-Tsman::execFREE_EXTENT_REQ(Signal* signal)
-{
- jamEntry();
- Ptr<Datafile> file_ptr;
- FreeExtentReq req = *(FreeExtentReq*)signal->getDataPtr();
- FreeExtentReq::ErrorCode err = (FreeExtentReq::ErrorCode)0;
-
- Datafile file_key;
- file_key.m_file_no = req.request.key.m_file_no;
- ndbrequire(m_file_hash.find(file_ptr, file_key));
-
- struct req val = lookup_extent(req.request.key.m_page_no, file_ptr.p);
- Uint32 extent =
- (req.request.key.m_page_no - val.m_extent_pages) / val.m_extent_size +
- file_ptr.p->m_online.m_extent_headers_per_extent_page;
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = val.m_extent_page_no;
- preq.m_page.m_file_no = req.request.key.m_file_no;
-
- ndbout << "Free extent: " << req.request.key << endl;
-
- /**
- * Handling of unmapped extent header pages is not implemented
- */
- int flags = Page_cache_client::DIRTY_REQ;
- int real_page_id;
- if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- File_formats::Datafile::Extent_header* header =
- page->get_header(val.m_extent_no, val.m_extent_size);
-
- ndbrequire(header->m_table == req.request.table_id);
- header->m_table = RNIL;
-
- file_ptr.p->m_online.m_used_extent_cnt--;
- if (m_lcp_ongoing)
- {
- jam();
- header->m_next_free_extent= file_ptr.p->m_online.m_lcp_free_extent_head;
- if(file_ptr.p->m_online.m_lcp_free_extent_head == RNIL)
- file_ptr.p->m_online.m_lcp_free_extent_tail= extent;
- file_ptr.p->m_online.m_lcp_free_extent_head= extent;
- }
- else
- {
- jam();
- header->m_next_free_extent = file_ptr.p->m_online.m_first_free_extent;
- if (file_ptr.p->m_online.m_first_free_extent == RNIL)
- {
- /**
- * Move from full to free
- */
- Ptr<Tablespace> ptr;
- m_tablespace_pool.getPtr(ptr, file_ptr.p->m_tablespace_ptr_i);
- Local_datafile_list free(m_file_pool, ptr.p->m_free_files);
- Local_datafile_list full(m_file_pool, ptr.p->m_full_files);
- full.remove(file_ptr);
- free.add(file_ptr);
- }
- file_ptr.p->m_online.m_first_free_extent = extent;
- }
- }
- else
- {
- jam();
- err = FreeExtentReq::UnmappedExtentPageIsNotImplemented;
- }
-
- /**
- * Pack return values
- */
- FreeExtentReq* rep = (FreeExtentReq*)signal->getDataPtr();
- rep->reply.errorCode = err;
- return;
-}
-
-int
-Tsman::update_page_free_bits(Signal* signal,
- Local_key *key,
- unsigned committed_bits)
-{
- jamEntry();
-
- /**
- * 1) Compute which extent_no key belongs to
- * 2) Find out which page extent_no belongs to
- * 3) Undo log m_page_bitmask
- * 4) Update m_page_bitmask
- */
- Ptr<Datafile> file_ptr;
- Datafile file_key;
- file_key.m_file_no = key->m_file_no;
- ndbrequire(m_file_hash.find(file_ptr, file_key));
-
- struct req val = lookup_extent(key->m_page_no, file_ptr.p);
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = val.m_extent_page_no;
- preq.m_page.m_file_no = key->m_file_no;
-
- /**
- * Handling of unmapped extent header pages is not implemented
- */
- int flags = Page_cache_client::COMMIT_REQ;
- int real_page_id;
- if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- File_formats::Datafile::Extent_header* header =
- page->get_header(val.m_extent_no, val.m_extent_size);
-
- if (header->m_table == RNIL)
- {
- ndbout << "update page free bits page: " << *key
- << " " << *header << endl;
- }
-
- if (0)
- {
- ndbout << "update page free bits page(" << committed_bits << ") "
- << *key << " " << *header << endl;
- }
-
- ndbrequire(header->m_table != RNIL);
-
- Uint32 page_no_in_extent = calc_page_no_in_extent(key->m_page_no, &val);
-
- /**
- * Toggle word
- */
- ndbassert((committed_bits & ~(COMMITTED_MASK)) == 0);
- Uint32 src = header->get_free_bits(page_no_in_extent) & UNCOMMITTED_MASK;
- header->update_free_bits(page_no_in_extent, src | committed_bits);
-
- m_page_cache_client.update_lsn(preq.m_page, 0);
-
- return 0;
- }
-
- return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
-}
-
-int
-Tsman::get_page_free_bits(Signal* signal, Local_key *key,
- unsigned* uncommitted,
- unsigned* committed)
-{
- jamEntry();
-
- Ptr<Datafile> file_ptr;
- Datafile file_key;
- file_key.m_file_no = key->m_file_no;
- ndbrequire(m_file_hash.find(file_ptr, file_key));
-
- struct req val = lookup_extent(key->m_page_no, file_ptr.p);
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = val.m_extent_page_no;
- preq.m_page.m_file_no = key->m_file_no;
-
- /**
- * Handling of unmapped extent header pages is not implemented
- */
- int flags = 0;
- int real_page_id;
- if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- File_formats::Datafile::Extent_header* header =
- page->get_header(val.m_extent_no, val.m_extent_size);
-
- ndbrequire(header->m_table != RNIL);
-
- Uint32 page_no_in_extent = calc_page_no_in_extent(key->m_page_no, &val);
- Uint32 bits = header->get_free_bits(page_no_in_extent);
- *uncommitted = (bits & UNCOMMITTED_MASK) >> UNCOMMITTED_SHIFT;
- *committed = (bits & COMMITTED_MASK);
- return 0;
- }
-
- return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
-}
-
-int
-Tsman::unmap_page(Signal* signal, Local_key *key, Uint32 uncommitted_bits)
-{
- jamEntry();
-
- /**
- * 1) Compute which extent_no key belongs to
- * 2) Find out which page extent_no belongs to
- * 3) Undo log m_page_bitmask
- * 4) Update m_page_bitmask
- */
- Ptr<Datafile> file_ptr;
- Datafile file_key;
- file_key.m_file_no = key->m_file_no;
- ndbrequire(m_file_hash.find(file_ptr, file_key));
-
- struct req val = lookup_extent(key->m_page_no, file_ptr.p);
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = val.m_extent_page_no;
- preq.m_page.m_file_no = key->m_file_no;
-
- /**
- * Handling of unmapped extent header pages is not implemented
- */
- int flags = 0;
- int real_page_id;
- if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- File_formats::Datafile::Extent_header* header =
- page->get_header(val.m_extent_no, val.m_extent_size);
-
- if (header->m_table == RNIL)
- {
- ndbout << "trying to unmap page: " << *key
- << " " << *header << endl;
- }
- ndbrequire(header->m_table != RNIL);
-
- Uint32 page_no_in_extent = calc_page_no_in_extent(key->m_page_no, &val);
-
- /**
- * Toggle word
- */
- ndbassert(((uncommitted_bits << UNCOMMITTED_SHIFT) & ~UNCOMMITTED_MASK) == 0);
- Uint32 src = header->get_free_bits(page_no_in_extent) & COMMITTED_MASK;
- header->update_free_bits(page_no_in_extent,
- src | (uncommitted_bits << UNCOMMITTED_SHIFT));
- }
-
- return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
-}
-
-int
-Tsman::restart_undo_page_free_bits(Signal* signal,
- Uint32 tableId,
- Uint32 fragId,
- Local_key *key,
- unsigned bits)
-{
- jamEntry();
-
- /**
- * 1) Compute which extent_no key belongs to
- * 2) Find out which page extent_no belongs to
- * 3) Undo log m_page_bitmask
- * 4) Update m_page_bitmask
- */
- Ptr<Datafile> file_ptr;
- Datafile file_key;
- file_key.m_file_no = key->m_file_no;
- ndbrequire(m_file_hash.find(file_ptr, file_key));
-
- struct req val = lookup_extent(key->m_page_no, file_ptr.p);
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = val.m_extent_page_no;
- preq.m_page.m_file_no = key->m_file_no;
-
- /**
- * Handling of unmapped extent header pages is not implemented
- */
- int flags = Page_cache_client::DIRTY_REQ;
- int real_page_id;
- if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- File_formats::Datafile::Extent_header* header =
- page->get_header(val.m_extent_no, val.m_extent_size);
-
- if (header->m_table == RNIL)
- {
- if (DBG_UNDO)
- ndbout_c("tsman: apply undo - skip table == RNIL");
- return 0;
- }
-
- Uint32 page_no_in_extent = calc_page_no_in_extent(key->m_page_no, &val);
- Uint32 src = header->get_free_bits(page_no_in_extent);
-
- ndbrequire(header->m_table == tableId);
- ndbrequire(header->m_fragment_id == fragId);
-
- /**
- * Toggle word
- */
- if (DBG_UNDO)
- {
- ndbout << "tsman: apply "
- << *key << " " << (src & COMMITTED_MASK)
- << " -> " << bits << endl;
- }
-
- ndbassert((bits & ~(COMMITTED_MASK)) == 0);
- header->update_free_bits(page_no_in_extent,
- bits | (bits << UNCOMMITTED_SHIFT));
-
- return 0;
- }
-
- return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
-}
-
-void
-Tsman::execALLOC_PAGE_REQ(Signal* signal)
-{
- jamEntry();
-
- AllocPageReq *rep= (AllocPageReq*)signal->getDataPtr();
- AllocPageReq req = *rep;
- AllocPageReq::ErrorCode
- err= AllocPageReq::UnmappedExtentPageIsNotImplemented;
-
- /**
- * 1) Compute which extent_no key belongs to
- * 2) Find out which page extent_no belongs to
- * 3) Undo log m_page_bitmask
- * 4) Update m_page_bitmask
- */
- Ptr<Datafile> file_ptr;
- Datafile file_key;
- file_key.m_file_no = req.key.m_file_no;
- ndbrequire(m_file_hash.find(file_ptr, file_key));
-
- struct req val = lookup_extent(req.key.m_page_no, file_ptr.p);
- Uint32 page_no_in_extent = calc_page_no_in_extent(req.key.m_page_no, &val);
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = val.m_extent_page_no;
- preq.m_page.m_file_no = req.key.m_file_no;
-
- Uint32 SZ= File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE;
-
- /**
- * Handling of unmapped extent header pages is not implemented
- */
- int flags = Page_cache_client::DIRTY_REQ;
- int real_page_id;
- Uint32 page_no;
- Uint32 src_bits;
- File_formats::Datafile::Extent_header* header;
- if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
- {
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- header= page->get_header(val.m_extent_no, val.m_extent_size);
-
- ndbrequire(header->m_table == req.request.table_id);
-
- Uint32 word = header->get_free_word_offset(page_no_in_extent);
- Uint32 shift = SZ * (page_no_in_extent & 7);
-
- /**
- * 0 = 00 - free - 100% free
- * 1 = 01 - atleast 70% free, 70= pct_free + 2 * (100 - pct_free) / 3
- * 2 = 10 - atleast 40% free, 40= pct_free + (100 - pct_free) / 3
- * 3 = 11 - full - less than pct_free% free, pct_free=10%
- */
-
- Uint32 reqbits = req.bits << UNCOMMITTED_SHIFT;
-
- /**
- * Search
- */
- Uint32 *src= header->m_page_bitmask + word;
- for(page_no= page_no_in_extent; page_no<val.m_extent_size; page_no++)
- {
- src_bits= (* src >> shift) & ((1 << SZ) - 1);
- if((src_bits & UNCOMMITTED_MASK) <= reqbits)
- {
- goto found;
- }
- shift += SZ;
- src = src + (shift >> 5);
- shift &= 31;
- }
-
- shift= 0;
- src= header->m_page_bitmask;
- for(page_no= 0; page_no<page_no_in_extent; page_no++)
- {
- src_bits= (* src >> shift) & ((1 << SZ) - 1);
- if((src_bits & UNCOMMITTED_MASK) <= reqbits)
- {
- goto found;
- }
- shift += SZ;
- src = src + (shift >> 5);
- shift &= 31;
- }
-
-#if 0
- printf("req.bits: %d bits: ", req.bits);
- for(Uint32 i = 0; i<size; i++)
- {
- printf("%x", header->get_free_bits(i));
- }
- ndbout_c("");
-#endif
- err= AllocPageReq::NoPageFree;
- }
-
- rep->reply.errorCode = err;
- return;
-
-found:
- header->update_free_bits(page_no, src_bits | UNCOMMITTED_MASK);
- rep->bits= (src_bits & UNCOMMITTED_MASK) >> UNCOMMITTED_SHIFT;
- rep->key.m_page_no = req.key.m_page_no + page_no - page_no_in_extent;
- rep->reply.errorCode= 0;
- return;
-}
-
-void
-Tsman::execLCP_FRAG_ORD(Signal* signal)
-{
- jamEntry();
- ndbrequire(!m_lcp_ongoing);
- m_lcp_ongoing = true;
-}
-
-void
-Tsman::execEND_LCP_REQ(Signal* signal)
-{
- jamEntry();
- ndbrequire(m_lcp_ongoing);
- m_lcp_ongoing = false;
-
- /**
- * Move extents from "lcp" free list to real free list
- */
- Ptr<Tablespace> ptr;
- if(m_tablespace_list.first(ptr))
- {
- signal->theData[0] = TsmanContinueB::END_LCP;
- signal->theData[1] = ptr.i;
- signal->theData[2] = 0; // free
- signal->theData[3] = RNIL; // first
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
- }
-}
-
-void
-Tsman::end_lcp(Signal* signal, Uint32 ptrI, Uint32 list, Uint32 filePtrI)
-{
- Ptr<Tablespace> ptr;
- m_tablespace_list.getPtr(ptr, ptrI);
-
- Ptr<Datafile> file;
- file.i = filePtrI;
- Uint32 nextFile = RNIL;
-
- switch(list){
- case 0:
- {
- Local_datafile_list tmp(m_file_pool, ptr.p->m_free_files);
- if(file.i == RNIL)
- {
- if(!tmp.first(file))
- {
- list= 1;
- goto next;
- }
- }
- else
- {
- tmp.getPtr(file);
- }
- break;
- }
- case 1:
- {
- Local_datafile_list tmp(m_file_pool, ptr.p->m_full_files);
- if(file.i == RNIL)
- {
- if(!tmp.first(file))
- {
- list= 0;
- if(m_tablespace_list.next(ptr))
- goto next;
- return;
- }
- }
- else
- {
- tmp.getPtr(file);
- }
- break;
- }
- default:
- ndbrequire(false);
- }
-
- nextFile = file.p->nextList;
-
- /**
- * Move extents...
- */
- if(file.p->m_online.m_lcp_free_extent_head != RNIL)
- {
- ndbout_c("moving extents (%d %d) to real free list %d",
- file.p->m_online.m_lcp_free_extent_head,
- file.p->m_online.m_lcp_free_extent_tail,
- file.p->m_online.m_first_free_extent);
-
- if(file.p->m_online.m_first_free_extent == RNIL)
- {
- ndbrequire(list == 1);
- file.p->m_online.m_first_free_extent =
- file.p->m_online.m_lcp_free_extent_head;
- file.p->m_online.m_lcp_free_extent_head = RNIL;
- file.p->m_online.m_lcp_free_extent_tail = RNIL;
-
- Local_datafile_list free(m_file_pool, ptr.p->m_free_files);
- Local_datafile_list full(m_file_pool, ptr.p->m_full_files);
- full.remove(file);
- free.add(file);
- }
- else
- {
- Uint32 extent = file.p->m_online.m_lcp_free_extent_tail;
- Uint32 size = ptr.p->m_extent_size;
- Uint32 eh_words = File_formats::Datafile::extent_header_words(size);
- Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS/eh_words;
-
- Uint32 page_no = extent / per_page;
- Uint32 extent_no = extent % per_page;
-
- Page_cache_client::Request preq;
- preq.m_page.m_page_no = page_no;
- preq.m_page.m_file_no = file.p->m_file_no;
-
- int flags = Page_cache_client::DIRTY_REQ;
- int real_page_id;
- ndbrequire((real_page_id = m_page_cache_client.get_page(signal, preq,
- flags)) > 0);
-
- GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
-
- File_formats::Datafile::Extent_page* page =
- (File_formats::Datafile::Extent_page*)ptr_p;
- File_formats::Datafile::Extent_header* header =
- page->get_header(extent_no, size);
-
- header->m_next_free_extent = file.p->m_online.m_first_free_extent;
- file.p->m_online.m_first_free_extent =
- file.p->m_online.m_lcp_free_extent_head;
-
- file.p->m_online.m_lcp_free_extent_head = RNIL;
- file.p->m_online.m_lcp_free_extent_tail = RNIL;
- }
- }
-
-
- /**
- * next file
- */
- file.i = nextFile;
- if(file.i == RNIL)
- {
- if(list == 0)
- list = 1;
- else
- {
- list = 0;
- m_tablespace_list.next(ptr);
- }
- }
-
-next:
- if(ptr.i != RNIL)
- {
- signal->theData[0] = TsmanContinueB::END_LCP;
- signal->theData[1] = ptr.i;
- signal->theData[2] = list;
- signal->theData[3] = file.i;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
- }
-}
-
-int
-Tablespace_client::get_tablespace_info(CreateFilegroupImplReq* rep)
-{
- Ptr<Tsman::Tablespace> ts_ptr;
- if(m_tsman->m_tablespace_hash.find(ts_ptr, m_tablespace_id));
- {
- rep->tablespace.extent_size = ts_ptr.p->m_extent_size;
- rep->tablespace.logfile_group_id =
- ts_ptr.p->m_logfile_client.m_logfile_group_id;
- return 0;
- }
- return -1;
-}
-
-void Tsman::execGET_TABINFOREQ(Signal* signal)
-{
- jamEntry();
-
- if(!assembleFragments(signal))
- {
- return;
- }
-
- GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
-
- Uint32 tableId= req->tableId;
- const Uint32 reqType = req->requestType & (~GetTabInfoReq::LongSignalConf);
- BlockReference retRef= req->senderRef;
- Uint32 senderData= req->senderData;
-
- if(reqType == GetTabInfoReq::RequestByName){
- jam();
- releaseSections(signal);
-
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::NoFetchByName);
- return;
- }
-
- Datafile_hash::Iterator iter;
- ndbrequire(m_file_hash.first(iter));
-
- while(iter.curr.p->m_file_id != tableId && m_file_hash.next(iter))
- ;
-
- if(iter.curr.p->m_file_id != tableId)
- {
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::InvalidTableId);
- return;
- }
-
- const Ptr<Datafile> &file_ptr= iter.curr;
-
- jam();
-
- Uint32 total_free_extents = file_ptr.p->m_online.m_data_pages;
- total_free_extents /= file_ptr.p->m_extent_size;
- total_free_extents -= file_ptr.p->m_online.m_used_extent_cnt;
-
- GetTabInfoConf *conf = (GetTabInfoConf *)&signal->theData[0];
-
- conf->senderData= senderData;
- conf->tableId= tableId;
- conf->freeExtents= total_free_extents;
- conf->tableType= DictTabInfo::Datafile;
- conf->senderRef= reference();
- sendSignal(retRef, GSN_GET_TABINFO_CONF, signal,
- GetTabInfoConf::SignalLength, JBB);
-}
-
-void Tsman::sendGET_TABINFOREF(Signal* signal,
- GetTabInfoReq * req,
- GetTabInfoRef::ErrorCode errorCode)
-{
- jamEntry();
- GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
- /**
- * The format of GetTabInfo Req/Ref is the same
- */
- BlockReference retRef = req->senderRef;
- ref->errorCode = errorCode;
-
- sendSignal(retRef, GSN_GET_TABINFOREF, signal, signal->length(), JBB);
-}
diff --git a/storage/ndb/src/kernel/blocks/tsman.hpp b/storage/ndb/src/kernel/blocks/tsman.hpp
deleted file mode 100644
index 6f005c1bfad..00000000000
--- a/storage/ndb/src/kernel/blocks/tsman.hpp
+++ /dev/null
@@ -1,453 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef TSMAN_H
-#define TSMAN_H
-
-#include <SimulatedBlock.hpp>
-
-#include <SLList.hpp>
-#include <DLList.hpp>
-#include <NodeBitmask.hpp>
-#include <signaldata/GetTabInfo.hpp>
-
-#include "lgman.hpp"
-#include "pgman.hpp"
-
-class Tsman : public SimulatedBlock
-{
-public:
- Tsman(Block_context&, Pgman*, Lgman*);
- virtual ~Tsman();
- BLOCK_DEFINES(Tsman);
-
-protected:
-
- void execSTTOR(Signal* signal);
- void sendSTTORRY(Signal*);
- void execREAD_CONFIG_REQ(Signal* signal);
- void execDUMP_STATE_ORD(Signal* signal);
- void execCONTINUEB(Signal* signal);
-
- void execCREATE_FILE_REQ(Signal* signal);
- void execCREATE_FILEGROUP_REQ(Signal* signal);
- void execDROP_FILE_REQ(Signal* signal);
- void execDROP_FILEGROUP_REQ(Signal* signal);
-
- void execSTART_RECREQ(Signal*);
-
- void execFSWRITEREQ(Signal*);
- void execFSOPENREF(Signal*);
- void execFSOPENCONF(Signal*);
- void execFSREADREF(Signal*);
- void execFSREADCONF(Signal*);
-
- void execFSCLOSEREF(Signal*);
- void execFSCLOSECONF(Signal*);
-
- void execALLOC_EXTENT_REQ(Signal*);
- void execFREE_EXTENT_REQ(Signal*);
-
- void execALLOC_PAGE_REQ(Signal* signal);
-
- void execLCP_FRAG_ORD(Signal*);
- void execEND_LCP_REQ(Signal*);
- void end_lcp(Signal*, Uint32 tablespace, Uint32 list, Uint32 file);
-
- void execGET_TABINFOREQ(Signal*);
-
- void sendGET_TABINFOREF(Signal* signal,
- GetTabInfoReq * req,
- GetTabInfoRef::ErrorCode errorCode);
-
-public:
- struct Datafile
- {
- Datafile(){}
- Datafile(const struct CreateFileImplReq*);
-
- /**
- * m_file_no
- * - Unique among datafiles on this node
- * - Part of local key
- * - Set by pgman
- */
- Uint32 m_magic;
- Uint32 m_file_no;
- Uint32 m_file_id; // Used when talking to DICT
- Uint32 m_fd; // NDBFS
-
- Uint32 m_tablespace_ptr_i;
- Uint32 m_extent_size;
- Uint32 m_state;
-
- enum FileState
- {
- FS_CREATING = 0x1,
- FS_ONLINE = 0x2,
- FS_DROPPING = 0x4
- };
-
- union {
- struct {
- Uint32 m_first_free_extent;
- Uint32 m_lcp_free_extent_head; // extents freed but not LCP
- Uint32 m_lcp_free_extent_tail;
- Uint32 m_offset_data_pages; // 1(zero) + extent header pages
- Uint32 m_data_pages;
- Uint32 m_used_extent_cnt;
- Uint32 m_extent_headers_per_extent_page;
- } m_online;
- struct {
- Uint32 m_senderData;
- Uint32 m_senderRef;
- Uint32 m_data_pages;
- Uint32 m_extent_pages;
- Uint32 m_requestInfo;
- union {
- Uint32 m_page_ptr_i;
- Uint32 m_loading_extent_page;
- };
- } m_create;
- };
-
- Uint32 nextHash;
- Uint32 prevHash;
- Uint32 nextList;
- union {
- Uint32 prevList;
- Uint32 nextPool;
- };
-
- Uint32 hashValue() const {
- return m_file_no;
- }
- bool equal(const Datafile& rec) const {
- return m_file_no == rec.m_file_no;
- }
- };
-
- typedef RecordPool<Datafile, RWPool> Datafile_pool;
- typedef DLListImpl<Datafile_pool, Datafile> Datafile_list;
- typedef LocalDLListImpl<Datafile_pool, Datafile> Local_datafile_list;
- typedef DLHashTableImpl<Datafile_pool, Datafile> Datafile_hash;
-
- struct Tablespace
- {
- Tablespace(){}
- Tablespace(Tsman*, Lgman*, const struct CreateFilegroupImplReq*);
-
- Uint32 m_magic;
- union {
- Uint32 key;
- Uint32 m_tablespace_id;
- };
- Uint32 m_version;
- Uint32 m_state;
-
- enum TablespaceState
- {
- TS_CREATING = 0x1,
- TS_ONLINE = 0x2,
- TS_DROPPING = 0x4
- };
-
- Uint32 m_extent_size; // In pages
- Datafile_list::Head m_free_files; // Files w/ free space
- Logfile_client m_logfile_client;
-
- Datafile_list::Head m_full_files; // Files wo/ free space
- Datafile_list::Head m_meta_files; // Files being created/dropped
-
- Uint32 nextHash;
- Uint32 prevHash;
- Uint32 nextList;
- union {
- Uint32 prevList;
- Uint32 nextPool;
- };
-
- Uint32 hashValue() const {
- return key;
- }
- bool equal(const Tablespace& rec) const {
- return key == rec.key;
- }
- };
-
- typedef RecordPool<Tablespace, RWPool> Tablespace_pool;
- typedef DLListImpl<Tablespace_pool, Tablespace> Tablespace_list;
- typedef LocalDLListImpl<Tablespace_pool, Tablespace> Local_tablespace_list;
- typedef KeyTableImpl<Tablespace_pool, Tablespace> Tablespace_hash;
-
-private:
- friend class Tablespace_client;
- Datafile_pool m_file_pool;
- Tablespace_pool m_tablespace_pool;
-
- bool m_lcp_ongoing;
- Datafile_hash m_file_hash;
- Tablespace_list m_tablespace_list;
- Tablespace_hash m_tablespace_hash;
- Page_cache_client m_page_cache_client;
- Lgman * const m_lgman;
-
- int open_file(Signal*, Ptr<Tablespace>, Ptr<Datafile>, CreateFileImplReq*);
- void load_extent_pages(Signal* signal, Ptr<Datafile> ptr);
- void load_extent_page_callback(Signal*, Uint32, Uint32);
- void create_file_ref(Signal*, Ptr<Tablespace>, Ptr<Datafile>,
- Uint32,Uint32,Uint32);
- int update_page_free_bits(Signal*, Local_key*, unsigned committed_bits);
-
- int get_page_free_bits(Signal*, Local_key*, unsigned*, unsigned*);
- int unmap_page(Signal*, Local_key*, unsigned uncommitted_bits);
- int restart_undo_page_free_bits(Signal*, Uint32, Uint32, Local_key*,
- unsigned committed_bits);
-
- int alloc_extent(Signal* signal, Uint32 tablespace, Local_key* key);
- int alloc_page_from_extent(Signal*, Uint32, Local_key*, Uint32 bits);
-
- void scan_tablespace(Signal*, Uint32 ptrI);
- void scan_datafile(Signal*, Uint32, Uint32);
- void scan_extent_headers(Signal*, Ptr<Datafile>);
-
- bool find_file_by_id(Ptr<Datafile>&, Datafile_list::Head&, Uint32 id);
- void create_file_abort(Signal* signal, Ptr<Datafile>);
-
- void release_extent_pages(Signal* signal, Ptr<Datafile> ptr);
- void release_extent_pages_callback(Signal*, Uint32, Uint32);
-
- struct req
- {
- Uint32 m_extent_pages;
- Uint32 m_extent_size;
- Uint32 m_extent_no; // on extent page
- Uint32 m_extent_page_no;
- };
-
- struct req lookup_extent(Uint32 page_no, const Datafile*) const;
- Uint32 calc_page_no_in_extent(Uint32 page_no, const struct req* val) const;
-};
-
-inline
-Tsman::req
-Tsman::lookup_extent(Uint32 page_no, const Datafile * filePtrP) const
-{
- struct req val;
- val.m_extent_size = filePtrP->m_extent_size;
- val.m_extent_pages = filePtrP->m_online.m_offset_data_pages;
- Uint32 per_page = filePtrP->m_online.m_extent_headers_per_extent_page;
-
- Uint32 extent =
- (page_no - val.m_extent_pages) / val.m_extent_size + per_page;
-
- val.m_extent_page_no = extent / per_page;
- val.m_extent_no = extent % per_page;
- return val;
-}
-
-inline
-Uint32
-Tsman::calc_page_no_in_extent(Uint32 page_no, const Tsman::req* val) const
-{
- return (page_no - val->m_extent_pages) % val->m_extent_size;
-}
-
-class Tablespace_client
-{
-public:
- Tsman * m_tsman;
- Signal* m_signal;
- Uint32 m_table_id;
- Uint32 m_fragment_id;
- Uint32 m_tablespace_id;
-
-public:
- Tablespace_client(Signal* signal, Tsman* tsman,
- Uint32 table, Uint32 fragment, Uint32 tablespaceId) {
- m_tsman= tsman;
- m_signal= signal;
- m_table_id= table;
- m_fragment_id= fragment;
- m_tablespace_id= tablespaceId;
- }
-
- Tablespace_client(Signal* signal, Tsman* tsman, Local_key* key);
-
- /**
- * Return >0 if success, no of pages in extent, sets key
- * <0 if failure, -error code
- */
- int alloc_extent(Local_key* key);
-
- /**
- * Allocated a page from an extent
- * performs linear search in extent free bits until it find
- * page that has atleast <em>bits</em> bits free
- *
- * Start search from key->m_page_no
- * and return found page in key->m_page_no
- * this make sequential calls find sequential pages
- *
- * If page is found, then the _unlogged_ "page allocated bit" is set
- * so that page can't be allocated twice unless freed first
- *
- * Note: user of allocated page should use update_page_free_bits
- * to undo log changes in free space on page
- *
- * Return <0 if none found
- * >=0 if found, then free bits of page found is returned
- */
- int alloc_page_from_extent(Local_key* key, unsigned bits);
-
- /**
- * Free extent
- */
- int free_extent(Local_key* key, Uint64 lsn);
-
- /**
- * Update page free bits
- */
- int update_page_free_bits(Local_key*, unsigned bits);
-
- /**
- * Get page free bits
- */
- int get_page_free_bits(Local_key*,
- unsigned* uncommitted, unsigned* committed);
-
- /**
- * Update unlogged page free bit
- */
- int unmap_page(Local_key*, Uint32 bits);
-
- /**
- * Undo handling of page bits
- */
- int restart_undo_page_free_bits(Local_key*, unsigned bits);
-
- /**
- * Get tablespace info
- *
- * Store result in <em>rep</em>
- *
- * Return 0 - on sucess
- * <0 - on error
- */
- int get_tablespace_info(CreateFilegroupImplReq* rep);
-
- /**
- * Update lsn of page corresponing to key
- */
- int update_lsn(Local_key* key, Uint64 lsn);
-};
-
-#include <signaldata/Extent.hpp>
-
-inline
-int
-Tablespace_client::alloc_extent(Local_key* key)
-{
- AllocExtentReq* req = (AllocExtentReq*)m_signal->theData;
- req->request.table_id = m_table_id;
- req->request.fragment_id = m_fragment_id;
- req->request.tablespace_id = m_tablespace_id;
- m_tsman->execALLOC_EXTENT_REQ(m_signal);
-
- if(req->reply.errorCode == 0){
- * key = req->reply.page_id;
- return req->reply.page_count;
- } else {
- return -req->reply.errorCode;
- }
-}
-
-inline
-int
-Tablespace_client::alloc_page_from_extent(Local_key* key, Uint32 bits)
-{
- AllocPageReq* req = (AllocPageReq*)m_signal->theData;
- req->key= *key;
- req->bits= bits;
- req->request.table_id = m_table_id;
- req->request.fragment_id = m_fragment_id;
- req->request.tablespace_id = m_tablespace_id;
- m_tsman->execALLOC_PAGE_REQ(m_signal);
-
- if(req->reply.errorCode == 0){
- *key = req->key;
- return req->bits;
- } else {
- return -req->reply.errorCode;
- }
-}
-
-inline
-int
-Tablespace_client::free_extent(Local_key* key, Uint64 lsn)
-{
- FreeExtentReq* req = (FreeExtentReq*)m_signal->theData;
- req->request.key = *key;
- req->request.table_id = m_table_id;
- req->request.tablespace_id = m_tablespace_id;
- req->request.lsn_hi = (Uint32)(lsn >> 32);
- req->request.lsn_lo = (Uint32)(lsn & 0xFFFFFFFF);
- m_tsman->execFREE_EXTENT_REQ(m_signal);
-
- if(req->reply.errorCode == 0){
- return 0;
- } else {
- return -req->reply.errorCode;
- }
-}
-
-inline
-int
-Tablespace_client::update_page_free_bits(Local_key *key,
- unsigned committed_bits)
-{
- return m_tsman->update_page_free_bits(m_signal, key, committed_bits);
-}
-
-inline
-int
-Tablespace_client::get_page_free_bits(Local_key *key,
- unsigned* uncommited,
- unsigned* commited)
-{
- return m_tsman->get_page_free_bits(m_signal, key, uncommited, commited);
-}
-
-inline
-int
-Tablespace_client::unmap_page(Local_key *key, unsigned uncommitted_bits)
-{
- return m_tsman->unmap_page(m_signal, key, uncommitted_bits);
-}
-
-inline
-int
-Tablespace_client::restart_undo_page_free_bits(Local_key* key,
- unsigned committed_bits)
-{
- return m_tsman->restart_undo_page_free_bits(m_signal,
- m_table_id,
- m_fragment_id,
- key,
- committed_bits);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/error/ErrorHandlingMacros.hpp b/storage/ndb/src/kernel/error/ErrorHandlingMacros.hpp
deleted file mode 100644
index aefc1b89f11..00000000000
--- a/storage/ndb/src/kernel/error/ErrorHandlingMacros.hpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef ERRORHANDLINGMACROS_H
-#define ERRORHANDLINGMACROS_H
-
-#include <ndbd_exit_codes.h>
-#include "ErrorReporter.hpp"
-
-extern const char programName[];
-
-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:
- // messageID IN Code identifying the error. If less
- // than 1000 a unix error is assumed. If
- // greater than 1000 the code is treated
- // as the specific problem code.
- // problemData IN A (short) text describing the error.
- // The context information is added to
- // this text.
- // objectRef IN The name of the "victim" of the error.
- // Specify NULL if not applicable.
- // Return value:
- // -
- // Reported errors:
- // -
- // Additional information:
- // -
-
-#endif
diff --git a/storage/ndb/src/kernel/error/ErrorReporter.cpp b/storage/ndb/src/kernel/error/ErrorReporter.cpp
deleted file mode 100644
index 0e3712b739b..00000000000
--- a/storage/ndb/src/kernel/error/ErrorReporter.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-
-#include <ndbd_exit_codes.h>
-#include "ErrorReporter.hpp"
-
-#include <FastScheduler.hpp>
-#include <DebuggerNames.hpp>
-#include <NdbHost.h>
-#include <NdbConfig.h>
-#include <Configuration.hpp>
-#include "EventLogger.hpp"
-
-#include <NdbAutoPtr.hpp>
-
-#define MESSAGE_LENGTH 500
-
-static int WriteMessage(int thrdMessageID,
- const char* thrdProblemData,
- const char* thrdObjRef,
- Uint32 thrdTheEmulatedJamIndex,
- Uint8 thrdTheEmulatedJam[]);
-
-static void dumpJam(FILE* jamStream,
- Uint32 thrdTheEmulatedJamIndex,
- Uint8 thrdTheEmulatedJam[]);
-
-extern EventLogger g_eventLogger;
-const char*
-ErrorReporter::formatTimeStampString(){
- TimeModule DateTime; /* To create "theDateTimeString" */
-
- static char theDateTimeString[39];
- /* Used to store the generated timestamp */
- /* ex: "Wednesday 18 September 2000 - 18:54:37" */
-
- DateTime.setTimeStamp();
-
- BaseString::snprintf(theDateTimeString, 39, "%s %d %s %d - %s:%s:%s",
- DateTime.getDayName(), DateTime.getDayOfMonth(),
- DateTime.getMonthName(), DateTime.getYear(), DateTime.getHour(),
- DateTime.getMinute(), DateTime.getSecond());
-
- return (const char *)&theDateTimeString;
-}
-
-int
-ErrorReporter::get_trace_no(){
-
- FILE *stream;
- unsigned int traceFileNo;
-
- char *file_name= NdbConfig_NextTraceFileName(globalData.ownId);
- NdbAutoPtr<char> tmp_aptr(file_name);
-
- /*
- * Read last number from tracefile
- */
- stream = fopen(file_name, "r+");
- if (stream == NULL){
- traceFileNo = 1;
- } else {
- char buf[255];
- fgets(buf, 255, stream);
- const int scan = sscanf(buf, "%u", &traceFileNo);
- if(scan != 1){
- traceFileNo = 1;
- }
- fclose(stream);
- traceFileNo++;
- }
-
- /**
- * Wrap tracefile no
- */
- Uint32 tmp = globalEmulatorData.theConfiguration->maxNoOfErrorLogs();
- if (traceFileNo > tmp ) {
- traceFileNo = 1;
- }
-
- /**
- * Save new number to the file
- */
- stream = fopen(file_name, "w");
- if(stream != NULL){
- fprintf(stream, "%u", traceFileNo);
- fclose(stream);
- }
-
- return traceFileNo;
-}
-
-
-void
-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,
- "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() ,
- exit_st_msg,
- exit_msg, exit_cl_msg,
- faultID,
- (problemData == NULL) ? "" : problemData,
- objRef,
- my_progname,
- processId,
- theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>",
- NDB_VERSION_STRING);
-
- // Add trailing blanks to get a fixed lenght of the message
- while (strlen(messptr) <= MESSAGE_LENGTH-3){
- strcat(messptr, " ");
- }
-
- strcat(messptr, "\n");
-
- return;
-}
-
-NdbShutdownType ErrorReporter::s_errorHandlerShutdownType = NST_ErrorHandler;
-
-void
-ErrorReporter::setErrorHandlerShutdownType(NdbShutdownType nst)
-{
- s_errorHandlerShutdownType = nst;
-}
-
-void childReportError(int error);
-
-void
-ErrorReporter::handleAssert(const char* message, const char* file, int line, int ec)
-{
- char refMessage[100];
-
-#ifdef NO_EMULATED_JAM
- BaseString::snprintf(refMessage, 100, "file: %s lineNo: %d",
- file, line);
-#else
- const Uint32 blockNumber = theEmulatedJamBlockNumber;
- const char *blockName = getBlockName(blockNumber);
-
- BaseString::snprintf(refMessage, 100, "%s line: %d (block: %s)",
- file, line, blockName);
-#endif
- WriteMessage(ec, message, refMessage,
- theEmulatedJamIndex, theEmulatedJam);
-
- childReportError(ec);
-
- NdbShutdown(s_errorHandlerShutdownType);
- exit(1); // Deadcode
-}
-
-void
-ErrorReporter::handleError(int messageID,
- const char* problemData,
- const char* objRef,
- NdbShutdownType nst)
-{
- WriteMessage(messageID, problemData,
- objRef, theEmulatedJamIndex, theEmulatedJam);
-
- g_eventLogger.info(problemData);
- g_eventLogger.info(objRef);
-
- childReportError(messageID);
-
- if(messageID == NDBD_EXIT_ERROR_INSERT){
- NdbShutdown(NST_ErrorInsert);
- } else {
- if (nst == NST_ErrorHandler)
- nst = s_errorHandlerShutdownType;
- NdbShutdown(nst);
- }
-}
-
-int
-WriteMessage(int thrdMessageID,
- const char* thrdProblemData, const char* thrdObjRef,
- Uint32 thrdTheEmulatedJamIndex,
- Uint8 thrdTheEmulatedJam[]){
- FILE *stream;
- unsigned offset;
- unsigned long maxOffset; // Maximum size of file.
- char theMessage[MESSAGE_LENGTH];
-
- /**
- * Format trace file name
- */
- char *theTraceFileName= 0;
- if (globalData.ownId > 0)
- theTraceFileName= NdbConfig_TraceFileName(globalData.ownId,
- ErrorReporter::get_trace_no());
- NdbAutoPtr<char> tmp_aptr1(theTraceFileName);
-
- // The first 69 bytes is info about the current offset
- Uint32 noMsg = globalEmulatorData.theConfiguration->maxNoOfErrorLogs();
-
- maxOffset = (69 + (noMsg * MESSAGE_LENGTH));
-
- char *theErrorFileName= (char *)NdbConfig_ErrorFileName(globalData.ownId);
- NdbAutoPtr<char> tmp_aptr2(theErrorFileName);
-
- stream = fopen(theErrorFileName, "r+");
- if (stream == NULL) { /* If the file could not be opened. */
-
- // Create a new file, and skip the first 69 bytes,
- // which are info about the current offset
- stream = fopen(theErrorFileName, "w");
- if(stream == NULL)
- {
- fprintf(stderr,"Unable to open error log file: %s\n", theErrorFileName);
- return -1;
- }
- fprintf(stream, "%s%u%s", "Current byte-offset of file-pointer is: ", 69,
- " \n\n\n");
-
- // ...and write the error-message...
- ErrorReporter::formatMessage(thrdMessageID,
- thrdProblemData, thrdObjRef,
- theTraceFileName, theMessage);
- fprintf(stream, "%s", theMessage);
- fflush(stream);
-
- /* ...and finally, at the beginning of the file,
- store the position where to
- start writing the next message. */
- offset = ftell(stream);
- // If we have not reached the maximum number of messages...
- if (offset <= (maxOffset - MESSAGE_LENGTH)){
- fseek(stream, 40, SEEK_SET);
- // ...set the current offset...
- fprintf(stream,"%d", offset);
- } else {
- fseek(stream, 40, SEEK_SET);
- // ...otherwise, start over from the beginning.
- fprintf(stream, "%u%s", 69, " ");
- }
- } else {
- // Go to the latest position in the file...
- fseek(stream, 40, SEEK_SET);
- fscanf(stream, "%u", &offset);
- fseek(stream, offset, SEEK_SET);
-
- // ...and write the error-message there...
- ErrorReporter::formatMessage(thrdMessageID,
- thrdProblemData, thrdObjRef,
- theTraceFileName, theMessage);
- fprintf(stream, "%s", theMessage);
- fflush(stream);
-
- /* ...and finally, at the beginning of the file,
- store the position where to
- start writing the next message. */
- offset = ftell(stream);
-
- // If we have not reached the maximum number of messages...
- if (offset <= (maxOffset - MESSAGE_LENGTH)){
- fseek(stream, 40, SEEK_SET);
- // ...set the current offset...
- fprintf(stream,"%d", offset);
- } else {
- fseek(stream, 40, SEEK_SET);
- // ...otherwise, start over from the beginning.
- fprintf(stream, "%u%s", 69, " ");
- }
- }
- fflush(stream);
- fclose(stream);
-
- if (theTraceFileName) {
- // Open the tracefile...
- FILE *jamStream = fopen(theTraceFileName, "w");
-
- // ...and "dump the jam" there.
- // ErrorReporter::dumpJam(jamStream);
- if(thrdTheEmulatedJam != 0){
- dumpJam(jamStream, thrdTheEmulatedJamIndex, thrdTheEmulatedJam);
- }
-
- /* Dont print the jobBuffers until a way to copy them,
- like the other variables,
- is implemented. Otherwise when NDB keeps running,
- with this function running
- in the background, the jobBuffers will change during runtime. And when
- they're printed here, they will not be correct anymore.
- */
- globalScheduler.dumpSignalMemory(jamStream);
-
- fclose(jamStream);
- }
-
- return 0;
-}
-
-void
-dumpJam(FILE *jamStream,
- Uint32 thrdTheEmulatedJamIndex,
- Uint8 thrdTheEmulatedJam[]) {
-#ifndef NO_EMULATED_JAM
- // print header
- const int maxaddr = 8;
- fprintf(jamStream, "JAM CONTENTS up->down left->right ?=not block entry\n");
- fprintf(jamStream, "%-7s ", "BLOCK");
- for (int i = 0; i < maxaddr; i++)
- fprintf(jamStream, "%-6s ", "ADDR");
- fprintf(jamStream, "\n");
-
- // treat as array of Uint32
- const Uint32 *base = (Uint32 *)thrdTheEmulatedJam;
- const int first = thrdTheEmulatedJamIndex / sizeof(Uint32); // oldest
- int cnt, idx;
-
- // look for first block entry
- for (cnt = 0, idx = first; cnt < EMULATED_JAM_SIZE; cnt++, idx++) {
- if (idx >= EMULATED_JAM_SIZE)
- idx = 0;
- const Uint32 aJamEntry = base[idx];
- if (aJamEntry > (1 << 20))
- break;
- }
-
- // 1. if first entry is a block entry, it is printed in the main loop
- // 2. else if any block entry exists, the jam starts in an unknown block
- // 3. else if no block entry exists, the block is theEmulatedJamBlockNumber
- // a "?" indicates first addr is not a block entry
- if (cnt == 0)
- ;
- else if (cnt < EMULATED_JAM_SIZE)
- fprintf(jamStream, "%-7s?", "");
- else {
- const Uint32 aBlockNumber = theEmulatedJamBlockNumber;
- const char *aBlockName = getBlockName(aBlockNumber);
- if (aBlockName != 0)
- fprintf(jamStream, "%-7s?", aBlockName);
- else
- fprintf(jamStream, "0x%-5X?", aBlockNumber);
- }
-
- // loop over all entries
- int cntaddr = 0;
- for (cnt = 0, idx = first; cnt < EMULATED_JAM_SIZE; cnt++, idx++) {
- globalData.incrementWatchDogCounter(4); // watchdog not to kill us ?
- if (idx >= EMULATED_JAM_SIZE)
- idx = 0;
- const Uint32 aJamEntry = base[idx];
- if (aJamEntry > (1 << 20)) {
- const Uint32 aBlockNumber = aJamEntry >> 20;
- const char *aBlockName = getBlockName(aBlockNumber);
- if (cnt > 0)
- fprintf(jamStream, "\n");
- if (aBlockName != 0)
- fprintf(jamStream, "%-7s ", aBlockName);
- else
- fprintf(jamStream, "0x%-5X ", aBlockNumber);
- cntaddr = 0;
- }
- if (cntaddr == maxaddr) {
- fprintf(jamStream, "\n%-7s ", "");
- cntaddr = 0;
- }
- fprintf(jamStream, "%06u ", aJamEntry & 0xFFFFF);
- cntaddr++;
- }
- fprintf(jamStream, "\n");
- fflush(jamStream);
-#endif // ifndef NO_EMULATED_JAM
-}
diff --git a/storage/ndb/src/kernel/error/ErrorReporter.hpp b/storage/ndb/src/kernel/error/ErrorReporter.hpp
deleted file mode 100644
index 8d61948fe49..00000000000
--- a/storage/ndb/src/kernel/error/ErrorReporter.hpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef ERRORREPORTER_H
-#define ERRORREPORTER_H
-
-#include <ndb_global.h>
-#include <ndbd_exit_codes.h>
-
-#include "TimeModule.hpp"
-#include <Emulator.hpp>
-
-class ErrorReporter
-{
-public:
- static void setErrorHandlerShutdownType(NdbShutdownType nst = NST_ErrorHandler);
- static void handleAssert(const char* message,
- const char* file,
- int line, int ec = NDBD_EXIT_PRGERR) __attribute__((__noreturn__));
-
- static void handleError(int faultID,
- const char* problemData,
- const char* objRef,
- enum NdbShutdownType = NST_ErrorHandler);
-
- static void handleWarning(int faultID,
- const char* problemData,
- const char* objRef);
-
- static void formatMessage(int faultID,
- const char* problemData,
- const char* objRef,
- const char* theNameOfTheTraceFile,
- char* messptr);
-
- static int get_trace_no();
-
- static const char* formatTimeStampString();
-
-private:
- static enum NdbShutdownType s_errorHandlerShutdownType;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/error/Makefile.am b/storage/ndb/src/kernel/error/Makefile.am
deleted file mode 100644
index 5f904cdac61..00000000000
--- a/storage/ndb/src/kernel/error/Makefile.am
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2004-2005 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-noinst_LIBRARIES = liberror.a
-
-liberror_a_SOURCES = TimeModule.cpp \
- ErrorReporter.cpp \
- ndbd_exit_codes.c
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
-
-windoze-dsp: liberror.dsp
-
-liberror.dsp: Makefile \
- $(top_srcdir)/storage/ndb/config/win-lib.am \
- $(top_srcdir)/storage/ndb/config/win-name \
- $(top_srcdir)/storage/ndb/config/win-includes \
- $(top_srcdir)/storage/ndb/config/win-sources \
- $(top_srcdir)/storage/ndb/config/win-libraries
- cat $(top_srcdir)/storage/ndb/config/win-lib.am > $@
- @$(top_srcdir)/storage/ndb/config/win-name $@ $(noinst_LIBRARIES)
- @$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES)
- @$(top_srcdir)/storage/ndb/config/win-sources $@ $(liberror_a_SOURCES)
- @$(top_srcdir)/storage/ndb/config/win-libraries $@ LIB $(LDADD)
diff --git a/storage/ndb/src/kernel/error/TimeModule.cpp b/storage/ndb/src/kernel/error/TimeModule.cpp
deleted file mode 100644
index 2fabae586aa..00000000000
--- a/storage/ndb/src/kernel/error/TimeModule.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-
-#include <ndb_global.h>
-#include "TimeModule.hpp"
-
-static const char* cMonth[] = { "x", "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"};
-
-static const char* cDay[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
- "Saturday", "Sunday"};
-
-static const char* cHour[] = { "00","01","02","03","04","05","06","07","08","09","10","11","12",
- "13","14","15","16","17","18","19","20","21","22","23"};
-
-static const char* cMinute[] = { "00","01","02","03","04","05","06","07","08","09","10","11","12",
- "13","14","15","16","17","18","19","20","21","22","23","24","25",
- "26","27","28","29","30","31","32","33","34","35","36","37","38",
- "39","40","41","42","43","44","45","46","47","48","49","50","51",
- "52","53","54","55","56","57","58","59"};
-
-static const char* cSecond[] = { "00","01","02","03","04","05","06","07","08","09","10","11","12",
- "13","14","15","16","17","18","19","20","21","22","23","24","25",
- "26","27","28","29","30","31","32","33","34","35","36","37","38",
- "39","40","41","42","43","44","45","46","47","48","49","50","51",
- "52","53","54","55","56","57","58","59"};
-
-
-TimeModule::TimeModule(){
-}
-
-TimeModule::~TimeModule(){
-}
-
-void
-TimeModule::setTimeStamp()
-{
- struct tm* rightnow;
- time_t now;
-
- time(&now);
-
- rightnow = localtime(&now);
-
- iYear = rightnow->tm_year+1900; // localtime returns current year -1900
- iMonth = rightnow->tm_mon+1; // and month 0-11
- iMonthDay = rightnow->tm_mday;
- iWeekDay = rightnow->tm_wday;
- iHour = rightnow->tm_hour;
- iMinute = rightnow->tm_min;
- iSecond = rightnow->tm_sec;
-}
-
-int
-TimeModule::getYear() const
-{
- return iYear;
-}
-
-int
-TimeModule::getMonthNumber() const
-{
- return iMonth;
-}
-
-const char*
-TimeModule::getMonthName() const {
- return cMonth[iMonth];
-}
-
-int
-TimeModule::getDayOfMonth() const {
- return iMonthDay;
-}
-
-const char*
-TimeModule::getDayName() const {
- return cDay[iWeekDay];
-}
-
-const char*
-TimeModule::getHour() const {
- return cHour[iHour];
-}
-
-const char*
-TimeModule::getMinute() const {
- return cMinute[iMinute];
-}
-
-const char*
-TimeModule::getSecond() const {
- return cSecond[iSecond];
-}
diff --git a/storage/ndb/src/kernel/error/TimeModule.hpp b/storage/ndb/src/kernel/error/TimeModule.hpp
deleted file mode 100644
index 8ea21750865..00000000000
--- a/storage/ndb/src/kernel/error/TimeModule.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef _TimeModule_
-#define _TimeModule_
-
-class TimeModule {
-public:
- TimeModule();
- ~TimeModule();
-
- void setTimeStamp();
-
- int getYear() const;
- int getMonthNumber() const;
- int getDayOfMonth() const;
- const char* getMonthName() const;
- const char* getDayName() const;
- const char* getHour() const;
- const char* getMinute() const;
- const char* getSecond() const;
-
-private:
- int iYear;
- int iMonth;
- int iMonthDay;
- int iWeekDay;
- int iHour;
- int iMinute;
- int iSecond;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/error/ndbd_exit_codes.c b/storage/ndb/src/kernel/error/ndbd_exit_codes.c
deleted file mode 100644
index 4224e7191f6..00000000000
--- a/storage/ndb/src/kernel/error/ndbd_exit_codes.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/* Copyright (c) 2003, 2005-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#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_GENERIC, XRE, "Generic error"},
- {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_NODE_DECLARED_DEAD, XAE,
- "Node declared dead. See error log for details"},
- {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"},
- {NDBD_EXIT_SR_SCHEMAFILE, XFI, "Error while reading the schema file"},
- /* 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_SINGLE_USER_MODE, XRE, "Data node is not allowed to get added "
- "to the cluster while it is in single user mode"},
- {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"},
-
- {NDBD_EXIT_RESOURCE_ALLOC_ERROR, XCE,
- "Resource allocation error, please review the configuration"},
-
- /* 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"},
-
- {NDBD_EXIT_INVALID_LCP_FILE, XFI, "Invalid LCP" },
- {NDBD_EXIT_INSUFFICENT_NODES, XRE, "Insufficent nodes for system restart" },
-
- /* 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' && cl != XUE)
- {
- 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/storage/ndb/src/kernel/main.cpp b/storage/ndb/src/kernel/main.cpp
deleted file mode 100644
index a9660a6ff86..00000000000
--- a/storage/ndb/src/kernel/main.cpp
+++ /dev/null
@@ -1,653 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include <my_pthread.h>
-
-#include <ndb_version.h>
-#include "Configuration.hpp"
-#include <ConfigRetriever.hpp>
-#include <TransporterRegistry.hpp>
-
-#include "vm/SimBlockList.hpp"
-#include "ThreadConfig.hpp"
-#include <SignalLoggerManager.hpp>
-#include <NdbOut.hpp>
-#include <NdbMain.h>
-#include <NdbDaemon.h>
-#include <NdbSleep.h>
-#include <NdbConfig.h>
-#include <WatchDog.hpp>
-
-#include <LogLevel.hpp>
-#include <EventLogger.hpp>
-
-#include <NdbAutoPtr.hpp>
-
-#include <Properties.hpp>
-
-#include <mgmapi_debug.h>
-
-#if defined NDB_SOLARIS // ok
-#include <sys/processor.h> // For system informatio
-#endif
-
-extern EventLogger g_eventLogger;
-extern NdbMutex * theShutdownMutex;
-
-void catchsigs(bool ignore); // for process signal handling
-
-#define MAX_FAILED_STARTUPS 3
-// Flag set by child through SIGUSR1 to signal a failed startup
-static bool failed_startup_flag = false;
-// Counter for consecutive failed startups
-static Uint32 failed_startups = 0;
-extern "C" void handler_shutdown(int signum); // for process signal handling
-extern "C" void handler_error(int signum); // for process signal handling
-extern "C" void handler_sigusr1(int signum); // child signalling failed restart
-
-// Shows system information
-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
- Configuration* theConfig = globalEmulatorData.theConfiguration;
- if(!theConfig->init(argc, argv)){
- return NRT_Default;
- }
-
- { // Do configuration
-#ifndef NDB_WIN32
- signal(SIGPIPE, SIG_IGN);
-#endif
- theConfig->fetch_configuration();
- }
-
- my_setwd(NdbConfig_get_path(0), MYF(0));
-
- if (theConfig->getDaemonMode()) {
- // Become a daemon
- char *lockfile= NdbConfig_PidFileName(globalData.ownId);
- char *logfile= NdbConfig_StdoutFileName(globalData.ownId);
- NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
-
- if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
- ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
- return 1;
- }
- }
-
-#ifndef NDB_WIN32
- signal(SIGUSR1, handler_sigusr1);
-
- 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);
-
- /**
- * 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:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_NoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = initial_state;
- break;
- case NRT_DoStart_InitialStart:
- theConfig->setInitialStart(true);
- globalData.theRestartFlag = perform_start;
- break;
- default:
- error_exit = 1;
- if(theConfig->stopOnError()){
- /**
- * Error shutdown && stopOnError()
- */
- reportShutdown(theConfig, error_exit, 0);
- exit(0);
- }
- // Fall-through
- case NRT_DoStart_Restart:
- theConfig->setInitialStart(false);
- globalData.theRestartFlag = perform_start;
- break;
- }
- } 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
- failed_startups = 0;
- }
- else if (failed_startups >= MAX_FAILED_STARTUPS && !theConfig->stopOnError())
- {
- /**
- * Error shutdown && stopOnError()
- */
- 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();
- }
-
- 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
- theConfig->setupConfiguration();
- systemInfo(* theConfig, * theConfig->m_logLevel);
-
- // Load blocks
- globalEmulatorData.theSimBlockList->load(globalEmulatorData);
-
- // Set thread concurrency for Solaris' light weight processes
- int status;
- status = NdbThread_SetConcurrencyLevel(30);
- assert(status == 0);
-
-#ifdef VM_TRACE
- // Create a signal logger
- char *buf= NdbConfig_SignalLogFileName(globalData.ownId);
- NdbAutoPtr<char> tmp_aptr(buf);
- 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);
-
- /**
- * Do startup
- */
-
- ErrorReporter::setErrorHandlerShutdownType(NST_ErrorHandlerStartup);
-
- switch(globalData.theRestartFlag){
- case initial_state:
- globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
- break;
- case perform_start:
- globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
- globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING);
- break;
- default:
- assert("Illegal state globalData.theRestartFlag" == 0);
- }
-
- globalTransporterRegistry.startSending();
- globalTransporterRegistry.startReceiving();
- if (!globalTransporterRegistry.start_service(*globalEmulatorData.m_socket_server)){
- ndbout_c("globalTransporterRegistry.start_service() failed");
- 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);
- }
-
- globalEmulatorData.theWatchDog->doStart();
-
- globalEmulatorData.m_socket_server->startServer();
-
- // theConfig->closeConfiguration();
-
- globalEmulatorData.theThreadConfig->ipControlLoop();
-
- NdbShutdown(NST_Normal);
-
- return NRT_Default;
-}
-
-
-void
-systemInfo(const Configuration & config, const LogLevel & logLevel){
-#ifdef NDB_WIN32
- int processors = 0;
- int speed;
- SYSTEM_INFO sinfo;
- GetSystemInfo(&sinfo);
- processors = sinfo.dwNumberOfProcessors;
- HKEY hKey;
- if(ERROR_SUCCESS==RegOpenKeyEx
- (HKEY_LOCAL_MACHINE,
- TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
- 0, KEY_READ, &hKey)) {
- DWORD dwMHz;
- DWORD cbData = sizeof(dwMHz);
- if(ERROR_SUCCESS==RegQueryValueEx(hKey,
- "~MHz", 0, 0, (LPBYTE)&dwMHz, &cbData)) {
- speed = int(dwMHz);
- }
- RegCloseKey(hKey);
- }
-#elif defined NDB_SOLARIS // ok
- // Search for at max 16 processors among the first 256 processor ids
- processor_info_t pinfo; memset(&pinfo, 0, sizeof(pinfo));
- int pid = 0;
- while(processors < 16 && pid < 256){
- if(!processor_info(pid++, &pinfo))
- processors++;
- }
- speed = pinfo.pi_clock;
-#endif
-
- if(logLevel.getLogLevel(LogLevel::llStartUp) > 0){
- g_eventLogger.info("NDB Cluster -- DB node %d", globalData.ownId);
- g_eventLogger.info("%s --", NDB_VERSION_STRING);
- if (config.get_mgmd_host())
- g_eventLogger.info("Configuration fetched at %s port %d",
- config.get_mgmd_host(), config.get_mgmd_port());
-#ifdef NDB_SOLARIS // ok
- g_eventLogger.info("NDB is running on a machine with %d processor(s) at %d MHz",
- processor, speed);
-#endif
- }
- if(logLevel.getLogLevel(LogLevel::llStartUp) > 3){
- Uint32 t = config.timeBetweenWatchDogCheck();
- g_eventLogger.info("WatchDog timer is set to %d ms", t);
- }
-
-}
-
-#define handler_register(signum, handler, ignore)\
-{\
- if (ignore) {\
- if(signum != SIGCHLD)\
- signal(signum, SIG_IGN);\
- } else\
- signal(signum, handler);\
-}
-
-void
-catchsigs(bool ignore){
-#if !defined NDB_WIN32
-
- static const int signals_shutdown[] = {
-#ifdef SIGBREAK
- SIGBREAK,
-#endif
- SIGHUP,
- SIGINT,
-#if defined SIGPWR
- SIGPWR,
-#elif defined SIGINFO
- SIGINFO,
-#endif
- SIGQUIT,
- SIGTERM,
-#ifdef SIGTSTP
- SIGTSTP,
-#endif
- SIGTTIN,
- SIGTTOU
- };
-
- static const int signals_error[] = {
- SIGABRT,
- SIGALRM,
-#ifdef SIGBUS
- SIGBUS,
-#endif
- SIGCHLD,
- SIGFPE,
- SIGILL,
-#ifdef SIGIO
- SIGIO,
-#endif
-#ifdef SIGPOLL
- SIGPOLL,
-#endif
- SIGSEGV
- };
-
- static const int signals_ignore[] = {
- SIGPIPE
- };
-
- size_t i;
- for(i = 0; i < sizeof(signals_shutdown)/sizeof(signals_shutdown[0]); i++)
- handler_register(signals_shutdown[i], handler_shutdown, ignore);
- for(i = 0; i < sizeof(signals_error)/sizeof(signals_error[0]); i++)
- handler_register(signals_error[i], handler_error, ignore);
- for(i = 0; i < sizeof(signals_ignore)/sizeof(signals_ignore[0]); i++)
- handler_register(signals_ignore[i], SIG_IGN, ignore);
-#ifdef SIGTRAP
- Configuration* theConfig = globalEmulatorData.theConfiguration;
- if (! theConfig->getForegroundMode())
- handler_register(SIGTRAP, handler_error, ignore);
-#endif
-#endif
-}
-
-extern "C"
-void
-handler_shutdown(int signum){
- g_eventLogger.info("Received signal %d. Performing stop.", signum);
- childReportError(0);
- childReportSignal(signum);
- globalData.theRestartFlag = perform_stop;
-}
-
-extern "C"
-void
-handler_error(int signum){
- // only let one thread run shutdown
- static long thread_id= 0;
-
- if (thread_id != 0 && thread_id == my_thread_id())
- {
- // Shutdown thread received signal
-#ifndef NDB_WIN32
- signal(signum, SIG_DFL);
- kill(getpid(), signum);
-#endif
- while(true)
- NdbSleep_MilliSleep(10);
- }
- if(theShutdownMutex && NdbMutex_Trylock(theShutdownMutex) != 0)
- while(true)
- 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[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"
-void
-handler_sigusr1(int signum)
-{
- if (!failed_startup_flag)
- {
- failed_startups++;
- failed_startup_flag = true;
- }
- g_eventLogger.info("Angel received ndbd startup failure count %u.", failed_startups);
-}
diff --git a/storage/ndb/src/kernel/vm/Array.hpp b/storage/ndb/src/kernel/vm/Array.hpp
deleted file mode 100644
index 7d9f955c296..00000000000
--- a/storage/ndb/src/kernel/vm/Array.hpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef ARRAY_HPP
-#define ARRAY_HPP
-
-#include "ArrayPool.hpp"
-
-#include <pc.hpp>
-#include <ErrorReporter.hpp>
-
-/**
- * Template class used for implementing an
- * array of object retreived from a pool
- */
-template <class T>
-class Array {
-public:
- Array(ArrayPool<T> & thePool);
-
- /**
- * Allocate an <b>n</b> objects from pool
- * These can now be addressed with 0 <= ptr.i < n
- */
- bool seize(Uint32 i);
-
- /**
- * Release all object from array
- */
- void release();
-
- /**
- * Return current size of array
- */
- Uint32 getSize() const;
-
- /**
- * empty
- */
- inline bool empty() const { return sz == 0;}
-
- /**
- * Update i & p value according to <b>i</b>
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &) const ;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i) const;
-
-private:
- Uint32 base, sz;
- ArrayPool<T> & thePool;
-};
-
-template<class T>
-inline
-Array<T>::Array(ArrayPool<T> & _pool)
- : thePool(_pool)
-{
- sz = 0;
- base = RNIL;
-}
-
-template<class T>
-inline
-bool
-Array<T>::seize(Uint32 n){
- if(base == RNIL && n > 0){
- base = thePool.seizeN(n);
- if(base != RNIL){
- sz = n;
- return true;
- }
- return false;
- }
- ErrorReporter::handleAssert("Array<T>::seize failed", __FILE__, __LINE__);
- return false;
-}
-
-template<class T>
-inline
-void
-Array<T>::release(){
- if(base != RNIL){
- thePool.releaseN(base, sz);
- sz = 0;
- base = RNIL;
- return;
- }
-}
-
-template<class T>
-inline
-Uint32
-Array<T>::getSize() const {
- return sz;
-}
-
-template <class T>
-inline
-void
-Array<T>::getPtr(Ptr<T> & p, Uint32 i) const {
- p.i = i;
-#ifdef ARRAY_GUARD
- if(i < sz && base != RNIL){
- p.p = thePool.getPtr(i + base);
- return;
- } else {
- ErrorReporter::handleAssert("Array::getPtr failed", __FILE__, __LINE__);
- }
-#endif
- p.p = thePool.getPtr(i + base);
-}
-
-template<class T>
-inline
-void
-Array<T>::getPtr(Ptr<T> & ptr) const {
-#ifdef ARRAY_GUARD
- if(ptr.i < sz && base != RNIL){
- ptr.p = thePool.getPtr(ptr.i + base);
- return;
- } else {
- ErrorReporter::handleAssert("Array<T>::getPtr failed", __FILE__, __LINE__);
- }
-#endif
- ptr.p = thePool.getPtr(ptr.i + base);
-}
-
-template<class T>
-inline
-T *
-Array<T>::getPtr(Uint32 i) const {
-#ifdef ARRAY_GUARD
- if(i < sz && base != RNIL){
- return thePool.getPtr(i + base);
- } else {
- ErrorReporter::handleAssert("Array<T>::getPtr failed", __FILE__, __LINE__);
- }
-#endif
- return thePool.getPtr(i + base);
-}
-
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/ArrayPool.hpp b/storage/ndb/src/kernel/vm/ArrayPool.hpp
deleted file mode 100644
index dbc6319a583..00000000000
--- a/storage/ndb/src/kernel/vm/ArrayPool.hpp
+++ /dev/null
@@ -1,985 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef ARRAY_POOL_HPP
-#define ARRAY_POOL_HPP
-
-#include <ndb_global.h>
-#include "ndbd_malloc.hpp"
-
-#include <pc.hpp>
-#include "Pool.hpp"
-#include <ErrorReporter.hpp>
-#include <NdbMem.h>
-#include <Bitmask.hpp>
-#include <mgmapi.h>
-
-template <class T> class Array;
-
-/**
- * Template class used for implementing an
- * pool of object (in an array with a free list)
- */
-template <class T>
-class ArrayPool {
-public:
- ArrayPool();
- ~ArrayPool();
-
- /**
- * Set the size of the pool
- *
- * Note, can currently only be called once
- */
- bool setSize(Uint32 noOfElements, bool align = false, bool exit_on_error = true,
- bool guard = true, Uint32 paramId = 0);
- bool set(T*, Uint32 cnt, bool align = false);
- void clear() { theArray = 0; }
-
- inline Uint32 getNoOfFree() const {
- return noOfFree;
- }
-
- inline Uint32 getSize() const {
- return size;
- }
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &);
- void getPtr(ConstPtr<T> &) const;
- void getPtr(Ptr<T> &, bool CrashOnBoundaryError);
- void getPtr(ConstPtr<T> &, bool CrashOnBoundaryError) const;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i);
- const T * getConstPtr(Uint32 i) const;
- T * getPtr(Uint32 i, bool CrashOnBoundaryError);
- const T * getConstPtr(Uint32 i, bool CrashOnBoundaryError) const;
-
- /**
- * Update p & i value for ptr according to <b>i</b> value
- */
- void getPtr(Ptr<T> &, Uint32 i);
- void getPtr(ConstPtr<T> &, Uint32 i) const;
- void getPtr(Ptr<T> &, Uint32 i, bool CrashOnBoundaryError);
- void getPtr(ConstPtr<T> &, Uint32 i, bool CrashOnBoundaryError) const;
-
- /**
- * Allocate an object from pool - update Ptr
- *
- * Return i
- */
- bool seize(Ptr<T> &);
-
- /**
- * Allocate object <b>i</b> from pool - update Ptr
- */
- bool seizeId(Ptr<T> &, Uint32 i);
-
- /**
- * Check if <b>i</b> is allocated.
- */
- bool findId(Uint32 i) const;
-
- /**
- * Return an object to pool
- */
- void release(Uint32 i);
-
- /**
- * Return an object to pool
- */
- void release(Ptr<T> &);
-
-#ifdef ARRAY_GUARD
- /**
- * Checks if i is a correct seized record
- *
- * @note Since this is either an expensive method,
- * or needs bitmask stuff, this method is only
- * recommended for debugging.
- *
- */
- bool isSeized(Uint32 i) const {
- if (i>=size) return false;
- return BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i);
- }
-#endif
-
-protected:
- friend class Array<T>;
-
- /**
- * Allocate <b>n</b> consecutive object from pool
- * return base
- */
- Uint32 seizeN(Uint32 n);
-
- /**
- * Deallocate <b>n<b> consecutive object to pool
- * starting from base
- */
- void releaseN(Uint32 base, Uint32 n);
-
-public:
- /**
- * Release a singel linked list in o(1)
- * @param first i-value of first element in list
- * @param last i-value of last element in list
- * @note nextPool must be used as next pointer in list
- */
- void releaseList(Uint32 n, Uint32 first, Uint32 last);
- //private:
-
-#ifdef DEBUG
- Uint32 getNoOfFree2() const {
- Uint32 c2 = size;
- for(Uint32 i = 0; i<((size + 31)>> 5); i++){
- Uint32 w = theAllocatedBitmask[i];
- for(Uint32 j = 0; j<32; j++){
- if((w & 1) == 1){
- c2--;
- }
- w >>= 1;
- }
- }
- return c2;
- }
-
- Uint32 getNoOfFree3() const {
- Uint32 c = 0;
- Ptr<T> p;
- p.i = firstFree;
- while(p.i != RNIL){
- c++;
- p.p = &theArray[p.i];
- p.i = p.p->next;
- }
- return c;
- }
-#endif
-
-protected:
- Uint32 firstFree;
- Uint32 size;
- Uint32 noOfFree;
- T * theArray;
- void * alloc_ptr;
- Uint32 bitmaskSz;
- Uint32 *theAllocatedBitmask;
-};
-
-template <class T>
-inline
-ArrayPool<T>::ArrayPool(){
- firstFree = RNIL;
- size = 0;
- noOfFree = 0;
- theArray = 0;
- alloc_ptr = 0;
-#ifdef ARRAY_GUARD
- theAllocatedBitmask = 0;
-#endif
-}
-
-template <class T>
-inline
-ArrayPool<T>::~ArrayPool(){
- if(theArray != 0){
- ndbd_free(alloc_ptr, size * sizeof(T));
- theArray = 0;
- alloc_ptr = 0;
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- delete []theAllocatedBitmask;
- theAllocatedBitmask = 0;
-#endif
- }
-}
-
-/**
- * Set the size of the pool
- *
- * Note, can currently only be called once
- */
-template <class T>
-inline
-bool
-ArrayPool<T>::setSize(Uint32 noOfElements,
- bool align, bool exit_on_error, bool guard, Uint32 paramId){
- if(size == 0){
- if(noOfElements == 0)
- return true;
- Uint64 real_size = (Uint64)noOfElements * sizeof(T);
- size_t req_size = (size_t)real_size;
- Uint64 real_size_align = real_size + sizeof(T);
- size_t req_size_align = (size_t)real_size_align;
-
- if(align)
- {
- if((Uint64)req_size_align == real_size_align && req_size_align > 0)
- alloc_ptr = ndbd_malloc(req_size_align);
- UintPtr p = (UintPtr)alloc_ptr;
- UintPtr mod = p % sizeof(T);
- if (mod)
- {
- p += sizeof(T) - mod;
- }
- theArray = (T *)p;
- }
- else if((Uint64)req_size == real_size && req_size > 0)
- theArray = (T *)(alloc_ptr = ndbd_malloc(req_size));
-
- if(theArray == 0)
- {
- char errmsg[255] = "ArrayPool<T>::setSize malloc failed";
- struct ndb_mgm_param_info param_info;
- size_t size = sizeof(ndb_mgm_param_info);
- if (!exit_on_error)
- return false;
-
- if(0 != paramId && 0 == ndb_mgm_get_db_parameter_info(paramId, &param_info, &size)) {
- BaseString::snprintf(errmsg, sizeof(errmsg),
- "Malloc memory for %s failed", param_info.m_name);
- }
-
- ErrorReporter::handleAssert(errmsg,
- __FILE__, __LINE__, NDBD_EXIT_MEMALLOC);
- return false; // not reached
- }
- size = noOfElements;
- noOfFree = noOfElements;
-
- /**
- * Set next pointers
- */
- T * t = &theArray[0];
- for(Uint32 i = 0; i<size; i++){
- t->nextPool = (i + 1);
- t++;
- }
- theArray[size-1].nextPool = RNIL;
- firstFree = 0;
-
-#ifdef ARRAY_GUARD
- if (guard)
- {
- bitmaskSz = (noOfElements + 31) >> 5;
- theAllocatedBitmask = new Uint32[bitmaskSz];
- BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask);
- }
-#endif
-
- return true;
- }
- if (!exit_on_error)
- return false;
-
- ErrorReporter::handleAssert("ArrayPool<T>::setSize called twice", __FILE__, __LINE__);
- return false; // not reached
-}
-
-template <class T>
-inline
-bool
-ArrayPool<T>::set(T* ptr, Uint32 cnt, bool align){
- if (size == 0)
- {
- alloc_ptr = ptr;
- if(align)
- {
- UintPtr p = (UintPtr)alloc_ptr;
- UintPtr mod = p % sizeof(T);
- if (mod)
- {
- p += sizeof(T) - mod;
- cnt --;
- }
- theArray = (T *)p;
- }
- else
- {
- theArray = (T *)alloc_ptr;
- }
-
- size = cnt;
- noOfFree = 0;
- return true;
- }
- ErrorReporter::handleAssert("ArrayPool<T>::set called twice",
- __FILE__, __LINE__);
- return false; // not reached
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(Ptr<T> & ptr){
- Uint32 i = ptr.i;
- if(likely (i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(ConstPtr<T> & ptr) const {
- Uint32 i = ptr.i;
- if(likely(i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i){
- ptr.i = i;
- if(likely(i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i) const {
- ptr.i = i;
- if(likely(i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-T *
-ArrayPool<T>::getPtr(Uint32 i){
- if(likely(i < size)){
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return &theArray[i];
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- return 0;
- }
-#endif
- return &theArray[i];
- } else {
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- return 0;
- }
-}
-
-template <class T>
-inline
-const T *
-ArrayPool<T>::getConstPtr(Uint32 i) const {
- if(likely(i < size)){
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return &theArray[i];
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- return 0;
- }
-#endif
- return &theArray[i];
- } else {
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- return 0;
- }
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(Ptr<T> & ptr, bool CrashOnBoundaryError){
- Uint32 i = ptr.i;
- if(likely(i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ptr.i = RNIL;
- }
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(ConstPtr<T> & ptr, bool CrashOnBoundaryError) const {
- Uint32 i = ptr.i;
- if(likely(i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ptr.i = RNIL;
- }
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i, bool CrashOnBoundaryError){
- ptr.i = i;
- if(likely(i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ptr.i = RNIL;
- }
-}
-
-template <class T>
-inline
-void
-ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i,
- bool CrashOnBoundaryError) const {
- ptr.i = i;
- if(likely(i < size)){
- ptr.p = &theArray[i];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return;
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- }
-#endif
- } else {
- ptr.i = RNIL;
- }
-}
-
-template <class T>
-inline
-T *
-ArrayPool<T>::getPtr(Uint32 i, bool CrashOnBoundaryError){
- if(likely(i < size)){
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return &theArray[i];
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
- return 0;
- }
-#endif
- return &theArray[i];
- } else {
- return 0;
- }
-}
-
-template <class T>
-inline
-const T *
-ArrayPool<T>::getConstPtr(Uint32 i, bool CrashOnBoundaryError) const {
- if(likely(i < size)){
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
- return &theArray[i];
- /**
- * Getting a non-seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::getConstPtr", __FILE__,__LINE__);
- return 0;
- }
-#endif
- return &theArray[i];
- } else {
- return 0;
- }
-}
-
-/**
- * Allocate an object from pool - update Ptr
- *
- * Return i
- */
-template <class T>
-inline
-bool
-ArrayPool<T>::seize(Ptr<T> & ptr){
- Uint32 ff = firstFree;
- if(ff != RNIL){
- firstFree = theArray[ff].nextPool;
-
- ptr.i = ff;
- ptr.p = &theArray[ff];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){
- BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff);
- noOfFree--;
- return true;
- } else {
- /**
- * Seizing an already seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::seize", __FILE__, __LINE__);
- return false;
- }
- }
-#endif
- noOfFree--;
- return true;
- }
- ptr.i = RNIL;
- ptr.p = NULL;
- return false;
-}
-
-template <class T>
-inline
-bool
-ArrayPool<T>::seizeId(Ptr<T> & ptr, Uint32 i){
- Uint32 ff = firstFree;
- Uint32 prev = RNIL;
- while(ff != i && ff != RNIL){
- prev = ff;
- ff = theArray[ff].nextPool;
- }
-
- if(ff != RNIL){
- if(prev == RNIL)
- firstFree = theArray[ff].nextPool;
- else
- theArray[prev].nextPool = theArray[ff].nextPool;
-
- ptr.i = ff;
- ptr.p = &theArray[ff];
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){
- BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff);
- noOfFree--;
- return true;
- } else {
- /**
- * Seizing an already seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::seizeId", __FILE__, __LINE__);
- return false;
- }
- }
-#endif
- noOfFree--;
- return true;
- }
- ptr.i = RNIL;
- ptr.p = NULL;
- return false;
-}
-
-template <class T>
-inline
-bool
-ArrayPool<T>::findId(Uint32 i) const {
- if (i >= size)
- return false;
- Uint32 ff = firstFree;
- while(ff != i && ff != RNIL){
- ff = theArray[ff].nextPool;
- }
- return (ff == RNIL);
-}
-
-template<class T>
-Uint32
-ArrayPool<T>::seizeN(Uint32 n){
- Uint32 curr = firstFree;
- Uint32 prev = RNIL;
- Uint32 sz = 0;
- while(sz < n && curr != RNIL){
- if(theArray[curr].nextPool == (curr + 1)){
- sz++;
- } else {
- sz = 0;
- prev = curr;
- }
- curr = theArray[curr].nextPool;
- }
- if(sz != n){
- return RNIL;
- }
- const Uint32 base = curr - n;
- if(base == firstFree){
- firstFree = curr;
- } else {
- theArray[prev].nextPool = curr;
- }
-
- noOfFree -= n;
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- for(Uint32 j = base; j<curr; j++){
- if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, j)){
- BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, j);
- } else {
- /**
- * Seizing an already seized element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::seize", __FILE__, __LINE__);
- return RNIL;
- }
- }
- }
-#endif
- return base;
-}
-
-template<class T>
-inline
-void
-ArrayPool<T>::releaseN(Uint32 base, Uint32 n){
- Uint32 curr = firstFree;
- Uint32 prev = RNIL;
- while(curr < base){
- prev = curr;
- curr = theArray[curr].nextPool;
- }
- if(curr == firstFree){
- firstFree = base;
- } else {
- theArray[prev].nextPool = base;
- }
- const Uint32 end = base + n;
- for(Uint32 i = base; i<end; i++){
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
- BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
- } else {
- /**
- * Relesing a already released element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
- return;
- }
- }
-#endif
- theArray[i].nextPool = i + 1;
- }
- theArray[end-1].nextPool = curr;
- noOfFree += n;
-}
-
-template<class T>
-inline
-void
-ArrayPool<T>::releaseList(Uint32 n, Uint32 first, Uint32 last){
-
- if(first < size && last < size){
- Uint32 ff = firstFree;
- firstFree = first;
- theArray[last].nextPool = ff;
- noOfFree += n;
-
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- Uint32 tmp = first;
- for(Uint32 i = 0; i<n; i++){
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmp)){
- BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, tmp);
- } else {
- /**
- * Relesing a already released element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::releaseList",
- __FILE__, __LINE__);
- return;
- }
- tmp = theArray[tmp].nextPool;
- }
- }
-#endif
- return;
- }
- ErrorReporter::handleAssert("ArrayPool<T>::releaseList", __FILE__, __LINE__);
-}
-
-/**
- * Return an object to pool
- */
-template <class T>
-inline
-void
-ArrayPool<T>::release(Uint32 _i){
- const Uint32 i = _i;
- if(likely(i < size)){
- Uint32 ff = firstFree;
- theArray[i].nextPool = ff;
- firstFree = i;
-
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
- BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
- noOfFree++;
- return;
- }
- /**
- * Relesing a already released element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
- }
-#endif
- noOfFree++;
- return;
- }
- ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
-}
-
-/**
- * Return an object to pool
- */
-template <class T>
-inline
-void
-ArrayPool<T>::release(Ptr<T> & ptr){
- Uint32 i = ptr.i;
- if(likely(i < size)){
- Uint32 ff = firstFree;
- theArray[i].nextPool = ff;
- firstFree = i;
-
-#ifdef ARRAY_GUARD
- if (theAllocatedBitmask)
- {
- if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
- BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
- //assert(noOfFree() == noOfFree2());
- noOfFree++;
- return;
- }
- /**
- * Relesing a already released element
- */
- ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
- }
-#endif
- noOfFree++;
- return;
- }
- ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
-}
-
-template <class T>
-class UnsafeArrayPool : public ArrayPool<T> {
-public:
- /**
- * Update p value for ptr according to i value
- * ignore if it's allocated or not
- */
- void getPtrForce(Ptr<T> &);
- void getPtrForce(ConstPtr<T> &) const;
- T * getPtrForce(Uint32 i);
- const T * getConstPtrForce(Uint32 i) const;
- void getPtrForce(Ptr<T> &, Uint32 i);
- void getPtrForce(ConstPtr<T> &, Uint32 i) const;
-};
-
-template <class T>
-inline
-void
-UnsafeArrayPool<T>::getPtrForce(Ptr<T> & ptr){
- Uint32 i = ptr.i;
- if(likely(i < this->size)){
- ptr.p = &this->theArray[i];
- } else {
- ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
- __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-void
-UnsafeArrayPool<T>::getPtrForce(ConstPtr<T> & ptr) const{
- Uint32 i = ptr.i;
- if(likely(i < this->size)){
- ptr.p = &this->theArray[i];
- } else {
- ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
- __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-T *
-UnsafeArrayPool<T>::getPtrForce(Uint32 i){
- if(likely(i < this->size)){
- return &this->theArray[i];
- } else {
- ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
- __FILE__, __LINE__);
- return 0;
- }
-}
-
-template <class T>
-inline
-const T *
-UnsafeArrayPool<T>::getConstPtrForce(Uint32 i) const {
- if(likely(i < this->size)){
- return &this->theArray[i];
- } else {
- ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
- __FILE__, __LINE__);
- return 0;
- }
-}
-
-template <class T>
-inline
-void
-UnsafeArrayPool<T>::getPtrForce(Ptr<T> & ptr, Uint32 i){
- ptr.i = i;
- if(likely(i < this->size)){
- ptr.p = &this->theArray[i];
- return ;
- } else {
- ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
- __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-void
-UnsafeArrayPool<T>::getPtrForce(ConstPtr<T> & ptr, Uint32 i) const{
- ptr.i = i;
- if(likely(i < this->size)){
- ptr.p = &this->theArray[i];
- return ;
- } else {
- ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
- __FILE__, __LINE__);
- }
-}
-
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/CArray.hpp b/storage/ndb/src/kernel/vm/CArray.hpp
deleted file mode 100644
index 4ae1451756b..00000000000
--- a/storage/ndb/src/kernel/vm/CArray.hpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef CARRAY_HPP
-#define CARRAY_HPP
-
-#include "ndbd_malloc.hpp"
-
-/**
- * Template class used for implementing an c - array
- */
-template <class T>
-class CArray {
-public:
- CArray();
- ~CArray();
-
- /**
- * Set the size of the pool
- *
- * Note, can currently only be called once
- */
- bool setSize(Uint32 noOfElements, bool exit_on_error = true);
-
- /**
- * Get size
- */
- Uint32 getSize() const;
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &) const;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i) const;
-
- /**
- * Update p & i value for ptr according to <b>i</b> value
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
-private:
- Uint32 size;
- T * theArray;
-};
-
-template <class T>
-inline
-CArray<T>::CArray(){
- size = 0;
- theArray = 0;
-}
-
-template <class T>
-inline
-CArray<T>::~CArray(){
- if(theArray != 0){
- ndbd_free(theArray, size * sizeof(T));
- theArray = 0;
- }
-}
-
-/**
- * Set the size of the pool
- *
- * Note, can currently only be called once
- */
-template <class T>
-inline
-bool
-CArray<T>::setSize(Uint32 noOfElements, bool exit_on_error){
- if(size == noOfElements)
- return true;
-
- theArray = (T *)ndbd_malloc(noOfElements * sizeof(T));
- if(theArray == 0)
- {
- 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;
-}
-
-template<class T>
-inline
-Uint32
-CArray<T>::getSize() const {
- return size;
-}
-
-template <class T>
-inline
-void
-CArray<T>::getPtr(Ptr<T> & ptr) const {
- const Uint32 i = ptr.i;
- if(i < size){
- ptr.p = &theArray[i];
- return;
- } else {
- ErrorReporter::handleAssert("CArray<T>::getPtr", __FILE__, __LINE__);
- }
-}
-
-template <class T>
-inline
-T *
-CArray<T>::getPtr(Uint32 i) const {
- if(i < size){
- return &theArray[i];
- } else {
- ErrorReporter::handleAssert("CArray<T>::getPtr", __FILE__, __LINE__);
- return 0;
- }
-}
-
-template <class T>
-inline
-void
-CArray<T>::getPtr(Ptr<T> & ptr, Uint32 i) const {
- ptr.i = i;
- if(i < size){
- ptr.p = &theArray[i];
- return;
- } else {
- ErrorReporter::handleAssert("CArray<T>::getPtr", __FILE__, __LINE__);
- }
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/Callback.hpp b/storage/ndb/src/kernel/vm/Callback.hpp
deleted file mode 100644
index d7f2caf2f54..00000000000
--- a/storage/ndb/src/kernel/vm/Callback.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef BLOCK_CALLBACK_HPP
-#define BLOCK_CALLBACK_HPP
-
-/**
- * Block callbacks
- */
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/ClusterConfiguration.cpp b/storage/ndb/src/kernel/vm/ClusterConfiguration.cpp
deleted file mode 100644
index 263b22e34af..00000000000
--- a/storage/ndb/src/kernel/vm/ClusterConfiguration.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include "ClusterConfiguration.hpp"
-#include <ErrorHandlingMacros.hpp>
-
-#include <pc.hpp>
-#include <BlockNumbers.h>
-#include <signaldata/AccSizeAltReq.hpp>
-#include <signaldata/DictSizeAltReq.hpp>
-#include <signaldata/DihSizeAltReq.hpp>
-#include <signaldata/LqhSizeAltReq.hpp>
-#include <signaldata/TcSizeAltReq.hpp>
-#include <signaldata/TupSizeAltReq.hpp>
-#include <signaldata/TuxSizeAltReq.hpp>
-
-ClusterConfiguration::ClusterConfiguration()
-{
- for (unsigned i= 0; i< MAX_SIZEALT_BLOCKS; i++) // initialize
- for (unsigned j= 0; j< MAX_SIZEALT_RECORD; j++) {
- the_clusterData.SizeAltData.varSize[i][j].valid = false;
- the_clusterData.SizeAltData.varSize[i][j].nrr = 0;
- }
-
- for (unsigned i1 = 0; i1< 5; i1++) // initialize
- for (unsigned j1= 0; j1< CmvmiCfgConf::NO_OF_WORDS; j1++)
- the_clusterData.ispValues[i1][j1] = 0;
-
- the_clusterData.SizeAltData.noOfNodes = 0;
- the_clusterData.SizeAltData.noOfNDBNodes = 0;
- the_clusterData.SizeAltData.noOfAPINodes = 0;
- the_clusterData.SizeAltData.noOfMGMNodes = 0;
-}
-
-ClusterConfiguration::~ClusterConfiguration(){
-}
-
-void
-setValue(VarSize* dst, const int index, UintR variableValue){
- assert(dst != NULL);
- assert(index >= 0 && index < MAX_SIZEALT_RECORD);
-
- dst[index].nrr = variableValue;
- dst[index].valid = true;
-}
-
-void
-ClusterConfiguration::calcSizeAlteration()
-{
- SizeAlt *size = &the_clusterData.SizeAltData;
-
- size->noOfTables++; // Remove impact of system table
- size->noOfTables += size->noOfIndexes; // Indexes are tables too
- size->noOfAttributes += 2; // ---"----
-
- size->noOfTables *= 2; // Remove impact of Dict need 2 ids for each table
-
- Uint32 noOfDBNodes = size->noOfNDBNodes;
- if (noOfDBNodes > 15) {
- noOfDBNodes = 15;
- }//if
- Uint32 noOfLocalScanRecords = (noOfDBNodes * size->noOfScanRecords) + 1;
- Uint32 noOfTCScanRecords = size->noOfScanRecords;
- {
- /**
- * Acc Size Alt values
- */
- size->blockNo[ACC] = DBACC;
-
- VarSize * const acc = &(size->varSize[ACC][0]);
-
- // Can keep 65536 pages (= 0.5 GByte)
- setValue(acc, AccSizeAltReq::IND_DIR_RANGE,
- 4 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- setValue(acc, AccSizeAltReq::IND_DIR_ARRAY,
- (size->noOfIndexPages >> 8) +
- 4 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- setValue(acc, AccSizeAltReq::IND_FRAGMENT,
- 2 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- /*-----------------------------------------------------------------------*/
- // The extra operation records added are used by the scan and node
- // recovery process.
- // Node recovery process will have its operations dedicated to ensure
- // that they never have a problem with allocation of the operation record.
- // The remainder are allowed for use by the scan processes.
- /*-----------------------------------------------------------------------*/
- setValue(acc, AccSizeAltReq::IND_OP_RECS,
- size->noOfReplicas*((16 * size->noOfOperations) / 10 + 50) +
- (noOfLocalScanRecords * MAX_PARALLEL_SCANS_PER_FRAG) +
- NODE_RECOVERY_SCAN_OP_RECORDS);
-
- setValue(acc, AccSizeAltReq::IND_OVERFLOW_RECS,
- size->noOfIndexPages +
- 2 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- setValue(acc, AccSizeAltReq::IND_PAGE8,
- size->noOfIndexPages + 32);
-
- setValue(acc, AccSizeAltReq::IND_ROOT_FRAG,
- NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- setValue(acc, AccSizeAltReq::IND_TABLE,
- size->noOfTables);
-
- setValue(acc, AccSizeAltReq::IND_SCAN,
- noOfLocalScanRecords);
- }
-
- {
- /**
- * Dict Size Alt values
- */
- size->blockNo[DICT] = DBDICT;
-
- VarSize * const dict = &(size->varSize[DICT][0]);
-
- setValue(dict, DictSizeAltReq::IND_ATTRIBUTE,
- size->noOfAttributes);
-
- setValue(dict, DictSizeAltReq::IND_CONNECT,
- size->noOfOperations + 32);
-
- setValue(dict, DictSizeAltReq::IND_FRAG_CONNECT,
- NO_OF_FRAG_PER_NODE * size->noOfNDBNodes * size->noOfReplicas);
-
- setValue(dict, DictSizeAltReq::IND_TABLE,
- size->noOfTables);
-
- setValue(dict, DictSizeAltReq::IND_TC_CONNECT,
- 2* size->noOfOperations);
- }
-
- {
- /**
- * Dih Size Alt values
- */
- size->blockNo[DIH] = DBDIH;
-
- VarSize * const dih = &(size->varSize[DIH][0]);
-
- setValue(dih, DihSizeAltReq::IND_API_CONNECT,
- 2 * size->noOfTransactions);
-
- setValue(dih, DihSizeAltReq::IND_CONNECT,
- size->noOfOperations + 46);
-
- setValue(dih, DihSizeAltReq::IND_FRAG_CONNECT,
- NO_OF_FRAG_PER_NODE * size->noOfTables * size->noOfNDBNodes);
-
- int temp;
- temp = size->noOfReplicas - 2;
- if (temp < 0)
- temp = 1;
- else
- temp++;
- setValue(dih, DihSizeAltReq::IND_MORE_NODES,
- temp * NO_OF_FRAG_PER_NODE *
- size->noOfTables * size->noOfNDBNodes);
-
- setValue(dih, DihSizeAltReq::IND_REPLICAS,
- NO_OF_FRAG_PER_NODE * size->noOfTables *
- size->noOfNDBNodes * size->noOfReplicas);
-
- setValue(dih, DihSizeAltReq::IND_TABLE,
- size->noOfTables);
- }
-
- {
- /**
- * Lqh Size Alt values
- */
- size->blockNo[LQH] = DBLQH;
-
- VarSize * const lqh = &(size->varSize[LQH][0]);
-
- setValue(lqh, LqhSizeAltReq::IND_FRAG,
- NO_OF_FRAG_PER_NODE * size->noOfTables * size->noOfReplicas);
-
- setValue(lqh, LqhSizeAltReq::IND_CONNECT,
- size->noOfReplicas*((11 * size->noOfOperations) / 10 + 50));
-
- setValue(lqh, LqhSizeAltReq::IND_TABLE,
- size->noOfTables);
-
- setValue(lqh, LqhSizeAltReq::IND_TC_CONNECT,
- size->noOfReplicas*((16 * size->noOfOperations) / 10 + 50));
-
- setValue(lqh, LqhSizeAltReq::IND_REPLICAS,
- size->noOfReplicas);
-
- setValue(lqh, LqhSizeAltReq::IND_LOG_FILES,
- (4 * the_clusterData.ispValues[1][4]));
-
- setValue(lqh, LqhSizeAltReq::IND_SCAN,
- noOfLocalScanRecords);
-
- }
-
- {
- /**
- * Tc Size Alt values
- */
- size->blockNo[TC] = DBTC;
-
- VarSize * const tc = &(size->varSize[TC][0]);
-
- setValue(tc, TcSizeAltReq::IND_API_CONNECT,
- 3 * size->noOfTransactions);
-
- setValue(tc, TcSizeAltReq::IND_TC_CONNECT,
- size->noOfOperations + 16 + size->noOfTransactions);
-
- setValue(tc, TcSizeAltReq::IND_TABLE,
- size->noOfTables);
-
- setValue(tc, TcSizeAltReq::IND_LOCAL_SCAN,
- noOfLocalScanRecords);
-
- setValue(tc, TcSizeAltReq::IND_TC_SCAN,
- noOfTCScanRecords);
- }
-
- {
- /**
- * Tup Size Alt values
- */
- size->blockNo[TUP] = DBTUP;
-
- VarSize * const tup = &(size->varSize[TUP][0]);
-
- setValue(tup, TupSizeAltReq::IND_DISK_PAGE_ARRAY,
- 2 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- setValue(tup, TupSizeAltReq::IND_DISK_PAGE_REPRESENT,
- size->noOfDiskClusters);
-
- setValue(tup, TupSizeAltReq::IND_FRAG,
- 2 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- setValue(tup, TupSizeAltReq::IND_PAGE_CLUSTER,
- size->noOfFreeClusters);
-
- setValue(tup, TupSizeAltReq::IND_LOGIC_PAGE,
- size->noOfDiskBufferPages + size->noOfDiskClusters);
-
- setValue(tup, TupSizeAltReq::IND_OP_RECS,
- size->noOfReplicas*((16 * size->noOfOperations) / 10 + 50));
-
- setValue(tup, TupSizeAltReq::IND_PAGE,
- size->noOfDataPages);
-
- setValue(tup, TupSizeAltReq::IND_PAGE_RANGE,
- 4 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas);
-
- setValue(tup, TupSizeAltReq::IND_TABLE,
- size->noOfTables);
-
- setValue(tup, TupSizeAltReq::IND_TABLE_DESC,
- 4 * NO_OF_FRAG_PER_NODE * size->noOfAttributes* size->noOfReplicas +
- 12 * NO_OF_FRAG_PER_NODE * size->noOfTables* size->noOfReplicas );
-
- setValue(tup, TupSizeAltReq::IND_DELETED_BLOCKS,
- size->noOfFreeClusters);
-
- setValue(tup, TupSizeAltReq::IND_STORED_PROC,
- noOfLocalScanRecords);
- }
-
- {
- /**
- * Tux Size Alt values
- */
- size->blockNo[TUX] = DBTUX;
-
- VarSize * const tux = &(size->varSize[TUX][0]);
-
- setValue(tux, TuxSizeAltReq::IND_INDEX,
- size->noOfTables);
-
- setValue(tux, TuxSizeAltReq::IND_FRAGMENT,
- 2 * NO_OF_FRAG_PER_NODE * size->noOfTables * size->noOfReplicas);
-
- setValue(tux, TuxSizeAltReq::IND_ATTRIBUTE,
- size->noOfIndexes * 4);
-
- setValue(tux, TuxSizeAltReq::IND_SCAN,
- noOfLocalScanRecords);
- }
-}
-
-const ClusterConfiguration::ClusterData&
-ClusterConfiguration::clusterData() const
-{
- return the_clusterData;
-}
-
-void ClusterConfiguration::init(const Properties & p, const Properties & db){
- const char * msg = "Invalid configuration fetched";
-
- ClusterData & cd = the_clusterData;
-
- struct AttribStorage { const char * attrib; Uint32 * storage; };
- AttribStorage tmp[] = {
- {"MaxNoOfConcurrentScans", &cd.SizeAltData.noOfScanRecords },
- {"MaxNoOfTables", &cd.SizeAltData.noOfTables },
- {"MaxNoOfIndexes", &cd.SizeAltData.noOfIndexes },
- {"NoOfReplicas", &cd.SizeAltData.noOfReplicas },
- {"MaxNoOfAttributes", &cd.SizeAltData.noOfAttributes },
- {"MaxNoOfConcurrentOperations", &cd.SizeAltData.noOfOperations },
- {"MaxNoOfConcurrentTransactions", &cd.SizeAltData.noOfTransactions },
- {"NoOfIndexPages", &cd.SizeAltData.noOfIndexPages },
- {"NoOfDataPages", &cd.SizeAltData.noOfDataPages },
- {"NoOfDiskBufferPages", &cd.SizeAltData.noOfDiskBufferPages },
- {"NoOfDiskClusters", &cd.SizeAltData.noOfDiskClusters },
- {"NoOfFreeDiskClusters", &cd.SizeAltData.noOfFreeClusters },
- {"TimeToWaitAlive", &cd.ispValues[0][0] },
- {"HeartbeatIntervalDbDb", &cd.ispValues[0][2] },
- {"HeartbeatIntervalDbApi", &cd.ispValues[0][3] },
- {"ArbitrationTimeout", &cd.ispValues[0][5] },
- {"TimeBetweenLocalCheckpoints", &cd.ispValues[1][2] },
- {"NoOfFragmentLogFiles", &cd.ispValues[1][4] },
- {"MaxNoOfConcurrentScans", &cd.SizeAltData.noOfScanRecords },
- {"NoOfConcurrentCheckpointsDuringRestart", &cd.ispValues[1][5] },
- {"TransactionDeadlockDetectionTimeout", &cd.ispValues[1][6] },
- {"NoOfConcurrentProcessesHandleTakeover", &cd.ispValues[1][7] },
- {"TimeBetweenGlobalCheckpoints", &cd.ispValues[2][3] },
- {"NoOfConcurrentCheckpointsAfterRestart", &cd.ispValues[2][4] },
- {"TransactionInactiveTimeout", &cd.ispValues[2][7] },
- {"NoOfDiskPagesToDiskDuringRestartTUP", &cd.ispValues[3][8] },
- {"NoOfDiskPagesToDiskAfterRestartTUP", &cd.ispValues[3][9] },
- {"NoOfDiskPagesToDiskDuringRestartACC", &cd.ispValues[3][10] },
- {"NoOfDiskPagesToDiskAfterRestartACC", &cd.ispValues[3][11] },
- {"NoOfDiskClustersPerDiskFile", &cd.ispValues[4][8] },
- {"NoOfDiskFiles", &cd.ispValues[4][9] },
- {"NoOfReplicas", &cd.ispValues[2][2] }
- };
-
-
- const int sz = sizeof(tmp)/sizeof(AttribStorage);
- for(int i = 0; i<sz; i++){
- 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, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
- }
-
- if(!p.get("NoOfNodes", &cd.SizeAltData.noOfNodes)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "NoOfNodes missing");
- }
-
- Properties::Iterator it(&p);
- const char * name = 0;
- Uint32 nodeNo = 0;
- for(name = it.first(); name != NULL; name = it.next()){
- if(strncmp(name, "Node_", strlen("Node_")) == 0){
-
- Uint32 nodeId;
- const char * nodeType;
- const Properties * node;
-
- if(!p.get(name, &node)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data missing");
- }
-
- if(!node->get("Id", &nodeId)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data (Id) missing");
- }
-
- if(!node->get("Type", &nodeType)){
- 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, 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, 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, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
- }
-
- {
- for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
- Uint32 logLevel;
- if(db.get(LogLevel::LOGLEVEL_CATEGORY_NAME[j].name, &logLevel)){
- cd.SizeAltData.logLevel.setLogLevel((LogLevel::EventCategory)j,
- logLevel);
- }
- }
- }
-
- cd.nodeData[nodeNo].nodeId = nodeId;
- const char* tmpApiMgmProperties = 0;
- if(strcmp("DB", nodeType) == 0){
- cd.nodeData[nodeNo].nodeType = NodeInfo::DB;
- cd.SizeAltData.noOfNDBNodes++; // No of NDB processes
-
- 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, 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, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
- } else if(strcmp("API", nodeType) == 0){
- cd.nodeData[nodeNo].nodeType = NodeInfo::API;
- cd.SizeAltData.noOfAPINodes++; // No of API processes
- tmpApiMgmProperties = "API";
- } else if(strcmp("REP", nodeType) == 0){
- cd.nodeData[nodeNo].nodeType = NodeInfo::REP;
- //cd.SizeAltData.noOfAPINodes++; // No of API processes
- tmpApiMgmProperties = "REP";
- } else if(strcmp("MGM", nodeType) == 0){
- cd.nodeData[nodeNo].nodeType = NodeInfo::MGM;
- cd.SizeAltData.noOfMGMNodes++; // No of MGM processes
- tmpApiMgmProperties = "MGM";
- } else {
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
- "Invalid configuration: Unknown node type",
- nodeType);
- }
-
- if (tmpApiMgmProperties) {
- /*
- const Properties* q = 0;
-
- if (!p.get(tmpApiMgmProperties, nodeId, &q)) {
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, tmpApiMgmProperties);
- } else {
- */
- Uint32 rank = 0;
- if (node->get("ArbitrationRank", &rank) && rank > 0) {
- cd.nodeData[nodeNo].arbitRank = rank;
- // }
- }
- } else {
- cd.nodeData[nodeNo].arbitRank = 0;
- }
-
- nodeNo++;
- }
- }
- cd.SizeAltData.exist = true;
- calcSizeAlteration();
-}
-
-
diff --git a/storage/ndb/src/kernel/vm/ClusterConfiguration.hpp b/storage/ndb/src/kernel/vm/ClusterConfiguration.hpp
deleted file mode 100644
index be0930e5db4..00000000000
--- a/storage/ndb/src/kernel/vm/ClusterConfiguration.hpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef ClusterConfiguration_H
-#define ClusterConfiguration_H
-
-#include <kernel_types.h>
-#include <ndb_limits.h>
-#include <Properties.hpp>
-#include <ErrorReporter.hpp>
-#include <signaldata/CmvmiCfgConf.hpp>
-#include <signaldata/SetLogLevelOrd.hpp>
-#include <NodeInfo.hpp>
-
-// MaxNumber of sizealteration records in each block
-// MaxNumber of blocks with sizealteration, (size of array)
-#define MAX_SIZEALT_RECORD 16
-#define MAX_SIZEALT_BLOCKS 8
-
-enum NdbBlockName { ACC = 0, DICT, DIH, LQH, TC, TUP, TUX, NDB_SIZEALT_OFF };
-// NDB_SIZEALT_OFF is used for block without sizealteration
-// IMPORTANT to assign NDB_SIZEALT_OFF as largest value
-
-struct VarSize {
- int nrr;
- bool valid;
-};
-
-struct SizeAlt {
- unsigned int noOfTables;
- unsigned int noOfIndexes;
- unsigned int noOfReplicas;
- unsigned int noOfNDBNodes;
- unsigned int noOfAPINodes;
- unsigned int noOfMGMNodes;
- unsigned int noOfNodes;
- unsigned int noOfDiskLessNodes;
- unsigned int noOfAttributes;
- unsigned int noOfOperations;
- unsigned int noOfTransactions;
- unsigned int noOfIndexPages;
- unsigned int noOfDataPages;
- unsigned int noOfDiskBufferPages;
- unsigned int noOfFreeClusters;
- unsigned int noOfDiskClusters;
- unsigned int noOfScanRecords;
- bool exist;
- VarSize varSize[MAX_SIZEALT_BLOCKS][MAX_SIZEALT_RECORD];
- unsigned short blockNo[MAX_SIZEALT_BLOCKS];
- LogLevel logLevel;
-};
-
-
-class ClusterConfiguration
-{
-public:
-
- struct NodeData {
- NodeData() {
- nodeId = MAX_NODES+1;
- nodeType = NodeInfo::INVALID;
- arbitRank = ~0;
- }
- NodeId nodeId;
- NodeInfo::NodeType nodeType;
- unsigned arbitRank;
- };
-
- struct ClusterData
- {
- SizeAlt SizeAltData;
- NodeData nodeData[MAX_NODES];
- Uint32 ispValues[5][CmvmiCfgConf::NO_OF_WORDS];
- };
-
- ClusterConfiguration();
- ~ClusterConfiguration();
- const ClusterData& clusterData() const;
-
- void init(const Properties & p, const Properties & db);
-protected:
-
-private:
-
- ClusterData the_clusterData;
-
- void calcSizeAlteration();
-
-};
-
-#endif // ClusterConfiguration_H
-
diff --git a/storage/ndb/src/kernel/vm/Configuration.cpp b/storage/ndb/src/kernel/vm/Configuration.cpp
deleted file mode 100644
index c84b068ce9c..00000000000
--- a/storage/ndb/src/kernel/vm/Configuration.cpp
+++ /dev/null
@@ -1,902 +0,0 @@
-/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include <ndb_opts.h>
-
-#include "Configuration.hpp"
-#include <ErrorHandlingMacros.hpp>
-#include "GlobalData.hpp"
-
-#include <ConfigRetriever.hpp>
-#include <IPCConfig.hpp>
-#include <ndb_version.h>
-#include <NdbMem.h>
-#include <NdbOut.hpp>
-#include <WatchDog.hpp>
-
-#include <mgmapi_configuration.hpp>
-#include <mgmapi_config_parameters_debug.h>
-#include <kernel_config_parameters.h>
-
-#include <kernel_types.h>
-#include <ndb_limits.h>
-#include <ndbapi_limits.h>
-#include "pc.hpp"
-#include <LogLevel.hpp>
-#include <NdbSleep.h>
-
-extern "C" {
- void ndbSetOwnVersion();
-}
-
-#include <EventLogger.hpp>
-extern EventLogger g_eventLogger;
-
-enum ndbd_options {
- OPT_INITIAL = NDB_STD_OPTIONS_LAST,
- OPT_NODAEMON,
- OPT_FOREGROUND,
- OPT_NOWAIT_NODES,
- OPT_INITIAL_START
-};
-
-NDB_STD_OPTS_VARS;
-// XXX should be my_bool ???
-static int _daemon, _no_daemon, _foreground, _initial, _no_start;
-static int _initialstart;
-static const char* _nowait_nodes = 0;
-static const char* _bind_address = 0;
-
-extern Uint32 g_start_type;
-extern NdbNodeBitmask g_nowait_nodes;
-
-const char *load_default_groups[]= { "mysql_cluster","ndbd",0 };
-
-/**
- * Arguments to NDB process
- */
-static struct my_option my_long_options[] =
-{
- NDB_STD_OPTS("ndbd"),
- { "initial", OPT_INITIAL,
- "Perform initial start of ndbd, including cleaning the file system. "
- "Consult documentation before using this",
- &_initial, &_initial, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "nostart", 'n',
- "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd",
- &_no_start, &_no_start, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "daemon", 'd', "Start ndbd as daemon (default)",
- &_daemon, &_daemon, 0,
- GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
- { "nodaemon", OPT_NODAEMON,
- "Do not start ndbd as daemon, provided for testing purposes",
- &_no_daemon, &_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)",
- &_foreground, &_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",
- &_nowait_nodes, &_nowait_nodes, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
- { "initial-start", OPT_INITIAL_START,
- "Perform initial start",
- &_initialstart, &_initialstart, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "bind-address", OPT_NOWAIT_NODES,
- "Local bind address",
- &_bind_address, &_bind_address, 0,
- GET_STR, REQUIRED_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);
-}
-static void usage()
-{
- short_usage_sub();
- ndb_std_print_version();
- print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
- puts("");
- my_print_help(my_long_options);
- my_print_variables(my_long_options);
-}
-
-bool
-Configuration::init(int argc, char** argv)
-{
- load_defaults("my",load_default_groups,&argc,&argv);
-
- int ho_error;
-#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 || _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();
-
- // Check the start flag
- if (_no_start)
- globalData.theRestartFlag = initial_state;
- else
- globalData.theRestartFlag = perform_start;
-
- // Check the initial flag
- if (_initial)
- _initialStart = true;
-
- // Check connectstring
- if (opt_connect_str)
- _connectString = strdup(opt_connect_str);
-
- // Check daemon flag
- if (_daemon)
- _daemonMode = true;
- if (_foreground)
- _foregroundMode = true;
-
- // Save programname
- if(argc > 0 && argv[0] != 0)
- _programName = strdup(argv[0]);
- else
- _programName = strdup("");
-
- 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: %ld : %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;
-}
-
-Configuration::Configuration()
-{
- _programName = 0;
- _connectString = 0;
- _fsPath = 0;
- _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);
-
- if(_fsPath != NULL)
- free(_fsPath);
-
- if(_backupPath != NULL)
- free(_backupPath);
-
- if (m_config_retriever) {
- delete m_config_retriever;
- }
-
- if(m_logLevel) {
- delete m_logLevel;
- }
-}
-
-void
-Configuration::closeConfiguration(bool end_session){
- m_config_retriever->end_session(end_session);
- if (m_config_retriever) {
- delete m_config_retriever;
- }
- m_config_retriever= 0;
-}
-
-void
-Configuration::fetch_configuration(){
- /**
- * Fetch configuration from management server
- */
- if (m_config_retriever) {
- delete m_config_retriever;
- }
-
- m_mgmd_port= 0;
- m_config_retriever= new ConfigRetriever(getConnectString(),
- NDB_VERSION,
- NODE_TYPE_DB,
- _bind_address);
-
- if (m_config_retriever->hasError())
- {
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
- "Could not connect initialize handle to management server",
- m_config_retriever->getErrorString());
- }
-
- if(m_config_retriever->do_connect(12,5,1) == -1){
- const char * s = m_config_retriever->getErrorString();
- if(s == 0)
- s = "No error given!";
- /* Set stop on error to true otherwise NDB will
- go into an restart loop...
- */
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Could not connect to ndb_mgmd", s);
- }
-
- m_mgmd_port= m_config_retriever->get_mgmd_port();
- m_mgmd_host.assign(m_config_retriever->get_mgmd_host());
-
- ConfigRetriever &cr= *m_config_retriever;
-
- /**
- * if we have a nodeid set (e.g in a restart situation)
- * reuse it
- */
- if (globalData.ownId)
- cr.setNodeId(globalData.ownId);
-
- globalData.ownId = cr.allocNodeId(globalData.ownId ? 10 : 2 /*retry*/,
- 3 /*delay*/);
-
- if(globalData.ownId == 0){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
- "Unable to alloc node id", m_config_retriever->getErrorString());
- }
-
- ndb_mgm_configuration * p = cr.getConfig();
- if(p == 0){
- const char * s = cr.getErrorString();
- if(s == 0)
- s = "No error given!";
-
- /* Set stop on error to true otherwise NDB will
- go into an restart loop...
- */
-
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Could not fetch configuration"
- "/invalid configuration", s);
- }
- if(m_clusterConfig)
- free(m_clusterConfig);
-
- m_clusterConfig = p;
-
- ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
- if (iter.find(CFG_NODE_ID, globalData.ownId)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched", "DB missing");
- }
-
- if(iter.get(CFG_DB_STOP_ON_ERROR, &_stopOnError)){
- 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,
- Uint32 param, const char *param_string)
-{
- const char* path = NULL;
- if(iter.get(param, &path)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched missing ",
- param_string);
- }
-
- if(path == 0 || strlen(path) == 0){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
- "Invalid configuration fetched. Configuration does not contain valid ",
- param_string);
- }
-
- // check that it is pointing on a valid directory
- //
- char buf2[PATH_MAX];
- memset(buf2, 0,sizeof(buf2));
-#ifdef NDB_WIN32
- char* szFilePart;
- if(!GetFullPathName(path, sizeof(buf2), buf2, &szFilePart) ||
- (GetFileAttributes(buf2) & FILE_ATTRIBUTE_READONLY))
-#else
- if((::realpath(path, buf2) == NULL)||
- (::access(buf2, W_OK) != 0))
-#endif
- {
- ERROR_SET(fatal, NDBD_EXIT_AFS_INVALIDPATH, path, param_string);
- }
-
- if (strcmp(&buf2[strlen(buf2) - 1], DIR_SEPARATOR))
- strcat(buf2, DIR_SEPARATOR);
-
- return strdup(buf2);
-}
-
-void
-Configuration::setupConfiguration(){
-
- DBUG_ENTER("Configuration::setupConfiguration");
-
- ndb_mgm_configuration * p = m_clusterConfig;
-
- /**
- * Configure transporters
- */
- {
- int res = IPCConfig::configureTransporters(globalData.ownId,
- * p,
- globalTransporterRegistry);
- if(res <= 0){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
- "No transporters configured");
- }
- }
-
- /**
- * Setup cluster configuration data
- */
- ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
- if (iter.find(CFG_NODE_ID, globalData.ownId)){
- 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, 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, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
- "MaxNoOfSavedMessages missing");
- }
-
- if(iter.get(CFG_DB_MEMLOCK, &_lockPagesInMainMemory)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
- "LockPagesInMainMemory missing");
- }
-
- if(iter.get(CFG_DB_WATCHDOG_INTERVAL, &_timeBetweenWatchDogCheck)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
- "TimeBetweenWatchDogCheck missing");
- }
-
- if(iter.get(CFG_DB_WATCHDOG_INTERVAL_INITIAL, &_timeBetweenWatchDogCheckInitial)){
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
- "TimeBetweenWatchDogCheckInitial missing");
- }
-
- /**
- * Get paths
- */
- if (_fsPath)
- free(_fsPath);
- _fsPath= get_and_validate_path(iter, CFG_DB_FILESYSTEM_PATH, "FileSystemPath");
- if (_backupPath)
- free(_backupPath);
- _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, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
- "RestartOnErrorInsert missing");
- }
-
- /**
- * Create the watch dog thread
- */
- {
- if (_timeBetweenWatchDogCheckInitial < _timeBetweenWatchDogCheck)
- _timeBetweenWatchDogCheckInitial = _timeBetweenWatchDogCheck;
-
- Uint32 t = _timeBetweenWatchDogCheckInitial;
- t = globalEmulatorData.theWatchDog ->setCheckInterval(t);
- _timeBetweenWatchDogCheckInitial = t;
- }
-
- 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);
-
- calcSizeAlt(cf);
-
- DBUG_VOID_RETURN;
-}
-
-Uint32
-Configuration::lockPagesInMainMemory() const {
- return _lockPagesInMainMemory;
-}
-
-int
-Configuration::timeBetweenWatchDogCheck() const {
- return _timeBetweenWatchDogCheck;
-}
-
-void
-Configuration::timeBetweenWatchDogCheck(int value) {
- _timeBetweenWatchDogCheck = value;
-}
-
-int
-Configuration::maxNoOfErrorLogs() const {
- return _maxErrorLogs;
-}
-
-void
-Configuration::maxNoOfErrorLogs(int val){
- _maxErrorLogs = val;
-}
-
-bool
-Configuration::stopOnError() const {
- return _stopOnError;
-}
-
-void
-Configuration::stopOnError(bool val){
- _stopOnError = val;
-}
-
-int
-Configuration::getRestartOnErrorInsert() const {
- return m_restartOnErrorInsert;
-}
-
-void
-Configuration::setRestartOnErrorInsert(int i){
- m_restartOnErrorInsert = i;
-}
-
-const char *
-Configuration::getConnectString() const {
- return _connectString;
-}
-
-char *
-Configuration::getConnectStringCopy() const {
- if(_connectString != 0)
- return strdup(_connectString);
- return 0;
-}
-
-const ndb_mgm_configuration_iterator *
-Configuration::getOwnConfigIterator() const {
- return m_ownConfigIterator;
-}
-
-ndb_mgm_configuration_iterator *
-Configuration::getClusterConfigIterator() const {
- return m_clusterConfigIter;
-}
-
-void
-Configuration::calcSizeAlt(ConfigValues * ownConfig){
- const char * msg = "Invalid configuration fetched";
- char buf[255];
-
- unsigned int noOfTables = 0;
- unsigned int noOfUniqueHashIndexes = 0;
- unsigned int noOfOrderedIndexes = 0;
- unsigned int noOfTriggers = 0;
- unsigned int noOfReplicas = 0;
- unsigned int noOfDBNodes = 0;
- unsigned int noOfAPINodes = 0;
- unsigned int noOfMGMNodes = 0;
- unsigned int noOfNodes = 0;
- unsigned int noOfAttributes = 0;
- unsigned int noOfOperations = 0;
- unsigned int noOfLocalOperations = 0;
- unsigned int noOfTransactions = 0;
- unsigned int noOfIndexPages = 0;
- unsigned int noOfDataPages = 0;
- unsigned int noOfScanRecords = 0;
- unsigned int noOfLocalScanRecords = 0;
- unsigned int noBatchSize = 0;
- m_logLevel = new LogLevel();
-
- struct AttribStorage { int paramId; Uint32 * storage; bool computable; };
- AttribStorage tmp[] = {
- { CFG_DB_NO_SCANS, &noOfScanRecords, false },
- { CFG_DB_NO_LOCAL_SCANS, &noOfLocalScanRecords, true },
- { CFG_DB_BATCH_SIZE, &noBatchSize, false },
- { CFG_DB_NO_TABLES, &noOfTables, false },
- { CFG_DB_NO_ORDERED_INDEXES, &noOfOrderedIndexes, false },
- { CFG_DB_NO_UNIQUE_HASH_INDEXES, &noOfUniqueHashIndexes, false },
- { CFG_DB_NO_TRIGGERS, &noOfTriggers, true },
- { CFG_DB_NO_REPLICAS, &noOfReplicas, false },
- { CFG_DB_NO_ATTRIBUTES, &noOfAttributes, false },
- { CFG_DB_NO_OPS, &noOfOperations, false },
- { CFG_DB_NO_LOCAL_OPS, &noOfLocalOperations, true },
- { CFG_DB_NO_TRANSACTIONS, &noOfTransactions, false }
- };
-
- ndb_mgm_configuration_iterator db(*(ndb_mgm_configuration*)ownConfig, 0);
-
- const int sz = sizeof(tmp)/sizeof(AttribStorage);
- for(int i = 0; i<sz; i++){
- if(ndb_mgm_get_int_parameter(&db, tmp[i].paramId, tmp[i].storage)){
- if (tmp[i].computable) {
- *tmp[i].storage = 0;
- } else {
- BaseString::snprintf(buf, sizeof(buf),"ConfigParam: %d not found", tmp[i].paramId);
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
- }
- }
-
- Uint64 indexMem = 0, dataMem = 0;
- ndb_mgm_get_int64_parameter(&db, CFG_DB_DATA_MEM, &dataMem);
- ndb_mgm_get_int64_parameter(&db, CFG_DB_INDEX_MEM, &indexMem);
- if(dataMem == 0){
- BaseString::snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_DATA_MEM);
- 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, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
-
- noOfDataPages = (dataMem / 32768);
- noOfIndexPages = (indexMem / 8192);
-
- for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
- Uint32 tmp;
- if(!ndb_mgm_get_int_parameter(&db, CFG_MIN_LOGLEVEL+j, &tmp)){
- m_logLevel->setLogLevel((LogLevel::EventCategory)j, tmp);
- }
- }
-
- // tmp
- ndb_mgm_configuration_iterator * p = m_clusterConfigIter;
-
- Uint32 nodeNo = noOfNodes = 0;
- NodeBitmask nodes;
- for(ndb_mgm_first(p); ndb_mgm_valid(p); ndb_mgm_next(p), nodeNo++){
-
- Uint32 nodeId;
- Uint32 nodeType;
-
- if(ndb_mgm_get_int_parameter(p, CFG_NODE_ID, &nodeId)){
- 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, 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, 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, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
- nodes.set(nodeId);
-
- switch(nodeType){
- case NODE_TYPE_DB:
- noOfDBNodes++; // No of NDB processes
-
- 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, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
- break;
- case NODE_TYPE_API:
- noOfAPINodes++; // No of API processes
- break;
- case NODE_TYPE_MGM:
- noOfMGMNodes++; // No of MGM processes
- break;
- default:
- BaseString::snprintf(buf, sizeof(buf), "Unknown node type: %d", nodeType);
- ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
- }
- }
- noOfNodes = nodeNo;
-
- noOfTables+= 2; // Add System tables
- noOfAttributes += 9; // Add System table attributes
-
- ConfigValues::Iterator it2(*ownConfig, db.m_config);
- it2.set(CFG_DB_NO_TABLES, noOfTables);
- it2.set(CFG_DB_NO_ATTRIBUTES, noOfAttributes);
- {
- Uint32 neededNoOfTriggers = /* types: Insert/Update/Delete/Custom */
- 3 * noOfUniqueHashIndexes + /* for unique hash indexes, I/U/D */
- 3 * NDB_MAX_ACTIVE_EVENTS + /* for events in suma, I/U/D */
- 3 * noOfTables + /* for backup, I/U/D */
- noOfOrderedIndexes; /* for ordered indexes, C */
- if (noOfTriggers < neededNoOfTriggers)
- {
- noOfTriggers= neededNoOfTriggers;
- it2.set(CFG_DB_NO_TRIGGERS, noOfTriggers);
- }
- }
-
- /**
- * Do size calculations
- */
- ConfigValuesFactory cfg(ownConfig);
-
- Uint32 noOfMetaTables= noOfTables + noOfOrderedIndexes +
- noOfUniqueHashIndexes;
- Uint32 noOfMetaTablesDict= noOfMetaTables;
- if (noOfMetaTablesDict > MAX_TABLES)
- noOfMetaTablesDict= MAX_TABLES;
-
- {
- /**
- * Dict Size Alt values
- */
- cfg.put(CFG_DICT_ATTRIBUTE,
- noOfAttributes);
-
- cfg.put(CFG_DICT_TABLE,
- noOfMetaTablesDict);
- }
-
-
- if (noOfLocalScanRecords == 0) {
- noOfLocalScanRecords = (noOfDBNodes * noOfScanRecords) + 1;
- }
- if (noOfLocalOperations == 0) {
- noOfLocalOperations= (11 * noOfOperations) / 10;
- }
- Uint32 noOfTCScanRecords = noOfScanRecords;
-
- {
- Uint32 noOfAccTables= noOfMetaTables/*noOfTables+noOfUniqueHashIndexes*/;
- /**
- * Acc Size Alt values
- */
- // Can keep 65536 pages (= 0.5 GByte)
- cfg.put(CFG_ACC_DIR_RANGE,
- 2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
-
- cfg.put(CFG_ACC_DIR_ARRAY,
- (noOfIndexPages >> 8) +
- 2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
-
- cfg.put(CFG_ACC_FRAGMENT,
- NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
-
- /*-----------------------------------------------------------------------*/
- // The extra operation records added are used by the scan and node
- // recovery process.
- // Node recovery process will have its operations dedicated to ensure
- // that they never have a problem with allocation of the operation record.
- // The remainder are allowed for use by the scan processes.
- /*-----------------------------------------------------------------------*/
- cfg.put(CFG_ACC_OP_RECS,
- (noOfLocalOperations + 50) +
- (noOfLocalScanRecords * noBatchSize) +
- NODE_RECOVERY_SCAN_OP_RECORDS);
-
- cfg.put(CFG_ACC_OVERFLOW_RECS,
- noOfIndexPages +
- NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
-
- cfg.put(CFG_ACC_PAGE8,
- noOfIndexPages + 32);
-
- cfg.put(CFG_ACC_TABLE, noOfAccTables);
-
- cfg.put(CFG_ACC_SCAN, noOfLocalScanRecords);
- }
-
- {
- /**
- * Dih Size Alt values
- */
- cfg.put(CFG_DIH_API_CONNECT,
- 2 * noOfTransactions);
-
- cfg.put(CFG_DIH_CONNECT,
- noOfOperations + noOfTransactions + 46);
-
- Uint32 noFragPerTable= ((noOfDBNodes + NO_OF_FRAGS_PER_CHUNK - 1) >>
- LOG_NO_OF_FRAGS_PER_CHUNK) <<
- LOG_NO_OF_FRAGS_PER_CHUNK;
-
- cfg.put(CFG_DIH_FRAG_CONNECT,
- noFragPerTable * noOfMetaTables);
-
- int temp;
- temp = noOfReplicas - 2;
- if (temp < 0)
- temp = 1;
- else
- temp++;
- cfg.put(CFG_DIH_MORE_NODES,
- temp * NO_OF_FRAG_PER_NODE *
- noOfMetaTables * noOfDBNodes);
-
- cfg.put(CFG_DIH_REPLICAS,
- NO_OF_FRAG_PER_NODE * noOfMetaTables *
- noOfDBNodes * noOfReplicas);
-
- cfg.put(CFG_DIH_TABLE,
- noOfMetaTables);
- }
-
- {
- /**
- * Lqh Size Alt values
- */
- cfg.put(CFG_LQH_FRAG,
- NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas);
-
- cfg.put(CFG_LQH_TABLE,
- noOfMetaTables);
-
- cfg.put(CFG_LQH_TC_CONNECT,
- noOfLocalOperations + 50);
-
- cfg.put(CFG_LQH_SCAN,
- noOfLocalScanRecords);
- }
-
- {
- /**
- * Tc Size Alt values
- */
- cfg.put(CFG_TC_API_CONNECT,
- 3 * noOfTransactions);
-
- cfg.put(CFG_TC_TC_CONNECT,
- (2 * noOfOperations) + 16 + noOfTransactions);
-
- cfg.put(CFG_TC_TABLE,
- noOfMetaTables);
-
- cfg.put(CFG_TC_LOCAL_SCAN,
- noOfLocalScanRecords);
-
- cfg.put(CFG_TC_SCAN,
- noOfTCScanRecords);
- }
-
- {
- /**
- * Tup Size Alt values
- */
- cfg.put(CFG_TUP_FRAG,
- NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
-
- cfg.put(CFG_TUP_OP_RECS,
- noOfLocalOperations + 50);
-
- cfg.put(CFG_TUP_PAGE,
- noOfDataPages);
-
- cfg.put(CFG_TUP_PAGE_RANGE,
- 2 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
-
- cfg.put(CFG_TUP_TABLE,
- noOfMetaTables);
-
- cfg.put(CFG_TUP_TABLE_DESC,
- 6 * NO_OF_FRAG_PER_NODE * noOfAttributes * noOfReplicas +
- 10 * NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas );
-
- cfg.put(CFG_TUP_STORED_PROC,
- noOfLocalScanRecords);
- }
-
- {
- /**
- * Tux Size Alt values
- */
- cfg.put(CFG_TUX_INDEX,
- noOfMetaTables /*noOfOrderedIndexes*/);
-
- cfg.put(CFG_TUX_FRAGMENT,
- NO_OF_FRAG_PER_NODE * noOfOrderedIndexes * noOfReplicas);
-
- cfg.put(CFG_TUX_ATTRIBUTE,
- noOfOrderedIndexes * 4);
-
- cfg.put(CFG_TUX_SCAN_OP, noOfLocalScanRecords);
- }
-
- m_ownConfig = (ndb_mgm_configuration*)cfg.getConfigValues();
- m_ownConfigIterator = ndb_mgm_create_configuration_iterator
- (m_ownConfig, 0);
-}
-
-void
-Configuration::setInitialStart(bool val){
- _initialStart = val;
-}
diff --git a/storage/ndb/src/kernel/vm/Configuration.hpp b/storage/ndb/src/kernel/vm/Configuration.hpp
deleted file mode 100644
index 9aefbf9c248..00000000000
--- a/storage/ndb/src/kernel/vm/Configuration.hpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef Configuration_H
-#define Configuration_H
-
-#include <util/BaseString.hpp>
-#include <mgmapi.h>
-#include <ndb_types.h>
-
-class ConfigRetriever;
-
-class Configuration {
-public:
- Configuration();
- ~Configuration();
-
- /**
- * Returns false if arguments are invalid
- */
- bool init(int argc, char** argv);
-
- void fetch_configuration();
- void setupConfiguration();
- void closeConfiguration(bool end_session= true);
-
- Uint32 lockPagesInMainMemory() const;
-
- int timeBetweenWatchDogCheck() const ;
- void timeBetweenWatchDogCheck(int value);
-
- int maxNoOfErrorLogs() const ;
- void maxNoOfErrorLogs(int val);
-
- bool stopOnError() const;
- void stopOnError(bool val);
-
- int getRestartOnErrorInsert() const;
- void setRestartOnErrorInsert(int);
-
- // Cluster configuration
- const char * programName() const;
- const char * fileSystemPath() const;
- const char * backupFilePath() const;
- const char * getConnectString() const;
- char * getConnectStringCopy() const;
-
- /**
- *
- */
- 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.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;
- Uint32 m_restartOnErrorInsert;
- Uint32 _maxErrorLogs;
- Uint32 _lockPagesInMainMemory;
- Uint32 _timeBetweenWatchDogCheck;
- Uint32 _timeBetweenWatchDogCheckInitial;
-
- ndb_mgm_configuration * m_ownConfig;
- ndb_mgm_configuration * m_clusterConfig;
-
- ndb_mgm_configuration_iterator * m_clusterConfigIter;
- ndb_mgm_configuration_iterator * m_ownConfigIterator;
-
- ConfigRetriever *m_config_retriever;
-
- Vector<BaseString> m_mgmds;
-
- /**
- * arguments to NDB process
- */
- char * _programName;
- char * _fsPath;
- char * _backupPath;
- bool _initialStart;
- char * _connectString;
- Uint32 m_mgmd_port;
- BaseString m_mgmd_host;
- bool _daemonMode; // if not, angel in foreground
- bool _foregroundMode; // no angel, raw ndbd in foreground
-
- void calcSizeAlt(class ConfigValues * );
-};
-
-inline
-const char *
-Configuration::programName() const {
- return _programName;
-}
-
-inline
-const char *
-Configuration::fileSystemPath() const {
- return _fsPath;
-}
-
-inline
-const char *
-Configuration::backupFilePath() const {
- return _backupPath;
-}
-
-inline
-bool
-Configuration::getInitialStart() const {
- return _initialStart;
-}
-
-inline
-bool
-Configuration::getDaemonMode() const {
- return _daemonMode;
-}
-
-inline
-bool
-Configuration::getForegroundMode() const {
- return _foregroundMode;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/DLCFifoList.hpp b/storage/ndb/src/kernel/vm/DLCFifoList.hpp
deleted file mode 100644
index ad449c08f4a..00000000000
--- a/storage/ndb/src/kernel/vm/DLCFifoList.hpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DLC_FIFOLIST_HPP
-#define DLC_FIFOLIST_HPP
-
-#include "DLFifoList.hpp"
-#include <NdbOut.hpp>
-
-// Adds "count" to DLFifoList
-template <class T, class U = T>
-class DLCFifoList : public DLFifoList<T, U> {
-public:
- // List head
- struct Head : public DLFifoList<T, U>::Head {
- Head() : m_count(0) {}
- Uint32 m_count;
- };
-
- // Ctor
- DLCFifoList(ArrayPool<T> & thePool) :
- DLFifoList<T, U>(thePool)
- {}
-
- // Get count
- Uint32 count() const { return head.m_count; }
-
- // Redefine methods which do add or remove
-
- bool seize(Ptr<T>& ptr) {
- if (DLFifoList<T, U>::seize(ptr)) {
- head.m_count++;
- return true;
- }
- return false;
- }
-
- bool seizeId(Ptr<T>& ptr, Uint32 i) {
- if (DLFifoList<T, U>::seizeId(ptr)) {
- head.m_count++;
- return true;
- }
- return false;
- }
-
- void add(Ptr<T>& ptr) {
- DLFifoList<T, U>::add(ptr);
- head.m_count++;
- }
-
- void remove(Ptr<T>& ptr) {
- DLFifoList<T, U>::remove(ptr);
- head.m_count--;
- }
-
- void release(Uint32 i) {
- DLFifoList<T, U>::release(i);
- head.m_count--;
- }
-
- void release(Ptr<T>& ptr) {
- DLFifoList<T, U>::release(ptr);
- head.m_count--;
- }
-
- void release() {
- DLFifoList<T, U>::release();
- head.m_count = 0;
- }
-
- DLCFifoList<T>& operator=(const DLCFifoList<T>& src){
- assert(&this->thePool == &src.thePool);
- this->head = src.head;
- return * this;
- }
-
-protected:
- Head head;
-};
-
-// Local variant
-template <class T, class U = T>
-class LocalDLCFifoList : public DLCFifoList<T, U> {
-public:
- LocalDLCFifoList(ArrayPool<T> & thePool,
- typename DLCFifoList<T, U>::Head &_src)
- : DLCFifoList<T, U>(thePool), src(_src)
- {
- this->head = src;
-#ifdef VM_TRACE
- assert(src.in_use == false);
- src.in_use = true;
-#endif
- }
-
- ~LocalDLCFifoList() {
-#ifdef VM_TRACE
- assert(src.in_use == true);
-#endif
- src = this->head;
- }
-private:
- typename DLCFifoList<T, U>::Head & src;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/DLCHashTable.hpp b/storage/ndb/src/kernel/vm/DLCHashTable.hpp
deleted file mode 100644
index fb224f2bd4c..00000000000
--- a/storage/ndb/src/kernel/vm/DLCHashTable.hpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DLC_HASHTABLE_HPP
-#define DLC_HASHTABLE_HPP
-
-#include <ndb_global.h>
-#include "DLHashTable.hpp"
-
-// Adds "count" to DLHashTable
-template <class T, class U = T>
-class DLCHashTable : public DLHashTable<T, U> {
-public:
- // Ctor
- DLCHashTable(ArrayPool<T> & thePool) :
- DLHashTable<T, U>(thePool),
- m_count(0)
- {}
-
- // Get count
- Uint32 count() const { return m_count; }
-
- // Redefine methods which do add or remove
-
- void add(Ptr<T>& ptr) {
- DLHashTable<T, U>::add(ptr);
- m_count++;
- }
-
- void remove(Ptr<T>& ptr, const T & key) {
- DLHashTable<T, U>::remove(ptr, key);
- m_count--;
- }
-
- void remove(Uint32 i) {
- DLHashTable<T, U>::remove(i);
- m_count--;
- }
-
- void remove(Ptr<T>& ptr) {
- DLHashTable<T, U>::remove(ptr);
- m_count--;
- }
-
- void removeAll() {
- DLHashTable<T, U>::removeAll();
- m_count = 0;
- }
-
- void release(Ptr<T>& ptr, const T & key) {
- DLHashTable<T, U>::release(ptr, key);
- m_count--;
- }
-
- void release(Uint32 i) {
- DLHashTable<T, U>::release(i);
- m_count--;
- }
-
- void release(Ptr<T>& ptr) {
- DLHashTable<T, U>::release(ptr);
- m_count--;
- }
-
-private:
- Uint32 m_count;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/DLFifoList.hpp b/storage/ndb/src/kernel/vm/DLFifoList.hpp
deleted file mode 100644
index b78df5126c5..00000000000
--- a/storage/ndb/src/kernel/vm/DLFifoList.hpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DLFIFOLIST_HPP
-#define DLFIFOLIST_HPP
-
-#include <ndb_global.h>
-#include <kernel_types.h>
-#include "Pool.hpp"
-
-/**
- * Template class used for implementing an
- * list of object retreived from a pool
- */
-template <typename P, typename T, typename U = T>
-class DLFifoListImpl
-{
-public:
- /**
- * List head
- */
- struct Head
- {
- Head();
- Uint32 firstItem;
- Uint32 lastItem;
-
-#ifdef VM_TRACE
- bool in_use;
-#endif
-
- inline bool isEmpty() const { return firstItem == RNIL;}
- };
-
- DLFifoListImpl(P & thePool);
-
- bool seizeFirst(Ptr<T> &);
- bool seizeLast(Ptr<T> &);
- bool seize(Ptr<T> & ptr) { return seizeLast(ptr);}
-
- void release(Ptr<T> &);
- void release(); // release all
-
- void addFirst(Ptr<T> &);
- void addLast(Ptr<T> &);
- void add(Ptr<T> & ptr) { addLast(ptr);}
-
- /**
- * Insert object <em>ptr</ptr> _before_ <em>loc</em>
- */
- void insert(Ptr<T> & ptr, Ptr<T>& loc);
-
- void remove();
- void remove(Ptr<T> &);
- void remove(T*);
- /**
- * Update i & p value according to <b>i</b>
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &) const ;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i) const ;
-
- /**
- * Update ptr to first element in list
- *
- * Return i
- */
- bool first(Ptr<T> &) const ;
-
- /**
- * Update ptr to first element in list
- *
- * Return i
- */
- bool last(Ptr<T> &) const ;
-
- /**
- * Get next element
- *
- * NOTE ptr must be both p & i
- */
- bool next(Ptr<T> &) const ;
-
- /**
- * Get next element
- *
- * NOTE ptr must be both p & i
- */
- bool prev(Ptr<T> &) const ;
-
- /**
- * Check if next exists i.e. this is not last
- *
- * NOTE ptr must be both p & i
- */
- bool hasNext(const Ptr<T> &) const;
-
- /**
- * Check if next exists i.e. this is not last
- *
- * NOTE ptr must be both p & i
- */
- bool hasPrev(const Ptr<T> &) const;
-
- inline bool isEmpty() const { return head.firstItem == RNIL;}
-
- /**
- * Copy list (head)
- * Will construct to identical lists
- */
- DLFifoListImpl<P,T,U>& operator=(const DLFifoListImpl<P,T,U>& src){
- assert(&thePool == &src.thePool);
- this->head = src.head;
- return * this;
- }
-
-protected:
- Head head;
- P & thePool;
-};
-
-template <typename P, typename T, typename U = T>
-class LocalDLFifoListImpl : public DLFifoListImpl<P,T,U>
-{
-public:
- LocalDLFifoListImpl(P & thePool, typename DLFifoListImpl<P,T,U>::Head &_src)
- : DLFifoListImpl<P,T,U>(thePool), src(_src)
- {
- this->head = src;
-#ifdef VM_TRACE
- assert(src.in_use == false);
- src.in_use = true;
-#endif
- }
-
- ~LocalDLFifoListImpl(){
-#ifdef VM_TRACE
- assert(src.in_use == true);
-#endif
- src = this->head;
- }
-private:
- typename DLFifoListImpl<P,T,U>::Head & src;
-};
-
-template <typename P, typename T, typename U>
-inline
-DLFifoListImpl<P,T,U>::DLFifoListImpl(P & _pool):
- thePool(_pool)
-{
-}
-
-template <typename P, typename T, typename U>
-inline
-DLFifoListImpl<P,T,U>::Head::Head()
-{
- firstItem = RNIL;
- lastItem = RNIL;
-#ifdef VM_TRACE
- in_use = false;
-#endif
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::seizeFirst(Ptr<T> & p)
-{
- if (likely(thePool.seize(p)))
- {
- addFirst(p);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::seizeLast(Ptr<T> & p)
-{
- if (likely(thePool.seize(p)))
- {
- addLast(p);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::addFirst(Ptr<T> & p)
-{
- Uint32 ff = head.firstItem;
-
- p.p->U::prevList = RNIL;
- p.p->U::nextList = ff;
- head.firstItem = p.i;
- if (ff == RNIL)
- {
- head.lastItem = p.i;
- }
- else
- {
- T * t2 = thePool.getPtr(ff);
- t2->U::prevList = p.i;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::addLast(Ptr<T> & p)
-{
- T * t = p.p;
- Uint32 last = head.lastItem;
- head.lastItem = p.i;
-
- t->U::nextList = RNIL;
- t->U::prevList = last;
-
- if(last != RNIL)
- {
- T * t2 = thePool.getPtr(last);
- t2->U::nextList = p.i;
- }
- else
- {
- head.firstItem = p.i;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::insert(Ptr<T> & ptr, Ptr<T> & loc)
-{
- Uint32 prev= loc.p->U::prevList;
- if(loc.i == head.firstItem)
- {
- head.firstItem = ptr.i;
- assert(prev == RNIL);
- }
- else
- {
- T* t2 = thePool.getPtr(prev);
- t2->U::nextList = ptr.i;
- }
-
- loc.p->U::prevList = ptr.i;
- ptr.p->U::prevList = prev;
- ptr.p->U::nextList = loc.i;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::remove()
-{
- head.firstItem = RNIL;
- head.lastItem = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::remove(Ptr<T> & p)
-{
- remove(p.p);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::remove(T * t)
-{
- Uint32 ni = t->U::nextList;
- Uint32 pi = t->U::prevList;
-
- if(ni != RNIL)
- {
- T * t = thePool.getPtr(ni);
- t->U::prevList = pi;
- }
- else
- {
- // We are releasing last
- head.lastItem = pi;
- }
-
- if(pi != RNIL)
- {
- T * t = thePool.getPtr(pi);
- t->U::nextList = ni;
- }
- else
- {
- // We are releasing first
- head.firstItem = ni;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::release()
-{
- Ptr<T> ptr;
- Uint32 curr = head.firstItem;
- while(curr != RNIL)
- {
- thePool.getPtr(ptr, curr);
- curr = ptr.p->U::nextList;
- thePool.release(ptr);
- }
- head.firstItem = RNIL;
- head.lastItem = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::release(Ptr<T> & p)
-{
- remove(p.p);
- thePool.release(p);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::getPtr(Ptr<T> & p, Uint32 i) const
-{
- p.i = i;
- p.p = thePool.getPtr(i);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLFifoListImpl<P,T,U>::getPtr(Ptr<T> & p) const
-{
- thePool.getPtr(p);
-}
-
-template <typename P, typename T, typename U>
-inline
-T *
-DLFifoListImpl<P,T,U>::getPtr(Uint32 i) const
-{
- return thePool.getPtr(i);
-}
-
-/**
- * Update ptr to first element in list
- *
- * Return i
- */
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::first(Ptr<T> & p) const
-{
- p.i = head.firstItem;
- if(p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::last(Ptr<T> & p) const
-{
- p.i = head.lastItem;
- if(p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::next(Ptr<T> & p) const
-{
- p.i = p.p->U::nextList;
- if(p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::prev(Ptr<T> & p) const
-{
- p.i = p.p->U::prevList;
- if(p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::hasNext(const Ptr<T> & p) const
-{
- return p.p->U::nextList != RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLFifoListImpl<P,T,U>::hasPrev(const Ptr<T> & p) const
-{
- return p.p->U::prevList != RNIL;
-}
-
-// Specializations
-
-template <typename T, typename U = T>
-class DLFifoList : public DLFifoListImpl<ArrayPool<T>, T, U>
-{
-public:
- DLFifoList(ArrayPool<T> & p) : DLFifoListImpl<ArrayPool<T>, T, U>(p) {}
-};
-
-template <typename T, typename U = T>
-class LocalDLFifoList : public LocalDLFifoListImpl<ArrayPool<T>,T,U> {
-public:
- LocalDLFifoList(ArrayPool<T> & p, typename DLFifoList<T,U>::Head & _src)
- : LocalDLFifoListImpl<ArrayPool<T>,T,U>(p, _src) {}
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/DLHashTable.hpp b/storage/ndb/src/kernel/vm/DLHashTable.hpp
deleted file mode 100644
index 1accadc1749..00000000000
--- a/storage/ndb/src/kernel/vm/DLHashTable.hpp
+++ /dev/null
@@ -1,519 +0,0 @@
-/* Copyright (c) 2003-2006, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DL_HASHTABLE_HPP
-#define DL_HASHTABLE_HPP
-
-#include <ndb_global.h>
-#include "ArrayPool.hpp"
-
-/**
- * DLHashTable implements a hashtable using chaining
- * (with a double linked list)
- *
- * The entries in the hashtable must have the following methods:
- * -# bool equal(const class T &) const;
- * Which should return equal if the to objects have the same key
- * -# Uint32 hashValue() const;
- * Which should return a 32 bit hashvalue
- */
-template <typename P, typename T, typename U = T>
-class DLHashTableImpl
-{
-public:
- DLHashTableImpl(P & thePool);
- ~DLHashTableImpl();
-
- /**
- * Set the no of bucket in the hashtable
- *
- * Note, can currently only be called once
- */
- bool setSize(Uint32 noOfElements);
-
- /**
- * Seize element from pool - return i
- *
- * Note *must* be added using <b>add</b> (even before hash.release)
- * or be released using pool
- */
- bool seize(Ptr<T> &);
-
- /**
- * Add an object to the hashtable
- */
- void add(Ptr<T> &);
-
- /**
- * Find element key in hashtable update Ptr (i & p)
- * (using key.equal(...))
- * @return true if found and false otherwise
- */
- bool find(Ptr<T> &, const T & key) const;
-
- /**
- * Update i & p value according to <b>i</b>
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
- /**
- * Get element using ptr.i (update ptr.p)
- */
- void getPtr(Ptr<T> &) const;
-
- /**
- * Get P value for i
- */
- T * getPtr(Uint32 i) const;
-
- /**
- * Remove element (and set Ptr to removed element)
- * Note does not return to pool
- */
- void remove(Ptr<T> &, const T & key);
-
- /**
- * Remove element
- * Note does not return to pool
- */
- void remove(Uint32 i);
-
- /**
- * Remove element
- * Note does not return to pool
- */
- void remove(Ptr<T> &);
-
- /**
- * Remove all elements, but dont return them to pool
- */
- void removeAll();
-
- /**
- * Remove element and return to pool
- */
- void release(Uint32 i);
-
- /**
- * Remove element and return to pool
- */
- void release(Ptr<T> &);
-
- class Iterator {
- public:
- Ptr<T> curr;
- Uint32 bucket;
- inline bool isNull() const { return curr.isNull();}
- inline void setNull() { curr.setNull(); }
- };
-
- /**
- * Sets curr.p according to curr.i
- */
- void getPtr(Iterator & iter) const ;
-
- /**
- * First element in bucket
- */
- bool first(Iterator & iter) const;
-
- /**
- * Next Element
- *
- * param iter - A "fully set" iterator
- */
- bool next(Iterator & iter) const;
-
- /**
- * Get next element starting from bucket
- *
- * @param bucket - Which bucket to start from
- * @param iter - An "uninitialized" iterator
- */
- bool next(Uint32 bucket, Iterator & iter) const;
-
-private:
- Uint32 mask;
- Uint32 * hashValues;
- P & thePool;
-};
-
-template <typename P, typename T, typename U>
-inline
-DLHashTableImpl<P, T, U>::DLHashTableImpl(P & _pool)
- : thePool(_pool)
-{
- mask = 0;
- hashValues = 0;
-}
-
-template <typename P, typename T, typename U>
-inline
-DLHashTableImpl<P, T, U>::~DLHashTableImpl()
-{
- if(hashValues != 0)
- delete [] hashValues;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLHashTableImpl<P, T, U>::setSize(Uint32 size)
-{
- Uint32 i = 1;
- while(i < size) i *= 2;
-
- if(mask == (i - 1))
- {
- /**
- * The size is already set to <b>size</b>
- */
- return true;
- }
-
- if(mask != 0)
- {
- /**
- * The mask is already set
- */
- return false;
- }
-
- mask = (i - 1);
- hashValues = new Uint32[i];
- for(Uint32 j = 0; j<i; j++)
- hashValues[j] = RNIL;
-
- return true;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::add(Ptr<T> & obj)
-{
- const Uint32 hv = obj.p->hashValue() & mask;
- const Uint32 i = hashValues[hv];
-
- if(i == RNIL)
- {
- hashValues[hv] = obj.i;
- obj.p->U::nextHash = RNIL;
- obj.p->U::prevHash = RNIL;
- }
- else
- {
- T * tmp = thePool.getPtr(i);
- tmp->U::prevHash = obj.i;
- obj.p->U::nextHash = i;
- obj.p->U::prevHash = RNIL;
-
- hashValues[hv] = obj.i;
- }
-}
-
-/**
- * First element
- */
-template <typename P, typename T, typename U>
-inline
-bool
-DLHashTableImpl<P, T, U>::first(Iterator & iter) const
-{
- Uint32 i = 0;
- while(i <= mask && hashValues[i] == RNIL) i++;
- if(i <= mask)
- {
- iter.bucket = i;
- iter.curr.i = hashValues[i];
- iter.curr.p = thePool.getPtr(iter.curr.i);
- return true;
- }
- else
- {
- iter.curr.i = RNIL;
- }
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLHashTableImpl<P, T, U>::next(Iterator & iter) const
-{
- if(iter.curr.p->U::nextHash == RNIL)
- {
- Uint32 i = iter.bucket + 1;
- while(i <= mask && hashValues[i] == RNIL) i++;
- if(i <= mask)
- {
- iter.bucket = i;
- iter.curr.i = hashValues[i];
- iter.curr.p = thePool.getPtr(iter.curr.i);
- return true;
- }
- else
- {
- iter.curr.i = RNIL;
- return false;
- }
- }
-
- iter.curr.i = iter.curr.p->U::nextHash;
- iter.curr.p = thePool.getPtr(iter.curr.i);
- return true;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::remove(Ptr<T> & ptr, const T & key)
-{
- const Uint32 hv = key.hashValue() & mask;
-
- Uint32 i;
- T * p;
- Ptr<T> prev;
- LINT_INIT(prev.p);
- prev.i = RNIL;
-
- i = hashValues[hv];
- while(i != RNIL)
- {
- p = thePool.getPtr(i);
- if(key.equal(* p))
- {
- const Uint32 next = p->U::nextHash;
- if(prev.i == RNIL)
- {
- hashValues[hv] = next;
- }
- else
- {
- prev.p->U::nextHash = next;
- }
-
- if(next != RNIL)
- {
- T * nextP = thePool.getPtr(next);
- nextP->U::prevHash = prev.i;
- }
-
- ptr.i = i;
- ptr.p = p;
- return;
- }
- prev.p = p;
- prev.i = i;
- i = p->U::nextHash;
- }
- ptr.i = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::remove(Uint32 i)
-{
- Ptr<T> tmp;
- tmp.i = i;
- tmp.p = thePool.getPtr(i);
- remove(tmp);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::release(Uint32 i)
-{
- Ptr<T> tmp;
- tmp.i = i;
- tmp.p = thePool.getPtr(i);
- release(tmp);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::remove(Ptr<T> & ptr)
-{
- const Uint32 next = ptr.p->U::nextHash;
- const Uint32 prev = ptr.p->U::prevHash;
-
- if(prev != RNIL)
- {
- T * prevP = thePool.getPtr(prev);
- prevP->U::nextHash = next;
- }
- else
- {
- const Uint32 hv = ptr.p->hashValue() & mask;
- if (hashValues[hv] == ptr.i)
- {
- hashValues[hv] = next;
- }
- else
- {
- // Will add assert in 5.1
- }
- }
-
- if(next != RNIL)
- {
- T * nextP = thePool.getPtr(next);
- nextP->U::prevHash = prev;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::release(Ptr<T> & ptr)
-{
- const Uint32 next = ptr.p->U::nextHash;
- const Uint32 prev = ptr.p->U::prevHash;
-
- if(prev != RNIL)
- {
- T * prevP = thePool.getPtr(prev);
- prevP->U::nextHash = next;
- }
- else
- {
- const Uint32 hv = ptr.p->hashValue() & mask;
- if (hashValues[hv] == ptr.i)
- {
- hashValues[hv] = next;
- }
- else
- {
- // Will add assert in 5.1
- }
- }
-
- if(next != RNIL)
- {
- T * nextP = thePool.getPtr(next);
- nextP->U::prevHash = prev;
- }
-
- thePool.release(ptr);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::removeAll()
-{
- for(Uint32 i = 0; i<=mask; i++)
- hashValues[i] = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLHashTableImpl<P, T, U>::next(Uint32 bucket, Iterator & iter) const
-{
- while (bucket <= mask && hashValues[bucket] == RNIL)
- bucket++;
-
- if (bucket > mask)
- {
- iter.bucket = bucket;
- iter.curr.i = RNIL;
- return false;
- }
-
- iter.bucket = bucket;
- iter.curr.i = hashValues[bucket];
- iter.curr.p = thePool.getPtr(iter.curr.i);
- return true;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLHashTableImpl<P, T, U>::seize(Ptr<T> & ptr)
-{
- if(thePool.seize(ptr)){
- ptr.p->U::nextHash = ptr.p->U::prevHash = RNIL;
- return true;
- }
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::getPtr(Ptr<T> & ptr, Uint32 i) const
-{
- ptr.i = i;
- ptr.p = thePool.getPtr(i);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLHashTableImpl<P, T, U>::getPtr(Ptr<T> & ptr) const
-{
- thePool.getPtr(ptr);
-}
-
-template <typename P, typename T, typename U>
-inline
-T *
-DLHashTableImpl<P, T, U>::getPtr(Uint32 i) const
-{
- return thePool.getPtr(i);
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLHashTableImpl<P, T, U>::find(Ptr<T> & ptr, const T & key) const
-{
- const Uint32 hv = key.hashValue() & mask;
-
- Uint32 i;
- T * p;
-
- i = hashValues[hv];
- while(i != RNIL)
- {
- p = thePool.getPtr(i);
- if(key.equal(* p))
- {
- ptr.i = i;
- ptr.p = p;
- return true;
- }
- i = p->U::nextHash;
- }
- ptr.i = RNIL;
- ptr.p = NULL;
- return false;
-}
-
-// Specializations
-
-template <typename T, typename U = T>
-class DLHashTable : public DLHashTableImpl<ArrayPool<T>, T, U>
-{
-public:
- DLHashTable(ArrayPool<T> & p) : DLHashTableImpl<ArrayPool<T>, T, U>(p) {}
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/DLHashTable2.hpp b/storage/ndb/src/kernel/vm/DLHashTable2.hpp
deleted file mode 100644
index 85567bfc9bd..00000000000
--- a/storage/ndb/src/kernel/vm/DLHashTable2.hpp
+++ /dev/null
@@ -1,515 +0,0 @@
-/* Copyright (c) 2003-2006, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DL_HASHTABLE2_HPP
-#define DL_HASHTABLE2_HPP
-
-#include <ndb_global.h>
-#include "ArrayPool.hpp"
-
-/**
- * DLHashTable2 is a DLHashTable variant meant for cases where different
- * DLHashTable instances share a common pool (based on a union U).
- *
- * Calls T constructor after seize from pool and T destructor before
- * release (in all forms) into pool.
- */
-template <class T, class U>
-class DLHashTable2 {
-public:
- DLHashTable2(ArrayPool<U> & thePool);
- ~DLHashTable2();
-
- /**
- * Set the no of bucket in the hashtable
- *
- * Note, can currently only be called once
- */
- bool setSize(Uint32 noOfElements);
-
- /**
- * Seize element from pool - return i
- *
- * Note *must* be added using <b>add</b> (even before hash.release)
- * or be released using pool
- */
- bool seize(Ptr<T> &);
-
- /**
- * Add an object to the hashtable
- */
- void add(Ptr<T> &);
-
- /**
- * Find element key in hashtable update Ptr (i & p)
- * (using key.equal(...))
- * @return true if found and false otherwise
- */
- bool find(Ptr<T> &, const T & key) const;
-
- /**
- * Update i & p value according to <b>i</b>
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
- /**
- * Get element using ptr.i (update ptr.p)
- */
- void getPtr(Ptr<T> &) const;
-
- /**
- * Get P value for i
- */
- T * getPtr(Uint32 i) const;
-
- /**
- * Remove element (and set Ptr to removed element)
- * Note does not return to pool
- */
- void remove(Ptr<T> &, const T & key);
-
- /**
- * Remove element
- * Note does not return to pool
- */
- void remove(Uint32 i);
-
- /**
- * Remove element
- * Note does not return to pool
- */
- void remove(Ptr<T> &);
-
- /**
- * Remove all elements, but dont return them to pool
- */
- void removeAll();
-
- /**
- * Remove element (and set Ptr to removed element)
- * And return element to pool
- */
- void release(Ptr<T> &, const T & key);
-
- /**
- * Remove element and return to pool
- */
- void release(Uint32 i);
-
- /**
- * Remove element and return to pool
- */
- void release(Ptr<T> &);
-
- class Iterator {
- public:
- Ptr<T> curr;
- Uint32 bucket;
- inline bool isNull() const { return curr.isNull();}
- inline void setNull() { curr.setNull(); }
- };
-
- /**
- * Sets curr.p according to curr.i
- */
- void getPtr(Iterator & iter) const ;
-
- /**
- * First element in bucket
- */
- bool first(Iterator & iter) const;
-
- /**
- * Next Element
- *
- * param iter - A "fully set" iterator
- */
- bool next(Iterator & iter) const;
-
- /**
- * Get next element starting from bucket
- *
- * @param bucket - Which bucket to start from
- * @param iter - An "uninitialized" iterator
- */
- bool next(Uint32 bucket, Iterator & iter) const;
-
- inline bool isEmpty() const { Iterator iter; return ! first(iter); }
-
-private:
- Uint32 mask;
- Uint32 * hashValues;
- ArrayPool<U> & thePool;
-};
-
-template<class T, class U>
-inline
-DLHashTable2<T, U>::DLHashTable2(ArrayPool<U> & _pool)
- : thePool(_pool)
-{
- mask = 0;
- hashValues = 0;
-}
-
-template<class T, class U>
-inline
-DLHashTable2<T, U>::~DLHashTable2(){
- if(hashValues != 0)
- delete [] hashValues;
-}
-
-template<class T, class U>
-inline
-bool
-DLHashTable2<T, U>::setSize(Uint32 size){
- Uint32 i = 1;
- while(i < size) i *= 2;
-
- if(mask == (i - 1)){
- /**
- * The size is already set to <b>size</b>
- */
- return true;
- }
-
- if(mask != 0){
- /**
- * The mask is already set
- */
- return false;
- }
-
- mask = (i - 1);
- hashValues = new Uint32[i];
- for(Uint32 j = 0; j<i; j++)
- hashValues[j] = RNIL;
-
- return true;
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::add(Ptr<T> & obj){
- const Uint32 hv = obj.p->hashValue() & mask;
- const Uint32 i = hashValues[hv];
-
- if(i == RNIL){
- hashValues[hv] = obj.i;
- obj.p->nextHash = RNIL;
- obj.p->prevHash = RNIL;
- } else {
-
- T * tmp = (T*)thePool.getPtr(i); // cast
- tmp->prevHash = obj.i;
- obj.p->nextHash = i;
- obj.p->prevHash = RNIL;
-
- hashValues[hv] = obj.i;
- }
-}
-
-/**
- * First element
- */
-template<class T, class U>
-inline
-bool
-DLHashTable2<T, U>::first(Iterator & iter) const {
- Uint32 i = 0;
- while(i <= mask && hashValues[i] == RNIL) i++;
- if(i <= mask){
- iter.bucket = i;
- iter.curr.i = hashValues[i];
- iter.curr.p = (T*)thePool.getPtr(iter.curr.i); // cast
- return true;
- } else {
- iter.curr.i = RNIL;
- }
- return false;
-}
-
-template<class T, class U>
-inline
-bool
-DLHashTable2<T, U>::next(Iterator & iter) const {
- if(iter.curr.p->nextHash == RNIL){
- Uint32 i = iter.bucket + 1;
- while(i <= mask && hashValues[i] == RNIL) i++;
- if(i <= mask){
- iter.bucket = i;
- iter.curr.i = hashValues[i];
- iter.curr.p = (T*)thePool.getPtr(iter.curr.i); // cast
- return true;
- } else {
- iter.curr.i = RNIL;
- return false;
- }
- }
-
- iter.curr.i = iter.curr.p->nextHash;
- iter.curr.p = (T*)thePool.getPtr(iter.curr.i); // cast
- return true;
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::remove(Ptr<T> & ptr, const T & key){
- const Uint32 hv = key.hashValue() & mask;
-
- Uint32 i;
- T * p;
- Ptr<T> prev;
- prev.i = RNIL;
-
- i = hashValues[hv];
- while(i != RNIL){
- p = (T*)thePool.getPtr(i); // cast
- if(key.equal(* p)){
- const Uint32 next = p->nextHash;
- if(prev.i == RNIL){
- hashValues[hv] = next;
- } else {
- prev.p->nextHash = next;
- }
-
- if(next != RNIL){
- T * nextP = (T*)thePool.getPtr(next); // cast
- nextP->prevHash = prev.i;
- }
-
- ptr.i = i;
- ptr.p = p;
- return;
- }
- prev.p = p;
- prev.i = i;
- i = p->nextHash;
- }
- ptr.i = RNIL;
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::release(Ptr<T> & ptr, const T & key){
- const Uint32 hv = key.hashValue() & mask;
-
- Uint32 i;
- T * p;
- Ptr<T> prev;
- prev.i = RNIL;
-
- i = hashValues[hv];
- while(i != RNIL){
- p = (T*)thePool.getPtr(i); // cast
- if(key.equal(* p)){
- const Uint32 next = p->nextHash;
- if(prev.i == RNIL){
- hashValues[hv] = next;
- } else {
- prev.p->nextHash = next;
- }
-
- if(next != RNIL){
- T * nextP = (T*)thePool.getPtr(next); // cast
- nextP->prevHash = prev.i;
- }
-
- p->~T(); // dtor
- thePool.release(i);
- ptr.i = i;
- ptr.p = p; // invalid
- return;
- }
- prev.p = p;
- prev.i = i;
- i = p->nextHash;
- }
- ptr.i = RNIL;
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::remove(Uint32 i){
- Ptr<T> tmp;
- tmp.i = i;
- tmp.p = (T*)thePool.getPtr(i); // cast
- remove(tmp);
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::release(Uint32 i){
- Ptr<T> tmp;
- tmp.i = i;
- tmp.p = (T*)thePool.getPtr(i); // cast
- release(tmp);
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::remove(Ptr<T> & ptr){
- const Uint32 next = ptr.p->nextHash;
- const Uint32 prev = ptr.p->prevHash;
-
- if(prev != RNIL){
- T * prevP = (T*)thePool.getPtr(prev); // cast
- prevP->nextHash = next;
- } else {
- const Uint32 hv = ptr.p->hashValue() & mask;
- if (hashValues[hv] == ptr.i)
- {
- hashValues[hv] = next;
- }
- else
- {
- // Will add assert in 5.1
- }
- }
-
- if(next != RNIL){
- T * nextP = (T*)thePool.getPtr(next); // cast
- nextP->prevHash = prev;
- }
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::release(Ptr<T> & ptr){
- const Uint32 next = ptr.p->nextHash;
- const Uint32 prev = ptr.p->prevHash;
-
- if(prev != RNIL){
- T * prevP = (T*)thePool.getPtr(prev); // cast
- prevP->nextHash = next;
- } else {
- const Uint32 hv = ptr.p->hashValue() & mask;
- if (hashValues[hv] == ptr.i)
- {
- hashValues[hv] = next;
- }
- else
- {
- // Will add assert in 5.1
- }
- }
-
- if(next != RNIL){
- T * nextP = (T*)thePool.getPtr(next); // cast
- nextP->prevHash = prev;
- }
-
- thePool.release(ptr.i);
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::removeAll(){
- for(Uint32 i = 0; i<=mask; i++)
- hashValues[i] = RNIL;
-}
-
-template<class T, class U>
-inline
-bool
-DLHashTable2<T, U>::next(Uint32 bucket, Iterator & iter) const {
- while (bucket <= mask && hashValues[bucket] == RNIL)
- bucket++;
-
- if (bucket > mask) {
- iter.bucket = bucket;
- iter.curr.i = RNIL;
- return false;
- }
-
- iter.bucket = bucket;
- iter.curr.i = hashValues[bucket];
- iter.curr.p = (T*)thePool.getPtr(iter.curr.i); // cast
- return true;
-}
-
-template<class T, class U>
-inline
-bool
-DLHashTable2<T, U>::seize(Ptr<T> & ptr){
- Ptr<U> ptr2;
- thePool.seize(ptr2);
- ptr.i = ptr2.i;
- ptr.p = (T*)ptr2.p; // cast
- if (ptr.p != NULL){
- ptr.p->nextHash = RNIL;
- ptr.p->prevHash = RNIL;
- new (ptr.p) T; // ctor
- }
- return !ptr.isNull();
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::getPtr(Ptr<T> & ptr, Uint32 i) const {
- ptr.i = i;
- ptr.p = (T*)thePool.getPtr(i); // cast
-}
-
-template<class T, class U>
-inline
-void
-DLHashTable2<T, U>::getPtr(Ptr<T> & ptr) const {
- Ptr<U> ptr2;
- thePool.getPtr(ptr2);
- ptr.i = ptr2.i;
- ptr.p = (T*)ptr2.p; // cast
-}
-
-template<class T, class U>
-inline
-T *
-DLHashTable2<T, U>::getPtr(Uint32 i) const {
- return (T*)thePool.getPtr(i); // cast
-}
-
-template<class T, class U>
-inline
-bool
-DLHashTable2<T, U>::find(Ptr<T> & ptr, const T & key) const {
- const Uint32 hv = key.hashValue() & mask;
-
- Uint32 i;
- T * p;
-
- i = hashValues[hv];
- while(i != RNIL){
- p = (T*)thePool.getPtr(i); // cast
- if(key.equal(* p)){
- ptr.i = i;
- ptr.p = p;
- return true;
- }
- i = p->nextHash;
- }
- ptr.i = RNIL;
- ptr.p = NULL;
- return false;
-}
-#endif
diff --git a/storage/ndb/src/kernel/vm/DLList.hpp b/storage/ndb/src/kernel/vm/DLList.hpp
deleted file mode 100644
index f691ae8ad26..00000000000
--- a/storage/ndb/src/kernel/vm/DLList.hpp
+++ /dev/null
@@ -1,438 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DLLIST_HPP
-#define DLLIST_HPP
-
-#include "ArrayPool.hpp"
-
-/**
- * Template class used for implementing an
- * list of object retreived from a pool
- */
-template <typename P, typename T, typename U = T>
-class DLListImpl
-{
-public:
- /**
- * List head
- */
- struct HeadPOD {
- Uint32 firstItem;
- inline bool isEmpty() const { return firstItem == RNIL; }
- inline void init () { firstItem = RNIL; }
- };
-
- struct Head : public HeadPOD
- {
- Head();
- Head& operator=(const HeadPOD& src) {
- this->firstItem = src.firstItem;
- return *this;
- }
- };
-
- DLListImpl(P& thePool);
-
- /**
- * Allocate an object from pool - update Ptr
- *
- * Return i
- */
- bool seize(Ptr<T> &);
-
- /**
- * Allocate object <b>i</b> from pool - update Ptr
- *
- * Return i
- */
- bool seizeId(Ptr<T> &, Uint32 i);
-
- /**
- * Check if <b>i</b> is allocated.
- */
- bool findId(Uint32 i) const;
-
- /**
- * Return an object to pool
- */
- void release(Uint32 i);
-
- /**
- * Return an object to pool
- */
- void release(Ptr<T> &);
-
- /**
- * Return all objects to the pool
- */
- void release();
-
- /**
- * Remove all objects from list
- */
- void remove();
-
- /**
- * Add object to list
- *
- * @NOTE MUST be seized from correct pool
- */
- void add(Ptr<T> &);
-
- /**
- * Add a list to list
- * @NOTE all elements _must_ be correctly initilized correctly wrt next/prev
- */
- void add(Uint32 first, Ptr<T> & last);
-
- /**
- * Remove object from list
- *
- * @NOTE Does not return it to pool
- */
- void remove(Ptr<T> &);
-
- /**
- * Remove object from list
- *
- * @NOTE Does not return it to pool
- */
- void remove(T*);
-
- /**
- * Update i & p value according to <b>i</b>
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &) const ;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i) const ;
-
- /**
- * Update ptr to first element in list
- *
- * @return True if element exists, false otherwise
- */
- bool first(Ptr<T> &) const ;
-
- /**
- * Get next element
- *
- * @note ptr must have both p & i values
- *
- * @return True if element exists, false otherwise
- */
- bool next(Ptr<T> &) const ;
-
- /**
- * Check if next exists
- *
- * @note ptr must have both p & i values
- * @return True if element exists, false otherwise
- */
- bool hasNext(const Ptr<T> &) const;
-
- inline bool isEmpty() const { return head.firstItem == RNIL;}
-
-protected:
- Head head;
- P & thePool;
-};
-
-template <typename P, typename T, typename U = T>
-class LocalDLListImpl : public DLListImpl<P,T,U>
-{
-public:
- LocalDLListImpl(P & thePool, typename DLListImpl<P,T,U>::HeadPOD & _src)
- : DLListImpl<P,T,U>(thePool), src(_src)
- {
- this->head = src;
- }
-
- ~LocalDLListImpl(){
- src = this->head;
- }
-private:
- typename DLListImpl<P,T,U>::HeadPOD & src;
-};
-
-template <typename P, typename T, typename U>
-inline
-DLListImpl<P,T,U>::DLListImpl(P & _pool)
- : thePool(_pool)
-{
-}
-
-template <typename P, typename T, typename U>
-inline
-DLListImpl<P,T,U>::Head::Head()
-{
- this->init();
-}
-
-/**
- * Allocate an object from pool - update Ptr
- *
- * Return i
- */
-template <typename P, typename T, typename U>
-inline
-bool
-DLListImpl<P,T,U>::seize(Ptr<T> & p)
-{
- if (likely(thePool.seize(p)))
- {
- add(p);
- return true;
- }
- return false;
-}
-
-/**
- * Allocate an object from pool - update Ptr
- *
- * Return i
- */
-template <typename P, typename T, typename U>
-inline
-bool
-DLListImpl<P,T,U>::seizeId(Ptr<T> & p, Uint32 ir)
-{
- if (likely(thePool.seizeId(p, ir)))
- {
- add(p);
- return true;
- }
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLListImpl<P,T,U>::findId(Uint32 i) const
-{
- return thePool.findId(i);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::add(Ptr<T> & p)
-{
- T * t = p.p;
- Uint32 ff = head.firstItem;
-
- t->U::nextList = ff;
- t->U::prevList = RNIL;
- head.firstItem = p.i;
-
- if(ff != RNIL)
- {
- T * t2 = thePool.getPtr(ff);
- t2->U::prevList = p.i;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::add(Uint32 first, Ptr<T> & lastPtr)
-{
- Uint32 ff = head.firstItem;
-
- head.firstItem = first;
- lastPtr.p->U::nextList = ff;
-
- if(ff != RNIL)
- {
- T * t2 = thePool.getPtr(ff);
- t2->U::prevList = lastPtr.i;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::remove(Ptr<T> & p)
-{
- remove(p.p);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::remove(T * p)
-{
- T * t = p;
- Uint32 ni = t->U::nextList;
- Uint32 pi = t->U::prevList;
-
- if(ni != RNIL){
- T * tn = thePool.getPtr(ni);
- tn->U::prevList = pi;
- }
-
- if(pi != RNIL){
- T * tp = thePool.getPtr(pi);
- tp->U::nextList = ni;
- } else {
- head.firstItem = ni;
- }
-}
-
-/**
- * Return an object to pool
- */
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::release(Uint32 i)
-{
- Ptr<T> p;
- p.i = i;
- p.p = thePool.getPtr(i);
- release(p);
-}
-
-/**
- * Return an object to pool
- */
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::release(Ptr<T> & p)
-{
- remove(p);
- thePool.release(p);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::release()
-{
- Ptr<T> ptr;
- Uint32 curr = head.firstItem;
- while(curr != RNIL)
- {
- thePool.getPtr(ptr, curr);
- curr = ptr.p->U::nextList;
- thePool.release(ptr);
- }
- head.firstItem = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::remove()
-{
- head.firstItem = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::getPtr(Ptr<T> & p, Uint32 i) const
-{
- p.i = i;
- p.p = thePool.getPtr(i);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-DLListImpl<P,T,U>::getPtr(Ptr<T> & p) const
-{
- thePool.getPtr(p);
-}
-
-template <typename P, typename T, typename U>
-inline
-T *
-DLListImpl<P,T,U>::getPtr(Uint32 i) const
-{
- return thePool.getPtr(i);
-}
-
-/**
- * Update ptr to first element in list
- *
- * Return i
- */
-template <typename P, typename T, typename U>
-inline
-bool
-DLListImpl<P,T,U>::first(Ptr<T> & p) const
-{
- Uint32 i = head.firstItem;
- p.i = i;
- if(i != RNIL)
- {
- p.p = thePool.getPtr(i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLListImpl<P,T,U>::next(Ptr<T> & p) const
-{
- Uint32 i = p.p->U::nextList;
- p.i = i;
- if(i != RNIL){
- p.p = thePool.getPtr(i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-DLListImpl<P,T,U>::hasNext(const Ptr<T> & p) const
-{
- return p.p->U::nextList != RNIL;
-}
-
-// Specializations
-
-template <typename T, typename U = T>
-class DLList : public DLListImpl<ArrayPool<T>, T, U>
-{
-public:
- DLList(ArrayPool<T> & p) : DLListImpl<ArrayPool<T>, T, U>(p) {}
-};
-
-template <typename T, typename U = T>
-class LocalDLList : public LocalDLListImpl<ArrayPool<T>, T, U> {
-public:
- LocalDLList(ArrayPool<T> & p, typename DLList<T,U>::HeadPOD & _src)
- : LocalDLListImpl<ArrayPool<T>, T, U>(p, _src) {}
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/DataBuffer.hpp b/storage/ndb/src/kernel/vm/DataBuffer.hpp
deleted file mode 100644
index a1956229d8b..00000000000
--- a/storage/ndb/src/kernel/vm/DataBuffer.hpp
+++ /dev/null
@@ -1,533 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DATA_BUFFER_HPP
-#define DATA_BUFFER_HPP
-
-#include "ArrayPool.hpp"
-
-/**
- * @class DataBuffer
- * @brief Buffer of data words
- *
- * @note The buffer is divided into segments (of size sz)
- */
-template <Uint32 sz>
-class DataBuffer {
-public:
- struct Segment {
- Uint32 nextPool;
- Uint32 data[sz];
- NdbOut& print(NdbOut& out){
- out << "[DataBuffer<" << sz << ">::Segment this="
- << this << dec << " nextPool= "
- << nextPool << " ]";
- return out;
- }
- };
-public:
- typedef ArrayPool<Segment> DataBufferPool;
-
- /**
- * Head/anchor for data buffer
- */
- struct Head {
- Head() ;
-
- Uint32 used; // Words used
- Uint32 firstItem; // First segment (or RNIL)
- Uint32 lastItem; // Last segment (or RNIL)
-
- /**
- * Get size of databuffer, in words
- */
- Uint32 getSize() const { return used;}
-
- /**
- * Get segment size in words (template argument)
- */
- static Uint32 getSegmentSize() { return sz;}
- };
-
- /** Constructor */
- DataBuffer(DataBufferPool &);
-
- /** Seize <b>n</b> words, Release */
- bool seize(Uint32 n);
- void release();
-
- /**
- * Get size of databuffer, in words
- */
- Uint32 getSize() const;
-
- /**
- * Check if buffer is empty
- */
- bool isEmpty() const;
-
- /**
- * Get segment size in words (template argument)
- */
- static Uint32 getSegmentSize();
-
- void print(FILE*) const;
-
- /* ----------------------------------------------------------------------- */
-
- struct DataBufferIterator {
- Ptr<Segment> curr; // Ptr to current segment
- Uint32* data; // Pointer to current data (word)
- Uint32 ind; // Word index within a segment
- Uint32 pos; // Absolute word position within DataBuffer
-
- void print(FILE* out) {
- fprintf(out, "[DataBufferIterator curr.i=%d, data=%p, ind=%d, pos=%d]\n",
- curr.i, (void*) data, ind, pos);
- };
-
- inline bool isNull() const { return curr.isNull();}
- inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
- };
- typedef DataBufferIterator Iterator;
-
- struct ConstDataBufferIterator {
- ConstPtr<Segment> curr;
- const Uint32 * data;
- Uint32 ind;
- Uint32 pos;
-
- inline bool isNull() const { return curr.isNull();}
- inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
- };
-
- /**
- * Iterator
- * @parameter hops Number of words to jump forward
- * @note DataBuffer::next returns false if applied to last word.
- */
- bool first(DataBufferIterator &);
- bool next(DataBufferIterator &);
- bool next(DataBufferIterator &, Uint32 hops);
- bool nextPool(DataBufferIterator &);
-
- /**
- * Set iterator to position
- */
- bool position(DataBufferIterator& it, Uint32 pos);
-
- /** Iterator */
- bool first(ConstDataBufferIterator &) const;
- bool next(ConstDataBufferIterator &) const;
- bool next(ConstDataBufferIterator &, Uint32 hops) const;
- bool nextPool(ConstDataBufferIterator &) const;
-
- /**
- * Returns true if it is possible to store <em>len</em>
- * no of words at position given in iterator.
- */
- bool importable(const DataBufferIterator, Uint32 len);
-
- /**
- * Stores <em>len</em> no of words starting at location <em>src</em> in
- * databuffer at position given in iterator.
- *
- * @return true if success, false otherwise.
- * @note Iterator is not advanced.
- */
- bool import(const DataBufferIterator &, const Uint32* src, Uint32 len);
-
- /**
- * Increases size with appends <em>len</em> words
- * @return true if success, false otherwise.
- */
- bool append(const Uint32* src, Uint32 len);
-
-protected:
- Head head;
- DataBufferPool & thePool;
-
-private:
- /**
- * This is NOT a public method, since the intension is that the import
- * method using iterators will be more effective in the future
- */
- bool import(Uint32 pos, const Uint32* src, Uint32 len);
-};
-
-template<Uint32 sz>
-class LocalDataBuffer : public DataBuffer<sz> {
-public:
- LocalDataBuffer(typename DataBuffer<sz>::DataBufferPool & thePool,
- typename DataBuffer<sz>::Head & _src)
- : DataBuffer<sz>(thePool), src(_src)
- {
- this->head = src;
- }
-
- ~LocalDataBuffer(){
- src = this->head;
- }
-private:
- typename DataBuffer<sz>::Head & src;
-};
-
-template<Uint32 sz>
-inline
-DataBuffer<sz>::Head::Head(){
- used = 0;
- firstItem = RNIL;
- lastItem = RNIL;
-}
-
-template<Uint32 sz>
-inline
-bool DataBuffer<sz>::importable(const DataBufferIterator it, Uint32 len){
- return (it.pos + len < head.used);
-}
-
-template<Uint32 sz>
-inline
-bool DataBuffer<sz>::position(DataBufferIterator& it, Uint32 p){
-
- // TODO: The current implementation is not the most effective one.
- // A more effective implementation would start at the current
- // position of the iterator.
-
- if(!first(it)){
- return false;
- }
- return next(it, p);
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::import(const DataBufferIterator & it,
- const Uint32* src, Uint32 len){
-
-#if 0
- DataBufferIterator it;
- position(it, _it.pos);
-
- for(; len > 0; len--){
- Uint32 s = * src;
- * it.data = s;
- next(it);
- src++;
- }
- return true;
-#else
- Uint32 ind = (it.pos % sz);
- Uint32 left = sz - ind;
- Segment * p = it.curr.p;
-
- while(len > left){
- memcpy(&p->data[ind], src, 4 * left);
- src += left;
- len -= left;
- ind = 0;
- left = sz;
- p = thePool.getPtr(p->nextPool);
- }
-
- memcpy(&p->data[ind], src, 4 * len);
- return true;
-#endif
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::append(const Uint32* src, Uint32 len){
- if(len == 0)
- return true;
-
- Uint32 pos = head.used;
- if(!seize(len)){
- return false;
- }
- DataBufferIterator it;
-
- if(position(it, pos) && import(it, src, len)){
- return true;
- }
- abort();
- return false;
-}
-
-template<Uint32 sz>
-inline
-void DataBuffer<sz>::print(FILE* out) const {
- fprintf(out, "[DataBuffer used=%d words, segmentsize=%d words",
- head.used, sz);
-
- if (head.firstItem == RNIL) {
- fprintf(out, ": No segments seized.]\n");
- return;
- } else {
- fprintf(out, "\n");
- }
-
- Ptr<Segment> ptr;
- ptr.i = head.firstItem;
-
- Uint32 acc = 0;
- for(; ptr.i != RNIL; ){
- thePool.getPtr(ptr);
- const Uint32 * rest = ptr.p->data;
- for(Uint32 i = 0; i<sz; i++){
- fprintf(out, " H'%.8x", rest[i]);
- if(acc++ == 6){
- acc = 0;
- fprintf(out, "\n");
- }
- }
- ptr.i = ptr.p->nextPool;
- }
- fprintf(out, " ]\n");
-}
-
-template<Uint32 sz>
-inline
-DataBuffer<sz>::DataBuffer(DataBufferPool & p) : thePool(p){
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::seize(Uint32 n){
- Uint32 rest; // Free space in last segment (currently)
- Segment* prevPtr;
-
- if(head.firstItem == RNIL){
- rest = 0;
- prevPtr = (Segment*)&head.firstItem;
- } else {
- rest = (sz - (head.used % sz)) % sz;
- prevPtr = thePool.getPtr(head.lastItem);
- }
-
- /**
- * Check for space
- */
- Uint32 free = thePool.getNoOfFree() * sz + rest;
- if(n > free){
- release();
- return false;
- }
-
- Uint32 used = head.used + n;
- Ptr<Segment> currPtr;
- currPtr.i = head.lastItem;
-
- while(n >= sz){
- if(0)
- ndbout_c("n(%d) %c sz(%d)", n, (n>sz?'>':(n<sz?'<':'=')), sz);
-
- thePool.seize(currPtr); assert(currPtr.i != RNIL);
- prevPtr->nextPool = currPtr.i;
-
- prevPtr = currPtr.p;
- prevPtr->nextPool = RNIL;
- n -= sz;
- }
-
- if(0){
- Uint32 pos = rest + n;
- ndbout_c("rest(%d), n(%d) pos=%d %c sz(%d)",
- rest, n, pos, (pos>sz?'>':(pos<sz?'<':'=')), sz);
- }
-
- if(n > rest){
- thePool.seize(currPtr);
- assert(currPtr.i != RNIL);
- prevPtr->nextPool = currPtr.i;
- currPtr.p->nextPool = RNIL;
- }
-
- head.used = used;
- head.lastItem = currPtr.i;
-
-#if 0
- {
- ndbout_c("Before validate - %d", head.used);
- if(head.used == 0){
- assert(head.firstItem == RNIL);
- assert(head.lastItem == RNIL);
- } else {
- Ptr<Segment> tmp;
- tmp.i = head.firstItem;
- for(Uint32 i = head.used; i > sz; i -= sz){
- ndbout << tmp.i << " ";
- tmp.p = thePool.getPtr(tmp.i);
- tmp.i = tmp.p->nextPool;
- }
- ndbout_c("%d", tmp.i);
- assert(head.lastItem == tmp.i);
- }
- ndbout_c("After validate");
- }
-#endif
- return true;
-}
-
-template<Uint32 sz>
-inline
-void
-DataBuffer<sz>::release(){
- Uint32 used = head.used + sz - 1;
- if(head.firstItem != RNIL){
- thePool.releaseList(used / sz, head.firstItem, head.lastItem);
- head.used = 0;
- head.firstItem = RNIL;
- head.lastItem = RNIL;
- }
-}
-
-template<Uint32 sz>
-inline
-Uint32
-DataBuffer<sz>::getSegmentSize(){
- return sz;
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::first(DataBufferIterator & it){
- return first((ConstDataBufferIterator&)it);
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::next(DataBufferIterator & it){
- return next((ConstDataBufferIterator&)it);
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::next(DataBufferIterator & it, Uint32 hops){
- return next((ConstDataBufferIterator&)it, hops);
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::first(ConstDataBufferIterator & it) const {
- it.curr.i = head.firstItem;
- if(it.curr.i == RNIL){
- it.setNull();
- return false;
- }
- thePool.getPtr(it.curr);
- it.data = &it.curr.p->data[0];
- it.ind = 0;
- it.pos = 0;
- return true;
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::next(ConstDataBufferIterator & it) const {
- it.ind ++;
- it.data ++;
- it.pos ++;
- if(it.ind < sz && it.pos < head.used){
- return true;
- }
-
- if(it.pos < head.used){
- it.curr.i = it.curr.p->nextPool;
-#ifdef ARRAY_GUARD
- if(it.curr.i == RNIL){
- /**
- * This is actually "internal error"
- * pos can't be less than head.used and at the same time we can't
- * find next segment
- *
- * Note this must not "really" be checked since thePool.getPtr will
- * abort when trying to get RNIL. That's why the check is within
- * ARRAY_GUARD
- */
- ErrorReporter::handleAssert("DataBuffer<sz>::next", __FILE__, __LINE__);
- }
-#endif
- thePool.getPtr(it.curr);
- it.data = &it.curr.p->data[0];
- it.ind = 0;
- return true;
- }
- it.setNull();
- return false;
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::next(ConstDataBufferIterator & it, Uint32 hops) const {
-#if 0
- for (Uint32 i=0; i<hops; i++) {
- if (!this->next(it))
- return false;
- }
- return true;
-#else
- if(it.pos + hops < head.used){
- while(hops >= sz){
- it.curr.i = it.curr.p->nextPool;
- thePool.getPtr(it.curr);
- hops -= sz;
- it.pos += sz;
- }
-
- it.ind += hops;
- it.pos += hops;
- if(it.ind < sz){
- it.data = &it.curr.p->data[it.ind];
- return true;
- }
-
- it.curr.i = it.curr.p->nextPool;
- thePool.getPtr(it.curr);
- it.ind -= sz;
- it.data = &it.curr.p->data[it.ind];
- return true;
- }
- it.setNull();
- return false;
-#endif
-}
-
-template<Uint32 sz>
-inline
-Uint32
-DataBuffer<sz>::getSize() const {
- return head.used;
-}
-
-template<Uint32 sz>
-inline
-bool
-DataBuffer<sz>::isEmpty() const {
- return (head.used == 0);
-}
-
-#endif
-
diff --git a/storage/ndb/src/kernel/vm/DynArr256.cpp b/storage/ndb/src/kernel/vm/DynArr256.cpp
deleted file mode 100644
index 6f3229c085c..00000000000
--- a/storage/ndb/src/kernel/vm/DynArr256.cpp
+++ /dev/null
@@ -1,1021 +0,0 @@
-/* Copyright (c) 2003, 2006, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "DynArr256.hpp"
-#include <stdio.h>
-#include <assert.h>
-#include <NdbOut.hpp>
-
-#define DA256_BITS 5
-#define DA256_MASK 31
-
-struct DA256CL
-{
- Uint32 m_magic;
- Uint32 m_data[15];
-};
-
-struct DA256Free
-{
- Uint32 m_magic;
- Uint32 m_next_free;
-};
-
-struct DA256Node
-{
- struct DA256CL m_lines[17];
-};
-
-struct DA256Page
-{
- struct DA256CL m_header[2];
- struct DA256Node m_nodes[30];
-};
-
-#define require(x) require_impl(x, __LINE__)
-//#define DA256_USE_PX
-//#define DA256_USE_PREFETCH
-#define DA256_EXTRA_SAFE
-
-
-#ifdef UNIT_TEST
-#ifdef USE_CALLGRIND
-#include <valgrind/callgrind.h>
-#else
-#define CALLGRIND_TOGGLE_COLLECT()
-#endif
-Uint32 allocatedpages = 0;
-Uint32 allocatednodes = 0;
-Uint32 releasednodes = 0;
-#endif
-
-inline
-void
-require_impl(bool x, int line)
-{
- if (!x)
- {
- ndbout_c("LINE: %d", line);
- abort();
- }
-}
-
-DynArr256Pool::DynArr256Pool()
-{
- m_type_id = RNIL;
- m_first_free = RNIL;
- m_memroot = 0;
-}
-
-void
-DynArr256Pool::init(Uint32 type_id, const Pool_context & pc)
-{
- m_ctx = pc;
- m_type_id = type_id;
- m_memroot = (DA256Page*)m_ctx.get_memroot();
-}
-
-static const Uint32 g_max_sizes[5] = { 0, 256, 65536, 16777216, ~0 };
-
-/**
- * sz = 0 = 1 - 0 level
- * sz = 1 = 256^1 - 1 level
- * sz = 2 = 256^2 - 2 level
- * sz = 3 = 256^3 - 3 level
- * sz = 4 = 256^4 - 4 level
- */
-Uint32 *
-DynArr256::get(Uint32 pos) const
-{
- Uint32 sz = m_head.m_sz;
- Uint32 ptrI = m_head.m_ptr_i;
- DA256Page * memroot = m_pool.m_memroot;
- Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
-
- if (unlikely(pos >= g_max_sizes[sz]))
- {
- return 0;
- }
-
-#ifdef DA256_USE_PX
- Uint32 px[4] = { (pos >> 24) & 255,
- (pos >> 16) & 255,
- (pos >> 8) & 255,
- (pos >> 0) & 255 };
-#endif
-
- Uint32* retVal = &m_head.m_ptr_i;
- for(; sz --;)
- {
- if (unlikely(ptrI == RNIL))
- {
- return 0;
- }
-#ifdef DA256_USE_PX
- Uint32 p0 = px[sz];
-#else
- Uint32 shr = sz << 3;
- Uint32 p0 = (pos >> shr) & 255;
-#endif
- Uint32 page_no = ptrI >> DA256_BITS;
- Uint32 page_idx = ptrI & DA256_MASK;
- DA256Page * page = memroot + page_no;
-
- Uint32 *magic_ptr, p;
- if (p0 != 255)
- {
- Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
- Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
-
- p = 0;
- retVal = (ptr + 1 + p0 + line);
- magic_ptr =(ptr + (p0 & ~15));
- }
- else
- {
- Uint32 b = (page_idx + 1) >> 4;
- Uint32 * ptr = (Uint32*)(page->m_header+b);
-
- p = page_idx - (b << 4) + b;
- retVal = (ptr + 1 + p);
- magic_ptr = ptr;
- }
-
- ptrI = *retVal;
- Uint32 magic = *magic_ptr;
-
- if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
- goto err;
- }
-
- return retVal;
-err:
- require(false);
- return 0;
-}
-
-Uint32 *
-DynArr256::set(Uint32 pos)
-{
- Uint32 sz = m_head.m_sz;
- Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
- DA256Page * memroot = m_pool.m_memroot;
-
- if (unlikely(pos >= g_max_sizes[sz]))
- {
- if (unlikely(!expand(pos)))
- {
- return 0;
- }
- sz = m_head.m_sz;
- }
-
-#ifdef DA256_USE_PX
- Uint32 px[4] = { (pos >> 24) & 255,
- (pos >> 16) & 255,
- (pos >> 8) & 255,
- (pos >> 0) & 255 };
-#endif
-
- Uint32 ptrI = m_head.m_ptr_i;
- Uint32 *retVal = &m_head.m_ptr_i;
- for(; sz --;)
- {
-#ifdef DA256_USE_PX
- Uint32 p0 = px[sz];
-#else
- Uint32 shr = sz << 3;
- Uint32 p0 = (pos >> shr) & 255;
-#endif
- if (ptrI == RNIL)
- {
- if (unlikely((ptrI = m_pool.seize()) == RNIL))
- {
- return 0;
- }
- * retVal = ptrI;
- }
-
- Uint32 page_no = ptrI >> DA256_BITS;
- Uint32 page_idx = ptrI & DA256_MASK;
- DA256Page * page = memroot + page_no;
-
- Uint32 *magic_ptr, p;
- if (p0 != 255)
- {
- Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
- Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
-
- p = 0;
- magic_ptr = (ptr + (p0 & ~15));
- retVal = (ptr + 1 + p0 + line);
- }
- else
- {
- Uint32 b = (page_idx + 1) >> 4;
- Uint32 * ptr = (Uint32*)(page->m_header+b);
-
- p = page_idx - (b << 4) + b;
- magic_ptr = ptr;
- retVal = (ptr + 1 + p);
- }
-
- ptrI = * retVal;
- Uint32 magic = *magic_ptr;
-
- if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
- goto err;
- }
-
- return retVal;
-
-err:
- require(false);
- return 0;
-}
-
-static
-inline
-void
-initpage(DA256Page* p, Uint32 page_no, Uint32 type_id)
-{
- Uint32 i, j;
-#ifdef DA256_USE_PREFETCH
-#if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
-#ifdef DA256_EXTRA_SAFE
- for (i = 0; i<(30 * 17 + 2); i++)
- {
- __builtin_prefetch (p->m_header + i, 1);
- }
-#else
- {
- __builtin_prefetch (p->m_header + 0, 1);
- __builtin_prefetch (p->m_header + 1, 1);
- for (i = 0; i<30; i++)
- {
- __builtin_prefetch (p->m_nodes + i, 1);
- }
- }
-#endif
-#endif
-#endif
- DA256CL* cl;
- for (i = 0; i<2; i++)
- {
- cl = p->m_header + i;
- cl->m_magic = (~type_id << 16);
- }
-
- DA256Free* free;
-
- for (i = 0; i<30; i++)
- {
- free = (DA256Free*)(p->m_nodes+i);
- free->m_magic = type_id;
- free->m_next_free = (page_no << DA256_BITS) + (i + 1);
-#ifdef DA256_EXTRA_SAFE
- DA256Node* node = p->m_nodes+i;
- for (j = 0; j<17; j++)
- node->m_lines[j].m_magic = type_id;
-#endif
- }
-
- free = (DA256Free*)(p->m_nodes+29);
- free->m_next_free = RNIL;
-}
-
-bool
-DynArr256::expand(Uint32 pos)
-{
- Uint32 i;
- Uint32 idx = 0;
- Uint32 alloc[5];
- Uint32 sz = m_head.m_sz;
-
- for (; pos >= g_max_sizes[sz]; sz++);
-
- if (m_head.m_sz == 0)
- {
- m_head.m_sz = sz;
- return true;
- }
-
- sz = m_head.m_sz;
- for (; pos >= g_max_sizes[sz]; sz++)
- {
- Uint32 ptrI = m_pool.seize();
- if (unlikely(ptrI == RNIL))
- goto err;
- alloc[idx++] = ptrI;
- }
-
- alloc[idx] = m_head.m_ptr_i;
- m_head.m_sz = 1;
- for (Uint32 i = 0; i<idx; i++)
- {
- m_head.m_ptr_i = alloc[i];
- Uint32 * ptr = get(0);
- * ptr = alloc[i + 1];
- }
-
- m_head.m_sz = sz;
- m_head.m_ptr_i = alloc[0];
-
- return true;
-
-err:
- for (i = 0; i<idx; i++)
- m_pool.release(alloc[i]);
- return false;
-}
-
-void
-DynArr256::init(ReleaseIterator &iter)
-{
- iter.m_sz = 1;
- iter.m_pos = 0;
- iter.m_ptr_i[0] = RNIL;
- iter.m_ptr_i[1] = m_head.m_ptr_i;
- iter.m_ptr_i[2] = RNIL;
- iter.m_ptr_i[3] = RNIL;
- iter.m_ptr_i[4] = RNIL;
-}
-
-/**
- * Iter is in next pos
- *
- * 0 - done
- * 1 - data
- * 2 - no data
- */
-Uint32
-DynArr256::release(ReleaseIterator &iter, Uint32 * retptr)
-{
- Uint32 sz = iter.m_sz;
- Uint32 ptrI = iter.m_ptr_i[sz];
- Uint32 page_no = ptrI >> DA256_BITS;
- Uint32 page_idx = ptrI & DA256_MASK;
- Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF;
- DA256Page * memroot = m_pool.m_memroot;
- DA256Page * page = memroot + page_no;
-
- if (ptrI != RNIL)
- {
- Uint32 p0 = iter.m_pos & 255;
- for (; p0<256; p0++)
- {
- Uint32 *retVal, *magic_ptr, p;
- if (p0 != 255)
- {
- Uint32 line = ((p0 << 8) + (p0 << 4) + p0 + 255) >> 12;
- Uint32 * ptr = (Uint32*)(page->m_nodes + page_idx);
-
- p = 0;
- retVal = (ptr + 1 + p0 + line);
- magic_ptr =(ptr + (p0 & ~15));
- }
- else
- {
- Uint32 b = (page_idx + 1) >> 4;
- Uint32 * ptr = (Uint32*)(page->m_header+b);
-
- p = page_idx - (b << 4) + b;
- retVal = (ptr + 1 + p);
- magic_ptr = ptr;
- }
-
- Uint32 magic = *magic_ptr;
- Uint32 val = *retVal;
- if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id)))
- goto err;
-
- if (sz == m_head.m_sz)
- {
- * retptr = val;
- p0++;
- if (p0 != 256)
- {
- /**
- * Move next
- */
- iter.m_pos &= ~(Uint32)255;
- iter.m_pos |= p0;
- }
- else
- {
- /**
- * Move up
- */
- m_pool.release(ptrI);
- iter.m_sz --;
- iter.m_pos >>= 8;
- }
- return 1;
- }
- else if (val != RNIL)
- {
- iter.m_sz++;
- iter.m_ptr_i[iter.m_sz] = val;
- iter.m_pos = (p0 << 8);
- * retVal = RNIL;
- return 2;
- }
- }
-
- assert(p0 == 256);
- m_pool.release(ptrI);
- iter.m_sz --;
- iter.m_pos >>= 8;
- return 2;
- }
-
- new (&m_head) Head();
- return 0;
-
-err:
- require(false);
- return false;
-}
-
-static
-inline
-bool
-seizenode(DA256Page* page, Uint32 idx, Uint32 type_id)
-{
- Uint32 i;
- Uint32 b = (idx + 1) >> 4;
- Uint32 p = idx - (b << 4) + b;
-
- DA256Node * ptr = (DA256Node*)(page->m_nodes + idx);
-
-#ifdef DA256_USE_PREFETCH
-#if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
- __builtin_prefetch (page->m_header + b, 1);
- for (i = 0; i<17; i++)
- {
- __builtin_prefetch (ptr->m_lines+i, 1);
- }
-#endif
-#endif
-
-#ifdef DA256_EXTRA_SAFE
- Uint32 check = type_id;
-#endif
- type_id = ((~type_id) << 16) | 0xFFFF;
-
-#ifdef DA256_EXTRA_SAFE
- if (unlikely(((page->m_header + b)->m_magic & (1 << p)) != 0))
- {
- return false;
- }
-#endif
-
- (page->m_header + b)->m_magic |= (1 << p);
- (page->m_header + b)->m_data[p] = RNIL;
- for (i = 0; i<17; i++)
- {
- DA256CL * line = ptr->m_lines + i;
-#ifdef DA256_EXTRA_SAFE
- if (unlikely(line->m_magic != check))
- {
- return false;
- }
-#endif
- line->m_magic = type_id;
- for (Uint32 j = 0; j<15; j++)
- line->m_data[j] = RNIL;
- }
-
-#ifdef UNIT_TEST
- allocatednodes++;
-#endif
- return true;
-}
-
-static
-bool
-releasenode(DA256Page* page, Uint32 idx, Uint32 type_id)
-{
- Uint32 i;
- Uint32 b = (idx + 1) >> 4;
- Uint32 p = idx - (b << 4) + b;
-
- DA256Node * ptr = (DA256Node*)(page->m_nodes + idx);
-
-#ifdef DA256_USE_PREFETCH
-#if defined(__GNUC__) && !(__GNUC__ == 2 && __GNUC_MINOR__ < 96)
- __builtin_prefetch (page->m_header + b, 1);
- for (i = 0; i<17; i++)
- {
- __builtin_prefetch (ptr->m_lines+i, 1);
- }
-#endif
-#endif
-
-#ifdef DA256_EXTRA_SAFE
- Uint32 check = ((~type_id) << 16) | 0xFFFF;
-#endif
-
-#ifdef DA256_EXTRA_SAFE
- if (unlikely((((page->m_header + b)->m_magic & (1 << p)) == 0)))
- {
- return false;
- }
-#endif
-
- (page->m_header + b)->m_magic ^= (1 << p);
- for (i = 0; i<17; i++)
- {
- DA256CL * line = ptr->m_lines + i;
-#ifdef DA256_EXTRA_SAFE
- if (unlikely(line->m_magic != check))
- {
- return false;
- }
-#endif
- line->m_magic = type_id;
- }
-
-#ifdef UNIT_TEST
- releasednodes++;
-#endif
-
- return true;
-}
-
-Uint32
-DynArr256Pool::seize()
-{
- Uint32 ff = m_first_free;
- Uint32 type_id = m_type_id;
-
- DA256Page* page;
- DA256Page * memroot = m_memroot;
- if (ff == RNIL)
- {
- Uint32 page_no;
- if (likely((page = (DA256Page*)m_ctx.alloc_page(type_id, &page_no)) != 0))
- {
- initpage(page, page_no, type_id);
-#ifdef UNIT_TEST
- allocatedpages++;
-#endif
- }
- else
- {
- return RNIL;
- }
- ff = (page_no << DA256_BITS);
- }
- else
- {
- page = memroot + (ff >> DA256_BITS);
- }
-
- Uint32 idx = ff & DA256_MASK;
- DA256Free * ptr = (DA256Free*)(page->m_nodes + idx);
- if (likely(ptr->m_magic == type_id))
- {
- Uint32 next = ptr->m_next_free;
- if (likely(seizenode(page, idx, type_id)))
- {
- m_first_free = next;
- return ff;
- }
- }
-
-//error:
- require(false);
- return 0;
-}
-
-void
-DynArr256Pool::release(Uint32 ptrI)
-{
- Uint32 ff = m_first_free;
- Uint32 type_id = m_type_id;
-
- Uint32 page_no = ptrI >> DA256_BITS;
- Uint32 page_idx = ptrI & DA256_MASK;
- DA256Page * memroot = m_memroot;
- DA256Page * page = memroot + page_no;
-
- DA256Free * ptr = (DA256Free*)(page->m_nodes + page_idx);
- if (likely(releasenode(page, page_idx, type_id)))
- {
- ptr->m_next_free = ff;
- ptr->m_magic = type_id;
- m_first_free = ptrI;
- return;
- }
- require(false);
-}
-
-#ifdef UNIT_TEST
-
-#include <NdbTick.h>
-#include "ndbd_malloc_impl.hpp"
-#include "SimulatedBlock.hpp"
-
-Ndbd_mem_manager mm;
-Configuration cfg;
-Block_context ctx(cfg, mm);
-struct BB : public SimulatedBlock
-{
- BB(int no, Block_context& ctx) : SimulatedBlock(no, ctx) {}
-};
-
-BB block(DBACC, ctx);
-
-static
-void
-simple(DynArr256 & arr, int argc, char* argv[])
-{
- ndbout_c("argc: %d", argc);
- for (Uint32 i = 1; i<(Uint32)argc; i++)
- {
- Uint32 * s = arr.set(atoi(argv[i]));
- {
- bool found = false;
- for (Uint32 j = 1; j<i; j++)
- {
- if (atoi(argv[i]) == atoi(argv[j]))
- {
- found = true;
- break;
- }
- }
- if (!found)
- * s = i;
- }
-
- Uint32 * g = arr.get(atoi(argv[i]));
- Uint32 v = g ? *g : ~0;
- ndbout_c("p: %p %p %d", s, g, v);
- }
-}
-
-static
-void
-basic(DynArr256& arr, int argc, char* argv[])
-{
-#define MAXLEN 65536
-
- Uint32 len = 0;
- Uint32 save[2*MAXLEN];
- for (Uint32 i = 0; i<MAXLEN; i++)
- {
- int op = (rand() % 100) > 50;
- if (len == 0)
- op = 1;
- if (len == MAXLEN)
- op = 0;
- switch(op){
- case 0:{ // get
- Uint32 item = (rand() % len) << 1;
- Uint32 idx = save[item];
- Uint32 val = save[item+1];
- //ndbout_c("get(%d)", idx);
- Uint32 *p = arr.get(idx);
- assert(p);
- assert(* p == val);
- break;
- }
- case 1:{ // set
- Uint32 item = len << 1;
- Uint32 idx = i; //rand() & 0xFFFFF; // & 0xFFFFF; //rand(); //(65536*i) / 10000;
- Uint32 val = rand();
-#if 0
- for(Uint32 j = 0; j < item; j += 2)
- {
- if (save[j] == idx)
- {
- item = j;
- break;
- }
- }
-#endif
- //ndbout_c("set(%d, %x)", idx, val);
- Uint32 *p = arr.set(idx);
- assert(* p);
- if (item == (len << 1))
- {
- *p = val;
- len++;
- }
- else
- {
- assert(* p == save[item+1]);
- * p = val;
- }
- save[item] = idx;
- save[item+1] = val;
- }
- }
- }
-}
-
-unsigned long long
-micro()
-{
- struct timeval tv;
- gettimeofday(&tv, 0);
- unsigned long long ret = tv.tv_sec;
- ret *= 1000000;
- ret += tv.tv_usec;
- return ret;
-}
-
-static
-void
-read(DynArr256& arr, int argc, char ** argv)
-{
- Uint32 cnt = 100000;
- Uint64 mbytes = 16*1024;
- Uint32 seed = time(0);
- Uint32 seq = 0, seqmask = 0;
-
- for (Uint32 i = 2; i<argc; i++)
- {
- if (strncmp(argv[i], "--mbytes=", sizeof("--mbytes=")-1) == 0)
- {
- mbytes = atoi(argv[i]+sizeof("--mbytes=")-1);
- if (argv[i][strlen(argv[i])-1] == 'g' ||
- argv[i][strlen(argv[i])-1] == 'G')
- mbytes *= 1024;
- }
- else if (strncmp(argv[i], "--cnt=", sizeof("--cnt=")-1) == 0)
- {
- cnt = atoi(argv[i]+sizeof("--cnt=")-1);
- }
- else if (strncmp(argv[i], "--seq", sizeof("--seq")-1) == 0)
- {
- seq = 1;
- }
- }
-
- /**
- * Populate with 5Mb
- */
- Uint32 maxidx = (1024*mbytes+31) / 32;
- Uint32 nodes = (maxidx+255) / 256;
- Uint32 pages = (nodes + 29)/ 30;
- ndbout_c("%lldmb data -> %d entries (%dkb)",
- mbytes, maxidx, 32*pages);
-
- for (Uint32 i = 0; i<maxidx; i++)
- {
- Uint32 *ptr = arr.set(i);
- assert(ptr);
- * ptr = i;
- }
-
- srand(seed);
-
- if (seq)
- {
- seq = rand();
- seqmask = ~(Uint32)0;
- }
-
- ndbout_c("Timing %d %s reads (seed: %u)", cnt,
- seq ? "sequential" : "random", seed);
-
- for (Uint32 i = 0; i<10; i++)
- {
- Uint32 sum0 = 0, sum1 = 0;
- Uint64 start = micro();
- for (Uint32 i = 0; i<cnt; i++)
- {
- Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
- Uint32 *ptr = arr.get(idx);
- sum0 += idx;
- sum1 += *ptr;
- }
- start = micro() - start;
- float uspg = start; uspg /= cnt;
- ndbout_c("Elapsed %lldus diff: %d -> %f us/get", start, sum0 - sum1, uspg);
- }
-}
-
-static
-void
-write(DynArr256& arr, int argc, char ** argv)
-{
- Uint32 seq = 0, seqmask = 0;
- Uint32 cnt = 100000;
- Uint64 mbytes = 16*1024;
- Uint32 seed = time(0);
-
- for (Uint32 i = 2; i<argc; i++)
- {
- if (strncmp(argv[i], "--mbytes=", sizeof("--mbytes=")-1) == 0)
- {
- mbytes = atoi(argv[i]+sizeof("--mbytes=")-1);
- if (argv[i][strlen(argv[i])-1] == 'g' ||
- argv[i][strlen(argv[i])-1] == 'G')
- mbytes *= 1024;
- }
- else if (strncmp(argv[i], "--cnt=", sizeof("--cnt=")-1) == 0)
- {
- cnt = atoi(argv[i]+sizeof("--cnt=")-1);
- }
- else if (strncmp(argv[i], "--seq", sizeof("--seq")-1) == 0)
- {
- seq = 1;
- }
- }
-
- /**
- * Populate with 5Mb
- */
- Uint32 maxidx = (1024*mbytes+31) / 32;
- Uint32 nodes = (maxidx+255) / 256;
- Uint32 pages = (nodes + 29)/ 30;
- ndbout_c("%lldmb data -> %d entries (%dkb)",
- mbytes, maxidx, 32*pages);
-
- srand(seed);
-
- if (seq)
- {
- seq = rand();
- seqmask = ~(Uint32)0;
- }
-
- ndbout_c("Timing %d %s writes (seed: %u)", cnt,
- seq ? "sequential" : "random", seed);
- for (Uint32 i = 0; i<10; i++)
- {
- Uint64 start = micro();
- for (Uint32 i = 0; i<cnt; i++)
- {
- Uint32 idx = ((rand() & (~seqmask)) + ((i + seq) & seqmask)) % maxidx;
- Uint32 *ptr = arr.set(idx);
- *ptr = i;
- }
- start = micro() - start;
- float uspg = start; uspg /= cnt;
- ndbout_c("Elapsed %lldus -> %f us/set", start, uspg);
- DynArr256::ReleaseIterator iter;
- arr.init(iter);
- Uint32 val;
- while(arr.release(iter, &val));
- }
-}
-
-int
-main(int argc, char** argv)
-{
- if (0)
- {
- for (Uint32 i = 0; i<30; i++)
- {
- Uint32 b = (i + 1) >> 4;
- Uint32 p = i - (b << 4) + b;
- printf("[ %d %d %d ]\n", i, b, p);
- }
- return 0;
- }
-
- Pool_context pc;
- pc.m_block = &block;
-
- Resource_limit rl;
- rl.m_min = 0;
- rl.m_max = 10000;
- rl.m_resource_id = 0;
- mm.set_resource_limit(rl);
- if(!mm.init())
- {
- abort();
- }
-
- DynArr256Pool pool;
- pool.init(0x2001, pc);
-
- DynArr256::Head head;
- DynArr256 arr(pool, head);
-
- if (strcmp(argv[1], "--simple") == 0)
- simple(arr, argc, argv);
- else if (strcmp(argv[1], "--basic") == 0)
- basic(arr, argc, argv);
- else if (strcmp(argv[1], "--read") == 0)
- read(arr, argc, argv);
- else if (strcmp(argv[1], "--write") == 0)
- write(arr, argc, argv);
-
- DynArr256::ReleaseIterator iter;
- arr.init(iter);
- Uint32 cnt = 0, val;
- while (arr.release(iter, &val)) cnt++;
-
- ndbout_c("allocatedpages: %d allocatednodes: %d releasednodes: %d"
- " releasecnt: %d",
- allocatedpages,
- allocatednodes,
- releasednodes,
- cnt);
-
- return 0;
-#if 0
- printf("sizeof(DA256Page): %d\n", sizeof(DA256Page));
-
- DA256Page page;
-
- for (Uint32 i = 0; i<10000; i++)
- {
- Uint32 arg = rand() & 255;
- Uint32 base = 0;
- Uint32 idx = arg & 256;
- printf("%d\n", arg);
-
- assert(base <= 30);
-
- if (idx == 255)
- {
- Uint32 b = (base + 1) >> 4;
- Uint32 p = base - (b << 4) + b;
- Uint32 magic = page.m_header[b].m_magic;
- Uint32 retVal = page.m_header[b].m_data[p];
-
- require(magic & (1 << p));
- return retVal;
- }
- else
- {
- // 4 bit extra offset per idx
- Uint32 line = idx / 15;
- Uint32 off = idx % 15;
-
- {
- Uint32 pos = 1 + idx + line;
- Uint32 magic = pos & ~15;
-
- Uint32 * ptr = (Uint32*)&page.m_nodes[base];
- assert((ptr + pos) == &page.m_nodes[base].m_lines[line].m_data[off]);
- assert((ptr + magic) == &page.m_nodes[base].m_lines[line].m_magic);
- }
- }
- }
-#endif
-}
-
-Uint32 g_currentStartPhase;
-Uint32 g_start_type;
-NdbNodeBitmask g_nowait_nodes;
-
-void childExit(int code, Uint32 currentStartPhase)
-{
- abort();
-}
-
-void childAbort(int code, Uint32 currentStartPhase)
-{
- abort();
-}
-
-void childReportError(int error)
-{
- abort();
-}
-
-void
-UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){
-}
-
-void
-UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
-}
-
-void
-UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
-}
-
-void
-UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
-}
-
-#include <SimBlockList.hpp>
-
-void
-SimBlockList::unload()
-{
-
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/DynArr256.hpp b/storage/ndb/src/kernel/vm/DynArr256.hpp
deleted file mode 100644
index 162f81d3173..00000000000
--- a/storage/ndb/src/kernel/vm/DynArr256.hpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2003, 2006, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef DYNARR256_HPP
-#define DYNARR256_HPP
-
-#include "Pool.hpp"
-
-class DynArr256;
-struct DA256Page;
-
-class DynArr256Pool
-{
- friend class DynArr256;
-public:
- DynArr256Pool();
-
- void init(Uint32 type_id, const Pool_context& pc);
-
-protected:
- Uint32 m_type_id;
- Uint32 m_first_free;
- Pool_context m_ctx;
- struct DA256Page* m_memroot;
-
-private:
- Uint32 seize();
- void release(Uint32);
-};
-
-class DynArr256
-{
-public:
- struct Head
- {
- Head() { m_ptr_i = RNIL; m_sz = 0;}
-
- Uint32 m_ptr_i;
- Uint32 m_sz;
-
- bool isEmpty() const { return m_sz == 0;}
- };
-
- DynArr256(DynArr256Pool & pool, Head& head) :
- m_head(head), m_pool(pool){}
-
- Uint32* set(Uint32 pos);
- Uint32* get(Uint32 pos) const ;
-
- struct ReleaseIterator
- {
- Uint32 m_sz;
- Uint32 m_pos;
- Uint32 m_ptr_i[5];
- };
-
- void init(ReleaseIterator&);
- /**
- * return 0 - done
- * 1 - data (in retptr)
- * 2 - nodata
- */
- Uint32 release(ReleaseIterator&, Uint32* retptr);
-protected:
- Head & m_head;
- DynArr256Pool & m_pool;
-
- bool expand(Uint32 pos);
- void handle_invalid_ptr(Uint32 pos, Uint32 ptrI, Uint32 p0);
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/Emulator.cpp b/storage/ndb/src/kernel/vm/Emulator.cpp
deleted file mode 100644
index 6610d88fba0..00000000000
--- a/storage/ndb/src/kernel/vm/Emulator.cpp
+++ /dev/null
@@ -1,292 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include "Emulator.hpp"
-#include <FastScheduler.hpp>
-#include <SignalLoggerManager.hpp>
-#include <TransporterRegistry.hpp>
-#include <TimeQueue.hpp>
-
-#include "Configuration.hpp"
-#include "WatchDog.hpp"
-#include "ThreadConfig.hpp"
-#include "SimBlockList.hpp"
-
-#include <NodeState.hpp>
-#include "ndbd_malloc_impl.hpp"
-
-#include <NdbMem.h>
-#include <NdbMutex.h>
-#include <NdbSleep.h>
-
-#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
- */
-
-#ifndef NO_EMULATED_JAM
-Uint8 theEmulatedJam[EMULATED_JAM_SIZE * 4];
-Uint32 theEmulatedJamIndex = 0;
-Uint32 theEmulatedJamBlockNumber = 0;
-#endif
-
- GlobalData globalData;
-
- TimeQueue globalTimeQueue;
- FastScheduler globalScheduler;
- TransporterRegistry globalTransporterRegistry;
-
-#ifdef VM_TRACE
- SignalLoggerManager globalSignalLoggers;
-#endif
-
-EmulatorData globalEmulatorData;
-NdbMutex * theShutdownMutex = 0;
-int simulate_error_during_shutdown= 0;
-
-EmulatorData::EmulatorData(){
- theConfiguration = 0;
- theWatchDog = 0;
- theThreadConfig = 0;
- theSimBlockList = 0;
- theShutdownMutex = 0;
- m_socket_server = 0;
- m_mem_manager = 0;
-}
-
-void
-ndb_new_handler_impl(){
- ERROR_SET(fatal, NDBD_EXIT_MEMALLOC, "New handler", "");
-}
-
-void
-EmulatorData::create(){
- NdbMem_Create();
-
- theConfiguration = new Configuration();
- theWatchDog = new WatchDog();
- theThreadConfig = new ThreadConfig();
- theSimBlockList = new SimBlockList();
- m_socket_server = new SocketServer();
- m_mem_manager = new Ndbd_mem_manager();
-
- theShutdownMutex = NdbMutex_Create();
-
- ndb_new_handler = ndb_new_handler_impl;
-}
-
-void
-EmulatorData::destroy(){
- if(theConfiguration)
- delete theConfiguration; theConfiguration = 0;
- if(theWatchDog)
- delete theWatchDog; theWatchDog = 0;
- if(theThreadConfig)
- delete theThreadConfig; theThreadConfig = 0;
- if(theSimBlockList)
- delete theSimBlockList; theSimBlockList = 0;
- if(m_socket_server)
- delete m_socket_server; m_socket_server = 0;
- NdbMutex_Destroy(theShutdownMutex);
- if (m_mem_manager)
- delete m_mem_manager; m_mem_manager = 0;
-
- NdbMem_Destroy();
-}
-
-void
-NdbShutdown(NdbShutdownType type,
- NdbRestartType restartType)
-{
- if(type == NST_ErrorInsert){
- type = NST_Restart;
- restartType = (NdbRestartType)
- globalEmulatorData.theConfiguration->getRestartOnErrorInsert();
- if(restartType == NRT_Default){
- type = NST_ErrorHandler;
- globalEmulatorData.theConfiguration->stopOnError(true);
- }
- }
-
- if((type == NST_ErrorHandlerSignal) || // Signal handler has already locked mutex
- (NdbMutex_Trylock(theShutdownMutex) == 0)){
- globalData.theRestartFlag = perform_stop;
-
- bool restart = false;
-
- if((type != NST_Normal &&
- globalEmulatorData.theConfiguration->stopOnError() == false) ||
- type == NST_Restart) {
-
- restart = true;
- }
-
-
- const char * shutting = "shutting down";
- if(restart){
- shutting = "restarting";
- }
-
- switch(type){
- case NST_Normal:
- g_eventLogger.info("Shutdown initiated");
- break;
- case NST_Watchdog:
- g_eventLogger.info("Watchdog %s system", shutting);
- break;
- case NST_ErrorHandler:
- g_eventLogger.info("Error handler %s system", shutting);
- break;
- case NST_ErrorHandlerSignal:
- g_eventLogger.info("Error handler signal %s system", shutting);
- break;
- case NST_ErrorHandlerStartup:
- g_eventLogger.info("Error handler startup %s system", shutting);
- break;
- case NST_Restart:
- g_eventLogger.info("Restarting system");
- break;
- default:
- g_eventLogger.info("Error handler %s system (unknown type: %u)",
- shutting, (unsigned)type);
- type = NST_ErrorHandler;
- break;
- }
-
- const char * exitAbort = 0;
- if (opt_core)
- exitAbort = "aborting";
- else
- exitAbort = "exiting";
-
- if(type == NST_Watchdog){
- /**
- * Very serious, don't attempt to free, just die!!
- */
- g_eventLogger.info("Watchdog shutdown completed - %s", exitAbort);
- if (opt_core)
- {
- childAbort(-1,g_currentStartPhase);
- }
- else
- {
- childExit(-1,g_currentStartPhase);
- }
- }
-
-#ifndef NDB_WIN32
- if (simulate_error_during_shutdown) {
- kill(getpid(), simulate_error_during_shutdown);
- while(true)
- NdbSleep_MilliSleep(10);
- }
-#endif
-
- globalEmulatorData.theWatchDog->doStop();
-
-#ifdef VM_TRACE
- FILE * outputStream = globalSignalLoggers.setOutputStream(0);
- if(outputStream != 0)
- fclose(outputStream);
-#endif
-
- /**
- * Stop all transporter connection attempts and accepts
- */
- globalEmulatorData.m_socket_server->stopServer();
- globalEmulatorData.m_socket_server->stopSessions();
- globalTransporterRegistry.stop_clients();
-
- /**
- * Stop transporter communication with other nodes
- */
- globalTransporterRegistry.stopSending();
- globalTransporterRegistry.stopReceiving();
-
- /**
- * Remove all transporters
- */
- globalTransporterRegistry.removeAll();
-
-#ifdef VM_TRACE
-#define UNLOAD (type != NST_ErrorHandler && type != NST_Watchdog)
-#else
-#define UNLOAD true
-#endif
- if(UNLOAD){
- globalEmulatorData.theSimBlockList->unload();
- globalEmulatorData.destroy();
- }
-
- if(type != NST_Normal && type != NST_Restart){
- // Signal parent that error occured during startup
- if (type == NST_ErrorHandlerStartup)
- kill(getppid(), SIGUSR1);
- g_eventLogger.info("Error handler shutdown completed - %s", exitAbort);
- if (opt_core)
- {
- childAbort(-1,g_currentStartPhase);
- }
- else
- {
- childExit(-1,g_currentStartPhase);
- }
- }
-
- /**
- * This is a normal restart, depend on angel
- */
- if(type == NST_Restart){
- childExit(restartType,g_currentStartPhase);
- }
-
- g_eventLogger.info("Shutdown completed - exiting");
- } else {
- /**
- * Shutdown is already in progress
- */
-
- /**
- * If this is the watchdog, kill system the hard way
- */
- if (type== NST_Watchdog){
- g_eventLogger.info("Watchdog is killing system the hard way");
-#if defined VM_TRACE
- childAbort(-1,g_currentStartPhase);
-#else
- childExit(-1,g_currentStartPhase);
-#endif
- }
-
- while(true)
- NdbSleep_MilliSleep(10);
- }
-}
-
diff --git a/storage/ndb/src/kernel/vm/Emulator.hpp b/storage/ndb/src/kernel/vm/Emulator.hpp
deleted file mode 100644
index 7168e043b15..00000000000
--- a/storage/ndb/src/kernel/vm/Emulator.hpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef EMULATOR_H
-#define EMULATOR_H
-
-//===========================================================================
-//
-// .DESCRIPTION
-// This is the main fuction for the AXE VM emulator.
-// It contains some global objects and a run method.
-//
-//===========================================================================
-#include <kernel_types.h>
-#include <TransporterRegistry.hpp>
-
-extern class JobTable globalJobTable;
-extern class TimeQueue globalTimeQueue;
-extern class FastScheduler globalScheduler;
-extern class TransporterRegistry globalTransporterRegistry;
-extern struct GlobalData globalData;
-
-#ifdef VM_TRACE
-extern class SignalLoggerManager globalSignalLoggers;
-#endif
-
-#ifndef NO_EMULATED_JAM
- #define EMULATED_JAM_SIZE 1024
- #define JAM_MASK ((EMULATED_JAM_SIZE * 4) - 1)
-
- extern Uint8 theEmulatedJam[];
- extern Uint32 theEmulatedJamIndex;
- // last block entry, used in dumpJam() if jam contains no block entries
- extern Uint32 theEmulatedJamBlockNumber;
-#else
- const Uint8 theEmulatedJam[]=0;
- const Uint32 theEmulatedJamIndex=0;
-#endif
-
-struct EmulatorData {
- class Configuration * theConfiguration;
- class WatchDog * theWatchDog;
- class ThreadConfig * theThreadConfig;
- class SimBlockList * theSimBlockList;
- class SocketServer * m_socket_server;
- class Ndbd_mem_manager * m_mem_manager;
-
- /**
- * Constructor
- *
- * Sets all the pointers to NULL
- */
- EmulatorData();
-
- /**
- * Create all the objects
- */
- void create();
-
- /**
- * Destroys all the objects
- */
- void destroy();
-};
-
-extern struct EmulatorData globalEmulatorData;
-
-enum NdbShutdownType {
- NST_Normal,
- NST_Watchdog,
- NST_ErrorHandler,
- NST_ErrorHandlerSignal,
- NST_Restart,
- NST_ErrorInsert,
- NST_ErrorHandlerStartup
-};
-
-enum NdbRestartType {
- NRT_Default = 0,
- NRT_NoStart_Restart = 1, // -n
- NRT_DoStart_Restart = 2, //
- NRT_NoStart_InitialStart = 3, // -n -i
- NRT_DoStart_InitialStart = 4 // -i
-};
-
-/**
- * Shutdown/restart Ndb
- *
- * @param type - Type of shutdown/restart
- * @param restartType - Type of restart (only valid if type == NST_Restart)
- */
-void
-NdbShutdown(NdbShutdownType type,
- NdbRestartType restartType = NRT_Default);
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/FastScheduler.cpp b/storage/ndb/src/kernel/vm/FastScheduler.cpp
deleted file mode 100644
index e5fbe0b1242..00000000000
--- a/storage/ndb/src/kernel/vm/FastScheduler.cpp
+++ /dev/null
@@ -1,500 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "FastScheduler.hpp"
-#include "RefConvert.hpp"
-
-#include "Emulator.hpp"
-#include "VMSignal.hpp"
-
-#include <SignalLoggerManager.hpp>
-#include <BlockNumbers.h>
-#include <GlobalSignalNumbers.h>
-#include <signaldata/EventReport.hpp>
-#include "LongSignal.hpp"
-#include <NdbTick.h>
-
-#define MIN_NUMBER_OF_SIG_PER_DO_JOB 64
-#define MAX_NUMBER_OF_SIG_PER_DO_JOB 2048
-#define EXTRA_SIGNALS_PER_DO_JOB 32
-
-FastScheduler::FastScheduler()
-{
- // These constants work for sun only, but they should be initated from
- // Emulator.C as soon as VMTime has been initiated.
- theJobBuffers[0].newBuffer(JBASIZE);
- theJobBuffers[1].newBuffer(JBBSIZE);
- theJobBuffers[2].newBuffer(JBCSIZE);
- theJobBuffers[3].newBuffer(JBDSIZE);
- clear();
-}
-
-FastScheduler::~FastScheduler()
-{
-}
-
-void
-FastScheduler::clear()
-{
- int i;
- // Make sure the restart signals are not sent too early
- // the prio is set back in 'main' using the 'ready' method.
- globalData.highestAvailablePrio = LEVEL_IDLE;
- globalData.sendPackedActivated = 0;
- globalData.activateSendPacked = 0;
- for (i = 0; i < JB_LEVELS; i++){
- theJobBuffers[i].clear();
- }
- globalData.JobCounter = 0;
- globalData.JobLap = 0;
- globalData.loopMax = 32;
- globalData.VMSignals[0].header.theSignalId = 0;
-
- theDoJobTotalCounter = 0;
- theDoJobCallCounter = 0;
-}
-
-void
-FastScheduler::activateSendPacked()
-{
- globalData.sendPackedActivated = 1;
- globalData.activateSendPacked = 0;
- globalData.loopMax = 2048;
-}//FastScheduler::activateSendPacked()
-
-//------------------------------------------------------------------------
-// sendPacked is executed at the end of the loop.
-// To ensure that we don't send any messages before executing all local
-// packed signals we do another turn in the loop (unless we have already
-// executed too many signals in the loop).
-//------------------------------------------------------------------------
-void
-FastScheduler::doJob()
-{
- Uint32 loopCount = 0;
- Uint32 TminLoops = getBOccupancy() + EXTRA_SIGNALS_PER_DO_JOB;
- Uint32 TloopMax = (Uint32)globalData.loopMax;
- if (TminLoops < TloopMax) {
- TloopMax = TminLoops;
- }//if
- if (TloopMax < MIN_NUMBER_OF_SIG_PER_DO_JOB) {
- TloopMax = MIN_NUMBER_OF_SIG_PER_DO_JOB;
- }//if
- register Signal* signal = getVMSignals();
- register Uint32 tHighPrio= globalData.highestAvailablePrio;
- do{
- while ((tHighPrio < LEVEL_IDLE) && (loopCount < TloopMax)) {
- // signal->garbage_register();
- // To ensure we find bugs quickly
- register Uint32 gsnbnr = theJobBuffers[tHighPrio].retrieve(signal);
- register BlockNumber reg_bnr = gsnbnr & 0xFFF;
- register GlobalSignalNumber reg_gsn = gsnbnr >> 16;
- globalData.incrementWatchDogCounter(1);
- if (reg_bnr > 0) {
- Uint32 tJobCounter = globalData.JobCounter;
- Uint32 tJobLap = globalData.JobLap;
- SimulatedBlock* b = globalData.getBlock(reg_bnr);
- theJobPriority[tJobCounter] = (Uint8)tHighPrio;
- globalData.JobCounter = (tJobCounter + 1) & 4095;
- globalData.JobLap = tJobLap + 1;
-
-#ifdef VM_TRACE_TIME
- Uint32 us1, us2;
- Uint64 ms1, ms2;
- NdbTick_CurrentMicrosecond(&ms1, &us1);
- b->m_currentGsn = reg_gsn;
-#endif
-
- getSections(signal->header.m_noOfSections, signal->m_sectionPtr);
-#ifdef VM_TRACE
- {
- if (globalData.testOn) {
- signal->header.theVerId_signalNumber = reg_gsn;
- signal->header.theReceiversBlockNumber = reg_bnr;
-
- globalSignalLoggers.executeSignal(signal->header,
- tHighPrio,
- &signal->theData[0],
- globalData.ownId,
- signal->m_sectionPtr,
- signal->header.m_noOfSections);
- }//if
- }
-#endif
- b->executeFunction(reg_gsn, signal);
- releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
- signal->header.m_noOfSections = 0;
-#ifdef VM_TRACE_TIME
- NdbTick_CurrentMicrosecond(&ms2, &us2);
- Uint64 diff = ms2;
- diff -= ms1;
- diff *= 1000000;
- diff += us2;
- diff -= us1;
- b->addTime(reg_gsn, diff);
-#endif
- tHighPrio = globalData.highestAvailablePrio;
- } else {
- tHighPrio++;
- globalData.highestAvailablePrio = tHighPrio;
- }//if
- loopCount++;
- }//while
- sendPacked();
- tHighPrio = globalData.highestAvailablePrio;
- if(getBOccupancy() > MAX_OCCUPANCY)
- {
- if(loopCount != TloopMax)
- abort();
- assert( loopCount == TloopMax );
- TloopMax += 512;
- }
- } while ((getBOccupancy() > MAX_OCCUPANCY) ||
- ((loopCount < TloopMax) &&
- (tHighPrio < LEVEL_IDLE)));
-
- theDoJobCallCounter ++;
- theDoJobTotalCounter += loopCount;
- if (theDoJobCallCounter == 8192) {
- reportDoJobStatistics(theDoJobTotalCounter >> 13);
- theDoJobCallCounter = 0;
- theDoJobTotalCounter = 0;
- }//if
-
-}//FastScheduler::doJob()
-
-void FastScheduler::sendPacked()
-{
- if (globalData.sendPackedActivated == 1) {
- SimulatedBlock* b_lqh = globalData.getBlock(DBLQH);
- SimulatedBlock* b_tc = globalData.getBlock(DBTC);
- SimulatedBlock* b_tup = globalData.getBlock(DBTUP);
- Signal* signal = getVMSignals();
- b_lqh->executeFunction(GSN_SEND_PACKED, signal);
- b_tc->executeFunction(GSN_SEND_PACKED, signal);
- b_tup->executeFunction(GSN_SEND_PACKED, signal);
- return;
- } else if (globalData.activateSendPacked == 0) {
- return;
- } else {
- activateSendPacked();
- }//if
- return;
-}//FastScheduler::sendPacked()
-
-Uint32
-APZJobBuffer::retrieve(Signal* signal)
-{
- Uint32 tOccupancy = theOccupancy;
- Uint32 myRPtr = rPtr;
- BufferEntry& buf = buffer[myRPtr];
- Uint32 gsnbnr;
- Uint32 cond = (++myRPtr == bufSize) - 1;
- Uint32 tRecBlockNo = buf.header.theReceiversBlockNumber;
-
- if (tOccupancy != 0) {
- if (tRecBlockNo != 0) {
- // Transform protocol to signal.
- rPtr = myRPtr & cond;
- theOccupancy = tOccupancy - 1;
- gsnbnr = buf.header.theVerId_signalNumber << 16 | tRecBlockNo;
-
- Uint32 tSignalId = globalData.theSignalId;
- Uint32 tLength = buf.header.theLength;
- Uint32 tFirstData = buf.theDataRegister[0];
- signal->header = buf.header;
-
- // Recall our signal Id for restart purposes
- buf.header.theSignalId = tSignalId;
- globalData.theSignalId = tSignalId + 1;
-
- Uint32* tDataRegPtr = &buf.theDataRegister[0];
- Uint32* tSigDataPtr = signal->getDataPtrSend();
- *tSigDataPtr = tFirstData;
- tDataRegPtr++;
- tSigDataPtr++;
- Uint32 tLengthCopied = 1;
- while (tLengthCopied < tLength) {
- Uint32 tData0 = tDataRegPtr[0];
- Uint32 tData1 = tDataRegPtr[1];
- Uint32 tData2 = tDataRegPtr[2];
- Uint32 tData3 = tDataRegPtr[3];
-
- tDataRegPtr += 4;
- tLengthCopied += 4;
-
- tSigDataPtr[0] = tData0;
- tSigDataPtr[1] = tData1;
- tSigDataPtr[2] = tData2;
- tSigDataPtr[3] = tData3;
- tSigDataPtr += 4;
- }//while
-
- /**
- * Copy sections references (copy all without if-statements)
- */
- tDataRegPtr = &buf.theDataRegister[tLength];
- SegmentedSectionPtr * tSecPtr = &signal->m_sectionPtr[0];
- Uint32 tData0 = tDataRegPtr[0];
- Uint32 tData1 = tDataRegPtr[1];
- Uint32 tData2 = tDataRegPtr[2];
-
- tSecPtr[0].i = tData0;
- tSecPtr[1].i = tData1;
- tSecPtr[2].i = tData2;
-
- //---------------------------------------------------------
- // Prefetch of buffer[rPtr] is done here. We prefetch for
- // read both the first cache line and the next 64 byte
- // entry
- //---------------------------------------------------------
- PREFETCH((void*)&buffer[rPtr]);
- PREFETCH((void*)(((char*)&buffer[rPtr]) + 64));
- return gsnbnr;
- } else {
- bnr_error();
- return 0; // Will never come here, simply to keep GCC happy.
- }//if
- } else {
- //------------------------------------------------------------
- // The Job Buffer was empty, signal this by return zero.
- //------------------------------------------------------------
- return 0;
- }//if
-}//APZJobBuffer::retrieve()
-
-void
-APZJobBuffer::signal2buffer(Signal* signal,
- BlockNumber bnr, GlobalSignalNumber gsn,
- BufferEntry& buf)
-{
- Uint32 tSignalId = globalData.theSignalId;
- Uint32 tFirstData = signal->theData[0];
- Uint32 tLength = signal->header.theLength;
- Uint32 tSigId = buf.header.theSignalId;
-
- buf.header = signal->header;
- buf.header.theVerId_signalNumber = gsn;
- buf.header.theReceiversBlockNumber = bnr;
- buf.header.theSendersSignalId = tSignalId - 1;
- buf.header.theSignalId = tSigId;
- buf.theDataRegister[0] = tFirstData;
-
- Uint32 tLengthCopied = 1;
- Uint32* tSigDataPtr = &signal->theData[1];
- Uint32* tDataRegPtr = &buf.theDataRegister[1];
- while (tLengthCopied < tLength) {
- Uint32 tData0 = tSigDataPtr[0];
- Uint32 tData1 = tSigDataPtr[1];
- Uint32 tData2 = tSigDataPtr[2];
- Uint32 tData3 = tSigDataPtr[3];
-
- tLengthCopied += 4;
- tSigDataPtr += 4;
-
- tDataRegPtr[0] = tData0;
- tDataRegPtr[1] = tData1;
- tDataRegPtr[2] = tData2;
- tDataRegPtr[3] = tData3;
- tDataRegPtr += 4;
- }//while
-
- /**
- * Copy sections references (copy all without if-statements)
- */
- tDataRegPtr = &buf.theDataRegister[tLength];
- SegmentedSectionPtr * tSecPtr = &signal->m_sectionPtr[0];
- Uint32 tData0 = tSecPtr[0].i;
- Uint32 tData1 = tSecPtr[1].i;
- Uint32 tData2 = tSecPtr[2].i;
- tDataRegPtr[0] = tData0;
- tDataRegPtr[1] = tData1;
- tDataRegPtr[2] = tData2;
-}//APZJobBuffer::signal2buffer()
-
-void
-APZJobBuffer::insert(const SignalHeader * const sh,
- const Uint32 * const theData, const Uint32 secPtrI[3]){
- Uint32 tOccupancy = theOccupancy + 1;
- Uint32 myWPtr = wPtr;
- register BufferEntry& buf = buffer[myWPtr];
-
- if (tOccupancy < bufSize) {
- Uint32 cond = (++myWPtr == bufSize) - 1;
- wPtr = myWPtr & cond;
- theOccupancy = tOccupancy;
-
- buf.header = * sh;
- const Uint32 len = buf.header.theLength;
- memcpy(buf.theDataRegister, theData, 4 * len);
- memcpy(&buf.theDataRegister[len], &secPtrI[0], 4 * 3);
- //---------------------------------------------------------
- // Prefetch of buffer[wPtr] is done here. We prefetch for
- // write both the first cache line and the next 64 byte
- // entry
- //---------------------------------------------------------
- WRITEHINT((void*)&buffer[wPtr]);
- WRITEHINT((void*)(((char*)&buffer[wPtr]) + 64));
-
- } else {
- jbuf_error();
- }//if
-}
-APZJobBuffer::APZJobBuffer()
- : bufSize(0), buffer(NULL), memRef(NULL)
-{
- clear();
-}
-
-APZJobBuffer::~APZJobBuffer()
-{
- delete [] buffer;
-}
-
-void
-APZJobBuffer::newBuffer(int size)
-{
- buffer = new BufferEntry[size + 1]; // +1 to support "overrrun"
- if(buffer){
-#ifndef NDB_PURIFY
- ::memset(buffer, 0, (size * sizeof(BufferEntry)));
-#endif
- bufSize = size;
- } else
- bufSize = 0;
-}
-
-void
-APZJobBuffer::clear()
-{
- rPtr = 0;
- wPtr = 0;
- theOccupancy = 0;
-}
-
-/**
- * Function prototype for print_restart
- *
- * Defined later in this file
- */
-void print_restart(FILE * output, Signal* signal, Uint32 aLevel);
-
-void FastScheduler::dumpSignalMemory(FILE * output)
-{
- SignalT<25> signalT;
- Signal &signal= *(Signal*)&signalT;
- Uint32 ReadPtr[5];
- Uint32 tJob;
- Uint32 tLastJob;
-
- fprintf(output, "\n");
-
- if (globalData.JobLap > 4095) {
- if (globalData.JobCounter != 0)
- tJob = globalData.JobCounter - 1;
- else
- tJob = 4095;
- tLastJob = globalData.JobCounter;
- } else {
- if (globalData.JobCounter == 0)
- return; // No signals sent
- else {
- tJob = globalData.JobCounter - 1;
- tLastJob = 4095;
- }
- }
- ReadPtr[0] = theJobBuffers[0].getReadPtr();
- ReadPtr[1] = theJobBuffers[1].getReadPtr();
- ReadPtr[2] = theJobBuffers[2].getReadPtr();
- ReadPtr[3] = theJobBuffers[3].getReadPtr();
-
- do {
- unsigned char tLevel = theJobPriority[tJob];
- globalData.incrementWatchDogCounter(4);
- if (ReadPtr[tLevel] == 0)
- ReadPtr[tLevel] = theJobBuffers[tLevel].getBufSize() - 1;
- else
- ReadPtr[tLevel]--;
-
- theJobBuffers[tLevel].retrieveDump(&signal, ReadPtr[tLevel]);
- print_restart(output, &signal, tLevel);
-
- if (tJob == 0)
- tJob = 4095;
- else
- tJob--;
-
- } while (tJob != tLastJob);
- fflush(output);
-}
-
-void
-FastScheduler::prio_level_error()
-{
- ERROR_SET(ecError, NDBD_EXIT_WRONG_PRIO_LEVEL,
- "Wrong Priority Level", "FastScheduler.C");
-}
-
-void
-jbuf_error()
-{
- ERROR_SET(ecError, NDBD_EXIT_BLOCK_JBUFCONGESTION,
- "Job Buffer Full", "APZJobBuffer.C");
-}
-
-void
-bnr_error()
-{
- ERROR_SET(ecError, NDBD_EXIT_BLOCK_BNR_ZERO,
- "Block Number Zero", "FastScheduler.C");
-}
-
-void
-print_restart(FILE * output, Signal* signal, Uint32 aLevel)
-{
- fprintf(output, "--------------- Signal ----------------\n");
- SignalLoggerManager::printSignalHeader(output,
- signal->header,
- aLevel,
- globalData.ownId,
- true);
- SignalLoggerManager::printSignalData (output,
- signal->header,
- &signal->theData[0]);
-}
-
-/**
- * This method used to be a Cmvmi member function
- * but is now a "ordinary" function"
- *
- * See TransporterCallback.cpp for explanation
- */
-void
-FastScheduler::reportDoJobStatistics(Uint32 tMeanLoopCount) {
- SignalT<2> signalT;
- Signal &signal= *(Signal*)&signalT;
-
- memset(&signal.header, 0, sizeof(signal.header));
- signal.header.theLength = 2;
- signal.header.theSendersSignalId = 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/storage/ndb/src/kernel/vm/FastScheduler.hpp b/storage/ndb/src/kernel/vm/FastScheduler.hpp
deleted file mode 100644
index f36b432ed4a..00000000000
--- a/storage/ndb/src/kernel/vm/FastScheduler.hpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef FastScheduler_H
-#define FastScheduler_H
-
-#include <VMSignal.hpp>
-#include <kernel_types.h>
-#include <Prio.hpp>
-#include <SignalLoggerManager.hpp>
-#include <SimulatedBlock.hpp>
-#include <ErrorHandlingMacros.hpp>
-#include <GlobalData.hpp>
-#include <TransporterDefinitions.hpp>
-#include <prefetch.h>
-
-#define MAX_OCCUPANCY 1024
-
-#define JBASIZE 1280 // Jobs which have dead lines to meet use this level
-#define JBBSIZE 4096 // Most jobs use this level
-#define JBCSIZE 64 // Only used by STTOR and STTORRY currently
-#define JBDSIZE 4096 // Time Queue uses this level for storage, not supported
- // as priority level
-void bnr_error();
-void jbuf_error();
-class Signal;
-class Block;
-
-class BufferEntry
-{
-public:
- SignalHeader header;
- Uint32 theDataRegister[25];
-};
-
-class APZJobBuffer
-{
-public:
- APZJobBuffer();
- ~APZJobBuffer();
-
- void newBuffer(int size);
-
- void insert(Signal* signal, BlockNumber bnr, GlobalSignalNumber gsn);
- void insert(const SignalHeader * const sh, const Uint32 * const theData, const Uint32 secPtrI[3]);
- void insert(Signal* signal, BlockNumber bnr, GlobalSignalNumber gsn,
- Uint32 myWPtr);
-
- Uint32 retrieve(Signal *signal);
- void retrieve(Signal *signal, Uint32 myRptr);
-
- /**
- * Used when dumping to trace file
- */
- void retrieveDump(Signal *signal, Uint32 myRptr);
-
- void clear();
- Uint32 getOccupancy() const;
-
- Uint32 getReadPtr() const;
- Uint32 getWritePtr() const;
- Uint32 getBufSize() const;
-
-private:
- void signal2buffer(Signal* signal, BlockNumber bnr,
- GlobalSignalNumber gsn, BufferEntry& buf);
- Uint32 rPtr;
- Uint32 wPtr;
- Uint32 theOccupancy;
- Uint32 bufSize;
- BufferEntry* buffer;
- BufferEntry* memRef;
-};
-
-
-class FastScheduler
-{
-public:
- FastScheduler();
- ~FastScheduler();
-
- void doJob();
- int checkDoJob();
-
- void activateSendPacked();
-
- void execute(Signal* signal,
- Priority prio,
- BlockNumber bnr,
- GlobalSignalNumber gsn);
-
- void execute(const SignalHeader * const sh,
- Uint8 prio, const Uint32 * const theData, const Uint32 secPtr[3]);
-
- void clear();
- Signal* getVMSignals();
-
- void dumpSignalMemory(FILE * output);
- Priority highestAvailablePrio() const;
- Uint32 getBOccupancy() const;
- void sendPacked();
-
- void insertTimeQueue(Signal* aSignal, BlockNumber bnr,
- GlobalSignalNumber gsn, Uint32 aIndex);
- void scheduleTimeQueue(Uint32 aIndex);
-
-private:
- void highestAvailablePrio(Priority prio);
- void reportJob(Priority aPriority);
- void prio_level_error();
-
- Uint32 theDoJobTotalCounter;
- Uint32 theDoJobCallCounter;
- Uint8 theJobPriority[4096];
- APZJobBuffer theJobBuffers[JB_LEVELS];
-
- void reportDoJobStatistics(Uint32 meanLoopCount);
-};
-
-inline
-Uint32
-FastScheduler::getBOccupancy() const {
- return theJobBuffers[JBB].getOccupancy();
-}//FastScheduler::getBOccupancy()
-
-inline
-int
-FastScheduler::checkDoJob()
-{
- /*
- * Job buffer overload protetction
- * If the job buffer B is filled over a certain limit start
- * to execute the signals in the job buffer's
- */
- if (getBOccupancy() < MAX_OCCUPANCY) {
- return 0;
- } else {
- doJob();
- return 1;
- }//if
-}//FastScheduler::checkDoJob()
-
-inline
-void
-FastScheduler::reportJob(Priority aPriority)
-{
- Uint32 tJobCounter = globalData.JobCounter;
- Uint32 tJobLap = globalData.JobLap;
- theJobPriority[tJobCounter] = (Uint8)aPriority;
- globalData.JobCounter = (tJobCounter + 1) & 4095;
- globalData.JobLap = tJobLap + 1;
-}
-
-inline
-Priority
-FastScheduler::highestAvailablePrio() const
-{
- return (Priority)globalData.highestAvailablePrio;
-}
-
-inline
-void
-FastScheduler::highestAvailablePrio(Priority prio)
-{
- globalData.highestAvailablePrio = (Uint32)prio;
-}
-
-inline
-Signal*
-FastScheduler::getVMSignals()
-{
- return &globalData.VMSignals[0];
-}
-
-
-// Inserts of a protocol object into the Job Buffer.
-inline
-void
-FastScheduler::execute(const SignalHeader * const sh, Uint8 prio,
- const Uint32 * const theData, const Uint32 secPtrI[3]){
-#ifdef VM_TRACE
- if (prio >= LEVEL_IDLE)
- prio_level_error();
-#endif
-
- theJobBuffers[prio].insert(sh, theData, secPtrI);
- if (prio < (Uint8)highestAvailablePrio())
- highestAvailablePrio((Priority)prio);
-}
-
-inline
-void
-FastScheduler::execute(Signal* signal, Priority prio,
- BlockNumber bnr, GlobalSignalNumber gsn)
-{
-#ifdef VM_TRACE
- if (prio >= LEVEL_IDLE)
- prio_level_error();
-#endif
- theJobBuffers[prio].insert(signal, bnr, gsn);
- if (prio < highestAvailablePrio())
- highestAvailablePrio(prio);
-}
-
-inline
-void
-FastScheduler::insertTimeQueue(Signal* signal, BlockNumber bnr,
- GlobalSignalNumber gsn, Uint32 aIndex)
-{
- theJobBuffers[3].insert(signal, bnr, gsn, aIndex);
-}
-
-inline
-void
-FastScheduler::scheduleTimeQueue(Uint32 aIndex)
-{
- Signal* signal = getVMSignals();
- theJobBuffers[3].retrieve(signal, aIndex);
- theJobBuffers[0].insert
- (signal,
- (BlockNumber)signal->header.theReceiversBlockNumber,
- (GlobalSignalNumber)signal->header.theVerId_signalNumber);
- if (highestAvailablePrio() > JBA)
- highestAvailablePrio(JBA);
-}
-
-inline
-Uint32
-APZJobBuffer::getWritePtr() const
-{
- return wPtr;
-}
-
-inline
-Uint32
-APZJobBuffer::getReadPtr() const
-{
- return rPtr;
-}
-
-inline
-Uint32
-APZJobBuffer::getOccupancy() const
-{
- return theOccupancy;
-}
-
-inline
-Uint32
-APZJobBuffer::getBufSize() const
-{
- return bufSize;
-}
-
-inline
-void
-APZJobBuffer::retrieve(Signal* signal, Uint32 myRptr)
-{
- register BufferEntry& buf = buffer[myRptr];
-
- buf.header.theSignalId = globalData.theSignalId++;
-
- signal->header = buf.header;
-
- Uint32 *from = (Uint32*) &buf.theDataRegister[0];
- Uint32 *to = (Uint32*) &signal->theData[0];
- Uint32 noOfWords = buf.header.theLength;
- for(; noOfWords; noOfWords--)
- *to++ = *from++;
- // Copy sections references (copy all without if-statements)
- SegmentedSectionPtr * tSecPtr = &signal->m_sectionPtr[0];
- tSecPtr[0].i = from[0];
- tSecPtr[1].i = from[1];
- tSecPtr[2].i = from[2];
- return;
-}
-
-inline
-void
-APZJobBuffer::retrieveDump(Signal* signal, Uint32 myRptr)
-{
- /**
- * Note that signal id is not taken from global data
- */
-
- register BufferEntry& buf = buffer[myRptr];
- signal->header = buf.header;
-
- Uint32 *from = (Uint32*) &buf.theDataRegister[0];
- Uint32 *to = (Uint32*) &signal->theData[0];
- Uint32 noOfWords = buf.header.theLength;
- for(; noOfWords; noOfWords--)
- *to++ = *from++;
- return;
-}
-
-inline
-void
-APZJobBuffer::insert(Signal* signal,
- BlockNumber bnr, GlobalSignalNumber gsn)
-{
- Uint32 tOccupancy = theOccupancy + 1;
- Uint32 myWPtr = wPtr;
- if (tOccupancy < bufSize) {
- register BufferEntry& buf = buffer[myWPtr];
- Uint32 cond = (++myWPtr == bufSize) - 1;
- wPtr = myWPtr & cond;
- theOccupancy = tOccupancy;
- signal2buffer(signal, bnr, gsn, buf);
- //---------------------------------------------------------
- // Prefetch of buffer[wPtr] is done here. We prefetch for
- // write both the first cache line and the next 64 byte
- // entry
- //---------------------------------------------------------
- WRITEHINT((void*)&buffer[wPtr]);
- WRITEHINT((void*)(((char*)&buffer[wPtr]) + 64));
- } else {
- jbuf_error();
- }//if
-}
-
-
-inline
-void
-APZJobBuffer::insert(Signal* signal, BlockNumber bnr,
- GlobalSignalNumber gsn, Uint32 myWPtr)
-{
- register BufferEntry& buf = buffer[myWPtr];
- signal2buffer(signal, bnr, gsn, buf);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/GlobalData.hpp b/storage/ndb/src/kernel/vm/GlobalData.hpp
deleted file mode 100644
index daf2469af49..00000000000
--- a/storage/ndb/src/kernel/vm/GlobalData.hpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef GLOBAL_DATA_H
-#define GLOBAL_DATA_H
-
-#include <ndb_global.h>
-#include <kernel_types.h>
-#include "Prio.hpp"
-#include "VMSignal.hpp"
-
-#include <BlockNumbers.h>
-#include <NodeState.hpp>
-#include <NodeInfo.hpp>
-#include "ArrayPool.hpp"
-
-class SimulatedBlock;
-
-enum restartStates {initial_state,
- perform_start,
- system_started,
- perform_stop};
-
-struct GlobalData {
- Uint32 m_restart_seq; //
- NodeVersionInfo m_versionInfo;
- NodeInfo m_nodeInfo[MAX_NODES];
- Signal VMSignals[1]; // Owned by FastScheduler::
-
- Uint64 internalMillisecCounter; // Owned by ThreadConfig::
- Uint32 highestAvailablePrio; // Owned by FastScheduler::
- Uint32 JobCounter; // Owned by FastScheduler
- Uint64 JobLap; // Owned by FastScheduler
- Uint32 loopMax; // Owned by FastScheduler
-
- Uint32 theNextTimerJob; // Owned by TimeQueue::
- Uint32 theCurrentTimer; // Owned by TimeQueue::
- Uint32 theShortTQIndex; // Owned by TimeQueue::
-
- Uint32 theLongTQIndex; // Owned by TimeQueue::
- Uint32 theCountTimer; // Owned by TimeQueue::
- Uint32 theFirstFreeTQIndex; // Owned by TimeQueue::
- Uint32 testOn; // Owned by the Signal Loggers
-
- NodeId ownId; // Own processor id
-
- Uint32 theStartLevel;
- restartStates theRestartFlag;
- Uint32 theSignalId;
-
- Uint32 sendPackedActivated;
- Uint32 activateSendPacked;
-
- GlobalData(){
- theSignalId = 0;
- theStartLevel = NodeState::SL_NOTHING;
- theRestartFlag = perform_start;
- }
- ~GlobalData(){}
-
- void setBlock(BlockNumber blockNo, SimulatedBlock * block);
- SimulatedBlock * getBlock(BlockNumber blockNo);
-
- void incrementWatchDogCounter(Uint32 place);
- const Uint32 * getWatchDogPtr();
-
-private:
- Uint32 watchDog;
- SimulatedBlock* blockTable[NO_OF_BLOCKS]; // Owned by Dispatcher::
-public:
- ArrayPool<GlobalPage> m_global_page_pool;
- ArrayPool<GlobalPage> m_shared_page_pool;
-};
-
-extern GlobalData globalData;
-
-#define GLOBAL_TEST_ON (localTestOn)
-#define GET_GLOBAL_TEST_FLAG bool localTestOn = globalData.testOn
-#define SET_GLOBAL_TEST_ON (globalData.testOn = true)
-#define SET_GLOBAL_TEST_OFF (globalData.testOn = false)
-#define TOGGLE_GLOBAL_TEST_FLAG (globalData.testOn = (globalData.testOn == true ? false : true))
-
-inline
-void
-GlobalData::setBlock(BlockNumber blockNo, SimulatedBlock * block){
- blockNo -= MIN_BLOCK_NO;
- assert((blockTable[blockNo] == 0) || (blockTable[blockNo] == block));
- blockTable[blockNo] = block;
-}
-
-inline
-SimulatedBlock *
-GlobalData::getBlock(BlockNumber blockNo){
- blockNo -= MIN_BLOCK_NO;
- return blockTable[blockNo];
-}
-
-inline
-void
-GlobalData::incrementWatchDogCounter(Uint32 place){
- watchDog = place;
-}
-
-inline
-const Uint32 *
-GlobalData::getWatchDogPtr(){
- return &watchDog;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/KeyDescriptor.hpp b/storage/ndb/src/kernel/vm/KeyDescriptor.hpp
deleted file mode 100644
index 8f2f3590695..00000000000
--- a/storage/ndb/src/kernel/vm/KeyDescriptor.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef KEY_DESCRIPTOR_HPP
-#define KEY_DESCRIPTOR_HPP
-
-#include <ndb_types.h>
-#include <ndb_limits.h>
-#include "CArray.hpp"
-
-struct KeyDescriptor
-{
- KeyDescriptor () {
- noOfKeyAttr = hasCharAttr = noOfDistrKeys = noOfVarKeys = 0;
- }
-
- Uint8 noOfKeyAttr;
- Uint8 hasCharAttr;
- Uint8 noOfDistrKeys;
- Uint8 noOfVarKeys;
- struct KeyAttr
- {
- Uint32 attributeDescriptor;
- CHARSET_INFO* charsetInfo;
- } keyAttr[MAX_ATTRIBUTES_IN_INDEX];
-};
-
-extern CArray<KeyDescriptor> g_key_descriptor_pool;
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/KeyTable.hpp b/storage/ndb/src/kernel/vm/KeyTable.hpp
deleted file mode 100644
index 5c26524a861..00000000000
--- a/storage/ndb/src/kernel/vm/KeyTable.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef KEY_TABLE_HPP
-#define KEY_TABLE_HPP
-
-#include <DLHashTable.hpp>
-
-/**
- * KeyTable2 is DLHashTable2 with hardcoded Uint32 key named "key".
- */
-template <typename P, typename T>
-class KeyTableImpl : public DLHashTableImpl<P, T> {
-public:
- KeyTableImpl(P & pool) :
- DLHashTableImpl<P, T>(pool) {
- }
-
- bool find(Ptr<T>& ptr, const T& rec) const {
- return DLHashTableImpl<P, T>::find(ptr, rec);
- }
-
- bool find(Ptr<T>& ptr, Uint32 key) const {
- T rec;
- rec.key = key;
- return DLHashTableImpl<P, T>::find(ptr, rec);
- }
-};
-
-// Specializations
-
-template <typename T>
-class KeyTable : public KeyTableImpl<ArrayPool<T>, T>
-{
-public:
- KeyTable(ArrayPool<T> & p) : KeyTableImpl<ArrayPool<T>, T>(p) {}
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/KeyTable2.hpp b/storage/ndb/src/kernel/vm/KeyTable2.hpp
deleted file mode 100644
index d754fddd64f..00000000000
--- a/storage/ndb/src/kernel/vm/KeyTable2.hpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef KEY_TABLE2_HPP
-#define KEY_TABLE2_HPP
-
-#include <DLHashTable2.hpp>
-
-/**
- * KeyTable2 is DLHashTable2 with hardcoded Uint32 key named "key".
- */
-template <class T, class U>
-class KeyTable2 : public DLHashTable2<T, U> {
-public:
- KeyTable2(ArrayPool<U>& pool) :
- DLHashTable2<T, U>(pool) {
- }
-
- bool find(Ptr<T>& ptr, const T& rec) const {
- return DLHashTable2<T, U>::find(ptr, rec);
- }
-
- bool find(Ptr<T>& ptr, Uint32 key) const {
- T rec;
- rec.key = key;
- return DLHashTable2<T, U>::find(ptr, rec);
- }
-};
-
-template <class T, class U>
-class KeyTable2C : public KeyTable2<T, U> {
- Uint32 m_count;
-public:
- KeyTable2C(ArrayPool<U>& pool) :
- KeyTable2<T, U>(pool), m_count(0) {
- }
-
- Uint32 get_count() const { return m_count; }
-
- bool seize(Ptr<T> & ptr) {
- if (KeyTable2<T, U>::seize(ptr))
- {
- m_count ++;
- return true;
- }
- return false;
- }
-
- void add(Ptr<T> & ptr) {
- KeyTable2<T, U>::add(ptr);
- m_count ++;
- }
-
- void remove(Ptr<T> & ptr, const T & key) {
- KeyTable2<T, U>::remove(ptr, key);
- if (ptr.i != RNIL)
- {
- assert(m_count);
- m_count --;
- }
- }
-
- void remove(Uint32 i) {
- KeyTable2<T, U>::remove(i);
- assert(m_count);
- m_count --;
- }
-
- void remove(Ptr<T> & ptr) {
- KeyTable2<T, U>::remove(ptr);
- assert(m_count);
- m_count --;
- }
-
- void removeAll() {
- KeyTable2<T, U>::removeAll();
- m_count = 0;
- }
-
- void release(Ptr<T> & ptr, const T & key) {
- KeyTable2<T, U>::release(ptr, key);
- if (ptr.i != RNIL)
- {
- assert(m_count);
- m_count --;
- }
- }
-
- void release(Uint32 i) {
- KeyTable2<T, U>::release(i);
- assert(m_count);
- m_count --;
- }
-
- void release(Ptr<T> & ptr) {
- KeyTable2<T, U>::release(ptr);
- assert(m_count);
- m_count --;
- }
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/KeyTable2Ref.hpp b/storage/ndb/src/kernel/vm/KeyTable2Ref.hpp
deleted file mode 100644
index 45373550a52..00000000000
--- a/storage/ndb/src/kernel/vm/KeyTable2Ref.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef KEY_TABLE2_REF_HPP
-#define KEY_TABLE2_REF_HPP
-
-#include "KeyTable2.hpp"
-
-/**
- * KeyTable2 is DLHashTable2 with hardcoded Uint32 key named "key".
- */
-template <class T, class U, class V>
-class KeyTable2Ref
-{
- KeyTable2<U, V>& m_ref;
-public:
- KeyTable2Ref(KeyTable2<U, V>& ref) :m_ref(ref) {}
-
- bool find(Ptr<T>& ptr, Uint32 key) const {
- U rec;
- rec.key = key;
- Ptr<U> tmp;
- bool ret = m_ref.find(tmp, rec);
- ptr.i = tmp.i;
- ptr.p = static_cast<T*>(tmp.p);
- return ret;
- }
-
- bool seize(Ptr<T> & ptr) {
- Ptr<U> tmp;
- bool ret = m_ref.seize(tmp);
- ptr.i = tmp.i;
- ptr.p = static_cast<T*>(tmp.p);
- return ret;
- }
-
- void add(Ptr<T> & ptr) {
- Ptr<U> tmp;
- tmp.i = ptr.i;
- tmp.p = static_cast<U*>(ptr.p);
- m_ref.add(tmp);
- }
-
- void release(Ptr<T> & ptr) {
- Ptr<U> tmp;
- tmp.i = ptr.i;
- tmp.p = static_cast<U*>(ptr.p);
- m_ref.release(tmp);
- }
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/LinearPool.hpp b/storage/ndb/src/kernel/vm/LinearPool.hpp
deleted file mode 100644
index 6d9a7b14a2d..00000000000
--- a/storage/ndb/src/kernel/vm/LinearPool.hpp
+++ /dev/null
@@ -1,656 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef LINEAR_POOL_HPP
-#define LINEAR_POOL_HPP
-
-#include <Bitmask.hpp>
-#include "SuperPool.hpp"
-
-/*
- * LinearPool - indexed record pool
- *
- * LinearPool implements a pool where each record has a 0-based index.
- * Any index value (up to 2^32-1) is allowed. Normal efficient usage is
- * to assign index values in sequence and to re-use any values which
- * have become free. This is default seize/release behaviour.
- *
- * LinearPool has 2 internal RecordPool instances:
- *
- * (a) record pool of T (the template argument class)
- * (b) record pool of "maps" (array of Uint32)
- *
- * The maps translate an index into an i-value in (a). Each map has
- * a level. Level 0 maps point to i-values. Level N+1 maps point to
- * level N maps. There is a unique "root map" at top.
- *
- * This works exactly like numbers in a given base. Each map has base
- * size entries. For implementation convenience the base must be power
- * of 2 between 2^1 and 2^15. It is given by its log2 value (1-15).
- *
- * A position in a map is also called a "digit".
- *
- * There is a doubly linked list of available maps (some free entries)
- * on each level. There is a doubly linked freelist within each map.
- * There is also a bitmask of used entries in each map.
- *
- * Level 0 free entry has space for one record. Level N free entry
- * implies space for base^N records. The implied levels are created and
- * removed on demand. Empty maps are usually removed.
- *
- * Default base is 256 (log2 = 8) which requires maximum 4 levels or
- * digits (similar to ip address).
- *
- * TODO
- *
- * - move most of the inline code to LinearPool.cpp
- * - optimize for common case
- * - add optimized 2-level implementation (?)
- */
-
-#include "SuperPool.hpp"
-
-template <class T, Uint32 LogBase = 8>
-class LinearPool {
- typedef SuperPool::PtrI PtrI;
-
- // Base.
- STATIC_CONST( Base = 1 << LogBase );
-
- // Digit mask.
- STATIC_CONST( DigitMask = Base - 1 );
-
- // Max possible levels (0 to max root level).
- STATIC_CONST( MaxLevels = (32 + LogBase - 1) / LogBase );
-
- // Number of words in map used bit mask.
- STATIC_CONST( BitmaskSize = (Base + 31) / 32 );
-
- // Map.
- struct Map {
- Uint32 m_level;
- Uint32 m_occup; // number of used entries
- Uint32 m_firstfree; // position of first free entry
- PtrI m_parent; // parent map
- Uint32 m_index; // from root to here
- PtrI m_nextavail;
- PtrI m_prevavail;
- Uint32 m_bitmask[BitmaskSize];
- PtrI m_entry[Base];
- };
-
-public:
-
- // Constructor.
- LinearPool(GroupPool& gp);
-
- // Destructor.
- ~LinearPool();
-
- // Update pointer ptr.p according to index value ptr.i.
- void getPtr(Ptr<T>& ptr);
-
- // Allocate record from the pool. Reuses free index if possible.
- bool seize(Ptr<T>& ptr);
-
- // Allocate given index. Like seize but returns -1 if in use.
- int seize_index(Ptr<T>& ptr, Uint32 index);
-
- // Return record to the pool.
- void release(Ptr<T>& ptr);
-
- // Return number of used records (may require 1 page scan).
- Uint32 count();
-
- // Verify (debugging).
- void verify();
-
-private:
-
- // Given index find the bottom map.
- void get_map(Ptr<Map>& map_ptr, Uint32 index);
-
- // Add new root map and increase level
- bool add_root();
-
- // Add new non-root map.
- bool add_map(Ptr<Map>& map_ptr, Ptr<Map> parent_ptr, Uint32 digit);
-
- // Subroutine to initialize map free lists.
- void init_free(Ptr<Map> map_ptr);
-
- // Add entry at given free position.
- void add_entry(Ptr<Map> map_ptr, Uint32 digit, PtrI ptr_i);
-
- // Remove entry and map if it becomes empty.
- void remove_entry(Ptr<Map> map_ptr, Uint32 digit);
-
- // Remove map and all parents which become empty.
- void remove_map(Ptr<Map> map_ptr);
-
- // Add map to available list.
- void add_avail(Ptr<Map> map_ptr);
-
- // Remove map from available list.
- void remove_avail(Ptr<Map> map_ptr);
-
- // Verify available lists
- void verify_avail();
-
- // Verify map (recursive).
- void verify_map(Ptr<Map> map_ptr, Uint32 level, Uint32* count);
-
- RecordPool<T> m_records;
- RecordPool<Map> m_maps;
- Uint32 m_levels; // 0 means empty pool
- PtrI m_root;
- PtrI m_avail[MaxLevels];
-};
-
-template <class T, Uint32 LogBase>
-inline
-LinearPool<T, LogBase>::LinearPool(GroupPool& gp) :
- m_records(gp),
- m_maps(gp),
- m_levels(0),
- m_root(RNIL)
-{
- Uint32 n;
- for (n = 0; n < MaxLevels; n++)
- m_avail[n] = RNIL;
-}
-
-template <class T, Uint32 LogBase>
-inline
-LinearPool<T, LogBase>::~LinearPool()
-{
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::getPtr(Ptr<T>& ptr)
-{
- Uint32 index = ptr.i;
- // get level 0 map
- Ptr<Map> map_ptr;
- get_map(map_ptr, index);
- // get record
- Ptr<T> rec_ptr;
- Uint32 digit = index & DigitMask;
- assert(BitmaskImpl::get(BitmaskSize, map_ptr.p->m_bitmask, digit));
- rec_ptr.i = map_ptr.p->m_entry[digit];
- m_records.getPtr(rec_ptr);
- ptr.p = rec_ptr.p;
-}
-
-template <class T, Uint32 LogBase>
-inline bool
-LinearPool<T, LogBase>::seize(Ptr<T>& ptr)
-{
- // look for free list on some level
- Ptr<Map> map_ptr;
- map_ptr.i = RNIL;
- Uint32 n = 0;
- while (n < m_levels) {
- if ((map_ptr.i = m_avail[n]) != RNIL)
- break;
- n++;
- }
- if (map_ptr.i == RNIL) {
- // add new level with available maps
- if (! add_root())
- return false;
- assert(n < m_levels);
- map_ptr.i = m_avail[n];
- }
- m_maps.getPtr(map_ptr);
- // walk down creating missing levels and using an entry on each
- Uint32 digit;
- Ptr<Map> new_ptr;
- new_ptr.i = RNIL;
- while (true) {
- digit = map_ptr.p->m_firstfree;
- if (n == 0)
- break;
- Ptr<Map> child_ptr;
- if (! add_map(child_ptr, map_ptr, digit)) {
- if (new_ptr.i != RNIL)
- remove_map(new_ptr);
- return false;
- }
- new_ptr = child_ptr;
- map_ptr = child_ptr;
- n--;
- }
- // now on level 0
- assert(map_ptr.p->m_level == 0);
- Ptr<T> rec_ptr;
- if (! m_records.seize(rec_ptr)) {
- if (new_ptr.i != RNIL)
- remove_map(new_ptr);
- return false;
- }
- add_entry(map_ptr, digit, rec_ptr.i);
- ptr.i = digit + (map_ptr.p->m_index << LogBase);
- ptr.p = rec_ptr.p;
- return true;
-}
-
-template <class T, Uint32 LogBase>
-inline int
-LinearPool<T, LogBase>::seize_index(Ptr<T>& ptr, Uint32 index)
-{
- // extract all digits at least up to current root level
- Uint32 digits[MaxLevels];
- Uint32 n = 0;
- Uint32 tmp = index;
- do {
- digits[n] = tmp & DigitMask;
- tmp >>= LogBase;
- } while (++n < m_levels || tmp != 0);
- // add any new root levels
- while (n > m_levels) {
- if (! add_root())
- return false;
- }
- // start from root
- Ptr<Map> map_ptr;
- map_ptr.i = m_root;
- m_maps.getPtr(map_ptr);
- // walk down creating or re-using existing levels
- Uint32 digit;
- bool used;
- Ptr<Map> new_ptr;
- new_ptr.i = RNIL;
- while (true) {
- digit = digits[--n];
- used = BitmaskImpl::get(BitmaskSize, map_ptr.p->m_bitmask, digit);
- if (n == 0)
- break;
- if (used) {
- map_ptr.i = map_ptr.p->m_entry[digit];
- m_maps.getPtr(map_ptr);
- } else {
- Ptr<Map> child_ptr;
- if (! add_map(child_ptr, map_ptr, digit)) {
- if (new_ptr.i != RNIL)
- remove_map(new_ptr);
- }
- new_ptr = child_ptr;
- map_ptr = child_ptr;
- }
- }
- // now at level 0
- assert(map_ptr.p->m_level == 0);
- Ptr<T> rec_ptr;
- if (used || ! m_records.seize(rec_ptr)) {
- if (new_ptr.i != RNIL)
- remove_map(new_ptr);
- return used ? -1 : false;
- }
- add_entry(map_ptr, digit, rec_ptr.i);
- assert(index == digit + (map_ptr.p->m_index << LogBase));
- ptr.i = index;
- ptr.p = rec_ptr.p;
- return true;
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::release(Ptr<T>& ptr)
-{
- Uint32 index = ptr.i;
- // get level 0 map
- Ptr<Map> map_ptr;
- get_map(map_ptr, index);
- // release record
- Ptr<T> rec_ptr;
- Uint32 digit = index & DigitMask;
- rec_ptr.i = map_ptr.p->m_entry[digit];
- m_records.release(rec_ptr);
- // remove entry
- remove_entry(map_ptr, digit);
- // null pointer
- ptr.i = RNIL;
- ptr.p = 0;
-}
-
-template <class T, Uint32 LogBase>
-inline Uint32
-LinearPool<T, LogBase>::count()
-{
- SuperPool& sp = m_records.m_superPool;
- Uint32 count1 = sp.getRecUseCount(m_records.m_recInfo);
- return count1;
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::verify()
-{
- verify_avail();
- if (m_root == RNIL) {
- assert(m_levels == 0);
- return;
- }
- assert(m_levels != 0);
- Ptr<Map> map_ptr;
- map_ptr.i = m_root;
- m_maps.getPtr(map_ptr);
- Uint32 count1 = count();
- Uint32 count2 = 0;
- verify_map(map_ptr, m_levels - 1, &count2);
- assert(count1 == count2);
-}
-
-// private methods
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::get_map(Ptr<Map>& map_ptr, Uint32 index)
-{
- // root map must exist
- Ptr<Map> tmp_ptr;
- tmp_ptr.i = m_root;
- m_maps.getPtr(tmp_ptr);
- assert(tmp_ptr.p->m_level + 1 == m_levels);
- // extract index digits up to current root level
- Uint32 digits[MaxLevels];
- Uint32 n = 0;
- do {
- digits[n] = index & DigitMask;
- index >>= LogBase;
- } while (++n < m_levels);
- assert(index == 0);
- // walk down indirect levels
- while (--n > 0) {
- tmp_ptr.i = tmp_ptr.p->m_entry[digits[n]];
- m_maps.getPtr(tmp_ptr);
- }
- // level 0 map
- assert(tmp_ptr.p->m_level == 0);
- map_ptr = tmp_ptr;
-}
-
-template <class T, Uint32 LogBase>
-inline bool
-LinearPool<T, LogBase>::add_root()
-{
- // new root
- Ptr<Map> map_ptr;
- if (! m_maps.seize(map_ptr))
- return false;
- Uint32 n = m_levels++;
- assert(n < MaxLevels);
- // set up
- map_ptr.p->m_level = n;
- map_ptr.p->m_parent = RNIL;
- map_ptr.p->m_index = 0;
- init_free(map_ptr);
- // on level > 0 digit 0 points to old root
- if (n > 0) {
- Ptr<Map> old_ptr;
- old_ptr.i = m_root;
- m_maps.getPtr(old_ptr);
- assert(old_ptr.p->m_parent == RNIL);
- old_ptr.p->m_parent = map_ptr.i;
- add_entry(map_ptr, 0, old_ptr.i);
- }
- // set new root
- m_root = map_ptr.i;
- return true;
-}
-
-template <class T, Uint32 LogBase>
-inline bool
-LinearPool<T, LogBase>::add_map(Ptr<Map>& map_ptr, Ptr<Map> parent_ptr, Uint32 digit)
-{
- if (! m_maps.seize(map_ptr))
- return false;
- assert(parent_ptr.p->m_level != 0);
- // set up
- map_ptr.p->m_level = parent_ptr.p->m_level - 1;
- map_ptr.p->m_parent = parent_ptr.i;
- map_ptr.p->m_index = digit + (parent_ptr.p->m_index << LogBase);
- init_free(map_ptr);
- add_entry(parent_ptr, digit, map_ptr.i);
- return true;
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::init_free(Ptr<Map> map_ptr)
-{
- map_ptr.p->m_occup = 0;
- map_ptr.p->m_firstfree = 0;
- // freelist
- Uint32 j;
- Uint16 back = ZNIL;
- for (j = 0; j < Base - 1; j++) {
- map_ptr.p->m_entry[j] = back | ((j + 1) << 16);
- back = j;
- }
- map_ptr.p->m_entry[j] = back | (ZNIL << 16);
- // bitmask
- BitmaskImpl::clear(BitmaskSize, map_ptr.p->m_bitmask);
- // add to available
- add_avail(map_ptr);
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::add_entry(Ptr<Map> map_ptr, Uint32 digit, PtrI ptr_i)
-{
- assert(map_ptr.p->m_occup < Base && digit < Base);
- assert(! BitmaskImpl::get(BitmaskSize, map_ptr.p->m_bitmask, digit));
- // unlink from freelist
- Uint32 val = map_ptr.p->m_entry[digit];
- Uint16 back = val & ZNIL;
- Uint16 forw = val >> 16;
- if (back != ZNIL) {
- assert(back < Base);
- map_ptr.p->m_entry[back] &= ZNIL;
- map_ptr.p->m_entry[back] |= (forw << 16);
- }
- if (forw != ZNIL) {
- assert(forw < Base);
- map_ptr.p->m_entry[forw] &= (ZNIL << 16);
- map_ptr.p->m_entry[forw] |= back;
- }
- if (back == ZNIL) {
- map_ptr.p->m_firstfree = forw;
- }
- // set new value
- map_ptr.p->m_entry[digit] = ptr_i;
- map_ptr.p->m_occup++;
- BitmaskImpl::set(BitmaskSize, map_ptr.p->m_bitmask, digit);
- if (map_ptr.p->m_occup == Base)
- remove_avail(map_ptr);
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::remove_entry(Ptr<Map> map_ptr, Uint32 digit)
-{
- assert(map_ptr.p->m_occup != 0 && digit < Base);
- assert(BitmaskImpl::get(BitmaskSize, map_ptr.p->m_bitmask, digit));
- // add to freelist
- Uint32 firstfree = map_ptr.p->m_firstfree;
- map_ptr.p->m_entry[digit] = ZNIL | (firstfree << 16);
- if (firstfree != ZNIL) {
- assert(firstfree < Base);
- map_ptr.p->m_entry[firstfree] &= (ZNIL << 16);
- map_ptr.p->m_entry[firstfree] |= digit;
- }
- map_ptr.p->m_firstfree = digit;
- map_ptr.p->m_occup--;
- BitmaskImpl::clear(BitmaskSize, map_ptr.p->m_bitmask, digit);
- if (map_ptr.p->m_occup + 1 == Base)
- add_avail(map_ptr);
- else if (map_ptr.p->m_occup == 0)
- remove_map(map_ptr);
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::remove_map(Ptr<Map> map_ptr)
-{
- assert(map_ptr.p->m_occup == 0);
- remove_avail(map_ptr);
- Ptr<Map> parent_ptr;
- parent_ptr.i = map_ptr.p->m_parent;
- Uint32 digit = map_ptr.p->m_index & DigitMask;
- PtrI map_ptr_i = map_ptr.i;
- m_maps.release(map_ptr);
- if (m_root == map_ptr_i) {
- assert(parent_ptr.i == RNIL);
- Uint32 used = count();
- assert(used == 0);
- m_root = RNIL;
- m_levels = 0;
- }
- if (parent_ptr.i != RNIL) {
- m_maps.getPtr(parent_ptr);
- // remove child entry (recursive)
- remove_entry(parent_ptr, digit);
- }
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::add_avail(Ptr<Map> map_ptr)
-{
- Uint32 n = map_ptr.p->m_level;
- assert(n < m_levels);
- map_ptr.p->m_nextavail = m_avail[n];
- if (map_ptr.p->m_nextavail != RNIL) {
- Ptr<Map> next_ptr;
- next_ptr.i = map_ptr.p->m_nextavail;
- m_maps.getPtr(next_ptr);
- next_ptr.p->m_prevavail = map_ptr.i;
- }
- map_ptr.p->m_prevavail = RNIL;
- m_avail[n] = map_ptr.i;
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::remove_avail(Ptr<Map> map_ptr)
-{
- Uint32 n = map_ptr.p->m_level;
- assert(n < m_levels);
- if (map_ptr.p->m_nextavail != RNIL) {
- Ptr<Map> next_ptr;
- next_ptr.i = map_ptr.p->m_nextavail;
- m_maps.getPtr(next_ptr);
- next_ptr.p->m_prevavail = map_ptr.p->m_prevavail;
- }
- if (map_ptr.p->m_prevavail != RNIL) {
- Ptr<Map> prev_ptr;
- prev_ptr.i = map_ptr.p->m_prevavail;
- m_maps.getPtr(prev_ptr);
- prev_ptr.p->m_nextavail = map_ptr.p->m_nextavail;
- }
- if (map_ptr.p->m_prevavail == RNIL) {
- m_avail[n] = map_ptr.p->m_nextavail;
- }
- map_ptr.p->m_nextavail = RNIL;
- map_ptr.p->m_prevavail = RNIL;
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::verify_avail()
-{
- // check available lists
- for (Uint32 n = 0; n < MaxLevels; n++) {
- Ptr<Map> map_ptr;
- map_ptr.i = m_avail[n];
- Uint32 back = RNIL;
- while (map_ptr.i != RNIL) {
- m_maps.getPtr(map_ptr);
- assert(map_ptr.p->m_occup < Base);
- assert(back == map_ptr.p->m_prevavail);
- back = map_ptr.i;
- map_ptr.i = map_ptr.p->m_nextavail;
- }
- }
-}
-
-template <class T, Uint32 LogBase>
-inline void
-LinearPool<T, LogBase>::verify_map(Ptr<Map> map_ptr, Uint32 level, Uint32* count)
-{
- assert(level < MaxLevels);
- assert(map_ptr.p->m_level == level);
- // check freelist
- {
- Uint32 nused = BitmaskImpl::count(BitmaskSize, map_ptr.p->m_bitmask);
- assert(nused <= Base);
- assert(map_ptr.p->m_occup == nused);
- Uint32 nfree = 0;
- Uint32 j = map_ptr.p->m_firstfree;
- Uint16 back = ZNIL;
- while (j != ZNIL) {
- assert(j < Base);
- assert(! BitmaskImpl::get(BitmaskSize, map_ptr.p->m_bitmask, j));
- Uint32 val = map_ptr.p->m_entry[j];
- assert(back == (val & ZNIL));
- back = j;
- j = (val >> 16);
- nfree++;
- }
- assert(nused + nfree == Base);
- }
- // check entries
- {
- for (Uint32 j = 0; j < Base; j++) {
- bool free = ! BitmaskImpl::get(BitmaskSize, map_ptr.p->m_bitmask, j);
- if (free)
- continue;
- if (level != 0) {
- Ptr<Map> child_ptr;
- child_ptr.i = map_ptr.p->m_entry[j];
- m_maps.getPtr(child_ptr);
- assert(child_ptr.p->m_parent == map_ptr.i);
- assert(child_ptr.p->m_index == j + (map_ptr.p->m_index << LogBase));
- verify_map(child_ptr, level - 1, count);
- } else {
- Ptr<T> rec_ptr;
- rec_ptr.i = map_ptr.p->m_entry[j];
- m_records.getPtr(rec_ptr);
- (*count)++;
- }
- }
- }
- // check membership on available list
- {
- Ptr<Map> avail_ptr;
- avail_ptr.i = m_avail[map_ptr.p->m_level];
- bool found = false;
- while (avail_ptr.i != RNIL) {
- if (avail_ptr.i == map_ptr.i) {
- found = true;
- break;
- }
- m_maps.getPtr(avail_ptr);
- avail_ptr.i = avail_ptr.p->m_nextavail;
- }
- assert(found == (map_ptr.p->m_occup < Base));
- }
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/LongSignal.hpp b/storage/ndb/src/kernel/vm/LongSignal.hpp
deleted file mode 100644
index 5f4f9744c45..00000000000
--- a/storage/ndb/src/kernel/vm/LongSignal.hpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef LONG_SIGNAL_HPP
-#define LONG_SIGNAL_HPP
-
-#include "pc.hpp"
-#include <ArrayPool.hpp>
-
-/**
- * Section handling
- */
-struct SectionSegment {
-
- STATIC_CONST( DataLength = NDB_SECTION_SEGMENT_SZ );
-
- Uint32 m_ownerRef;
- Uint32 m_sz;
- Uint32 m_lastSegment;
- union {
- Uint32 m_nextSegment;
- Uint32 nextPool;
- };
- Uint32 theData[DataLength];
-};
-
-/**
- * Pool for SectionSegments
- */
-class SectionSegmentPool : public ArrayPool<SectionSegment> {};
-
-/**
- * And the instance
- */
-extern SectionSegmentPool g_sectionSegmentPool;
-
-/**
- * Function prototypes
- */
-void print(SegmentedSectionPtr ptr, FILE* out);
-void copy(SegmentedSectionPtr dst, Uint32 * src, Uint32 len);
-void copy(Uint32 * dst, SegmentedSectionPtr src);
-bool import(Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len);
-
-extern class SectionSegmentPool g_sectionSegmentPool;
-void getSection(SegmentedSectionPtr & ptr, Uint32 id);
-void linkSegments(Uint32 head, Uint32 tail);
-
-void getSections(Uint32 secCount, SegmentedSectionPtr ptr[3]);
-void releaseSections(Uint32 secCount, SegmentedSectionPtr ptr[3]);
-
-
-#include "DataBuffer.hpp"
-
-template<Uint32 sz>
-void
-append(DataBuffer<sz>& dst, SegmentedSectionPtr ptr, SectionSegmentPool& pool){
- Uint32 len = ptr.sz;
- while(len > SectionSegment::DataLength){
- dst.append(ptr.p->theData, SectionSegment::DataLength);
- ptr.p = pool.getPtr(ptr.p->m_nextSegment);
- len -= SectionSegment::DataLength;
- }
- dst.append(ptr.p->theData, len);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/Makefile.am b/storage/ndb/src/kernel/vm/Makefile.am
deleted file mode 100644
index a862da610bd..00000000000
--- a/storage/ndb/src/kernel/vm/Makefile.am
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright (C) 2004-2005 MySQL AB
-# Use is subject to license terms
-#
-# 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; version 2 of the License.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-#SUBDIRS = testCopy testDataBuffer testSimplePropertiesSection
-#ifneq ($(USE_EDITLINE), N)
-#DIRS += testLongSig
-#endif
-
-noinst_LIBRARIES = libkernel.a
-
-libkernel_a_SOURCES = \
- SimulatedBlock.cpp \
- FastScheduler.cpp \
- TimeQueue.cpp \
- VMSignal.cpp \
- ThreadConfig.cpp \
- TransporterCallback.cpp \
- Emulator.cpp \
- Configuration.cpp \
- WatchDog.cpp \
- SimplePropertiesSection.cpp \
- SectionReader.cpp \
- Mutex.cpp SafeCounter.cpp \
- Rope.cpp \
- ndbd_malloc.cpp ndbd_malloc_impl.cpp \
- Pool.cpp WOPool.cpp RWPool.cpp \
- DynArr256.cpp
-
-INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/mgmapi
-
-include $(top_srcdir)/storage/ndb/config/common.mk.am
-include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
-
-windoze-dsp: libkernel.dsp
-
-libkernel.dsp: Makefile \
- $(top_srcdir)/storage/ndb/config/win-lib.am \
- $(top_srcdir)/storage/ndb/config/win-name \
- $(top_srcdir)/storage/ndb/config/win-includes \
- $(top_srcdir)/storage/ndb/config/win-sources \
- $(top_srcdir)/storage/ndb/config/win-libraries
- cat $(top_srcdir)/storage/ndb/config/win-lib.am > $@
- @$(top_srcdir)/storage/ndb/config/win-name $@ $(noinst_LIBRARIES)
- @$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES)
- @$(top_srcdir)/storage/ndb/config/win-sources $@ $(libkernel_a_SOURCES)
- @$(top_srcdir)/storage/ndb/config/win-libraries $@ LIB $(LDADD)
-
-EXTRA_PROGRAMS = ndbd_malloc_impl_test bench_pool testDynArr256
-ndbd_malloc_impl_test_CXXFLAGS = -DUNIT_TEST
-ndbd_malloc_impl_test_SOURCES = ndbd_malloc_impl.cpp
-ndbd_malloc_impl_test_LDFLAGS = @ndb_bin_am_ldflags@ \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
-
-bench_pool_SOURCES = bench_pool.cpp
-bench_pool_LDFLAGS = @ndb_bin_am_ldflags@\
- libkernel.a ../error/liberror.a \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
-
-testDynArr256_CXXFLAGS = -DUNIT_TEST
-testDynArr256_SOURCES = DynArr256.cpp
-testDynArr256_LDFLAGS = @ndb_bin_am_ldflags@ \
- libkernel.a ../error/liberror.a \
- $(top_builddir)/storage/ndb/src/libndbclient.la \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a
-
diff --git a/storage/ndb/src/kernel/vm/Mutex.cpp b/storage/ndb/src/kernel/vm/Mutex.cpp
deleted file mode 100644
index e489386e3df..00000000000
--- a/storage/ndb/src/kernel/vm/Mutex.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include "SimulatedBlock.hpp"
-#include "Mutex.hpp"
-#include <signaldata/UtilLock.hpp>
-
-SimulatedBlock::MutexManager::MutexManager(class SimulatedBlock & block)
- : m_block(block),
- m_activeMutexes(m_mutexPool) {
-}
-
-bool
-SimulatedBlock::MutexManager::setSize(Uint32 maxNoOfActiveMutexes){
- return m_mutexPool.setSize(maxNoOfActiveMutexes);
-}
-
-Uint32
-SimulatedBlock::MutexManager::getSize() const {
- return m_mutexPool.getSize();
-}
-
-bool
-SimulatedBlock::MutexManager::seize(ActiveMutexPtr& ptr){
- return m_activeMutexes.seize(ptr);
-}
-
-void
-SimulatedBlock::MutexManager::release(Uint32 activeMutexPtrI){
- m_activeMutexes.release(activeMutexPtrI);
-}
-
-void
-SimulatedBlock::MutexManager::getPtr(ActiveMutexPtr& ptr){
- m_activeMutexes.getPtr(ptr);
-}
-
-BlockReference
-SimulatedBlock::MutexManager::reference() const {
- return m_block.reference();
-}
-
-void
-SimulatedBlock::MutexManager::progError(int line,
- int err_code,
- const char* extra)
-{
- m_block.progError(line, err_code, extra);
-}
-
-void
-SimulatedBlock::MutexManager::create(Signal* signal, ActiveMutexPtr& ptr){
-
- UtilCreateLockReq * req = (UtilCreateLockReq*)signal->getDataPtrSend();
- req->senderData = ptr.i;
- req->senderRef = m_block.reference();
- req->lockId = ptr.p->m_mutexId;
- req->lockType = UtilCreateLockReq::Mutex;
-
- m_block.sendSignal(DBUTIL_REF,
- GSN_UTIL_CREATE_LOCK_REQ,
- signal,
- UtilCreateLockReq::SignalLength,
- JBB);
-
- ptr.p->m_gsn = GSN_UTIL_CREATE_LOCK_REQ;
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_CREATE_LOCK_REF(Signal* signal){
-
- UtilCreateLockRef * ref = (UtilCreateLockRef*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, ref->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_CREATE_LOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == ref->lockId);
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, ref->errorCode);
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_CREATE_LOCK_CONF(Signal* signal){
-
- UtilCreateLockConf * conf = (UtilCreateLockConf*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, conf->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_CREATE_LOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == conf->lockId);
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, 0);
-}
-
-
-void
-SimulatedBlock::MutexManager::destroy(Signal* signal, ActiveMutexPtr& ptr){
-
- UtilDestroyLockReq * req = (UtilDestroyLockReq*)signal->getDataPtrSend();
- req->senderData = ptr.i;
- req->senderRef = m_block.reference();
- req->lockId = ptr.p->m_mutexId;
- req->lockKey = ptr.p->m_mutexKey;
-
- m_block.sendSignal(DBUTIL_REF,
- GSN_UTIL_DESTROY_LOCK_REQ,
- signal,
- UtilDestroyLockReq::SignalLength,
- JBB);
-
- ptr.p->m_gsn = GSN_UTIL_DESTROY_LOCK_REQ;
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_DESTORY_LOCK_REF(Signal* signal){
- UtilDestroyLockRef * ref = (UtilDestroyLockRef*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, ref->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_DESTROY_LOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == ref->lockId);
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, ref->errorCode);
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_DESTORY_LOCK_CONF(Signal* signal){
- UtilDestroyLockConf * conf = (UtilDestroyLockConf*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, conf->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_DESTROY_LOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == conf->lockId);
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, 0);
-}
-
-
-void
-SimulatedBlock::MutexManager::lock(Signal* signal, ActiveMutexPtr& ptr){
-
- UtilLockReq * req = (UtilLockReq*)signal->getDataPtrSend();
- req->senderData = ptr.i;
- req->senderRef = m_block.reference();
- req->lockId = ptr.p->m_mutexId;
- req->requestInfo = 0;
-
- m_block.sendSignal(DBUTIL_REF,
- GSN_UTIL_LOCK_REQ,
- signal,
- UtilLockReq::SignalLength,
- JBB);
-
- ptr.p->m_gsn = GSN_UTIL_LOCK_REQ;
-}
-
-void
-SimulatedBlock::MutexManager::trylock(Signal* signal, ActiveMutexPtr& ptr){
-
- UtilLockReq * req = (UtilLockReq*)signal->getDataPtrSend();
- req->senderData = ptr.i;
- req->senderRef = m_block.reference();
- req->lockId = ptr.p->m_mutexId;
- req->requestInfo = UtilLockReq::TryLock;
-
- m_block.sendSignal(DBUTIL_REF,
- GSN_UTIL_LOCK_REQ,
- signal,
- UtilLockReq::SignalLength,
- JBB);
-
- ptr.p->m_gsn = GSN_UTIL_LOCK_REQ;
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_LOCK_REF(Signal* signal){
- UtilLockRef * ref = (UtilLockRef*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, ref->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_LOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == ref->lockId);
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, ref->errorCode);
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_LOCK_CONF(Signal* signal){
- UtilLockConf * conf = (UtilLockConf*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, conf->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_LOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == conf->lockId);
-
- ptr.p->m_mutexKey = conf->lockKey;
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, 0);
-}
-
-void
-SimulatedBlock::MutexManager::unlock(Signal* signal, ActiveMutexPtr& ptr){
- UtilUnlockReq * req = (UtilUnlockReq*)signal->getDataPtrSend();
- req->senderData = ptr.i;
- req->senderRef = m_block.reference();
- req->lockId = ptr.p->m_mutexId;
- req->lockKey = ptr.p->m_mutexKey;
-
- m_block.sendSignal(DBUTIL_REF,
- GSN_UTIL_UNLOCK_REQ,
- signal,
- UtilUnlockReq::SignalLength,
- JBB);
-
- ptr.p->m_gsn = GSN_UTIL_UNLOCK_REQ;
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_UNLOCK_REF(Signal* signal){
- UtilUnlockRef * ref = (UtilUnlockRef*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, ref->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_UNLOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == ref->lockId);
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, ref->errorCode);
-}
-
-void
-SimulatedBlock::MutexManager::execUTIL_UNLOCK_CONF(Signal* signal){
- UtilUnlockConf * conf = (UtilUnlockConf*)signal->getDataPtr();
- ActiveMutexPtr ptr;
- m_activeMutexes.getPtr(ptr, conf->senderData);
- ndbrequire(ptr.p->m_gsn == GSN_UTIL_UNLOCK_REQ);
- ndbrequire(ptr.p->m_mutexId == conf->lockId);
-
- ptr.p->m_gsn = 0;
- m_block.execute(signal, ptr.p->m_callback, 0);
-}
-
-void
-Mutex::release(SimulatedBlock::MutexManager& mgr,
- Uint32 activePtrI, Uint32 mutexId){
- SimulatedBlock::MutexManager::ActiveMutexPtr ptr;
- ptr.i = activePtrI;
- mgr.getPtr(ptr);
- if(ptr.p->m_gsn == 0 && ptr.p->m_mutexId == mutexId){
- mgr.release(activePtrI);
- return;
- }
-
- if(ptr.p->m_mutexId != mutexId)
- ErrorReporter::handleAssert("MutexHandle::release invalid handle",
- __FILE__, __LINE__);
- ErrorReporter::handleAssert("MutexHandle::release of mutex inuse",
- __FILE__, __LINE__);
-}
-
-void
-Mutex::unlock(){
- if(!m_ptr.isNull()){
- m_mgr.getPtr(m_ptr);
- if(m_ptr.p->m_mutexId == m_mutexId){
- SimulatedBlock::Callback c =
- { &SimulatedBlock::ignoreMutexUnlockCallback, m_ptr.i };
- m_ptr.p->m_callback = c;
- m_mgr.unlock(m_signal, m_ptr);
- m_ptr.setNull(); // Remove reference
- }
- }
-}
-
diff --git a/storage/ndb/src/kernel/vm/Mutex.hpp b/storage/ndb/src/kernel/vm/Mutex.hpp
deleted file mode 100644
index eb45e27f80e..00000000000
--- a/storage/ndb/src/kernel/vm/Mutex.hpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef BLOCK_MUTEX_HPP
-#define BLOCK_MUTEX_HPP
-
-#include "Callback.hpp"
-#include "SimulatedBlock.hpp"
-
-class Mutex;
-
-/**
- * MutexHandle - A "reference" to a mutex
- * - Should be used together with Mutex
- */
-class MutexHandle {
- friend class Mutex;
-public:
- MutexHandle(Uint32 id);
-
- bool isNull() const;
- void release(SimulatedBlock::MutexManager & mgr);
-
-private:
- const Uint32 m_mutexId;
- Uint32 m_activeMutexPtrI;
-};
-
-/**
- * MutexHandle2 - A template-based "reference" to a mutex
- */
-template<Uint32 MutexId>
-class MutexHandle2 {
- friend class Mutex;
-public:
- MutexHandle2();
-
- bool isNull() const;
- void release(SimulatedBlock::MutexManager & mgr);
-
-private:
- Uint32 m_activeMutexPtrI;
-};
-
-/**
- * A mutex - Used together with a MutexHandle to be put on the stack
- */
-class Mutex {
-public:
- Mutex(Signal*, SimulatedBlock::MutexManager & mgr, MutexHandle &);
-
- template<Uint32 MutexId>
- Mutex(Signal*, SimulatedBlock::MutexManager & mgr, MutexHandle2<MutexId> &);
-
- ~Mutex();
-
- void release();
- bool isNull() const ;
-
- bool lock(SimulatedBlock::Callback & callback);
- bool trylock(SimulatedBlock::Callback & callback);
- void unlock(SimulatedBlock::Callback & callback);
- void unlock(); // Ignore callback
-
- bool create(SimulatedBlock::Callback & callback);
- bool destroy(SimulatedBlock::Callback & callback);
-
-private:
- Signal* m_signal;
- SimulatedBlock::MutexManager & m_mgr;
- const Uint32 m_mutexId;
- Uint32 & m_srcPtrI;
- SimulatedBlock::MutexManager::ActiveMutexPtr m_ptr;
-
-public:
- static void release(SimulatedBlock::MutexManager&,
- Uint32 activePtrI, Uint32 mutexId);
-};
-
-inline
-MutexHandle::MutexHandle(Uint32 id) : m_mutexId(id) {
- m_activeMutexPtrI = RNIL;
-}
-
-inline
-bool
-MutexHandle::isNull() const {
- return m_activeMutexPtrI == RNIL;
-}
-
-inline
-void
-MutexHandle::release(SimulatedBlock::MutexManager & mgr){
- if(!isNull()){
- Mutex::release(mgr, m_activeMutexPtrI, m_mutexId);
- m_activeMutexPtrI = RNIL;
- }
-}
-
-template<Uint32 MutexId>
-inline
-MutexHandle2<MutexId>::MutexHandle2() {
- m_activeMutexPtrI = RNIL;
-}
-
-template<Uint32 MutexId>
-inline
-bool
-MutexHandle2<MutexId>::isNull() const {
- return m_activeMutexPtrI == RNIL;
-}
-
-
-template<Uint32 MutexId>
-inline
-void
-MutexHandle2<MutexId>::release(SimulatedBlock::MutexManager & mgr){
- if(!isNull()){
- Mutex::release(mgr, m_activeMutexPtrI, MutexId);
- m_activeMutexPtrI = RNIL;
- }
-}
-
-
-inline
-Mutex::Mutex(Signal* signal, SimulatedBlock::MutexManager & mgr,
- MutexHandle & mh)
- : m_signal(signal),
- m_mgr(mgr),
- m_mutexId(mh.m_mutexId),
- m_srcPtrI(mh.m_activeMutexPtrI){
-
- m_ptr.i = m_srcPtrI;
-
-}
-
-template<Uint32 MutexId>
-inline
-Mutex::Mutex(Signal* signal, SimulatedBlock::MutexManager & mgr,
- MutexHandle2<MutexId> & mh)
- : m_signal(signal),
- m_mgr(mgr),
- m_mutexId(MutexId),
- m_srcPtrI(mh.m_activeMutexPtrI){
-
- m_ptr.i = m_srcPtrI;
-
-}
-
-inline
-Mutex::~Mutex(){
- m_srcPtrI = m_ptr.i;
-}
-
-inline
-void
-Mutex::release(){
- if(!m_ptr.isNull()){
- Mutex::release(m_mgr, m_ptr.i, m_mutexId);
- m_ptr.setNull();
- }
-}
-
-inline
-bool
-Mutex::isNull() const {
- return m_ptr.isNull();
-}
-
-inline
-bool
-Mutex::lock(SimulatedBlock::Callback & callback){
- if(m_ptr.isNull()){
- if(m_mgr.seize(m_ptr)){
- m_ptr.p->m_mutexId = m_mutexId;
- m_ptr.p->m_callback = callback;
- m_mgr.lock(m_signal, m_ptr);
- return true;
- }
- return false;
- }
- ErrorReporter::handleAssert("Mutex::lock mutex alreay inuse",
- __FILE__, __LINE__);
- return false;
-}
-
-inline
-bool
-Mutex::trylock(SimulatedBlock::Callback & callback){
- if(m_ptr.isNull()){
- if(m_mgr.seize(m_ptr)){
- m_ptr.p->m_mutexId = m_mutexId;
- m_ptr.p->m_callback = callback;
- m_mgr.lock(m_signal, m_ptr);
- return true;
- }
- return false;
- }
- ErrorReporter::handleAssert("Mutex::trylock mutex alreay inuse",
- __FILE__, __LINE__);
- return false;
-}
-
-inline
-void
-Mutex::unlock(SimulatedBlock::Callback & callback){
- if(!m_ptr.isNull()){
- m_mgr.getPtr(m_ptr);
- if(m_ptr.p->m_mutexId == m_mutexId){
- m_ptr.p->m_callback = callback;
- m_mgr.unlock(m_signal, m_ptr);
- return;
- }
- }
- ErrorReporter::handleAssert("Mutex::unlock invalid mutex",
- __FILE__, __LINE__);
-}
-
-inline
-bool
-Mutex::create(SimulatedBlock::Callback & callback){
- if(m_ptr.isNull()){
- if(m_mgr.seize(m_ptr)){
- m_ptr.p->m_mutexId = m_mutexId;
- m_ptr.p->m_callback = callback;
- m_mgr.create(m_signal, m_ptr);
- return true;
- }
- return false;
- }
- ErrorReporter::handleAssert("Mutex::create mutex alreay inuse",
- __FILE__, __LINE__);
- return false;
-}
-
-inline
-bool
-Mutex::destroy(SimulatedBlock::Callback & callback){
- if(m_ptr.isNull()){
- if(m_mgr.seize(m_ptr)){
- m_ptr.p->m_mutexId = m_mutexId;
- m_ptr.p->m_callback = callback;
- m_mgr.destroy(m_signal, m_ptr);
- return true;
- }
- return false;
- }
- ErrorReporter::handleAssert("Mutex::destroy mutex alreay inuse",
- __FILE__, __LINE__);
- return false;
-}
-
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/NdbdSuperPool.cpp b/storage/ndb/src/kernel/vm/NdbdSuperPool.cpp
deleted file mode 100644
index b9557d843ab..00000000000
--- a/storage/ndb/src/kernel/vm/NdbdSuperPool.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-/* Copyright (c) 2003, 2006, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include "SuperPool.hpp"
-#include "ndbd_malloc_impl.hpp"
-#include "NdbdSuperPool.hpp"
-
-#define PSI (1 << (BMW_2LOG + 2))
-
-struct AllocArea
-{
- AllocArea(AllocArea* next);
-
- Uint16 m_currPage; // 2
- Uint16 m_numPages; // number of pages // 2
- SuperPool::PtrI m_firstPageI; // 4
- void* m_memory; // page-aligned pages // 4/8
- struct AllocArea* m_nextArea; // 4/8
- // tot 16/24
-};
-
-AllocArea::AllocArea(AllocArea* next)
-{
- m_nextArea = next;
- m_firstPageI = RNIL;
- m_currPage = m_numPages = 0;
- m_memory = 0;
-}
-
-NdbdSuperPool::NdbdSuperPool(class Ndbd_mem_manager & mm,
- Uint32 pageSize, Uint32 pageBits) :
- SuperPool(pageSize, pageBits),
- m_mm(mm),
- m_currArea(0), m_firstArea(0)
-{
- m_memRoot = m_mm.get_memroot();
-
- m_shift = Ndbd_mem_manager::ndb_log2((1 << (BMW_2LOG + 2)) / pageSize) - 1;
- m_add = (1 << m_shift) - 1;
-}
-
-NdbdSuperPool::~NdbdSuperPool()
-{
- Uint32 cnt = PSI / sizeof(AllocArea);
- AllocArea* ap = m_firstArea;
- while(ap != 0)
- {
- AllocArea * first = ap;
- for(Uint32 i = 0; i<cnt; i++)
- {
- if (ap->m_numPages)
- {
- m_mm.release(ap->m_memory, ap->m_numPages >> m_shift);
- }
- ap = ap->m_nextArea;
- }
- m_mm.release((void*)first, 1);
- }
-}
-
-bool
-NdbdSuperPool::init_1()
-{
- Uint32 pageCount = (1 << m_pageBits);
- if (m_pageEnt == 0) {
- // allocate page entry array
- Uint32 bytes = pageCount * sizeof(PageEnt);
- m_pageEnt = static_cast<PageEnt*>(malloc(bytes));
- if (m_pageEnt == 0)
- return false;
- for (Uint32 i = 0; i < pageCount; i++)
- new (&m_pageEnt[i]) PageEnt();
- }
- if (m_pageType == 0) {
- // allocate type check array
- Uint32 bytes = pageCount;
- m_pageType = static_cast<Uint8*>(malloc(bytes));
- if (m_pageType == 0)
- return false;
- memset(m_pageType, 0, bytes);
- }
-
- return true;
-}
-
-static
-void
-initAllocAreaPage(AllocArea * p1)
-{
- AllocArea * ap = p1;
- Uint32 cnt = PSI / sizeof(AllocArea);
- for(Uint32 i = 0; i<cnt; i++, ap++)
- {
- new (ap) AllocArea(ap + 1);
- }
-
- (p1 + cnt - 1)->m_nextArea = 0;
-}
-
-bool
-NdbdSuperPool::init_2()
-{
- m_memRoot = m_mm.get_memroot();
-
- Uint32 cnt = 1;
- AllocArea* p1 = (AllocArea*)m_mm.alloc(&cnt, 1);
- if (p1 == 0)
- return false;
-
- initAllocAreaPage(p1);
- m_currArea = p1;
- m_firstArea = p1;
- return true;
-}
-
-SuperPool::PtrI
-NdbdSuperPool::getNewPage()
-{
- AllocArea* ap = m_currArea;
- Uint32 curr = ap->m_currPage;
- Uint32 cnt = ap->m_numPages;
- if (curr == cnt)
- {
- // area is used up
- if (! (ap = allocMem()))
- {
- abort();
- return RNIL;
- }
- curr = ap->m_currPage;
- cnt = ap->m_numPages;
- }
-
- assert(curr < cnt);
- PtrI pageI = ap->m_firstPageI;
- Uint32 recBits = m_recBits;
- Int32 ip = ((Int32)pageI >> recBits) + curr;
- pageI = ip << recBits;
- ap->m_currPage = curr + 1;
- return pageI;
-}
-
-Uint32
-NdbdSuperPool::allocAreaMemory(AllocArea* ap, Uint32 tryPages)
-{
- Uint32 cnt = (tryPages + m_add) >> m_shift;
- void* p1 = m_mm.alloc(&cnt, 1);
- if (p1 == 0)
- {
- abort();
- return 0;
- }
- Uint32 pageI = getPageI(p1);
- ap->m_firstPageI = pageI;
- ap->m_currPage = 0;
- ap->m_memory = p1;
- ap->m_numPages = cnt << m_shift;
- return cnt;
-}
-
-AllocArea*
-NdbdSuperPool::allocArea()
-{
- AllocArea * curr = m_currArea;
- AllocArea * next = curr->m_nextArea;
- if (next == 0)
- {
- Uint32 cnt = 1;
- AllocArea* p1 = (AllocArea*)m_mm.alloc(&cnt, 1);
- if (p1 == 0)
- return 0;
-
- initAllocAreaPage(p1);
-
- m_currArea->m_nextArea = p1;
- return m_currArea = p1;
- }
- else
- {
- m_currArea = m_currArea->m_nextArea;
- return m_currArea;
- }
-}
-
-AllocArea*
-NdbdSuperPool::allocMem()
-{
- // compute number of additional pages needed
- if (m_totPages >= m_maxPages)
- {
- abort();
- return 0;
- }
- Uint32 needPages = (m_totPages == 0 ? m_initPages : m_incrPages);
-
- // add new area
- AllocArea* ap = allocArea();
- if (ap == 0)
- {
- abort();
- return 0;
- }
-
- Uint32 numPages;
- if (!(numPages = allocAreaMemory(ap, needPages)))
- {
- abort();
- return 0;
- }
-
- // update counts
- m_totPages += numPages;
- return ap;
-}
diff --git a/storage/ndb/src/kernel/vm/NdbdSuperPool.hpp b/storage/ndb/src/kernel/vm/NdbdSuperPool.hpp
deleted file mode 100644
index 66765fcebc5..00000000000
--- a/storage/ndb/src/kernel/vm/NdbdSuperPool.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (c) 2003, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef NDBD_SUPER_POOL_HPP
-#define NDBD_SUPER_POOL_HPP
-
-#include "SuperPool.hpp"
-
-struct AllocArea;
-
-class NdbdSuperPool : public SuperPool
-{
-public:
- NdbdSuperPool(class Ndbd_mem_manager&, Uint32 pageSize, Uint32 pageBits);
-
- // Destructor.
- virtual ~NdbdSuperPool();
-
- // Get new page from current area.
- virtual PtrI getNewPage();
-
- // Call first...on all superpools (uses malloc)
- bool init_1();
-
- // Call second...uses mm
- bool init_2();
-
- virtual bool allocMemory() { return allocMem() != 0; }
-private:
- Uint32 allocAreaMemory(AllocArea*, Uint32 pages);
- AllocArea* allocArea();
- AllocArea* allocMem();
-
- // List of malloc areas.
- Uint32 m_shift, m_add;
- class Ndbd_mem_manager & m_mm;
-
- AllocArea* m_currArea;
- AllocArea* m_firstArea;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/Pool.cpp b/storage/ndb/src/kernel/vm/Pool.cpp
deleted file mode 100644
index 6b4b36a5036..00000000000
--- a/storage/ndb/src/kernel/vm/Pool.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2003, 2006, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include "Pool.hpp"
-#include "SimulatedBlock.hpp"
-
-void*
-Pool_context::alloc_page(Uint32 type_id, Uint32 *i)
-{
- return m_block->m_ctx.m_mm.alloc_page(type_id, i,
- Ndbd_mem_manager::NDB_ZONE_LO);
-}
-
-void
-Pool_context::release_page(Uint32 type_id, Uint32 i)
-{
- m_block->m_ctx.m_mm.release_page(type_id, i);
-}
-
-void*
-Pool_context::get_memroot()
-{
- return m_block->m_ctx.m_mm.get_memroot();
-}
-
-void
-Pool_context::handleAbort(int err, const char * msg)
-{
- m_block->progError(__LINE__, err, msg);
-}
diff --git a/storage/ndb/src/kernel/vm/Pool.hpp b/storage/ndb/src/kernel/vm/Pool.hpp
deleted file mode 100644
index 47b2e0d8892..00000000000
--- a/storage/ndb/src/kernel/vm/Pool.hpp
+++ /dev/null
@@ -1,341 +0,0 @@
-/* Copyright (c) 2003, 2006, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef NDB_POOL_HPP
-#define NDB_POOL_HPP
-
-#include <ndb_global.h>
-#include <kernel_types.h>
-
-/**
- * Type bits
- *
- * Type id is 11 bits record type, and 5 bits resource id
- * -> 2048 different kind of records and 32 different resource groups
- *
- * Resource id is used to handle configuration parameters
- *
- * see blocks/records_types.hpp
- */
-#define RG_BITS 5
-#define RG_MASK ((1 << RG_BITS) - 1)
-#define MAKE_TID(TID,RG) ((TID << RG_BITS) | RG)
-
-/**
- * Page bits
- */
-#define POOL_RECORD_BITS 13
-#define POOL_RECORD_MASK ((1 << POOL_RECORD_BITS) - 1)
-
-/**
- * Record_info
- *
- */
-struct Record_info
-{
- Uint16 m_size;
- Uint16 m_type_id;
- Uint16 m_offset_next_pool;
- Uint16 m_offset_magic;
-};
-
-/**
- * Resource_limit
- */
-struct Resource_limit
-{
- Uint32 m_min;
- Uint32 m_max;
- Uint32 m_curr;
- Uint32 m_resource_id;
-};
-
-struct Pool_context
-{
- Pool_context() {}
- class SimulatedBlock* m_block;
-
- /**
- * Get mem root
- */
- void* get_memroot();
-
- /**
- * Alloc consekutive pages
- *
- * @param i : out : i value of first page
- * @return : pointer to first page (NULL if failed)
- *
- * Will handle resource limit
- */
- void* alloc_page(Uint32 type_id, Uint32 *i);
-
- /**
- * Release pages
- *
- * @param i : in : i value of first page
- * @param p : in : pointer to first page
- */
- void release_page(Uint32 type_id, Uint32 i);
-
- /**
- * Alloc consekutive pages
- *
- * @param cnt : in/out : no of requested pages,
- * return no of allocated (undefined return NULL)
- * out will never be > in
- * @param i : out : i value of first page
- * @param min : in : will never allocate less than min
- * @return : pointer to first page (NULL if failed)
- *
- * Will handle resource limit
- */
- void* alloc_pages(Uint32 type_id, Uint32 *i, Uint32 *cnt, Uint32 min =1);
-
- /**
- * Release pages
- *
- * @param i : in : i value of first page
- * @param p : in : pointer to first page
- * @param cnt : in : no of pages to release
- */
- void release_pages(Uint32 type_id, Uint32 i, Uint32 cnt);
-
- /**
- * Abort
- */
- void handleAbort(int code, const char* msg);
-};
-
-template <typename T>
-struct Ptr
-{
- T * p;
- Uint32 i;
- inline bool isNull() const { return i == RNIL; }
- inline void setNull() { i = RNIL; }
-};
-
-template <typename T>
-struct ConstPtr
-{
- const T * p;
- Uint32 i;
- inline bool isNull() const { return i == RNIL; }
- inline void setNull() { i = RNIL; }
-};
-
-#ifdef XX_DOCUMENTATION_XX
-/**
- * Any pool should implement the following
- */
-struct PoolImpl
-{
- Pool_context m_ctx;
- Record_info m_record_info;
-
- void init(const Record_info& ri, const Pool_context& pc);
- void init(const Record_info& ri, const Pool_context& pc);
-
- bool seize(Ptr<void>&);
- void release(Ptr<void>);
- void * getPtr(Uint32 i);
-};
-#endif
-
-template <typename T, typename P>
-class RecordPool {
-public:
- RecordPool();
- ~RecordPool();
-
- void init(Uint32 type_id, const Pool_context& pc);
- void wo_pool_init(Uint32 type_id, const Pool_context& pc);
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &);
- void getPtr(ConstPtr<T> &) const;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i);
- const T * getConstPtr(Uint32 i) const;
-
- /**
- * Update p & i value for ptr according to <b>i</b> value
- */
- void getPtr(Ptr<T> &, Uint32 i);
- void getPtr(ConstPtr<T> &, Uint32 i) const;
-
- /**
- * Allocate an object from pool - update Ptr
- *
- * Return i
- */
- bool seize(Ptr<T> &);
-
- /**
- * Return an object to pool
- */
- void release(Uint32 i);
-
- /**
- * Return an object to pool
- */
- void release(Ptr<T>);
-private:
- P m_pool;
-};
-
-template <typename T, typename P>
-inline
-RecordPool<T, P>::RecordPool()
-{
-}
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::init(Uint32 type_id, const Pool_context& pc)
-{
- T tmp;
- const char * off_base = (char*)&tmp;
- const char * off_next = (char*)&tmp.nextPool;
- const char * off_magic = (char*)&tmp.m_magic;
-
- Record_info ri;
- ri.m_size = sizeof(T);
- ri.m_offset_next_pool = Uint32(off_next - off_base);
- ri.m_offset_magic = Uint32(off_magic - off_base);
- ri.m_type_id = type_id;
- m_pool.init(ri, pc);
-}
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::wo_pool_init(Uint32 type_id, const Pool_context& pc)
-{
- T tmp;
- const char * off_base = (char*)&tmp;
- const char * off_magic = (char*)&tmp.m_magic;
-
- Record_info ri;
- ri.m_size = sizeof(T);
- ri.m_offset_next_pool = 0;
- ri.m_offset_magic = Uint32(off_magic - off_base);
- ri.m_type_id = type_id;
- m_pool.init(ri, pc);
-}
-
-template <typename T, typename P>
-inline
-RecordPool<T, P>::~RecordPool()
-{
-}
-
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::getPtr(Ptr<T> & ptr)
-{
- ptr.p = static_cast<T*>(m_pool.getPtr(ptr.i));
-}
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::getPtr(ConstPtr<T> & ptr) const
-{
- ptr.p = static_cast<const T*>(m_pool.getPtr(ptr.i));
-}
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::getPtr(Ptr<T> & ptr, Uint32 i)
-{
- ptr.i = i;
- ptr.p = static_cast<T*>(m_pool.getPtr(ptr.i));
-}
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::getPtr(ConstPtr<T> & ptr, Uint32 i) const
-{
- ptr.i = i;
- ptr.p = static_cast<const T*>(m_pool.getPtr(ptr.i));
-}
-
-template <typename T, typename P>
-inline
-T *
-RecordPool<T, P>::getPtr(Uint32 i)
-{
- return static_cast<T*>(m_pool.getPtr(i));
-}
-
-template <typename T, typename P>
-inline
-const T *
-RecordPool<T, P>::getConstPtr(Uint32 i) const
-{
- return static_cast<const T*>(m_pool.getPtr(i));
-}
-
-template <typename T, typename P>
-inline
-bool
-RecordPool<T, P>::seize(Ptr<T> & ptr)
-{
- Ptr<void> tmp;
- bool ret = m_pool.seize(tmp);
- if(likely(ret))
- {
- ptr.i = tmp.i;
- ptr.p = static_cast<T*>(tmp.p);
- }
- return ret;
-}
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::release(Uint32 i)
-{
- Ptr<void> ptr;
- ptr.i = i;
- ptr.p = m_pool.getPtr(i);
- m_pool.release(ptr);
-}
-
-template <typename T, typename P>
-inline
-void
-RecordPool<T, P>::release(Ptr<T> ptr)
-{
- Ptr<void> tmp;
- tmp.i = ptr.i;
- tmp.p = ptr.p;
- m_pool.release(tmp);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/Prio.hpp b/storage/ndb/src/kernel/vm/Prio.hpp
deleted file mode 100644
index 3cc34a43918..00000000000
--- a/storage/ndb/src/kernel/vm/Prio.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef PRIO_H
-#define PRIO_H
-
-enum JobBufferLevel {
- JBA = 0,
- JBB = 1,
- JBC = 2,
- JBD = 3, LEVEL_IDLE = 3,
- JB_LEVELS,
- ILLEGAL_JB_LEVEL
-};
-
-typedef JobBufferLevel Priority;
-
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/RWPool.cpp b/storage/ndb/src/kernel/vm/RWPool.cpp
deleted file mode 100644
index a98e2b9b1d1..00000000000
--- a/storage/ndb/src/kernel/vm/RWPool.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/* Copyright (c) 2003, 2006, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "RWPool.hpp"
-#include <ndbd_exit_codes.h>
-#include <NdbOut.hpp>
-
-#define REC_NIL GLOBAL_PAGE_SIZE_WORDS
-
-RWPool::RWPool()
-{
- bzero(this, sizeof(* this));
- m_current_pos = RWPage::RWPAGE_WORDS;
- m_current_first_free = REC_NIL;
- m_first_free_page = RNIL;
-}
-
-void
-RWPool::init(const Record_info& ri, const Pool_context& pc)
-{
- m_ctx = pc;
- m_record_info = ri;
- m_record_info.m_size = ((ri.m_size + 3) >> 2); // Align to word boundary
- m_record_info.m_offset_magic = ((ri.m_offset_magic + 3) >> 2);
- m_record_info.m_offset_next_pool = ((ri.m_offset_next_pool + 3) >> 2);
- m_memroot = (RWPage*)m_ctx.get_memroot();
- ndbout_c("RWPool::init(%x, %d)",ri.m_type_id, m_record_info.m_size);
-}
-
-bool
-RWPool::seize(Ptr<void>& ptr)
-{
- Uint32 pos = m_current_pos;
- Uint32 size = m_record_info.m_size;
- Uint32 off = m_record_info.m_offset_magic;
- RWPage *pageP = m_current_page;
- if (likely(m_current_first_free != REC_NIL))
- {
-seize_free:
- pos = m_current_first_free;
- ptr.i = (m_current_page_no << POOL_RECORD_BITS) + pos;
- ptr.p = pageP->m_data + pos;
- pageP->m_data[pos+off] = ~(Uint32)m_record_info.m_type_id;
- m_current_ref_count++;
- m_current_first_free = pageP->m_data[pos+m_record_info.m_offset_next_pool];
- return true;
- }
- else if (pos + size < RWPage::RWPAGE_WORDS)
- {
-seize_first:
- ptr.i = (m_current_page_no << POOL_RECORD_BITS) + pos;
- ptr.p = (pageP->m_data + pos);
- pageP->m_data[pos+off] = ~(Uint32)m_record_info.m_type_id;
- m_current_ref_count++;
- m_current_pos = pos + size;
- return true;
- }
-
- if (m_current_page)
- {
- m_current_page->m_first_free = REC_NIL;
- m_current_page->m_next_page = RNIL;
- m_current_page->m_prev_page = RNIL;
- m_current_page->m_type_id = m_record_info.m_type_id;
- m_current_page->m_ref_count = m_current_ref_count;
- }
-
- if (m_first_free_page != RNIL)
- {
- pageP = m_current_page = m_memroot + m_first_free_page;
- m_current_page_no = m_first_free_page;
- m_current_pos = RWPage::RWPAGE_WORDS;
- m_current_first_free = m_current_page->m_first_free;
- m_first_free_page = m_current_page->m_next_page;
- m_current_ref_count = m_current_page->m_ref_count;
- if (m_first_free_page != RNIL)
- {
- (m_memroot + m_first_free_page)->m_prev_page = RNIL;
- }
- goto seize_free;
- }
-
- m_current_ref_count = 0;
-
- RWPage* page;
- Uint32 page_no = RNIL;
- if ((page = (RWPage*)m_ctx.alloc_page(m_record_info.m_type_id, &page_no)))
- {
- pos = 0;
- m_current_page_no = page_no;
- pageP = m_current_page = page;
- m_current_first_free = REC_NIL;
- page->m_type_id = m_record_info.m_type_id;
- goto seize_first;
- }
-
- m_current_page = 0;
- m_current_page_no = RNIL;
- m_current_pos = RWPage::RWPAGE_WORDS;
- m_current_first_free = REC_NIL;
-
- return false;
-}
-
-void
-RWPool::release(Ptr<void> ptr)
-{
- Uint32 cur_page = m_current_page_no;
- Uint32 ptr_page = ptr.i >> POOL_RECORD_BITS;
- Uint32 *record_ptr = (Uint32*)ptr.p;
- Uint32 magic_val = * (record_ptr + m_record_info.m_offset_magic);
-
- if (likely(magic_val == ~(Uint32)m_record_info.m_type_id))
- {
- * (record_ptr + m_record_info.m_offset_magic) = 0;
- if (cur_page == ptr_page)
- {
- * (record_ptr + m_record_info.m_offset_next_pool) = m_current_first_free;
- assert(m_current_ref_count);
- m_current_ref_count--;
- m_current_first_free = ptr.i & POOL_RECORD_MASK;
- return;
- }
-
- // Cache miss on page...
- RWPage* page = m_memroot + ptr_page;
- Uint32 ref_cnt = page->m_ref_count;
- Uint32 ff = page->m_first_free;
-
- * (record_ptr + m_record_info.m_offset_next_pool) = ff;
- page->m_first_free = ptr.i & POOL_RECORD_MASK;
- page->m_ref_count = ref_cnt - 1;
-
- if (ff == REC_NIL)
- {
- /**
- * It was full...add to free page list
- */
- Uint32 ffp = m_first_free_page;
- if (ffp != RNIL)
- {
- RWPage* next = (m_memroot + ffp);
- assert(next->m_prev_page == RNIL);
- next->m_prev_page = ptr_page;
- }
- page->m_next_page = ffp;
- page->m_prev_page = RNIL;
- m_first_free_page = ptr_page;
- return;
- }
- else if(ref_cnt == 1)
- {
- /**
- * It's now empty...release it
- */
- Uint32 prev = page->m_prev_page;
- Uint32 next = page->m_next_page;
- if (prev != RNIL)
- {
- (m_memroot + prev)->m_next_page = next;
- }
- else
- {
- assert(m_first_free_page == ptr_page);
- m_first_free_page = next;
- }
-
- if (next != RNIL)
- {
- (m_memroot + next)->m_prev_page = prev;
- }
- m_ctx.release_page(m_record_info.m_type_id, ptr_page);
- return;
- }
- return;
- }
- handle_invalid_release(ptr);
-}
-
-void
-RWPool::handle_invalid_release(Ptr<void> ptr)
-{
- char buf[255];
-
- Uint32 pos = ptr.i & POOL_RECORD_MASK;
- Uint32 pageI = ptr.i >> POOL_RECORD_BITS;
- Uint32 * record_ptr_p = (Uint32*)ptr.p;
- Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
-
- Uint32 magic = * (record_ptr_p + m_record_info.m_offset_magic);
- snprintf(buf, sizeof(buf),
- "Invalid memory release: ptr (%x %p %p) magic: (%.8x %.8x) memroot: %p page: %x",
- ptr.i, ptr.p, record_ptr_i, magic, m_record_info.m_type_id,
- m_memroot,
- (m_memroot+pageI)->m_type_id);
-
- m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
-}
-
-void
-RWPool::handle_invalid_get_ptr(Uint32 ptrI)
-{
- char buf[255];
-
- Uint32 pos = ptrI & POOL_RECORD_MASK;
- Uint32 pageI = ptrI >> POOL_RECORD_BITS;
- Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
-
- Uint32 magic = * (record_ptr_i + m_record_info.m_offset_magic);
- snprintf(buf, sizeof(buf),
- "Invalid memory access: ptr (%x %p) magic: (%.8x %.8x) memroot: %p page: %x",
- ptrI, record_ptr_i, magic, m_record_info.m_type_id,
- m_memroot,
- (m_memroot+pageI)->m_type_id);
-
- m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
-}
diff --git a/storage/ndb/src/kernel/vm/RWPool.hpp b/storage/ndb/src/kernel/vm/RWPool.hpp
deleted file mode 100644
index dfe4c04e644..00000000000
--- a/storage/ndb/src/kernel/vm/RWPool.hpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright (c) 2003, 2006, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef RWPOOL_HPP
-#define RWPOOL_HPP
-
-#include "Pool.hpp"
-
-struct RWPage
-{
- STATIC_CONST( RWPAGE_WORDS = GLOBAL_PAGE_SIZE_WORDS - 4 );
-
- Uint32 m_type_id;
- Uint16 m_first_free;
- Uint16 m_ref_count;
- Uint32 m_next_page;
- Uint32 m_prev_page;
- Uint32 m_data[RWPAGE_WORDS];
-};
-
-/**
- * Read Write Pool
- */
-struct RWPool
-{
- Record_info m_record_info;
- RWPage* m_memroot;
- RWPage* m_current_page;
- Pool_context m_ctx;
- Uint32 m_first_free_page;
- Uint32 m_current_page_no;
- Uint16 m_current_pos;
- Uint16 m_current_first_free;
- Uint16 m_current_ref_count;
-public:
- RWPool();
-
- void init(const Record_info& ri, const Pool_context& pc);
- bool seize(Ptr<void>&);
- void release(Ptr<void>);
- void * getPtr(Uint32 i);
-
-private:
- void handle_invalid_release(Ptr<void>);
- void handle_invalid_get_ptr(Uint32 i);
-};
-
-inline
-void*
-RWPool::getPtr(Uint32 i)
-{
- Uint32 page_no = i >> POOL_RECORD_BITS;
- Uint32 page_idx = i & POOL_RECORD_MASK;
- RWPage * page = m_memroot + page_no;
- Uint32 * record = page->m_data + page_idx;
- Uint32 magic_val = * (record + m_record_info.m_offset_magic);
- if (likely(magic_val == ~(Uint32)m_record_info.m_type_id))
- {
- return record;
- }
- handle_invalid_get_ptr(i);
- return 0; /* purify: deadcode */
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/RequestTracker.hpp b/storage/ndb/src/kernel/vm/RequestTracker.hpp
deleted file mode 100644
index 743a90234b1..00000000000
--- a/storage/ndb/src/kernel/vm/RequestTracker.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef __REQUEST_TRACKER_HPP
-#define __REQUEST_TRACKER_HPP
-
-#include "SafeCounter.hpp"
-
-class RequestTracker {
-public:
- RequestTracker(){ init(); }
-
- void init() { m_confs.clear(); m_nRefs = 0; }
-
- template<typename SignalClass>
- bool init(SafeCounterManager& mgr,
- NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData)
- {
- init();
- SafeCounter tmp(mgr, m_sc);
- return tmp.init<SignalClass>(rg, GSN, senderData);
- }
-
- bool ignoreRef(SafeCounterManager& mgr, Uint32 nodeId)
- { return m_sc.clearWaitingFor(mgr, nodeId); }
-
- bool reportRef(SafeCounterManager& mgr, Uint32 nodeId)
- { m_nRefs++; return m_sc.clearWaitingFor(mgr, nodeId); }
-
- bool reportConf(SafeCounterManager& mgr, Uint32 nodeId)
- { m_confs.set(nodeId); return m_sc.clearWaitingFor(mgr, nodeId); }
-
- bool hasRef() { return m_nRefs != 0; }
-
- bool hasConf() { return !m_confs.isclear(); }
-
- bool done() { return m_sc.done(); }
-
-private:
- SafeCounterHandle m_sc;
- NodeBitmask m_confs;
- Uint8 m_nRefs;
-};
-
-#endif // __REQUEST_TRACKER_HPP
diff --git a/storage/ndb/src/kernel/vm/Rope.cpp b/storage/ndb/src/kernel/vm/Rope.cpp
deleted file mode 100644
index 9ee48d5fa3e..00000000000
--- a/storage/ndb/src/kernel/vm/Rope.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Copyright (C) 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "Rope.hpp"
-
-#define DEBUG_ROPE 0
-
-void
-ConstRope::copy(char* buf) const {
- char * ptr = buf;
- if(DEBUG_ROPE)
- ndbout_c("ConstRope::copy() head = [ %d 0x%x 0x%x ]",
- head.used, head.firstItem, head.lastItem);
- Uint32 left = head.used;
- Ptr<Segment> curr;
- curr.i = head.firstItem;
- while(left > 4 * getSegmentSize()){
- thePool.getPtr(curr);
- memcpy(buf, curr.p->data, 4 * getSegmentSize());
- curr.i = curr.p->nextPool;
- left -= 4 * getSegmentSize();
- buf += 4 * getSegmentSize();
- }
- if(left > 0){
- thePool.getPtr(curr);
- memcpy(buf, curr.p->data, left);
- }
-
- if(DEBUG_ROPE)
- ndbout_c("ConstRope::copy()-> %s", ptr);
-}
-
-int
-ConstRope::compare(const char * str, size_t len) const {
- if(DEBUG_ROPE)
- ndbout_c("ConstRope[ %d 0x%x 0x%x ]::compare(%s, %d)",
- head.used, head.firstItem, head.lastItem, str, (int) len);
- Uint32 left = head.used > len ? len : head.used;
- Ptr<Segment> curr;
- curr.i = head.firstItem;
- while(left > 4 * getSegmentSize()){
- thePool.getPtr(curr);
- int res = memcmp(str, (const char*)curr.p->data, 4 * getSegmentSize());
- if(res != 0){
- if(DEBUG_ROPE)
- ndbout_c("ConstRope::compare(%s, %d, %s) -> %d", str, left,
- (const char*)curr.p->data, res);
- return res;
- }
- curr.i = curr.p->nextPool;
- left -= 4 * getSegmentSize();
- str += 4 * getSegmentSize();
- }
-
- if(left > 0){
- thePool.getPtr(curr);
- int res = memcmp(str, (const char*)curr.p->data, left);
- if(res){
- if(DEBUG_ROPE)
- ndbout_c("ConstRope::compare(%s, %d, %s) -> %d",
- str, left, (const char*)curr.p->data, res);
- return res;
- }
- }
- if(DEBUG_ROPE)
- ndbout_c("ConstRope::compare(%s, %d) -> %d", str, (int) len, head.used > len);
- return head.used > len;
-}
-
-void
-Rope::copy(char* buf) const {
- char * ptr = buf;
- if(DEBUG_ROPE)
- ndbout_c("Rope::copy() head = [ %d 0x%x 0x%x ]",
- head.used, head.firstItem, head.lastItem);
- Uint32 left = head.used;
- Ptr<Segment> curr;
- curr.i = head.firstItem;
- while(left > 4 * getSegmentSize()){
- thePool.getPtr(curr);
- memcpy(buf, curr.p->data, 4 * getSegmentSize());
- curr.i = curr.p->nextPool;
- left -= 4 * getSegmentSize();
- buf += 4 * getSegmentSize();
- }
- if(left > 0){
- thePool.getPtr(curr);
- memcpy(buf, curr.p->data, left);
- }
- if(DEBUG_ROPE)
- ndbout_c("Rope::copy()-> %s", ptr);
-}
-
-int
-Rope::compare(const char * str, size_t len) const {
- if(DEBUG_ROPE)
- ndbout_c("Rope::compare(%s, %d)", str, (int) len);
- Uint32 left = head.used > len ? len : head.used;
- Ptr<Segment> curr;
- curr.i = head.firstItem;
- while(left > 4 * getSegmentSize()){
- thePool.getPtr(curr);
- int res = memcmp(str, (const char*)curr.p->data, 4 * getSegmentSize());
- if(res != 0){
- if(DEBUG_ROPE)
- ndbout_c("Rope::compare(%s, %d, %s) -> %d", str, (int) len,
- (const char*)curr.p->data, res);
- return res;
- }
-
- curr.i = curr.p->nextPool;
- left -= 4 * getSegmentSize();
- str += 4 * getSegmentSize();
- }
-
- if(left > 0){
- thePool.getPtr(curr);
- int res = memcmp(str, (const char*)curr.p->data, left);
- if(res){
- if(DEBUG_ROPE)
- ndbout_c("Rope::compare(%s, %d) -> %d", str, (int) len, res);
- return res;
- }
- }
- if(DEBUG_ROPE)
- ndbout_c("Rope::compare(%s, %d) -> %d", str, (int) len, head.used > len);
- return head.used > len;
-}
-
-bool
-Rope::assign(const char * s, size_t len, Uint32 hash){
- if(DEBUG_ROPE)
- ndbout_c("Rope::assign(%s, %d, 0x%x)", s, (int) len, hash);
- m_hash = hash;
- head.used = (head.used + 3) / 4;
- release();
- if(append((const Uint32*)s, len >> 2)){
- if(len & 3){
- Uint32 buf = 0;
- const char * src = (const char*)(((Uint32*)s)+(len >> 2));
- char* dst = (char*)&buf;
- size_t left = len & 3;
- while(left){
- * dst ++ = * src++;
- left--;
- }
- if(!append(&buf, 1))
- return false;
- }
- head.used = len;
- if(DEBUG_ROPE)
- ndbout_c("Rope::assign(...) head = [ %d 0x%x 0x%x ]",
- head.used, head.firstItem, head.lastItem);
- return true;
- }
- return false;
-}
-
-void
-Rope::erase(){
- head.used = (head.used + 3) / 4;
- release();
-}
-
-Uint32
-Rope::hash(const char * p, Uint32 len){
- if(DEBUG_ROPE)
- ndbout_c("Rope::hash(%s, %d)", p, len);
- Uint32 h = 0;
- for (; len > 0; len--)
- h = (h << 5) + h + (* p++);
- if(DEBUG_ROPE)
- ndbout_c("Rope::hash(...) -> 0x%x", h);
- return h;
-}
-
diff --git a/storage/ndb/src/kernel/vm/Rope.hpp b/storage/ndb/src/kernel/vm/Rope.hpp
deleted file mode 100644
index d7e3ccc6e53..00000000000
--- a/storage/ndb/src/kernel/vm/Rope.hpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef NDB_ROPE_HPP
-#define NDB_ROPE_HPP
-
-#include "DataBuffer.hpp"
-
-typedef DataBuffer<7> RopeBase;
-typedef DataBuffer<7>::DataBufferPool RopePool;
-
-struct RopeHandle {
- RopeHandle() { m_hash = 0; }
-
- Uint32 m_hash;
- RopeBase::Head m_head;
-
- Uint32 hashValue() const { return m_hash; }
-};
-
-class ConstRope : private RopeBase {
-public:
- ConstRope(RopePool& thePool, const RopeHandle& handle)
- : RopeBase(thePool), src(handle)
- {
- this->head = src.m_head;
- }
-
- ~ConstRope(){
- }
-
- size_t size() const;
- bool empty() const;
-
- void copy(char* buf) const;
-
- int compare(const char * s) const { return compare(s, strlen(s) + 1); }
- int compare(const char *, size_t len) const;
-
-private:
- const RopeHandle & src;
-};
-
-class Rope : private RopeBase {
-public:
- Rope(RopePool& thePool, RopeHandle& handle)
- : RopeBase(thePool), src(handle)
- {
- this->head = src.m_head;
- m_hash = src.m_hash;
- }
-
- ~Rope(){
- src.m_head = this->head;
- src.m_hash = m_hash;
- }
-
- size_t size() const;
- bool empty() const;
-
- void copy(char* buf) const;
-
- int compare(const char * s) const { return compare(s, strlen(s) + 1); }
- int compare(const char *, size_t len) const;
-
- bool assign(const char * s) { return assign(s, strlen(s) + 1);}
- bool assign(const char * s, size_t l) { return assign(s, l, hash(s, l));}
- bool assign(const char *, size_t len, Uint32 hash);
-
- void erase();
-
- static Uint32 hash(const char * str, Uint32 len);
-
-private:
- Uint32 m_hash;
- RopeHandle & src;
-};
-
-inline
-size_t
-Rope::size() const {
- return head.used;
-}
-
-inline
-bool
-Rope::empty() const {
- return head.used == 0;
-}
-
-inline
-size_t
-ConstRope::size() const {
- return head.used;
-}
-
-inline
-bool
-ConstRope::empty() const {
- return head.used == 0;
-}
-
-#endif
-
diff --git a/storage/ndb/src/kernel/vm/SLFifoList.hpp b/storage/ndb/src/kernel/vm/SLFifoList.hpp
deleted file mode 100644
index 4cd370a3129..00000000000
--- a/storage/ndb/src/kernel/vm/SLFifoList.hpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/* Copyright (c) 2003, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SLFIFOLIST_HPP
-#define SLFIFOLIST_HPP
-
-#include <ndb_global.h>
-#include <kernel_types.h>
-#include "Pool.hpp"
-
-/**
- * Template class used for implementing an
- * list of object retreived from a pool
- */
-template <typename P, typename T, typename U = T>
-class SLFifoListImpl
-{
-public:
- /**
- * List head
- */
- struct Head
- {
- Head();
- Uint32 firstItem;
- Uint32 lastItem;
-
-#ifdef VM_TRACE
- bool in_use;
-#endif
-
- inline bool isEmpty() const { return firstItem == RNIL;}
- };
-
- SLFifoListImpl(P & thePool);
-
- bool seizeFirst(Ptr<T> &);
- bool seizeLast(Ptr<T> &);
- bool seize(Ptr<T> & ptr) { return seizeLast(ptr);}
-
- void releaseFirst(Ptr<T> &);
-
- void addFirst(Ptr<T> &);
- void addLast(Ptr<T> &);
-
- void removeFirst(Ptr<T> &);
-
- /**
- * Update i & p value according to <b>i</b>
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &) const ;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i) const ;
-
- /**
- * Update ptr to first element in list
- *
- * Return i
- */
- bool first(Ptr<T> &) const ;
-
- /**
- * Update ptr to first element in list
- *
- * Return i
- */
- bool last(Ptr<T> &) const ;
-
- /**
- * Get next element
- *
- * NOTE ptr must be both p & i
- */
- bool next(Ptr<T> &) const ;
-
- /**
- * Check if next exists i.e. this is not last
- *
- * NOTE ptr must be both p & i
- */
- bool hasNext(const Ptr<T> &) const;
-
- inline bool isEmpty() const { return head.firstItem == RNIL;}
-
-protected:
- Head head;
- P & thePool;
-};
-
-template <typename P, typename T, typename U = T>
-class LocalSLFifoListImpl : public SLFifoListImpl<P,T,U>
-{
-public:
- LocalSLFifoListImpl(P & thePool, typename SLFifoListImpl<P,T,U>::Head &_src)
- : SLFifoListImpl<P,T,U>(thePool), src(_src)
- {
- this->head = src;
-#ifdef VM_TRACE
- assert(src.in_use == false);
- src.in_use = true;
-#endif
- }
-
- ~LocalSLFifoListImpl(){
-#ifdef VM_TRACE
- assert(src.in_use == true);
-#endif
- src = this->head;
- }
-private:
- typename SLFifoListImpl<P,T,U>::Head & src;
-};
-
-template <typename P, typename T, typename U>
-inline
-SLFifoListImpl<P,T,U>::SLFifoListImpl(P & _pool):
- thePool(_pool)
-{
-}
-
-template <typename P, typename T, typename U>
-inline
-SLFifoListImpl<P,T,U>::Head::Head()
-{
- firstItem = RNIL;
- lastItem = RNIL;
-#ifdef VM_TRACE
- in_use = false;
-#endif
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLFifoListImpl<P,T,U>::seizeFirst(Ptr<T> & p)
-{
- if (likely(thePool.seize(p)))
- {
- addFirst(p);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLFifoListImpl<P,T,U>::seizeLast(Ptr<T> & p)
-{
- if (likely(thePool.seize(p)))
- {
- addLast(p);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLFifoListImpl<P,T,U>::addFirst(Ptr<T> & p)
-{
- Uint32 first = head.firstItem;
- head.firstItem = p.i;
- if (first == RNIL)
- {
- head.lastItem = p.i;
- }
- p.p->U::nextList = first;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLFifoListImpl<P,T,U>::addLast(Ptr<T> & p)
-{
- T * t = p.p;
- Uint32 last = head.lastItem;
-
- t->U::nextList = RNIL;
- head.lastItem = p.i;
-
- if(last != RNIL)
- {
- T * t2 = thePool.getPtr(last);
- t2->U::nextList = p.i;
- }
- else
- {
- head.firstItem = p.i;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLFifoListImpl<P,T,U>::removeFirst(Ptr<T> & p)
-{
- Uint32 first = head.firstItem;
- Uint32 last = head.lastItem;
- assert(p.i == first);
- if (first != last)
- {
- head.firstItem = p.p->U::nextList;
- }
- else
- {
- head.firstItem = head.lastItem = RNIL;
- }
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLFifoListImpl<P,T,U>::releaseFirst(Ptr<T> & p)
-{
- removeFirst(p);
- thePool.release(p);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLFifoListImpl<P,T,U>::getPtr(Ptr<T> & p, Uint32 i) const
-{
- p.i = i;
- p.p = thePool.getPtr(i);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLFifoListImpl<P,T,U>::getPtr(Ptr<T> & p) const
-{
- thePool.getPtr(p);
-}
-
-template <typename P, typename T, typename U>
-inline
-T *
-SLFifoListImpl<P,T,U>::getPtr(Uint32 i) const
-{
- return thePool.getPtr(i);
-}
-
-/**
- * Update ptr to first element in list
- *
- * Return i
- */
-template <typename P, typename T, typename U>
-inline
-bool
-SLFifoListImpl<P,T,U>::first(Ptr<T> & p) const
-{
- p.i = head.firstItem;
- if(p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLFifoListImpl<P,T,U>::last(Ptr<T> & p) const
-{
- p.i = head.lastItem;
- if(p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLFifoListImpl<P,T,U>::next(Ptr<T> & p) const
-{
- p.i = p.p->U::nextList;
- if(p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLFifoListImpl<P,T,U>::hasNext(const Ptr<T> & p) const
-{
- return p.p->U::nextList != RNIL;
-}
-
-// Specializations
-
-template <typename T, typename U = T>
-class SLFifoList : public SLFifoListImpl<ArrayPool<T>, T, U>
-{
-public:
- SLFifoList(ArrayPool<T> & p) : SLFifoListImpl<ArrayPool<T>, T, U>(p) {}
-};
-
-template <typename T, typename U = T>
-class LocalSLFifoList : public LocalSLFifoListImpl<ArrayPool<T>,T,U> {
-public:
- LocalSLFifoList(ArrayPool<T> & p, typename SLFifoList<T,U>::Head & _src)
- : LocalSLFifoListImpl<ArrayPool<T>,T,U>(p, _src) {}
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/SLList.hpp b/storage/ndb/src/kernel/vm/SLList.hpp
deleted file mode 100644
index 08ba6898185..00000000000
--- a/storage/ndb/src/kernel/vm/SLList.hpp
+++ /dev/null
@@ -1,402 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SLLIST_HPP
-#define SLLIST_HPP
-
-#include "ArrayPool.hpp"
-#include <NdbOut.hpp>
-
-/**
- * Template class used for implementing an
- * list of object retreived from a pool
- */
-template <typename P, typename T, typename U = T>
-class SLListImpl
-{
-public:
- /**
- * List head
- */
- struct HeadPOD {
- Uint32 firstItem;
- void init() { firstItem = RNIL;}
- };
-
- struct Head : public HeadPOD {
- Head();
- Head& operator= (const HeadPOD& src) {
- this->firstItem = src.firstItem;
- return *this;
- }
- };
-
- SLListImpl(P & thePool);
-
- /**
- * Allocate an object from pool - update Ptr
- *
- * Return i
- */
- bool seize(Ptr<T> &);
-
- /**
- * Allocate object <b>i</b> from pool - update Ptr
- *
- * Return i
- */
- bool seizeId(Ptr<T> &, Uint32 i);
-
- /**
- * Allocate <b>n</b>objects from pool
- *
- * Return i value of first object allocated or RNIL if fails
- */
- bool seizeN(Ptr<T> &, Uint32 n);
-
- /**
- * Return all objects to the pool
- */
- void release();
-
- /**
- * Remove all object from list but don't return to pool
- */
- void remove();
-
- /**
- * Update i & p value according to <b>i</b>
- */
- void getPtr(Ptr<T> &, Uint32 i) const;
-
- /**
- * Update p value for ptr according to i value
- */
- void getPtr(Ptr<T> &) const ;
-
- /**
- * Get pointer for i value
- */
- T * getPtr(Uint32 i) const ;
-
- /**
- * Update ptr to first element in list
- *
- * Return i
- */
- bool first(Ptr<T> &) const ;
-
- /**
- * Get next element
- *
- * NOTE ptr must be both p & i
- */
- bool next(Ptr<T> &) const ;
-
- /**
- * Check if next exists
- *
- * NOTE ptr must be both p & i
- */
- bool hasNext(const Ptr<T> &) const;
-
- /**
- * Add
- */
- void add(Ptr<T> & p){
- p.p->U::nextList = head.firstItem;
- head.firstItem = p.i;
- }
-
- /**
- * Add a list to list
- * @NOTE all elements _must_ be correctly initilized correctly wrt next/prev
- */
- void add(Uint32 first, Ptr<T> & last);
-
- /**
- * Remove object from list
- *
- * @NOTE Does not return it to pool
- */
- bool remove_front(Ptr<T> &);
-
- Uint32 noOfElements() const {
- Uint32 c = 0;
- Uint32 i = head.firstItem;
- while(i != RNIL){
- c++;
- const T * t = thePool.getPtr(i);
- i = t->U::nextList;
- }
- return c;
- }
-
- /**
- * Print
- * (Run operator NdbOut<< on every element)
- */
- void print(NdbOut & out) {
- out << "firstItem = " << head.firstItem << endl;
- Uint32 i = head.firstItem;
- while(i != RNIL){
- T * t = thePool.getPtr(i);
- t->print(out); out << " ";
- i = t->next;
- }
- }
-
- inline bool empty() const { return head.firstItem == RNIL;}
-
-protected:
- Head head;
- P & thePool;
-};
-
-template <typename P, typename T, typename U = T>
-class LocalSLListImpl : public SLListImpl<P, T, U>
-{
-public:
- LocalSLListImpl(P & thePool, typename SLListImpl<P, T, U>::HeadPOD & _src)
- : SLListImpl<P, T, U>(thePool), src(_src)
- {
- this->head = src;
- }
-
- ~LocalSLListImpl(){
- src = this->head;
- }
-private:
- typename SLListImpl<P, T, U>::HeadPOD & src;
-};
-
-template <typename P, typename T, typename U>
-inline
-SLListImpl<P, T, U>::SLListImpl(P & _pool):
- thePool(_pool)
-{
-}
-
-template <typename P, typename T, typename U>
-inline
-SLListImpl<P, T, U>::Head::Head()
-{
- this->init();
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLListImpl<P, T, U>::seize(Ptr<T> & p)
-{
- thePool.seize(p);
- T * t = p.p;
- Uint32 ff = head.firstItem;
- if(p.i != RNIL)
- {
- t->U::nextList = ff;
- head.firstItem = p.i;
- return true;
- }
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLListImpl<P, T, U>::seizeId(Ptr<T> & p, Uint32 ir)
-{
- thePool.seizeId(p, ir);
- T * t = p.p;
- Uint32 ff = head.firstItem;
- if(p.i != RNIL)
- {
- t->U::nextList = ff;
- head.firstItem = p.i;
- return true;
- }
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLListImpl<P, T, U>::seizeN(Ptr<T> & p, Uint32 n)
-{
- for(Uint32 i = 0; i < n; i++)
- {
- if(seize(p) == RNIL)
- {
- /**
- * Failure
- */
- for(; i > 0; i--)
- {
- p.i = head.firstItem;
- thePool.getPtr(p);
- head.firstItem = p.p->U::nextList;
- thePool.release(p);
- }
- return false;
- }
- }
-
- /**
- * Success
- */
- p.i = head.firstItem;
- p.p = thePool.getPtr(head.firstItem);
-
- return true;
-}
-
-
-template <typename P, typename T, typename U>
-inline
-void
-SLListImpl<P, T, U>::remove()
-{
- head.firstItem = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLListImpl<P, T, U>::remove_front(Ptr<T> & p)
-{
- p.i = head.firstItem;
- if (p.i != RNIL)
- {
- p.p = thePool.getPtr(p.i);
- head.firstItem = p.p->U::nextList;
- return true;
- }
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLListImpl<P, T, U>::add(Uint32 first, Ptr<T> & last)
-{
- last.p->U::nextList = head.firstItem;
- head.firstItem = first;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLListImpl<P, T, U>::release()
-{
- Ptr<T> ptr;
- Uint32 curr = head.firstItem;
- while(curr != RNIL)
- {
- thePool.getPtr(ptr, curr);
- curr = ptr.p->U::nextList;
- thePool.release(ptr);
- }
- head.firstItem = RNIL;
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLListImpl<P, T, U>::getPtr(Ptr<T> & p, Uint32 i) const
-{
- p.i = i;
- p.p = thePool.getPtr(i);
-}
-
-template <typename P, typename T, typename U>
-inline
-void
-SLListImpl<P, T, U>::getPtr(Ptr<T> & p) const
-{
- thePool.getPtr(p);
-}
-
-template <typename P, typename T, typename U>
-inline
-T *
-SLListImpl<P, T, U>::getPtr(Uint32 i) const
-{
- return thePool.getPtr(i);
-}
-
-/**
- * Update ptr to first element in list
- *
- * Return i
- */
-template <typename P, typename T, typename U>
-inline
-bool
-SLListImpl<P, T, U>::first(Ptr<T> & p) const
-{
- Uint32 i = head.firstItem;
- p.i = i;
- if(i != RNIL)
- {
- p.p = thePool.getPtr(i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLListImpl<P, T, U>::next(Ptr<T> & p) const
-{
- Uint32 i = p.p->U::nextList;
- p.i = i;
- if(i != RNIL)
- {
- p.p = thePool.getPtr(i);
- return true;
- }
- p.p = NULL;
- return false;
-}
-
-template <typename P, typename T, typename U>
-inline
-bool
-SLListImpl<P, T, U>::hasNext(const Ptr<T> & p) const
-{
- return p.p->U::nextList != RNIL;
-}
-
-// Specializations
-
-template <typename T, typename U = T>
-class SLList : public SLListImpl<ArrayPool<T>, T, U>
-{
-public:
- SLList(ArrayPool<T> & p) : SLListImpl<ArrayPool<T>, T, U>(p) {}
-};
-
-template <typename T, typename U = T>
-class LocalSLList : public LocalSLListImpl<ArrayPool<T>,T,U> {
-public:
- LocalSLList(ArrayPool<T> & p, typename SLList<T,U>::Head & _src)
- : LocalSLListImpl<ArrayPool<T>,T,U>(p, _src) {}
-};
-
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/SafeCounter.cpp b/storage/ndb/src/kernel/vm/SafeCounter.cpp
deleted file mode 100644
index f01bb4d8f85..00000000000
--- a/storage/ndb/src/kernel/vm/SafeCounter.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include "SimulatedBlock.hpp"
-#include "SafeCounter.hpp"
-#include <signaldata/NodeFailRep.hpp>
-
-SafeCounterManager::SafeCounterManager(class SimulatedBlock & block)
- : m_block(block),
- m_activeCounters(m_counterPool)
-{}
-
-bool
-SafeCounterManager::setSize(Uint32 maxNoOfActiveMutexes, bool exit_on_error) {
- return m_counterPool.setSize(maxNoOfActiveMutexes, false, exit_on_error);
-}
-
-Uint32
-SafeCounterManager::getSize() const {
- return m_counterPool.getSize();
-}
-
-bool
-SafeCounterManager::seize(ActiveCounterPtr& ptr){
- return m_activeCounters.seize(ptr);
-}
-
-void
-SafeCounterManager::release(ActiveCounterPtr& ptr){
- m_activeCounters.release(ptr);
-}
-
-void
-SafeCounterManager::getPtr(ActiveCounterPtr& ptr, Uint32 ptrI){
- m_activeCounters.getPtr(ptr, ptrI);
-}
-
-
-void
-SafeCounterManager::printNODE_FAILREP(){
- ActiveCounterPtr ptr;
-
- NodeBitmask nodes;
- nodes.clear();
- // nodes.bitORC(nodes);
-
- for(m_activeCounters.first(ptr); !ptr.isNull(); m_activeCounters.next(ptr)){
- ActiveCounter::SignalDesc desc = ptr.p->m_signalDesc;
- ndbout_c("theData[desc.m_senderDataOffset=%u] = %u",
- desc.m_senderDataOffset, ptr.p->m_senderData);
- ndbout_c("theData[desc.m_errorCodeOffset=%u] = %u",
- desc.m_errorCodeOffset, desc.m_nodeFailErrorCode);
- Uint32 len = MAX(MAX(desc.m_senderDataOffset, desc.m_errorCodeOffset),
- desc.m_senderRefOffset);
-
- NodeBitmask overlapping = ptr.p->m_nodes;
- Uint32 i = 0;
- while((i = overlapping.find(i)) != NodeBitmask::NotFound){
- ndbout_c(" theData[desc.m_senderRefOffset=%u] = %x",
- desc.m_senderRefOffset, numberToRef(desc.m_block, i));
- ndbout_c(" sendSignal(%x,%u,signal,%u,JBB",
- m_block.reference(), desc.m_gsn, len+1);
- i++;
- }
- }
-}
-
-void
-SafeCounterManager::execNODE_FAILREP(Signal* signal){
- Uint32 * theData = signal->getDataPtrSend();
- ActiveCounterPtr ptr;
- NodeBitmask nodes;
- nodes.assign(NodeBitmask::Size,
- ((const NodeFailRep*)signal->getDataPtr())->theNodes);
-
- for(m_activeCounters.first(ptr); !ptr.isNull(); m_activeCounters.next(ptr)){
- if(nodes.overlaps(ptr.p->m_nodes)){
- ActiveCounter::SignalDesc desc = ptr.p->m_signalDesc;
- theData[desc.m_senderDataOffset] = ptr.p->m_senderData;
- theData[desc.m_errorCodeOffset] = desc.m_nodeFailErrorCode;
- Uint32 len = MAX(MAX(desc.m_senderDataOffset, desc.m_errorCodeOffset),
- desc.m_senderRefOffset);
-
- NodeBitmask overlapping = ptr.p->m_nodes;
- overlapping.bitAND(nodes);
- Uint32 i = 0;
- while((i = overlapping.find(i)) != NodeBitmask::NotFound){
- theData[desc.m_senderRefOffset] = numberToRef(desc.m_block, i);
- m_block.sendSignal(m_block.reference(), desc.m_gsn, signal, len+1,JBB);
- i++;
- }
- }
- }
-}
-
-BlockReference
-SafeCounterManager::reference() const {
- return m_block.reference();
-}
-
-void
-SafeCounterManager::progError(int line, int err_code, const char* extra){
- m_block.progError(line, err_code, extra);
-}
-
-bool
-SafeCounterHandle::clearWaitingFor(SafeCounterManager& mgr, Uint32 nodeId)
-{
- SafeCounterManager::ActiveCounterPtr ptr;
- mgr.getPtr(ptr, m_activeCounterPtrI);
- ptr.p->m_nodes.clear(nodeId);
-
- if (ptr.p->m_nodes.isclear()){
- mgr.release(ptr);
- m_activeCounterPtrI = RNIL;
- return true;
- }
- return false;
-}
-
-SafeCounter::~SafeCounter(){
- bool clear = m_count == 0;
- bool isnull = m_ptr.i == RNIL;
-
- m_activeCounterPtrI = m_ptr.i;
-
- if(clear && isnull)
- return;
-
- if(clear && !isnull){
- m_mgr.release(m_ptr);
- m_activeCounterPtrI = RNIL;
- return;
- }
-
- /**
- * !clear && !isnull
- */
- if(!isnull){
- m_ptr.p->m_nodes = m_nodes;
- return;
- }
-
- ErrorReporter::handleAssert("~SafeCounter:: wo/ init", __FILE__, __LINE__);
-}
diff --git a/storage/ndb/src/kernel/vm/SafeCounter.hpp b/storage/ndb/src/kernel/vm/SafeCounter.hpp
deleted file mode 100644
index 7a917fd4310..00000000000
--- a/storage/ndb/src/kernel/vm/SafeCounter.hpp
+++ /dev/null
@@ -1,307 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef __SAFE_COUNTER_HPP
-#define __SAFE_COUNTER_HPP
-
-/*************************************************************
- *
- * SafeCounter "automates" three way to node-fais safe protocols
- * for "slave" failures. This is done by registing "fake" signals
- * to be sent in case of nodefailure.
- *
- * init<SignalClass>(..., GSN, senderData);
- *
- * It is implemented so that one can replace SignalCounter with
- * SafeCounter (SignalCounter should probably go away with time)
- * methods:
- * clearWaitingFor(nodeId);
- * done();
- * etc.
- *
- * If included in a new block method
- * SafeCounterManager::execNODE_FAILREP must included in
- * <block>::execNODE_FAILREP
- *
- * the SignalClass must have senderRef, senderData and errorCode
- * and also ErrorCode::NF_FakeErrorREF, implemented
- *
- * SafeCounter consists of 3 parts:
- * SafeCounterManager which keeps track of active "counters"
- * SafeCounterHandle to store "i-value" in your "op record"
- * SafeCounter as a temporary variable only to use on the stack
- * for operation
- *
- */
-
-#include <NodeBitmask.hpp>
-#include "DLList.hpp"
-#include "VMSignal.hpp"
-
-class SimulatedBlock;
-
-/**
- *
- */
-class SafeCounterManager {
- friend class SafeCounter;
- friend class SafeCounterHandle;
- friend class SimulatedBlock;
-public:
- SafeCounterManager(class SimulatedBlock &);
-
- bool setSize(Uint32 maxNoOfActiveMutexes, bool exit_on_error = true);
- Uint32 getSize() const ;
-
- void execNODE_FAILREP(Signal*);
- void printNODE_FAILREP();
-
-private:
- struct ActiveCounter { /** sizeof = 7words = 28bytes */
- public:
- Uint32 m_senderData;
- NodeBitmask m_nodes;
- struct SignalDesc {
- public:
- Uint16 m_gsn;
- Uint16 m_block;
- Uint8 m_senderRefOffset;
- Uint8 m_senderDataOffset;
- Uint8 m_errorCodeOffset;
- Uint8 m_nodeFailErrorCode;
- } m_signalDesc;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
-
- typedef Ptr<ActiveCounter> ActiveCounterPtr;
-
- bool seize(ActiveCounterPtr& ptr);
- void release(ActiveCounterPtr& ptr);
- void getPtr(ActiveCounterPtr& ptr, Uint32 ptrI);
-
- SimulatedBlock & m_block;
- ArrayPool<ActiveCounter> m_counterPool;
- DLList<ActiveCounter> m_activeCounters;
-
- BlockReference reference() const;
- void progError(int line, int err_code, const char* extra = 0);
-};
-
-
-class SafeCounterHandle {
- friend class SafeCounter;
-public:
- SafeCounterHandle();
-
- /**
- * Return if done (no nodes set in bitmask)
- */
- bool clearWaitingFor(SafeCounterManager& mgr, Uint32 nodeId);
-
- bool done() const;
-
-private:
- Uint32 m_activeCounterPtrI;
-};
-
-class SafeCounter {
- friend class SafeCounterManager;
-public:
- SafeCounter(SafeCounterManager&, SafeCounterHandle&);
-
- template<typename SignalClass>
- bool init(Uint16 block, Uint16 GSN, Uint32 senderData);
-
- template<typename SignalClass>
- bool init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData);
-
- template<typename SignalClass>
- bool init(NodeReceiverGroup rg, Uint32 senderData);
-
- ~SafeCounter();
-
- void clearWaitingFor();
-
- /**
- * When sending to different node
- */
- void setWaitingFor(Uint32 nodeId);
- bool clearWaitingFor(Uint32 nodeId);
- bool forceClearWaitingFor(Uint32 nodeId);
-
- bool isWaitingFor(Uint32 nodeId) const;
- bool done() const;
-
- const char * getText() const; /* ? needed for, some portability issues */
-
- SafeCounter& operator=(const NdbNodeBitmask&);
- SafeCounter& operator=(const NodeReceiverGroup&);
-private:
- Uint32 m_count;
- NodeBitmask m_nodes;
-
- SafeCounterManager & m_mgr;
- SafeCounterManager::ActiveCounterPtr m_ptr;
-
- Uint32 & m_activeCounterPtrI;
-};
-
-inline
-SafeCounterHandle::SafeCounterHandle(){
- m_activeCounterPtrI = RNIL;
-}
-
-inline
-bool
-SafeCounterHandle::done() const {
- return m_activeCounterPtrI == RNIL;
-}
-
-inline
-SafeCounter::SafeCounter(SafeCounterManager& mgr, SafeCounterHandle& handle)
- : m_mgr(mgr),
- m_activeCounterPtrI(handle.m_activeCounterPtrI)
-{
- m_ptr.i = handle.m_activeCounterPtrI;
- if (m_ptr.i == RNIL) {
- m_nodes.clear();
- m_count = 0;
- } else {
- m_mgr.getPtr(m_ptr, m_ptr.i);
- m_nodes = m_ptr.p->m_nodes;
- m_count = m_nodes.count();
- }
-}
-
-template<typename Ref>
-inline
-bool
-SafeCounter::init(Uint16 block, Uint16 GSN, Uint32 senderData){
-
- SafeCounterManager::ActiveCounter::SignalDesc signalDesc;
- signalDesc.m_gsn = GSN;
- signalDesc.m_block = block;
- signalDesc.m_errorCodeOffset = offsetof(Ref, errorCode) >> 2;
- signalDesc.m_senderRefOffset = offsetof(Ref, senderRef) >> 2;
- signalDesc.m_senderDataOffset = offsetof(Ref, senderData) >> 2;
- signalDesc.m_nodeFailErrorCode = Ref::NF_FakeErrorREF;
- assert(((Uint32)Ref::NF_FakeErrorREF) < 256);
-
- if(m_ptr.i == RNIL){
- SafeCounterManager::ActiveCounterPtr ptr;
- if(m_mgr.seize(ptr)){
- ptr.p->m_senderData = senderData;
- ptr.p->m_signalDesc = signalDesc;
- m_ptr = ptr;
- return true;
- }
- return false;
- }
-
- if(m_count == 0){
- m_ptr.p->m_senderData = senderData;
- m_ptr.p->m_signalDesc = signalDesc;
- return true;
- }
-
- ErrorReporter::handleAssert("SafeCounter::init twice", __FILE__, __LINE__);
- return false;
-}
-
-template<typename Ref>
-inline
-bool
-SafeCounter::init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData){
-
- if (init<Ref>(rg.m_block, GSN, senderData))
- {
- m_nodes = rg.m_nodes;
- m_count = m_nodes.count();
- return true;
- }
- return false;
-}
-
-template<typename Ref>
-inline
-bool
-SafeCounter::init(NodeReceiverGroup rg, Uint32 senderData){
-
- if (init<Ref>(rg.m_block, Ref::GSN, senderData))
- {
- m_nodes = rg.m_nodes;
- m_count = m_nodes.count();
- return true;
- }
- return false;
-}
-
-inline
-void
-SafeCounter::setWaitingFor(Uint32 nodeId) {
- if(!m_nodes.get(nodeId)){
- m_nodes.set(nodeId);
- m_count++;
- return;
- }
- ErrorReporter::handleAssert("SafeCounter::set", __FILE__, __LINE__);
-}
-
-inline
-bool
-SafeCounter::isWaitingFor(Uint32 nodeId) const {
- return m_nodes.get(nodeId);
-}
-
-inline
-bool
-SafeCounter::done() const {
- return m_count == 0;
-}
-
-inline
-bool
-SafeCounter::clearWaitingFor(Uint32 nodeId) {
- if(m_count > 0 && m_nodes.get(nodeId)){
- m_count--;
- m_nodes.clear(nodeId);
- return (m_count == 0);
- }
- ErrorReporter::handleAssert("SafeCounter::clear", __FILE__, __LINE__);
- return false;
-}
-
-inline
-void
-SafeCounter::clearWaitingFor(){
- m_count = 0;
- m_nodes.clear();
-}
-
-inline
-bool
-SafeCounter::forceClearWaitingFor(Uint32 nodeId){
- if(isWaitingFor(nodeId)){
- return clearWaitingFor(nodeId);
- }
- return (m_count == 0);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/SectionReader.cpp b/storage/ndb/src/kernel/vm/SectionReader.cpp
deleted file mode 100644
index 7cad2ed51c1..00000000000
--- a/storage/ndb/src/kernel/vm/SectionReader.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <SectionReader.hpp>
-#include <TransporterDefinitions.hpp>
-#include "LongSignal.hpp"
-
-#if 0
- Uint32 m_len;
- class SectionSegmentPool & m_pool;
- class SectionSegment * m_head;
- class SectionSegment * m_currentPos;
-#endif
-
-SectionReader::SectionReader
-(struct SegmentedSectionPtr & ptr, class SectionSegmentPool & pool)
- : m_pool(pool)
-{
- if(ptr.p == 0){
- m_pos = 0;
- m_len = 0;
- m_head = 0;
- m_currentSegment = 0;
- } else {
- m_pos = 0;
- m_len = ptr.p->m_sz;
- m_head = ptr.p;
- m_currentSegment = ptr.p;
- }
-}
-
-void
-SectionReader::reset(){
- m_pos = 0;
- m_currentSegment = m_head;
-}
-
-bool
-SectionReader::step(Uint32 len){
- if(m_pos + len >= m_len) {
- m_pos++;
- return false;
- }
- while(len > SectionSegment::DataLength){
- m_currentSegment = m_pool.getPtr(m_currentSegment->m_nextSegment);
-
- len -= SectionSegment::DataLength;
- m_pos += SectionSegment::DataLength;
- }
-
- Uint32 ind = m_pos % SectionSegment::DataLength;
- while(len > 0){
- len--;
- m_pos++;
-
- ind++;
- if(ind == SectionSegment::DataLength){
- ind = 0;
- m_currentSegment = m_pool.getPtr(m_currentSegment->m_nextSegment);
- }
- }
- return true;
-}
-
-bool
-SectionReader::getWord(Uint32 * dst){
- if (peekWord(dst)) {
- step(1);
- return true;
- }
- return false;
-}
-
-bool
-SectionReader::peekWord(Uint32 * dst) const {
- if(m_pos < m_len){
- Uint32 ind = m_pos % SectionSegment::DataLength;
- * dst = m_currentSegment->theData[ind];
- return true;
- }
- return false;
-}
-
-bool
-SectionReader::peekWords(Uint32 * dst, Uint32 len) const {
- if(m_pos + len > m_len)
- return false;
-
- Uint32 ind = (m_pos % SectionSegment::DataLength);
- Uint32 left = SectionSegment::DataLength - ind;
- SectionSegment * p = m_currentSegment;
-
- while(len > left){
- memcpy(dst, &p->theData[ind], 4 * left);
- dst += left;
- len -= left;
- ind = 0;
- left = SectionSegment::DataLength;
- p = m_pool.getPtr(p->m_nextSegment);
- }
-
- memcpy(dst, &p->theData[ind], 4 * len);
- return true;
-}
-
-bool
-SectionReader::getWords(Uint32 * dst, Uint32 len){
- if(m_pos + len > m_len)
- return false;
-
- Uint32 ind = (m_pos % SectionSegment::DataLength);
- Uint32 left = SectionSegment::DataLength - ind;
- SectionSegment * p = m_currentSegment;
-
- while(len > left){
- memcpy(dst, &p->theData[ind], 4 * left);
- dst += left;
- len -= left;
- ind = 0;
- left = SectionSegment::DataLength;
- p = m_pool.getPtr(p->m_nextSegment);
- }
-
- memcpy(dst, &p->theData[ind], 4 * len);
-
- m_pos += len;
- m_currentSegment = p;
- return true;
-}
-
diff --git a/storage/ndb/src/kernel/vm/SectionReader.hpp b/storage/ndb/src/kernel/vm/SectionReader.hpp
deleted file mode 100644
index 9e39c3666e3..00000000000
--- a/storage/ndb/src/kernel/vm/SectionReader.hpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SECTION_READER_HPP
-#define SECTION_READER_HPP
-
-#include <ndb_types.h>
-
-class SectionReader {
-public:
- SectionReader(struct SegmentedSectionPtr &,
- class SectionSegmentPool &);
-
- void reset();
- bool step(Uint32 len);
- bool getWord(Uint32 * dst);
- bool peekWord(Uint32 * dst) const ;
- bool peekWords(Uint32 * dst, Uint32 len) const;
- Uint32 getSize() const;
- bool getWords(Uint32 * dst, Uint32 len);
-
-private:
- Uint32 m_pos;
- Uint32 m_len;
- class SectionSegmentPool & m_pool;
- class SectionSegment * m_head;
- class SectionSegment * m_currentSegment;
-};
-
-inline
-Uint32 SectionReader::getSize() const
-{
- return m_len;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/SignalCounter.hpp b/storage/ndb/src/kernel/vm/SignalCounter.hpp
deleted file mode 100644
index 1d451114dff..00000000000
--- a/storage/ndb/src/kernel/vm/SignalCounter.hpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SIGNAL_COUNTER_HPP
-#define SIGNAL_COUNTER_HPP
-
-#include <NodeBitmask.hpp>
-#include <ErrorReporter.hpp>
-
-class SignalCounter {
- friend struct NodeReceiverGroup;
-
-private:
- Uint32 m_count;
- NdbNodeBitmask m_nodes;
-
-public:
- SignalCounter() { clearWaitingFor();}
- void clearWaitingFor();
-
- /**
- * When sending to different node
- */
- void setWaitingFor(Uint32 nodeId);
- void clearWaitingFor(Uint32 nodeId);
- void forceClearWaitingFor(Uint32 nodeId);
-
- bool isWaitingFor(Uint32 nodeId) const;
- bool done() const;
-
- const char * getText() const;
-
- SignalCounter& operator=(const NdbNodeBitmask & bitmask);
- SignalCounter& operator=(const NodeReceiverGroup& rg) {
- return (* this) = rg.m_nodes;
- }
-
- /**
- * When sending to same node
- */
- SignalCounter& operator=(Uint32 count);
- SignalCounter& operator--(int);
- SignalCounter& operator++(int);
- SignalCounter& operator+=(Uint32);
- Uint32 getCount() const;
-};
-
-inline
-void
-SignalCounter::setWaitingFor(Uint32 nodeId) {
- if(!m_nodes.get(nodeId)){
- m_nodes.set(nodeId);
- m_count++;
- return;
- }
- ErrorReporter::handleAssert("SignalCounter::set", __FILE__, __LINE__);
-}
-
-inline
-bool
-SignalCounter::isWaitingFor(Uint32 nodeId) const {
- return m_nodes.get(nodeId);
-}
-
-inline
-bool
-SignalCounter::done() const {
- return m_count == 0;
-}
-
-inline
-Uint32
-SignalCounter::getCount() const {
- return m_count;
-}
-
-inline
-void
-SignalCounter::clearWaitingFor(Uint32 nodeId) {
- if(m_nodes.get(nodeId) && m_count > 0){
- m_count--;
- m_nodes.clear(nodeId);
- return;
- }
- ErrorReporter::handleAssert("SignalCounter::clear", __FILE__, __LINE__);
-}
-
-inline
-void
-SignalCounter::clearWaitingFor(){
- m_count = 0;
- m_nodes.clear();
-}
-
-inline
-void
-SignalCounter::forceClearWaitingFor(Uint32 nodeId){
- if(isWaitingFor(nodeId)){
- clearWaitingFor(nodeId);
- }
-}
-
-inline
-SignalCounter&
-SignalCounter::operator=(Uint32 count){
- m_count = count;
- m_nodes.clear();
- return * this;
-}
-
-inline
-SignalCounter&
-SignalCounter::operator--(int){
- if(m_count > 0){
- m_count--;
- return * this;
- }
- ErrorReporter::handleAssert("SignalCounter::operator--", __FILE__, __LINE__);
- return * this;
-}
-
-inline
-SignalCounter&
-SignalCounter::operator++(int){
- m_count++;
- return * this;
-}
-
-inline
-SignalCounter&
-SignalCounter::operator+=(Uint32 n){
- m_count += n;
- return * this;
-}
-
-inline
-const char *
-SignalCounter::getText() const {
- static char buf[255];
- static char nodes[NodeBitmask::TextLength+1];
- BaseString::snprintf(buf, sizeof(buf), "[SignalCounter: m_count=%d %s]", m_count, m_nodes.getText(nodes));
- return buf;
-}
-
-inline
-SignalCounter&
-SignalCounter::operator=(const NdbNodeBitmask & bitmask){
- m_nodes = bitmask;
- m_count = bitmask.count();
- return * this;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/SimBlockList.hpp b/storage/ndb/src/kernel/vm/SimBlockList.hpp
deleted file mode 100644
index 2f4fbac5711..00000000000
--- a/storage/ndb/src/kernel/vm/SimBlockList.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SimBlockList_H
-#define SimBlockList_H
-
-#include <SimulatedBlock.hpp>
-
-class EmulatorData;
-
-class SimBlockList
-{
-public:
- SimBlockList();
- ~SimBlockList();
-
- void load(EmulatorData&);
- void unload();
-private:
- int noOfBlocks;
- SimulatedBlock** theList;
-};
-
-inline
-SimBlockList::SimBlockList(){
- noOfBlocks = 0;
- theList = 0;
-}
-
-inline
-SimBlockList::~SimBlockList(){
- unload();
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp b/storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp
deleted file mode 100644
index 77f72d1a5c3..00000000000
--- a/storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <SimpleProperties.hpp>
-#include <TransporterDefinitions.hpp>
-#include "LongSignal.hpp"
-
-SimplePropertiesSectionReader::SimplePropertiesSectionReader
-(struct SegmentedSectionPtr & ptr, class SectionSegmentPool & pool)
- : m_pool(pool)
-{
- if(ptr.p == 0){
- m_pos = 0;
- m_len = 0;
- m_head = 0;
- m_currentSegment = 0;
- } else {
- m_pos = 0;
- m_len = ptr.p->m_sz;
- m_head = ptr.p;
- m_currentSegment = ptr.p;
- }
- first();
-}
-
-void
-SimplePropertiesSectionReader::reset(){
- m_pos = 0;
- m_currentSegment = m_head;
-}
-
-bool
-SimplePropertiesSectionReader::step(Uint32 len){
- if(m_pos + len >= m_len) {
- m_pos++;
- return false;
- }
- while(len > SectionSegment::DataLength){
- m_currentSegment = m_pool.getPtr(m_currentSegment->m_nextSegment);
-
- len -= SectionSegment::DataLength;
- m_pos += SectionSegment::DataLength;
- }
-
- Uint32 ind = m_pos % SectionSegment::DataLength;
- while(len > 0){
- len--;
- m_pos++;
-
- ind++;
- if(ind == SectionSegment::DataLength){
- ind = 0;
- m_currentSegment = m_pool.getPtr(m_currentSegment->m_nextSegment);
- }
- }
- return true;
-}
-
-bool
-SimplePropertiesSectionReader::getWord(Uint32 * dst){
- if (peekWord(dst)) {
- step(1);
- return true;
- }
- return false;
-}
-
-bool
-SimplePropertiesSectionReader::peekWord(Uint32 * dst) const {
- if(m_pos < m_len){
- Uint32 ind = m_pos % SectionSegment::DataLength;
- * dst = m_currentSegment->theData[ind];
- return true;
- }
- return false;
-}
-
-bool
-SimplePropertiesSectionReader::peekWords(Uint32 * dst, Uint32 len) const {
- if(m_pos + len > m_len){
- return false;
- }
- Uint32 ind = (m_pos % SectionSegment::DataLength);
- Uint32 left = (SectionSegment::DataLength - ind);
- SectionSegment * p = m_currentSegment;
-
- while(len > left){
- memcpy(dst, &p->theData[ind], 4 * left);
- dst += left;
- len -= left;
- ind = 0;
- left = SectionSegment::DataLength;
- p = m_pool.getPtr(p->m_nextSegment);
- }
-
- memcpy(dst, &p->theData[ind], 4 * len);
- return true;
-}
-
-bool
-SimplePropertiesSectionReader::getWords(Uint32 * dst, Uint32 len){
- if(peekWords(dst, len)){
- step(len);
- return true;
- }
- return false;
-}
-
-SimplePropertiesSectionWriter::SimplePropertiesSectionWriter(class SectionSegmentPool & pool)
- : m_pool(pool)
-{
- Ptr<SectionSegment> first;
- if(m_pool.seize(first)){
- ;
- } else {
- m_pos = -1;
- m_head = 0;
- m_currentSegment = 0;
- m_prevPtrI = RNIL;
- return;
- }
- m_sz = 0;
- m_pos = 0;
- m_head = first.p;
- m_head->m_lastSegment = first.i;
- m_currentSegment = first.p;
- m_prevPtrI = RNIL;
-}
-
-bool
-SimplePropertiesSectionWriter::reset(){
- if(m_pos >= 0){
- m_pos = 0;
- return true;
- }
- return false;
-}
-
-bool
-SimplePropertiesSectionWriter::putWord(Uint32 val){
- return putWords(&val, 1);
-}
-
-bool
-SimplePropertiesSectionWriter::putWords(const Uint32 * src, Uint32 len){
- Uint32 left = SectionSegment::DataLength - m_pos;
-
- while(len >= left){
- memcpy(&m_currentSegment->theData[m_pos], src, 4 * left);
- Ptr<SectionSegment> next;
- if(m_pool.seize(next)){
-
- m_prevPtrI = m_currentSegment->m_lastSegment;
- m_currentSegment->m_nextSegment = next.i;
- next.p->m_lastSegment = next.i;
- m_currentSegment = next.p;
-
- len -= left;
- src += left;
- m_sz += left;
-
- left = SectionSegment::DataLength;
- m_pos = 0;
- } else {
- abort();
- return false;
- }
- }
-
- memcpy(&m_currentSegment->theData[m_pos], src, 4 * len);
- m_sz += len;
- m_pos += len;
-
- assert(m_pos < (int)SectionSegment::DataLength);
-
- return true;
-}
-
-void
-SimplePropertiesSectionWriter::getPtr(struct SegmentedSectionPtr & dst){
- // Set last ptr and size
- if(m_pos >= 0){
- dst.p = m_head;
- dst.i = m_head->m_lastSegment;
- dst.sz = m_sz;
- m_head->m_sz = m_sz;
- m_head->m_lastSegment = m_currentSegment->m_lastSegment;
-
- if((m_pos % SectionSegment::DataLength) == 0){
- m_pool.release(m_currentSegment->m_lastSegment);
- m_head->m_lastSegment = m_prevPtrI;
- }
-
- m_sz = 0;
- m_pos = -1;
- m_head = m_currentSegment = 0;
- m_prevPtrI = RNIL;
- return ;
- }
- dst.p = 0;
- dst.sz = 0;
- dst.i = RNIL;
-
- m_pool.release(m_head->m_lastSegment);
-
- m_sz = 0;
- m_pos = -1;
- m_head = m_currentSegment = 0;
- m_prevPtrI = RNIL;
-}
diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp
deleted file mode 100644
index 6703b3c7fab..00000000000
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ /dev/null
@@ -1,2082 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include "SimulatedBlock.hpp"
-#include <NdbOut.hpp>
-#include <GlobalData.hpp>
-#include <Emulator.hpp>
-#include <WatchDog.hpp>
-#include <ErrorHandlingMacros.hpp>
-#include <TimeQueue.hpp>
-#include <TransporterRegistry.hpp>
-#include <SignalLoggerManager.hpp>
-#include <FastScheduler.hpp>
-#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"
-
-#include <Properties.hpp>
-#include "Configuration.hpp"
-#include <AttributeDescriptor.hpp>
-#include <NdbSqlUtil.hpp>
-
-#include <EventLogger.hpp>
-extern EventLogger g_eventLogger;
-
-#define ljamEntry() jamEntryLine(30000 + __LINE__)
-#define ljam() jamLine(30000 + __LINE__)
-
-//
-// Constructor, Destructor
-//
-SimulatedBlock::SimulatedBlock(BlockNumber blockNumber,
- struct Block_context & ctx)
- : theNodeId(globalData.ownId),
- theNumber(blockNumber),
- theReference(numberToRef(blockNumber, globalData.ownId)),
- m_ctx(ctx),
- m_global_page_pool(globalData.m_global_page_pool),
- m_shared_page_pool(globalData.m_shared_page_pool),
- c_fragmentInfoHash(c_fragmentInfoPool),
- c_linearFragmentSendList(c_fragmentSendPool),
- c_segmentedFragmentSendList(c_fragmentSendPool),
- c_mutexMgr(* this),
- c_counterMgr(* this)
-{
- NewVarRef = 0;
-
- globalData.setBlock(blockNumber, this);
- c_fragmentIdCounter = 1;
- c_fragSenderRunning = false;
-
- Properties tmp;
- const Properties * p = &tmp;
- ndbrequire(p != 0);
-
- Uint32 count = 10;
- char buf[255];
-
- count = 10;
- BaseString::snprintf(buf, 255, "%s.FragmentSendPool", getBlockName(blockNumber));
- if(!p->get(buf, &count))
- p->get("FragmentSendPool", &count);
- c_fragmentSendPool.setSize(count);
-
- count = 10;
- BaseString::snprintf(buf, 255, "%s.FragmentInfoPool", getBlockName(blockNumber));
- if(!p->get(buf, &count))
- p->get("FragmentInfoPool", &count);
- c_fragmentInfoPool.setSize(count);
-
- count = 10;
- BaseString::snprintf(buf, 255, "%s.FragmentInfoHash", getBlockName(blockNumber));
- if(!p->get(buf, &count))
- p->get("FragmentInfoHash", &count);
- c_fragmentInfoHash.setSize(count);
-
- count = 5;
- BaseString::snprintf(buf, 255, "%s.ActiveMutexes", getBlockName(blockNumber));
- if(!p->get(buf, &count))
- p->get("ActiveMutexes", &count);
- c_mutexMgr.setSize(count);
-
- c_counterMgr.setSize(5);
-
-#ifdef VM_TRACE_TIME
- clearTimes();
-#endif
-
- for(GlobalSignalNumber i = 0; i<=MAX_GSN; i++)
- theExecArray[i] = 0;
-
- installSimulatedBlockFunctions();
- UpgradeStartup::installEXEC(this);
-
- CLEAR_ERROR_INSERT_VALUE;
-
-#ifdef VM_TRACE
- m_global_variables = new Ptr<void> * [1];
- m_global_variables[0] = 0;
-#endif
-}
-
-SimulatedBlock::~SimulatedBlock()
-{
- freeBat();
-#ifdef VM_TRACE_TIME
- printTimes(stdout);
-#endif
-
-#ifdef VM_TRACE
- delete [] m_global_variables;
-#endif
-}
-
-void
-SimulatedBlock::installSimulatedBlockFunctions(){
- ExecFunction * a = theExecArray;
- a[GSN_NODE_STATE_REP] = &SimulatedBlock::execNODE_STATE_REP;
- a[GSN_CHANGE_NODE_STATE_REQ] = &SimulatedBlock::execCHANGE_NODE_STATE_REQ;
- a[GSN_NDB_TAMPER] = &SimulatedBlock::execNDB_TAMPER;
- a[GSN_SIGNAL_DROPPED_REP] = &SimulatedBlock::execSIGNAL_DROPPED_REP;
- a[GSN_CONTINUE_FRAGMENTED]= &SimulatedBlock::execCONTINUE_FRAGMENTED;
- a[GSN_UTIL_CREATE_LOCK_REF] = &SimulatedBlock::execUTIL_CREATE_LOCK_REF;
- a[GSN_UTIL_CREATE_LOCK_CONF] = &SimulatedBlock::execUTIL_CREATE_LOCK_CONF;
- a[GSN_UTIL_DESTROY_LOCK_REF] = &SimulatedBlock::execUTIL_DESTORY_LOCK_REF;
- a[GSN_UTIL_DESTROY_LOCK_CONF] = &SimulatedBlock::execUTIL_DESTORY_LOCK_CONF;
- a[GSN_UTIL_LOCK_REF] = &SimulatedBlock::execUTIL_LOCK_REF;
- 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_FSOPENREF] = &SimulatedBlock::execFSOPENREF;
- a[GSN_FSCLOSEREF] = &SimulatedBlock::execFSCLOSEREF;
- a[GSN_FSWRITEREF] = &SimulatedBlock::execFSWRITEREF;
- a[GSN_FSREADREF] = &SimulatedBlock::execFSREADREF;
- a[GSN_FSREMOVEREF] = &SimulatedBlock::execFSREMOVEREF;
- a[GSN_FSSYNCREF] = &SimulatedBlock::execFSSYNCREF;
- a[GSN_FSAPPENDREF] = &SimulatedBlock::execFSAPPENDREF;
- a[GSN_NODE_START_REP] = &SimulatedBlock::execNODE_START_REP;
- a[GSN_API_START_REP] = &SimulatedBlock::execAPI_START_REP;
-}
-
-void
-SimulatedBlock::addRecSignalImpl(GlobalSignalNumber gsn,
- ExecFunction f, bool force){
- if(gsn > MAX_GSN || (!force && theExecArray[gsn] != 0)){
- char errorMsg[255];
- BaseString::snprintf(errorMsg, 255,
- "GSN %d(%d))", gsn, MAX_GSN);
- ERROR_SET(fatal, NDBD_EXIT_ILLEGAL_SIGNAL, errorMsg, errorMsg);
- }
- theExecArray[gsn] = f;
-}
-
-void
-SimulatedBlock::signal_error(Uint32 gsn, Uint32 len, Uint32 recBlockNo,
- const char* filename, int lineno) const
-{
- char objRef[255];
- BaseString::snprintf(objRef, 255, "%s:%d", filename, lineno);
- char probData[255];
- BaseString::snprintf(probData, 255,
- "Signal (GSN: %d, Length: %d, Rec Block No: %d)",
- gsn, len, recBlockNo);
-
- ErrorReporter::handleError(NDBD_EXIT_BLOCK_BNR_ZERO,
- probData,
- objRef);
-}
-
-
-extern class SectionSegmentPool g_sectionSegmentPool;
-
-void
-SimulatedBlock::sendSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jobBuffer) const {
-
- BlockNumber sendBnr = number();
- BlockReference sendBRef = reference();
-
- Uint32 noOfSections = signal->header.m_noOfSections;
- Uint32 recBlock = refToBlock(ref);
- Uint32 recNode = refToNode(ref);
- Uint32 ourProcessor = globalData.ownId;
-
- signal->header.theLength = length;
- signal->header.theVerId_signalNumber = gsn;
- signal->header.theReceiversBlockNumber = recBlock;
-
- Uint32 tSignalId = signal->header.theSignalId;
-
- if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
- signal_error(gsn, length, recBlock, __FILE__, __LINE__);
- return;
- }//if
-#ifdef VM_TRACE
- if(globalData.testOn){
- Uint16 proc =
- (recNode == 0 ? globalData.ownId : recNode);
- signal->header.theSendersBlockRef = sendBRef;
- globalSignalLoggers.sendSignal(signal->header,
- jobBuffer,
- &signal->theData[0],
- proc,
- signal->m_sectionPtr,
- signal->header.m_noOfSections);
- }
-#endif
-
- if(recNode == ourProcessor || recNode == 0) {
- signal->header.theSendersSignalId = tSignalId;
- signal->header.theSendersBlockRef = sendBRef;
- signal->header.theLength = length;
- globalScheduler.execute(signal, jobBuffer, recBlock,
- gsn);
- signal->header.m_noOfSections = 0;
- signal->header.m_fragmentInfo = 0;
- return;
- } else {
- // send distributed Signal
- SignalHeader sh;
-
- Uint32 tTrace = signal->getTrace();
-
- sh.theVerId_signalNumber = gsn;
- sh.theReceiversBlockNumber = recBlock;
- sh.theSendersBlockRef = sendBnr;
- sh.theLength = length;
- sh.theTrace = tTrace;
- sh.theSignalId = tSignalId;
- sh.m_noOfSections = noOfSections;
- sh.m_fragmentInfo = 0;
-
-#ifdef TRACE_DISTRIBUTED
- ndbout_c("send: %s(%d) to (%s, %d)",
- getSignalName(gsn), gsn, getBlockName(recBlock),
- recNode);
-#endif
- SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer,
- &signal->theData[0],
- recNode,
- g_sectionSegmentPool,
- signal->m_sectionPtr);
-
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
- ::releaseSections(noOfSections, signal->m_sectionPtr);
- signal->header.m_noOfSections = 0;
- }
- return;
-}
-
-void
-SimulatedBlock::sendSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jobBuffer) const {
-
- Uint32 noOfSections = signal->header.m_noOfSections;
- Uint32 tSignalId = signal->header.theSignalId;
- Uint32 tTrace = signal->getTrace();
- Uint32 tFragInf = signal->header.m_fragmentInfo;
-
- Uint32 ourProcessor = globalData.ownId;
- Uint32 recBlock = rg.m_block;
-
- signal->header.theLength = length;
- signal->header.theVerId_signalNumber = gsn;
- signal->header.theReceiversBlockNumber = recBlock;
- signal->header.theSendersSignalId = tSignalId;
- signal->header.theSendersBlockRef = reference();
-
- if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
- signal_error(gsn, length, recBlock, __FILE__, __LINE__);
- return;
- }//if
-
- SignalHeader sh;
-
- sh.theVerId_signalNumber = gsn;
- sh.theReceiversBlockNumber = recBlock;
- sh.theSendersBlockRef = number();
- sh.theLength = length;
- sh.theTrace = tTrace;
- sh.theSignalId = tSignalId;
- sh.m_noOfSections = noOfSections;
- sh.m_fragmentInfo = tFragInf;
-
- /**
- * Check own node
- */
- bool release = true;
- if(rg.m_nodes.get(0) || rg.m_nodes.get(ourProcessor)){
-#ifdef VM_TRACE
- if(globalData.testOn){
- globalSignalLoggers.sendSignal(signal->header,
- jobBuffer,
- &signal->theData[0],
- ourProcessor,
- signal->m_sectionPtr,
- signal->header.m_noOfSections);
- }
-#endif
- globalScheduler.execute(signal, jobBuffer, recBlock, gsn);
-
- rg.m_nodes.clear((Uint32)0);
- rg.m_nodes.clear(ourProcessor);
- release = false;
- }
-
- /**
- * Do the big loop
- */
- Uint32 recNode = 0;
- while(!rg.m_nodes.isclear()){
- recNode = rg.m_nodes.find(recNode + 1);
- rg.m_nodes.clear(recNode);
-#ifdef VM_TRACE
- if(globalData.testOn){
- globalSignalLoggers.sendSignal(signal->header,
- jobBuffer,
- &signal->theData[0],
- recNode,
- signal->m_sectionPtr,
- signal->header.m_noOfSections);
- }
-#endif
-
-#ifdef TRACE_DISTRIBUTED
- ndbout_c("send: %s(%d) to (%s, %d)",
- getSignalName(gsn), gsn, getBlockName(recBlock),
- recNode);
-#endif
-
- SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer,
- &signal->theData[0],
- recNode,
- g_sectionSegmentPool,
- signal->m_sectionPtr);
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
- }
-
- if(release){
- ::releaseSections(noOfSections, signal->m_sectionPtr);
- }
-
- signal->header.m_noOfSections = 0;
- signal->header.m_fragmentInfo = 0;
-
- return;
-}
-
-bool import(Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len);
-
-void
-SimulatedBlock::sendSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jobBuffer,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections) const {
-
- BlockNumber sendBnr = number();
- BlockReference sendBRef = reference();
-
- Uint32 recBlock = refToBlock(ref);
- Uint32 recNode = refToNode(ref);
- Uint32 ourProcessor = globalData.ownId;
-
- ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
-
- signal->header.theLength = length;
- signal->header.theVerId_signalNumber = gsn;
- signal->header.theReceiversBlockNumber = recBlock;
- signal->header.m_noOfSections = noOfSections;
-
- Uint32 tSignalId = signal->header.theSignalId;
- Uint32 tFragInfo = signal->header.m_fragmentInfo;
-
- if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
- signal_error(gsn, length, recBlock, __FILE__, __LINE__);
- return;
- }//if
-#ifdef VM_TRACE
- if(globalData.testOn){
- Uint16 proc =
- (recNode == 0 ? globalData.ownId : recNode);
- signal->header.theSendersBlockRef = sendBRef;
- globalSignalLoggers.sendSignal(signal->header,
- jobBuffer,
- &signal->theData[0],
- proc,
- ptr, noOfSections);
- }
-#endif
-
- if(recNode == ourProcessor || recNode == 0) {
- signal->header.theSendersSignalId = tSignalId;
- signal->header.theSendersBlockRef = sendBRef;
-
- /**
- * We have to copy the data
- */
- Ptr<SectionSegment> segptr[3];
- for(Uint32 i = 0; i<noOfSections; i++){
- ndbrequire(import(segptr[i], ptr[i].p, ptr[i].sz));
- signal->m_sectionPtr[i].i = segptr[i].i;
- }
-
- globalScheduler.execute(signal, jobBuffer, recBlock,
- gsn);
- signal->header.m_noOfSections = 0;
- return;
- } else {
- // send distributed Signal
- SignalHeader sh;
-
- Uint32 tTrace = signal->getTrace();
- Uint32 noOfSections = signal->header.m_noOfSections;
-
- sh.theVerId_signalNumber = gsn;
- sh.theReceiversBlockNumber = recBlock;
- sh.theSendersBlockRef = sendBnr;
- sh.theLength = length;
- sh.theTrace = tTrace;
- sh.theSignalId = tSignalId;
- sh.m_noOfSections = noOfSections;
- sh.m_fragmentInfo = tFragInfo;
-
-#ifdef TRACE_DISTRIBUTED
- ndbout_c("send: %s(%d) to (%s, %d)",
- getSignalName(gsn), gsn, getBlockName(recBlock),
- recNode);
-#endif
-
- SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer,
- &signal->theData[0],
- recNode,
- ptr);
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
- }
-
- signal->header.m_noOfSections = 0;
- signal->header.m_fragmentInfo = 0;
- return;
-}
-
-void
-SimulatedBlock::sendSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jobBuffer,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections) const {
-
- Uint32 tSignalId = signal->header.theSignalId;
- Uint32 tTrace = signal->getTrace();
- Uint32 tFragInfo = signal->header.m_fragmentInfo;
-
- Uint32 ourProcessor = globalData.ownId;
- Uint32 recBlock = rg.m_block;
-
- ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
-
- signal->header.theLength = length;
- signal->header.theVerId_signalNumber = gsn;
- signal->header.theReceiversBlockNumber = recBlock;
- signal->header.theSendersSignalId = tSignalId;
- signal->header.theSendersBlockRef = reference();
- signal->header.m_noOfSections = noOfSections;
-
- if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
- signal_error(gsn, length, recBlock, __FILE__, __LINE__);
- return;
- }//if
-
- SignalHeader sh;
- sh.theVerId_signalNumber = gsn;
- sh.theReceiversBlockNumber = recBlock;
- sh.theSendersBlockRef = number();
- sh.theLength = length;
- sh.theTrace = tTrace;
- sh.theSignalId = tSignalId;
- sh.m_noOfSections = noOfSections;
- sh.m_fragmentInfo = tFragInfo;
-
- /**
- * Check own node
- */
- if(rg.m_nodes.get(0) || rg.m_nodes.get(ourProcessor)){
-#ifdef VM_TRACE
- if(globalData.testOn){
- globalSignalLoggers.sendSignal(signal->header,
- jobBuffer,
- &signal->theData[0],
- ourProcessor,
- ptr, noOfSections);
- }
-#endif
- /**
- * We have to copy the data
- */
- Ptr<SectionSegment> segptr[3];
- for(Uint32 i = 0; i<noOfSections; i++){
- ndbrequire(import(segptr[i], ptr[i].p, ptr[i].sz));
- signal->m_sectionPtr[i].i = segptr[i].i;
- }
- globalScheduler.execute(signal, jobBuffer, recBlock, gsn);
-
- rg.m_nodes.clear((Uint32)0);
- rg.m_nodes.clear(ourProcessor);
- }
-
- /**
- * Do the big loop
- */
- Uint32 recNode = 0;
- while(!rg.m_nodes.isclear()){
- recNode = rg.m_nodes.find(recNode + 1);
- rg.m_nodes.clear(recNode);
-
-#ifdef VM_TRACE
- if(globalData.testOn){
- globalSignalLoggers.sendSignal(signal->header,
- jobBuffer,
- &signal->theData[0],
- recNode,
- ptr, noOfSections);
- }
-#endif
-
-#ifdef TRACE_DISTRIBUTED
- ndbout_c("send: %s(%d) to (%s, %d)",
- getSignalName(gsn), gsn, getBlockName(recBlock),
- recNode);
-#endif
-
- SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer,
- &signal->theData[0],
- recNode,
- ptr);
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
- }
-
- signal->header.m_noOfSections = 0;
- signal->header.m_fragmentInfo = 0;
-
- return;
-}
-
-void
-SimulatedBlock::sendSignalWithDelay(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 delayInMilliSeconds,
- Uint32 length) const {
-
- BlockNumber bnr = refToBlock(ref);
-
- //BlockNumber sendBnr = number();
- BlockReference sendBRef = reference();
-
- if (bnr == 0) {
- bnr_error();
- }//if
-
- signal->header.theLength = length;
- signal->header.theSendersSignalId = signal->header.theSignalId;
- signal->header.theSendersBlockRef = sendBRef;
- signal->header.theVerId_signalNumber = gsn;
- signal->header.theReceiversBlockNumber = bnr;
-
-#ifdef VM_TRACE
- {
- if(globalData.testOn){
- globalSignalLoggers.sendSignalWithDelay(delayInMilliSeconds,
- signal->header,
- 0,
- &signal->theData[0],
- globalData.ownId,
- signal->m_sectionPtr,
- signal->header.m_noOfSections);
- }
- }
-#endif
- globalTimeQueue.insert(signal, bnr, gsn, delayInMilliSeconds);
-
- signal->header.m_noOfSections = 0;
- signal->header.m_fragmentInfo = 0;
-
- // befor 2nd parameter to globalTimeQueue.insert
- // (Priority)theSendSig[sigIndex].jobBuffer
-}
-
-void
-SimulatedBlock::releaseSections(Signal* signal){
- ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
- signal->header.m_noOfSections = 0;
-}
-
-class SectionSegmentPool&
-SimulatedBlock::getSectionSegmentPool(){
- return g_sectionSegmentPool;
-}
-
-NewVARIABLE *
-SimulatedBlock::allocateBat(int batSize){
- NewVARIABLE* bat = NewVarRef;
- bat = (NewVARIABLE*)realloc(bat, batSize * sizeof(NewVARIABLE));
- NewVarRef = bat;
- theBATSize = batSize;
- return bat;
-}
-
-void
-SimulatedBlock::freeBat(){
- if(NewVarRef != 0){
- free(NewVarRef);
- NewVarRef = 0;
- }
-}
-
-const NewVARIABLE *
-SimulatedBlock::getBat(Uint16 blockNo){
- SimulatedBlock * sb = globalData.getBlock(blockNo);
- if(sb == 0)
- return 0;
- return sb->NewVarRef;
-}
-
-Uint16
-SimulatedBlock::getBatSize(Uint16 blockNo){
- SimulatedBlock * sb = globalData.getBlock(blockNo);
- if(sb == 0)
- return 0;
- return sb->theBATSize;
-}
-
-void* SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear, Uint32 paramId)
-{
- return allocRecordAligned(type, s, n, 0, 0, clear, paramId);
-}
-
-void*
-SimulatedBlock::allocRecordAligned(const char * type, size_t s, size_t n, void **unaligned_buffer, Uint32 align, bool clear, Uint32 paramId)
-{
-
- void * p = NULL;
- Uint32 over_alloc = unaligned_buffer ? (align - 1) : 0;
- size_t size = n*s + over_alloc;
- Uint64 real_size = (Uint64)((Uint64)n)*((Uint64)s) + over_alloc;
- refresh_watch_dog(9);
- if (real_size > 0){
-#ifdef VM_TRACE_MEM
- ndbout_c("%s::allocRecord(%s, %u, %u) = %llu bytes",
- getBlockName(number()),
- type,
- s,
- n,
- real_size);
-#endif
- if( real_size == (Uint64)size )
- p = ndbd_malloc(size);
- if (p == NULL){
- char buf1[255];
- char buf2[255];
- struct ndb_mgm_param_info param_info;
- size_t size = sizeof(ndb_mgm_param_info);
-
- if(0 != paramId && 0 == ndb_mgm_get_db_parameter_info(paramId, &param_info, &size)) {
- BaseString::snprintf(buf1, sizeof(buf1), "%s could not allocate memory for parameter %s",
- getBlockName(number()), param_info.m_name);
- } else {
- BaseString::snprintf(buf1, sizeof(buf1), "%s could not allocate memory for %s",
- getBlockName(number()), type);
- }
- BaseString::snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %llu bytes",
- (Uint32)s, (Uint32)n, (Uint64)real_size);
- ERROR_SET(fatal, NDBD_EXIT_MEMALLOC, buf1, buf2);
- }
-
- if(clear){
- char * ptr = (char*)p;
- const Uint32 chunk = 128 * 1024;
- while(size > chunk){
- refresh_watch_dog(9);
- memset(ptr, 0, chunk);
- ptr += chunk;
- size -= chunk;
- }
- refresh_watch_dog(9);
- memset(ptr, 0, size);
- }
- if (unaligned_buffer)
- {
- *unaligned_buffer = p;
- p = (void *)(((UintPtr)p + over_alloc) & ~(UintPtr)(over_alloc));
-#ifdef VM_TRACE
- g_eventLogger.info("'%s' (%u) %llu %llu, alignment correction %u bytes",
- type, align, (Uint64)p, (Uint64)p+n*s,
- (Uint32)((UintPtr)p - (UintPtr)*unaligned_buffer));
-#endif
- }
- }
- return p;
-}
-
-void
-SimulatedBlock::deallocRecord(void ** ptr,
- const char * type, size_t s, size_t n){
- (void)type;
-
- if(* ptr != 0){
- ndbd_free(* ptr, n*s);
- * ptr = 0;
- }
-}
-
-void
-SimulatedBlock::refresh_watch_dog(Uint32 place)
-{
- globalData.incrementWatchDogCounter(place);
-}
-
-void
-SimulatedBlock::update_watch_dog_timer(Uint32 interval)
-{
- extern EmulatorData globalEmulatorData;
- globalEmulatorData.theWatchDog->setCheckInterval(interval);
-}
-
-void
-SimulatedBlock::progError(int line, int err_code, const char* extra) const {
- jamLine(line);
-
- const char *aBlockName = getBlockName(number(), "VM Kernel");
-
- // Pack status of interesting config variables
- // so that we can print them in error.log
- int magicStatus =
- (m_ctx.m_config.stopOnError()<<1) +
- (m_ctx.m_config.getInitialStart()<<2) +
- (m_ctx.m_config.getDaemonMode()<<3);
-
-
- /* Add line number to block name */
- char buf[100];
- BaseString::snprintf(&buf[0], 100, "%s (Line: %d) 0x%.8x",
- aBlockName, line, magicStatus);
-
- ErrorReporter::handleError(err_code, extra, buf);
-
-}
-
-void
-SimulatedBlock::infoEvent(const char * msg, ...) const {
- if(msg == 0)
- return;
-
- Uint32 theData[25];
- theData[0] = NDB_LE_InfoEvent;
- char * buf = (char *)&(theData[1]);
-
- va_list ap;
- va_start(ap, msg);
- BaseString::vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
- va_end(ap);
-
- int len = strlen(buf) + 1;
- if(len > 96){
- len = 96;
- buf[95] = 0;
- }
-
- /**
- * Init and put it into the job buffer
- */
- SignalHeader sh;
- memset(&sh, 0, sizeof(SignalHeader));
-
- const Signal * signal = globalScheduler.getVMSignals();
- Uint32 tTrace = signal->header.theTrace;
- Uint32 tSignalId = signal->header.theSignalId;
-
- sh.theVerId_signalNumber = GSN_EVENT_REP;
- sh.theReceiversBlockNumber = CMVMI;
- sh.theSendersBlockRef = reference();
- sh.theTrace = tTrace;
- sh.theSignalId = tSignalId;
- sh.theLength = ((len+3)/4)+1;
-
- Uint32 secPtrI[3]; // Dummy
- globalScheduler.execute(&sh, JBB, theData, secPtrI);
-}
-
-void
-SimulatedBlock::warningEvent(const char * msg, ...) const {
- if(msg == 0)
- return;
-
- Uint32 theData[25];
- theData[0] = NDB_LE_WarningEvent;
- char * buf = (char *)&(theData[1]);
-
- va_list ap;
- va_start(ap, msg);
- BaseString::vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
- va_end(ap);
-
- int len = strlen(buf) + 1;
- if(len > 96){
- len = 96;
- buf[95] = 0;
- }
-
- /**
- * Init and put it into the job buffer
- */
- SignalHeader sh;
- memset(&sh, 0, sizeof(SignalHeader));
-
- const Signal * signal = globalScheduler.getVMSignals();
- Uint32 tTrace = signal->header.theTrace;
- Uint32 tSignalId = signal->header.theSignalId;
-
- sh.theVerId_signalNumber = GSN_EVENT_REP;
- sh.theReceiversBlockNumber = CMVMI;
- sh.theSendersBlockRef = reference();
- sh.theTrace = tTrace;
- sh.theSignalId = tSignalId;
- sh.theLength = ((len+3)/4)+1;
-
- Uint32 secPtrI[3]; // Dummy
- globalScheduler.execute(&sh, JBB, theData, secPtrI);
-}
-
-void
-SimulatedBlock::execNODE_STATE_REP(Signal* signal){
- const NodeStateRep * const rep = (NodeStateRep *)&signal->theData[0];
-
- this->theNodeState = rep->nodeState;
-}
-
-void
-SimulatedBlock::execCHANGE_NODE_STATE_REQ(Signal* signal){
- const ChangeNodeStateReq * const req =
- (ChangeNodeStateReq *)&signal->theData[0];
-
- this->theNodeState = req->nodeState;
- const Uint32 senderData = req->senderData;
- const BlockReference senderRef = req->senderRef;
-
- /**
- * Pack return signal
- */
- ChangeNodeStateConf * const conf =
- (ChangeNodeStateConf *)&signal->theData[0];
-
- conf->senderData = senderData;
-
- sendSignal(senderRef, GSN_CHANGE_NODE_STATE_CONF, signal,
- ChangeNodeStateConf::SignalLength, JBB);
-}
-
-void
-SimulatedBlock::execNDB_TAMPER(Signal * signal){
- SET_ERROR_INSERT_VALUE(signal->theData[0]);
-}
-
-void
-SimulatedBlock::execSIGNAL_DROPPED_REP(Signal * signal){
- 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);
-}
-
-void
-SimulatedBlock::execCONTINUE_FRAGMENTED(Signal * signal){
- ljamEntry();
-
- Ptr<FragmentSendInfo> fragPtr;
-
- c_segmentedFragmentSendList.first(fragPtr);
- for(; !fragPtr.isNull();){
- ljam();
- Ptr<FragmentSendInfo> copyPtr = fragPtr;
- c_segmentedFragmentSendList.next(fragPtr);
-
- sendNextSegmentedFragment(signal, * copyPtr.p);
- if(copyPtr.p->m_status == FragmentSendInfo::SendComplete){
- ljam();
- if(copyPtr.p->m_callback.m_callbackFunction != 0) {
- ljam();
- execute(signal, copyPtr.p->m_callback, 0);
- }//if
- c_segmentedFragmentSendList.release(copyPtr);
- }
- }
-
- c_linearFragmentSendList.first(fragPtr);
- for(; !fragPtr.isNull();){
- ljam();
- Ptr<FragmentSendInfo> copyPtr = fragPtr;
- c_linearFragmentSendList.next(fragPtr);
-
- sendNextLinearFragment(signal, * copyPtr.p);
- if(copyPtr.p->m_status == FragmentSendInfo::SendComplete){
- ljam();
- if(copyPtr.p->m_callback.m_callbackFunction != 0) {
- ljam();
- execute(signal, copyPtr.p->m_callback, 0);
- }//if
- c_linearFragmentSendList.release(copyPtr);
- }
- }
-
- if(c_segmentedFragmentSendList.isEmpty() &&
- c_linearFragmentSendList.isEmpty()){
- ljam();
- c_fragSenderRunning = false;
- return;
- }
-
- ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
- sig->line = __LINE__;
- sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
-}
-
-void
-SimulatedBlock::execNODE_START_REP(Signal* signal)
-{
-}
-
-void
-SimulatedBlock::execAPI_START_REP(Signal* signal)
-{
-}
-
-#ifdef VM_TRACE_TIME
-void
-SimulatedBlock::clearTimes() {
- for(Uint32 i = 0; i <= MAX_GSN; i++){
- m_timeTrace[i].cnt = 0;
- m_timeTrace[i].sum = 0;
- m_timeTrace[i].sub = 0;
- }
-}
-
-void
-SimulatedBlock::printTimes(FILE * output){
- fprintf(output, "-- %s --\n", getBlockName(number()));
- Uint64 sum = 0;
- for(Uint32 i = 0; i <= MAX_GSN; i++){
- Uint32 n = m_timeTrace[i].cnt;
- if(n != 0){
- double dn = n;
-
- double avg = m_timeTrace[i].sum;
- double avg2 = avg - m_timeTrace[i].sub;
-
- avg /= dn;
- avg2 /= dn;
-
- fprintf(output,
- //name ; cnt ; loc ; acc
- "%s ; #%d ; %dus ; %dus ; %dms\n",
- getSignalName(i), n, (Uint32)avg, (Uint32)avg2,
- (Uint32)((m_timeTrace[i].sum - m_timeTrace[i].sub + 500)/ 1000));
-
- sum += (m_timeTrace[i].sum - m_timeTrace[i].sub);
- }
- }
- sum = (sum + 500)/ 1000;
- fprintf(output, "-- %s : %d --\n", getBlockName(number()), sum);
- fprintf(output, "\n");
- fflush(output);
-}
-
-#endif
-
-void release(SegmentedSectionPtr & ptr);
-
-SimulatedBlock::FragmentInfo::FragmentInfo(Uint32 fragId, Uint32 sender){
- m_fragmentId = fragId;
- m_senderRef = sender;
- m_sectionPtrI[0] = RNIL;
- m_sectionPtrI[1] = RNIL;
- m_sectionPtrI[2] = RNIL;
-}
-
-SimulatedBlock::FragmentSendInfo::FragmentSendInfo()
-{
-}
-
-bool
-SimulatedBlock::assembleFragments(Signal * signal){
- Uint32 sigLen = signal->length() - 1;
- Uint32 fragId = signal->theData[sigLen];
- Uint32 fragInfo = signal->header.m_fragmentInfo;
- Uint32 senderRef = signal->getSendersBlockRef();
-
- if(fragInfo == 0){
- return true;
- }
-
- const Uint32 secs = signal->header.m_noOfSections;
- const Uint32 * const secNos = &signal->theData[sigLen - secs];
-
- if(fragInfo == 1){
- /**
- * First in train
- */
- Ptr<FragmentInfo> fragPtr;
- if(!c_fragmentInfoHash.seize(fragPtr)){
- ndbrequire(false);
- return false;
- }
-
- new (fragPtr.p)FragmentInfo(fragId, senderRef);
- c_fragmentInfoHash.add(fragPtr);
-
- for(Uint32 i = 0; i<secs; i++){
- Uint32 sectionNo = secNos[i];
- ndbassert(sectionNo < 3);
- fragPtr.p->m_sectionPtrI[sectionNo] = signal->m_sectionPtr[i].i;
- }
-
- /**
- * Don't release allocated segments
- */
- signal->header.m_fragmentInfo = 0;
- signal->header.m_noOfSections = 0;
- return false;
- }
-
- FragmentInfo key(fragId, senderRef);
- Ptr<FragmentInfo> fragPtr;
- if(c_fragmentInfoHash.find(fragPtr, key)){
-
- /**
- * FragInfo == 2 or 3
- */
- Uint32 i;
- for(i = 0; i<secs; i++){
- Uint32 sectionNo = secNos[i];
- ndbassert(sectionNo < 3);
- Uint32 sectionPtrI = signal->m_sectionPtr[i].i;
- if(fragPtr.p->m_sectionPtrI[sectionNo] != RNIL){
- linkSegments(fragPtr.p->m_sectionPtrI[sectionNo], sectionPtrI);
- } else {
- fragPtr.p->m_sectionPtrI[sectionNo] = sectionPtrI;
- }
- }
-
- /**
- * fragInfo = 2
- */
- if(fragInfo == 2){
- signal->header.m_fragmentInfo = 0;
- signal->header.m_noOfSections = 0;
- return false;
- }
-
- /**
- * fragInfo = 3
- */
- for(i = 0; i<3; i++){
- Uint32 ptrI = fragPtr.p->m_sectionPtrI[i];
- if(ptrI != RNIL){
- signal->m_sectionPtr[i].i = ptrI;
- } else {
- break;
- }
- }
- signal->setLength(sigLen - i);
- signal->header.m_noOfSections = i;
- signal->header.m_fragmentInfo = 0;
- getSections(i, signal->m_sectionPtr);
-
- c_fragmentInfoHash.release(fragPtr);
- return true;
- }
-
- /**
- * Unable to find fragment
- */
- ndbrequire(false);
- return false;
-}
-
-bool
-SimulatedBlock::sendFirstFragment(FragmentSendInfo & info,
- NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Uint32 messageSize){
-
- info.m_sectionPtr[0].m_segmented.i = RNIL;
- info.m_sectionPtr[1].m_segmented.i = RNIL;
- info.m_sectionPtr[2].m_segmented.i = RNIL;
-
- Uint32 totalSize = 0;
- SectionSegment * p;
- switch(signal->header.m_noOfSections){
- case 3:
- p = signal->m_sectionPtr[2].p;
- info.m_sectionPtr[2].m_segmented.p = p;
- info.m_sectionPtr[2].m_segmented.i = signal->m_sectionPtr[2].i;
- totalSize += p->m_sz;
- case 2:
- p = signal->m_sectionPtr[1].p;
- info.m_sectionPtr[1].m_segmented.p = p;
- info.m_sectionPtr[1].m_segmented.i = signal->m_sectionPtr[1].i;
- totalSize += p->m_sz;
- case 1:
- p = signal->m_sectionPtr[0].p;
- info.m_sectionPtr[0].m_segmented.p = p;
- info.m_sectionPtr[0].m_segmented.i = signal->m_sectionPtr[0].i;
- totalSize += p->m_sz;
- }
-
- if(totalSize <= messageSize + SectionSegment::DataLength){
- /**
- * Send signal directly
- */
- sendSignal(rg, gsn, signal, length, jbuf);
- info.m_status = FragmentSendInfo::SendComplete;
- return true;
- }
-
- /**
- * Consume sections
- */
- signal->header.m_noOfSections = 0;
-
- /**
- * Setup info object
- */
- info.m_status = FragmentSendInfo::SendNotComplete;
- info.m_prio = (Uint8)jbuf;
- info.m_gsn = gsn;
- info.m_fragInfo = 1;
- info.m_messageSize = messageSize;
- info.m_fragmentId = c_fragmentIdCounter++;
- info.m_nodeReceiverGroup = rg;
- info.m_callback.m_callbackFunction = 0;
-
- Ptr<SectionSegment> tmp;
- if(!import(tmp, &signal->theData[0], length)){
- ndbrequire(false);
- return false;
- }
- info.m_theDataSection.p = &tmp.p->theData[0];
- info.m_theDataSection.sz = length;
- tmp.p->theData[length] = tmp.i;
-
- sendNextSegmentedFragment(signal, info);
-
- if(c_fragmentIdCounter == 0){
- /**
- * Fragment id 0 is invalid
- */
- c_fragmentIdCounter = 1;
- }
-
- return true;
-}
-
-#if 0
-#define lsout(x) x
-#else
-#define lsout(x)
-#endif
-
-void
-SimulatedBlock::sendNextSegmentedFragment(Signal* signal,
- FragmentSendInfo & info){
-
- /**
- * Store "theData"
- */
- const Uint32 sigLen = info.m_theDataSection.sz;
- memcpy(&signal->theData[0], info.m_theDataSection.p, 4 * sigLen);
-
- Uint32 sz = 0;
- Uint32 maxSz = info.m_messageSize;
-
- Int32 secNo = 2;
- Uint32 secCount = 0;
- Uint32 * secNos = &signal->theData[sigLen];
-
- enum { Unknown = 0, Full = 1 } loop = Unknown;
- for(; secNo >= 0 && secCount < 3; secNo--){
- Uint32 ptrI = info.m_sectionPtr[secNo].m_segmented.i;
- if(ptrI == RNIL)
- continue;
-
- info.m_sectionPtr[secNo].m_segmented.i = RNIL;
-
- SectionSegment * ptrP = info.m_sectionPtr[secNo].m_segmented.p;
- const Uint32 size = ptrP->m_sz;
-
- signal->m_sectionPtr[secCount].i = ptrI;
- signal->m_sectionPtr[secCount].p = ptrP;
- signal->m_sectionPtr[secCount].sz = size;
- secNos[secCount] = secNo;
- secCount++;
-
- const Uint32 sizeLeft = maxSz - sz;
- if(size <= sizeLeft){
- /**
- * The section fits
- */
- sz += size;
- lsout(ndbout_c("section %d saved as %d", secNo, secCount-1));
- continue;
- }
-
- const Uint32 overflow = size - sizeLeft; // > 0
- if(overflow <= SectionSegment::DataLength){
- /**
- * Only one segment left to send
- * send even if sizeLeft <= size
- */
- lsout(ndbout_c("section %d saved as %d but full over: %d",
- secNo, secCount-1, overflow));
- secNo--;
- break;
- }
-
- // size >= 61
- if(sizeLeft < SectionSegment::DataLength){
- /**
- * Less than one segment left (space)
- * dont bother sending
- */
- secCount--;
- info.m_sectionPtr[secNo].m_segmented.i = ptrI;
- loop = Full;
- lsout(ndbout_c("section %d not saved", secNo));
- break;
- }
-
- /**
- * Split list
- * 1) Find place to split
- * 2) Rewrite header (the part that will be sent)
- * 3) Write new header (for remaining part)
- * 4) Store new header on FragmentSendInfo - record
- */
- // size >= 61 && sizeLeft >= 60
- Uint32 sum = SectionSegment::DataLength;
- Uint32 prevPtrI = ptrI;
- ptrI = ptrP->m_nextSegment;
- const Uint32 fill = sizeLeft - SectionSegment::DataLength;
- while(sum < fill){
- prevPtrI = ptrI;
- ptrP = g_sectionSegmentPool.getPtr(ptrI);
- ptrI = ptrP->m_nextSegment;
- sum += SectionSegment::DataLength;
- }
-
- /**
- * Rewrite header w.r.t size and last
- */
- Uint32 prev = secCount - 1;
- const Uint32 last = signal->m_sectionPtr[prev].p->m_lastSegment;
- signal->m_sectionPtr[prev].p->m_lastSegment = prevPtrI;
- signal->m_sectionPtr[prev].p->m_sz = sum;
- signal->m_sectionPtr[prev].sz = sum;
-
- /**
- * Write "new" list header
- */
- ptrP = g_sectionSegmentPool.getPtr(ptrI);
- ptrP->m_lastSegment = last;
- ptrP->m_sz = size - sum;
-
- /**
- * And store it on info-record
- */
- info.m_sectionPtr[secNo].m_segmented.i = ptrI;
- info.m_sectionPtr[secNo].m_segmented.p = ptrP;
-
- loop = Full;
- lsout(ndbout_c("section %d split into %d", secNo, prev));
- break;
- }
-
- lsout(ndbout_c("loop: %d secNo: %d secCount: %d sz: %d",
- loop, secNo, secCount, sz));
-
- /**
- * Store fragment id
- */
- secNos[secCount] = info.m_fragmentId;
-
- Uint32 fragInfo = info.m_fragInfo;
- info.m_fragInfo = 2;
- switch(loop){
- case Unknown:
- if(secNo >= 0){
- lsout(ndbout_c("Unknown - Full"));
- /**
- * Not finished
- */
- break;
- }
- // Fall through
- lsout(ndbout_c("Unknown - Done"));
- info.m_status = FragmentSendInfo::SendComplete;
- ndbassert(fragInfo == 2);
- fragInfo = 3;
- case Full:
- break;
- }
-
- signal->header.m_fragmentInfo = fragInfo;
- signal->header.m_noOfSections = secCount;
-
- sendSignal(info.m_nodeReceiverGroup,
- info.m_gsn,
- signal,
- sigLen + secCount + 1,
- (JobBufferLevel)info.m_prio);
-
- if(fragInfo == 3){
- /**
- * This is the last signal
- */
- g_sectionSegmentPool.release(info.m_theDataSection.p[sigLen]);
- }
-}
-
-bool
-SimulatedBlock::sendFirstFragment(FragmentSendInfo & info,
- NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections,
- Uint32 messageSize){
-
- ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
- signal->header.m_noOfSections = 0;
-
- info.m_sectionPtr[0].m_linear.p = NULL;
- info.m_sectionPtr[1].m_linear.p = NULL;
- info.m_sectionPtr[2].m_linear.p = NULL;
-
- Uint32 totalSize = 0;
- switch(noOfSections){
- case 3:
- info.m_sectionPtr[2].m_linear = ptr[2];
- totalSize += ptr[2].sz;
- case 2:
- info.m_sectionPtr[1].m_linear = ptr[1];
- totalSize += ptr[1].sz;
- case 1:
- info.m_sectionPtr[0].m_linear = ptr[0];
- totalSize += ptr[0].sz;
- }
-
- if(totalSize <= messageSize + SectionSegment::DataLength){
- /**
- * Send signal directly
- */
- sendSignal(rg, gsn, signal, length, jbuf, ptr, noOfSections);
- info.m_status = FragmentSendInfo::SendComplete;
-
- /**
- * Indicate to sendLinearSignalFragment
- * that we'r already done
- */
- return true;
- }
-
- /**
- * Setup info object
- */
- info.m_status = FragmentSendInfo::SendNotComplete;
- info.m_prio = (Uint8)jbuf;
- info.m_gsn = gsn;
- info.m_messageSize = messageSize;
- info.m_fragInfo = 1;
- info.m_fragmentId = c_fragmentIdCounter++;
- info.m_nodeReceiverGroup = rg;
- info.m_callback.m_callbackFunction = 0;
-
- Ptr<SectionSegment> tmp;
- if(!import(tmp, &signal->theData[0], length)){
- ndbrequire(false);
- return false;
- }
-
- info.m_theDataSection.p = &tmp.p->theData[0];
- info.m_theDataSection.sz = length;
- tmp.p->theData[length] = tmp.i;
-
- sendNextLinearFragment(signal, info);
-
- if(c_fragmentIdCounter == 0){
- /**
- * Fragment id 0 is invalid
- */
- c_fragmentIdCounter = 1;
- }
-
- return true;
-}
-
-void
-SimulatedBlock::sendNextLinearFragment(Signal* signal,
- FragmentSendInfo & info){
-
- /**
- * Store "theData"
- */
- const Uint32 sigLen = info.m_theDataSection.sz;
- memcpy(&signal->theData[0], info.m_theDataSection.p, 4 * sigLen);
-
- Uint32 sz = 0;
- Uint32 maxSz = info.m_messageSize;
-
- Int32 secNo = 2;
- Uint32 secCount = 0;
- Uint32 * secNos = &signal->theData[sigLen];
- LinearSectionPtr signalPtr[3];
-
- enum { Unknown = 0, Full = 2 } loop = Unknown;
- for(; secNo >= 0 && secCount < 3; secNo--){
- Uint32 * ptrP = info.m_sectionPtr[secNo].m_linear.p;
- if(ptrP == NULL)
- continue;
-
- info.m_sectionPtr[secNo].m_linear.p = NULL;
- const Uint32 size = info.m_sectionPtr[secNo].m_linear.sz;
-
- signalPtr[secCount].p = ptrP;
- signalPtr[secCount].sz = size;
- secNos[secCount] = secNo;
- secCount++;
-
- const Uint32 sizeLeft = maxSz - sz;
- if(size <= sizeLeft){
- /**
- * The section fits
- */
- sz += size;
- lsout(ndbout_c("section %d saved as %d", secNo, secCount-1));
- continue;
- }
-
- const Uint32 overflow = size - sizeLeft; // > 0
- if(overflow <= SectionSegment::DataLength){
- /**
- * Only one segment left to send
- * send even if sizeLeft <= size
- */
- lsout(ndbout_c("section %d saved as %d but full over: %d",
- secNo, secCount-1, overflow));
- secNo--;
- break;
- }
-
- // size >= 61
- if(sizeLeft < SectionSegment::DataLength){
- /**
- * Less than one segment left (space)
- * dont bother sending
- */
- secCount--;
- info.m_sectionPtr[secNo].m_linear.p = ptrP;
- loop = Full;
- lsout(ndbout_c("section %d not saved", secNo));
- break;
- }
-
- /**
- * Split list
- * 1) Find place to split
- * 2) Rewrite header (the part that will be sent)
- * 3) Write new header (for remaining part)
- * 4) Store new header on FragmentSendInfo - record
- */
- Uint32 sum = sizeLeft;
- sum /= SectionSegment::DataLength;
- sum *= SectionSegment::DataLength;
-
- /**
- * Rewrite header w.r.t size
- */
- Uint32 prev = secCount - 1;
- signalPtr[prev].sz = sum;
-
- /**
- * Write/store "new" header
- */
- info.m_sectionPtr[secNo].m_linear.p = ptrP + sum;
- info.m_sectionPtr[secNo].m_linear.sz = size - sum;
-
- loop = Full;
- lsout(ndbout_c("section %d split into %d", secNo, prev));
- break;
- }
-
- lsout(ndbout_c("loop: %d secNo: %d secCount: %d sz: %d",
- loop, secNo, secCount, sz));
-
- /**
- * Store fragment id
- */
- secNos[secCount] = info.m_fragmentId;
-
- Uint32 fragInfo = info.m_fragInfo;
- info.m_fragInfo = 2;
- switch(loop){
- case Unknown:
- if(secNo >= 0){
- lsout(ndbout_c("Unknown - Full"));
- /**
- * Not finished
- */
- break;
- }
- // Fall through
- lsout(ndbout_c("Unknown - Done"));
- info.m_status = FragmentSendInfo::SendComplete;
- ndbassert(fragInfo == 2);
- fragInfo = 3;
- case Full:
- break;
- }
-
- signal->header.m_noOfSections = 0;
- signal->header.m_fragmentInfo = fragInfo;
-
- sendSignal(info.m_nodeReceiverGroup,
- info.m_gsn,
- signal,
- sigLen + secCount + 1,
- (JobBufferLevel)info.m_prio,
- signalPtr,
- secCount);
-
- if(fragInfo == 3){
- /**
- * This is the last signal
- */
- g_sectionSegmentPool.release(info.m_theDataSection.p[sigLen]);
- }
-}
-
-void
-SimulatedBlock::sendFragmentedSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Callback & c,
- Uint32 messageSize){
- bool res = true;
- Ptr<FragmentSendInfo> ptr;
- res = c_segmentedFragmentSendList.seize(ptr);
- ndbrequire(res);
-
- res = sendFirstFragment(* ptr.p,
- NodeReceiverGroup(ref),
- gsn,
- signal,
- length,
- jbuf,
- messageSize);
- ndbrequire(res);
-
- if(ptr.p->m_status == FragmentSendInfo::SendComplete){
- c_segmentedFragmentSendList.release(ptr);
- if(c.m_callbackFunction != 0)
- execute(signal, c, 0);
- return;
- }
- ptr.p->m_callback = c;
-
- if(!c_fragSenderRunning){
- c_fragSenderRunning = true;
- ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
- sig->line = __LINE__;
- sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
- }
-}
-
-void
-SimulatedBlock::sendFragmentedSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Callback & c,
- Uint32 messageSize){
- bool res = true;
- Ptr<FragmentSendInfo> ptr;
- res = c_segmentedFragmentSendList.seize(ptr);
- ndbrequire(res);
-
- res = sendFirstFragment(* ptr.p,
- rg,
- gsn,
- signal,
- length,
- jbuf,
- messageSize);
- ndbrequire(res);
-
- if(ptr.p->m_status == FragmentSendInfo::SendComplete){
- c_segmentedFragmentSendList.release(ptr);
- if(c.m_callbackFunction != 0)
- execute(signal, c, 0);
- return;
- }
- ptr.p->m_callback = c;
-
- if(!c_fragSenderRunning){
- c_fragSenderRunning = true;
- ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
- sig->line = __LINE__;
- sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
- }
-}
-
-SimulatedBlock::Callback SimulatedBlock::TheEmptyCallback = {0, 0};
-void
-SimulatedBlock::TheNULLCallbackFunction(class Signal*, Uint32, Uint32)
-{ abort(); /* should never be called */ }
-SimulatedBlock::Callback SimulatedBlock::TheNULLCallback =
-{ &SimulatedBlock::TheNULLCallbackFunction, 0 };
-
-void
-SimulatedBlock::sendFragmentedSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections,
- Callback & c,
- Uint32 messageSize){
- bool res = true;
- Ptr<FragmentSendInfo> tmp;
- res = c_linearFragmentSendList.seize(tmp);
- ndbrequire(res);
-
- res = sendFirstFragment(* tmp.p,
- NodeReceiverGroup(ref),
- gsn,
- signal,
- length,
- jbuf,
- ptr,
- noOfSections,
- messageSize);
- ndbrequire(res);
-
- if(tmp.p->m_status == FragmentSendInfo::SendComplete){
- c_linearFragmentSendList.release(tmp);
- if(c.m_callbackFunction != 0)
- execute(signal, c, 0);
- return;
- }
- tmp.p->m_callback = c;
-
- if(!c_fragSenderRunning){
- c_fragSenderRunning = true;
- ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
- sig->line = __LINE__;
- sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
- }
-}
-
-void
-SimulatedBlock::sendFragmentedSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections,
- Callback & c,
- Uint32 messageSize){
- bool res = true;
- Ptr<FragmentSendInfo> tmp;
- res = c_linearFragmentSendList.seize(tmp);
- ndbrequire(res);
-
- res = sendFirstFragment(* tmp.p,
- rg,
- gsn,
- signal,
- length,
- jbuf,
- ptr,
- noOfSections,
- messageSize);
- ndbrequire(res);
-
- if(tmp.p->m_status == FragmentSendInfo::SendComplete){
- c_linearFragmentSendList.release(tmp);
- if(c.m_callbackFunction != 0)
- execute(signal, c, 0);
- return;
- }
- tmp.p->m_callback = c;
-
- if(!c_fragSenderRunning){
- c_fragSenderRunning = true;
- ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
- sig->line = __LINE__;
- sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
- }
-}
-
-NodeInfo &
-SimulatedBlock::setNodeInfo(NodeId nodeId) {
- ndbrequire(nodeId > 0 && nodeId < MAX_NODES);
- return globalData.m_nodeInfo[nodeId];
-}
-
-void
-SimulatedBlock::execUTIL_CREATE_LOCK_REF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_CREATE_LOCK_REF(signal);
-}
-
-void SimulatedBlock::execUTIL_CREATE_LOCK_CONF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_CREATE_LOCK_CONF(signal);
-}
-
-void SimulatedBlock::execUTIL_DESTORY_LOCK_REF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_DESTORY_LOCK_REF(signal);
-}
-
-void SimulatedBlock::execUTIL_DESTORY_LOCK_CONF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_DESTORY_LOCK_CONF(signal);
-}
-
-void SimulatedBlock::execUTIL_LOCK_REF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_LOCK_REF(signal);
-}
-
-void SimulatedBlock::execUTIL_LOCK_CONF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_LOCK_CONF(signal);
-}
-
-void SimulatedBlock::execUTIL_UNLOCK_REF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_UNLOCK_REF(signal);
-}
-
-void SimulatedBlock::execUTIL_UNLOCK_CONF(Signal* signal){
- ljamEntry();
- c_mutexMgr.execUTIL_UNLOCK_CONF(signal);
-}
-
-void
-SimulatedBlock::ignoreMutexUnlockCallback(Signal* signal,
- Uint32 ptrI, Uint32 retVal){
- c_mutexMgr.release(ptrI);
-}
-
-void
-UpgradeStartup::installEXEC(SimulatedBlock* block){
- SimulatedBlock::ExecFunction * a = block->theExecArray;
- switch(block->number()){
- case QMGR:
- a[UpgradeStartup::GSN_CM_APPCHG] = &SimulatedBlock::execUPGRADE;
- break;
- case CNTR:
- a[UpgradeStartup::GSN_CNTR_MASTERREF] = &SimulatedBlock::execUPGRADE;
- a[UpgradeStartup::GSN_CNTR_MASTERCONF] = &SimulatedBlock::execUPGRADE;
- break;
- }
-}
-
-void
-SimulatedBlock::execUPGRADE(Signal* signal){
- Uint32 gsn = signal->header.theVerId_signalNumber;
- switch(gsn){
- case UpgradeStartup::GSN_CM_APPCHG:
- UpgradeStartup::execCM_APPCHG(* this, signal);
- break;
- case UpgradeStartup::GSN_CNTR_MASTERREF:
- UpgradeStartup::execCNTR_MASTER_REPLY(* this, signal);
- break;
- case UpgradeStartup::GSN_CNTR_MASTERCONF:
- UpgradeStartup::execCNTR_MASTER_REPLY(* this, signal);
- break;
- }
-}
-
-void
-SimulatedBlock::fsRefError(Signal* signal, Uint32 line, const char *msg)
-{
- const FsRef *fsRef = (FsRef*)signal->getDataPtr();
- Uint32 errorCode = fsRef->errorCode;
- Uint32 osErrorCode = fsRef->osErrorCode;
- char msg2[100];
-
- sprintf(msg2, "%s: %s. OS errno: %u", getBlockName(number()), msg, osErrorCode);
-
- progError(line, errorCode, msg2);
-}
-
-void
-SimulatedBlock::execFSWRITEREF(Signal* signal)
-{
- fsRefError(signal, __LINE__, "File system write failed");
-}
-
-void
-SimulatedBlock::execFSREADREF(Signal* signal)
-{
- fsRefError(signal, __LINE__, "File system read failed");
-}
-
-void
-SimulatedBlock::execFSCLOSEREF(Signal* signal)
-{
- fsRefError(signal, __LINE__, "File system close failed");
-}
-
-void
-SimulatedBlock::execFSOPENREF(Signal* signal)
-{
- fsRefError(signal, __LINE__, "File system open failed");
-}
-
-void
-SimulatedBlock::execFSREMOVEREF(Signal* signal)
-{
- fsRefError(signal, __LINE__, "File system remove failed");
-}
-
-void
-SimulatedBlock::execFSSYNCREF(Signal* signal)
-{
- fsRefError(signal, __LINE__, "File system sync failed");
-}
-
-void
-SimulatedBlock::execFSAPPENDREF(Signal* signal)
-{
- fsRefError(signal, __LINE__, "File system append failed");
-}
-
-#ifdef VM_TRACE
-void
-SimulatedBlock::clear_global_variables(){
- Ptr<void> ** tmp = m_global_variables;
- while(* tmp != 0){
- (* tmp)->i = RNIL;
- (* tmp)->p = 0;
- tmp++;
- }
-}
-
-void
-SimulatedBlock::init_globals_list(void ** tmp, size_t cnt){
- m_global_variables = new Ptr<void> * [cnt+1];
- for(size_t i = 0; i<cnt; i++){
- m_global_variables[i] = (Ptr<void>*)tmp[i];
- }
- m_global_variables[cnt] = 0;
-}
-
-#endif
-
-#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;
- }
-
- if (0)
- {
- for(Uint32 i = 0; i<dstPos; i++)
- {
- printf("%.8x ", dst[i]);
- }
- printf("\n");
- }
- return dstPos;
-}
-
-Uint32
-SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
- const Uint32* src, Uint32 & srcPos,
- Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const
-{
- Uint32 array =
- AttributeDescriptor::getArrayType(attrDesc);
- Uint32 srcBytes =
- AttributeDescriptor::getSizeInBytes(attrDesc);
-
- Uint32 srcWords = ~0;
- Uint32 dstWords = ~0;
- uchar* dstPtr = (uchar*)&dst[dstPos];
- const uchar* srcPtr = (const uchar*)&src[srcPos];
-
- if (cs == NULL)
- {
- jam();
- Uint32 len;
- LINT_INIT(len);
- switch(array){
- case NDB_ARRAYTYPE_SHORT_VAR:
- len = 1 + srcPtr[0];
- break;
- case NDB_ARRAYTYPE_MEDIUM_VAR:
- len = 2 + srcPtr[0] + (srcPtr[1] << 8);
- break;
-#ifndef VM_TRACE
- default:
-#endif
- case NDB_ARRAYTYPE_FIXED:
- len = srcBytes;
- }
- srcWords = (len + 3) >> 2;
- dstWords = srcWords;
- memcpy(dstPtr, srcPtr, dstWords << 2);
-
- if (0)
- {
- ndbout_c("srcPos: %d dstPos: %d len: %d srcWords: %d dstWords: %d",
- srcPos, dstPos, len, srcWords, dstWords);
-
- for(Uint32 i = 0; i<srcWords; i++)
- printf("%.8x ", src[srcPos + i]);
- printf("\n");
- }
- }
- 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);
- srcWords = (lb + len + 3) >> 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);
- ndbrequire(AttributeDescriptor::getArrayType(attr) == NDB_ARRAYTYPE_FIXED);
- if(AttributeDescriptor::getDKey(attr))
- {
- noOfDistrKeys--;
- memmove(dst+dstPos, src, len << 2);
- dstPos += len;
- }
- src += len;
- i++;
- }
- }
- return dstPos;
-}
-
-CArray<KeyDescriptor> g_key_descriptor_pool;
-
diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp
deleted file mode 100644
index ebd07a5bb1a..00000000000
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ /dev/null
@@ -1,824 +0,0 @@
-/* Copyright (c) 2003-2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SIMULATEDBLOCK_H
-#define SIMULATEDBLOCK_H
-
-#include <NdbTick.h>
-#include <kernel_types.h>
-#include <util/version.h>
-#include <ndb_limits.h>
-
-#include "VMSignal.hpp"
-#include <RefConvert.hpp>
-#include <BlockNumbers.h>
-#include <GlobalSignalNumbers.h>
-
-#include "pc.hpp"
-#include "Pool.hpp"
-#include <NodeInfo.hpp>
-#include <NodeState.hpp>
-#include "GlobalData.hpp"
-#include "LongSignal.hpp"
-#include <SignalLoggerManager.hpp>
-
-#include <ErrorReporter.hpp>
-#include <ErrorHandlingMacros.hpp>
-
-#include "DLList.hpp"
-#include "ArrayPool.hpp"
-#include "DLHashTable.hpp"
-#include "WOPool.hpp"
-#include "RWPool.hpp"
-#include "Callback.hpp"
-#include "SafeCounter.hpp"
-
-#include <mgmapi.h>
-#include <mgmapi_config_parameters.h>
-#include <mgmapi_config_parameters_debug.h>
-#include <kernel_config_parameters.h>
-#include <Configuration.hpp>
-
-#include <signaldata/ReadConfig.hpp>
-#include <signaldata/UpgradeStartup.hpp>
-#include "ndbd_malloc_impl.hpp"
-#include <blocks/record_types.hpp>
-
-/**
- * Something for filesystem access
- */
-struct NewBaseAddrBits /* 32 bits */
-{
- unsigned int q : 4; /* Highest index - 2log */
- /* Strings are treated as 16 bit indexed */
- /* variables with the number of characters in */
- /* index 0, byte 0 */
- unsigned int v : 3; /* Size in bits - 2log */
- unsigned int unused : 25 ;
-};
-
-typedef struct NewVar
-{
- Uint32 * WA;
- Uint32 nrr;
- Uint32 ClusterSize; /* Real Cluster size */
- NewBaseAddrBits bits;
-} NewVARIABLE; /* 128 bits */
-
-struct Block_context
-{
- Block_context(class Configuration& cfg, class Ndbd_mem_manager& mm)
- : m_config(cfg), m_mm(mm) {}
- class Configuration& m_config;
- class Ndbd_mem_manager& m_mm;
-};
-
-class SimulatedBlock {
- friend class TraceLCP;
- friend class SafeCounter;
- friend class SafeCounterManager;
- friend struct UpgradeStartup;
- friend class AsyncFile;
- friend class Pgman;
- friend class Page_cache_client;
- friend class Lgman;
- friend class Logfile_client;
- friend struct Pool_context;
-public:
- friend class BlockComponent;
- virtual ~SimulatedBlock();
-
-protected:
- /**
- * Constructor
- */
- SimulatedBlock(BlockNumber blockNumber,
- struct Block_context & ctx);
-
- /**********************************************************
- * Handling of execFunctions
- */
- typedef void (SimulatedBlock::* ExecFunction)(Signal* signal);
- void addRecSignalImpl(GlobalSignalNumber g, ExecFunction fun, bool f =false);
- void installSimulatedBlockFunctions();
- ExecFunction theExecArray[MAX_GSN+1];
-public:
- /**
- *
- */
- inline void executeFunction(GlobalSignalNumber gsn, Signal* signal);
-public:
- typedef void (SimulatedBlock::* CallbackFunction)(class Signal*,
- Uint32 callbackData,
- Uint32 returnCode);
- struct Callback {
- CallbackFunction m_callbackFunction;
- Uint32 m_callbackData;
- };
-
- virtual const char* get_filename(Uint32 fd) const { return "";}
-protected:
- static Callback TheEmptyCallback;
- void TheNULLCallbackFunction(class Signal*, Uint32, Uint32);
- static Callback TheNULLCallback;
- void execute(Signal* signal, Callback & c, Uint32 returnCode);
-
-
- /**********************************************************
- * Send signal - dialects
- */
-
- void sendSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf ) const ;
-
- void sendSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf ) const ;
-
- void sendSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections) const ;
-
- void sendSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections) const ;
-
- // Send multiple signal with delay. In this VM the jobbufffer level has
- // no effect on on delayed signals
- //
- void sendSignalWithDelay(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 delayInMilliSeconds,
- Uint32 length) const ;
-
- void EXECUTE_DIRECT(Uint32 block,
- Uint32 gsn,
- Signal* signal,
- Uint32 len);
-
- class SectionSegmentPool& getSectionSegmentPool();
- void releaseSections(Signal* signal);
-
- /**********************************************************
- * Fragmented signals
- */
-
- /**
- * Assemble fragments
- *
- * @return true if all fragments has arrived
- * false otherwise
- */
- bool assembleFragments(Signal * signal);
-
- void sendFragmentedSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Callback & = TheEmptyCallback,
- Uint32 messageSize = 240);
-
- void sendFragmentedSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Callback & = TheEmptyCallback,
- Uint32 messageSize = 240);
-
- void sendFragmentedSignal(BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections,
- Callback &,
- Uint32 messageSize = 240);
-
- void sendFragmentedSignal(NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections,
- Callback &,
- Uint32 messageSize = 240);
-
- /**********************************************************
- * Fragmented signals structures
- */
-
- /**
- * Struct used when assembling fragmented long signals at receiver side
- */
- struct FragmentInfo {
- FragmentInfo(Uint32 fragId, Uint32 sender);
-
- Uint32 m_senderRef;
- Uint32 m_fragmentId;
- Uint32 m_sectionPtrI[3];
- union {
- Uint32 nextPool;
- Uint32 nextHash;
- };
- Uint32 prevHash;
-
- inline bool equal(FragmentInfo & p) const {
- return m_senderRef == p.m_senderRef && m_fragmentId == p.m_fragmentId;
- }
-
- inline Uint32 hashValue() const {
- return m_senderRef + m_fragmentId ;
- }
- }; // sizeof() = 32 bytes
-
- /**
- * Struct used when sending fragmented signals
- */
- struct FragmentSendInfo {
- FragmentSendInfo();
-
- enum Status {
- SendNotComplete = 0,
- SendComplete = 1
- };
- Uint8 m_status;
- Uint8 m_prio;
- Uint16 m_fragInfo;
- Uint16 m_gsn;
- Uint16 m_messageSize; // Size of each fragment
- Uint32 m_fragmentId;
- union {
- Ptr<struct SectionSegment> m_segmented;
- LinearSectionPtr m_linear;
- } m_sectionPtr[3];
- LinearSectionPtr m_theDataSection;
- NodeReceiverGroup m_nodeReceiverGroup; // 3
- Callback m_callback;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
-
- /**
- * setupFragmentSendInfo
- * Setup a struct to be used with sendSignalFragment
- * Used by sendFragmentedSignal
- */
- bool sendFirstFragment(FragmentSendInfo & info,
- NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections,
- Uint32 messageSize = 240);
-
- bool sendFirstFragment(FragmentSendInfo & info,
- NodeReceiverGroup rg,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- Uint32 messageSize = 240);
-
- /**
- * Send signal fragment
- *
- * @see sendFragmentedSignal
- */
- void sendNextSegmentedFragment(Signal* signal, FragmentSendInfo & info);
-
- /**
- * Send signal fragment
- *
- * @see sendFragmentedSignal
- */
- void sendNextLinearFragment(Signal* signal, FragmentSendInfo & info);
-
- BlockNumber number() const;
- BlockReference reference() const;
- NodeId getOwnNodeId() const;
-
- /**
- * Refresh Watch Dog in initialising code
- *
- */
- void refresh_watch_dog(Uint32 place = 1);
- void update_watch_dog_timer(Uint32 interval);
-
- /**
- * Prog error
- * This function should be called when this node should be shutdown
- * If the cause of the shutdown is known use extradata to add an
- * errormessage describing the problem
- */
- void progError(int line, int err_code, const char* extradata=NULL) const ;
-private:
- void signal_error(Uint32, Uint32, Uint32, const char*, int) const ;
- const NodeId theNodeId;
- const BlockNumber theNumber;
- const BlockReference theReference;
-
-protected:
- Block_context m_ctx;
- NewVARIABLE* allocateBat(int batSize);
- void freeBat();
- static const NewVARIABLE* getBat (BlockNumber blockNo);
- static Uint16 getBatSize(BlockNumber blockNo);
-
- static BlockReference calcTcBlockRef (NodeId aNode);
- static BlockReference calcLqhBlockRef (NodeId aNode);
- static BlockReference calcAccBlockRef (NodeId aNode);
- static BlockReference calcTupBlockRef (NodeId aNode);
- static BlockReference calcTuxBlockRef (NodeId aNode);
- static BlockReference calcDihBlockRef (NodeId aNode);
- static BlockReference calcQmgrBlockRef (NodeId aNode);
- static BlockReference calcDictBlockRef (NodeId aNode);
- static BlockReference calcNdbCntrBlockRef (NodeId aNode);
- static BlockReference calcTrixBlockRef (NodeId aNode);
- static BlockReference calcBackupBlockRef (NodeId aNode);
- static BlockReference calcSumaBlockRef (NodeId aNode);
-
- static BlockReference calcApiClusterMgrBlockRef (NodeId aNode);
-
- /**
- * allocRecord
- * Allocates memory for the datastructures where ndb keeps the data
- *
- */
- void* allocRecord(const char * type, size_t s, size_t n, bool clear = true, Uint32 paramId = 0);
- void* allocRecordAligned(const char * type, size_t s, size_t n, void **unaligned_buffer, Uint32 align = NDB_O_DIRECT_WRITE_ALIGNMENT, bool clear = true, Uint32 paramId = 0);
-
- /**
- * Deallocate record
- *
- * NOTE: Also resets pointer
- */
- void deallocRecord(void **, const char * type, size_t s, size_t n);
-
- /**
- * General info event (sent to cluster log)
- */
- void infoEvent(const char * msg, ...) const ;
- void warningEvent(const char * msg, ...) const ;
-
- /**
- * Get node state
- */
- const NodeState & getNodeState() const;
-
- /**
- * Get node info
- */
- const NodeInfo & getNodeInfo(NodeId nodeId) const;
- NodeInfo & setNodeInfo(NodeId);
-
- const NodeVersionInfo& getNodeVersionInfo() const;
- NodeVersionInfo& setNodeVersionInfo();
-
- /**********************
- * 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 */
- Uint16 theBATSize; /* # entries in BAT */
-
-protected:
- ArrayPool<GlobalPage>& m_global_page_pool;
- ArrayPool<GlobalPage>& m_shared_page_pool;
-
-private:
- /**
- * Node state
- */
- NodeState theNodeState;
- void execNDB_TAMPER(Signal * signal);
- void execNODE_STATE_REP(Signal* signal);
- void execCHANGE_NODE_STATE_REQ(Signal* signal);
-
- void execSIGNAL_DROPPED_REP(Signal* signal);
- void execCONTINUE_FRAGMENTED(Signal* signal);
- void execAPI_START_REP(Signal* signal);
- void execNODE_START_REP(Signal* signal);
-
- Uint32 c_fragmentIdCounter;
- ArrayPool<FragmentInfo> c_fragmentInfoPool;
- DLHashTable<FragmentInfo> c_fragmentInfoHash;
-
- bool c_fragSenderRunning;
- ArrayPool<FragmentSendInfo> c_fragmentSendPool;
- DLList<FragmentSendInfo> c_linearFragmentSendList;
- DLList<FragmentSendInfo> c_segmentedFragmentSendList;
-
-public:
- class MutexManager {
- friend class Mutex;
- friend class SimulatedBlock;
- friend class DbUtil;
- public:
- MutexManager(class SimulatedBlock &);
-
- bool setSize(Uint32 maxNoOfActiveMutexes);
- Uint32 getSize() const ; // Get maxNoOfActiveMutexes
-
- private:
- /**
- * core interface
- */
- struct ActiveMutex {
- Uint32 m_gsn; // state
- Uint32 m_mutexId;
- Uint32 m_mutexKey;
- Callback m_callback;
- union {
- Uint32 nextPool;
- Uint32 nextList;
- };
- Uint32 prevList;
- };
- typedef Ptr<ActiveMutex> ActiveMutexPtr;
-
- bool seize(ActiveMutexPtr& ptr);
- void release(Uint32 activeMutexPtrI);
-
- void getPtr(ActiveMutexPtr& ptr);
-
- void create(Signal*, ActiveMutexPtr&);
- void destroy(Signal*, ActiveMutexPtr&);
- void lock(Signal*, ActiveMutexPtr&);
- void trylock(Signal*, ActiveMutexPtr&);
- void unlock(Signal*, ActiveMutexPtr&);
-
- private:
- void execUTIL_CREATE_LOCK_REF(Signal* signal);
- void execUTIL_CREATE_LOCK_CONF(Signal* signal);
- void execUTIL_DESTORY_LOCK_REF(Signal* signal);
- void execUTIL_DESTORY_LOCK_CONF(Signal* signal);
- void execUTIL_LOCK_REF(Signal* signal);
- void execUTIL_LOCK_CONF(Signal* signal);
- void execUTIL_UNLOCK_REF(Signal* signal);
- void execUTIL_UNLOCK_CONF(Signal* signal);
-
- SimulatedBlock & m_block;
- ArrayPool<ActiveMutex> m_mutexPool;
- DLList<ActiveMutex> m_activeMutexes;
-
- BlockReference reference() const;
- void progError(int line, int err_code, const char* extra = 0);
- };
-
- friend class MutexManager;
- MutexManager c_mutexMgr;
-
- void ignoreMutexUnlockCallback(Signal* signal, Uint32 ptrI, Uint32 retVal);
-
- SafeCounterManager c_counterMgr;
-private:
- void execUTIL_CREATE_LOCK_REF(Signal* signal);
- void execUTIL_CREATE_LOCK_CONF(Signal* signal);
- void execUTIL_DESTORY_LOCK_REF(Signal* signal);
- void execUTIL_DESTORY_LOCK_CONF(Signal* signal);
- void execUTIL_LOCK_REF(Signal* signal);
- void execUTIL_LOCK_CONF(Signal* signal);
- void execUTIL_UNLOCK_REF(Signal* signal);
- void execUTIL_UNLOCK_CONF(Signal* signal);
-
-protected:
- void execUPGRADE(Signal* signal);
-
- void fsRefError(Signal* signal, Uint32 line, const char *msg);
- void execFSWRITEREF(Signal* signal);
- void execFSREADREF(Signal* signal);
- void execFSOPENREF(Signal* signal);
- void execFSCLOSEREF(Signal* signal);
- void execFSREMOVEREF(Signal* signal);
- void execFSSYNCREF(Signal* signal);
- void execFSAPPENDREF(Signal* signal);
-
- // Variable for storing inserted errors, see pc.H
- ERROR_INSERT_VARIABLE;
-
-#ifdef VM_TRACE_TIME
-public:
- void clearTimes();
- void printTimes(FILE * output);
- void addTime(Uint32 gsn, Uint64 time);
- void subTime(Uint32 gsn, Uint64 time);
- struct TimeTrace {
- Uint32 cnt;
- Uint64 sum, sub;
- } m_timeTrace[MAX_GSN+1];
- Uint32 m_currentGsn;
-#endif
-
-#ifdef VM_TRACE
- Ptr<void> **m_global_variables;
- void clear_global_variables();
- void init_globals_list(void ** tmp, size_t cnt);
-#endif
-};
-
-inline
-void
-SimulatedBlock::executeFunction(GlobalSignalNumber gsn, Signal* signal){
- ExecFunction f = theExecArray[gsn];
- if(gsn <= MAX_GSN && f != 0){
-#ifdef VM_TRACE
- clear_global_variables();
-#endif
- (this->*f)(signal);
- return;
- }
-
- /**
- * This point only passed if an error has occurred
- */
- char errorMsg[255];
- if (!(gsn <= MAX_GSN)) {
- BaseString::snprintf(errorMsg, 255, "Illegal signal received (GSN %d too high)", gsn);
- 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, NDBD_EXIT_PRGERR, errorMsg, errorMsg);
- }
- ndbrequire(false);
-}
-
-inline
-void
-SimulatedBlock::execute(Signal* signal, Callback & c, Uint32 returnCode){
- CallbackFunction fun = c.m_callbackFunction;
- if (fun == TheNULLCallback.m_callbackFunction)
- return;
- ndbrequire(fun != 0);
- c.m_callbackFunction = NULL;
- (this->*fun)(signal, c.m_callbackData, returnCode);
-}
-
-inline
-BlockNumber
-SimulatedBlock::number() const {
- return theNumber;
-}
-
-inline
-BlockReference
-SimulatedBlock::reference() const {
- return theReference;
-}
-
-inline
-NodeId
-SimulatedBlock::getOwnNodeId() const {
- return theNodeId;
-}
-
-inline
-BlockReference
-SimulatedBlock::calcTcBlockRef (NodeId aNodeId){
- return numberToRef(DBTC, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcLqhBlockRef (NodeId aNodeId){
-return numberToRef(DBLQH, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcAccBlockRef (NodeId aNodeId){
- return numberToRef(DBACC, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcTupBlockRef (NodeId aNodeId){
- return numberToRef(DBTUP, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcTuxBlockRef (NodeId aNodeId){
- return numberToRef(DBTUX, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcDihBlockRef (NodeId aNodeId){
- return numberToRef(DBDIH, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcDictBlockRef (NodeId aNodeId){
- return numberToRef(DBDICT, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcQmgrBlockRef (NodeId aNodeId){
- return numberToRef(QMGR, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcNdbCntrBlockRef (NodeId aNodeId){
- return numberToRef(NDBCNTR, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcTrixBlockRef (NodeId aNodeId){
- return numberToRef(TRIX, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcBackupBlockRef (NodeId aNodeId){
- return numberToRef(BACKUP, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcSumaBlockRef (NodeId aNodeId){
- return numberToRef(SUMA, aNodeId);
-}
-
-inline
-BlockReference
-SimulatedBlock::calcApiClusterMgrBlockRef (NodeId aNodeId){
- return numberToRef(API_CLUSTERMGR, aNodeId);
-}
-
-inline
-const NodeState &
-SimulatedBlock::getNodeState() const {
- return theNodeState;
-}
-
-inline
-const NodeInfo &
-SimulatedBlock::getNodeInfo(NodeId nodeId) const {
- ndbrequire(nodeId > 0 && nodeId < MAX_NODES);
- return globalData.m_nodeInfo[nodeId];
-}
-
-inline
-const NodeVersionInfo &
-SimulatedBlock::getNodeVersionInfo() const {
- return globalData.m_versionInfo;
-}
-
-inline
-NodeVersionInfo &
-SimulatedBlock::setNodeVersionInfo() {
- return globalData.m_versionInfo;
-}
-
-inline
-void
-SimulatedBlock::EXECUTE_DIRECT(Uint32 block,
- Uint32 gsn,
- Signal* signal,
- Uint32 len){
- signal->setLength(len);
-#ifdef VM_TRACE
- if(globalData.testOn){
- signal->header.theVerId_signalNumber = gsn;
- signal->header.theReceiversBlockNumber = block;
- signal->header.theSendersBlockRef = reference();
- globalSignalLoggers.executeDirect(signal->header,
- 0, // in
- &signal->theData[0],
- globalData.ownId);
- }
-#endif
- SimulatedBlock* b = globalData.getBlock(block);
-#ifdef VM_TRACE_TIME
- Uint32 us1, us2;
- Uint64 ms1, ms2;
- NdbTick_CurrentMicrosecond(&ms1, &us1);
- Uint32 tGsn = m_currentGsn;
- b->m_currentGsn = gsn;
-#endif
- b->executeFunction(gsn, signal);
-#ifdef VM_TRACE_TIME
- NdbTick_CurrentMicrosecond(&ms2, &us2);
- Uint64 diff = ms2;
- diff -= ms1;
- diff *= 1000000;
- diff += us2;
- diff -= us1;
- b->addTime(gsn, diff);
- m_currentGsn = tGsn;
- subTime(tGsn, diff);
-#endif
-#ifdef VM_TRACE
- if(globalData.testOn){
- signal->header.theVerId_signalNumber = gsn;
- signal->header.theReceiversBlockNumber = block;
- signal->header.theSendersBlockRef = reference();
- globalSignalLoggers.executeDirect(signal->header,
- 1, // out
- &signal->theData[0],
- globalData.ownId);
- }
-#endif
-}
-
-#ifdef VM_TRACE_TIME
-inline
-void
-SimulatedBlock::addTime(Uint32 gsn, Uint64 time){
- m_timeTrace[gsn].cnt ++;
- m_timeTrace[gsn].sum += time;
-}
-
-inline
-void
-SimulatedBlock::subTime(Uint32 gsn, Uint64 time){
- m_timeTrace[gsn].sub += time;
-}
-#endif
-
-/**
- * Defines for backward compatiblility
- */
-
-#define BLOCK_DEFINES(BLOCK) \
- typedef void (BLOCK::* ExecSignalLocal) (Signal* signal); \
- typedef void (BLOCK::* BlockCallback)(Signal*, Uint32 callb, Uint32 retCode); \
- inline CallbackFunction safe_cast(BlockCallback f){ \
- return static_cast<CallbackFunction>(f); \
- } \
-public:\
-private: \
- void addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force = false)
-
-#define BLOCK_CONSTRUCTOR(BLOCK)
-
-#define BLOCK_FUNCTIONS(BLOCK) \
-void \
-BLOCK::addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force){ \
- addRecSignalImpl(gsn, (ExecFunction)f, force);\
-}
-
-#include "Mutex.hpp"
-
-#endif
-
diff --git a/storage/ndb/src/kernel/vm/SuperPool.cpp b/storage/ndb/src/kernel/vm/SuperPool.cpp
deleted file mode 100644
index de391bcab42..00000000000
--- a/storage/ndb/src/kernel/vm/SuperPool.cpp
+++ /dev/null
@@ -1,750 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include "SuperPool.hpp"
-
-#define SP_ALIGN(sz, al) (((sz) + (al) - 1) & ~((al) - 1))
-
-// This is used for m_freeRecI when there is no record pool page.
-#define NNIL 0xffffffff
-
-// SuperPool
-
-SuperPool::SuperPool(Uint32 pageSize, Uint32 pageBits) :
- m_pageSize(pageSize),
- m_pageBits(pageBits),
- m_recBits(32 - m_pageBits),
- m_recMask((1 << m_recBits) - 1),
- m_memRoot(0),
- m_pageEnt(0),
- m_pageType(0),
- m_freeList(),
- m_initPages(0),
- m_incrPages(0),
- m_maxPages(0),
- m_totPages(0),
- m_typeCount(0),
- m_groupMinPct(0),
- m_groupMinPages(0),
- m_groupTotPages(0)
-{
- assert(m_pageSize != 0 && (m_pageSize & (m_pageSize - 1)) == 0);
- assert(m_pageBits <= 30);
-}
-
-SuperPool::~SuperPool()
-{
-}
-
-SuperPool::PageEnt::PageEnt() :
- m_pageType(0),
- m_useCount(0),
- m_freeRecI(NNIL),
- m_nextPageI(RNIL),
- m_prevPageI(RNIL)
-{
-}
-
-// page list routines
-
-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)
-{
- assert(pageI != RNIL);
-}
-
-void
-SuperPool::movePages(PageList& pl1, PageList& pl2)
-{
- PtrI pageI1 = pl1.m_tailPageI;
- PtrI pageI2 = pl2.m_headPageI;
- if (pl1.m_pageCount != 0) {
- assert(pageI1 != RNIL);
- if (pl2.m_pageCount != 0) {
- assert(pageI2 != RNIL);
- PageEnt& pe1 = getPageEnt(pageI1);
- PageEnt& pe2 = getPageEnt(pageI2);
- pe1.m_nextPageI = pageI2;
- pe2.m_prevPageI = pageI1;
- pl1.m_tailPageI = pl2.m_tailPageI;
- pl1.m_pageCount += pl2.m_pageCount;
- } else {
- assert(pageI2 == RNIL);
- }
- } else {
- assert(pageI1 == RNIL);
- pl1 = pl2;
- }
- pl2.m_headPageI = pl2.m_tailPageI = RNIL;
- pl2.m_pageCount = 0;
-}
-
-void
-SuperPool::addHeadPage(PageList& pl, PtrI pageI)
-{
- assert(pageI != RNIL);
- PageEnt& pe = getPageEnt(pageI);
- assert(pe.m_nextPageI == RNIL & pe.m_prevPageI == RNIL);
- PageList pl2(pageI);
- movePages(pl2, pl);
- pl = pl2;
-}
-
-void
-SuperPool::addTailPage(PageList& pl, PtrI pageI)
-{
- assert(pageI != RNIL);
- PageEnt& pe = getPageEnt(pageI);
- assert(pe.m_nextPageI == RNIL & pe.m_prevPageI == RNIL);
- PageList pl2(pageI);
- movePages(pl, pl2);
-}
-
-void
-SuperPool::removePage(PageList& pl, PtrI pageI)
-{
- assert(pageI != RNIL);
- PageEnt& pe = getPageEnt(pageI);
- if (pe.m_nextPageI != RNIL) {
- assert(pl.m_tailPageI != pageI);
- PageEnt& nextPe = getPageEnt(pe.m_nextPageI);
- nextPe.m_prevPageI = pe.m_prevPageI;
- } else {
- assert(pl.m_tailPageI == pageI);
- pl.m_tailPageI = pe.m_prevPageI;
- }
- if (pe.m_prevPageI != RNIL) {
- assert(pl.m_headPageI != pageI);
- PageEnt& prevPe = getPageEnt(pe.m_prevPageI);
- prevPe.m_nextPageI = pe.m_nextPageI;
- } else {
- assert(pl.m_headPageI == pageI);
- pl.m_headPageI = pe.m_nextPageI;
- }
- pe.m_nextPageI = RNIL;
- pe.m_prevPageI = RNIL;
- assert(pl.m_pageCount != 0);
- pl.m_pageCount--;
-}
-
-// reverse mapping
-
-SuperPool::PtrI
-SuperPool::getPageI(void* pageP)
-{
- Uint32 pageSize = m_pageSize;
- Uint32 pageBits = m_pageBits;
- Uint32 recBits = m_recBits;
- void* memRoot = m_memRoot;
- my_ptrdiff_t ipL = (Uint8*)pageP - (Uint8*)memRoot;
- assert(ipL % pageSize == 0);
- ipL /= (Int32)pageSize;
- Int32 ip = (Int32)ipL;
- Int32 lim = 1 << (pageBits - 1);
- if (! (ip == ipL && -lim <= ip && ip < lim && ip != -1)) {
- // page was too distant from memory root
- return RNIL;
- }
- PtrI pageI = ip << recBits;
- assert(pageP == getPageP(pageI));
- return pageI;
-}
-
-// record pool
-
-SuperPool::RecInfo::RecInfo(GroupPool& gp, Uint32 recSize) :
- m_groupPool(gp),
- m_recSize(recSize),
- m_recType(0),
- m_maxPerPage(0),
- m_freeRecI(NNIL),
- m_useCount(0),
- m_pageList(),
- m_hyX(1),
- m_hyY(2)
-{
- SuperPool& sp = gp.m_superPool;
- m_recType = (sp.m_typeCount++ << 1) | 1;
- assert(m_recSize == SP_ALIGN(m_recSize, sizeof(Uint32)));
- { // compute max records per page
- Uint32 n1 = sp.m_pageSize / m_recSize;
- Uint32 b2 = (sp.m_recBits < 16 ? sp.m_recBits : 16);
- Uint32 n2 = (1 << b2) - 1; // last is reserved
- m_maxPerPage = (n1 < n2 ? n1 : n2);
- assert(m_maxPerPage != 0);
- }
-}
-
-Uint32
-SuperPool::getFreeCount(RecInfo& ri, PtrI recI)
-{
- Uint32 n = 0;
- Uint32 recMask = m_recMask;
- Uint32 loopRecI = recI;
- while ((loopRecI & recMask) != recMask) {
- n++;
- void* loopRecP = getRecP(loopRecI, ri);
- loopRecI = *(Uint32*)loopRecP;
- }
- assert(n == (Uint16)n);
- return n;
-}
-
-Uint32
-SuperPool::getRecPageCount(RecInfo& ri)
-{
- Uint32 n = 0;
- for (Uint32 k = 0; k <= 2; k++)
- n += ri.m_pageList[k].m_pageCount;
- if (ri.m_freeRecI != NNIL)
- n += 1;
- return n;
-}
-
-Uint32
-SuperPool::getRecTotCount(RecInfo& ri)
-{
- return ri.m_maxPerPage * getRecPageCount(ri);
-}
-
-Uint32
-SuperPool::getRecUseCount(RecInfo& ri)
-{
- Uint32 n = ri.m_useCount;
- // current page does not keep count
- if (ri.m_freeRecI != NNIL) {
- Uint32 maxPerPage = ri.m_maxPerPage;
- Uint32 freeCount = getFreeCount(ri, ri.m_freeRecI);
- assert(maxPerPage >= freeCount);
- n += maxPerPage - freeCount;
- }
- return n;
-}
-
-// current page
-
-Uint32
-SuperPool::getRecPageList(RecInfo& ri, PageEnt& pe)
-{
- if (pe.m_useCount == 0)
- return 0;
- if (pe.m_useCount < ri.m_maxPerPage)
- return 1;
- if (pe.m_useCount == ri.m_maxPerPage)
- return 2;
- assert(false);
- return ~(Uint32)0;
-}
-
-void
-SuperPool::addCurrPage(RecInfo& ri, PtrI pageI)
-{
- PageEnt& pe = getPageEnt(pageI);
- ri.m_freeRecI = pe.m_freeRecI;
- // remove from right list
- Uint32 k = getRecPageList(ri, pe);
- assert(k != 2);
- removePage(ri.m_pageList[k], pageI);
- assert(ri.m_useCount >= pe.m_useCount);
- ri.m_useCount -= pe.m_useCount;
-}
-
-void
-SuperPool::removeCurrPage(RecInfo& ri)
-{
- Uint32 recMask = m_recMask;
- PtrI pageI = ri.m_freeRecI & ~ m_recMask;
- // update page entry
- PageEnt& pe = getPageEnt(pageI);
- pe.m_freeRecI = ri.m_freeRecI;
- Uint32 maxPerPage = ri.m_maxPerPage;
- Uint32 freeCount = getFreeCount(ri, pe.m_freeRecI);
- assert(maxPerPage >= freeCount);
- pe.m_useCount = maxPerPage - freeCount;
- // add to right list
- Uint32 k = getRecPageList(ri, pe);
- addHeadPage(ri.m_pageList[k], pageI);
- ri.m_useCount += pe.m_useCount;
- ri.m_freeRecI = NNIL;
- if (k == 0) {
- freeRecPages(ri);
- }
-}
-
-// page allocation
-
-bool
-SuperPool::getAvailPage(RecInfo& ri)
-{
- PtrI pageI;
- if ((pageI = ri.m_pageList[1].m_headPageI) != RNIL ||
- (pageI = ri.m_pageList[0].m_headPageI) != RNIL ||
- (pageI = getFreePage(ri)) != RNIL) {
- // the page is in record pool now
- if (ri.m_freeRecI != NNIL)
- removeCurrPage(ri);
- addCurrPage(ri, pageI);
- return true;
- }
- return false;
-}
-
-SuperPool::PtrI
-SuperPool::getFreePage(RecInfo& ri)
-{
- GroupPool& gp = ri.m_groupPool;
- PtrI pageI;
- if ((pageI = getFreePage(gp)) != RNIL) {
- initFreePage(ri, pageI);
- addHeadPage(ri.m_pageList[0], pageI);
- return pageI;
- }
- return RNIL;
-}
-
-SuperPool::PtrI
-SuperPool::getFreePage(GroupPool& gp)
-{
- PtrI pageI;
- if ((pageI = gp.m_freeList.m_headPageI) != RNIL) {
- removePage(gp.m_freeList, pageI);
- return pageI;
- }
- if (gp.m_totPages < getMaxPages(gp) &&
- (pageI = getFreePage()) != RNIL) {
- gp.m_totPages++;
- return pageI;
- }
- return RNIL;
-}
-
-SuperPool::PtrI
-SuperPool::getFreePage()
-{
- PtrI pageI;
- if ((pageI = m_freeList.m_headPageI) != RNIL) {
- removePage(m_freeList, pageI);
- return pageI;
- }
- if ((pageI = getNewPage()) != RNIL) {
- return pageI;
- }
- return RNIL;
-}
-
-void
-SuperPool::initFreePage(RecInfo& ri, PtrI pageI)
-{
- void* pageP = getPageP(pageI);
- // set up free record list
- Uint32 num = ri.m_maxPerPage;
- Uint32 recSize = ri.m_recSize;
- void* recP = (Uint8*)pageP;
- Uint32 irNext = 1;
- while (irNext < num) {
- *(Uint32*)recP = pageI | irNext;
- recP = (Uint8*)recP + recSize;
- irNext++;
- }
- // terminator has all recBits set
- *(Uint32*)recP = pageI | m_recMask;
- // 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 byte
- Uint32 ip = pageI >> m_recBits;
- m_pageType[ip] = (ri.m_recType & 0xFF);
-}
-
-// release
-
-void
-SuperPool::releaseNotCurrent(RecInfo& ri, PtrI recI)
-{
- PageEnt& pe = getPageEnt(recI);
- void* recP = getRecP(recI, ri);
- *(Uint32*)recP = pe.m_freeRecI;
- pe.m_freeRecI = recI;
- PtrI pageI = recI & ~ m_recMask;
- Uint32 maxPerPage = ri.m_maxPerPage;
- // move to right list
- Uint32 k1 = getRecPageList(ri, pe);
- assert(pe.m_useCount != 0);
- pe.m_useCount--;
- Uint32 k2 = getRecPageList(ri, pe);
- if (k1 != k2) {
- removePage(ri.m_pageList[k1], pageI);
- addHeadPage(ri.m_pageList[k2], pageI);
- if (k2 == 0) {
- freeRecPages(ri);
- }
- }
- assert(ri.m_useCount != 0);
- ri.m_useCount--;
-}
-
-void
-SuperPool::freeRecPages(RecInfo& ri)
-{
- // ignore current page
- Uint32 useCount = ri.m_useCount;
- Uint32 totCount = 0;
- for (uint32 k = 0; k <= 2; k++)
- totCount += ri.m_pageList[k].m_pageCount;
- totCount *= ri.m_maxPerPage;
- assert(totCount >= useCount);
- if ((totCount - useCount) * ri.m_hyY < useCount * ri.m_hyX)
- return;
- // free all free pages
- GroupPool& gp = ri.m_groupPool;
- Uint32 minPages = getMinPages(gp);
- PageList& pl = ri.m_pageList[0];
- while (pl.m_pageCount != 0) {
- PtrI pageI = pl.m_headPageI;
- removePage(pl, pageI);
- PageEnt& pe = getPageEnt(pageI);
- pe.m_pageType = 0;
- pe.m_freeRecI = NNIL;
- Uint32 ip = pageI >> m_recBits;
- m_pageType[ip] = 0;
- if (gp.m_totPages <= minPages) {
- addHeadPage(gp.m_freeList, pageI);
- } else {
- // return excess to super pool
- addHeadPage(m_freeList, pageI);
- assert(gp.m_totPages != 0);
- gp.m_totPages--;
- }
- }
-}
-
-void
-SuperPool::freeAllRecPages(RecInfo& ri, bool force)
-{
- GroupPool& gp = ri.m_groupPool;
- if (ri.m_freeRecI != NNIL)
- removeCurrPage(ri);
- assert(force || ri.m_useCount == 0);
- for (Uint32 k = 0; k <= 2; k++)
- movePages(gp.m_freeList, ri.m_pageList[k]);
-}
-
-// size parameters
-
-void
-SuperPool::setInitPages(Uint32 initPages)
-{
- m_initPages = initPages;
-}
-
-void
-SuperPool::setIncrPages(Uint32 incrPages)
-{
- m_incrPages = incrPages;
-}
-
-void
-SuperPool::setMaxPages(Uint32 maxPages)
-{
- m_maxPages = maxPages;
-}
-
-Uint32
-SuperPool::getGpMinPages()
-{
- Uint32 minPages = (m_groupMinPct * m_totPages) / 100;
- if (minPages < m_groupMinPages)
- minPages = m_groupMinPages;
- return minPages;
-}
-
-Uint32
-SuperPool::getMinPages(GroupPool& gp)
-{
- Uint32 minPages = (gp.m_minPct * m_totPages) / 100;
- if (minPages < gp.m_minPages)
- minPages = gp.m_minPages;
- return minPages;
-}
-
-Uint32
-SuperPool::getMaxPages(GroupPool& gp)
-{
- Uint32 n1 = getGpMinPages();
- Uint32 n2 = getMinPages(gp);
- assert(n1 >= n2);
- // pages reserved by other groups
- Uint32 n3 = n1 - n2;
- // rest can be claimed
- Uint32 n4 = (m_totPages >= n3 ? m_totPages - n3 : 0);
- return n4;
-}
-
-// debug
-
-void
-SuperPool::verify(RecInfo& ri)
-{
- GroupPool& gp = ri.m_groupPool;
- verifyPageList(m_freeList);
- verifyPageList(gp.m_freeList);
- for (Uint32 k = 0; k <= 2; k++) {
- PageList& pl = ri.m_pageList[k];
- verifyPageList(pl);
- PtrI pageI = pl.m_headPageI;
- while (pageI != RNIL) {
- PageEnt& pe = getPageEnt(pageI);
- assert(pe.m_pageType == ri.m_recType);
- Uint32 maxPerPage = ri.m_maxPerPage;
- Uint32 freeCount = getFreeCount(ri, pe.m_freeRecI);
- assert(maxPerPage >= freeCount);
- Uint32 useCount = maxPerPage - freeCount;
- assert(pe.m_useCount == useCount);
- assert(k != 0 || useCount == 0);
- assert(k != 1 || (useCount != 0 && freeCount != 0));
- assert(k != 2 || freeCount == 0);
- pageI = pe.m_nextPageI;
- }
- }
-}
-
-void
-SuperPool::verifyPageList(PageList& pl)
-{
- Uint32 count = 0;
- PtrI pageI = pl.m_headPageI;
- while (pageI != RNIL) {
- PageEnt& pe = getPageEnt(pageI);
- if (pe.m_prevPageI == RNIL) {
- assert(count == 0);
- } else {
- PageEnt& prevPe = getPageEnt(pe.m_prevPageI);
- assert(prevPe.m_nextPageI == pageI);
- }
- if (pe.m_nextPageI == RNIL) {
- assert(pl.m_tailPageI == pageI);
- } else {
- PageEnt& nextPe = getPageEnt(pe.m_nextPageI);
- assert(nextPe.m_prevPageI == pageI);
- }
- if (pe.m_pageType != 0) {
- assert(pe.m_freeRecI != NNIL);
- PageEnt& pe2 = getPageEnt(pe.m_freeRecI);
- assert(&pe == &pe2);
- } else {
- assert(pe.m_freeRecI == NNIL);
- }
- pageI = pe.m_nextPageI;
- count++;
- }
- assert(pl.m_pageCount == count);
-}
-
-// GroupPool
-
-GroupPool::GroupPool(SuperPool& sp) :
- m_superPool(sp),
- m_minPct(0),
- m_minPages(0),
- m_totPages(0),
- m_freeList()
-{
-}
-
-GroupPool::~GroupPool()
-{
-}
-
-void
-GroupPool::setMinPct(Uint32 minPct)
-{
- SuperPool& sp = m_superPool;
- // subtract any previous value
- assert(sp.m_groupMinPct >= m_minPct);
- sp.m_groupMinPct -= m_minPct;
- // add new value
- sp.m_groupMinPct += minPct;
- m_minPct = minPct;
-}
-
-void
-GroupPool::setMinPages(Uint32 minPages)
-{
- SuperPool& sp = m_superPool;
- // subtract any previous value
- assert(sp.m_groupMinPages >= m_minPages);
- sp.m_groupMinPages -= m_minPages;
- // add new value
- sp.m_groupMinPages += minPages;
- m_minPages = minPages;
-}
-
-// HeapPool
-
-HeapPool::HeapPool(Uint32 pageSize, Uint32 pageBits) :
- SuperPool(pageSize, pageBits),
- m_areaHead(),
- m_currArea(&m_areaHead),
- m_lastArea(&m_areaHead)
-{
-}
-
-HeapPool::~HeapPool()
-{
- free(m_pageEnt);
- free(m_pageType);
- 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_memory(0),
- m_pages(0),
- m_numPages(0)
-{
-}
-
-SuperPool::PtrI
-HeapPool::getNewPage()
-{
- Area* ap = m_currArea;
- if (ap->m_currPage == ap->m_numPages) {
- // area is used up
- if (ap->m_nextArea == 0) {
- if (! allocMemoryImpl())
- return RNIL;
- }
- ap = m_currArea = ap->m_nextArea;
- assert(ap != 0);
- }
- assert(ap->m_currPage < ap->m_numPages);
- PtrI pageI = ap->m_firstPageI;
- Uint32 recBits = m_recBits;
- Int32 ip = (Int32)pageI >> recBits;
- ip += ap->m_currPage;
- pageI = ip << recBits;
- ap->m_currPage++;
- return pageI;
-}
-
-bool
-HeapPool::allocInit()
-{
- Uint32 pageCount = (1 << m_pageBits);
- if (m_pageEnt == 0) {
- // allocate page entry array
- Uint32 bytes = pageCount * sizeof(PageEnt);
- m_pageEnt = static_cast<PageEnt*>(malloc(bytes));
- if (m_pageEnt == 0)
- return false;
- for (Uint32 i = 0; i < pageCount; i++)
- new (&m_pageEnt[i]) PageEnt();
- }
- if (m_pageType == 0) {
- // allocate type check array
- Uint32 bytes = pageCount;
- m_pageType = static_cast<Uint8*>(malloc(bytes));
- if (m_pageType == 0)
- return false;
- memset(m_pageType, 0, bytes);
- }
- return true;
-}
-
-bool
-HeapPool::allocArea(Area* ap, Uint32 tryPages)
-{
- Uint32 pageSize = m_pageSize;
- // one page is usually lost due to alignment
- Uint8* p1 = (Uint8*)malloc(pageSize * (tryPages + 1));
- if (p1 == 0)
- return false;
- // align
- UintPtr n1 = (UintPtr)p1;
- UintPtr n2 = SP_ALIGN(n1, (UintPtr)pageSize);
- Uint8* p2 = p1 + (n2 - n1);
- assert(p2 >= p1 && p2 - p1 < pageSize && (UintPtr)p2 % pageSize == 0);
- // set memory root to first allocated page
- if (m_memRoot == 0)
- m_memRoot = p2;
- // convert to i-value
- Uint32 pageI = getPageI(p2);
- ap->m_firstPageI = pageI;
- ap->m_currPage = 0;
- ap->m_memory = p1;
- ap->m_pages = p2;
- ap->m_numPages = tryPages + (p1 == p2);
- return true;
-}
-
-bool
-HeapPool::allocMemoryImpl()
-{
- if (! allocInit())
- return false;
- // compute number of additional pages needed
- if (m_maxPages <= m_totPages)
- return false;
- Uint32 needPages = (m_totPages == 0 ? m_initPages : m_incrPages);
- if (needPages > m_maxPages - m_totPages)
- needPages = m_maxPages - m_totPages;
- while (needPages != 0) {
- // add new area
- Area* ap = static_cast<Area*>(malloc(sizeof(Area)));
- if (ap == 0)
- return false;
- new (ap) Area();
- m_lastArea->m_nextArea = ap;
- m_lastArea = ap;
- // initial malloc is done in m_incrPages pieces
- Uint32 wantPages = needPages;
- if (m_incrPages != 0 && wantPages > m_incrPages)
- wantPages = m_incrPages;
- Uint32 tryPages = wantPages;
- while (tryPages != 0) {
- if (allocArea(ap, tryPages))
- break;
- tryPages /= 2;
- }
- if (tryPages == 0)
- return false;
- // update counts
- Uint32 numPages = ap->m_numPages;
- m_totPages += numPages;
- needPages = (needPages > numPages ? needPages - numPages : 0);
- }
- return true;
-}
diff --git a/storage/ndb/src/kernel/vm/SuperPool.hpp b/storage/ndb/src/kernel/vm/SuperPool.hpp
deleted file mode 100644
index 8fe4e681452..00000000000
--- a/storage/ndb/src/kernel/vm/SuperPool.hpp
+++ /dev/null
@@ -1,592 +0,0 @@
-/* Copyright (c) 2003, 2005, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef SUPER_POOL_HPP
-#define SUPER_POOL_HPP
-
-#include <ndb_global.h>
-
-#include <pc.hpp>
-#include <ErrorReporter.hpp>
-
-/*
- * SuperPool - super pool for record pools (abstract class)
- *
- * Documents: SuperPool GroupPool RecordPool<T>
- *
- * SUPER POOL
- *
- * 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 a number of record pools to allocate their memory. A special
- * case is a "page pool" where a record is a simple page whose size
- * divides super pool page size.
- *
- * 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")
- *
- * At most 16 recBits are used, the rest are zero.
- *
- * 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.
- *
- * One advantage of i-value is that it can be verified. The level of
- * verification can depend on compile options.
- *
- * - "v1" check i-value specifies valid page
- * - "v2" check record type matches page type, see below
- * - "v3" check record is in use
- * - "v4" check unused record is unmodified
- *
- * Another advantage of a 32-bit i-value is that it extends the space of
- * 32-bit addressable records on a 64-bit platform.
- *
- * 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 all 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.
- *
- * RESERVED I-VALUES
- *
- * RNIL is 0xffffff00 (signed -256). It is used everywhere in NDB as
- * "null pointer" i.e. as an i-value which does not point to a record.
- * In addition the signed values -255 to -1 are reserved for use by the
- * application.
- *
- * An i-value with all "ir" bits set is used as terminator in free
- * record list. Unlike RNIL, it still has valid page bits "ip".
- *
- * Following restrictions avoid hitting the reserved values:
- *
- * - pageBits is <= 30
- * - the maximum "ip" value 2^pageBits-1 (signed -1) is not used
- * - the maximum "ir" value 2^recBits-1 is not used
- *
- * 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 for page pools in
- * NDB. For now the implementation provides an array of page entries
- * with place for all potential (2^pageBits) entries.
- *
- * PAGE TYPE
- *
- * Page type is 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 ("v2") 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 page
- * type array. It truncates type to one non-zero byte.
- *
- * GROUP POOL
- *
- * Each record pool belongs to a group. The group specifies minimum
- * size or memory percentage the group must be able to allocate. The
- * sum of the minimum sizes of group pools is normally smaller than
- * super pool size. This provides unclaimed memory which a group can
- * use temporarily to allocate more than its minimum.
- *
- * The record pools within a group compete freely for the available
- * memory within the group.
- *
- * Typical exmaple is group of all metadata pools. The group allows
- * specifying the memory to reserve for metadata, without having to
- * specify number of tables, attributes, indexes, triggers, etc.
- *
- * PAGE LISTS
- *
- * Super pool has free page list. Each group pool uses it to allocate
- * its own free page list. And each record pool within the group uses
- * the group's free list to allocate its pages.
- *
- * A page allocated to a record pool has a use count i.e. number of used
- * records. When use count drops to zero the page can be returned to
- * the group. This is not necessarily done at once.
- *
- * The list of free records in a record pool 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 (all free, available, could be returned to group)
- * - busy page (some free, some used, available)
- * - full page (none free)
- * - current page (list of one), 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 via a group pool. 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 entry.
- * For seize (and release) there is a small optimization.
- *
- * The "current page" is the page of latest seize. It is unlinked from
- * its normal list and the free record pointer is stored under record
- * pool instance.
- *
- * The page remains current until there is a seize and the page is full.
- * Then the real page entry and its list membership are updated, and
- * a new page is made current.
- *
- * This implies that each (active) record pool allocates at least one
- * page which is never returned to the group.
- *
- * PAGE POLICY
- *
- * A group pool returns its "excess" (above minimum) free pages to the
- * super pool immediately.
- *
- * Allocating a new page to a record pool is expensive due to free list
- * setup. Therefore a record pool should not always return empty pages
- * to the group. Policies:
- *
- * - "pp1" never return empty page to the group
- * - "pp2" always return empty (non-current) page to the group
- * - "pp3" simple hysteresis
- *
- * Last one "pp3" is used. It works as follows:
- *
- * When a page becomes free, check if number of free records exceeds
- * some fixed fraction of all records. If it does, move all free pages
- * to the group. Current page is ignored in the check.
- *
- * TODO
- *
- * Define abstract class SuperAlloc. Make SuperPool a concrete class
- * with SuperAlloc instance in ctor. Replace HeapPool by HeapAlloc.
- */
-
-// Types forward.
-class GroupPool;
-
-class SuperPool {
-public:
- // Type of i-value, used to reference both pages and records.
- typedef Uint32 PtrI;
-
- // Page entry.
- struct PageEnt {
- PageEnt();
- Uint16 m_pageType; // zero if not in record pool
- Uint16 m_useCount; // used records on the page
- PtrI m_freeRecI; // first free record on the page
- PtrI m_nextPageI;
- PtrI m_prevPageI;
- };
-
- // Doubly-linked list of page entries.
- struct PageList {
- PageList();
- PageList(PtrI pageI);
- PtrI m_headPageI;
- PtrI m_tailPageI;
- Uint32 m_pageCount;
- };
-
- // Constructor. Gives page size in bytes (must be power of 2) and
- // number of bits to use for page index "ip" in i-value.
- SuperPool(Uint32 pageSize, Uint32 pageBits);
-
- // Destructor.
- virtual ~SuperPool() = 0;
-
- // 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);
-
- // Translate i-value ("ri" ignored) to page entry.
- PageEnt& getPageEnt(PtrI pageI);
-
- // Translate i-value ("ri" ignored) to page address.
- void* getPageP(PtrI pageI);
-
- // Translate page address to i-value. Address must be page-aligned to
- // memory root. Returns RNIL if "ip" range exceeded.
- PtrI getPageI(void* pageP);
-
- // Record pool info.
- struct RecInfo {
- RecInfo(GroupPool& gp, Uint32 recSize);
- GroupPool& m_groupPool;
- Uint32 m_recSize;
- Uint16 m_recType;
- Uint16 m_maxPerPage;
- PtrI m_freeRecI; // first free record on current page
- Uint32 m_useCount; // used records excluding current page
- PageList m_pageList[3]; // 0-free 1-busy 2-full
- Uint16 m_hyX; // hysteresis fraction x/y in "pp3"
- Uint16 m_hyY;
- };
-
- // Translate i-value to record address.
- void* getRecP(PtrI recI, RecInfo& ri);
-
- // Count records on page free list.
- Uint32 getFreeCount(RecInfo& ri, PtrI freeRecPtrI);
-
- // Compute total number of pages in pool.
- Uint32 getRecPageCount(RecInfo& ri);
-
- // Compute total number of records (used or not) in pool.
- Uint32 getRecTotCount(RecInfo& ri);
-
- // Compute total number of used records in pool.
- Uint32 getRecUseCount(RecInfo& ri);
-
- // Compute record pool page list index (0,1,2).
- Uint32 getRecPageList(RecInfo& ri, PageEnt& pe);
-
- // Add current page.
- void addCurrPage(RecInfo& ri, PtrI pageI);
-
- // Remove current page.
- void removeCurrPage(RecInfo& ri);
-
- // Get page with some free records and make it current. Takes head of
- // used or free list, or else gets free page from group pool.
- bool getAvailPage(RecInfo& ri);
-
- // Get free page from group pool and add it to record pool free list.
- // This is an expensive subroutine of getAvailPage(RecInfo&):
- PtrI getFreePage(RecInfo& ri);
-
- // Get free detached (not on list) page from group pool.
- PtrI getFreePage(GroupPool& gp);
-
- // Get free detached page from super pool.
- PtrI getFreePage();
-
- // Get new free detached page from the implementation.
- virtual PtrI getNewPage() = 0;
-
- // Initialize free list etc. Subroutine of getFreePage(RecInfo&).
- void initFreePage(RecInfo& ri, PtrI pageI);
-
- // Release record which is not on current page.
- void releaseNotCurrent(RecInfo& ri, PtrI recI);
-
- // Free pages from record pool according to page policy.
- void freeRecPages(RecInfo& ri);
-
- // Free all pages in record pool.
- void freeAllRecPages(RecInfo& ri, bool force);
-
- // Set pool size parameters in pages. Call allocMemory() for changes
- // (such as extra mallocs) to take effect.
- void setInitPages(Uint32 initPages);
- void setIncrPages(Uint32 incrPages);
- void setMaxPages(Uint32 maxPages);
-
- // Get number of pages reserved by all groups.
- Uint32 getGpMinPages();
-
- // Get number of pages reserved to a group.
- Uint32 getMinPages(GroupPool& gp);
-
- // Get max number of pages a group can try to allocate.
- Uint32 getMaxPages(GroupPool& gp);
-
- // Allocate more memory according to current parameters. Returns
- // false if no new memory was allocated. Otherwise returns true,
- // even if the amount allocated was less than requested.
- virtual bool allocMemory() = 0;
-
- // Debugging.
- void verify(RecInfo& ri);
- void verifyPageList(PageList& pl);
-
- // Super pool parameters.
- const Uint32 m_pageSize;
- const Uint16 m_pageBits;
- const Uint16 m_recBits;
- const Uint32 m_recMask;
- // Implementation must set up these 3 pointers.
- void* m_memRoot;
- PageEnt* m_pageEnt;
- Uint8* m_pageType;
- // Free page list.
- PageList m_freeList;
- // Free pages and sizes.
- Uint32 m_initPages;
- Uint32 m_incrPages;
- Uint32 m_maxPages;
- Uint32 m_totPages;
- Uint32 m_typeCount;
- // Reserved and allocated by group pools.
- Uint32 m_groupMinPct;
- Uint32 m_groupMinPages;
- Uint32 m_groupTotPages;
-};
-
-inline SuperPool::PageEnt&
-SuperPool::getPageEnt(PtrI pageI)
-{
- Uint32 ip = pageI >> m_recBits;
- return m_pageEnt[ip];
-}
-
-inline void*
-SuperPool::getPageP(PtrI ptrI)
-{
- Int32 ip = (Int32)ptrI >> m_recBits;
- return (Uint8*)m_memRoot + ip * (my_ptrdiff_t)m_pageSize;
-}
-
-inline void*
-SuperPool::getRecP(PtrI ptrI, RecInfo& ri)
-{
- Uint32 ip = ptrI >> m_recBits;
- assert(m_pageType[ip] == (ri.m_recType & 0xFF));
- Uint32 ir = ptrI & m_recMask;
- return (Uint8*)getPageP(ptrI) + ir * ri.m_recSize;
-}
-
-/*
- * GroupPool - subset of a super pool pages (concrete class)
- */
-
-class GroupPool {
-public:
- // Types.
- typedef SuperPool::PageList PageList;
-
- // Constructor.
- GroupPool(SuperPool& sp);
-
- // Destructor.
- ~GroupPool();
-
- // Set minimum pct reserved in super pool.
- void setMinPct(Uint32 resPct);
-
- // Set minimum pages reserved in super pool.
- void setMinPages(Uint32 resPages);
-
- SuperPool& m_superPool;
- Uint32 m_minPct;
- Uint32 m_minPages;
- Uint32 m_totPages;
- PageList m_freeList;
-};
-
-/*
- * RecordPool - record pool using one super pool instance (template)
- */
-
-template <class T>
-class RecordPool {
-public:
- // Constructor.
- RecordPool(GroupPool& gp);
-
- // 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 group pool. The force flag is required if
- // there are any used records.
- void freeAllRecPages(bool force);
-
- SuperPool& m_superPool;
- SuperPool::RecInfo m_recInfo;
-};
-
-template <class T>
-inline
-RecordPool<T>::RecordPool(GroupPool& gp) :
- m_superPool(gp.m_superPool),
- m_recInfo(gp, sizeof(T))
-{
-}
-
-template <class T>
-inline
-RecordPool<T>::~RecordPool()
-{
- freeAllRecPages(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;
- Uint32 recMask = sp.m_recMask;
- // get current page
- if ((ri.m_freeRecI & recMask) != recMask ||
- sp.getAvailPage(ri)) {
- SuperPool::PtrI recI = ri.m_freeRecI;
- void* recP = sp.getRecP(recI, ri);
- ri.m_freeRecI = *(Uint32*)recP;
- ptr.i = recI;
- ptr.p = static_cast<T*>(recP);
- return true;
- }
- ptr.i = RNIL;
- ptr.p = 0;
- return false;
-}
-
-template <class T>
-inline void
-RecordPool<T>::release(Ptr<T>& ptr)
-{
- SuperPool& sp = m_superPool;
- SuperPool::RecInfo& ri = m_recInfo;
- SuperPool::PtrI recI = ptr.i;
- Uint32 recMask = sp.m_recMask;
- // check if current page
- if ((recI & ~recMask) == (ri.m_freeRecI & ~recMask)) {
- void* recP = sp.getRecP(recI, ri);
- *(Uint32*)recP = ri.m_freeRecI;
- ri.m_freeRecI = recI;
- } else {
- sp.releaseNotCurrent(ri, recI);
- }
- ptr.i = RNIL;
- ptr.p = 0;
-}
-
-template <class T>
-inline void
-RecordPool<T>::freeAllRecPages(bool force)
-{
- SuperPool& sp = m_superPool;
- sp.freeAllRecPages(m_recInfo, force);
-}
-
-/*
- * 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 the page-aligned
- * address from first page 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;
- void* m_memory; // from malloc
- void* m_pages; // page-aligned pages
- Uint32 m_numPages; // number of pages
- };
-
- // Constructor.
- HeapPool(Uint32 pageSize, Uint32 pageBits);
-
- // Destructor.
- virtual ~HeapPool();
-
- // Get new page from current area.
- virtual PtrI getNewPage();
-
- // Allocate fixed arrays.
- bool allocInit();
-
- // Allocate array of aligned pages.
- bool allocArea(Area* ap, Uint32 tryPages);
-
- // Allocate memory.
- virtual bool allocMemory() { return allocMemoryImpl();}
- bool allocMemoryImpl();
-
- // List of malloc areas.
- Area m_areaHead;
- Area* m_currArea;
- Area* m_lastArea;
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/ThreadConfig.cpp b/storage/ndb/src/kernel/vm/ThreadConfig.cpp
deleted file mode 100644
index e7cfa0e6492..00000000000
--- a/storage/ndb/src/kernel/vm/ThreadConfig.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "ThreadConfig.hpp"
-#include "Emulator.hpp"
-#include "GlobalData.hpp"
-#include "TimeQueue.hpp"
-#include "TransporterRegistry.hpp"
-#include "FastScheduler.hpp"
-#include "pc.hpp"
-
-#include <GlobalSignalNumbers.h>
-#include <BlockNumbers.h>
-
-#include <NdbSleep.h>
-#include <NdbTick.h>
-#include <NdbOut.hpp>
-
-#include <signaldata/StartOrd.hpp>
-
-ThreadConfig::ThreadConfig()
-{
-}
-
-ThreadConfig::~ThreadConfig()
-{
-}
-
-/**
- * For each millisecond that has passed since this function was last called:
- * Scan the job buffer and increment the internalMillisecCounter
- * with 1 to keep track of where we are
- */
-inline
-void
-ThreadConfig::scanTimeQueue()
-{
- unsigned int maxCounter;
- Uint64 currMilliSecond;
- maxCounter = 0;
- currMilliSecond = NdbTick_CurrentMillisecond();
- if (currMilliSecond < globalData.internalMillisecCounter) {
-//--------------------------------------------------------------------
-// This could occur around 2036 or if the operator decides to change
-// time backwards. We cannot know how long time has past since last
-// time and we make a best try with 0 milliseconds.
-//--------------------------------------------------------------------
-#ifdef VM_TRACE
- ndbout << "Time moved backwards with ";
- ndbout << (globalData.internalMillisecCounter - currMilliSecond);
- ndbout << " milliseconds" << endl;
-#endif
- globalData.internalMillisecCounter = currMilliSecond;
- }//if
- if (currMilliSecond > (globalData.internalMillisecCounter + 1500)) {
-//--------------------------------------------------------------------
-// Time has moved forward more than a second. Either it could happen
-// if operator changed the time or if the OS has misbehaved badly.
-// We set the new time to one second from the past.
-//--------------------------------------------------------------------
-#ifdef VM_TRACE
- ndbout << "Time moved forward with ";
- ndbout << (currMilliSecond - globalData.internalMillisecCounter);
- ndbout << " milliseconds" << endl;
-#endif
- globalData.internalMillisecCounter = currMilliSecond - 1000;
- }//if
- while (((currMilliSecond - globalData.internalMillisecCounter) > 0) &&
- (maxCounter < 20)){
- globalData.internalMillisecCounter++;
- maxCounter++;
- globalTimeQueue.scanTable();
- }//while
-}//ThreadConfig::scanTimeQueue()
-
-
-//--------------------------------------------------------------------
-// ipControlLoop -- The main loop of ndb.
-// Handles the scheduling of signal execution and input/output
-// One lap in the loop should take approximately 10 milli seconds
-// If the jobbuffer is empty and the laptime is less than 10 milliseconds
-// at the end of the loop
-// the TransporterRegistry is called in order to sleep on the IO ports
-// waiting for another incoming signal to wake us up.
-// The timeout value in this call is calculated as (10 ms - laptime)
-// This would make ndb use less cpu while improving response time.
-//--------------------------------------------------------------------
-void ThreadConfig::ipControlLoop()
-{
-
-//--------------------------------------------------------------------
-// initialise the counter that keeps track of the current millisecond
-//--------------------------------------------------------------------
- globalData.internalMillisecCounter = NdbTick_CurrentMillisecond();
- Uint32 i = 0;
- while (globalData.theRestartFlag != perform_stop) {
-
- Uint32 timeOutMillis = 0;
- if (LEVEL_IDLE == globalData.highestAvailablePrio) {
-//--------------------------------------------------------------------
-// The buffers are empty, we need to wait for a while until we continue.
-// We cannot wait forever since we can also have timed events.
-//--------------------------------------------------------------------
-//--------------------------------------------------------------------
-// Set the time we will sleep on the sockets before waking up
-// unconditionally to 10 ms. Will never sleep more than 10 milliseconds
-// on a socket.
-//--------------------------------------------------------------------
- timeOutMillis = 10;
- }//if
-//--------------------------------------------------------------------
-// Now it is time to check all interfaces. We will send all buffers
-// plus checking for any received messages.
-//--------------------------------------------------------------------
- if (i++ >= 20) {
- globalTransporterRegistry.update_connections();
- globalData.incrementWatchDogCounter(5);
- i = 0;
- }//if
-
- globalData.incrementWatchDogCounter(6);
- globalTransporterRegistry.performSend();
-
- globalData.incrementWatchDogCounter(7);
- if (globalTransporterRegistry.pollReceive(timeOutMillis)) {
- globalData.incrementWatchDogCounter(8);
- globalTransporterRegistry.performReceive();
- }
-
-//--------------------------------------------------------------------
-// We scan the time queue to see if there are any timed signals that
-// is now ready to be executed.
-//--------------------------------------------------------------------
- globalData.incrementWatchDogCounter(2);
- scanTimeQueue();
-
-//--------------------------------------------------------------------
-// This is where the actual execution of signals occur. We execute
-// until all buffers are empty or until we have executed 2048 signals.
-//--------------------------------------------------------------------
- globalScheduler.doJob();
- }//while
-
- globalData.incrementWatchDogCounter(6);
- globalTransporterRegistry.performSend();
-
-}//ThreadConfig::ipControlLoop()
-
-int
-ThreadConfig::doStart(NodeState::StartLevel startLevel){
-
- SignalHeader sh;
- memset(&sh, 0, sizeof(SignalHeader));
-
- sh.theVerId_signalNumber = GSN_START_ORD;
- sh.theReceiversBlockNumber = CMVMI;
- sh.theSendersBlockRef = 0;
- sh.theTrace = 0;
- sh.theSignalId = 0;
- sh.theLength = StartOrd::SignalLength;
-
- Uint32 theData[25];
- StartOrd * const startOrd = (StartOrd *)&theData[0];
- startOrd->restartInfo = 0;
-
- Uint32 secPtrI[3];
- globalScheduler.execute(&sh, JBA, theData, secPtrI);
- return 0;
-}
-
diff --git a/storage/ndb/src/kernel/vm/ThreadConfig.hpp b/storage/ndb/src/kernel/vm/ThreadConfig.hpp
deleted file mode 100644
index a05cc9c8532..00000000000
--- a/storage/ndb/src/kernel/vm/ThreadConfig.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef ThreadConfig_H
-#define ThreadConfig_H
-
-#include <kernel_types.h>
-#include <ErrorReporter.hpp>
-#include <NodeState.hpp>
-
-class IPCConfig;
-
-class ThreadConfig
-{
-public:
- ThreadConfig();
- ~ThreadConfig();
-
- void ipControlLoop();
-
- int doStart(NodeState::StartLevel startLevel);
-private:
-
- void scanTimeQueue();
-};
-#endif // ThreadConfig_H
diff --git a/storage/ndb/src/kernel/vm/TimeQueue.cpp b/storage/ndb/src/kernel/vm/TimeQueue.cpp
deleted file mode 100644
index ad4e4cd1b8a..00000000000
--- a/storage/ndb/src/kernel/vm/TimeQueue.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "TimeQueue.hpp"
-#include <ErrorHandlingMacros.hpp>
-#include <GlobalData.hpp>
-#include <FastScheduler.hpp>
-#include <VMSignal.hpp>
-
-static const int MAX_TIME_QUEUE_VALUE = 32000;
-
-TimeQueue::TimeQueue()
-{
- clear();
-}
-
-TimeQueue::~TimeQueue()
-{
-}
-
-void
-TimeQueue::clear()
-{
- globalData.theNextTimerJob = 65535;
- globalData.theCurrentTimer = 0;
- globalData.theShortTQIndex = 0;
- globalData.theLongTQIndex = 0;
- for (int i = 0; i < MAX_NO_OF_TQ; i++)
- theFreeIndex[i] = i+1;
- theFreeIndex[MAX_NO_OF_TQ - 1] = NULL_TQ_ENTRY;
- globalData.theFirstFreeTQIndex = 0;
-}
-
-void
-TimeQueue::insert(Signal* signal, BlockNumber bnr,
- GlobalSignalNumber gsn, Uint32 delayTime)
-{
- if (delayTime == 0)
- delayTime = 1;
- register Uint32 regCurrentTime = globalData.theCurrentTimer;
- register Uint32 i;
- register Uint32 regSave;
- register TimerEntry newEntry;
-
- newEntry.time_struct.delay_time = regCurrentTime + delayTime;
- newEntry.time_struct.job_index = getIndex();
- regSave = newEntry.copy_struct;
-
- globalScheduler.insertTimeQueue(signal, bnr, gsn,
- newEntry.time_struct.job_index);
-
- if (newEntry.time_struct.delay_time < globalData.theNextTimerJob)
- globalData.theNextTimerJob = newEntry.time_struct.delay_time;
- if (delayTime < 100){
- register Uint32 regShortIndex = globalData.theShortTQIndex;
- if (regShortIndex == 0){
- theShortQueue[0].copy_struct = newEntry.copy_struct;
- } else if (regShortIndex >= MAX_NO_OF_SHORT_TQ - 1) {
- ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_SHORT,
- "Too many in Short Time Queue", "TimeQueue.C" );
- } else {
- for (i = 0; i < regShortIndex; i++) {
- if (theShortQueue[i].time_struct.delay_time >
- newEntry.time_struct.delay_time) {
-
- regSave = theShortQueue[i].copy_struct;
- theShortQueue[i].copy_struct = newEntry.copy_struct;
- break;
- }
- }
- if (i == regShortIndex) {
- theShortQueue[regShortIndex].copy_struct = regSave;
- } else {
- for (i++; i < regShortIndex; i++) {
- register Uint32 regTmp = theShortQueue[i].copy_struct;
- theShortQueue[i].copy_struct = regSave;
- regSave = regTmp;
- }
- theShortQueue[regShortIndex].copy_struct = regSave;
- }
- }
- globalData.theShortTQIndex = regShortIndex + 1;
- } else if (delayTime <= (unsigned)MAX_TIME_QUEUE_VALUE) {
- register Uint32 regLongIndex = globalData.theLongTQIndex;
- if (regLongIndex == 0) {
- theLongQueue[0].copy_struct = newEntry.copy_struct;
- } else if (regLongIndex >= MAX_NO_OF_LONG_TQ - 1) {
- ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_LONG,
- "Too many in Long Time Queue", "TimeQueue.C" );
- } else {
- for (i = 0; i < regLongIndex; i++) {
- if (theLongQueue[i].time_struct.delay_time >
- newEntry.time_struct.delay_time) {
-
- regSave = theLongQueue[i].copy_struct;
- theLongQueue[i].copy_struct = newEntry.copy_struct;
- break;
- }
- }
- if (i == regLongIndex) {
- theLongQueue[regLongIndex].copy_struct = regSave;
- } else {
- for (i++; i < regLongIndex; i++) {
- register Uint32 regTmp = theLongQueue[i].copy_struct;
- theLongQueue[i].copy_struct = regSave;
- regSave = regTmp;
- }
- theLongQueue[regLongIndex].copy_struct = regSave;
- }
- }
- globalData.theLongTQIndex = regLongIndex + 1;
- } else {
- ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_DELAY,
- "Too long delay for Time Queue", "TimeQueue.C" );
- }
-}
-
-// executes the expired signals;
-void
-TimeQueue::scanTable()
-{
- register Uint32 i, j;
-
- globalData.theCurrentTimer++;
- if (globalData.theCurrentTimer == 32000)
- recount_timers();
- if (globalData.theNextTimerJob > globalData.theCurrentTimer)
- return;
- globalData.theNextTimerJob = 65535; // If no more timer jobs
- for (i = 0; i < globalData.theShortTQIndex; i++) {
- if (theShortQueue[i].time_struct.delay_time > globalData.theCurrentTimer){
- break;
- } else {
- releaseIndex((Uint32)theShortQueue[i].time_struct.job_index);
- globalScheduler.scheduleTimeQueue(theShortQueue[i].time_struct.job_index);
- }
- }
- if (i > 0) {
- for (j = i; j < globalData.theShortTQIndex; j++)
- theShortQueue[j - i].copy_struct = theShortQueue[j].copy_struct;
- globalData.theShortTQIndex -= i;
- }
- if (globalData.theShortTQIndex != 0) // If not empty
- globalData.theNextTimerJob = theShortQueue[0].time_struct.delay_time;
- for (i = 0; i < globalData.theLongTQIndex; i++) {
- if (theLongQueue[i].time_struct.delay_time > globalData.theCurrentTimer) {
- break;
- } else {
- releaseIndex((Uint32)theLongQueue[i].time_struct.job_index);
- globalScheduler.scheduleTimeQueue(theLongQueue[i].time_struct.job_index);
- }
- }
- if (i > 0) {
- for (j = i; j < globalData.theLongTQIndex; j++)
- theLongQueue[j - i].copy_struct = theLongQueue[j].copy_struct;
- globalData.theLongTQIndex -= i;
- }
- if (globalData.theLongTQIndex != 0) // If not empty
- if (globalData.theNextTimerJob > theLongQueue[0].time_struct.delay_time)
- globalData.theNextTimerJob = theLongQueue[0].time_struct.delay_time;
-}
-
-void
-TimeQueue::recount_timers()
-{
- Uint32 i;
-
- globalData.theCurrentTimer = 0;
- globalData.theNextTimerJob -= 32000;
-
- for (i = 0; i < globalData.theShortTQIndex; i++)
- theShortQueue[i].time_struct.delay_time -= 32000;
- for (i = 0; i < globalData.theLongTQIndex; i++)
- theLongQueue[i].time_struct.delay_time -= 32000;
-}
-
-Uint32
-TimeQueue::getIndex()
-{
- Uint32 retValue = globalData.theFirstFreeTQIndex;
- globalData.theFirstFreeTQIndex = (Uint32)theFreeIndex[retValue];
- if (retValue >= MAX_NO_OF_TQ)
- ERROR_SET(fatal, NDBD_EXIT_TIME_QUEUE_INDEX,
- "Index out of range", "TimeQueue.C" );
- return retValue;
-}
-
-void
-TimeQueue::releaseIndex(Uint32 aIndex)
-{
- theFreeIndex[aIndex] = globalData.theFirstFreeTQIndex;
- globalData.theFirstFreeTQIndex = aIndex;
-}
-
-
diff --git a/storage/ndb/src/kernel/vm/TimeQueue.hpp b/storage/ndb/src/kernel/vm/TimeQueue.hpp
deleted file mode 100644
index 4c1a32ac3e6..00000000000
--- a/storage/ndb/src/kernel/vm/TimeQueue.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef TimeQueue_H
-#define TimeQueue_H
-
-#include <kernel_types.h>
-#include "Prio.hpp"
-
-#define MAX_NO_OF_SHORT_TQ 512
-#define MAX_NO_OF_LONG_TQ 512
-#define MAX_NO_OF_TQ (MAX_NO_OF_SHORT_TQ + MAX_NO_OF_LONG_TQ)
-#define NULL_TQ_ENTRY 65535
-
-class Signal;
-
-struct TimeStruct
-{
- Uint16 delay_time;
- Uint16 job_index;
-};
-
-union TimerEntry
-{
- struct TimeStruct time_struct;
- Uint32 copy_struct;
-};
-
-class TimeQueue
-{
-public:
- TimeQueue();
- ~TimeQueue();
-
- void insert(Signal* signal, BlockNumber bnr,
- GlobalSignalNumber gsn, Uint32 delayTime);
- void clear();
- void scanTable(); // Called once per millisecond
- Uint32 getIndex();
- void releaseIndex(Uint32 aIndex);
- void recount_timers();
-
-private:
- TimerEntry theShortQueue[MAX_NO_OF_SHORT_TQ];
- TimerEntry theLongQueue[MAX_NO_OF_LONG_TQ];
- Uint16 theFreeIndex[MAX_NO_OF_TQ];
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/TransporterCallback.cpp b/storage/ndb/src/kernel/vm/TransporterCallback.cpp
deleted file mode 100644
index 979a8075bdd..00000000000
--- a/storage/ndb/src/kernel/vm/TransporterCallback.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/* Copyright (c) 2003-2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include <TransporterCallback.hpp>
-#include <TransporterRegistry.hpp>
-#include <FastScheduler.hpp>
-#include <Emulator.hpp>
-#include <ErrorHandlingMacros.hpp>
-
-#include "LongSignal.hpp"
-
-#include <signaldata/EventReport.hpp>
-#include <signaldata/TestOrd.hpp>
-#include <signaldata/SignalDroppedRep.hpp>
-#include <signaldata/DisconnectRep.hpp>
-
-#include "VMSignal.hpp"
-#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 &&
- connectionError[i].err != -1)
- i++;
- return connectionError[i].text;
-}
-
-bool
-import(Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len){
- /**
- * Dummy data used when setting prev.m_nextSegment for first segment of a
- * section
- */
- Uint32 dummyPrev[4];
-
- first.p = 0;
- if(g_sectionSegmentPool.seize(first)){
- ;
- } else {
- return false;
- }
-
- first.p->m_sz = len;
- first.p->m_ownerRef = 0;
-
- Ptr<SectionSegment> prevPtr = { (SectionSegment *)&dummyPrev[0], 0 };
- Ptr<SectionSegment> currPtr = first;
-
- while(len > SectionSegment::DataLength){
- prevPtr.p->m_nextSegment = currPtr.i;
- memcpy(&currPtr.p->theData[0], src, 4 * SectionSegment::DataLength);
- src += SectionSegment::DataLength;
- len -= SectionSegment::DataLength;
- prevPtr = currPtr;
- if(g_sectionSegmentPool.seize(currPtr)){
- ;
- } else {
- first.p->m_lastSegment = prevPtr.i;
- return false;
- }
- }
-
- first.p->m_lastSegment = currPtr.i;
- currPtr.p->m_nextSegment = RNIL;
- memcpy(&currPtr.p->theData[0], src, 4 * len);
- return true;
-}
-
-void
-linkSegments(Uint32 head, Uint32 tail){
-
- Ptr<SectionSegment> headPtr;
- g_sectionSegmentPool.getPtr(headPtr, head);
-
- Ptr<SectionSegment> tailPtr;
- g_sectionSegmentPool.getPtr(tailPtr, tail);
-
- Ptr<SectionSegment> oldTailPtr;
- g_sectionSegmentPool.getPtr(oldTailPtr, headPtr.p->m_lastSegment);
-
- headPtr.p->m_lastSegment = tailPtr.p->m_lastSegment;
- headPtr.p->m_sz += tailPtr.p->m_sz;
-
- oldTailPtr.p->m_nextSegment = tailPtr.i;
-}
-
-void
-copy(Uint32 * & insertPtr,
- class SectionSegmentPool & thePool, const SegmentedSectionPtr & _ptr){
-
- Uint32 len = _ptr.sz;
- SectionSegment * ptrP = _ptr.p;
-
- while(len > 60){
- memcpy(insertPtr, &ptrP->theData[0], 4 * 60);
- len -= 60;
- insertPtr += 60;
- ptrP = thePool.getPtr(ptrP->m_nextSegment);
- }
- memcpy(insertPtr, &ptrP->theData[0], 4 * len);
- insertPtr += len;
-}
-
-void
-copy(Uint32 * dst, SegmentedSectionPtr src){
- copy(dst, g_sectionSegmentPool, src);
-}
-
-void
-getSections(Uint32 secCount, SegmentedSectionPtr ptr[3]){
- Uint32 tSec0 = ptr[0].i;
- Uint32 tSec1 = ptr[1].i;
- Uint32 tSec2 = ptr[2].i;
- SectionSegment * p;
- switch(secCount){
- case 3:
- p = g_sectionSegmentPool.getPtr(tSec2);
- ptr[2].p = p;
- ptr[2].sz = p->m_sz;
- case 2:
- p = g_sectionSegmentPool.getPtr(tSec1);
- ptr[1].p = p;
- ptr[1].sz = p->m_sz;
- case 1:
- p = g_sectionSegmentPool.getPtr(tSec0);
- ptr[0].p = p;
- ptr[0].sz = p->m_sz;
- case 0:
- return;
- }
- char msg[40];
- sprintf(msg, "secCount=%d", secCount);
- ErrorReporter::handleAssert(msg, __FILE__, __LINE__);
-}
-
-void
-getSection(SegmentedSectionPtr & ptr, Uint32 i){
- ptr.i = i;
- SectionSegment * p = g_sectionSegmentPool.getPtr(i);
- ptr.p = p;
- ptr.sz = p->m_sz;
-}
-
-#define relSz(x) ((x + SectionSegment::DataLength - 1) / SectionSegment::DataLength)
-
-void
-release(SegmentedSectionPtr & ptr){
- g_sectionSegmentPool.releaseList(relSz(ptr.sz),
- ptr.i,
- ptr.p->m_lastSegment);
-}
-
-void
-releaseSections(Uint32 secCount, SegmentedSectionPtr ptr[3]){
- Uint32 tSec0 = ptr[0].i;
- Uint32 tSz0 = ptr[0].sz;
- Uint32 tSec1 = ptr[1].i;
- Uint32 tSz1 = ptr[1].sz;
- Uint32 tSec2 = ptr[2].i;
- Uint32 tSz2 = ptr[2].sz;
- switch(secCount){
- case 3:
- g_sectionSegmentPool.releaseList(relSz(tSz2), tSec2,
- ptr[2].p->m_lastSegment);
- case 2:
- g_sectionSegmentPool.releaseList(relSz(tSz1), tSec1,
- ptr[1].p->m_lastSegment);
- case 1:
- g_sectionSegmentPool.releaseList(relSz(tSz0), tSec0,
- ptr[0].p->m_lastSegment);
- case 0:
- return;
- }
- char msg[40];
- sprintf(msg, "secCount=%d", secCount);
- ErrorReporter::handleAssert(msg, __FILE__, __LINE__);
-}
-
-#include <DebuggerNames.hpp>
-
-void
-execute(void * callbackObj,
- SignalHeader * const header,
- Uint8 prio,
- Uint32 * const theData,
- LinearSectionPtr ptr[3]){
-
- const Uint32 secCount = header->m_noOfSections;
- const Uint32 length = header->theLength;
-
-#ifdef TRACE_DISTRIBUTED
- ndbout_c("recv: %s(%d) from (%s, %d)",
- getSignalName(header->theVerId_signalNumber),
- header->theVerId_signalNumber,
- getBlockName(refToBlock(header->theSendersBlockRef)),
- refToNode(header->theSendersBlockRef));
-#endif
-
- bool ok = true;
- Ptr<SectionSegment> secPtr[3];
- switch(secCount){
- case 3:
- ok &= import(secPtr[2], ptr[2].p, ptr[2].sz);
- case 2:
- ok &= import(secPtr[1], ptr[1].p, ptr[1].sz);
- case 1:
- ok &= import(secPtr[0], ptr[0].p, ptr[0].sz);
- }
-
- /**
- * Check that we haven't received a too long signal
- */
- ok &= (length + secCount <= 25);
-
- Uint32 secPtrI[3];
- if(ok){
- /**
- * Normal path
- */
- secPtrI[0] = secPtr[0].i;
- secPtrI[1] = secPtr[1].i;
- secPtrI[2] = secPtr[2].i;
-
- globalScheduler.execute(header, prio, theData, secPtrI);
- return;
- }
-
- /**
- * Out of memory
- */
- for(Uint32 i = 0; i<secCount; i++){
- if(secPtr[i].p != 0){
- g_sectionSegmentPool.releaseList(relSz(ptr[i].sz), secPtr[i].i,
- secPtr[i].p->m_lastSegment);
- }
- }
- Uint32 gsn = header->theVerId_signalNumber;
- Uint32 len = header->theLength;
- Uint32 newLen= (len > 22 ? 22 : len);
- SignalDroppedRep * rep = (SignalDroppedRep*)theData;
- memmove(rep->originalData, theData, (4 * newLen));
- rep->originalGsn = gsn;
- rep->originalLength = len;
- rep->originalSectionCount = secCount;
- header->theVerId_signalNumber = GSN_SIGNAL_DROPPED_REP;
- header->theLength = newLen + 3;
- header->m_noOfSections = 0;
- globalScheduler.execute(header, prio, theData, secPtrI);
-}
-
-NdbOut &
-operator<<(NdbOut& out, const SectionSegment & ss){
- out << "[ last= " << ss.m_lastSegment << " next= " << ss.nextPool << " ]";
- return out;
-}
-
-void
-print(SectionSegment * s, Uint32 len, FILE* out){
- for(Uint32 i = 0; i<len; i++){
- fprintf(out, "H\'0x%.8x ", s->theData[i]);
- if(((i + 1) % 6) == 0)
- fprintf(out, "\n");
- }
-}
-
-void
-print(SegmentedSectionPtr ptr, FILE* out){
-
- ptr.p = g_sectionSegmentPool.getPtr(ptr.i);
- Uint32 len = ptr.p->m_sz;
-
- fprintf(out, "ptr.i = %d(%p) ptr.sz = %d(%d)\n", ptr.i, ptr.p, len, ptr.sz);
- while(len > SectionSegment::DataLength){
- print(ptr.p, SectionSegment::DataLength, out);
-
- len -= SectionSegment::DataLength;
- fprintf(out, "ptr.i = %d\n", ptr.p->m_nextSegment);
- ptr.p = g_sectionSegmentPool.getPtr(ptr.p->m_nextSegment);
- }
-
- print(ptr.p, len, out);
- fprintf(out, "\n");
-}
-
-int
-checkJobBuffer() {
- /**
- * Check to see if jobbbuffers are starting to get full
- * and if so call doJob
- */
- return globalScheduler.checkDoJob();
-}
-
-void
-reportError(void * callbackObj, NodeId nodeId,
- TransporterError errorCode, const char *info)
-{
-#ifdef DEBUG_TRANSPORTER
- ndbout_c("reportError (%d, 0x%x) %s", nodeId, errorCode, info ? info : "")
-#endif
-
- 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);
- }
- 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);
- }
- 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);
- }
-
- SignalT<3> signalT;
- Signal &signal= *(Signal*)&signalT;
- memset(&signal.header, 0, sizeof(signal.header));
-
-
- if(errorCode & TE_DO_DISCONNECT)
- signal.theData[0] = NDB_LE_TransporterError;
- else
- signal.theData[0] = NDB_LE_TransporterWarning;
-
- signal.theData[1] = nodeId;
- signal.theData[2] = errorCode;
-
- signal.header.theLength = 3;
- signal.header.theSendersSignalId = 0;
- signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
- globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
-
- DBUG_VOID_RETURN;
-}
-
-/**
- * Report average send length in bytes (4096 last sends)
- */
-void
-reportSendLen(void * callbackObj,
- NodeId nodeId, Uint32 count, Uint64 bytes){
-
- 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] = NDB_LE_SendBytesStatistic;
- signal.theData[1] = nodeId;
- signal.theData[2] = (bytes/count);
- globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
-}
-
-/**
- * Report average receive length in bytes (4096 last receives)
- */
-void
-reportReceiveLen(void * callbackObj,
- NodeId nodeId, Uint32 count, Uint64 bytes){
-
- 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] = NDB_LE_ReceiveBytesStatistic;
- signal.theData[1] = nodeId;
- signal.theData[2] = (bytes/count);
- globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
-}
-
-/**
- * Report connection established
- */
-
-void
-reportConnect(void * callbackObj, NodeId nodeId){
-
- SignalT<1> signalT;
- Signal &signal= *(Signal*)&signalT;
- memset(&signal.header, 0, sizeof(signal.header));
-
- signal.header.theLength = 1;
- signal.header.theSendersSignalId = 0;
- signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
- signal.theData[0] = nodeId;
-
- globalScheduler.execute(&signal, JBA, CMVMI, GSN_CONNECT_REP);
-}
-
-/**
- * Report connection broken
- */
-void
-reportDisconnect(void * callbackObj, NodeId nodeId, Uint32 errNo){
-
- DBUG_ENTER("reportDisconnect");
-
- SignalT<sizeof(DisconnectRep)/4> signalT;
- Signal &signal= *(Signal*)&signalT;
- memset(&signal.header, 0, sizeof(signal.header));
-
- signal.header.theLength = DisconnectRep::SignalLength;
- signal.header.theSendersSignalId = 0;
- signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
- signal.header.theTrace = TestOrd::TraceDisconnect;
-
- DisconnectRep * const rep = (DisconnectRep *)&signal.theData[0];
- rep->nodeId = nodeId;
- rep->err = errNo;
-
- globalScheduler.execute(&signal, JBA, CMVMI, GSN_DISCONNECT_REP);
-
- DBUG_VOID_RETURN;
-}
-
-void
-SignalLoggerManager::printSegmentedSection(FILE * output,
- const SignalHeader & sh,
- const SegmentedSectionPtr ptr[3],
- unsigned i)
-{
- fprintf(output, "SECTION %u type=segmented", i);
- if (i >= 3) {
- fprintf(output, " *** invalid ***\n");
- return;
- }
- const Uint32 len = ptr[i].sz;
- SectionSegment * ssp = ptr[i].p;
- Uint32 pos = 0;
- fprintf(output, " size=%u\n", (unsigned)len);
- while (pos < len) {
- if (pos > 0 && pos % SectionSegment::DataLength == 0) {
- ssp = g_sectionSegmentPool.getPtr(ssp->m_nextSegment);
- }
- printDataWord(output, pos, ssp->theData[pos % SectionSegment::DataLength]);
- }
- if (len > 0)
- putc('\n', output);
-}
-
-void
-transporter_recv_from(void * callbackObj, NodeId nodeId){
- globalData.m_nodeInfo[nodeId].m_heartbeat_cnt= 0;
- return;
-}
diff --git a/storage/ndb/src/kernel/vm/VMSignal.cpp b/storage/ndb/src/kernel/vm/VMSignal.cpp
deleted file mode 100644
index 3d6d7ddc8f7..00000000000
--- a/storage/ndb/src/kernel/vm/VMSignal.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "VMSignal.hpp"
-#include <string.h>
-
-Signal::Signal(){
- memset(&header, 0, sizeof(header));
- memset(theData, 0, sizeof(theData));
-}
-
-void
-Signal::garbage_register()
-{
- int i;
- theData[0] = 0x13579135;
- header.theLength = 0x13579135;
- header.theSendersBlockRef = 0x13579135;
- for (i = 1; i < 24; i++)
- theData[i] = 0x13579135;
-}
diff --git a/storage/ndb/src/kernel/vm/VMSignal.hpp b/storage/ndb/src/kernel/vm/VMSignal.hpp
deleted file mode 100644
index ccdcea56463..00000000000
--- a/storage/ndb/src/kernel/vm/VMSignal.hpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef VMSignal_H
-#define VMSignal_H
-
-#include <ndb_global.h>
-#include <ndb_limits.h>
-#include <kernel_types.h>
-
-#include <ErrorReporter.hpp>
-#include <NodeBitmask.hpp>
-
-#include <RefConvert.hpp>
-#include <TransporterDefinitions.hpp>
-
-/**
- * Struct used when sending to multiple blocks
- */
-struct NodeReceiverGroup {
- NodeReceiverGroup();
- NodeReceiverGroup(Uint32 blockRef);
- NodeReceiverGroup(Uint32 blockNo, const NodeBitmask &);
- NodeReceiverGroup(Uint32 blockNo, const class SignalCounter &);
-
- NodeReceiverGroup& operator=(BlockReference ref);
-
- Uint32 m_block;
- 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
- */
-class Signal {
- friend class SimulatedBlock;
- friend class APZJobBuffer;
- friend class FastScheduler;
-public:
- Signal();
-
- Uint32 getLength() const;
- Uint32 getTrace() const;
- Uint32 getSendersBlockRef() const;
-
- const Uint32* getDataPtr() const ;
- Uint32* getDataPtrSend() ;
-
- void setTrace(Uint32);
-
- Uint32 getNoOfSections() const;
- bool getSection(SegmentedSectionPtr & ptr, Uint32 sectionNo);
- void setSection(SegmentedSectionPtr ptr, Uint32 sectionNo);
-
- /**
- * Old depricated methods...
- */
- Uint32 length() const { return getLength();}
- BlockReference senderBlockRef() const { return getSendersBlockRef();}
-
-private:
- void setLength(Uint32);
-
-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];
- union {
- Uint32 theData[8192]; // 8192 32-bit words -> 32K Bytes
- Uint64 dummyAlign;
- };
- void garbage_register();
-};
-
-inline
-Uint32
-Signal::getLength() const {
- return header.theLength;
-}
-
-inline
-Uint32
-Signal::getTrace() const {
- return header.theTrace;
-}
-
-inline
-Uint32
-Signal::getSendersBlockRef() const {
- return header.theSendersBlockRef;
-}
-
-inline
-const Uint32*
-Signal::getDataPtr() const {
- return &theData[0];
-}
-
-inline
-Uint32*
-Signal::getDataPtrSend() {
- return &theData[0];
-}
-
-inline
-void
-Signal::setLength(Uint32 len){
- header.theLength = len;
-}
-
-inline
-void
-Signal::setTrace(Uint32 t){
- header.theTrace = t;
-}
-
-inline
-Uint32
-Signal::getNoOfSections() const {
- return header.m_noOfSections;
-}
-
-inline
-bool
-Signal::getSection(SegmentedSectionPtr & ptr, Uint32 section){
- if(section < header.m_noOfSections){
- ptr = m_sectionPtr[section];
- return true;
- }
- ptr.p = 0;
- return false;
-}
-
-inline
-void
-Signal::setSection(SegmentedSectionPtr ptr, Uint32 sectionNo){
- if(sectionNo != header.m_noOfSections || sectionNo > 2){
- abort();
- }
- m_sectionPtr[sectionNo] = ptr;
- header.m_noOfSections++;
-}
-
-inline
-NodeReceiverGroup::NodeReceiverGroup() : m_block(0){
- m_nodes.clear();
-}
-
-inline
-NodeReceiverGroup::NodeReceiverGroup(Uint32 blockRef){
- m_nodes.clear();
- m_block = refToBlock(blockRef);
- m_nodes.set(refToNode(blockRef));
-}
-
-inline
-NodeReceiverGroup::NodeReceiverGroup(Uint32 blockNo, const NodeBitmask & nodes){
- m_block = blockNo;
- m_nodes = nodes;
-}
-
-#include "SignalCounter.hpp"
-
-inline
-NodeReceiverGroup::NodeReceiverGroup(Uint32 blockNo, const SignalCounter & nodes){
- m_block = blockNo;
- m_nodes = nodes.m_nodes;
-}
-
-inline
-NodeReceiverGroup&
-NodeReceiverGroup::operator=(BlockReference blockRef){
- m_nodes.clear();
- m_block = refToBlock(blockRef);
- m_nodes.set(refToNode(blockRef));
- return * this;
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/WOPool.cpp b/storage/ndb/src/kernel/vm/WOPool.cpp
deleted file mode 100644
index 359b79c42fe..00000000000
--- a/storage/ndb/src/kernel/vm/WOPool.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright (c) 2003, 2006, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "WOPool.hpp"
-#include <ndbd_exit_codes.h>
-#include <NdbOut.hpp>
-
-WOPool::WOPool()
-{
- bzero(this, sizeof(* this));
- m_current_pos = WOPage::WOPAGE_WORDS;
-}
-
-void
-WOPool::init(const Record_info& ri, const Pool_context& pc)
-{
- m_ctx = pc;
- m_record_info = ri;
- m_record_info.m_size = ((ri.m_size + 3) >> 2); // Align to word boundary
- m_record_info.m_offset_magic = ((ri.m_offset_magic + 3) >> 2);
- m_memroot = (WOPage*)m_ctx.get_memroot();
- ndbout_c("WOPool::init(%x, %d)",ri.m_type_id, m_record_info.m_size);
-}
-
-bool
-WOPool::seize_new_page(Ptr<void>& ptr)
-{
- WOPage* page;
- Uint32 page_no = RNIL;
- if ((page = (WOPage*)m_ctx.alloc_page(m_record_info.m_type_id, &page_no)))
- {
- if (m_current_page)
- {
- m_current_page->m_ref_count = m_current_ref_count;
- }
-
- m_current_pos = 0;
- m_current_ref_count = 0;
- m_current_page_no = page_no;
- m_current_page = page;
- page->m_type_id = m_record_info.m_type_id;
- bool ret = seize(ptr);
- assert(ret);
- return true;
- }
- return false;
-}
-
-void
-WOPool::release_not_current(Ptr<void> ptr)
-{
- WOPage* page = (WOPage*)(UintPtr(ptr.p) & ~(GLOBAL_PAGE_SIZE - 1));
- Uint32 cnt = page->m_ref_count;
- Uint32 type = page->m_type_id;
- Uint32 ri_type = m_record_info.m_type_id;
- if (likely(cnt && type == ri_type))
- {
- if (cnt == 1)
- {
- m_ctx.release_page(ri_type, ptr.i >> POOL_RECORD_BITS);
- return;
- }
- page->m_ref_count = cnt - 1;
- return;
- }
-
- handle_inconsistent_release(ptr);
-}
-
-void
-WOPool::handle_invalid_release(Ptr<void> ptr)
-{
- char buf[255];
-
- Uint32 pos = ptr.i & POOL_RECORD_MASK;
- Uint32 pageI = ptr.i >> POOL_RECORD_BITS;
- Uint32 * record_ptr_p = (Uint32*)ptr.p;
- Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
-
- Uint32 magic = * (record_ptr_p + m_record_info.m_offset_magic);
- snprintf(buf, sizeof(buf),
- "Invalid memory release: ptr (%x %p %p) magic: (%.8x %.8x) memroot: %p page: %x",
- ptr.i, ptr.p, record_ptr_i, magic, m_record_info.m_type_id,
- m_memroot,
- (m_memroot+pageI)->m_type_id);
-
- m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
-}
-
-void
-WOPool::handle_invalid_get_ptr(Uint32 ptrI)
-{
- char buf[255];
-
- Uint32 pos = ptrI & POOL_RECORD_MASK;
- Uint32 pageI = ptrI >> POOL_RECORD_BITS;
- Uint32 * record_ptr_i = (m_memroot+pageI)->m_data + pos;
-
- Uint32 magic = * (record_ptr_i + m_record_info.m_offset_magic);
- snprintf(buf, sizeof(buf),
- "Invalid memory access: ptr (%x %p) magic: (%.8x %.8x) memroot: %p page: %x",
- ptrI, record_ptr_i, magic, m_record_info.m_type_id,
- m_memroot,
- (m_memroot+pageI)->m_type_id);
-
- m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
-}
-
-void
-WOPool::handle_inconsistent_release(Ptr<void> ptr)
-{
- WOPage* page = (WOPage*)(UintPtr(ptr.p) & ~(GLOBAL_PAGE_SIZE - 1));
- Uint32 cnt = page->m_ref_count;
- Uint32 type = page->m_type_id;
- Uint32 ri_type = m_record_info.m_type_id;
-
- char buf[255];
-
- snprintf(buf, sizeof(buf),
- "Memory corruption: ptr (%x %p) page (%d %x %x)",
- ptr.i, ptr.p, cnt, type, ri_type);
-
- m_ctx.handleAbort(NDBD_EXIT_PRGERR, buf);
-}
diff --git a/storage/ndb/src/kernel/vm/WOPool.hpp b/storage/ndb/src/kernel/vm/WOPool.hpp
deleted file mode 100644
index a9cdef881fb..00000000000
--- a/storage/ndb/src/kernel/vm/WOPool.hpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Copyright (c) 2003, 2006, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef WOPOOL_HPP
-#define WOPOOL_HPP
-
-#include "Pool.hpp"
-
-struct WOPage
-{
- STATIC_CONST( WOPAGE_WORDS = GLOBAL_PAGE_SIZE_WORDS - 2 );
-
- Uint32 m_type_id;
- Uint32 m_ref_count;
- Uint32 m_data[WOPAGE_WORDS];
-};
-
-/**
- * Write Once Pool
- */
-struct WOPool
-{
- Record_info m_record_info;
- WOPage* m_memroot;
- WOPage* m_current_page;
- Pool_context m_ctx;
- Uint32 m_current_page_no;
- Uint16 m_current_pos;
- Uint16 m_current_ref_count;
-public:
- WOPool();
-
- void init(const Record_info& ri, const Pool_context& pc);
- bool seize(Ptr<void>&);
- void release(Ptr<void>);
- void * getPtr(Uint32 i);
-
-private:
- bool seize_new_page(Ptr<void>&);
- void release_not_current(Ptr<void>);
-
- void handle_invalid_release(Ptr<void>);
- void handle_invalid_get_ptr(Uint32 i);
- void handle_inconsistent_release(Ptr<void>);
-};
-
-inline
-bool
-WOPool::seize(Ptr<void>& ptr)
-{
- Uint32 pos = m_current_pos;
- Uint32 size = m_record_info.m_size;
- WOPage *pageP = m_current_page;
- if (likely(pos + size < WOPage::WOPAGE_WORDS))
- {
- ptr.i = (m_current_page_no << POOL_RECORD_BITS) + pos;
- ptr.p = (pageP->m_data + pos);
- pageP->m_data[pos+m_record_info.m_offset_magic] = ~(Uint32)m_record_info.m_type_id;
- m_current_pos = pos + size;
- m_current_ref_count++;
- return true;
- }
-
- return seize_new_page(ptr);
-}
-
-inline
-void
-WOPool::release(Ptr<void> ptr)
-{
- Uint32 cur_page = m_current_page_no;
- Uint32 ptr_page = ptr.i >> POOL_RECORD_BITS;
- Uint32 *magic_ptr = (((Uint32*)ptr.p)+m_record_info.m_offset_magic);
- Uint32 magic_val = *magic_ptr;
-
- if (likely(magic_val == ~(Uint32)m_record_info.m_type_id))
- {
- * magic_ptr = 0;
- if (cur_page == ptr_page)
- {
- if (m_current_ref_count == 1)
- {
- m_current_pos = 0;
- }
- m_current_ref_count--;
- return;
- }
- return release_not_current(ptr);
- }
- handle_invalid_release(ptr);
-}
-
-inline
-void*
-WOPool::getPtr(Uint32 i)
-{
- Uint32 page_no = i >> POOL_RECORD_BITS;
- Uint32 page_idx = i & POOL_RECORD_MASK;
- WOPage * page = m_memroot + page_no;
- Uint32 * record = page->m_data + page_idx;
- Uint32 magic_val = * (record + m_record_info.m_offset_magic);
- if (likely(magic_val == ~(Uint32)m_record_info.m_type_id))
- {
- return record;
- }
- handle_invalid_get_ptr(i);
- return 0; /* purify: deadcode */
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/WaitQueue.hpp b/storage/ndb/src/kernel/vm/WaitQueue.hpp
deleted file mode 100644
index 732c895ea12..00000000000
--- a/storage/ndb/src/kernel/vm/WaitQueue.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef WAIT_QUEUE_HPP
-#define WAIT_QUEUE_HPP
-
-#include "ArrayPool.hpp"
-#include "SimulatedBlock.hpp"
-
-template <class Block,
- class T,
- void (Block::* Function)(Signal*, Ptr<T>)>
-class WaitQueue {
-public:
- WaitQueue(Block & block, ArrayPool<T>& pool){
- }
-
- void add(Ptr<T>, void (Block::* Callback)(Signal*, Ptr<T>)) {}
- void complete(Ptr<T>) {}
-};
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/WatchDog.cpp b/storage/ndb/src/kernel/vm/WatchDog.cpp
deleted file mode 100644
index fdf45a1803b..00000000000
--- a/storage/ndb/src/kernel/vm/WatchDog.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/* Copyright (c) 2003-2005, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-#include <my_pthread.h>
-#include <sys/times.h>
-
-#include "WatchDog.hpp"
-#include "GlobalData.hpp"
-#include <NdbOut.hpp>
-#include <NdbSleep.h>
-#include <ErrorHandlingMacros.hpp>
-#include <EventLogger.hpp>
-
-#include <NdbTick.h>
-
-extern EventLogger g_eventLogger;
-
-extern "C"
-void*
-runWatchDog(void* w){
- ((WatchDog*)w)->run();
- return NULL;
-}
-
-WatchDog::WatchDog(Uint32 interval) :
- theIPValue(globalData.getWatchDogPtr())
-{
- setCheckInterval(interval);
- theStop = false;
- theThreadPtr = 0;
-}
-
-WatchDog::~WatchDog(){
- doStop();
-}
-
-Uint32
-WatchDog::setCheckInterval(Uint32 interval){
- // An interval of less than 70ms is not acceptable
- return theInterval = (interval < 70 ? 70 : interval);
-}
-
-void
-WatchDog::doStart(){
- theStop = false;
- theThreadPtr = NdbThread_Create(runWatchDog,
- (void**)this,
- 32768,
- "ndb_watchdog",
- NDB_THREAD_PRIO_HIGH);
-}
-
-void
-WatchDog::doStop(){
- void *status;
- theStop = true;
- if(theThreadPtr){
- NdbThread_WaitFor(theThreadPtr, &status);
- NdbThread_Destroy(&theThreadPtr);
- }
-}
-
-const char *get_action(Uint32 IPValue)
-{
- const char *action;
- switch (IPValue) {
- case 1:
- action = "Job Handling";
- break;
- case 2:
- action = "Scanning Timers";
- break;
- case 3:
- action = "External I/O";
- break;
- case 4:
- action = "Print Job Buffers at crash";
- break;
- case 5:
- action = "Checking connections";
- break;
- case 6:
- action = "Performing Send";
- break;
- case 7:
- action = "Polling for Receive";
- break;
- case 8:
- action = "Performing Receive";
- break;
- case 9:
- action = "Allocating memory";
- break;
- default:
- action = "Unknown place";
- break;
- }//switch
- return action;
-}
-
-void
-WatchDog::run()
-{
- unsigned int anIPValue, sleep_time;
- unsigned int oldIPValue = 0;
- unsigned int theIntervalCheck = theInterval;
- struct MicroSecondTimer start_time, last_time, now;
- NdbTick_getMicroTimer(&start_time);
- last_time = start_time;
-
- // WatchDog for the single threaded NDB
- while (!theStop)
- {
- sleep_time= 100;
-
- NdbSleep_MilliSleep(sleep_time);
- if(theStop)
- break;
-
- NdbTick_getMicroTimer(&now);
- if (NdbTick_getMicrosPassed(last_time, now)/1000 > sleep_time*2)
- {
- struct tms my_tms;
- times(&my_tms);
- g_eventLogger.info("Watchdog: User time: %llu System time: %llu",
- (Uint64)my_tms.tms_utime,
- (Uint64)my_tms.tms_stime);
- g_eventLogger.warning("Watchdog: Warning overslept %u ms, expected %u ms.",
- NdbTick_getMicrosPassed(last_time, now)/1000,
- sleep_time);
- }
- last_time = now;
-
- // Verify that the IP thread is not stuck in a loop
- anIPValue = *theIPValue;
- if (anIPValue != 0)
- {
- oldIPValue = anIPValue;
- globalData.incrementWatchDogCounter(0);
- NdbTick_getMicroTimer(&start_time);
- theIntervalCheck = theInterval;
- }
- else
- {
- int warn = 1;
- Uint32 elapsed = NdbTick_getMicrosPassed(start_time, now)/1000;
- /*
- oldIPValue == 9 indicates malloc going on, this can take some time
- so only warn if we pass the watchdog interval
- */
- if (oldIPValue == 9)
- if (elapsed < theIntervalCheck)
- warn = 0;
- else
- theIntervalCheck += theInterval;
-
- if (warn)
- {
- const char *last_stuck_action = get_action(oldIPValue);
- g_eventLogger.warning("Ndb kernel is stuck in: %s", last_stuck_action);
- {
- struct tms my_tms;
- times(&my_tms);
- g_eventLogger.info("Watchdog: User time: %llu System time: %llu",
- (Uint64)my_tms.tms_utime,
- (Uint64)my_tms.tms_stime);
- }
- if (elapsed > 3 * theInterval)
- {
- shutdownSystem(last_stuck_action);
- }
- }
- }
- }
- return;
-}
-
-void
-WatchDog::shutdownSystem(const char *last_stuck_action){
-
- ErrorReporter::handleError(NDBD_EXIT_WATCHDOG_TERMINATE,
- last_stuck_action,
- __FILE__,
- NST_Watchdog);
-}
diff --git a/storage/ndb/src/kernel/vm/WatchDog.hpp b/storage/ndb/src/kernel/vm/WatchDog.hpp
deleted file mode 100644
index f78850f8e86..00000000000
--- a/storage/ndb/src/kernel/vm/WatchDog.hpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef WatchDog_H
-#define WatchDog_H
-
-#include <kernel_types.h>
-#include <NdbThread.h>
-
-extern "C" void* runWatchDog(void* w);
-
-class WatchDog{
-public:
- WatchDog(Uint32 interval = 3000);
- ~WatchDog();
-
- void doStart();
- void doStop();
-
- Uint32 setCheckInterval(Uint32 interval);
-
-protected:
- /**
- * Thread function
- */
- friend void* runWatchDog(void* w);
-
- /**
- * Thread pointer
- */
- NdbThread* theThreadPtr;
-
-private:
- Uint32 theInterval;
- const Uint32 * theIPValue;
-
- bool theStop;
-
- void run();
- void shutdownSystem(const char *last_stuck_action);
-};
-
-#endif // WatchDog_H
diff --git a/storage/ndb/src/kernel/vm/al_test/Makefile b/storage/ndb/src/kernel/vm/al_test/Makefile
deleted file mode 100644
index a7287a341fd..00000000000
--- a/storage/ndb/src/kernel/vm/al_test/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-BIN_TARGET := al_test
-BIN_TARGET_ARCHIVES := portlib
-
-SOURCES = main.cpp
-
-CFLAGS_main.cpp = -DDEBUG
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/storage/ndb/src/kernel/vm/al_test/arrayListTest.cpp b/storage/ndb/src/kernel/vm/al_test/arrayListTest.cpp
deleted file mode 100644
index 3b5304b432c..00000000000
--- a/storage/ndb/src/kernel/vm/al_test/arrayListTest.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-
-#include <ndb_global.hpp>
-
-#include <ArrayList.hpp>
-#include <NdbOut.hpp>
-#include <NdbTick.h>
-
-struct A_Listable_Object {
- Uint32 next;
- Uint32 prev;
- char somedata[12];
-
- void print (NdbOut & out) {
- out << "ALO: next = " << next
- << " prev = " << prev << endl;
- }
-};
-
-extern const int x_AL_Next = offsetof(A_Listable_Object, next);
-extern const int x_AL_Prev = offsetof(A_Listable_Object, prev);
-
-NdbOut &
-operator<<(NdbOut & o, A_Listable_Object & a){
- a.print(o);
- return o;
-}
-
-typedef Ptr<A_Listable_Object> A_Listable_ObjectPtr;
-
-#define APool ArrayPool<A_Listable_Object>
-#define AList ArrayList<A_Listable_Object>
-
-APool aGPool;
-AList aGList(aGPool);
-
-class ArrayListTest {
-public:
- static void tryList0(int listSize){
- APool aPool;
- AList aList(aPool);
-
- if(!aPool.setSize(listSize)){
- ndbout << "Failed to do aPool.setSize(" << listSize << ")" << endl;
- return;
- }
-
- int * anArray = new int[listSize];
-
- for(int i = 1; i<listSize; i++){
- int arrayElements = 0;
-
-
- for(int j = 0; j<i; j++){
- A_Listable_ObjectPtr p;
- const int ret = aList.seize(p);
- if(ret == RNIL){
- ndbout << "Failed to seize!!" << endl;
- ndbout << "Have seized " << j
- << " out of " << listSize << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- anArray[arrayElements] = ret;
- arrayElements++;
- }
- assert(aList.noOfElements() == i);
- assert(aPool.noOfFree() == (listSize - i));
- assert(arrayElements == i);
-
- for(int j = 0; j<i; j++){
- aList.release(anArray[j]);
- }
-
- assert(aList.noOfElements() == 0);
- assert(aPool.noOfFree() == listSize);
- }
- }
-
- static void tryList1(int listSize, int iterations){
- APool aPool;
- AList aList(aPool);
-
- if(!aPool.setSize(listSize)){
- ndbout << "Failed to do aPool.setSize(" << listSize << ")" << endl;
- return;
- }
-
- ndbout << "Seizing/Releaseing " << iterations
- << " times over list with " << listSize << " elements" << endl;
-
- int * anArray = new int[listSize];
- int arrayElements = 0;
-
- int noOfSeize = 0;
- int noFailSeize = 0;
- int noOfRelease = 0;
-
- for(int i = 0; i<iterations; i++){
- assert(arrayElements <= listSize);
- const int r = rand() % (10 * listSize);
- if(r < (arrayElements - 1)){
- /**
- * Release an element
- */
- noOfRelease++;
- aList.release(anArray[r]);
- arrayElements--;
- for(int j = r; j<arrayElements; j++)
- anArray[j] = anArray[j+1];
-
- } else {
- /**
- * Seize an element
- */
- A_Listable_ObjectPtr p;
- const int ret = aList.seize(p);
- if(ret == RNIL && arrayElements != listSize){
- ndbout << "Failed to seize!!"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << listSize << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(arrayElements >= listSize && ret != RNIL){
- ndbout << "Seize did not fail when it should have"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << listSize << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(ret != RNIL){
- noOfSeize++;
- anArray[arrayElements] = ret;
- arrayElements++;
- } else {
- noFailSeize++;
- }
- }
- }
- delete []anArray;
-
- ndbout << "Seized: " << noOfSeize
- << " Seized with buffer full: " << noFailSeize
- << " Release: " << noOfRelease << " --- ";
- ndbout << "(" << noOfSeize << " + " << noFailSeize << " + " << noOfRelease
- << " = " << (noOfSeize + noFailSeize + noOfRelease) << ")" << endl;
- }
-
- static void tryList2(int size, int iter, int fail){
- APool aPool;
- AList aList(aPool);
-
- if(!aPool.setSize(size)){
- ndbout << "Failed to do aPool.setSize(" << size << ")" << endl;
- return;
- }
-
- ndbout << "doing getPtr(i) where i > size(" << size << ") "
- << fail << " times mixed with " << iter
- << " ordinary seize/release" << endl;
-
- int * anArray = new int[size];
- int arrayElements = 0;
-
- int noOfSeize = 0;
- int noFailSeize = 0;
- int noOfRelease = 0;
-
- for(int i = 0; i<iter; i++){
- assert(arrayElements <= size);
- const int r = rand() % (10 * size);
-
- if((i + 1)%(iter/fail) == 0){
- aList.getPtr(size + r);
- continue;
- }
-
- if(r < (arrayElements - 1)){
- /**
- * Release an element
- */
- noOfRelease++;
- aList.release(anArray[r]);
- arrayElements--;
- for(int j = r; j<arrayElements; j++)
- anArray[j] = anArray[j+1];
-
- } else {
- /**
- * Seize an element
- */
- A_Listable_ObjectPtr p;
- const int ret = aList.seize(p);
- if(ret == RNIL && arrayElements != size){
- ndbout << "Failed to seize!!"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(arrayElements >= size && ret != RNIL){
- ndbout << "Seize did not fail when it should have"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(ret != RNIL){
- noOfSeize++;
- anArray[arrayElements] = ret;
- arrayElements++;
- } else {
- noFailSeize++;
- }
- }
- }
- delete []anArray;
- }
-
- static void
- tryList3(int size, int fail){
- ndbout << "Failing " << fail << " times " << endl;
-
- for(int i = 0; i<fail; i++){
- APool aPool;
- AList aList(aPool);
-
- if(!aPool.setSize(size)){
- ndbout << "Failed to do aPool.setSize(" << size << ")" << endl;
- return;
- }
-
- const int noOfElementsInBufferWhenFail = (i + 1) * (size /(fail + 1));
-
- int * anArray = new int[size];
- for(int i = 0; i<size; i++)
- anArray[i] = i;
- int arrayElements = 0;
-
- int noOfSeize = 0;
- int noFailSeize = 0;
- int noOfRelease = 0;
-
- while(true){
- assert(arrayElements <= size);
- if(arrayElements == noOfElementsInBufferWhenFail){
- ndbout << "++ You should get a ErrorReporter::handle... " << endl;
- aList.release(anArray[arrayElements]);
- ndbout << "++ Inbetween these lines" << endl << endl;
- break;
- }
- const int r = rand() % (10 * size);
- if(r < (arrayElements - 1)){
- /**
- * Release an element
- */
- noOfRelease++;
- aList.release(anArray[r]);
- arrayElements--;
- for(int j = r; j<arrayElements; j++)
- anArray[j] = anArray[j+1];
-
- } else {
- /**
- * Seize an element
- */
- A_Listable_ObjectPtr p;
- const int ret = aList.seize(p);
- if(ret == RNIL && arrayElements != size){
- ndbout << "Failed to seize!!" << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(arrayElements >= size && ret != RNIL){
- ndbout << "Seize did not fail when it should have" << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(ret != RNIL){
- noOfSeize++;
- anArray[arrayElements] = ret;
- arrayElements++;
- } else {
- noFailSeize++;
- }
- }
- }
- delete []anArray;
- }
-
- }
-};
diff --git a/storage/ndb/src/kernel/vm/al_test/arrayPoolTest.cpp b/storage/ndb/src/kernel/vm/al_test/arrayPoolTest.cpp
deleted file mode 100644
index 75f97d1ffba..00000000000
--- a/storage/ndb/src/kernel/vm/al_test/arrayPoolTest.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-
-#include <ndb_global.h>
-
-#include <ArrayList.hpp>
-#include <NdbOut.hpp>
-#include <NdbTick.h>
-
-struct A_Poolable_Object {
- Uint32 next;
- char somedata[12];
-
- void print (NdbOut & out) {
- out << "A_Poolable_Object: next = " << next << endl;
- }
-
-};
-
-
-NdbOut &
-operator<<(NdbOut & o, A_Poolable_Object & a){
- a.print(o);
- return o;
-}
-
-typedef Ptr<A_Poolable_Object> A_Poolable_ObjectPtr;
-#if 1
-#define BPool ArrayPool<A_Poolable_Object>
-#else
-#define BPool ArrayPool(A_Poolable_Object, next)
-#endif
-
-class ArrayPoolTest {
-public:
- static void tryPool1(int poolSize, int iterations){
- BPool aPool;
-
- if(!aPool.setSize(poolSize)){
- ndbout << "Failed to do aPool.setSize(" << poolSize << ")" << endl;
- return;
- }
-
- ndbout << "Seizing/Releaseing " << iterations
- << " times over pool with " << poolSize << " elements" << endl;
-
- int * anArray = new int[poolSize];
- int arrayElements = 0;
-
- int noOfSeize = 0;
- int noFailSeize = 0;
- int noOfRelease = 0;
-
- for(int i = 0; i<iterations; i++){
- if(!((arrayElements <= poolSize) &&
- (aPool.noOfFree() == aPool.noOfFree2()) &&
- (aPool.noOfFree() == (poolSize - arrayElements)))){
- ndbout << "Assertion!!"
- << " iteration=" << i << endl;
- const int f1 = aPool.noOfFree();
- const int f2 = aPool.noOfFree2();
- ndbout << "noOfFree() = " << f1 << endl;
- ndbout << "noOfFree2() = " << f2 << endl;
- ndbout << "poolSize = " << poolSize << endl;
- ndbout << "arrayElemts = " << arrayElements << endl;
- aPool.print(ndbout);
- assert(0);
- }
-
- const int r = rand() % (10 * poolSize);
- if(r < (arrayElements - 1)){
- /**
- * Release an element
- */
- noOfRelease++;
- aPool.release(anArray[r]);
- arrayElements--;
- for(int j = r; j<arrayElements; j++)
- anArray[j] = anArray[j+1];
-
- } else {
- /**
- * Seize an element
- */
- A_Poolable_ObjectPtr p;
- const int ret = aPool.seize(p);
- if(ret == RNIL && arrayElements != poolSize){
- ndbout << "Failed to seize!!"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << poolSize << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(arrayElements >= poolSize && ret != RNIL){
- ndbout << "Seize did not fail when it should have"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << poolSize << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(ret != RNIL){
- noOfSeize++;
- anArray[arrayElements] = ret;
- arrayElements++;
- memset(p.p, i, sizeof(p.p->somedata));
- } else {
- noFailSeize++;
- }
- }
- }
- delete []anArray;
-
- ndbout << "Seized: " << noOfSeize
- << " Seized with buffer full: " << noFailSeize
- << " Release: " << noOfRelease << " --- ";
- ndbout << "(" << noOfSeize << " + " << noFailSeize << " + " << noOfRelease
- << " = " << (noOfSeize + noFailSeize + noOfRelease) << ")" << endl;
- }
-
- static void tryPool2(int size, int iter, int fail){
- BPool aPool;
-
- if(!aPool.setSize(size)){
- ndbout << "Failed to do aPool.setSize(" << size << ")" << endl;
- return;
- }
-
- ndbout << "doing getPtr(i) where i > size(" << size << ") "
- << fail << " times mixed with " << iter
- << " ordinary seize/release" << endl;
-
- int * anArray = new int[size];
- int arrayElements = 0;
-
- int noOfSeize = 0;
- int noFailSeize = 0;
- int noOfRelease = 0;
-
- for(int i = 0; i<iter; i++){
- if(!((arrayElements <= size) &&
- (aPool.noOfFree() == aPool.noOfFree2()) &&
- (aPool.noOfFree() == (size - arrayElements)))){
- ndbout << "Assertion!!"
- << " iteration=" << i << endl;
- const int f1 = aPool.noOfFree();
- const int f2 = aPool.noOfFree2();
- ndbout << "noOfFree() = " << f1 << endl;
- ndbout << "noOfFree2() = " << f2 << endl;
- ndbout << "poolSize = " << size << endl;
- ndbout << "arrayElemts = " << arrayElements << endl;
- aPool.print(ndbout);
- assert(0);
- }
- const int r = rand() % (10 * size);
-
- if((i + 1)%(iter/fail) == 0){
- aPool.getPtr(size + r);
- continue;
- }
-
- if(r < (arrayElements - 1)){
- /**
- * Release an element
- */
- noOfRelease++;
- aPool.release(anArray[r]);
- arrayElements--;
- for(int j = r; j<arrayElements; j++)
- anArray[j] = anArray[j+1];
-
- } else {
- /**
- * Seize an element
- */
- A_Poolable_ObjectPtr p;
- const int ret = aPool.seize(p);
- if(ret == RNIL && arrayElements != size){
- ndbout << "Failed to seize!!"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(arrayElements >= size && ret != RNIL){
- ndbout << "Seize did not fail when it should have"
- << " iteration=" << i << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(ret != RNIL){
- noOfSeize++;
- anArray[arrayElements] = ret;
- arrayElements++;
- memset(p.p, p.i, sizeof(p.p->somedata));
- } else {
- noFailSeize++;
- }
- }
- }
- delete []anArray;
- }
-
- static void
- tryPool3(int size, int fail){
- ndbout << "Failing " << fail << " times " << endl;
-
- for(int i = 0; i<fail; i++){
- BPool aPool;
- if(!aPool.setSize(size)){
- ndbout << "Failed to do aPool.setSize(" << size << ")" << endl;
- return;
- }
-
- const int noOfElementsInBufferWhenFail = (i + 1) * (size /(fail + 1));
-
- int * anArray = new int[size];
- for(int i = 0; i<size; i++)
- anArray[i] = i;
- int arrayElements = 0;
-
- int noOfSeize = 0;
- int noFailSeize = 0;
- int noOfRelease = 0;
-
- while(true){
- assert(arrayElements <= size);
- if(arrayElements == noOfElementsInBufferWhenFail){
- ndbout << "++ You should get a ErrorReporter::handle... " << endl;
- aPool.release(anArray[arrayElements]);
- ndbout << "++ Inbetween these lines" << endl << endl;
- break;
- }
- const int r = rand() % (10 * size);
- if(r < (arrayElements - 1)){
- /**
- * Release an element
- */
- noOfRelease++;
- aPool.release(anArray[r]);
- arrayElements--;
- for(int j = r; j<arrayElements; j++)
- anArray[j] = anArray[j+1];
-
- } else {
- /**
- * Seize an element
- */
- A_Poolable_ObjectPtr p;
- const int ret = aPool.seize(p);
- if(ret == RNIL && arrayElements != size){
- ndbout << "Failed to seize!!" << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(arrayElements >= size && ret != RNIL){
- ndbout << "Seize did not fail when it should have" << endl;
- ndbout << "Have seized " << arrayElements
- << " out of " << size << endl;
- ndbout << "Terminating..." << endl;
- abort();
- }
- if(ret != RNIL){
- noOfSeize++;
- anArray[arrayElements] = ret;
- arrayElements++;
- } else {
- noFailSeize++;
- }
- }
- }
- delete []anArray;
- }
-
- }
-};
-
diff --git a/storage/ndb/src/kernel/vm/al_test/main.cpp b/storage/ndb/src/kernel/vm/al_test/main.cpp
deleted file mode 100644
index 5f536031bb1..00000000000
--- a/storage/ndb/src/kernel/vm/al_test/main.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-
-#include <ArrayList.hpp>
-#include <NdbOut.hpp>
-#include <NdbTick.h>
-#include <NdbMain.h>
-
-#include "arrayListTest.cpp"
-#include "arrayPoolTest.cpp"
-
-NDB_COMMAND(al_test, "al_test", "al_test", "al_test", 65535)
-{
- NdbMem_Create();
- srand(NdbTick_CurrentMillisecond());
-
-#if 1
- ndbout << endl << endl << "-- Testing basic basic seize/release" << endl;
- ArrayListTest::tryList0(10);
-
- ndbout << endl << endl << "-- Testing basic seize/release" << endl;
- ArrayListTest::tryList1(1000, 1000);
-
- ndbout << endl << endl << "-- Testing that seize returns RNIL"
- << endl;
- ArrayListTest::tryList1(10, 1000000);
-
- ndbout << endl << endl << "-- Testing access out of array" << endl;
- ArrayListTest::tryList2(1000, 100000, 5);
-#endif
-
-#if 1
- ndbout << endl << endl << "-- Testing basic seize/release" << endl;
- ArrayPoolTest::tryPool1(1000, 1000);
-
- ndbout << endl << endl << "-- Testing that seize returns RNIL"
- << endl;
- ArrayPoolTest::tryPool1(10, 1000000);
-
- ndbout << endl << endl << "-- Testing access out of array" << endl;
- ArrayPoolTest::tryPool2(1000, 100000, 5);
-
- ndbout << endl << endl << "-- Testing releasing none seized element" << endl;
- ArrayPoolTest::tryPool3(1000, 5);
-#endif
-}
-
-void
-ErrorReporter::handleBlockAssert(int line)
-{
- ndbout << "ErrorReporter::handleAssert activated - "
- << " line= " << line << endl;
- //assert(0);
-}
diff --git a/storage/ndb/src/kernel/vm/bench_pool.cpp b/storage/ndb/src/kernel/vm/bench_pool.cpp
deleted file mode 100644
index 8011bd0f8cd..00000000000
--- a/storage/ndb/src/kernel/vm/bench_pool.cpp
+++ /dev/null
@@ -1,608 +0,0 @@
-/* Copyright (c) 2003, 2006 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include "ArrayPool.hpp"
-#include "WOPool.hpp"
-#include "RWPool.hpp"
-#include <NdbTick.h>
-#include "ndbd_malloc_impl.hpp"
-#include "SimulatedBlock.hpp"
-
-#ifdef USE_CALLGRIND
-#include <valgrind/callgrind.h>
-#else
-#define CALLGRIND_TOGGLE_COLLECT()
-#endif
-
-#define T_TEST_AP (1 << 0)
-#define T_TEST_WO (1 << 1)
-#define T_TEST_RW (1 << 2)
-
-#define T_SEIZE (1 << 0)
-#define T_RELEASE (1 << 1)
-#define T_G_RELEASE (1 << 2)
-#define T_R_RELEASE (1 << 3)
-#define T_R_G_RELEASE (1 << 4)
-#define T_MIX (1 << 5)
-#define T_GETPTR (1 << 6)
-#define T_FIFO (1 << 7)
-
-const char *test_names[] = {
- "seize",
- "release",
- "get+rel",
- "r-rel",
- "r-get+rel",
- "mix",
- "getptr",
- "fifo",
- 0
-};
-
-Uint32 pools = ~0;
-Uint32 tests = ~0;
-Uint32 records = ~0;
-Uint32 sizes = 7;
-unsigned int seed;
-Ndbd_mem_manager mm;
-Configuration cfg;
-Block_context ctx(cfg, mm);
-struct BB : public SimulatedBlock
-{
- BB(int no, Block_context& ctx) : SimulatedBlock(no, ctx) {}
-};
-
-BB block(DBACC, ctx);
-
-template <typename T>
-void
-init(ArrayPool<T> & pool, Uint32 cnt)
-{
- pool.setSize(cnt + 1, true);
-}
-
-template <typename T>
-void
-init(RecordPool<T, WOPool> & pool, Uint32 cnt)
-{
- Pool_context pc;
- pc.m_block = &block;
- pool.wo_pool_init(0x2001, pc);
-}
-
-template <typename T>
-void
-init(RecordPool<T, RWPool> & pool, Uint32 cnt)
-{
- Pool_context pc;
- pc.m_block = &block;
- pool.init(0x2001, pc);
-}
-
-template <typename T, typename R>
-void
-test_pool(R& pool, Uint32 cnt, Uint32 loops)
-{
- Ptr<T> ptr;
- Uint32 *arr = (Uint32*)alloca(cnt * sizeof(Uint32));
- bzero(arr, cnt * sizeof(Uint32));
- if (tests & T_SEIZE)
- {
- Uint64 sum = 0;
- for(Uint32 i = 0; i<loops; i++)
- { // seize
- Uint64 start = NdbTick_CurrentMillisecond();
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 j = 0; j<cnt; j++)
- {
- bool b = pool.seize(ptr);
- arr[j] = ptr.i;
- ptr.p->do_stuff();
- assert(b);
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
-
- for(Uint32 j = 0; j<cnt; j++)
- {
- ptr.i = arr[j];
- pool.getPtr(ptr);
- ptr.p->do_stuff();
- pool.release(ptr.i);
- arr[j] = RNIL;
- }
- sum += (stop - start);
- }
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- if (tests & T_RELEASE)
- { // release
- Uint64 sum = 0;
- for(Uint32 i = 0; i<loops; i++)
- {
- for(Uint32 j = 0; j<cnt; j++)
- {
- bool b = pool.seize(ptr);
- arr[j] = ptr.i;
- ptr.p->do_stuff();
- }
-
- Uint64 start = NdbTick_CurrentMillisecond();
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 j = 0; j<cnt; j++)
- {
- pool.release(arr[j]);
- arr[j] = RNIL;
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
-
- sum += (stop - start);
- }
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- if (tests & T_G_RELEASE)
- { // getptr + release
- Uint64 sum = 0;
- for(Uint32 i = 0; i<loops; i++)
- {
- for(Uint32 j = 0; j<cnt; j++)
- {
- bool b = pool.seize(ptr);
- arr[j] = ptr.i;
- ptr.p->do_stuff();
- }
-
- Uint64 start = NdbTick_CurrentMillisecond();
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 j = 0; j<cnt; j++)
- {
- pool.getPtr(ptr, arr[j]);
- ptr.p->do_stuff();
- pool.release(ptr);
- arr[j] = RNIL;
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
-
- sum += (stop - start);
- }
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- if (tests & T_R_RELEASE)
- { // release reverse
- Uint64 sum = 0;
- for(Uint32 i = 0; i<loops; i++)
- {
- for(Uint32 j = 0; j<cnt; j++)
- {
- bool b = pool.seize(ptr);
- arr[j] = ptr.i;
- ptr.p->do_stuff();
- }
-
- Uint64 start = NdbTick_CurrentMillisecond();
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 j = 0; j<cnt; j++)
- {
- pool.release(arr[cnt - j - 1]);
- arr[cnt - j - 1] = RNIL;
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
-
- sum += (stop - start);
- }
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- if (tests & T_R_G_RELEASE)
- { // getptr + release
- Uint64 sum = 0;
- for(Uint32 i = 0; i<loops; i++)
- {
- for(Uint32 j = 0; j<cnt; j++)
- {
- bool b = pool.seize(ptr);
- arr[j] = ptr.i;
- ptr.p->do_stuff();
- }
-
- Uint64 start = NdbTick_CurrentMillisecond();
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 j = 0; j<cnt; j++)
- {
- pool.getPtr(ptr, arr[cnt - j - 1]);
- ptr.p->do_stuff();
- pool.release(ptr);
- arr[cnt - j - 1] = RNIL;
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
-
- sum += (stop - start);
- }
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- if (tests & T_MIX)
- {
- Uint64 sum = 0;
- Uint64 start = NdbTick_CurrentMillisecond();
- Uint32 lseed = seed;
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 i = 0; i<loops * cnt; i++)
- {
- int pos = rand_r(&lseed) % cnt;
- ptr.i = arr[pos];
- if (ptr.i == RNIL)
- {
- pool.seize(ptr);
- arr[pos] = ptr.i;
- assert(ptr.i != RNIL);
- ptr.p->do_stuff();
- }
- else
- {
- pool.getPtr(ptr);
- ptr.p->do_stuff();
- pool.release(ptr);
- arr[pos] = RNIL;
- }
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
-
- for(Uint32 j = 0; j<cnt; j++)
- {
- ptr.i = arr[j];
- if (ptr.i != RNIL)
- {
- pool.getPtr(ptr);
- pool.release(ptr.i);
- }
- arr[j] = RNIL;
- }
-
- sum += (stop - start);
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- if (tests & T_GETPTR)
- {
- Uint32 lseed = seed;
- for(Uint32 j = 0; j<cnt; j++)
- {
- bool b = pool.seize(ptr);
- arr[j] = ptr.i;
- ptr.p->do_stuff();
- assert(b);
- }
-
- Uint64 sum = 0;
- Uint64 start = NdbTick_CurrentMillisecond();
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 i = 0; i<loops * cnt; i++)
- {
- int pos = rand_r(&lseed) % cnt;
- ptr.i = arr[pos];
- pool.getPtr(ptr);
- ptr.p->do_stuff();
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
-
- for(Uint32 j = 0; j<cnt; j++)
- {
- ptr.i = arr[j];
- pool.getPtr(ptr);
- ptr.p->do_stuff();
- pool.release(ptr.i);
- arr[j] = RNIL;
- }
-
- sum += (stop - start);
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- if (tests & T_FIFO)
- { // fifo
- Uint64 sum = 0;
- Uint64 start = NdbTick_CurrentMillisecond();
- CALLGRIND_TOGGLE_COLLECT();
- for(Uint32 i = 0; i<loops; i++)
- {
- Uint32 head = RNIL;
- Uint32 last = RNIL;
-
- Uint64 sum = 0;
- for(Uint32 j = 0; j<cnt; j++)
- {
- pool.seize(ptr);
- ptr.p->do_stuff();
- ptr.p->m_nextList = RNIL;
- if (head == RNIL)
- {
- head = ptr.i;
- }
- else
- {
- T* t = pool.getPtr(last);
- t->m_nextList = ptr.i;
- }
- last = ptr.i;
- }
-
- while (head != RNIL)
- {
- pool.getPtr(ptr, head);
- ptr.p->do_stuff();
- head = ptr.p->m_nextList;
- pool.release(ptr);
- }
- }
- CALLGRIND_TOGGLE_COLLECT();
- Uint64 stop = NdbTick_CurrentMillisecond();
- sum += (stop - start);
- printf(" ; %lld", sum); fflush(stdout);
- }
-
- ndbout_c("");
-}
-
-template <Uint32 sz>
-struct Rec {
- Uint32 m_data;
- Uint32 m_magic;
- Uint32 nextPool;
- Uint32 m_nextList;
- char m_cdata[sz-16];
-
- void do_stuff() {
- Uint32 sum = 0;
- Uint32 *ptr = (Uint32*)this;
- for(Uint32 i = 0; i<(sz >> 2); i++)
- sum += * ptr ++;
- m_data = sum;
- }
-};
-
-typedef Rec<32> Rec32;
-typedef Rec<36> Rec36;
-typedef Rec<56> Rec56;
-typedef Rec<224> Rec224;
-
-template <typename T>
-void test_ap(Uint32 cnt, Uint32 loop)
-{
- printf("AP ; %d ; %d", sizeof(T), (cnt * sizeof(T))>>10); fflush(stdout);
- ArrayPool<T> pool;
- init(pool, cnt);
- test_pool<T, ArrayPool<T> >(pool, cnt, loop);
-}
-
-template <typename T>
-void test_rw(Uint32 cnt, Uint32 loop)
-{
- printf("RW ; %d ; %d", sizeof(T), (cnt * sizeof(T))>>10); fflush(stdout);
- RecordPool<T, RWPool> pool;
- init(pool, cnt);
- test_pool<T, RecordPool<T, RWPool> >(pool, cnt, loop);
-}
-
-template <typename T>
-void test_wo(Uint32 cnt, Uint32 loop)
-{
- printf("WO ; %d ; %d", sizeof(T), (cnt * sizeof(T))>>10); fflush(stdout);
- RecordPool<T, WOPool> pool;
- init(pool, cnt);
- test_pool<T, RecordPool<T, WOPool> >(pool, cnt, loop);
-}
-
-#include <EventLogger.hpp>
-extern EventLogger g_eventLogger;
-
-int
-main(int argc, char **argv)
-{
- Uint32 loops = 300000;
- for (Uint32 i = 1 ; i<argc ; i++)
- {
- if (argc > i+1 && strcmp(argv[i], "-pools") == 0)
- {
- pools = 0;
- for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
- {
- char c = argv[i+1][j];
- if (c >= '0' && c <= '9')
- pools |= 1 << (c - '0');
- else
- pools |= 1 << (10 + (c - 'a'));
- }
- }
- else if (argc > i+1 && strcmp(argv[i], "-tests") == 0)
- {
- tests = 0;
- for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
- {
- char c = argv[i+1][j];
- if (c >= '0' && c <= '9')
- tests |= 1 << (c - '0');
- else
- tests |= 1 << (10 + (c - 'a'));
- }
- }
- else if (argc > i+1 && strcmp(argv[i], "-sizes") == 0)
- {
- sizes = 0;
- for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
- {
- char c = argv[i+1][j];
- if (c >= '0' && c <= '9')
- sizes |= 1 << (c - '0');
- else
- sizes |= 1 << (10 + (c - 'a'));
- }
- }
- else if (argc > i+1 && strcmp(argv[i], "-records") == 0)
- {
- records = 0;
- for (Uint32 j = 0; j<strlen(argv[i+1]); j++)
- {
- char c = argv[i+1][j];
- if (c >= '0' && c <= '9')
- records |= 1 << (c - '0');
- else
- records |= 1 << (10 + (c - 'a'));
- }
- }
- else if (argc > i+1 && strcmp(argv[i], "-loop") == 0)
- {
- loops = atoi(argv[i+1]);
- }
- }
-
- Resource_limit rl;
- rl.m_min = 0;
- rl.m_max = 10000;
- rl.m_resource_id = 0;
- mm.set_resource_limit(rl);
- if(!mm.init())
- {
- abort();
- }
-
- seed = time(0);
- Uint32 sz = 0;
- Uint32 cnt = 256;
-
- printf("pool ; rs ; ws");
- for (Uint32 i = 0; test_names[i] && i<31; i++)
- if (tests & (1 << i))
- printf(" ; %s", test_names[i]);
- ndbout_c("");
-
- while(cnt <= 1000000)
- {
- Uint32 loop = 768 * loops / cnt;
- if (sizes & (1 << sz))
- {
- if (records & 1)
- {
- if (pools & T_TEST_AP)
- test_ap<Rec32>(cnt, loop);
- if (pools & T_TEST_WO)
- test_wo<Rec32>(cnt, loop);
- if (pools & T_TEST_RW)
- test_rw<Rec32>(cnt, loop);
- }
- if (records & 2)
- {
- if (pools & T_TEST_AP)
- test_ap<Rec36>(cnt, loop);
- if (pools & T_TEST_WO)
- test_wo<Rec36>(cnt, loop);
- if (pools & T_TEST_RW)
- test_rw<Rec36>(cnt, loop);
- }
- if (records & 4)
- {
- if (pools & T_TEST_AP)
- test_ap<Rec56>(cnt, loop);
- if (pools & T_TEST_WO)
- test_wo<Rec56>(cnt, loop);
- if (pools & T_TEST_RW)
- test_rw<Rec56>(cnt, loop);
- }
- if (records & 8)
- {
- if (pools & T_TEST_AP)
- test_ap<Rec224>(cnt, loop);
- if (pools & T_TEST_WO)
- test_wo<Rec224>(cnt, loop);
- if (pools & T_TEST_RW)
- test_rw<Rec224>(cnt, loop);
- }
- }
-
- cnt += (512 << sz);
- sz++;
- }
-}
-
-Uint32 g_currentStartPhase;
-Uint32 g_start_type;
-NdbNodeBitmask g_nowait_nodes;
-
-void childExit(int code, Uint32 currentStartPhase)
-{
- abort();
-}
-
-void childAbort(int code, Uint32 currentStartPhase)
-{
- abort();
-}
-
-void childReportError(int error)
-{
- abort();
-}
-
-void
-UpgradeStartup::sendCmAppChg(Ndbcntr& cntr, Signal* signal, Uint32 startLevel){
-}
-
-void
-UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
-}
-
-void
-UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
-}
-
-void
-UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
-}
-
-#include <SimBlockList.hpp>
-
-void
-SimBlockList::unload()
-{
-
-}
-
-#define INSTANCE(X) \
-template void test_ap<X>(unsigned, unsigned);\
-template void test_wo<X>(unsigned, unsigned);\
-template void test_rw<X>(unsigned, unsigned);\
-template void test_pool<X, ArrayPool<X> >(ArrayPool<X>&, unsigned, unsigned);\
-template void test_pool<X, RecordPool<X, RWPool> >(RecordPool<X, RWPool>&, unsigned, unsigned); \
-template void test_pool<X, RecordPool<X, WOPool> >(RecordPool<X, WOPool>&, unsigned, unsigned);\
-template void init<X>(ArrayPool<X>&, unsigned);\
-template void init<X>(RecordPool<X, RWPool>&, unsigned);\
-template void init<X>(RecordPool<X, WOPool>&, unsigned)
-
-INSTANCE(Rec32);
-INSTANCE(Rec36);
-INSTANCE(Rec56);
-INSTANCE(Rec224);
-
diff --git a/storage/ndb/src/kernel/vm/mem.txt b/storage/ndb/src/kernel/vm/mem.txt
deleted file mode 100644
index 0ab0ff2a5a9..00000000000
--- a/storage/ndb/src/kernel/vm/mem.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-Structure
-
-Ndbd_mem_allocator
-Handles allocation on 32k blocks
-Provides Buddy allocation of max 8G objects
-
-SuperPool 8k (chunk size 64k)
-GroupPool - Metadata
- DICT::RopePool
-
-GroupPool - Disk operations
- TUP::Page request
- PGMAN::Page request
- LGMAN::Log waiter
- LGMAN::Log syncer
-
-GroupPool - Disk space
- Tsman::Datafile
- Tsman::Tablespace
- Lgman::Undofile
- Lgman::Logfilegroup
- TUP::Extent alloc info
-
-SuperPool 32k
- TUP Undo buffer
- SUMA GCI buffer
- Pgman::PageEntry
-
-Direct Ndbd_mem_allocator
- Pgman::GlobalPage -
- TUP PageMan
- Restore
- Backup
- Lgman::Logbuffer
diff --git a/storage/ndb/src/kernel/vm/ndbd_malloc.cpp b/storage/ndb/src/kernel/vm/ndbd_malloc.cpp
deleted file mode 100644
index 596b30e416b..00000000000
--- a/storage/ndb/src/kernel/vm/ndbd_malloc.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Copyright (c) 2003, 2005, 2007 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include "ndbd_malloc.hpp"
-#include <NdbMem.h>
-
-//#define TRACE_MALLOC
-#ifdef TRACE_MALLOC
-#include <stdio.h>
-#endif
-
-#ifdef TRACE_MALLOC
-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;
-}
-#endif
-
-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/storage/ndb/src/kernel/vm/ndbd_malloc.hpp b/storage/ndb/src/kernel/vm/ndbd_malloc.hpp
deleted file mode 100644
index 52f50daf2ee..00000000000
--- a/storage/ndb/src/kernel/vm/ndbd_malloc.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef NDBD_MALLOC_H
-#define NDBD_MALLOC_H
-
-/**
- * common memory allocation function for ndbd kernel
- */
-void *ndbd_malloc(size_t size);
-void ndbd_free(void *p, size_t size);
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp b/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp
deleted file mode 100644
index f96488ada9f..00000000000
--- a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp
+++ /dev/null
@@ -1,1016 +0,0 @@
-/* Copyright (c) 2003, 2006-2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-
-#include "ndbd_malloc_impl.hpp"
-#include <ndb_global.h>
-#include <EventLogger.hpp>
-
-#ifndef UNIT_TEST
-extern EventLogger g_eventLogger;
-#else
-extern EventLogger g_eventLogger;
-#endif
-
-static int f_method_idx = 0;
-#ifdef NDBD_MALLOC_METHOD_SBRK
-static const char * f_method = "SMsm";
-#else
-static const char * f_method = "MSms";
-#endif
-#define MAX_CHUNKS 10
-
-#define ZONE_LO 0
-#define ZONE_HI 1
-
-/**
- * POOL_RECORD_BITS == 13 => 32 - 13 = 19 bits for page
- */
-#define ZONE_LO_BOUND (1u << 19)
-
-struct InitChunk
-{
- Uint32 m_cnt;
- Uint32 m_start;
- Alloc_page* m_ptr;
-};
-
-#include <NdbOut.hpp>
-
-static
-bool
-do_malloc(Uint32 pages, InitChunk* chunk)
-{
- pages += 1;
- void * ptr = 0;
- Uint32 sz = pages;
-
-retry:
- char method = f_method[f_method_idx];
- switch(method){
- case 0:
- return false;
- case 'S':
- case 's':
- {
- ptr = 0;
- while (ptr == 0)
- {
- ptr = sbrk(sizeof(Alloc_page) * sz);
-
- if (ptr == (void*)-1)
- {
- if (method == 'S')
- {
- f_method_idx++;
- goto retry;
- }
-
- ptr = 0;
- sz = 1 + (9 * sz) / 10;
- if (pages >= 32 && sz < 32)
- {
- sz = pages;
- f_method_idx++;
- goto retry;
- }
- }
- }
- break;
- }
- case 'M':
- case 'm':
- {
- ptr = 0;
- while (ptr == 0)
- {
- ptr = malloc(sizeof(Alloc_page) * sz);
- if (ptr == 0)
- {
- if (method == 'M')
- {
- f_method_idx++;
- goto retry;
- }
-
- sz = 1 + (9 * sz) / 10;
- if (pages >= 32 && sz < 32)
- {
- f_method_idx++;
- goto retry;
- }
- }
- }
- break;
- }
- default:
- return false;
- }
-
- chunk->m_cnt = sz;
- chunk->m_ptr = (Alloc_page*)ptr;
- const UintPtr align = sizeof(Alloc_page) - 1;
- if (UintPtr(ptr) & align)
- {
- chunk->m_cnt--;
- chunk->m_ptr = (Alloc_page*)((UintPtr(ptr) + align) & ~align);
- }
-
-#ifdef UNIT_TEST
- ndbout_c("do_malloc(%d) -> %p %d", pages, ptr, chunk->m_cnt);
- if (1)
- {
- Uint32 sum = 0;
- Alloc_page* page = chunk->m_ptr;
- for (Uint32 i = 0; i<chunk->m_cnt; i++, page++)
- {
- page->m_data[0*1024] = 0;
- page->m_data[1*1024] = 0;
- page->m_data[2*1024] = 0;
- page->m_data[3*1024] = 0;
- page->m_data[4*1024] = 0;
- page->m_data[5*1024] = 0;
- page->m_data[6*1024] = 0;
- page->m_data[7*1024] = 0;
- }
- }
-#endif
-
- return true;
-}
-
-Uint32
-Ndbd_mem_manager::ndb_log2(Uint32 input)
-{
- input = input | (input >> 8);
- input = input | (input >> 4);
- input = input | (input >> 2);
- input = input | (input >> 1);
- Uint32 output = (input & 0x5555) + ((input >> 1) & 0x5555);
- output = (output & 0x3333) + ((output >> 2) & 0x3333);
- output = output + (output >> 4);
- output = (output & 0xf) + ((output >> 8) & 0xf);
- return output;
-}
-
-Ndbd_mem_manager::Ndbd_mem_manager()
-{
- m_base_page = 0;
- bzero(m_buddy_lists, sizeof(m_buddy_lists));
- bzero(m_resource_limit, sizeof(m_resource_limit));
-
- if (sizeof(Free_page_data) != (4 * (1 << FPD_2LOG)))
- {
- g_eventLogger.error("Invalid build, ndbd_malloc_impl.cpp:%d", __LINE__);
- abort();
- }
-}
-
-/**
- * m_min = reserved
- * m_curr = current
- * m_max = max alloc, 0 = no limit
- */
-
-void
-Ndbd_mem_manager::set_resource_limit(const Resource_limit& rl)
-{
- Uint32 id = rl.m_resource_id;
- assert(id < XX_RL_COUNT);
-
- Uint32 reserve = id ? rl.m_min : 0;
- Uint32 current_reserved = m_resource_limit[0].m_min;
-
- m_resource_limit[id] = rl;
- m_resource_limit[id].m_curr = 0;
- m_resource_limit[0].m_min = current_reserved + reserve;
-}
-
-bool
-Ndbd_mem_manager::get_resource_limit(Uint32 id, Resource_limit& rl) const
-{
- if (id < XX_RL_COUNT)
- {
- rl = m_resource_limit[id];
- return true;
- }
- return false;
-}
-
-static
-inline
-void
-check_resource_limits(Resource_limit* rl)
-{
-#ifdef VM_TRACE
- Uint32 curr = 0;
- Uint32 res_alloc = 0;
- Uint32 shared_alloc = 0;
- Uint32 sumres = 0;
- for (Uint32 i = 1; i<XX_RL_COUNT; i++)
- {
- curr += rl[i].m_curr;
- sumres += rl[i].m_min;
- assert(rl[i].m_max == 0 || rl[i].m_curr <= rl[i].m_max);
- if (rl[i].m_curr > rl[i].m_min)
- {
- shared_alloc += rl[i].m_curr - rl[i].m_min;
- res_alloc += rl[i].m_min;
- }
- else
- {
- res_alloc += rl[i].m_curr;
- }
- }
- assert(curr == rl[0].m_curr);
- assert(res_alloc + shared_alloc == curr);
- assert(res_alloc <= sumres);
- assert(sumres == res_alloc + rl[0].m_min);
- assert(rl[0].m_curr <= rl[0].m_max);
-#endif
-}
-
-
-bool
-Ndbd_mem_manager::init(bool alloc_less_memory)
-{
- assert(m_base_page == 0);
-
- Uint32 pages = 0;
- Uint32 max_page = 0;
- Uint32 reserved = m_resource_limit[0].m_min;
- if (m_resource_limit[0].m_max)
- {
- pages = m_resource_limit[0].m_max;
- }
- else
- {
- pages = m_resource_limit[0].m_min; // reserved
- }
-
- if (m_resource_limit[0].m_min == 0)
- {
- m_resource_limit[0].m_min = pages;
- }
-
- g_eventLogger.info("Ndbd_mem_manager::init(%d) min: %dMb initial: %dMb",
- alloc_less_memory,
- (sizeof(Alloc_page)*m_resource_limit[0].m_min)>>20,
- (sizeof(Alloc_page)*pages)>>20);
-
- if (pages == 0)
- {
- return 0;
- }
-
- /**
- * Do malloc
- */
-
- Uint32 cnt = 0;
- struct InitChunk chunks[MAX_CHUNKS];
- bzero(chunks, sizeof(chunks));
-
- Uint32 allocated = 0;
- while (cnt < MAX_CHUNKS && allocated < pages)
- {
- InitChunk chunk;
- LINT_INIT(chunk.m_start);
-
-#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
- memset((char*) &chunk, 0 , sizeof(chunk));
-#endif
-
- if (do_malloc(pages - allocated, &chunk))
- {
- Uint32 i = 0;
- for(; i<cnt ; i++)
- {
- if (chunk.m_ptr < chunks[i].m_ptr)
- {
- for (Uint32 j = cnt; j > i; j--)
- chunks[j] = chunks[j-1];
- break;
- }
- }
- cnt++;
- chunks[i] = chunk;
- allocated += chunk.m_cnt;
- }
- else
- {
- break;
- }
- }
-
- if (allocated < m_resource_limit[0].m_min)
- {
- g_eventLogger.
- error("Unable to alloc min memory from OS: min: %lldMb "
- " allocated: %lldMb",
- (Uint64)(sizeof(Alloc_page)*m_resource_limit[0].m_min) >> 20,
- (Uint64)(sizeof(Alloc_page)*allocated) >> 20);
- return false;
- }
- else if (allocated < pages)
- {
- g_eventLogger.
- warning("Unable to alloc requested memory from OS: min: %lldMb"
- " requested: %lldMb allocated: %lldMb",
- (Uint64)(sizeof(Alloc_page)*m_resource_limit[0].m_min)>>20,
- (Uint64)(sizeof(Alloc_page)*m_resource_limit[0].m_max)>>20,
- (Uint64)(sizeof(Alloc_page)*allocated)>>20);
- if (!alloc_less_memory)
- return false;
- }
-
- m_base_page = chunks[0].m_ptr;
-
- for (Uint32 i = 0; i<cnt; i++)
- {
- UintPtr start = UintPtr(chunks[i].m_ptr) - UintPtr(m_base_page);
- start >>= (2 + BMW_2LOG);
- UintPtr last = start + chunks[i].m_cnt;
- chunks[i].m_start = start;
- assert((Uint64(start) >> 32) == 0);
-
- if (last > max_page)
- max_page = last;
- }
-
- m_resource_limit[0].m_resource_id = max_page;
- m_resource_limit[0].m_min = reserved;
- m_resource_limit[0].m_max = 0;
-
- for (Uint32 i = 0; i<cnt; i++)
- {
- grow(chunks[i].m_start, chunks[i].m_cnt);
- }
-
- check_resource_limits(m_resource_limit);
-
- return true;
-}
-
-#include <NdbOut.hpp>
-
-void
-Ndbd_mem_manager::grow(Uint32 start, Uint32 cnt)
-{
- assert(cnt);
- Uint32 start_bmp = start >> BPP_2LOG;
- Uint32 last_bmp = (start + cnt - 1) >> BPP_2LOG;
-
-#if SIZEOF_CHARP == 4
- assert(start_bmp == 0 && last_bmp == 0);
-#endif
-
- if (start_bmp != last_bmp)
- {
- Uint32 tmp = ((start_bmp + 1) << BPP_2LOG) - start;
- grow(start, tmp);
- grow((start_bmp + 1) << BPP_2LOG, cnt - tmp);
- return;
- }
-
- if ((start + cnt) == ((start_bmp + 1) << BPP_2LOG))
- {
- cnt--; // last page is always marked as empty
- }
-
- for (Uint32 i = 0; i<m_used_bitmap_pages.size(); i++)
- if (m_used_bitmap_pages[i] == start_bmp)
- goto found;
-
- if (start != (start_bmp << BPP_2LOG))
- {
-
- ndbout_c("ndbd_malloc_impl.cpp:%d:grow(%d, %d) %d!=%d not using %uMb"
- " - Unable to use due to bitmap pages missaligned!!",
- __LINE__, start, cnt, start, (start_bmp << BPP_2LOG),
- (cnt >> (20 - 15)));
- g_eventLogger.error("ndbd_malloc_impl.cpp:%d:grow(%d, %d) not using %uMb"
- " - Unable to use due to bitmap pages missaligned!!",
- __LINE__, start, cnt,
- (cnt >> (20 - 15)));
-
- dump();
- return;
- }
-
-#ifdef UNIT_TEST
- ndbout_c("creating bitmap page %d", start_bmp);
-#endif
-
- {
- Alloc_page* bmp = m_base_page + start;
- memset(bmp, 0, sizeof(Alloc_page));
- cnt--;
- start++;
- }
- m_used_bitmap_pages.push_back(start_bmp);
-
-found:
- if (cnt)
- {
- m_resource_limit[0].m_curr += cnt;
- m_resource_limit[0].m_max += cnt;
- if (start >= ZONE_LO_BOUND)
- {
- Uint64 mbytes = ((Uint64(cnt) * 32) + 1023) / 1024;
- ndbout_c("Adding %uMb to ZONE_HI (%u,%u)", (Uint32)mbytes, start, cnt);
- release(start, cnt);
- }
- else if (start + cnt <= ZONE_LO_BOUND)
- {
- Uint64 mbytes = ((Uint64(cnt)*32) + 1023) / 1024;
- ndbout_c("Adding %uMb to ZONE_LO (%u,%u)", (Uint32)mbytes, start, cnt);
- release(start, cnt);
- }
- else
- {
- Uint32 cnt0 = ZONE_LO_BOUND - start;
- Uint32 cnt1 = start + cnt - ZONE_LO_BOUND;
- Uint64 mbytes0 = ((Uint64(cnt0)*32) + 1023) / 1024;
- Uint64 mbytes1 = ((Uint64(cnt1)*32) + 1023) / 1024;
- ndbout_c("Adding %uMb to ZONE_LO (split %u,%u)", (Uint32)mbytes0,
- start, cnt0);
- ndbout_c("Adding %uMb to ZONE_HI (split %u,%u)", (Uint32)mbytes1,
- ZONE_LO_BOUND, cnt1);
- release(start, cnt0);
- release(ZONE_LO_BOUND, cnt1);
- }
- }
-}
-
-void
-Ndbd_mem_manager::release(Uint32 start, Uint32 cnt)
-{
- assert(m_resource_limit[0].m_curr >= cnt);
- assert(start);
- m_resource_limit[0].m_curr -= cnt;
-
- set(start, start+cnt-1);
-
- Uint32 zone = start < ZONE_LO_BOUND ? 0 : 1;
- release_impl(zone, start, cnt);
-}
-
-void
-Ndbd_mem_manager::release_impl(Uint32 zone, Uint32 start, Uint32 cnt)
-{
- assert(start);
-
- Uint32 test = check(start-1, start+cnt);
- if (start != ZONE_LO_BOUND && test & 1)
- {
- Free_page_data *fd = get_free_page_data(m_base_page + start - 1,
- start - 1);
- Uint32 sz = fd->m_size;
- Uint32 left = start - sz;
- remove_free_list(zone, left, fd->m_list);
- cnt += sz;
- start = left;
- }
-
- Uint32 right = start + cnt;
- if (right != ZONE_LO_BOUND && test & 2)
- {
- Free_page_data *fd = get_free_page_data(m_base_page+right, right);
- Uint32 sz = fd->m_size;
- remove_free_list(zone, right, fd->m_list);
- cnt += sz;
- }
-
- insert_free_list(zone, start, cnt);
-}
-
-void
-Ndbd_mem_manager::alloc(AllocZone zone,
- Uint32* ret, Uint32 *pages, Uint32 min)
-{
- if (zone == NDB_ZONE_ANY)
- {
- Uint32 save = * pages;
- alloc_impl(ZONE_HI, ret, pages, min);
- if (*pages)
- return;
- * pages = save;
- }
-
- alloc_impl(ZONE_LO, ret, pages, min);
-}
-
-void
-Ndbd_mem_manager::alloc_impl(Uint32 zone,
- Uint32* ret, Uint32 *pages, Uint32 min)
-{
- Int32 i;
- Uint32 start;
- Uint32 cnt = * pages;
- Uint32 list = ndb_log2(cnt - 1);
-
- assert(cnt);
- assert(list <= 16);
-
- for (i = list; i < 16; i++)
- {
- if ((start = m_buddy_lists[zone][i]))
- {
-/* ---------------------------------------------------------------- */
-/* PROPER AMOUNT OF PAGES WERE FOUND. NOW SPLIT THE FOUND */
-/* AREA AND RETURN THE PART NOT NEEDED. */
-/* ---------------------------------------------------------------- */
-
- Uint32 sz = remove_free_list(zone, start, i);
- Uint32 extra = sz - cnt;
- assert(sz >= cnt);
- if (extra)
- {
- insert_free_list(zone, start + cnt, extra);
- clear_and_set(start, start+cnt-1);
- }
- else
- {
- clear(start, start+cnt-1);
- }
- * ret = start;
- assert(m_resource_limit[0].m_curr + cnt <= m_resource_limit[0].m_max);
- return;
- }
- }
-
- /**
- * Could not find in quaranteed list...
- * search in other lists...
- */
-
- Int32 min_list = ndb_log2(min - 1);
- assert((Int32)list >= min_list);
- for (i = list - 1; i >= min_list; i--)
- {
- if ((start = m_buddy_lists[zone][i]))
- {
- Uint32 sz = remove_free_list(zone, start, i);
- Uint32 extra = sz - cnt;
- if (sz > cnt)
- {
- insert_free_list(zone, start + cnt, extra);
- sz -= extra;
- clear_and_set(start, start+sz-1);
- }
- else
- {
- clear(start, start+sz-1);
- }
-
- * ret = start;
- * pages = sz;
- assert(m_resource_limit[0].m_curr + sz <= m_resource_limit[0].m_max);
- return;
- }
- }
- * pages = 0;
-}
-
-void
-Ndbd_mem_manager::insert_free_list(Uint32 zone, Uint32 start, Uint32 size)
-{
- Uint32 list = ndb_log2(size) - 1;
- Uint32 last = start + size - 1;
-
- Uint32 head = m_buddy_lists[zone][list];
- Free_page_data* fd_first = get_free_page_data(m_base_page+start,
- start);
- fd_first->m_list = list;
- fd_first->m_next = head;
- fd_first->m_prev = 0;
- fd_first->m_size = size;
-
- Free_page_data* fd_last = get_free_page_data(m_base_page+last, last);
- fd_last->m_list = list;
- fd_last->m_next = head;
- fd_last->m_prev = 0;
- fd_last->m_size = size;
-
- if (head)
- {
- Free_page_data* fd = get_free_page_data(m_base_page+head, head);
- assert(fd->m_prev == 0);
- assert(fd->m_list == list);
- fd->m_prev = start;
- }
-
- m_buddy_lists[zone][list] = start;
-}
-
-Uint32
-Ndbd_mem_manager::remove_free_list(Uint32 zone, Uint32 start, Uint32 list)
-{
- Free_page_data* fd = get_free_page_data(m_base_page+start, start);
- Uint32 size = fd->m_size;
- Uint32 next = fd->m_next;
- Uint32 prev = fd->m_prev;
- assert(fd->m_list == list);
-
- if (prev)
- {
- assert(m_buddy_lists[zone][list] != start);
- fd = get_free_page_data(m_base_page+prev, prev);
- assert(fd->m_next == start);
- assert(fd->m_list == list);
- fd->m_next = next;
- }
- else
- {
- assert(m_buddy_lists[zone][list] == start);
- m_buddy_lists[zone][list] = next;
- }
-
- if (next)
- {
- fd = get_free_page_data(m_base_page+next, next);
- assert(fd->m_list == list);
- assert(fd->m_prev == start);
- fd->m_prev = prev;
- }
-
- return size;
-}
-
-void
-Ndbd_mem_manager::dump() const
-{
- for (Uint32 zone = 0; zone < 2; zone ++)
- {
- for (Uint32 i = 0; i<16; i++)
- {
- printf(" list: %d - ", i);
- Uint32 head = m_buddy_lists[zone][i];
- while(head)
- {
- Free_page_data* fd = get_free_page_data(m_base_page+head, head);
- printf("[ i: %d prev %d next %d list %d size %d ] ",
- head, fd->m_prev, fd->m_next, fd->m_list, fd->m_size);
- head = fd->m_next;
- }
- printf("EOL\n");
- }
-
- for (Uint32 i = 0; i<XX_RL_COUNT; i++)
- {
- printf("ri: %d min: %d curr: %d max: %d\n",
- i,
- m_resource_limit[i].m_min,
- m_resource_limit[i].m_curr,
- m_resource_limit[i].m_max);
- }
- }
-}
-
-void*
-Ndbd_mem_manager::alloc_page(Uint32 type, Uint32* i, AllocZone zone)
-{
- Uint32 idx = type & RG_MASK;
- assert(idx && idx < XX_RL_COUNT);
- Resource_limit tot = m_resource_limit[0];
- Resource_limit rl = m_resource_limit[idx];
-
- Uint32 cnt = 1;
- Uint32 res0 = (rl.m_curr < rl.m_min) ? 1 : 0;
- Uint32 limit = (rl.m_max == 0 || rl.m_curr < rl.m_max) ? 0 : 1; // Over limit
- Uint32 free = (tot.m_min + tot.m_curr < tot.m_max) ? 1 : 0; // Has free
-
- assert(tot.m_min >= res0);
-
- if (likely(res0 == 1 || (limit == 0 && free == 1)))
- {
- alloc(zone, i, &cnt, 1);
- if (likely(cnt))
- {
- m_resource_limit[0].m_curr = tot.m_curr + cnt;
- m_resource_limit[0].m_min = tot.m_min - res0;
- m_resource_limit[idx].m_curr = rl.m_curr + cnt;
-
- check_resource_limits(m_resource_limit);
- return m_base_page + *i;
- }
- }
-
- return 0;
-}
-
-void
-Ndbd_mem_manager::release_page(Uint32 type, Uint32 i)
-{
- Uint32 idx = type & RG_MASK;
- assert(idx && idx < XX_RL_COUNT);
- Resource_limit tot = m_resource_limit[0];
- Resource_limit rl = m_resource_limit[idx];
-
- Uint32 sub = (rl.m_curr <= rl.m_min) ? 1 : 0; // Over min ?
- release(i, 1);
- m_resource_limit[0].m_curr = tot.m_curr - 1;
- m_resource_limit[0].m_min = tot.m_min + sub;
- m_resource_limit[idx].m_curr = rl.m_curr - 1;
-
- check_resource_limits(m_resource_limit);
-}
-
-void
-Ndbd_mem_manager::alloc_pages(Uint32 type, Uint32* i, Uint32 *cnt, Uint32 min)
-{
- Uint32 idx = type & RG_MASK;
- assert(idx && idx < XX_RL_COUNT);
- Resource_limit tot = m_resource_limit[0];
- Resource_limit rl = m_resource_limit[idx];
-
- Uint32 req = *cnt;
-
- Uint32 max = rl.m_max - rl.m_curr;
- Uint32 res0 = rl.m_min - rl.m_curr;
- Uint32 free_shared = tot.m_max - (tot.m_min + tot.m_curr);
-
- Uint32 res1;
- if (rl.m_curr + req <= rl.m_min)
- {
- // all is reserved...
- res0 = req;
- res1 = 0;
- }
- else
- {
- req = rl.m_max ? max : req;
- res0 = (rl.m_curr > rl.m_min) ? 0 : res0;
- res1 = req - res0;
-
- if (unlikely(res1 > free_shared))
- {
- res1 = free_shared;
- req = res0 + res1;
- }
- }
-
- // req = pages to alloc
- // res0 = portion that is reserved
- // res1 = part that is over reserver
- assert (res0 + res1 == req);
- assert (tot.m_min >= res0);
-
- if (likely(req))
- {
- // Hi order allocations can always use any zone
- alloc(NDB_ZONE_ANY, i, &req, 1);
- * cnt = req;
- if (unlikely(req < res0)) // Got min than what was reserved :-(
- {
- res0 = req;
- }
- assert(tot.m_min >= res0);
- assert(tot.m_curr + req <= tot.m_max);
-
- m_resource_limit[0].m_curr = tot.m_curr + req;
- m_resource_limit[0].m_min = tot.m_min - res0;
- m_resource_limit[idx].m_curr = rl.m_curr + req;
- check_resource_limits(m_resource_limit);
- return ;
- }
- * cnt = req;
- return;
-}
-
-void
-Ndbd_mem_manager::release_pages(Uint32 type, Uint32 i, Uint32 cnt)
-{
- Uint32 idx = type & RG_MASK;
- assert(idx && idx < XX_RL_COUNT);
- Resource_limit tot = m_resource_limit[0];
- Resource_limit rl = m_resource_limit[idx];
-
- release(i, cnt);
-
- Uint32 currnew = rl.m_curr - cnt;
- if (rl.m_curr > rl.m_min)
- {
- if (currnew < rl.m_min)
- {
- m_resource_limit[0].m_min = tot.m_min + (rl.m_min - currnew);
- }
- }
- else
- {
- m_resource_limit[0].m_min = tot.m_min + cnt;
- }
- m_resource_limit[0].m_curr = tot.m_curr - cnt;
- m_resource_limit[idx].m_curr = currnew;
- check_resource_limits(m_resource_limit);
-}
-
-#ifdef UNIT_TEST
-
-#include <Vector.hpp>
-#include <NdbTick.h>
-
-struct Chunk {
- Uint32 pageId;
- Uint32 pageCount;
-};
-
-struct Timer
-{
- Uint64 sum;
- Uint32 cnt;
-
- Timer() { sum = cnt = 0;}
-
- struct timeval st;
-
- void start() {
- gettimeofday(&st, 0);
- }
-
- Uint64 calc_diff() {
- struct timeval st2;
- gettimeofday(&st2, 0);
- Uint64 diff = st2.tv_sec;
- diff -= st.tv_sec;
- diff *= 1000000;
- diff += st2.tv_usec;
- diff -= st.tv_usec;
- return diff;
- }
-
- void stop() {
- add(calc_diff());
- }
-
- void add(Uint64 diff) { sum += diff; cnt++;}
-
- void print(const char * title) const {
- float ps = sum;
- ps /= cnt;
- printf("%s %fus/call %lld %d\n", title, ps, sum, cnt);
- }
-};
-
-int
-main(int argc, char** argv)
-{
- int sz = 1*32768;
- int run_time = 30;
- if (argc > 1)
- sz = 32*atoi(argv[1]);
-
- if (argc > 2)
- run_time = atoi(argv[2]);
-
- char buf[255];
- Timer timer[4];
- printf("Startar modul test av Page Manager %dMb %ds\n",
- (sz >> 5), run_time);
- g_eventLogger.createConsoleHandler();
- g_eventLogger.setCategory("keso");
- 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);
-
-#define DEBUG 0
-
- Ndbd_mem_manager mem;
- Resource_limit rl;
- rl.m_min = 0;
- rl.m_max = sz;
- rl.m_curr = 0;
- rl.m_resource_id = 0;
- mem.set_resource_limit(rl);
- rl.m_min = sz < 16384 ? sz : 16384;
- rl.m_max = 0;
- rl.m_resource_id = 1;
- mem.set_resource_limit(rl);
-
- mem.init();
- mem.dump();
- printf("pid: %d press enter to continue\n", getpid());
- fgets(buf, sizeof(buf), stdin);
- Vector<Chunk> chunks;
- time_t stop = time(0) + run_time;
- for(Uint32 i = 0; time(0) < stop; i++){
- //mem.dump();
-
- // Case
- Uint32 c = (rand() % 100);
- if (c < 50)
- {
- c = 0;
- }
- else if (c < 93)
- {
- c = 1;
- }
- else
- {
- c = 2;
- }
-
- Uint32 alloc = 1 + rand() % 3200;
-
- if(chunks.size() == 0 && c == 0)
- {
- c = 1 + rand() % 2;
- }
-
- if(DEBUG)
- printf("loop=%d ", i);
- switch(c){
- case 0:{ // Release
- const int ch = rand() % chunks.size();
- Chunk chunk = chunks[ch];
- chunks.erase(ch);
- timer[0].start();
- Uint64 start = NdbTick_CurrentMillisecond();
- mem.release(chunk.pageId, chunk.pageCount);
- timer[0].stop();
- if(DEBUG)
- printf(" release %d %d\n", chunk.pageId, chunk.pageCount);
- }
- break;
- case 2: { // Seize(n) - fail
- alloc += sz;
- // Fall through
- }
- case 1: { // Seize(n) (success)
- Chunk chunk;
- chunk.pageCount = alloc;
- if (DEBUG)
- {
- printf(" alloc %d -> ", alloc); fflush(stdout);
- }
- timer[0].start();
- mem.alloc(&chunk.pageId, &chunk.pageCount, 1);
- Uint64 diff = timer[0].calc_diff();
-
- if (DEBUG)
- printf("%d %d", chunk.pageId, chunk.pageCount);
- assert(chunk.pageCount <= alloc);
- if(chunk.pageCount != 0){
- chunks.push_back(chunk);
- if(chunk.pageCount != alloc) {
- timer[2].add(diff);
- if (DEBUG)
- printf(" - Tried to allocate %d - only allocated %d - free: %d",
- alloc, chunk.pageCount, 0);
- }
- else
- {
- timer[1].add(diff);
- }
- } else {
- timer[3].add(diff);
- if (DEBUG)
- printf(" Failed to alloc %d pages with %d pages free",
- alloc, 0);
- }
- if (DEBUG)
- printf("\n");
- }
- break;
- }
- }
- if (!DEBUG)
- while(chunks.size() > 0){
- Chunk chunk = chunks.back();
- mem.release(chunk.pageId, chunk.pageCount);
- chunks.erase(chunks.size() - 1);
- }
-
- const char *title[] = {
- "release ",
- "alloc full",
- "alloc part",
- "alloc fail"
- };
- for(Uint32 i = 0; i<4; i++)
- timer[i].print(title[i]);
-
- mem.dump();
-}
-
-template class Vector<Chunk>;
-
-#endif
-template class Vector<Uint32>;
diff --git a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp b/storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp
deleted file mode 100644
index e820d1303d3..00000000000
--- a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/* Copyright (c) 2003, 2006, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef NDBD_MALLOC_IMPL_H
-#define NDBD_MALLOC_IMPL_H
-
-#include <kernel_types.h>
-#include <Bitmask.hpp>
-#include <assert.h>
-#include "Pool.hpp"
-#include <Vector.hpp>
-
-/**
- * 13 -> 8192 words -> 32768 bytes
- * 18 -> 262144 words -> 1M
- */
-#define BMW_2LOG 13
-#define BITMAP_WORDS (1 << BMW_2LOG)
-
-#define BPP_2LOG (BMW_2LOG + 5)
-#define SPACE_PER_BMP_2LOG ((2 + BMW_2LOG) + BPP_2LOG)
-
-//#define BITMAP_WORDS GLOBAL_PAGE_SIZE_WORDS
-
-struct Alloc_page
-{
- Uint32 m_data[BITMAP_WORDS];
-};
-
-struct Free_page_data
-{
- Uint32 m_list;
- Uint32 m_next;
- Uint32 m_prev;
- Uint32 m_size;
-};
-
-#define FPD_2LOG 2
-
-class Ndbd_mem_manager
-{
-public:
- Ndbd_mem_manager();
-
- void set_resource_limit(const Resource_limit& rl);
- bool get_resource_limit(Uint32 id, Resource_limit& rl) const;
-
- bool init(bool allow_alloc_less_than_requested = true);
- void* get_memroot() const { return (void*)m_base_page;}
-
- void dump() const ;
-
- enum AllocZone
- {
- NDB_ZONE_LO = 0, // Only allocate with page_id < (1 << 13)
- NDB_ZONE_ANY = 1 // Allocate with any page_id
- };
-
- void* alloc_page(Uint32 type, Uint32* i, enum AllocZone);
- void release_page(Uint32 type, Uint32 i);
-
- void alloc_pages(Uint32 type, Uint32* i, Uint32 *cnt, Uint32 min = 1);
- void release_pages(Uint32 type, Uint32 i, Uint32 cnt);
-
- /**
- * Compute 2log of size
- * @note size = 0 -> 0
- * @note size > 65536 -> 16
- */
- static Uint32 ndb_log2(Uint32 size);
-
-private:
- void grow(Uint32 start, Uint32 cnt);
-
-#define XX_RL_COUNT 4
- /**
- * Return pointer to free page data on page
- */
- static Free_page_data* get_free_page_data(Alloc_page*, Uint32 idx);
- Vector<Uint32> m_used_bitmap_pages;
-
- Uint32 m_buddy_lists[2][16];
- Resource_limit m_resource_limit[XX_RL_COUNT]; // RG_COUNT in record_types.hpp
- Alloc_page * m_base_page;
-
- void release_impl(Uint32 zone, Uint32 start, Uint32 cnt);
- void insert_free_list(Uint32 zone, Uint32 start, Uint32 cnt);
- Uint32 remove_free_list(Uint32 zone, Uint32 start, Uint32 list);
-
- void set(Uint32 first, Uint32 last);
- void clear(Uint32 first, Uint32 last);
- void clear_and_set(Uint32 first, Uint32 last);
- Uint32 check(Uint32 first, Uint32 last);
-
- void alloc(AllocZone, Uint32* ret, Uint32 *pages, Uint32 min_requested);
- void alloc_impl(Uint32 zone, Uint32* ret, Uint32 *pages, Uint32 min);
- void release(Uint32 start, Uint32 cnt);
-};
-
-inline
-Free_page_data*
-Ndbd_mem_manager::get_free_page_data(Alloc_page* ptr, Uint32 idx)
-{
- assert(idx & ((1 << BPP_2LOG) - 1));
- assert((idx & ((1 << BPP_2LOG) - 1)) != ((1 << BPP_2LOG) - 1));
-
- return (Free_page_data*)
- (ptr->m_data + ((idx & ((BITMAP_WORDS >> FPD_2LOG) - 1)) << FPD_2LOG));
-}
-
-inline
-void
-Ndbd_mem_manager::set(Uint32 first, Uint32 last)
-{
- Alloc_page * ptr = m_base_page;
-#if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
- Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
- assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
- assert(bmp < m_resource_limit[0].m_resource_id);
-
- first -= bmp;
- last -= bmp;
- ptr += bmp;
-#endif
- BitmaskImpl::set(BITMAP_WORDS, ptr->m_data, first);
- BitmaskImpl::set(BITMAP_WORDS, ptr->m_data, last);
-}
-
-inline
-void
-Ndbd_mem_manager::clear(Uint32 first, Uint32 last)
-{
- Alloc_page * ptr = m_base_page;
-#if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
- Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
- assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
- assert(bmp < m_resource_limit[0].m_resource_id);
-
- first -= bmp;
- last -= bmp;
- ptr += bmp;
-#endif
- BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, first);
- BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, last);
-}
-
-inline
-void
-Ndbd_mem_manager::clear_and_set(Uint32 first, Uint32 last)
-{
- Alloc_page * ptr = m_base_page;
-#if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
- Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
- assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
- assert(bmp < m_resource_limit[0].m_resource_id);
-
- first -= bmp;
- last -= bmp;
- ptr += bmp;
-#endif
- BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, first);
- BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, last);
- BitmaskImpl::set(BITMAP_WORDS, ptr->m_data, last+1);
-}
-
-inline
-Uint32
-Ndbd_mem_manager::check(Uint32 first, Uint32 last)
-{
- Uint32 ret = 0;
- Alloc_page * ptr = m_base_page;
-#if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
- Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
- assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
- assert(bmp < m_resource_limit[0].m_resource_id);
-
- first -= bmp;
- last -= bmp;
- ptr += bmp;
-#endif
- ret |= BitmaskImpl::get(BITMAP_WORDS, ptr->m_data, first) << 0;
- ret |= BitmaskImpl::get(BITMAP_WORDS, ptr->m_data, last) << 1;
- return ret;
-}
-
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/pc.hpp b/storage/ndb/src/kernel/vm/pc.hpp
deleted file mode 100644
index 8be09ca91e4..00000000000
--- a/storage/ndb/src/kernel/vm/pc.hpp
+++ /dev/null
@@ -1,237 +0,0 @@
-/* Copyright (c) 2003-2006, 2008 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#ifndef PC_H
-#define PC_H
-
-
-#include "Emulator.hpp"
-#include <NdbOut.hpp>
-#include <ndb_limits.h>
-
-#ifdef NO_EMULATED_JAM
-
-#define jam()
-#define jamLine(line)
-#define jamEntry()
-#define jamEntryLine(line)
-
-#else
-#ifdef NDB_WIN32
-
-#define jam() { \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)(theEmulatedJam + tEmulatedJamIndex) = __LINE__; \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-#define jamLine(line) { \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)(theEmulatedJam + tEmulatedJamIndex) = line; \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-#define jamEntry() { \
- theEmulatedJamBlockNumber = number(); \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)(theEmulatedJam + tEmulatedJamIndex) = \
- ((theEmulatedJamBlockNumber << 20) | __LINE__); \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-#define jamEntryLine(line) { \
- theEmulatedJamBlockNumber = number(); \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)(theEmulatedJam + tEmulatedJamIndex) = \
- ((theEmulatedJamBlockNumber << 20) | (line)); \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-
-#else
-
-#define jam() { \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)((UintPtr)theEmulatedJam + (Uint32)tEmulatedJamIndex) = __LINE__; \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-#define jamLine(line) { \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)((UintPtr)theEmulatedJam + (Uint32)tEmulatedJamIndex) = line; \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-#define jamEntry() { \
- theEmulatedJamBlockNumber = number(); \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)((UintPtr)theEmulatedJam + (Uint32)tEmulatedJamIndex) = \
- ((theEmulatedJamBlockNumber << 20) | __LINE__); \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-#define jamEntryLine(line) { \
- theEmulatedJamBlockNumber = number(); \
- Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \
- *(Uint32*)((UintPtr)theEmulatedJam + (Uint32)tEmulatedJamIndex) = \
- ((theEmulatedJamBlockNumber << 20) | (line)); \
- theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; }
-
-#endif
-
-#endif
-#ifndef NDB_OPT
-#define ptrCheck(ptr, limit, rec) if (ptr.i < (limit)) ptr.p = &rec[ptr.i]; else ptr.p = NULL
-
-/**
- * Sets the p-value of a ptr-struct to be a pointer to record no i
- * (where i is the i-value of the ptr-struct)
- *
- * @param ptr ptr-struct with a set i-value (the p-value in this gets set)
- * @param limit max no of records in rec
- * @param rec pointer to first record in an array of records
- */
-#define ptrCheckGuardErr(ptr, limit, rec, error) {\
- UintR TxxzLimit; \
- TxxzLimit = (limit); \
- UintR TxxxPtr; \
- TxxxPtr = ptr.i; \
- ptr.p = &rec[TxxxPtr]; \
- if (TxxxPtr < (TxxzLimit)) { \
- ; \
- } else { \
- progError(__LINE__, error, __FILE__); \
- }}
-#define ptrAss(ptr, rec) ptr.p = &rec[ptr.i]
-#define ptrNull(ptr) ptr.p = NULL
-#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 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 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
-
-/* ------------------------------------------------------------------------- */
-/* COMMONLY USED CONSTANTS. */
-/* ------------------------------------------------------------------------- */
-#define ZFALSE 0
-#define ZTRUE 1
-#define ZSET 1
-#define ZOK 0
-#define ZNOT_OK 1
-#define ZCLOSE_FILE 2
-#define ZNIL 0xffff
-#define Z8NIL 255
-
-/* ------------------------------------------------------------------------- */
-// Number of fragments stored per node. Should be settable on a table basis
-// in future version since small tables want small value and large tables
-// need large value.
-/* ------------------------------------------------------------------------- */
-#define NO_OF_FRAG_PER_NODE 1
-#define MAX_FRAG_PER_NODE 8
-
-/**
-* DIH allocates fragments in chunk for fast find of fragment record.
-* These parameters define chunk size and log of chunk size.
-*/
-#define NO_OF_FRAGS_PER_CHUNK 4
-#define LOG_NO_OF_FRAGS_PER_CHUNK 2
-
-/* ---------------------------------------------------------------- */
-// To avoid synching too big chunks at a time we synch after writing
-// a certain number of data/UNDO pages. (e.g. 2 MBytes).
-/* ---------------------------------------------------------------- */
-#define MAX_REDO_PAGES_WITHOUT_SYNCH 32
-
-/* ------------------------------------------------------------------ */
-// We have these constants to ensure that we can easily change the
-// parallelism of node recovery and the amount of scan
-// operations needed for node recoovery.
-/* ------------------------------------------------------------------ */
-#define MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT 6000
-#define MAGIC_CONSTANT 56
-#define NODE_RECOVERY_SCAN_OP_RECORDS \
- (4 + ((4*MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT)/ \
- ((MAGIC_CONSTANT + 2) * 5)))
-
-#ifdef NO_CHECKPOINT
-#define NO_LCP
-#define NO_GCP
-#endif
-
-/**
- * Ndb kernel blocks assertion handling
- *
- * Two type of assertions:
- * - ndbassert - Only used when compiling VM_TRACE
- * - ndbrequire - Always checked
- *
- * If a ndbassert/ndbrequire fails, the system will
- * shutdown and generate an error log
- *
- *
- * NOTE these may only be used within blocks
- */
-#if defined VM_TRACE
-#define ndbassert(check) \
- if(likely(check)){ \
- } else { \
- progError(__LINE__, NDBD_EXIT_NDBASSERT, __FILE__); \
- }
-#else
-#define ndbassert(check)
-#endif
-
-#define ndbrequireErr(check, error) \
- if(likely(check)){ \
- } else { \
- progError(__LINE__, error, __FILE__); \
- }
-
-#define ndbrequire(check) \
- ndbrequireErr(check, NDBD_EXIT_NDBREQUIRE)
-
-#define CRASH_INSERTION(errorType) \
- if (!ERROR_INSERTED((errorType))) { \
- } else { \
- progError(__LINE__, NDBD_EXIT_ERROR_INSERT, __FILE__); \
- }
-
-#define CRASH_INSERTION2(errorNum, condition) \
- if (!(ERROR_INSERTED(errorNum) && condition)) { \
- } else { \
- progError(__LINE__, NDBD_EXIT_ERROR_INSERT, __FILE__); \
- }
-
-#define MEMCOPY_PAGE(to, from, page_size_in_bytes) \
- memcpy((void*)(to), (void*)(from), (size_t)(page_size_in_bytes));
-#define MEMCOPY_NO_WORDS(to, from, no_of_words) \
- memcpy((to), (void*)(from), (size_t)((no_of_words) << 2));
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/testCopy/Makefile b/storage/ndb/src/kernel/vm/testCopy/Makefile
deleted file mode 100644
index 5abd93eb74f..00000000000
--- a/storage/ndb/src/kernel/vm/testCopy/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-BIN_TARGET := testCopy
-
-SOURCES = testCopy.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/storage/ndb/src/kernel/vm/testCopy/rr.cpp b/storage/ndb/src/kernel/vm/testCopy/rr.cpp
deleted file mode 100644
index bb0521357ea..00000000000
--- a/storage/ndb/src/kernel/vm/testCopy/rr.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-
-#include <sched.h>
-
-int
-main(int argc, char * const argv[]){
- struct sched_param p;
- p.sched_priority = 1;
-
- int ret = sched_setscheduler(getpid(), SCHED_RR, &p);
- printf("ref = %d\n", ret);
-
- execv(argv[1], &argv[1]);
- return 0;
-}
diff --git a/storage/ndb/src/kernel/vm/testCopy/testCopy.cpp b/storage/ndb/src/kernel/vm/testCopy/testCopy.cpp
deleted file mode 100644
index ef7f3277174..00000000000
--- a/storage/ndb/src/kernel/vm/testCopy/testCopy.cpp
+++ /dev/null
@@ -1,341 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-#include <NdbOut.hpp>
-#include <NdbTick.h>
-
-#ifdef __NDB_FORTE6
-#define HAND
-bool hand = true;
-#else
-bool hand = false;
-#endif
-
-struct Data7 {
- Uint32 data[7];
-
-#ifdef HAND
- inline Data7& operator=(const Data7 & o){
- Uint32 t0 = o.data[0];
- Uint32 t1 = o.data[1];
- Uint32 t2 = o.data[2];
- Uint32 t3 = o.data[3];
- Uint32 t4 = o.data[4];
- Uint32 t5 = o.data[5];
- Uint32 t6 = o.data[6];
- data[0] = t0;
- data[1] = t1;
- data[2] = t2;
- data[3] = t3;
- data[4] = t4;
- data[5] = t5;
- data[6] = t6;
- return * this;
- }
-#endif
-};
-
-struct Data25 {
- Uint32 data[25];
-};
-
-struct TestSignal {
-
- Data7 head;
- Data25 data;
-};
-
-Uint32 g_time = 3000;
-Uint32 g_count = 8*2048;
-
-TestSignal g_signal;
-TestSignal * g_jobBuffer;
-
-template<Uint32 LEN>
-inline
-void
-MEMCOPY(Uint32 * to, const Uint32 * from){
- Uint32 t0 ;
- Uint32 t1 ;
- Uint32 t2 ;
- Uint32 t3 ;
- Uint32 len = LEN;
- while(len > 4){
- t0 = from[0];
- t1 = from[1];
- t2 = from[2];
- t3 = from[3];
-
- to[0] = t0;
- to[1] = t1;
- to[2] = t2;
- to[3] = t3;
-
-
- to += 4;
- from += 4;
- len -= 4;
- }
-
- //ndbout_c("len = %d", len);
-
- t0 = from[0];
- t1 = from[1];
- t2 = from[2];
- switch(len & 3){
- case 3:
- //ndbout_c("3");
- to[2] = t2;
- case 2:
- //ndbout_c("2");
- to[1] = t1;
- case 1:
- //ndbout_c("1");
- to[0] = t0;
- }
-
-}
-
-inline
-void
-MEMCOPY_NO_WORDS(Uint32 * to, const Uint32 * from, Uint32 len){
- Uint32 t0 ;
- Uint32 t1 ;
- Uint32 t2 ;
- Uint32 t3 ;
- while(len > 4){
- t0 = from[0];
- t1 = from[1];
- t2 = from[2];
- t3 = from[3];
-
- to[0] = t0;
- to[1] = t1;
- to[2] = t2;
- to[3] = t3;
-
-
- to += 4;
- from += 4;
- len -= 4;
- }
-
- //ndbout_c("len = %d", len);
-
- t0 = from[0];
- t1 = from[1];
- t2 = from[2];
- switch(len & 3){
- case 3:
- //ndbout_c("3");
- to[2] = t2;
- case 2:
- //ndbout_c("2");
- to[1] = t1;
- case 1:
- //ndbout_c("1");
- to[0] = t0;
- }
-}
-
-inline
-void
-copy1(Uint32 i, TestSignal & ts){
- TestSignal & dst = g_jobBuffer[i];
-
- Uint32 t0 = ts.head.data[0];
- Uint32 t1 = ts.head.data[1];
- Uint32 t2 = ts.head.data[2];
- Uint32 t3 = ts.head.data[3];
- Uint32 t4 = ts.head.data[4];
- Uint32 t5 = ts.head.data[5];
- Uint32 t6 = ts.head.data[6];
-
- dst.head.data[0] = t0;
- dst.head.data[1] = t1;
- dst.head.data[2] = t2;
- dst.head.data[3] = t3;
- dst.head.data[4] = t4;
- dst.head.data[5] = t5;
- dst.head.data[6] = t6;
-}
-
-
-
-inline
-void
-copy2(Uint32 i, TestSignal & ts){
- TestSignal & dst = g_jobBuffer[i];
-
- Uint32 t0 = ts.head.data[0];
- Uint32 t1 = ts.head.data[1];
- Uint32 t2 = ts.head.data[2];
- Uint32 t3 = ts.head.data[3];
-
- dst.head.data[0] = t0;
- dst.head.data[1] = t1;
- dst.head.data[2] = t2;
- dst.head.data[3] = t3;
-
- Uint32 t4 = ts.head.data[4];
- Uint32 t5 = ts.head.data[5];
- Uint32 t6 = ts.head.data[6];
-
- dst.head.data[4] = t4;
- dst.head.data[5] = t5;
- dst.head.data[6] = t6;
-}
-
-inline
-void
-copy3(Uint32 i, TestSignal & ts){
- TestSignal & dst = g_jobBuffer[i];
-
- dst.head = ts.head;
-}
-
-inline
-void
-copy4(Uint32 i, TestSignal & ts){
- TestSignal & dst = g_jobBuffer[i];
-
- memcpy(&dst.head.data[0], &ts.head.data[0], sizeof(Data7));
-}
-
-inline
-void
-copy5(Uint32 i, TestSignal & ts){
- TestSignal & dst = g_jobBuffer[i];
-
- MEMCOPY_NO_WORDS(&dst.head.data[0], &ts.head.data[0], 7);
-}
-
-inline
-void
-copy6(Uint32 i, TestSignal & ts){
- TestSignal & dst = g_jobBuffer[i];
-
- MEMCOPY<7>(&dst.head.data[0], &ts.head.data[0]);
-}
-
-inline
-void
-copy7(Uint32 i, TestSignal & ts){
- TestSignal & dst = g_jobBuffer[i];
-
-#if (__GNUC__ >= 3 ) || (__GNUC__ == 2 && __GNUC_MINOR >= 95)
- __builtin_memcpy(&dst.head.data[0], &ts.head.data[0], sizeof(Data7));
-#else
- dst.head = ts.head;
-#endif
-}
-
-template<void (* C)(Uint32 i, TestSignal & ts)>
-int
-doTime(Uint32 ms){
-
- Uint64 ms1, ms2;
- const Uint32 count = g_count;
- for(Uint32 i = 0; i<count; i++)
- C(i, g_signal);
- for(Uint32 i = 0; i<count; i++)
- C(i, g_signal);
-
- Uint32 laps = 0;
-
- ms1 = NdbTick_CurrentMillisecond();
- do {
- for(int j = 100; j>= 0; j--)
- for(Uint32 i = 0; i<count; i++){
- C(i, g_signal);
- }
- ms2 = NdbTick_CurrentMillisecond();
- laps += 100;
- } while((ms2 - ms1) < ms);
-
- return laps;
-}
-
-
-template<void (* C)(Uint32 i, TestSignal & ts)>
-void doCopyLap(Uint32 laps, const char * title){
-
- Uint64 ms1, ms2;
- const Uint32 count = g_count;
- for(Uint32 i = 0; i<count; i++)
- C(i, g_signal);
- laps--;
- for(Uint32 i = 0; i<count; i++)
- C(i, g_signal);
- laps--;
-
- Uint32 div = laps;
-
- ms1 = NdbTick_CurrentMillisecond();
- while(laps > 0){
- for(Uint32 i = 0; i<count; i++){
-#if (__GNUC__ == 3 && __GNUC_MINOR >= 1)
- _builtin_prefetch(&g_jobBuffer[i], 1, 0);
-#endif
- C(i, g_signal);
- }
- laps--;
- }
- ms2 = NdbTick_CurrentMillisecond();
-
- ms2 -= ms1;
- Uint32 diff = ms2;
- ndbout_c("%s : %d laps in %d millis => %d copies/sec",
- title, div, diff, (1000*div*g_count+(diff/2))/diff);
-}
-
-int
-main(int argc, const char ** argv){
-
- if(argc > 1)
- g_count = atoi(argv[1]);
-
- if(argc > 2)
- g_time = atoi(argv[2]);
-
- ndbout_c("Using %d entries => %d kB ",
- g_count,
- g_count * sizeof(TestSignal) / 1024);
- ndbout_c("Testing for %d ms", g_time);
-
- ndbout_c("Using %s copy-constructor",
- (hand ? "hand written" : "compiler generated"));
-
- g_jobBuffer = new TestSignal[g_count + 1];
- for(int i = 0; i<10; i++)
- memset(g_jobBuffer, 0, g_count * sizeof(TestSignal));
-
- int laps = doTime<copy2>(g_time);
- ndbout_c("Laps = %d", laps);
-
- doCopyLap<copy2>(laps, "4 t-variables");
- doCopyLap<copy3>(laps, "copy constr. ");
- doCopyLap<copy1>(laps, "7 t-variables");
- doCopyLap<copy4>(laps, "mem copy ");
- doCopyLap<copy5>(laps, "mem copy hand");
- doCopyLap<copy6>(laps, "mem copy temp");
- doCopyLap<copy7>(laps, "mem copy gcc ");
-
- delete[] g_jobBuffer;
- return 0;
-}
diff --git a/storage/ndb/src/kernel/vm/testDataBuffer/Makefile b/storage/ndb/src/kernel/vm/testDataBuffer/Makefile
deleted file mode 100644
index 693989dfe3c..00000000000
--- a/storage/ndb/src/kernel/vm/testDataBuffer/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-BIN_TARGET := testKernelDataBuffer
-BIN_TARGET_ARCHIVES := general portlib
-
-SOURCES = testDataBuffer.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/storage/ndb/src/kernel/vm/testDataBuffer/testDataBuffer.cpp b/storage/ndb/src/kernel/vm/testDataBuffer/testDataBuffer.cpp
deleted file mode 100644
index 03233f72ff8..00000000000
--- a/storage/ndb/src/kernel/vm/testDataBuffer/testDataBuffer.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-#include <NdbTick.h>
-#include <DataBuffer.hpp>
-
-#undef test
-
-struct Buffer {
- Buffer(Uint32 size){ m_sz = size; buffer = new Uint32[m_sz]; m_len = 0;}
- ~Buffer(){ delete [] buffer;}
-
- Uint32 m_sz;
- Uint32 m_len;
- Uint32 * buffer;
-};
-
-inline
-void
-require(bool b){
- if(!b)
- abort();
-}
-
-template<Uint32 sz>
-void
-compare(DataBuffer<sz> & db, Buffer & buf){
- typename DataBuffer<sz>::DataBufferIterator it;
- db.first(it);
- for(Uint32 i = 0; i<buf.m_len; i++){
- if(buf.buffer[i] != * it.data){
- db.print(stdout);
- abort();
- }
- db.next(it);
- }
-
- for(Uint32 i = 0; i<buf.m_len; i++){
- if(!db.position(it, i))
- abort();
- if(buf.buffer[i] != * it.data){
- db.print(stdout);
- abort();
- }
- }
-}
-
-template<Uint32 sz>
-void
-test(Uint32 loops, Uint32 iter){
-
- ndbout_c("DataBuffer<%d> loops=%d iter=%d", sz, loops, iter);
-
- while(loops-- > 0){
- Uint32 size = sz*((10 + (rand() % (10 * sz)) + sz - 1)/sz);
-
- typename DataBuffer<sz>::DataBufferPool thePool;
- typename DataBuffer<sz>::DataBufferIterator it;
- DataBuffer<sz> db(thePool);
-
- thePool.setSize((size + sz - 1) / sz);
- Buffer buf(size);
-
- bool testOverRun = true;
-
- for(Uint32 i = 0; i<iter; i++){
- Uint32 c = (rand() % (testOverRun ? 7 : 4));
- Uint32 free = (size - db.getSize());
- Uint32 alloc = 0;
- if(free == 0){
- c = (testOverRun ? c : 0);
- if(c >= 1 && c <= 3)
- c += 3;
- }
-
- if(free <= 1)
- alloc = 1;
- else
- alloc = 1 + (rand() % (free - 1));
-
- //ndbout_c("iter=%d case=%d free=%d alloc=%d", i, c, free, alloc);
- switch(c){
- case 0: // Release
- db.first(it);
- for(; !it.curr.isNull(); db.next(it))
- * it.data = 0;
-
- db.release();
- buf.m_len = 0;
- break;
- case 1:{ // Append (success)
- for(Uint32 i = 0; i<alloc; i++)
- buf.buffer[buf.m_len + i] = buf.m_len + i;//rand();
-
- require(db.append(&buf.buffer[buf.m_len], alloc));
- buf.m_len += alloc;
- break;
- }
- case 2: { // Seize(1) (success)
- for(Uint32 i = 0; i<alloc; i++){
- buf.buffer[buf.m_len + i] = buf.m_len + i;//rand();
- require(db.seize(1));
- require(db.position(it, db.getSize()-1));
- * it.data = buf.buffer[buf.m_len + i];
- }
- buf.m_len += alloc;
- break;
- }
- case 3: { // Seize(n) (success)
- for(Uint32 i = 0; i<alloc; i++){
- buf.buffer[buf.m_len + i] = buf.m_len + i;//rand();
- }
- Uint32 pos = db.getSize();
- require(db.seize(alloc));
- require(db.position(it, pos));
- for(Uint32 i = 0; i<alloc; i++){
- * it.data = buf.buffer[buf.m_len + i];
- db.next(it);
- }
- buf.m_len += alloc;
- break;
- }
- case 4: { // Append fail
- require(!db.append(buf.buffer, alloc + free));
- require(db.getSize() == 0);
- buf.m_len = 0;
- break;
- }
- case 5: { // Seize(1) - fail
- for(Uint32 i = 0; i<free; i++){
- require(db.seize(1));
- }
-
- require(!db.seize(1));
- require(db.getSize() == 0);
- buf.m_len = 0;
- break;
- }
- case 6: { // Seize(n) - fail
- require(!db.seize(alloc + free));
- require(db.getSize() == 0);
- buf.m_len = 0;
- break;
- }
- }
- compare(db, buf);
- }
- }
-}
-
-int
-main(void){
-
- srand(NdbTick_CurrentMillisecond());
-
-
- test<1>(1000, 1000);
- test<11>(1000, 1000);
- test<15>(1000, 1000);
- test<16>(1000, 1000);
- test<17>(1000, 1000);
-#if 0
-#endif
- return 0;
-}
-
-void
-ErrorReporter::handleAssert(const char * msg, const char * file, int line)
-{
- ndbout << "ErrorReporter::handleAssert activated - "
- << " line= " << line << endl;
- abort();
-}
diff --git a/storage/ndb/src/kernel/vm/testLongSig/Makefile b/storage/ndb/src/kernel/vm/testLongSig/Makefile
deleted file mode 100644
index ecf33dca109..00000000000
--- a/storage/ndb/src/kernel/vm/testLongSig/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include .defs.mk
-
-TYPE := signalsender
-
-BIN_TARGET := testLongSig
-
-SOURCES = testLongSig.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/storage/ndb/src/kernel/vm/testLongSig/testLongSig.cpp b/storage/ndb/src/kernel/vm/testLongSig/testLongSig.cpp
deleted file mode 100644
index cc5c3286168..00000000000
--- a/storage/ndb/src/kernel/vm/testLongSig/testLongSig.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-#include <ndb_global.h>
-#include <editline/editline.h>
-#include <SignalSender.hpp>
-
-void
-print_help(){
- ndbout << "The test menu" << endl;
- ndbout << "1 - Sending of long signals w/ segmented sections" << endl;
- ndbout << "2 - As 1 but using receiver group" << endl;
- ndbout << "3 - Sending of long signals w/ linear sections" << endl;
- ndbout << "4 - As 3 but using receiver group" << endl;
- ndbout << "5 - Sending of manually fragmented signals w/ segmented sections"
- << endl;
- ndbout << "6 - As 5 but using receiver group" << endl;
- ndbout << "7 - Sending of manually fragmented signals w/ linear sections"
- << endl;
- ndbout << "8 - As but using receiver group" << endl;
-
- ndbout << "9 - Sending of CONTINUEB fragmented signals w/ segmented sections"
- << endl;
- ndbout << "10 - As 9 but using receiver group" << endl;
- ndbout << "11 - Sending of CONTINUEB fragmented signals w/ linear sections"
- << endl;
- ndbout << "12 - As but using receiver group" << endl;
- ndbout << "13 - Send 100 * 1000 25 len signals wo/ sections" << endl;
- ndbout << "r - Recive signal from anyone" << endl;
- ndbout << "a - Run tests 1 - 12 with variable sizes - 10 loops" << endl;
- ndbout << "b - Run tests 1 - 12 with variable sizes - 100 loops" << endl;
- ndbout << "c - Run tests 1 - 12 with variable sizes - 1000k loops" << endl;
-}
-
-void runTest(SignalSender &, Uint32 i, bool verbose);
-
-static
-int
-randRange(Uint32 min, Uint32 max){
- float r = rand();
- float f = (max - min + 1);
- float d = (float)RAND_MAX + 1.0;
- return min + (int)(f * r / d);
-}
-
-static
-int
-randRange(const Uint32 odds[], Uint32 count){
- Uint32 val = randRange((Uint32)0, 100);
-
- Uint32 i = 0;
- Uint32 sum = 0;
- while(sum <= val && i < count){
- sum += odds[i];
- i++;
- }
- return i - 1;
-}
-
-int
-main(void){
-
- srand(NdbTick_CurrentMillisecond());
-#if 0
- for(int i = 0; i<100; i++)
- ndbout_c("randRange(0, 3) = %d", randRange(0, 3));
- return 0;
-#endif
- SignalSender ss;
-
- ndbout << "Connecting...";
- if(!ss.connect(30)){
- ndbout << "failed" << endl << "Exiting" << endl;
- return 0;
- }
- ndbout << "done" << endl;
- ndbout_c("Connected as block=%d node=%d",
- refToBlock(ss.getOwnRef()), refToNode(ss.getOwnRef()));
-
- Uint32 data[25];
- Uint32 sec0[70];
- Uint32 sec1[123];
- Uint32 sec2[10];
-
- data[0] = ss.getOwnRef();
- data[1] = 1;
- data[2] = 76;
- data[3] = 1;
- data[4] = 1;
- data[5] = 70;
- data[6] = 123;
- data[7] = 10;
- const Uint32 theDataLen = 18;
-
- for(Uint32 i = 0; i<70; i++)
- sec0[i] = i;
-
- for(Uint32 i = 0; i<123; i++)
- sec1[i] = 70+i;
-
- for(Uint32 i = 0; i<10; i++)
- sec2[i] = (i + 1)*(i + 1);
-
- SimpleSignal signal1;
- signal1.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + 2);
- signal1.header.m_noOfSections = 1;
- signal1.header.m_fragmentInfo = 1;
-
- memcpy(&signal1.theData[0], data, 4 * theDataLen );
- signal1.theData[theDataLen + 0] = 0;
- signal1.theData[theDataLen + 1] = 7; // FragmentId
-
- signal1.ptr[0].sz = 60;
- signal1.ptr[0].p = &sec0[0];
-
- SimpleSignal signal2;
-
- Uint32 idx = 0;
- memcpy(&signal2.theData[0], data, 4 * theDataLen );
- signal2.theData[theDataLen + idx] = 0; idx++;
- signal2.theData[theDataLen + idx] = 1; idx++;
- //signal2.theData[theDataLen + idx] = 2; idx++;
- signal2.theData[theDataLen + idx] = 7; idx++; // FragmentId
-
- signal2.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + idx);
- signal2.header.m_fragmentInfo = 3;
- signal2.header.m_noOfSections = idx - 1;
-
- signal2.ptr[0].sz = 10;
- signal2.ptr[0].p = &sec0[60];
-
- signal2.ptr[1].sz = 123;
- signal2.ptr[1].p = &sec1[0];
-
- signal2.ptr[2].sz = 10;
- signal2.ptr[2].p = &sec2[0];
-
- char * buf;
- while((buf = readline("Enter command: "))){
- add_history(buf);
- data[1] = atoi(buf);
- if(strcmp(buf, "r") == 0){
- SimpleSignal * ret1 = ss.waitFor();
- (* ret1).print();
- delete ret1;
- continue;
- }
- if(strcmp(buf, "a") == 0){
- runTest(ss, 10, true);
- print_help();
- continue;
- }
- if(strcmp(buf, "b") == 0){
- runTest(ss, 100, false);
- print_help();
- continue;
- }
- if(strcmp(buf, "c") == 0){
- runTest(ss, 1000000, false);
- print_help();
- continue;
- }
-
- if(data[1] >= 1 && data[1] <= 12){
- Uint32 nodeId = ss.getAliveNode();
- ndbout_c("Sending 2 fragmented to node %d", nodeId);
- ss.sendSignal(nodeId, &signal1);
- ss.sendSignal(nodeId, &signal2);
-
- if(data[1] >= 5){
- continue;
- }
- ndbout_c("Waiting for signal from %d", nodeId);
-
- SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
- (* ret1).print();
- Uint32 count = ret1->theData[4] - 1;
- delete ret1;
- while(count > 0){
- ndbout << "Waiting for " << count << " signals... ";
- SimpleSignal * ret1 = ss.waitFor();
- ndbout_c("received from node %d",
- refToNode(ret1->header.theSendersBlockRef));
- (* ret1).print();
- delete ret1;
- count--;
- }
- } else if (data[1] == 13) {
- const Uint32 count = 3500;
- const Uint32 loop = 1000;
-
- signal1.set(ss, 0, CMVMI, GSN_TESTSIG, 25);
- signal1.header.m_fragmentInfo = 0;
- signal1.header.m_noOfSections = 0;
- signal1.theData[1] = 14;
- signal1.theData[3] = 0; // Print
- signal1.theData[8] = count;
- signal1.theData[9] = loop;
- Uint32 nodeId = ss.getAliveNode();
- ndbout_c("Sending 25 len signal to node %d", nodeId);
- ss.sendSignal(nodeId, &signal1);
-
- Uint32 total;
- {
- SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
- ndbout_c("received from node %d",
- refToNode(ret1->header.theSendersBlockRef));
- total = ret1->theData[10] - 1;
- delete ret1;
- }
-
- do {
- ndbout << "Waiting for " << total << " signals... " << flush;
- SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
- ndbout_c("received from node %d",
- refToNode(ret1->header.theSendersBlockRef));
- delete ret1;
- total --;
- } while(total > 0);
- } else {
- print_help();
- }
- }
- ndbout << "Exiting" << endl;
-};
-
-void
-runTest(SignalSender & ss, Uint32 count, bool verbose){
-
- SimpleSignal sig;
- Uint32 sec0[256];
- Uint32 sec1[256];
- Uint32 sec2[256];
- for(Uint32 i = 0; i<256; i++){
- sec0[i] = i;
- sec1[i] = i + i;
- sec2[i] = i * i;
- }
-
- sig.theData[0] = ss.getOwnRef();
- sig.theData[1] = 1; // TestType
- sig.theData[2] = 128; // FragSize
- sig.theData[3] = 0; // Print
- sig.theData[4] = 1; // RetCount
-
- sig.ptr[0].p = &sec0[0];
- sig.ptr[1].p = &sec1[0];
- sig.ptr[2].p = &sec2[0];
-
- for(unsigned loop = 0; loop < count; loop++){
- const Uint32 odds[] = { 5, 40, 30, 25 };
- const Uint32 secs = randRange(odds, 4);
- sig.ptr[0].sz = randRange(1, 256);
- sig.ptr[1].sz = randRange(1, 256);
- sig.ptr[2].sz = randRange(1, 256);
- sig.header.m_noOfSections = secs;
- const Uint32 len = 5 + (secs > 0 ? 1 : 0) * (25 - 5 - 7);
- sig.set(ss, 0, CMVMI, GSN_TESTSIG, len);
- ndbout << "Loop " << loop << " #secs = " << secs << " sizes = [ ";
- unsigned min = 256;
- unsigned max = 0;
- unsigned sum = 0;
- for(unsigned i = 0; i<secs; i++){
- const Uint32 sz = sig.ptr[i].sz;
- ndbout << sz << " ";
- min = (min < sz ? min : sz);
- max = (max > sz ? max : sz);
- sum += sz;
- sig.theData[5+i] = sz;
- }
- ndbout_c("] len = %d", len);
- for(int test = 1; test <= 12; test++){
- sig.theData[1] = test;
- Uint32 nodeId = ss.getAliveNode();
- if(verbose){
- ndbout << " Test " << test << " node " << nodeId << "...";
- fflush(stdout);
- }
- SendStatus r = ss.sendSignal(nodeId, &sig);
- assert(r == SEND_OK);
- if(test < 5){
- SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
- Uint32 count = ret1->theData[4] - 1;
- delete ret1;
-
- while(count > 0){
- SimpleSignal * ret1 = ss.waitFor();
- delete ret1;
- count--;
- }
- if(verbose)
- ndbout << "done" << endl;
- } else {
- Uint32 nodes = ss.getNoOfConnectedNodes();
- Uint32 sum2 = 0;
- if((test & 1) == 1)
- nodes = 1;
- while(nodes > 0){
- SimpleSignal * ret = ss.waitFor();
- if(ret->header.m_fragmentInfo == 0){
- for(Uint32 i = 0; i<ret->header.m_noOfSections; i++)
- sum2 += ret->ptr[i].sz;
- } else {
- for(Uint32 i = 0; i<ret->header.m_noOfSections; i++)
- if(ret->theData[i] != 3)
- sum2 += ret->ptr[i].sz;
- }
- if(ret->header.m_fragmentInfo == 0 ||
- ret->header.m_fragmentInfo == 3){
- nodes--;
- }
- delete ret;
- }
- if(verbose)
- ndbout_c("done sum=%d sum2=%d", sum, sum2);
- }
- }
- }
-}
diff --git a/storage/ndb/src/kernel/vm/testSimplePropertiesSection/Makefile b/storage/ndb/src/kernel/vm/testSimplePropertiesSection/Makefile
deleted file mode 100644
index fb3aea00507..00000000000
--- a/storage/ndb/src/kernel/vm/testSimplePropertiesSection/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-BIN_TARGET := testSimplePropertiesSection
-BIN_TARGET_ARCHIVES := general portlib
-
-SOURCES = test.cpp ../SimplePropertiesSection.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/storage/ndb/src/kernel/vm/testSimplePropertiesSection/test.cpp b/storage/ndb/src/kernel/vm/testSimplePropertiesSection/test.cpp
deleted file mode 100644
index 5d58d062d97..00000000000
--- a/storage/ndb/src/kernel/vm/testSimplePropertiesSection/test.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/* Copyright (c) 2003-2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include <ndb_global.h>
-#include <NdbTick.h>
-#include <TransporterDefinitions.hpp>
-#include <SimpleProperties.hpp>
-#include <LongSignal.hpp>
-
-#undef test
-
-struct Buffer {
- Buffer(Uint32 size){ m_sz = size; buffer = new Uint32[m_sz]; m_len = 0;}
- ~Buffer(){ delete [] buffer;}
-
- Uint32 m_sz;
- Uint32 m_len;
- Uint32 * buffer;
-};
-
-inline
-void
-require(bool b){
- if(!b)
- abort();
-}
-
-#define relSz(x) ((x + SectionSegment::DataLength - 1) / SectionSegment::DataLength)
-
-void
-release(SectionSegmentPool & thePool, SegmentedSectionPtr & ptr){
- const Uint32 sz = relSz(ptr.sz);
- thePool.releaseList(sz,
- ptr.i,
- ptr.p->m_lastSegment);
-}
-
-void
-compare(SimplePropertiesSectionReader & db, Buffer & buf){
-
- {
- bool fail = false;
- db.reset();
- for(Uint32 i = 0; i<buf.m_len; i++){
- Uint32 tmp;
- if(!db.getWord(&tmp)){
- ndbout_c("getWord(...) failed i=%d size=%d", i, buf.m_len);
- abort();
- }
-
- if(tmp != buf.buffer[i]){
- ndbout_c("getWord(...)=%d != buf[%d]=%d size=%d", tmp, i,
- buf.buffer[i], buf.m_len);
- fail = true;
- }
- }
- require(!fail);
- }
-
- {
- db.reset();
- Buffer buf2(buf.m_sz);
- if(!db.getWords(buf2.buffer, buf.m_len))
- abort();
-
- bool fail = false;
- for(Uint32 i = 0; i<buf.m_len; i++){
- if(buf.buffer[i] != buf2.buffer[i]){
- ndbout_c("getWords(...) buf[%d] != buf2[%d] size=%d", i, i, buf.m_len);
- fail = true;
- }
- }
- require(!fail);
- }
-}
-
-
-void
-test(Uint32 sz, Uint32 loops, Uint32 iter){
-
- ndbout_c("SimplePropertiesSection sz=%d loops=%d iter=%d", sz, loops, iter);
-
- while(loops-- > 0){
- Uint32 size = sz*((10 + (rand() % (10 * sz)) + sz - 1)/sz);
-
- Buffer buf(size);
- SectionSegmentPool thePool; thePool.setSize(size);
-
- for(Uint32 i = 0; i<iter; i++){
- Uint32 c = 0 + (rand() % (2));
-
- const Uint32 alloc = 1 + (rand() % (size - 1));
- SegmentedSectionPtr dst;
-
- if(0)
- ndbout_c("size: %d loops: %d iter: %d c=%d alloc=%d",
- size, loops, i, c, alloc);
-
- switch(c){
- case 0:{
- for(Uint32 i = 0; i<alloc; i++)
- buf.buffer[i] = i; //rand();
- buf.m_len = alloc;
-
- SimplePropertiesSectionWriter w(thePool);
- for(Uint32 i = 0; i<alloc; i++){
- w.putWord(buf.buffer[i]);
- }
- w.getPtr(dst);
- break;
- }
- case 1:{
- for(Uint32 i = 0; i<alloc; i++)
- buf.buffer[i] = i; //rand();
- buf.m_len = alloc;
-
- SimplePropertiesSectionWriter w(thePool);
- Uint32 i = 0;
- while(i < alloc){
- Uint32 sz = rand() % (alloc - i + 1);
- w.putWords(&buf.buffer[i], sz);
- i += sz;
- }
- w.getPtr(dst);
- break;
- }
- case 2:{
- break;
- }
- }
- SimplePropertiesSectionReader r(dst, thePool);
- compare(r, buf);
- release(thePool, dst);
- require(thePool.getSize() == thePool.getNoOfFree());
- }
- }
-}
-
-int
-main(void){
-
- srand(NdbTick_CurrentMillisecond());
-
- //test( 1, 1000, 1000);
- test(54, 1000, 1000);
- test(59, 1000, 1000);
- test(60, 1000, 1000);
- test(61, 1000, 1000);
- return 0;
-}
-
-void
-ErrorReporter::handleAssert(const char * msg, const char * file, int line)
-{
- ndbout << "ErrorReporter::handleAssert activated - "
- << " line= " << line << endl;
- abort();
-}
diff --git a/storage/ndb/src/kernel/vm/testSuperPool.cpp b/storage/ndb/src/kernel/vm/testSuperPool.cpp
deleted file mode 100644
index b5f57be1bbe..00000000000
--- a/storage/ndb/src/kernel/vm/testSuperPool.cpp
+++ /dev/null
@@ -1,364 +0,0 @@
-#if 0
-make -f Makefile -f - testSuperPool <<'_eof_'
-testSuperPool: testSuperPool.cpp libkernel.a LinearPool.hpp
- $(CXXCOMPILE) -o $@ $@.cpp libkernel.a -L../../common/util/.libs -lgeneral
-_eof_
-exit $?
-#endif
-
-/* Copyright (c) 2003, 2005 MySQL AB
- Use is subject to license terms
-
- 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; version 2 of the License.
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-#include "SuperPool.hpp"
-#include "LinearPool.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]);
- assert(n != 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 <class T>
-static void
-sp_test(GroupPool& gp)
-{
- SuperPool& sp = gp.m_superPool;
- RecordPool<T> rp(gp);
- assert(gp.m_totPages == gp.m_freeList.m_pageCount);
- SuperPool::RecInfo& ri = rp.m_recInfo;
- Uint32 pageCount = sp.m_totPages;
- Uint32 perPage = rp.m_recInfo.m_maxPerPage;
- 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 verify = 1000;
- Uint32 useCount;
- 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++) {
- if (verify == 0 || urandom(perPool) < verify)
- sp.verify(ri);
- j = i;
- Ptr<T> ptr1 = { 0, RNIL };
- if (! rp.seize(ptr1))
- break;
- ptr1.p->fill();
- ptr1.p->check();
- Ptr<T> ptr2 = { 0, ptr1.i };
- rp.getPtr(ptr2);
- assert(ptr1.i == ptr2.i && ptr1.p == ptr2.p);
- ptrList[j] = ptr1;
- }
- sp.verify(ri);
- ndbout << "seized " << i << endl;
- assert(i == perPool);
- useCount = sp.getRecUseCount(ri);
- assert(useCount == perPool);
- // check duplicates
- ndbout << "check dups" << endl;
- {
- 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++) {
- if (verify == 0 || urandom(perPool) < verify)
- 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.verify(ri);
- useCount = sp.getRecUseCount(ri);
- assert(useCount == 0);
- // seize/release at random
- ndbout << "seize/release at random" << endl;
- for (i = 0; i < loopcount * perPool; i++) {
- if (verify == 0 || urandom(perPool) < verify)
- sp.verify(ri);
- j = urandom(perPool);
- Ptr<T>& ptr = ptrList[j];
- if (ptr.i == RNIL) {
- if (rp.seize(ptr))
- ptr.p->fill();
- } else {
- ptr.p->check();
- rp.release(ptr);
- }
- }
- ndbout << "used " << ri.m_useCount << endl;
- sp.verify(ri);
- // release all
- ndbout << "release all" << endl;
- for (i = 0; i < perPool; i++) {
- if (verify == 0 || urandom(perPool) < verify)
- sp.verify(ri);
- j = i;
- Ptr<T>& ptr = ptrList[j];
- if (ptr.i != RNIL) {
- ptr.p->check();
- rp.release(ptr);
- }
- }
- sp.verify(ri);
- useCount = sp.getRecUseCount(ri);
- assert(useCount == 0);
- }
- // done
- delete [] ptrList;
-}
-
-template <class T>
-static void
-lp_test(GroupPool& gp)
-{
- SuperPool& sp = gp.m_superPool;
- LinearPool<T, 5> lp(gp);
- ndbout << "linear pool test" << endl;
- Ptr<T> ptr;
- Uint32 loop;
- for (loop = 0; loop < loopcount; loop++) {
- int count = 0;
- while (1) {
- bool ret = lp.seize(ptr);
- lp.verify();
- if (! ret)
- break;
- assert(ptr.i == count);
- Ptr<T> ptr2;
- ptr2.i = ptr.i;
- ptr2.p = 0;
- lp.getPtr(ptr2);
- assert(ptr.p == ptr2.p);
- count++;
- }
- assert(count != 0);
- ndbout << "seized " << count << endl;
- switch (loop % 3) {
- case 0:
- {
- int n = 0;
- while (n < count) {
- ptr.i = n;
- lp.release(ptr);
- lp.verify();
- n++;
- }
- ndbout << "released in order" << endl;
- }
- break;
- case 1:
- {
- int n = count;
- while (n > 0) {
- n--;
- ptr.i = n;
- lp.release(ptr);
- lp.verify();
- }
- ndbout << "released in reverse" << endl;
- }
- break;
- default:
- {
- int coprime = random_coprime(count);
- int n = 0;
- while (n < count) {
- int m = (coprime * n) % count;
- ptr.i = m;
- lp.release(ptr);
- lp.verify();
- n++;
- }
- ndbout << "released at random" << endl;
- }
- break;
- }
- { Uint32 cnt = lp.count(); assert(cnt == 0); }
- // seize_index test
- char *used = new char [10 * count];
- memset(used, false, sizeof(used));
- Uint32 i, ns = 0, nr = 0;
- for (i = 0; i < count; i++) {
- Uint32 index = urandom(10 * count);
- if (used[index]) {
- ptr.i = index;
- lp.release(ptr);
- lp.verify();
- nr++;
- } else {
- int i = lp.seize_index(ptr, index);
- assert(i >= 0);
- lp.verify();
- if (i == 0) // no space
- continue;
- assert(ptr.i == index);
- Ptr<T> ptr2;
- ptr2.i = ptr.i;
- ptr2.p = 0;
- lp.getPtr(ptr2);
- assert(ptr.p == ptr2.p);
- ns++;
- }
- used[index] = ! used[index];
- }
- ndbout << "random sparse seize " << ns << " release " << nr << endl;
- nr = 0;
- for (i = 0; i < 10 * count; i++) {
- if (used[i]) {
- ptr.i = i;
- lp.release(ptr);
- lp.verify();
- used[i] = false;
- nr++;
- }
- }
- ndbout << "released " << nr << endl;
- { Uint32 cnt = lp.count(); assert(cnt == 0); }
- }
-}
-
-static Uint32 pageSize = 32768;
-static Uint32 pageBits = 17;
-
-const Uint32 sz1 = 3;
-const Uint32 sz2 = 4;
-const Uint32 sz3 = 53;
-const Uint32 sz4 = 424;
-const Uint32 sz5 = 5353;
-
-typedef A<sz1> T1;
-typedef A<sz2> T2;
-typedef A<sz3> T3;
-typedef A<sz4> T4;
-typedef A<sz5> T5;
-
-template static void sp_test<T1>(GroupPool& sp);
-template static void sp_test<T2>(GroupPool& sp);
-template static void sp_test<T3>(GroupPool& sp);
-template static void sp_test<T4>(GroupPool& sp);
-template static void sp_test<T5>(GroupPool& sp);
-//
-template static void lp_test<T3>(GroupPool& sp);
-
-int
-main(int argc, char** argv)
-{
- if (argc > 1 && strncmp(argv[1], "-l", 2) == 0)
- loopcount = atoi(argv[1] + 2);
- HeapPool sp(pageSize, pageBits);
- sp.setInitPages(7);
- sp.setMaxPages(7);
- if (! sp.allocMemory())
- assert(false);
- GroupPool gp(sp);
- Uint16 s = (Uint16)getpid();
- srandom(s);
- ndbout << "rand " << s << endl;
- int count;
- count = 0;
- while (++count <= 0) { // change to 1 to find new bug
- sp_test<T1>(gp);
- sp_test<T2>(gp);
- sp_test<T3>(gp);
- sp_test<T4>(gp);
- sp_test<T5>(gp);
- }
- count = 0;
- while (++count <= 1) {
- lp_test<T3>(gp);
- }
- return 0;
-}