summaryrefslogtreecommitdiff
path: root/storage/ndb/src
diff options
context:
space:
mode:
authorunknown <jonas@perch.ndb.mysql.com>2005-11-07 12:19:28 +0100
committerunknown <jonas@perch.ndb.mysql.com>2005-11-07 12:19:28 +0100
commitee740746aff3c5163adfff481bc4cf70c37728f5 (patch)
tree2cb53178c95e7d8d6578018e169c2d71bb1fdbcb /storage/ndb/src
parent8a224ed85a8794743472f3611830349dc490aabc (diff)
downloadmariadb-git-ee740746aff3c5163adfff481bc4cf70c37728f5.tar.gz
Import ndb varsize
BitKeeper/deleted/.del-MetaData.cpp~146ae9865dd35829: Delete: storage/ndb/src/kernel/vm/MetaData.cpp BitKeeper/deleted/.del-MetaData.hpp~538342afcd8ac53c: Delete: storage/ndb/src/kernel/vm/MetaData.hpp BitKeeper/deleted/.del-DbtupLCP.cpp~855b1ed3fbc86a42: Delete: storage/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp BitKeeper/deleted/.del-DbtupSystemRestart.cpp~15b54d7e4e75d2d: Delete: storage/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp BitKeeper/deleted/.del-DbtupUndoLog.cpp~5a2ef6e86b1404e9: Delete: storage/ndb/src/kernel/blocks/dbtup/DbtupUndoLog.cpp storage/ndb/include/kernel/signaldata/CreateFilegroup.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/CreateFilegroup.hpp'' storage/ndb/include/kernel/signaldata/CreateFilegroupImpl.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/CreateFilegroupImpl.hpp'' storage/ndb/include/kernel/signaldata/CreateObj.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/CreateObj.hpp'' storage/ndb/include/kernel/signaldata/DictObjOp.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/DictObjOp.hpp'' storage/ndb/include/kernel/signaldata/DropFilegroup.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/DropFilegroup.hpp'' storage/ndb/include/kernel/signaldata/DropFilegroupImpl.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/DropFilegroupImpl.hpp'' storage/ndb/include/kernel/signaldata/DropObj.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/DropObj.hpp'' storage/ndb/include/kernel/signaldata/Extent.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/Extent.hpp'' storage/ndb/include/kernel/signaldata/LgmanContinueB.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/LgmanContinueB.hpp'' storage/ndb/include/kernel/signaldata/PgmanContinueB.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/PgmanContinueB.hpp'' storage/ndb/include/kernel/signaldata/RestoreContinueB.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/RestoreContinueB.hpp'' storage/ndb/include/kernel/signaldata/RestoreImpl.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/RestoreImpl.hpp'' storage/ndb/include/kernel/signaldata/TsmanContinueB.hpp: New BitKeeper file ``storage/ndb/include/kernel/signaldata/TsmanContinueB.hpp'' storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp'' storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp'' storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp'' storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp'' storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp'' storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp'' storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp'' storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp'' storage/ndb/src/kernel/blocks/diskpage.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/diskpage.cpp'' storage/ndb/src/kernel/blocks/diskpage.hpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/diskpage.hpp'' storage/ndb/src/kernel/blocks/lgman.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/lgman.cpp'' storage/ndb/src/kernel/blocks/lgman.hpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/lgman.hpp'' storage/ndb/src/kernel/blocks/pgman.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/pgman.cpp'' storage/ndb/src/kernel/blocks/pgman.hpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/pgman.hpp'' storage/ndb/src/kernel/blocks/print_file.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/print_file.cpp'' storage/ndb/src/kernel/blocks/restore.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/restore.cpp'' storage/ndb/src/kernel/blocks/restore.hpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/restore.hpp'' storage/ndb/src/kernel/blocks/tsman.cpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/tsman.cpp'' storage/ndb/src/kernel/blocks/tsman.hpp: New BitKeeper file ``storage/ndb/src/kernel/blocks/tsman.hpp'' storage/ndb/src/kernel/vm/DLCFifoList.hpp: New BitKeeper file ``storage/ndb/src/kernel/vm/DLCFifoList.hpp'' storage/ndb/src/kernel/vm/DLCHashTable.hpp: New BitKeeper file ``storage/ndb/src/kernel/vm/DLCHashTable.hpp'' storage/ndb/src/kernel/vm/KeyTable2Ref.hpp: New BitKeeper file ``storage/ndb/src/kernel/vm/KeyTable2Ref.hpp'' storage/ndb/src/kernel/vm/Rope.cpp: New BitKeeper file ``storage/ndb/src/kernel/vm/Rope.cpp'' storage/ndb/src/kernel/vm/Rope.hpp: New BitKeeper file ``storage/ndb/src/kernel/vm/Rope.hpp''
Diffstat (limited to 'storage/ndb/src')
-rw-r--r--storage/ndb/src/common/debugger/BlockNames.cpp6
-rw-r--r--storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp95
-rw-r--r--storage/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp8
-rw-r--r--storage/ndb/src/common/debugger/signaldata/LqhKey.cpp4
-rw-r--r--storage/ndb/src/common/debugger/signaldata/ScanTab.cpp5
-rw-r--r--storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp1
-rw-r--r--storage/ndb/src/common/debugger/signaldata/SignalNames.cpp57
-rw-r--r--storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp6
-rw-r--r--storage/ndb/src/common/debugger/signaldata/TuxMaint.cpp2
-rw-r--r--storage/ndb/src/kernel/Makefile.am6
-rw-r--r--storage/ndb/src/kernel/SimBlockList.cpp52
-rw-r--r--storage/ndb/src/kernel/blocks/Makefile.am19
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Backup.cpp715
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Backup.hpp66
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Backup.txt62
-rw-r--r--storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp14
-rw-r--r--storage/ndb/src/kernel/blocks/backup/BackupInit.cpp107
-rw-r--r--storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp19
-rw-r--r--storage/ndb/src/kernel/blocks/backup/Makefile.am8
-rw-r--r--storage/ndb/src/kernel/blocks/backup/read.cpp59
-rw-r--r--storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp6
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp434
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp101
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp4786
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp4207
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp612
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Makefile.am11
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp18
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp30
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp16
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/Makefile.am16
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp12
-rw-r--r--storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp160
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp314
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp63
-rw-r--r--storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp3704
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp5
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp24
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp16
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp14
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp2170
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp393
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp159
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp1061
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp175
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp1511
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp3213
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp358
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp835
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp599
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp596
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp1049
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp87
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp38
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp1748
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp258
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp42
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp1021
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp8
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp492
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupUndoLog.cpp284
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp846
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Makefile.am18
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp120
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp57
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp125
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp330
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp231
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp25
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp35
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp4
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp8
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp6
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp44
-rw-r--r--storage/ndb/src/kernel/blocks/dbtux/Makefile.am3
-rw-r--r--storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp11
-rw-r--r--storage/ndb/src/kernel/blocks/diskpage.cpp75
-rw-r--r--storage/ndb/src/kernel/blocks/diskpage.hpp236
-rw-r--r--storage/ndb/src/kernel/blocks/lgman.cpp2952
-rw-r--r--storage/ndb/src/kernel/blocks/lgman.hpp342
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp18
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp182
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp14
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp105
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp42
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp310
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp8
-rw-r--r--storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp4
-rw-r--r--storage/ndb/src/kernel/blocks/pgman.cpp2214
-rw-r--r--storage/ndb/src/kernel/blocks/pgman.hpp659
-rw-r--r--storage/ndb/src/kernel/blocks/print_file.cpp370
-rw-r--r--storage/ndb/src/kernel/blocks/restore.cpp1211
-rw-r--r--storage/ndb/src/kernel/blocks/restore.hpp154
-rw-r--r--storage/ndb/src/kernel/blocks/suma/Suma.cpp28
-rw-r--r--storage/ndb/src/kernel/blocks/tsman.cpp2101
-rw-r--r--storage/ndb/src/kernel/blocks/tsman.hpp372
-rw-r--r--storage/ndb/src/kernel/vm/ArrayPool.hpp30
-rw-r--r--storage/ndb/src/kernel/vm/Configuration.cpp21
-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.hpp208
-rw-r--r--storage/ndb/src/kernel/vm/DLHashTable.hpp128
-rw-r--r--storage/ndb/src/kernel/vm/DLList.hpp133
-rw-r--r--storage/ndb/src/kernel/vm/DataBuffer.hpp3
-rw-r--r--storage/ndb/src/kernel/vm/GlobalData.hpp6
-rw-r--r--storage/ndb/src/kernel/vm/KeyDescriptor.hpp6
-rw-r--r--storage/ndb/src/kernel/vm/KeyTable2Ref.hpp51
-rw-r--r--storage/ndb/src/kernel/vm/LongSignal.hpp1
-rw-r--r--storage/ndb/src/kernel/vm/Makefile.am6
-rw-r--r--storage/ndb/src/kernel/vm/MetaData.cpp113
-rw-r--r--storage/ndb/src/kernel/vm/MetaData.hpp243
-rw-r--r--storage/ndb/src/kernel/vm/Rope.cpp173
-rw-r--r--storage/ndb/src/kernel/vm/Rope.hpp117
-rw-r--r--storage/ndb/src/kernel/vm/SLList.hpp108
-rw-r--r--storage/ndb/src/kernel/vm/SafeCounter.cpp2
-rw-r--r--storage/ndb/src/kernel/vm/SimBlockList.hpp3
-rw-r--r--storage/ndb/src/kernel/vm/SimulatedBlock.cpp53
-rw-r--r--storage/ndb/src/kernel/vm/SimulatedBlock.hpp20
-rw-r--r--storage/ndb/src/kernel/vm/pc.hpp10
-rw-r--r--storage/ndb/src/ndbapi/DictCache.cpp17
-rw-r--r--storage/ndb/src/ndbapi/Ndb.cpp20
-rw-r--r--storage/ndb/src/ndbapi/NdbBlob.cpp11
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionary.cpp463
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp1346
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp261
-rw-r--r--storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp12
-rw-r--r--storage/ndb/src/ndbapi/NdbIndexOperation.cpp2
-rw-r--r--storage/ndb/src/ndbapi/NdbOperation.cpp25
-rw-r--r--storage/ndb/src/ndbapi/NdbOperationDefine.cpp71
-rw-r--r--storage/ndb/src/ndbapi/NdbOperationExec.cpp4
-rw-r--r--storage/ndb/src/ndbapi/NdbOperationInt.cpp15
-rw-r--r--storage/ndb/src/ndbapi/NdbOperationSearch.cpp146
-rw-r--r--storage/ndb/src/ndbapi/NdbRecAttr.cpp413
-rw-r--r--storage/ndb/src/ndbapi/NdbReceiver.cpp24
-rw-r--r--storage/ndb/src/ndbapi/NdbScanOperation.cpp47
-rw-r--r--storage/ndb/src/ndbapi/Ndbif.cpp9
-rw-r--r--storage/ndb/src/ndbapi/TransporterFacade.cpp4
-rw-r--r--storage/ndb/src/ndbapi/ndberror.c27
138 files changed, 31846 insertions, 17924 deletions
diff --git a/storage/ndb/src/common/debugger/BlockNames.cpp b/storage/ndb/src/common/debugger/BlockNames.cpp
index 0c61b6327ef..8403609eb30 100644
--- a/storage/ndb/src/common/debugger/BlockNames.cpp
+++ b/storage/ndb/src/common/debugger/BlockNames.cpp
@@ -33,6 +33,10 @@ const BlockName BlockNames[] = {
{ "DBUTIL", DBUTIL },
{ "SUMA", SUMA },
{ "DBTUX", DBTUX }
+ ,{ "TSMAN", TSMAN}
+ ,{ "LGMAN", LGMAN }
+ ,{ "PGMAN", PGMAN }
+ ,{ "RESTORE", RESTORE }
};
-
+
const BlockNumber NO_OF_BLOCK_NAMES = sizeof(BlockNames) / sizeof(BlockName);
diff --git a/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp b/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
index 43c129347c0..6212f91290b 100644
--- a/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
@@ -30,7 +30,6 @@ DictTabInfo::TableMapping[] = {
DTIMAP2(Table, MinLoadFactor, MinLoadFactor, 0, 90),
DTIMAP2(Table, MaxLoadFactor, MaxLoadFactor, 25, 110),
DTIMAP2(Table, FragmentTypeVal, FragmentType, 0, 3),
- DTIMAP2(Table, TableStorageVal, TableStorage, 0, 0),
DTIMAP2(Table, TableTypeVal, TableType, 1, 3),
DTIMAP(Table, NoOfKeyAttr, NoOfKeyAttr),
DTIMAP2(Table, NoOfAttributes, NoOfAttributes, 1, MAX_ATTRIBUTES_IN_TABLE),
@@ -48,6 +47,8 @@ DictTabInfo::TableMapping[] = {
DTIMAP(Table, FragmentCount, FragmentCount),
DTIMAP2(Table, FragmentDataLen, FragmentDataLen, 0, MAX_FRAGMENT_DATA_BYTES),
DTIMAPB(Table, FragmentData, FragmentData, 0, MAX_FRAGMENT_DATA_BYTES, FragmentDataLen),
+ DTIMAP(Table, TablespaceId, TablespaceId),
+ DTIMAP(Table, TablespaceVersion, TablespaceVersion),
DTIBREAK(AttributeName)
};
@@ -64,9 +65,11 @@ DictTabInfo::AttributeMapping[] = {
DTIMAP(Attribute, AttributeType, AttributeType),
DTIMAP2(Attribute, AttributeSize, AttributeSize, 3, 7),
DTIMAP2(Attribute, AttributeArraySize, AttributeArraySize, 0, 65535),
+ DTIMAP2(Attribute, AttributeArrayType, AttributeArrayType, 0, 3),
DTIMAP2(Attribute, AttributeKeyFlag, AttributeKeyFlag, 0, 1),
DTIMAP2(Attribute, AttributeNullableFlag, AttributeNullableFlag, 0, 1),
DTIMAP2(Attribute, AttributeDKey, AttributeDKey, 0, 1),
+ DTIMAP2(Attribute, AttributeStorageType, AttributeStorageType, 0, 1),
DTIMAP(Attribute, AttributeExtType, AttributeExtType),
DTIMAP(Attribute, AttributeExtPrecision, AttributeExtPrecision),
DTIMAP(Attribute, AttributeExtScale, AttributeExtScale),
@@ -111,7 +114,6 @@ DictTabInfo::Table::init(){
MaxLoadFactor = 80;
KeyLength = 0;
FragmentType = DictTabInfo::AllNodesSmallTable;
- TableStorage = 0;
TableType = DictTabInfo::UndefTableType;
TableVersion = 0;
IndexState = ~0;
@@ -124,15 +126,18 @@ DictTabInfo::Table::init(){
FragmentCount = 0;
FragmentDataLen = 0;
memset(FragmentData, 0, sizeof(FragmentData));
+ TablespaceId = RNIL;
+ TablespaceVersion = ~0;
}
void
DictTabInfo::Attribute::init(){
memset(AttributeName, 0, sizeof(AttributeName));//AttributeName[0] = 0;
- AttributeId = 0;
+ AttributeId = 0xFFFF; // ZNIL
AttributeType = ~0, // deprecated
AttributeSize = DictTabInfo::a32Bit;
AttributeArraySize = 1;
+ AttributeArrayType = NDB_ARRAYTYPE_FIXED;
AttributeKeyFlag = 0;
AttributeNullableFlag = 0;
AttributeDKey = 0;
@@ -141,5 +146,89 @@ DictTabInfo::Attribute::init(){
AttributeExtScale = 0,
AttributeExtLength = 0,
AttributeAutoIncrement = false;
+ AttributeStorageType = 0;
memset(AttributeDefaultValue, 0, sizeof(AttributeDefaultValue));//AttributeDefaultValue[0] = 0;
}
+
+//static
+const
+SimpleProperties::SP2StructMapping
+DictFilegroupInfo::Mapping[] = {
+ DFGIMAPS(Filegroup, FilegroupName, FilegroupName, 0, MAX_TAB_NAME_SIZE),
+ DFGIMAP2(Filegroup, FilegroupType, FilegroupType, 0, 1),
+ DFGIMAP(Filegroup, FilegroupId, FilegroupId),
+ DFGIMAP(Filegroup, FilegroupVersion, FilegroupVersion),
+
+ DFGIMAP(Filegroup, TS_ExtentSize, TS_ExtentSize),
+ DFGIMAP(Filegroup, TS_LogfileGroupId, TS_LogfileGroupId),
+ DFGIMAP(Filegroup, TS_LogfileGroupVersion, TS_LogfileGroupVersion),
+ DFGIMAP(Filegroup, TS_GrowLimit, TS_DataGrow.GrowLimit),
+ DFGIMAP(Filegroup, TS_GrowSizeHi, TS_DataGrow.GrowSizeHi),
+ DFGIMAP(Filegroup, TS_GrowSizeLo, TS_DataGrow.GrowSizeLo),
+ DFGIMAPS(Filegroup, TS_GrowPattern, TS_DataGrow.GrowPattern, 0, PATH_MAX),
+ DFGIMAP(Filegroup, TS_GrowMaxSize, TS_DataGrow.GrowMaxSize),
+
+ DFGIMAP(Filegroup, LF_UndoBufferSize, LF_UndoBufferSize),
+ DFGIMAP(Filegroup, LF_UndoGrowLimit, LF_UndoGrow.GrowLimit),
+ DFGIMAP(Filegroup, LF_UndoGrowSizeHi, LF_UndoGrow.GrowSizeHi),
+ DFGIMAP(Filegroup, LF_UndoGrowSizeLo, LF_UndoGrow.GrowSizeLo),
+ DFGIMAPS(Filegroup, LF_UndoGrowPattern, LF_UndoGrow.GrowPattern, 0,PATH_MAX),
+ DFGIMAP(Filegroup, LF_UndoGrowMaxSize, LF_UndoGrow.GrowMaxSize),
+
+ DFGIBREAK(FileName)
+};
+
+//static
+const Uint32 DictFilegroupInfo::MappingSize =
+sizeof(DictFilegroupInfo::Mapping) / sizeof(SimpleProperties::SP2StructMapping);
+
+//static
+const
+SimpleProperties::SP2StructMapping
+DictFilegroupInfo::FileMapping[] = {
+ DFGIMAPS(File, FileName, FileName, 0, PATH_MAX),
+ DFGIMAP2(File, FileType, FileType, 0, 1),
+ DFGIMAP(File, FileNo, FileNo),
+ DFGIMAP(File, FileId, FileId),
+ DFGIMAP(File, FileFGroupId, FilegroupId),
+ DFGIMAP(File, FileFGroupVersion, FilegroupVersion),
+ DFGIMAP(File, FileSizeHi, FileSizeHi),
+ DFGIMAP(File, FileSizeLo, FileSizeLo),
+ DFGIMAP(File, FileFreeExtents, FileFreeExtents),
+ DFGIBREAK(FileEnd)
+};
+
+//static
+const Uint32 DictFilegroupInfo::FileMappingSize =
+sizeof(DictFilegroupInfo::FileMapping) /
+sizeof(SimpleProperties::SP2StructMapping);
+
+void
+DictFilegroupInfo::Filegroup::init(){
+ memset(FilegroupName, sizeof(FilegroupName), 0);
+ FilegroupType = ~0;
+ FilegroupId = ~0;
+ FilegroupVersion = ~0;
+
+ TS_ExtentSize = 0;
+ TS_LogfileGroupId = ~0;
+ TS_LogfileGroupVersion = ~0;
+ TS_DataGrow.GrowLimit = 0;
+ TS_DataGrow.GrowSizeHi = 0;
+ TS_DataGrow.GrowSizeLo = 0;
+ memset(TS_DataGrow.GrowPattern, sizeof(TS_DataGrow.GrowPattern), 0);
+ TS_DataGrow.GrowMaxSize = 0;
+}
+
+void
+DictFilegroupInfo::File::init(){
+ memset(FileName, sizeof(FileName), 0);
+ FileType = ~0;
+ FileNo = ~0;
+ FileId = ~0;
+ FilegroupId = ~0;
+ FilegroupVersion = ~0;
+ FileSizeHi = 0;
+ FileSizeLo = 0;
+ FileFreeExtents = 0;
+}
diff --git a/storage/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp b/storage/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp
index a9f240d3cb4..9270417c3ed 100644
--- a/storage/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp
@@ -47,6 +47,9 @@ printFSREADWRITEREQ(FILE * output, const Uint32 * theData,
case FsReadWriteReq::fsFormatListOfMemPages:
fprintf(output, "List of mem pages)\n");
break;
+ case FsReadWriteReq::fsFormatGlobalPage:
+ fprintf(output, "List of global pages)\n");
+ break;
default:
fprintf(output, "fsFormatMax not handled\n");
ret = false;
@@ -76,6 +79,11 @@ printFSREADWRITEREQ(FILE * output, const Uint32 * theData,
fprintf(output, " H\'%.8x, ", sig->data.pageData[i]);
}
break;
+ case FsReadWriteReq::fsFormatGlobalPage:
+ for (i= 0; i < sig->numberOfPages; i++){
+ fprintf(output, " H\'%.8x, ", sig->data.pageData[i]);
+ }
+ break;
default:
fprintf(output, "Impossible event\n");
}
diff --git a/storage/ndb/src/common/debugger/signaldata/LqhKey.cpp b/storage/ndb/src/common/debugger/signaldata/LqhKey.cpp
index 2796437fd8b..95a571a08ed 100644
--- a/storage/ndb/src/common/debugger/signaldata/LqhKey.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/LqhKey.cpp
@@ -49,7 +49,9 @@ printLQHKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receive
fprintf(output, "ScanTakeOver ");
if(LqhKeyReq::getMarkerFlag(reqInfo))
fprintf(output, "CommitAckMarker ");
-
+ if(LqhKeyReq::getNoDiskFlag(reqInfo))
+ fprintf(output, "NoDisk ");
+
fprintf(output, "ScanInfo/noFiredTriggers: H\'%x\n", sig->scanInfo);
fprintf(output,
diff --git a/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp b/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp
index d78beb4740a..97ed01a74e2 100644
--- a/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp
@@ -30,7 +30,7 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
fprintf(output, " apiConnectPtr: H\'%.8x",
sig->apiConnectPtr);
fprintf(output, " requestInfo: H\'%.8x:\n", requestInfo);
- fprintf(output, " Parallellism: %u Batch: %u LockMode: %u Keyinfo: %u Holdlock: %u RangeScan: %u Descending: %u TupScan: %u\n ReadCommitted: %u DistributionKeyFlag: %u",
+ fprintf(output, " Parallellism: %u Batch: %u LockMode: %u Keyinfo: %u Holdlock: %u RangeScan: %u Descending: %u TupScan: %u\n ReadCommitted: %u DistributionKeyFlag: %u NoDisk: %u",
sig->getParallelism(requestInfo),
sig->getScanBatch(requestInfo),
sig->getLockMode(requestInfo),
@@ -40,7 +40,8 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
sig->getDescendingFlag(requestInfo),
sig->getTupScanFlag(requestInfo),
sig->getReadCommittedFlag(requestInfo),
- sig->getDistributionKeyFlag(requestInfo));
+ sig->getDistributionKeyFlag(requestInfo),
+ sig->getNoDiskFlag(requestInfo));
if(sig->getDistributionKeyFlag(requestInfo))
fprintf(output, " DKey: %x", sig->distributionKey);
diff --git a/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index 34cae9f618f..0a6bfe980a1 100644
--- a/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -145,6 +145,7 @@ SignalDataPrintFunctions[] = {
{ GSN_SYSTEM_ERROR, printSYSTEM_ERROR },
{ GSN_START_RECREQ, printSTART_REC_REQ },
{ GSN_START_RECCONF, printSTART_REC_CONF },
+ { GSN_START_FRAGREQ, printSTART_FRAG_REQ },
{ GSN_NF_COMPLETEREP, printNF_COMPLETE_REP },
{ GSN_SIGNAL_DROPPED_REP, printSIGNAL_DROPPED_REP },
{ GSN_FAIL_REP, printFAIL_REP },
diff --git a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 96424098086..ca2821d8448 100644
--- a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -63,22 +63,12 @@ const GsnName SignalNames [] = {
,{ GSN_ACC_CHECK_SCAN, "ACC_CHECK_SCAN" }
,{ GSN_ACC_COMMITCONF, "ACC_COMMITCONF" }
,{ GSN_ACC_COMMITREQ, "ACC_COMMITREQ" }
- ,{ GSN_ACC_CONTOPCONF, "ACC_CONTOPCONF" }
- ,{ GSN_ACC_CONTOPREQ, "ACC_CONTOPREQ" }
- ,{ GSN_ACC_LCPCONF, "ACC_LCPCONF" }
- ,{ GSN_ACC_LCPREF, "ACC_LCPREF" }
- ,{ GSN_ACC_LCPREQ, "ACC_LCPREQ" }
- ,{ GSN_ACC_LCPSTARTED, "ACC_LCPSTARTED" }
,{ GSN_ACC_OVER_REC, "ACC_OVER_REC" }
- ,{ GSN_ACC_SAVE_PAGES, "ACC_SAVE_PAGES" }
,{ GSN_ACC_SCAN_INFO, "ACC_SCAN_INFO" }
,{ GSN_ACC_SCAN_INFO24, "ACC_SCAN_INFO24" }
,{ GSN_ACC_SCANCONF, "ACC_SCANCONF" }
,{ GSN_ACC_SCANREF, "ACC_SCANREF" }
,{ GSN_ACC_SCANREQ, "ACC_SCANREQ" }
- ,{ GSN_ACC_SRCONF, "ACC_SRCONF" }
- ,{ GSN_ACC_SRREF, "ACC_SRREF" }
- ,{ GSN_ACC_SRREQ, "ACC_SRREQ" }
,{ GSN_ACC_TO_CONF, "ACC_TO_CONF" }
,{ GSN_ACC_TO_REF, "ACC_TO_REF" }
,{ GSN_ACC_TO_REQ, "ACC_TO_REQ" }
@@ -238,13 +228,6 @@ const GsnName SignalNames [] = {
,{ GSN_INCL_NODECONF, "INCL_NODECONF" }
,{ GSN_INCL_NODEREF, "INCL_NODEREF" }
,{ GSN_INCL_NODEREQ, "INCL_NODEREQ" }
- ,{ GSN_LCP_FRAGIDCONF, "LCP_FRAGIDCONF" }
- ,{ GSN_LCP_FRAGIDREF, "LCP_FRAGIDREF" }
- ,{ GSN_LCP_FRAGIDREQ, "LCP_FRAGIDREQ" }
- ,{ GSN_LCP_HOLDOPCONF, "LCP_HOLDOPCONF" }
- ,{ GSN_LCP_HOLDOPREF, "LCP_HOLDOPREF" }
- ,{ GSN_LCP_HOLDOPREQ, "LCP_HOLDOPREQ" }
- ,{ GSN_LQH_RESTART_OP, "LQH_RESTART_OP" }
,{ GSN_LQH_TRANSCONF, "LQH_TRANSCONF" }
,{ GSN_LQH_TRANSREQ, "LQH_TRANSREQ" }
,{ GSN_LQHADDATTCONF, "LQHADDATTCONF" }
@@ -299,9 +282,6 @@ const GsnName SignalNames [] = {
,{ GSN_SHRINKCHECK2, "SHRINKCHECK2" }
,{ GSN_READ_CONFIG_REQ, "READ_CONFIG_REQ" }
,{ GSN_READ_CONFIG_CONF, "READ_CONFIG_CONF" }
- ,{ GSN_SR_FRAGIDCONF, "SR_FRAGIDCONF" }
- ,{ GSN_SR_FRAGIDREF, "SR_FRAGIDREF" }
- ,{ GSN_SR_FRAGIDREQ, "SR_FRAGIDREQ" }
,{ GSN_START_COPYCONF, "START_COPYCONF" }
,{ GSN_START_COPYREF, "START_COPYREF" }
,{ GSN_START_COPYREQ, "START_COPYREQ" }
@@ -348,16 +328,6 @@ const GsnName SignalNames [] = {
,{ GSN_TUP_ADD_ATTRREQ, "TUP_ADD_ATTRREQ" }
,{ GSN_TUP_ATTRINFO, "TUP_ATTRINFO" }
,{ GSN_TUP_COMMITREQ, "TUP_COMMITREQ" }
- ,{ GSN_TUP_LCPCONF, "TUP_LCPCONF" }
- ,{ GSN_TUP_LCPREF, "TUP_LCPREF" }
- ,{ GSN_TUP_LCPREQ, "TUP_LCPREQ" }
- ,{ GSN_TUP_LCPSTARTED, "TUP_LCPSTARTED" }
- ,{ GSN_TUP_PREPLCPCONF, "TUP_PREPLCPCONF" }
- ,{ GSN_TUP_PREPLCPREF, "TUP_PREPLCPREF" }
- ,{ GSN_TUP_PREPLCPREQ, "TUP_PREPLCPREQ" }
- ,{ GSN_TUP_SRCONF, "TUP_SRCONF" }
- ,{ GSN_TUP_SRREF, "TUP_SRREF" }
- ,{ GSN_TUP_SRREQ, "TUP_SRREQ" }
,{ GSN_TUPFRAGCONF, "TUPFRAGCONF" }
,{ GSN_TUPFRAGREF, "TUPFRAGREF" }
,{ GSN_TUPFRAGREQ, "TUPFRAGREQ" }
@@ -631,6 +601,33 @@ const GsnName SignalNames [] = {
,{ GSN_TUX_MAINT_REF, "TUX_MAINT_REF" }
,{ GSN_TUX_BOUND_INFO, "TUX_BOUND_INFO" }
,{ GSN_ACC_LOCKREQ, "ACC_LOCKREQ" }
+
+ ,{ GSN_CREATE_FILEGROUP_REQ, "CREATE_FILEGROUP_REQ" }
+ ,{ GSN_CREATE_FILEGROUP_REF, "CREATE_FILEGROUP_REF" }
+ ,{ GSN_CREATE_FILEGROUP_CONF, "CREATE_FILEGROUP_CONF" }
+
+ ,{ GSN_CREATE_FILE_REQ, "CREATE_FILE_REQ" }
+ ,{ GSN_CREATE_FILE_REF, "CREATE_FILE_REF" }
+ ,{ GSN_CREATE_FILE_CONF, "CREATE_FILE_CONF" }
+
+ ,{ GSN_DROP_FILEGROUP_REQ, "DROP_FILEGROUP_REQ" }
+ ,{ GSN_DROP_FILEGROUP_REF, "DROP_FILEGROUP_REF" }
+ ,{ GSN_DROP_FILEGROUP_CONF, "DROP_FILEGROUP_CONF" }
+
+ ,{ GSN_DROP_FILE_REQ, "DROP_FILE_REQ" }
+ ,{ GSN_DROP_FILE_REF, "DROP_FILE_REF" }
+ ,{ GSN_DROP_FILE_CONF, "DROP_FILE_CONF" }
+
+ ,{ GSN_CREATE_OBJ_REQ, "CREATE_OBJ_REQ" }
+ ,{ GSN_CREATE_OBJ_REF, "CREATE_OBJ_REF" }
+ ,{ GSN_CREATE_OBJ_CONF, "CREATE_OBJ_CONF" }
+
+ ,{ GSN_DROP_OBJ_REQ, "DROP_OBJ_REQ" }
+ ,{ GSN_DROP_OBJ_REF, "DROP_OBJ_REF" }
+ ,{ GSN_DROP_OBJ_CONF, "DROP_OBJ_CONF" }
+ ,{ GSN_LCP_PREPARE_REQ, "LCP_PREPARE_REQ" }
+ ,{ GSN_LCP_PREPARE_REF, "LCP_PREPARE_REF" }
+ ,{ GSN_LCP_PREPARE_CONF, "LCP_PREPARE_CONF" }
};
const unsigned short NO_OF_SIGNAL_NAMES = sizeof(SignalNames)/sizeof(GsnName);
diff --git a/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp b/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
index 3918bd5db26..f74382295d8 100644
--- a/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
@@ -51,7 +51,11 @@ printTCKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiver
if (sig->getExecutingTrigger(requestInfo)) {
fprintf(output, "Trigger ");
}
-
+
+ if (sig->getNoDiskFlag(requestInfo)) {
+ fprintf(output, "NoDisk ");
+ }
+
UintR TcommitType = sig->getAbortOption(requestInfo);
if (TcommitType == TcKeyReq::AbortOnError) {
fprintf(output, "AbortOnError ");
diff --git a/storage/ndb/src/common/debugger/signaldata/TuxMaint.cpp b/storage/ndb/src/common/debugger/signaldata/TuxMaint.cpp
index ba6a299b77d..a9ed63abe44 100644
--- a/storage/ndb/src/common/debugger/signaldata/TuxMaint.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/TuxMaint.cpp
@@ -27,7 +27,7 @@ printTUX_MAINT_REQ(FILE* output, const Uint32* theData, Uint32 len, Uint16 rbn)
fprintf(output, " table: id=%u", sig->tableId);
fprintf(output, " index: id=%u", sig->indexId);
fprintf(output, " fragment: id=%u\n", sig->fragId);
- fprintf(output, " tuple: loc=%u.%u version=%u\n", sig->pageId, sig->pageOffset, sig->tupVersion);
+ fprintf(output, " tuple: loc=%u.%u version=%u\n", sig->pageId, sig->pageIndex, sig->tupVersion);
const Uint32 opCode = sig->opInfo & 0xFF;
const Uint32 opFlag = sig->opInfo >> 8;
switch (opCode ) {
diff --git a/storage/ndb/src/kernel/Makefile.am b/storage/ndb/src/kernel/Makefile.am
index 9f8331ecf81..6746cab2611 100644
--- a/storage/ndb/src/kernel/Makefile.am
+++ b/storage/ndb/src/kernel/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = error blocks vm
+SUBDIRS = vm error blocks
include $(top_srcdir)/storage/ndb/config/common.mk.am
@@ -23,7 +23,8 @@ INCLUDES += \
-Iblocks/backup \
-Iblocks/dbutil \
-Iblocks/suma \
- -Iblocks/dbtux
+ -Iblocks/dbtux \
+ -Iblocks
LDADD += \
blocks/cmvmi/libcmvmi.a \
@@ -41,6 +42,7 @@ LDADD += \
blocks/dbutil/libdbutil.a \
blocks/suma/libsuma.a \
blocks/dbtux/libdbtux.a \
+ blocks/libblocks.a \
vm/libkernel.a \
error/liberror.a \
$(top_builddir)/storage/ndb/src/common/transporter/libtransporter.la \
diff --git a/storage/ndb/src/kernel/SimBlockList.cpp b/storage/ndb/src/kernel/SimBlockList.cpp
index e2c342af34a..8a1121f8cc8 100644
--- a/storage/ndb/src/kernel/SimBlockList.cpp
+++ b/storage/ndb/src/kernel/SimBlockList.cpp
@@ -31,6 +31,10 @@
#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
@@ -66,10 +70,13 @@ void * operator new (size_t sz, SIMBLOCKLIST_DUMMY dummy){
void
SimBlockList::load(const Configuration & conf){
- noOfBlocks = 15;
+ noOfBlocks = NO_OF_BLOCKS;
theList = new SimulatedBlock * [noOfBlocks];
Dbdict* dbdict = 0;
Dbdih* dbdih = 0;
+ Pgman* pg = 0;
+ Lgman* lg = 0;
+ Tsman* ts = 0;
SimulatedBlock * fs = 0;
{
@@ -82,27 +89,26 @@ SimBlockList::load(const Configuration & conf){
}
}
- theList[0] = NEW_BLOCK(Dbacc)(conf);
- theList[1] = NEW_BLOCK(Cmvmi)(conf);
- theList[2] = fs;
- theList[3] = dbdict = NEW_BLOCK(Dbdict)(conf);
- theList[4] = dbdih = NEW_BLOCK(Dbdih)(conf);
- theList[5] = NEW_BLOCK(Dblqh)(conf);
- theList[6] = NEW_BLOCK(Dbtc)(conf);
- theList[7] = NEW_BLOCK(Dbtup)(conf);
- theList[8] = NEW_BLOCK(Ndbcntr)(conf);
- theList[9] = NEW_BLOCK(Qmgr)(conf);
- theList[10] = NEW_BLOCK(Trix)(conf);
- theList[11] = NEW_BLOCK(Backup)(conf);
- theList[12] = NEW_BLOCK(DbUtil)(conf);
- theList[13] = NEW_BLOCK(Suma)(conf);
- theList[14] = NEW_BLOCK(Dbtux)(conf);
-
- // Metadata common part shared by block instances
- ptrMetaDataCommon = new MetaData::Common(*dbdict, *dbdih);
- for (int i = 0; i < noOfBlocks; i++)
- if(theList[i])
- theList[i]->setMetaDataCommon(ptrMetaDataCommon);
+ theList[0] = pg = NEW_BLOCK(Pgman)(conf);
+ theList[1] = lg = NEW_BLOCK(Lgman)(conf);
+ theList[2] = ts = NEW_BLOCK(Tsman)(conf, pg, lg);
+ theList[3] = NEW_BLOCK(Dbacc)(conf);
+ theList[4] = NEW_BLOCK(Cmvmi)(conf);
+ theList[5] = fs;
+ theList[6] = dbdict = NEW_BLOCK(Dbdict)(conf);
+ theList[7] = dbdih = NEW_BLOCK(Dbdih)(conf);
+ theList[8] = NEW_BLOCK(Dblqh)(conf);
+ theList[9] = NEW_BLOCK(Dbtc)(conf);
+ theList[10] = NEW_BLOCK(Dbtup)(conf, pg);
+ theList[11] = NEW_BLOCK(Ndbcntr)(conf);
+ theList[12] = NEW_BLOCK(Qmgr)(conf);
+ theList[13] = NEW_BLOCK(Trix)(conf);
+ theList[14] = NEW_BLOCK(Backup)(conf);
+ theList[15] = NEW_BLOCK(DbUtil)(conf);
+ theList[16] = NEW_BLOCK(Suma)(conf);
+ theList[17] = NEW_BLOCK(Dbtux)(conf);
+ theList[18] = NEW_BLOCK(Restore)(conf);
+ assert(NO_OF_BLOCKS == 19);
}
void
@@ -116,9 +122,7 @@ SimBlockList::unload(){
}
}
delete [] theList;
- delete ptrMetaDataCommon;
theList = 0;
noOfBlocks = 0;
- ptrMetaDataCommon = 0;
}
}
diff --git a/storage/ndb/src/kernel/blocks/Makefile.am b/storage/ndb/src/kernel/blocks/Makefile.am
index 8addf257003..389d0cc7aaa 100644
--- a/storage/ndb/src/kernel/blocks/Makefile.am
+++ b/storage/ndb/src/kernel/blocks/Makefile.am
@@ -15,4 +15,23 @@ SUBDIRS = \
suma \
dbtux
+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
+
+ndbtools_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
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
+
windoze-dsp:
diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.cpp b/storage/ndb/src/kernel/blocks/backup/Backup.cpp
index 2379bd6cf21..ac74b0aa40f 100644
--- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -52,6 +52,7 @@
#include <AttributeHeader.hpp>
#include <signaldata/WaitGCP.hpp>
+#include <signaldata/LCP.hpp>
#include <NdbTick.h>
@@ -66,112 +67,13 @@ static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
#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::execREAD_CONFIG_REQ(Signal* signal)
-{
- jamEntry();
-
- const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
-
- Uint32 ref = req->senderRef;
- Uint32 senderData = req->senderData;
-
- const ndb_mgm_configuration_iterator * p =
- theConfiguration.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- c_nodePool.setSize(MAX_NDB_NODES);
-
- Uint32 noBackups = 0, noTables = 0, noAttribs = 0;
- 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 * 2 * 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);
- }
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
void
Backup::execSTTOR(Signal* signal)
{
@@ -426,13 +328,27 @@ Backup::execDUMP_STATE_ORD(Signal* signal)
if(signal->getLength() == 2 && signal->theData[1] == 2424)
{
- ndbrequire(c_tablePool.getSize() == c_tablePool.getNoOfFree());
- ndbrequire(c_attributePool.getSize() == c_attributePool.getNoOfFree());
- ndbrequire(c_backupPool.getSize() == c_backupPool.getNoOfFree());
- ndbrequire(c_backupFilePool.getSize() == c_backupFilePool.getNoOfFree());
- ndbrequire(c_pagePool.getSize() == c_pagePool.getNoOfFree());
- ndbrequire(c_fragmentPool.getSize() == c_fragmentPool.getNoOfFree());
- ndbrequire(c_triggerPool.getSize() == c_triggerPool.getNoOfFree());
+ /**
+ * 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.p->pages.getSize() +
+ lcp_file.p->pages.getSize());
}
}
}
@@ -1339,11 +1255,12 @@ Backup::createAttributeMask(TablePtr tabPtr,
{
mask.clear();
Table & table = * tabPtr.p;
- for(Uint32 i = 0; i<table.noOfAttributes; i++) {
+ Ptr<Attribute> attrPtr;
+ table.attributes.first(attrPtr);
+ for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
+ {
jam();
- AttributePtr attr;
- table.attributes.getPtr(attr, i);
- mask.set(i);
+ mask.set(attrPtr.p->data.attrId);
}
}
@@ -2336,6 +2253,27 @@ Backup::abort_scan(Signal * signal, BackupRecordPtr ptr)
void
Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode)
{
+ if(ptr.p->is_lcp())
+ {
+ jam();
+ TablePtr tabPtr;
+ FragmentPtr fragPtr;
+
+ ptr.p->setErrorCode(errCode);
+ 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;
ptr.p->setErrorCode(errCode);
ndbrequire(ptr.p->errorCode != 0);
@@ -2407,7 +2345,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
ptr.p->noOfLogBytes = 0;
ptr.p->noOfLogRecords = 0;
ptr.p->currGCP = 0;
-
+
/**
* Allocate files
*/
@@ -2442,9 +2380,22 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
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,
@@ -2482,15 +2433,22 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
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
- files[0].p->fileType = BackupFormat::CTL_FILE;
- files[1].p->fileType = BackupFormat::LOG_FILE;
- files[2].p->fileType = BackupFormat::DATA_FILE;
-
- ptr.p->ctlFilePtr = files[0].i;
- ptr.p->logFilePtr = files[1].i;
- ptr.p->dataFilePtr = files[2].i;
-
+
if (!verifyNodesAlive(ptr, ptr.p->nodes)) {
jam();
defineBackupRef(signal, ptr, DefineBackupRef::Undefined);
@@ -2508,6 +2466,13 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
return;
}//if
+ if(ptr.p->is_lcp())
+ {
+ jam();
+ getFragmentInfoDone(signal, ptr);
+ return;
+ }
+
/**
* Not implemented
*/
@@ -2591,8 +2556,7 @@ Backup::openFiles(Signal* signal, BackupRecordPtr ptr)
FsOpenReq::OM_WRITEONLY |
FsOpenReq::OM_TRUNCATE |
FsOpenReq::OM_CREATE |
- FsOpenReq::OM_APPEND |
- FsOpenReq::OM_SYNC;
+ FsOpenReq::OM_APPEND;
FsOpenReq::v2_setCount(req->fileNumber, 0xFFFFFFFF);
/**
@@ -2712,30 +2676,44 @@ Backup::openFilesReply(Signal* signal,
return;
}//if
- /**
- * 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
-
+ 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
*/
@@ -2743,14 +2721,14 @@ Backup::openFilesReply(Signal* signal,
filePtr.p->fileRunning = 1;
signal->theData[0] = BackupContinueB::START_FILE_THREAD;
- signal->theData[1] = ptr.p->ctlFilePtr;
+ signal->theData[1] = filePtr.i;
sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 2);
/**
* Insert table list in ctl file
*/
FsBuffer & buf = filePtr.p->operation.dataBuffer;
-
+
const Uint32 sz =
(sizeof(BackupFormat::CtlFile::TableList) >> 2) +
ptr.p->tables.noOfElements() - 1;
@@ -2784,7 +2762,7 @@ Backup::openFilesReply(Signal* signal,
* 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;
@@ -2867,7 +2845,6 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
if(ptr.p->pages.seize(noPages) == false) {
jam();
ptr.p->setErrorCode(DefineBackupRef::FailedAllocateTableMem);
- ndbrequire(false);
releaseSections(signal);
defineBackupRef(signal, ptr);
return;
@@ -2927,19 +2904,25 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
jam();
ptr.p->tables.release(tmp);
}
- else
+ else if(!ptr.p->is_lcp())
{
jam();
signal->theData[0] = tmp.p->tableId;
signal->theData[1] = 1; // lock
EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
}
-
+
if(tabPtr.i == RNIL) {
jam();
ptr.p->pages.release();
+ if(ptr.p->is_lcp())
+ {
+ lcp_open_file_done(signal, ptr);
+ return;
+ }
+
ndbrequire(ptr.p->tables.first(tabPtr));
signal->theData[0] = RNIL;
signal->theData[1] = tabPtr.p->tableId;
@@ -2980,6 +2963,11 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
jam();
return tabPtr;
}
+
+ /**
+ * LCP should not save disk attributes but only mem attributes
+ */
+ bool lcp = ptr.p->is_lcp();
/**
* Initialize table object
@@ -2996,13 +2984,7 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
tabPtr.p->triggerAllocated[1] = false;
tabPtr.p->triggerAllocated[2] = false;
- if(tabPtr.p->attributes.seize(tabPtr.p->noOfAttributes) == false) {
- jam();
- ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord);
- tabPtr.i = RNIL;
- return tabPtr;
- }//if
-
+ Uint32 disk = 0;
const Uint32 count = tabPtr.p->noOfAttributes;
for(Uint32 i = 0; i<count; i++) {
jam();
@@ -3013,47 +2995,70 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
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;
- tabPtr.p->attributes.getPtr(attrPtr, tmp.AttributeId);
+ if(!tabPtr.p->attributes.seize(attrPtr))
+ {
+ jam();
+ ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord);
+ tabPtr.i = RNIL;
+ return tabPtr;
+ }
- attrPtr.p->data.nullable = tmp.AttributeNullableFlag;
- attrPtr.p->data.fixed = (tmp.AttributeArraySize != 0);
- attrPtr.p->data.sz32 = sz32;
+ 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;
+
/**
- * Either
- * 1) Fixed
- * 2) Nullable
- * 3) Variable
+ * 1) Fixed non-nullable
+ * 2) Other
*/
- if(attrPtr.p->data.fixed == true && attrPtr.p->data.nullable == false) {
+ 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;
- }//if
-
- if(attrPtr.p->data.fixed == true && attrPtr.p->data.nullable == true) {
- jam();
- attrPtr.p->data.offset = 0;
-
- attrPtr.p->data.offsetNull = tabPtr.p->noOfNull;
- tabPtr.p->noOfNull++;
+ } else {
+ attrPtr.p->data.offset = ~0;
tabPtr.p->noOfVariable++;
- }//if
+ }
+ }//for
+
+ if(lcp && disk)
+ {
+ /**
+ * Remove all disk attributes, but add DISK_REF (8 bytes)
+ */
+ tabPtr.p->noOfAttributes -= (disk - 1);
- if(attrPtr.p->data.fixed == false) {
- jam();
- tabPtr.p->noOfVariable++;
- ndbrequire(0);
- }//if
+ AttributePtr attrPtr;
+ ndbrequire(tabPtr.p->attributes.seize(attrPtr));
- it.next(); // Move Past EndOfAttribute
- }//for
+ Uint32 sz32 = 2;
+ attrPtr.p->data.m_flags = 0;
+ attrPtr.p->data.attrId = AttributeHeader::DISK_REF;
+ attrPtr.p->data.m_flags = Attribute::COL_FIXED;
+ attrPtr.p->data.sz32 = sz32;
+
+ attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
+ tabPtr.p->sz_FixedAttributes += sz32;
+ }
return tabPtr;
}
@@ -3083,6 +3088,7 @@ Backup::execDI_FCOUNTCONF(Signal* signal)
fragPtr.p->scanned = 0;
fragPtr.p->scanning = 0;
fragPtr.p->tableId = tableId;
+ fragPtr.p->fragmentId = i;
fragPtr.p->node = RNIL;
}//for
@@ -3154,7 +3160,7 @@ Backup::execDIGETPRIMCONF(Signal* signal)
FragmentPtr fragPtr;
tabPtr.p->fragments.getPtr(fragPtr, fragNo);
-
+
fragPtr.p->node = signal->theData[2];
getFragmentInfo(signal, ptr, tabPtr, fragNo + 1);
@@ -3279,7 +3285,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
const Uint32 tableId = req->tableId;
const Uint32 fragNo = req->fragmentNo;
const Uint32 count = req->count;
-
+
/**
* Get backup record
*/
@@ -3316,7 +3322,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
ndbrequire(fragPtr.p->scanned == 0);
ndbrequire(fragPtr.p->scanning == 0 ||
refToNode(ptr.p->masterRef) == getOwnNodeId());
-
+
/**
* Init operation
*/
@@ -3329,7 +3335,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
/**
* Check for space in buffer
*/
- if(!filePtr.p->operation.newFragment(tableId, fragNo)) {
+ if(!filePtr.p->operation.newFragment(tableId, fragPtr.p->fragmentId)) {
jam();
req->count = count + 1;
sendSignalWithDelay(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal, 50,
@@ -3342,8 +3348,8 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
* Mark things as "in use"
*/
fragPtr.p->scanning = 1;
- filePtr.p->fragmentNo = fragNo;
-
+ filePtr.p->fragmentNo = fragPtr.p->fragmentId;
+
/**
* Start scan
*/
@@ -3358,7 +3364,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
req->senderData = filePtr.i;
req->resultRef = reference();
req->schemaVersion = table.schemaVersion;
- req->fragmentNoKeyLen = fragNo;
+ req->fragmentNoKeyLen = fragPtr.p->fragmentId;
req->requestInfo = 0;
req->savePointId = 0;
req->tableId = table.tableId;
@@ -3367,6 +3373,12 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
ScanFragReq::setHoldLockFlag(req->requestInfo, 0);
ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
ScanFragReq::setAttrLen(req->requestInfo,attrLen);
+ if (ptr.p->is_lcp())
+ {
+ ScanFragReq::setScanPrio(req->requestInfo, 1);
+ ScanFragReq::setTupScanFlag(req->requestInfo, 1);
+ ScanFragReq::setNoDiskFlag(req->requestInfo, 1);
+ }
req->transId1 = 0;
req->transId2 = (BACKUP << 20) + (getOwnNodeId() << 8);
req->clientOpPtr= filePtr.i;
@@ -3387,13 +3399,20 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
signal->theData[7] = 0;
Uint32 dataPos = 8;
- Uint32 i;
- for(i = 0; i<table.noOfAttributes; i++) {
+ Ptr<Attribute> attrPtr;
+ table.attributes.first(attrPtr);
+ for(; !attrPtr.isNull(); table.attributes.next(attrPtr))
+ {
jam();
- AttributePtr attr;
- table.attributes.getPtr(attr, i);
- AttributeHeader::init(&signal->theData[dataPos], i, 0);
+ /**
+ * 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();
@@ -3440,65 +3459,57 @@ Backup::execTRANSID_AI(Signal* signal)
op.attrSzTotal += dataLen;
Uint32 srcSz = dataLen;
+ Uint32 usedSz = 0;
const Uint32 * src = &signal->theData[3];
- Uint32 * dst = op.dst;
- Uint32 dstSz = op.attrSzLeft;
+ Ptr<Attribute> attrPtr;
+ table.attributes.first(attrPtr);
+ Uint32 columnNo = 0;
- while(srcSz > 0) {
+ while (usedSz < srcSz)
+ {
jam();
-
- if(dstSz == 0) {
- 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 = table.attributes.getPtr(attrId)->data;
-
- srcSz -= attrHead.getHeaderSize();
- src += attrHead.getHeaderSize();
-
- if(null) {
- jam();
- ndbrequire(attr.nullable);
- op.nullAttribute(attr.offsetNull);
- dstSz = 0;
- continue;
- }//if
+
+ /**
+ * 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();
- dstSz = attrHead.getDataSize();
- ndbrequire(dstSz == attr.sz32);
- if(attr.fixed && ! attr.nullable) {
- jam();
- dst = op.newAttrib(attr.offset, dstSz);
- } else if (attr.fixed && attr.nullable) {
- jam();
- dst = op.newNullable(attrId, dstSz);
+ 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 {
- ndbrequire(false);
- //dst = op.newVariable(attrId, attrSize);
- }//if
- }//if
-
- const Uint32 szCopy = (dstSz > srcSz) ? srcSz : dstSz;
- memcpy(dst, src, (szCopy << 2));
-
- srcSz -= szCopy;
- dstSz -= szCopy;
- src += szCopy;
- dst += szCopy;
- }//while
- op.dst = dst;
- op.attrSzLeft = dstSz;
-
- if(op.finished()){
- jam();
- op.newRecord(op.dst);
+ 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
@@ -3693,6 +3704,7 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
conf->fragmentNo = filePtr.p->fragmentNo;
conf->noOfRecords = op.noOfRecords;
conf->noOfBytes = op.noOfBytes;
+
sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
BackupFragmentConf::SignalLength, JBB);
@@ -4230,6 +4242,7 @@ Backup::execFSCLOSECONF(Signal* signal)
ndbrequire(filePtr.p->scanRunning == 0);
filePtr.p->fileOpened = 0;
+ filePtr.p->operation.dataBuffer.reset();
BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
@@ -4251,6 +4264,12 @@ void
Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr)
{
jam();
+
+ if(ptr.p->is_lcp())
+ {
+ lcp_close_file_conf(signal, ptr);
+ return;
+ }
jam();
BackupFilePtr filePtr;
@@ -4550,3 +4569,203 @@ Backup::execFSREMOVECONF(Signal* signal){
c_backups.release(ptr);
}
+/**
+ * LCP
+ */
+void
+Backup::execLCP_PREPARE_REQ(Signal* signal)
+{
+ jamEntry();
+ LcpPrepareReq req = *(LcpPrepareReq*)signal->getDataPtr();
+
+ BackupRecordPtr ptr;
+ c_backupPool.getPtr(ptr, req.backupPtr);
+
+ bool first= true;
+ TablePtr tabPtr;
+ if(ptr.p->tables.first(tabPtr) && tabPtr.p->tableId != req.tableId)
+ {
+ jam();
+ first= false;
+ tabPtr.p->attributes.release();
+ tabPtr.p->fragments.release();
+ ptr.p->tables.release();
+ ptr.p->errorCode = 0;
+ }
+
+ if(ptr.p->tables.first(tabPtr) && ptr.p->errorCode == 0)
+ {
+ jam();
+ FragmentPtr fragPtr;
+ tabPtr.p->fragments.getPtr(fragPtr, 0);
+ fragPtr.p->fragmentId = req.fragmentId;
+
+ lcp_open_file_done(signal, ptr);
+ return;
+ }
+ else if(ptr.p->errorCode == 0)
+ {
+ jam();
+ FragmentPtr fragPtr;
+ 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;
+ }
+ else
+ {
+ jam();
+ FragmentPtr fragPtr;
+ tabPtr.p->fragments.getPtr(fragPtr, 0);
+ fragPtr.p->fragmentId = req.fragmentId;
+ defineBackupRef(signal, ptr, ptr.p->errorCode);
+ return;
+ }
+
+ if(first)
+ {
+ jam();
+ // start file thread
+ ptr.p->backupId= req.backupId;
+ lcp_open_file(signal, ptr);
+ return;
+ }
+ else
+ {
+ jam();
+ ndbrequire(ptr.p->backupId == req.backupId);
+ }
+
+ /**
+ * Close previous file
+ */
+ jam();
+ BackupFilePtr filePtr;
+ c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
+ filePtr.p->fileClosing = 1;
+ filePtr.p->operation.dataBuffer.eof();
+}
+
+void
+Backup::lcp_close_file_conf(Signal* signal, BackupRecordPtr ptr)
+{
+ if(!ptr.p->tables.isEmpty())
+ {
+ jam();
+ lcp_open_file(signal, ptr);
+ return;
+ }
+
+ lcp_send_end_lcp_conf(signal, ptr);
+}
+
+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::v2_setCount(req->fileNumber, 0xFFFFFFFF);
+
+ TablePtr tabPtr;
+ FragmentPtr fragPtr;
+
+ ndbrequire(ptr.p->tables.first(tabPtr));
+ tabPtr.p->fragments.getPtr(fragPtr, 0);
+
+ /**
+ * Lcp file
+ */
+ BackupFilePtr filePtr;
+ c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
+ ndbrequire(filePtr.p->fileRunning == 0);
+ filePtr.p->fileClosing = 0;
+ filePtr.p->fileRunning = 1;
+
+ 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);
+ 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);
+
+ 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);
+}
+
+void
+Backup::execEND_LCPREQ(Signal* signal)
+{
+ EndLcpReq* req= (EndLcpReq*)signal->getDataPtr();
+
+ BackupRecordPtr ptr;
+ c_backupPool.getPtr(ptr, req->backupPtr);
+ ndbrequire(ptr.p->backupId == req->backupId);
+
+ ptr.p->slaveState.setState(STOPPING);
+
+ TablePtr tabPtr;
+ if(ptr.p->tables.first(tabPtr))
+ {
+ tabPtr.p->attributes.release();
+ tabPtr.p->fragments.release();
+ ptr.p->tables.release();
+
+ BackupFilePtr filePtr;
+ c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
+ filePtr.p->fileClosing = 1;
+ filePtr.p->operation.dataBuffer.eof();
+ return;
+ }
+
+ lcp_send_end_lcp_conf(signal, ptr);
+}
+
+void
+Backup::lcp_send_end_lcp_conf(Signal* signal, BackupRecordPtr ptr)
+{
+ EndLcpConf* conf= (EndLcpConf*)signal->getDataPtr();
+
+ conf->senderData = ptr.p->clientData;
+ conf->senderRef = reference();
+
+ ptr.p->errorCode = 0;
+ ptr.p->slaveState.setState(CLEANING);
+ ptr.p->slaveState.setState(INITIAL);
+ ptr.p->slaveState.setState(DEFINING);
+ ptr.p->slaveState.setState(DEFINED);
+
+ 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
index c455e32fa67..6d9e0dc5aed 100644
--- a/storage/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -28,6 +28,7 @@
#include <SLList.hpp>
#include <ArrayList.hpp>
+#include <DLFifoList.hpp>
#include <SignalCounter.hpp>
#include <blocks/mutexes.hpp>
@@ -147,7 +148,9 @@ protected:
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);
@@ -169,24 +172,33 @@ public:
typedef Ptr<Page32> Page32Ptr;
struct Attribute {
+ enum Flags {
+ COL_NULLABLE = 0x1,
+ COL_FIXED = 0x2,
+ COL_DISK = 0x4
+ };
struct Data {
- Uint8 nullable;
- Uint8 fixed;
- Uint8 unused;
- Uint8 unused2;
+ Uint16 m_flags;
+ Uint16 attrId;
Uint32 sz32; // No of 32 bit words
Uint32 offset; // Relative DataFixedAttributes/DataFixedKeys
Uint32 offsetNull; // In NullBitmask
} data;
- Uint32 nextPool;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
};
typedef Ptr<Attribute> AttributePtr;
struct Fragment {
Uint32 tableId;
- Uint32 node;
- Uint16 scanned; // 0 = not scanned x = scanned by node x
- Uint16 scanning; // 0 = not scanning x = scanning on node x
+ 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;
@@ -204,7 +216,7 @@ public:
Uint32 triggerIds[3];
bool triggerAllocated[3];
- Array<Attribute> attributes;
+ DLFifoList<Attribute> attributes;
Array<Fragment> fragments;
Uint32 nextList;
@@ -243,6 +255,7 @@ public:
/**
* Per attribute
*/
+ void nullVariable();
void nullAttribute(Uint32 nullOffset);
Uint32 * newNullable(Uint32 attrId, Uint32 sz);
Uint32 * newAttrib(Uint32 offset, Uint32 sz);
@@ -264,7 +277,6 @@ public:
public:
Uint32* dst;
- Uint32 attrSzLeft; // No of words missing for current attribute
Uint32 attrSzTotal; // No of AI words received
Uint32 tablePtr; // Ptr.i to current table
@@ -486,6 +498,10 @@ public:
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) {
@@ -500,6 +516,7 @@ public:
Uint32 m_logBufferSize;
Uint32 m_minWriteSize;
Uint32 m_maxWriteSize;
+ Uint32 m_lcp_buffer_size;
};
/**
@@ -604,6 +621,11 @@ public:
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);
+ void lcp_send_end_lcp_conf(Signal* signal, BackupRecordPtr);
};
inline
@@ -616,14 +638,13 @@ Backup::OperationRecord::newRecord(Uint32 * p){
dst_VariableData = (BackupFormat::DataFile::VariableData*)p;
BitmaskImpl::clear(sz_Bitmask, dst_Bitmask);
attrLeft = noOfAttributes;
- attrSzLeft = attrSzTotal = 0;
+ attrSzTotal = 0;
}
inline
Uint32 *
Backup::OperationRecord::newAttrib(Uint32 offset, Uint32 sz){
attrLeft--;
- attrSzLeft = sz;
dst = dst_FixedAttribs + offset;
return dst;
}
@@ -636,16 +657,24 @@ Backup::OperationRecord::nullAttribute(Uint32 offsetNull){
}
inline
+void
+Backup::OperationRecord::nullVariable()
+{
+ attrLeft --;
+}
+
+inline
Uint32 *
Backup::OperationRecord::newNullable(Uint32 id, Uint32 sz){
+ Uint32 sz32 = (sz + 3) >> 2;
+
attrLeft--;
- attrSzLeft = sz;
dst = &dst_VariableData->Data[0];
dst_VariableData->Sz = htonl(sz);
dst_VariableData->Id = htonl(id);
- dst_VariableData = (BackupFormat::DataFile::VariableData *)(dst + sz);
+ dst_VariableData = (BackupFormat::DataFile::VariableData *)(dst + sz32);
// Clear all bits on newRecord -> dont need to clear this
// BitmaskImpl::clear(sz_Bitmask, dst_Bitmask, offsetNull);
@@ -655,21 +684,22 @@ Backup::OperationRecord::newNullable(Uint32 id, Uint32 sz){
inline
Uint32 *
Backup::OperationRecord::newVariable(Uint32 id, Uint32 sz){
+ Uint32 sz32 = (sz + 3) >> 2;
+
attrLeft--;
- attrSzLeft = sz;
dst = &dst_VariableData->Data[0];
dst_VariableData->Sz = htonl(sz);
dst_VariableData->Id = htonl(id);
- dst_VariableData = (BackupFormat::DataFile::VariableData *)(dst + sz);
+ dst_VariableData = (BackupFormat::DataFile::VariableData *)(dst + sz32);
return dst;
}
inline
bool
Backup::OperationRecord::finished(){
- if(attrLeft != 0 || attrSzLeft != 0){
+ if(attrLeft != 0){
return false;
}
diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.txt b/storage/ndb/src/kernel/blocks/backup/Backup.txt
index 73942c6ebdc..acc9efff02d 100644
--- a/storage/ndb/src/kernel/blocks/backup/Backup.txt
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.txt
@@ -366,3 +366,65 @@ NF_COMPLETE_REP
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
index 65dd2ad9053..60f2edd6bed 100644
--- a/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
+++ b/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
@@ -54,7 +54,8 @@ struct BackupFormat {
enum FileType {
CTL_FILE = 1,
LOG_FILE = 2,
- DATA_FILE = 3
+ DATA_FILE = 3,
+ LCP_FILE = 4
};
/**
@@ -144,6 +145,17 @@ struct BackupFormat {
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
index 4c734d58c8e..d99ff7950c4 100644
--- a/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ b/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
@@ -44,7 +44,8 @@ Backup::Backup(const Configuration & conf) :
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);
@@ -118,6 +119,9 @@ Backup::Backup(const Configuration & conf) :
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()
@@ -129,3 +133,104 @@ 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 =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 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_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);
+
+ // 2 = no of replicas
+ c_fragmentPool.setSize(noBackups * NO_OF_FRAG_PER_NODE * noTables + 1);
+
+ 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;
+ 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);
+
+ { // Init all tables
+ ArrayList<Table> tables(c_tablePool);
+ TablePtr ptr;
+ while(tables.seize(ptr)){
+ new (ptr.p) Table(c_attributePool, c_fragmentPool);
+ }
+ tables.release();
+ }
+
+ {
+ ArrayList<BackupFile> ops(c_backupFilePool);
+ BackupFilePtr ptr;
+ while(ops.seize(ptr)){
+ new (ptr.p) BackupFile(* this, c_pagePool);
+ }
+ ops.release();
+ }
+
+ {
+ ArrayList<BackupRecord> recs(c_backupPool);
+ BackupRecordPtr ptr;
+ while(recs.seize(ptr)){
+ new (ptr.p) BackupRecord(* this, c_pagePool, c_tablePool,
+ c_backupFilePool, c_triggerPool);
+ }
+ recs.release();
+ }
+
+ // Initialize BAT for interface to file system
+ {
+ Page32Ptr p;
+ ndbrequire(c_pagePool.seizeId(p, 0));
+ c_startOfPages = (Uint32 *)p.p;
+ c_pagePool.release(p);
+
+ NewVARIABLE* bat = allocateBat(1);
+ bat[0].WA = c_startOfPages;
+ bat[0].nrr = c_pagePool.getSize()*sizeof(Page32)/sizeof(Uint32);
+ }
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
diff --git a/storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp b/storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp
index 2f3c7daae43..3a21be99792 100644
--- a/storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp
+++ b/storage/ndb/src/kernel/blocks/backup/FsBuffer.hpp
@@ -108,7 +108,11 @@ public:
Uint32 getMinRead() const { return m_minRead;}
Uint32 getFreeSize() const { return m_free; }
-
+
+ /**
+ * reset
+ */
+ void reset();
private:
@@ -198,13 +202,24 @@ FsBuffer::setup(Uint32 * Buffer,
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()
+{
+ assert(m_free = m_size);
+ assert(m_readIndex == m_writeIndex);
+ 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";
diff --git a/storage/ndb/src/kernel/blocks/backup/Makefile.am b/storage/ndb/src/kernel/blocks/backup/Makefile.am
index 8d1df032514..bad6833f531 100644
--- a/storage/ndb/src/kernel/blocks/backup/Makefile.am
+++ b/storage/ndb/src/kernel/blocks/backup/Makefile.am
@@ -3,6 +3,14 @@ noinst_LIBRARIES = libbackup.a
libbackup_a_SOURCES = Backup.cpp BackupInit.cpp
+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
index 89cc08ee9de..5e7f3216abc 100644
--- a/storage/ndb/src/kernel/blocks/backup/read.cpp
+++ b/storage/ndb/src/kernel/blocks/backup/read.cpp
@@ -22,6 +22,7 @@
#include "BackupFormat.hpp"
#include <AttributeHeader.hpp>
#include <SimpleProperties.hpp>
+#include <ndb_version.h>
bool readHeader(FILE*, BackupFormat::FileHeader *);
bool readFragHeader(FILE*, BackupFormat::DataFile::FragmentHeader *);
@@ -84,7 +85,7 @@ main(int argc, const char * argv[]){
ndbout << endl;
#endif
}
-
+
BackupFormat::DataFile::FragmentFooter fragFooter;
if(!readFragFooter(f, &fragFooter))
break;
@@ -156,6 +157,49 @@ main(int argc, const char * argv[]){
}
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;
@@ -178,7 +222,7 @@ readHeader(FILE* f, BackupFormat::FileHeader * dst){
RETURN_FALSE();
dst->NdbVersion = ntohl(dst->NdbVersion);
- if(dst->NdbVersion != 210)
+ if(dst->NdbVersion != NDB_VERSION)
RETURN_FALSE();
if(fread(&dst->SectionType, 4, 2, f) != 2)
@@ -200,10 +244,6 @@ readHeader(FILE* f, BackupFormat::FileHeader * dst){
dst->BackupId = ntohl(dst->BackupId);
dst->BackupKey_0 = ntohl(dst->BackupKey_0);
dst->BackupKey_1 = ntohl(dst->BackupKey_1);
-
- if(dst->FileType < BackupFormat::CTL_FILE ||
- dst->FileType > BackupFormat::DATA_FILE)
- RETURN_FALSE();
if(dst->ByteOrder != 0x12345678)
endian = true;
@@ -264,12 +304,17 @@ readRecord(FILE* f, Uint32 **dst){
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;
}
diff --git a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index 0c0f0cb5c71..7b6ebd76b33 100644
--- a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -93,7 +93,8 @@ Cmvmi::Cmvmi(const Configuration & conf) :
addRecSignal(GSN_TESTSIG, &Cmvmi::execTESTSIG);
subscriberPool.setSize(5);
-
+ m_global_page_pool.setSize(1024+256, true);
+
const ndb_mgm_configuration_iterator * db = theConfig.getOwnConfigIterator();
for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
Uint32 logLevel;
@@ -1013,6 +1014,9 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal)
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);
/**
*
diff --git a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index 8afbd87fe0f..a0e96a4515d 100644
--- a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -23,7 +23,7 @@
#include <SimulatedBlock.hpp>
// primary key is stored in TUP
-#include <Dbtup.hpp>
+#include "../dbtup/Dbtup.hpp"
#ifdef DBACC_C
// Debug Macros
@@ -62,8 +62,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
}\
*/
-#define dbgUndoword(ptr, ind, val)
-
// Constants
/** ------------------------------------------------------------------------
* THESE ARE CONSTANTS THAT ARE USED FOR DEFINING THE SIZE OF BUFFERS, THE
@@ -103,39 +101,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZOVERFLOW_PAGE_TYPE 1
#define ZDEFAULT_LIST 3
#define ZWORDS_IN_PAGE 2048
-/* --------------------------------------------------------------------------------- */
-/* CONSTANTS FOR THE ZERO PAGES */
-/* --------------------------------------------------------------------------------- */
-#define ZPAGEZERO_PREV_UNDOP 8
-#define ZPAGEZERO_NO_OVER_PAGE 9
-#define ZPAGEZERO_TABID 10
-#define ZPAGEZERO_FRAGID0 11
-#define ZPAGEZERO_FRAGID1 12
-#define ZPAGEZERO_HASH_CHECK 13
-#define ZPAGEZERO_DIRSIZE 14
-#define ZPAGEZERO_EXPCOUNTER 15
-#define ZPAGEZERO_NEXT_UNDO_FILE 16
-#define ZPAGEZERO_SLACK 17
-#define ZPAGEZERO_NO_PAGES 18
-#define ZPAGEZERO_HASHCHECKBIT 19
-#define ZPAGEZERO_K 20
-#define ZPAGEZERO_LHFRAGBITS 21
-#define ZPAGEZERO_LHDIRBITS 22
-#define ZPAGEZERO_LOCALKEYLEN 23
-#define ZPAGEZERO_MAXP 24
-#define ZPAGEZERO_MAXLOADFACTOR 25
-#define ZPAGEZERO_MINLOADFACTOR 26
-#define ZPAGEZERO_MYFID 27
-#define ZPAGEZERO_LAST_OVER_INDEX 28
-#define ZPAGEZERO_P 29
-#define ZPAGEZERO_NO_OF_ELEMENTS 30
-#define ZPAGEZERO_ELEMENT_LENGTH 31
-#define ZPAGEZERO_KEY_LENGTH 32
-#define ZPAGEZERO_NODETYPE 33
-#define ZPAGEZERO_SLACK_CHECK 34
-/* --------------------------------------------------------------------------------- */
-/* CONSTANTS IN ALPHABETICAL ORDER */
-/* --------------------------------------------------------------------------------- */
#define ZADDFRAG 0
#define ZCOPY_NEXT 1
#define ZCOPY_NEXT_COMMIT 2
@@ -151,17 +116,14 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZFS_CONNECTSIZE 300
#define ZFS_OPSIZE 100
#define ZKEYINKEYREQ 4
-#define ZLCP_CONNECTSIZE 30
#define ZLEFT 1
#define ZLOCALLOGFILE 2
#define ZLOCKED 0
#define ZMAXSCANSIGNALLEN 20
#define ZMAINKEYLEN 8
-#define ZMAX_UNDO_VERSION 4
#define ZNO_OF_DISK_VERSION 3
#define ZNO_OF_OP_PER_SIGNAL 20
//#define ZNOT_EMPTY_FRAGMENT 1
-#define ZNR_OF_UNDO_PAGE_GROUP 16
#define ZOP_HEAD_INFO_LN 3
#define ZOPRECSIZE 740
#define ZOVERFLOWRECSIZE 5
@@ -181,35 +143,21 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZSCAN_LOCK_ALL 3
#define ZSCAN_OP 5
#define ZSCAN_REC_SIZE 256
-#define ZSR_VERSION_REC_SIZE 16
#define ZSTAND_BY 2
#define ZTABLESIZE 16
#define ZTABMAXINDEX 3
#define ZUNDEFINED_OP 6
-#define ZUNDOHEADSIZE 7
#define ZUNLOCKED 1
-#define ZUNDOPAGE_BASE_ADD 2
-#define ZUNDOPAGEINDEXBITS 13
-#define ZUNDOPAGEINDEX_MASK 0x1fff
-#define ZWRITEPAGESIZE 8
-#define ZWRITE_UNDOPAGESIZE 2
-#define ZMIN_UNDO_PAGES_AT_COMMIT 4
-#define ZMIN_UNDO_PAGES_AT_OPERATION 10
-#define ZMIN_UNDO_PAGES_AT_EXPAND 16
/* --------------------------------------------------------------------------------- */
/* CONTINUEB CODES */
/* --------------------------------------------------------------------------------- */
-#define ZLOAD_BAL_LCP_TIMER 0
#define ZINITIALISE_RECORDS 1
-#define ZSR_READ_PAGES_ALLOC 2
-#define ZSTART_UNDO 3
#define ZSEND_SCAN_HBREP 4
#define ZREL_ROOT_FRAG 5
#define ZREL_FRAG 6
#define ZREL_DIR 7
#define ZREPORT_MEMORY_USAGE 8
-#define ZLCP_OP_WRITE_RT_BREAK 9
/* ------------------------------------------------------------------------- */
/* ERROR CODES */
@@ -235,7 +183,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZWRITE_ERROR 630
#define ZTO_OP_STATE_ERROR 631
#define ZTOO_EARLY_ACCESS_ERROR 632
-#define ZTEMPORARY_ACC_UNDO_FAILURE 677
#endif
class ElementHeader {
@@ -331,34 +278,9 @@ public:
enum State {
FREEFRAG = 0,
ACTIVEFRAG = 1,
- SEND_QUE_OP = 2,
- WAIT_ACC_LCPREQ = 3,
- LCP_SEND_PAGES = 4,
- LCP_SEND_OVER_PAGES = 5,
- LCP_SEND_ZERO_PAGE = 6,
- SR_READ_PAGES = 7,
- SR_READ_OVER_PAGES = 8,
- WAIT_ZERO_PAGE_STORED = 9,
+ //SEND_QUE_OP = 2,
WAIT_NOTHING = 10,
- WAIT_OPEN_UNDO_LCP = 11,
- WAIT_OPEN_UNDO_LCP_NEXT = 12,
- WAIT_OPEN_DATA_FILE_FOR_READ = 13,
- WAIT_OPEN_DATA_FILE_FOR_WRITE = 14,
- OPEN_UNDO_FILE_SR = 15,
- READ_UNDO_PAGE = 16,
- READ_UNDO_PAGE_AND_CLOSE = 17,
- WAIT_READ_DATA = 18,
- WAIT_READ_PAGE_ZERO = 19,
- WAIT_WRITE_DATA = 20,
- WAIT_WRITE_UNDO = 21,
- WAIT_WRITE_UNDO_EXIT = 22,
- WAIT_CLOSE_UNDO = 23,
- LCP_CLOSE_DATA = 24,
- SR_CLOSE_DATA = 25,
WAIT_ONE_CONF = 26,
- WAIT_TWO_CONF = 27,
- LCP_FREE = 28,
- LCP_ACTIVE = 29,
FREE_OP = 30,
WAIT_EXE_OP = 32,
WAIT_IN_QUEUE = 34,
@@ -378,33 +300,12 @@ enum State {
ADDSECONDFRAG = 49,
DELETEFIRSTFRAG = 50,
DELETESECONDFRAG = 51,
- ACTIVEROOT = 52,
- LCP_CREATION = 53
+ ACTIVEROOT = 52
};
// Records
/* --------------------------------------------------------------------------------- */
-/* UNDO HEADER RECORD */
-/* --------------------------------------------------------------------------------- */
-
- struct UndoHeader {
- enum UndoHeaderType{
- ZPAGE_INFO = 0,
- ZOVER_PAGE_INFO = 1,
- ZOP_INFO = 2,
- ZNO_UNDORECORD_TYPES = 3
- };
- UintR tableId;
- UintR rootFragId;
- UintR localFragId;
- UintR variousInfo;
- UintR logicalPageId;
- UintR prevUndoAddressForThisFrag;
- UintR prevUndoAddress;
- };
-
-/* --------------------------------------------------------------------------------- */
/* DIRECTORY RANGE */
/* --------------------------------------------------------------------------------- */
struct DirRange {
@@ -427,19 +328,26 @@ struct Directoryarray {
/* REC A POINTER TO FRAGMENT RECORD IS SAVED IN ROOTFRAGMENTREC FRAGMENT */
/* --------------------------------------------------------------------------------- */
struct Fragmentrec {
-//-----------------------------------------------------------------------------
-// References to long key pages with free area. Some type of buddy structure
-// where references in higher index have more free space.
-//-----------------------------------------------------------------------------
- Uint32 longKeyPageArray[4];
-
+ 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;
- Uint32 activeDataFilePage;
//-----------------------------------------------------------------------------
// Temporary variables used during shrink and expand process.
@@ -456,9 +364,7 @@ struct Fragmentrec {
// List of lock owners and list of lock waiters to support LCP handling
//-----------------------------------------------------------------------------
Uint32 lockOwnersList;
- Uint32 firstWaitInQueOp;
- Uint32 lastWaitInQueOp;
- Uint32 sentWaitInQueOp;
+ Uint32 m_current_sequence_no;
//-----------------------------------------------------------------------------
// References to Directory Ranges (which in turn references directories, which
@@ -471,23 +377,6 @@ struct Fragmentrec {
Uint32 lastOverIndex;
//-----------------------------------------------------------------------------
-// These variables are used to support LCP and Restore from disk.
-// lcpDirIndex: used during LCP as the frag page id currently stored.
-// lcpMaxDirIndex: The dirsize at start of LCP.
-// lcpMaxOverDirIndex: The xx at start of LCP
-// During a LCP one writes the minimum of the number of pages in the directory
-// and the number of pages at the start of the LCP.
-// noStoredPages: Number of bucket pages written in LCP used at restore
-// noOfOverStoredPages: Number of overflow pages written in LCP used at restore
-// This variable is also used during LCP to calculate this number.
-//-----------------------------------------------------------------------------
- Uint32 lcpDirIndex;
- Uint32 lcpMaxDirIndex;
- Uint32 lcpMaxOverDirIndex;
- Uint32 noStoredPages;
- Uint32 noOfStoredOverPages;
-
-//-----------------------------------------------------------------------------
// 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
@@ -500,22 +389,10 @@ struct Fragmentrec {
Uint32 firstFreeDirindexRec;
//-----------------------------------------------------------------------------
-// localCheckpId is used during execution of UNDO log to ensure that we only
-// apply UNDO log records from the restored LCP of the fragment.
-// lcpLqhPtr keeps track of LQH record for this fragment to checkpoint
-//-----------------------------------------------------------------------------
- Uint32 localCheckpId;
- Uint32 lcpLqhPtr;
-
-//-----------------------------------------------------------------------------
// 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;
-//-----------------------------------------------------------------------------
-// Reference to record for open file at LCP and restore
-//-----------------------------------------------------------------------------
- Uint32 fsConnPtr;
//-----------------------------------------------------------------------------
// These variables are important for the linear hashing algorithm.
@@ -544,13 +421,8 @@ struct Fragmentrec {
Uint32 slackCheck;
//-----------------------------------------------------------------------------
-// myfid is the fragment id of the fragment
-// myroot is the reference to the root fragment record
// nextfreefrag is the next free fragment if linked into a free list
//-----------------------------------------------------------------------------
- Uint32 myfid;
- Uint32 myroot;
- Uint32 myTableId;
Uint32 nextfreefrag;
//-----------------------------------------------------------------------------
@@ -562,17 +434,6 @@ struct Fragmentrec {
Uint32 nextAllocPage;
//-----------------------------------------------------------------------------
-// Keeps track of undo position for fragment during LCP and restore.
-//-----------------------------------------------------------------------------
- Uint32 prevUndoposition;
-
-//-----------------------------------------------------------------------------
-// Page reference during LCP and restore of page zero where fragment data is
-// saved
-//-----------------------------------------------------------------------------
- Uint32 zeroPagePtr;
-
-//-----------------------------------------------------------------------------
// Number of pages read from file during restore
//-----------------------------------------------------------------------------
Uint32 noOfExpectedPages;
@@ -583,29 +444,6 @@ struct Fragmentrec {
State fragState;
//-----------------------------------------------------------------------------
-// Keep track of number of outstanding writes of UNDO log records to ensure that
-// we have saved all UNDO info before concluding local checkpoint.
-//-----------------------------------------------------------------------------
- Uint32 nrWaitWriteUndoExit;
-
-//-----------------------------------------------------------------------------
-// lastUndoIsStored is used to handle parallel writes of UNDO log and pages to
-// know when LCP is completed
-//-----------------------------------------------------------------------------
- Uint8 lastUndoIsStored;
-
-//-----------------------------------------------------------------------------
-// Set to ZTRUE when local checkpoint freeze occurs and set to ZFALSE when
-// local checkpoint concludes.
-//-----------------------------------------------------------------------------
- Uint8 createLcp;
-
-//-----------------------------------------------------------------------------
-// Flag indicating whether we are in the load phase of restore still.
-//-----------------------------------------------------------------------------
- Uint8 loadingFlag;
-
-//-----------------------------------------------------------------------------
// elementLength: Length of element in bucket and overflow pages
// keyLength: Length of key
//-----------------------------------------------------------------------------
@@ -631,11 +469,8 @@ struct Fragmentrec {
//-----------------------------------------------------------------------------
// nodetype can only be STORED in this release. Is currently only set, never read
-// stopQueOp is indicator that locked operations will not start until LCP have
-// released the lock on the fragment
//-----------------------------------------------------------------------------
Uint8 nodetype;
- Uint8 stopQueOp;
//-----------------------------------------------------------------------------
// flag to avoid accessing table record if no char attributes
@@ -646,49 +481,6 @@ struct Fragmentrec {
typedef Ptr<Fragmentrec> FragmentrecPtr;
/* --------------------------------------------------------------------------------- */
-/* FS_CONNECTREC */
-/* --------------------------------------------------------------------------------- */
-struct FsConnectrec {
- Uint32 fsNext;
- Uint32 fsPrev;
- Uint32 fragrecPtr;
- Uint32 fsPtr;
- State fsState;
- Uint8 activeFragId;
- Uint8 fsPart;
-}; /* p2c: size = 24 bytes */
-
- typedef Ptr<FsConnectrec> FsConnectrecPtr;
-
-/* --------------------------------------------------------------------------------- */
-/* FS_OPREC */
-/* --------------------------------------------------------------------------------- */
-struct FsOprec {
- Uint32 fsOpnext;
- Uint32 fsOpfragrecPtr;
- Uint32 fsConptr;
- State fsOpstate;
- Uint16 fsOpMemPage;
-}; /* p2c: size = 20 bytes */
-
- typedef Ptr<FsOprec> FsOprecPtr;
-
-/* --------------------------------------------------------------------------------- */
-/* LCP_CONNECTREC */
-/* --------------------------------------------------------------------------------- */
-struct LcpConnectrec {
- Uint32 nextLcpConn;
- Uint32 lcpUserptr;
- Uint32 rootrecptr;
- State syncUndopageState;
- State lcpstate;
- Uint32 lcpUserblockref;
- Uint16 localCheckPid;
- Uint8 noOfLcpConf;
-};
- typedef Ptr<LcpConnectrec> LcpConnectrecPtr;
-
-/* --------------------------------------------------------------------------------- */
/* OPERATIONREC */
/* --------------------------------------------------------------------------------- */
struct Operationrec {
@@ -718,6 +510,7 @@ struct Operationrec {
Uint32 transId2;
Uint32 longPagePtr;
Uint32 longKeyPageIndex;
+ Uint32 m_sequence_no;
State opState;
Uint32 userptr;
State transactionstate;
@@ -736,7 +529,6 @@ struct Operationrec {
Uint8 dirtyRead;
Uint8 commitDeleteCheckFlag;
Uint8 isAccLockReq;
- Uint8 isUndoLogReq;
}; /* p2c: size = 168 bytes */
typedef Ptr<Operationrec> OperationrecPtr;
@@ -766,29 +558,6 @@ struct Page8 {
typedef Ptr<Page8> Page8Ptr;
/* --------------------------------------------------------------------------------- */
-/* 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. */
-/* --------------------------------------------------------------------------------- */
-struct Rootfragmentrec {
- Uint32 scan[MAX_PARALLEL_SCANS_PER_FRAG];
- Uint32 fragmentptr[2];
- Uint32 fragmentid[2];
- Uint32 lcpPtr;
- Uint32 mytabptr;
- Uint32 nextroot;
- Uint32 roothashcheck;
- Uint32 noOfElements;
- Uint32 m_commit_count;
- State rootState;
-}; /* p2c: size = 72 bytes */
-
- typedef Ptr<Rootfragmentrec> RootfragmentrecPtr;
-
-/* --------------------------------------------------------------------------------- */
/* SCAN_REC */
/* --------------------------------------------------------------------------------- */
struct ScanRec {
@@ -802,7 +571,6 @@ struct ScanRec {
SCAN_COMPLETED
};
Uint32 activeLocalFrag;
- Uint32 rootPtr;
Uint32 nextBucketIndex;
Uint32 scanNextfreerec;
Uint32 scanFirstActiveOp;
@@ -831,17 +599,6 @@ struct ScanRec {
typedef Ptr<ScanRec> ScanRecPtr;
-/* --------------------------------------------------------------------------------- */
-/* SR_VERSION_REC */
-/* --------------------------------------------------------------------------------- */
-struct SrVersionRec {
- Uint32 nextFreeSr;
- Uint32 checkPointId;
- Uint32 prevAddress;
- Uint32 srUnused; /* p2c: Not used */
-}; /* p2c: size = 16 bytes */
-
- typedef Ptr<SrVersionRec> SrVersionRecPtr;
/* --------------------------------------------------------------------------------- */
/* TABREC */
@@ -854,15 +611,6 @@ struct Tabrec {
};
typedef Ptr<Tabrec> TabrecPtr;
-/* --------------------------------------------------------------------------------- */
-/* UNDOPAGE */
-/* --------------------------------------------------------------------------------- */
-struct Undopage {
- Uint32 undoword[8192];
-}; /* p2c: size = 32768 bytes */
-
- typedef Ptr<Undopage> UndopagePtr;
-
public:
Dbacc(const class Configuration &);
virtual ~Dbacc();
@@ -870,6 +618,8 @@ public:
// pointer to TUP instance in this thread
Dbtup* c_tup;
+ void execACCMINUPDATE(Signal* signal);
+
private:
BLOCK_DEFINES(Dbacc);
@@ -880,37 +630,22 @@ private:
void execEXPANDCHECK2(Signal* signal);
void execSHRINKCHECK2(Signal* signal);
void execACC_OVER_REC(Signal* signal);
- void execACC_SAVE_PAGES(Signal* signal);
void execNEXTOPERATION(Signal* signal);
void execREAD_PSEUDO_REQ(Signal* signal);
// Received signals
void execSTTOR(Signal* signal);
- void execSR_FRAGIDREQ(Signal* signal);
- void execLCP_FRAGIDREQ(Signal* signal);
- void execLCP_HOLDOPREQ(Signal* signal);
- void execEND_LCPREQ(Signal* signal);
- void execACC_LCPREQ(Signal* signal);
- void execSTART_RECREQ(Signal* signal);
- void execACC_CONTOPREQ(Signal* signal);
void execACCKEYREQ(Signal* signal);
void execACCSEIZEREQ(Signal* signal);
void execACCFRAGREQ(Signal* signal);
- void execACC_SRREQ(Signal* signal);
void execNEXT_SCANREQ(Signal* signal);
void execACC_ABORTREQ(Signal* signal);
void execACC_SCANREQ(Signal* signal);
- void execACCMINUPDATE(Signal* signal);
void execACC_COMMITREQ(Signal* signal);
void execACC_TO_REQ(Signal* signal);
void execACC_LOCKREQ(Signal* signal);
- void execFSOPENCONF(Signal* signal);
- void execFSCLOSECONF(Signal* signal);
- void execFSWRITECONF(Signal* signal);
- void execFSREADCONF(Signal* signal);
void execNDB_STTOR(Signal* signal);
void execDROP_TAB_REQ(Signal* signal);
- void execFSREMOVECONF(Signal* signal);
void execREAD_CONFIG_REQ(Signal* signal);
void execSET_VAR_REQ(Signal* signal);
void execDUMP_STATE_ORD(Signal* signal);
@@ -920,14 +655,12 @@ private:
void commitDeleteCheck();
- void initRootFragPageZero(RootfragmentrecPtr, Page8Ptr);
- void initRootFragSr(RootfragmentrecPtr, Page8Ptr);
- void initFragAdd(Signal*, Uint32 rootFragIndex, Uint32 rootIndex, FragmentrecPtr);
+ typedef void * RootfragmentrecPtr;
+ void initRootFragPageZero(FragmentrecPtr, Page8Ptr);
+ void initFragAdd(Signal*, FragmentrecPtr);
void initFragPageZero(FragmentrecPtr, Page8Ptr);
- void initFragSr(FragmentrecPtr, Page8Ptr);
void initFragGeneral(FragmentrecPtr);
void verifyFragCorrect(FragmentrecPtr regFragPtr);
- void sendFSREMOVEREQ(Signal* signal, Uint32 tableId);
void releaseFragResources(Signal* signal, Uint32 fragIndex);
void releaseRootFragRecord(Signal* signal, RootfragmentrecPtr rootPtr);
void releaseRootFragResources(Signal* signal, Uint32 tableId);
@@ -943,11 +676,6 @@ private:
void releaseOverflowResources(Signal* signal, FragmentrecPtr regFragPtr);
void releaseDirIndexResources(Signal* signal, FragmentrecPtr regFragPtr);
void releaseFragRecord(Signal* signal, FragmentrecPtr regFragPtr);
- Uint32 remainingUndoPages();
- void updateLastUndoPageIdWritten(Signal* signal, Uint32 aNewValue);
- void updateUndoPositionPage(Signal* signal, Uint32 aNewValue);
- void srCheckPage(Signal* signal);
- void srCheckContainer(Signal* signal);
void initScanFragmentPart(Signal* signal);
Uint32 checkScanExpand(Signal* signal);
Uint32 checkScanShrink(Signal* signal);
@@ -956,14 +684,11 @@ private:
void initialiseFragRec(Signal* signal);
void initialiseFsConnectionRec(Signal* signal);
void initialiseFsOpRec(Signal* signal);
- void initialiseLcpConnectionRec(Signal* signal);
void initialiseOperationRec(Signal* signal);
void initialiseOverflowRec(Signal* signal);
void initialisePageRec(Signal* signal);
- void initialiseLcpPages(Signal* signal);
void initialiseRootfragRec(Signal* signal);
void initialiseScanRec(Signal* signal);
- void initialiseSrVerRec(Signal* signal);
void initialiseTableRec(Signal* signal);
bool addfragtotab(Signal* signal, Uint32 rootIndex, Uint32 fragId);
void initOpRec(Signal* signal);
@@ -979,17 +704,6 @@ private:
void expandcontainer(Signal* signal);
void shrinkcontainer(Signal* signal);
void nextcontainerinfoExp(Signal* signal);
- void lcpCopyPage(Signal* signal);
- void lcpUpdatePage(Signal* signal);
- void checkUndoPages(Signal* signal);
- void undoWritingProcess(Signal* signal);
- void writeUndoDataInfo(Signal* signal);
- void writeUndoHeader(Signal* signal,
- Uint32 logicalPageId,
- UndoHeader::UndoHeaderType pageType);
- void writeUndoOpInfo(Signal* signal);
- void checksumControl(Signal* signal, Uint32 checkPage);
- void startActiveUndo(Signal* signal);
void releaseAndCommitActiveOps(Signal* signal);
void releaseAndCommitQueuedOps(Signal* signal);
void releaseAndAbortLockedOps(Signal* signal);
@@ -1019,7 +733,7 @@ private:
Uint32 readTablePk(Uint32 localkey1);
void getElement(Signal* signal);
void getdirindex(Signal* signal);
- void commitdelete(Signal* signal, bool systemRestart);
+ void commitdelete(Signal* signal);
void deleteElement(Signal* signal);
void getLastAndRemove(Signal* signal);
void releaseLeftlist(Signal* signal);
@@ -1035,11 +749,11 @@ private:
void check_lock_upgrade(Signal* signal, OperationrecPtr lock_owner,
OperationrecPtr release_op);
void allocOverflowPage(Signal* signal);
- bool getrootfragmentrec(Signal* signal, RootfragmentrecPtr&, Uint32 fragId);
+ bool getfragmentrec(Signal* signal, FragmentrecPtr&, Uint32 fragId);
void insertLockOwnersList(Signal* signal, const OperationrecPtr&);
void takeOutLockOwnersList(Signal* signal, const OperationrecPtr&);
+
void initFsOpRec(Signal* signal);
- void initLcpConnRec(Signal* signal);
void initOverpage(Signal* signal);
void initPage(Signal* signal);
void initRootfragrec(Signal* signal);
@@ -1050,27 +764,21 @@ private:
void releaseDirrange(Signal* signal);
void releaseFsConnRec(Signal* signal);
void releaseFsOpRec(Signal* signal);
- void releaseLcpConnectRec(Signal* signal);
void releaseOpRec(Signal* signal);
void releaseOverflowRec(Signal* signal);
void releaseOverpage(Signal* signal);
void releasePage(Signal* signal);
- void releaseLcpPage(Signal* signal);
- void releaseSrRec(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 seizeLcpConnectRec(Signal* signal);
void seizeOpRec(Signal* signal);
void seizeOverRec(Signal* signal);
void seizePage(Signal* signal);
- void seizeLcpPage(Page8Ptr&);
void seizeRootfragrec(Signal* signal);
void seizeScanRec(Signal* signal);
- void seizeSrVerRec(Signal* signal);
void sendSystemerror(Signal* signal, int line);
void takeRecOutOfFreeOverdir(Signal* signal);
void takeRecOutOfFreeOverpage(Signal* signal);
@@ -1078,51 +786,26 @@ private:
void addFragRefuse(Signal* signal, Uint32 errorCode);
void ndbsttorryLab(Signal* signal);
- void srCloseDataFileLab(Signal* signal);
void acckeyref1Lab(Signal* signal, Uint32 result_code);
void insertelementLab(Signal* signal);
- void startUndoLab(Signal* signal);
void checkNextFragmentLab(Signal* signal);
void endofexpLab(Signal* signal);
void endofshrinkbucketLab(Signal* signal);
- void srStartUndoLab(Signal* signal);
void senddatapagesLab(Signal* signal);
- void undoNext2Lab(Signal* signal);
void sttorrysignalLab(Signal* signal);
void sendholdconfsignalLab(Signal* signal);
void accIsLockedLab(Signal* signal);
void insertExistElemLab(Signal* signal);
void refaccConnectLab(Signal* signal);
- void srReadOverPagesLab(Signal* signal);
void releaseScanLab(Signal* signal);
- void lcpOpenUndofileConfLab(Signal* signal);
- void srFsOpenConfLab(Signal* signal);
- void checkSyncUndoPagesLab(Signal* signal);
- void sendaccSrconfLab(Signal* signal);
- void checkSendLcpConfLab(Signal* signal);
- void endsaveoverpageLab(Signal* signal);
- void lcpCloseDataFileLab(Signal* signal);
- void srOpenDataFileLoopLab(Signal* signal);
- void srReadPagesLab(Signal* signal);
- void srDoUndoLab(Signal* signal);
void ndbrestart1Lab(Signal* signal);
void initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data);
- void srReadPagesAllocLab(Signal* signal);
void checkNextBucketLab(Signal* signal);
- void endsavepageLab(Signal* signal);
- void saveZeroPageLab(Signal* signal);
- void srAllocPage0011Lab(Signal* signal);
- void sendLcpFragidconfLab(Signal* signal);
- void savepagesLab(Signal* signal);
- void saveOverPagesLab(Signal* signal);
- void srReadPageZeroLab(Signal* signal);
void storeDataPageInDirectoryLab(Signal* signal);
- void lcpFsOpenConfLab(Signal* signal);
void zpagesize_error(const char* where);
void reportMemoryUsage(Signal* signal, int gth);
- void lcp_write_op_to_undolog(Signal* signal);
void reenable_expand_after_redo_log_exection_complete(Signal*);
// charsets
@@ -1166,25 +849,6 @@ private:
/* --------------------------------------------------------------------------------- */
/* FS_CONNECTREC */
/* --------------------------------------------------------------------------------- */
- FsConnectrec *fsConnectrec;
- FsConnectrecPtr fsConnectptr;
- Uint32 cfsConnectsize;
- Uint32 cfsFirstfreeconnect;
-/* --------------------------------------------------------------------------------- */
-/* FS_OPREC */
-/* --------------------------------------------------------------------------------- */
- FsOprec *fsOprec;
- FsOprecPtr fsOpptr;
- Uint32 cfsOpsize;
- Uint32 cfsFirstfreeop;
-/* --------------------------------------------------------------------------------- */
-/* LCP_CONNECTREC */
-/* --------------------------------------------------------------------------------- */
- LcpConnectrec *lcpConnectrec;
- LcpConnectrecPtr lcpConnectptr;
- Uint32 clcpConnectsize;
- Uint32 cfirstfreelcpConnect;
-/* --------------------------------------------------------------------------------- */
/* OPERATIONREC */
/* --------------------------------------------------------------------------------- */
Operationrec *operationrec;
@@ -1254,9 +918,7 @@ private:
Uint32 cfirstfreepage;
Uint32 cfreepage;
Uint32 cpagesize;
- Uint32 cfirstfreeLcpPage;
Uint32 cnoOfAllocatedPages;
- Uint32 cnoLcpPages;
/* --------------------------------------------------------------------------------- */
/* ROOTFRAGMENTREC */
/* DURING EXPAND FRAGMENT PROCESS, EACH FRAGMEND WILL BE EXPAND INTO TWO */
@@ -1265,10 +927,6 @@ private:
/* 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. */
/* --------------------------------------------------------------------------------- */
- Rootfragmentrec *rootfragmentrec;
- RootfragmentrecPtr rootfragrecptr;
- Uint32 crootfragmentsize;
- Uint32 cfirstfreerootfrag;
/* --------------------------------------------------------------------------------- */
/* SCAN_REC */
/* --------------------------------------------------------------------------------- */
@@ -1277,24 +935,11 @@ private:
Uint32 cscanRecSize;
Uint32 cfirstFreeScanRec;
/* --------------------------------------------------------------------------------- */
-/* SR_VERSION_REC */
-/* --------------------------------------------------------------------------------- */
- SrVersionRec *srVersionRec;
- SrVersionRecPtr srVersionPtr;
- Uint32 csrVersionRecSize;
- Uint32 cfirstFreeSrVersionRec;
-/* --------------------------------------------------------------------------------- */
/* TABREC */
/* --------------------------------------------------------------------------------- */
Tabrec *tabrec;
TabrecPtr tabptr;
Uint32 ctablesize;
-/* --------------------------------------------------------------------------------- */
-/* UNDOPAGE */
-/* --------------------------------------------------------------------------------- */
- Undopage *undopage;
- /* 32 KB PAGE */
- UndopagePtr undopageptr;
Uint32 tpwiElementptr;
Uint32 tpriElementptr;
Uint32 tgseElementptr;
@@ -1335,7 +980,6 @@ private:
Uint32 tgeContainerptr;
Uint32 tgeElementptr;
Uint32 tgeForward;
- Uint32 tundoElemIndex;
Uint32 texpReceivedBucket;
Uint32 texpDirInd;
Uint32 texpDirRangeIndex;
@@ -1357,7 +1001,6 @@ private:
Uint32 tsscElementptr;
Uint32 tfid;
Uint32 tscanFlag;
- Uint32 theadundoindex;
Uint32 tgflBufType;
Uint32 tgseIsforward;
Uint32 tsscIsforward;
@@ -1388,11 +1031,9 @@ private:
Uint32 tslUpdateHeader;
Uint32 tuserptr;
BlockReference tuserblockref;
- Uint32 tundoindex;
Uint32 tlqhPointer;
Uint32 tholdSentOp;
Uint32 tholdMore;
- Uint32 tlcpLqhCheckV;
Uint32 tgdiPageindex;
Uint32 tiopIndex;
Uint32 tnciTmp;
@@ -1403,35 +1044,15 @@ private:
Uint32 tscanTrid1;
Uint32 tscanTrid2;
- Uint16 clastUndoPageIdWritten;
- Uint32 cactiveCheckpId;
- Uint32 cactiveRootfrag;
- Uint32 cactiveSrFsPtr;
- Uint32 cactiveUndoFilePage;
- Uint32 cactiveOpenUndoFsPtr;
- Uint32 cactiveSrUndoPage;
- Uint32 cprevUndoaddress;
- Uint32 creadyUndoaddress;
Uint32 ctest;
- Uint32 cundoLogActive;
Uint32 clqhPtr;
BlockReference clqhBlockRef;
Uint32 cminusOne;
NodeId cmynodeid;
- Uint32 cactiveUndoFileVersion;
BlockReference cownBlockref;
BlockReference cndbcntrRef;
Uint16 csignalkey;
- Uint32 cundopagesize;
- Uint32 cundoposition;
- Uint32 cundoElemIndex;
- Uint32 cundoinfolength;
Uint32 czero;
- Uint32 csrVersList[16];
- Uint32 clblPageCounter;
- Uint32 clblPageOver;
- Uint32 clblPagesPerTick;
- Uint32 clblPagesPerTickAfterSr;
Uint32 csystemRestart;
Uint32 cexcForward;
Uint32 cexcPageindex;
@@ -1451,7 +1072,6 @@ private:
};
Uint32 c_errorInsert3000_TableId;
- Uint32 cSrUndoRecords[UndoHeader::ZNO_UNDORECORD_TYPES];
};
#endif
diff --git a/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
index c041e57cb2c..768750e00ce 100644
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
@@ -26,32 +26,21 @@ void Dbacc::initData()
cdirarraysize = ZDIRARRAY;
coprecsize = ZOPRECSIZE;
cpagesize = ZPAGESIZE;
- clcpConnectsize = ZLCP_CONNECTSIZE;
ctablesize = ZTABLESIZE;
cfragmentsize = ZFRAGMENTSIZE;
- crootfragmentsize = ZROOTFRAGMENTSIZE;
cdirrangesize = ZDIRRANGESIZE;
coverflowrecsize = ZOVERFLOWRECSIZE;
- cfsConnectsize = ZFS_CONNECTSIZE;
- cfsOpsize = ZFS_OPSIZE;
cscanRecSize = ZSCAN_REC_SIZE;
- csrVersionRecSize = ZSR_VERSION_REC_SIZE;
dirRange = 0;
directoryarray = 0;
fragmentrec = 0;
- fsConnectrec = 0;
- fsOprec = 0;
- lcpConnectrec = 0;
operationrec = 0;
overflowRecord = 0;
page8 = 0;
- rootfragmentrec = 0;
scanRec = 0;
- srVersionRec = 0;
tabrec = 0;
- undopage = 0;
// Records with constant sizes
}//Dbacc::initData()
@@ -72,11 +61,6 @@ void Dbacc::initRecords()
sizeof(DirRange),
cdirrangesize);
- undopage = (Undopage*)allocRecord("Undopage",
- sizeof(Undopage),
- cundopagesize,
- false);
-
directoryarray = (Directoryarray*)allocRecord("Directoryarray",
sizeof(Directoryarray),
cdirarraysize);
@@ -85,51 +69,17 @@ void Dbacc::initRecords()
sizeof(Fragmentrec),
cfragmentsize);
- fsConnectrec = (FsConnectrec*)allocRecord("FsConnectrec",
- sizeof(FsConnectrec),
- cfsConnectsize);
-
- fsOprec = (FsOprec*)allocRecord("FsOprec",
- sizeof(FsOprec),
- cfsOpsize);
-
- lcpConnectrec = (LcpConnectrec*)allocRecord("LcpConnectrec",
- sizeof(LcpConnectrec),
- clcpConnectsize);
-
overflowRecord = (OverflowRecord*)allocRecord("OverflowRecord",
sizeof(OverflowRecord),
coverflowrecsize);
- rootfragmentrec = (Rootfragmentrec*)allocRecord("Rootfragmentrec",
- sizeof(Rootfragmentrec),
- crootfragmentsize);
-
scanRec = (ScanRec*)allocRecord("ScanRec",
sizeof(ScanRec),
cscanRecSize);
- srVersionRec = (SrVersionRec*)allocRecord("SrVersionRec",
- sizeof(SrVersionRec),
- csrVersionRecSize);
-
tabrec = (Tabrec*)allocRecord("Tabrec",
sizeof(Tabrec),
ctablesize);
-
- // Initialize BAT for interface to file system
-
- NewVARIABLE* bat = allocateBat(3);
- bat[1].WA = &page8->word32[0];
- bat[1].nrr = cpagesize;
- bat[1].ClusterSize = sizeof(Page8);
- bat[1].bits.q = 11;
- bat[1].bits.v = 5;
- bat[2].WA = &undopage->undoword[0];
- bat[2].nrr = cundopagesize;
- bat[2].ClusterSize = sizeof(Undopage);
- bat[2].bits.q = 13;
- bat[2].bits.v = 5;
}//Dbacc::initRecords()
Dbacc::Dbacc(const class Configuration & conf):
@@ -145,24 +95,13 @@ Dbacc::Dbacc(const class Configuration & conf):
addRecSignal(GSN_ACC_CHECK_SCAN, &Dbacc::execACC_CHECK_SCAN);
addRecSignal(GSN_EXPANDCHECK2, &Dbacc::execEXPANDCHECK2);
addRecSignal(GSN_SHRINKCHECK2, &Dbacc::execSHRINKCHECK2);
- addRecSignal(GSN_ACC_OVER_REC, &Dbacc::execACC_OVER_REC);
- addRecSignal(GSN_ACC_SAVE_PAGES, &Dbacc::execACC_SAVE_PAGES);
- addRecSignal(GSN_NEXTOPERATION, &Dbacc::execNEXTOPERATION);
addRecSignal(GSN_READ_PSEUDO_REQ, &Dbacc::execREAD_PSEUDO_REQ);
// Received signals
addRecSignal(GSN_STTOR, &Dbacc::execSTTOR);
- addRecSignal(GSN_SR_FRAGIDREQ, &Dbacc::execSR_FRAGIDREQ);
- addRecSignal(GSN_LCP_FRAGIDREQ, &Dbacc::execLCP_FRAGIDREQ);
- addRecSignal(GSN_LCP_HOLDOPREQ, &Dbacc::execLCP_HOLDOPREQ);
- addRecSignal(GSN_END_LCPREQ, &Dbacc::execEND_LCPREQ);
- addRecSignal(GSN_ACC_LCPREQ, &Dbacc::execACC_LCPREQ);
- addRecSignal(GSN_START_RECREQ, &Dbacc::execSTART_RECREQ);
- addRecSignal(GSN_ACC_CONTOPREQ, &Dbacc::execACC_CONTOPREQ);
addRecSignal(GSN_ACCKEYREQ, &Dbacc::execACCKEYREQ);
addRecSignal(GSN_ACCSEIZEREQ, &Dbacc::execACCSEIZEREQ);
addRecSignal(GSN_ACCFRAGREQ, &Dbacc::execACCFRAGREQ);
- addRecSignal(GSN_ACC_SRREQ, &Dbacc::execACC_SRREQ);
addRecSignal(GSN_NEXT_SCANREQ, &Dbacc::execNEXT_SCANREQ);
addRecSignal(GSN_ACC_ABORTREQ, &Dbacc::execACC_ABORTREQ);
addRecSignal(GSN_ACC_SCANREQ, &Dbacc::execACC_SCANREQ);
@@ -170,13 +109,8 @@ Dbacc::Dbacc(const class Configuration & conf):
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_FSOPENCONF, &Dbacc::execFSOPENCONF);
- addRecSignal(GSN_FSCLOSECONF, &Dbacc::execFSCLOSECONF);
- addRecSignal(GSN_FSWRITECONF, &Dbacc::execFSWRITECONF);
- addRecSignal(GSN_FSREADCONF, &Dbacc::execFSREADCONF);
addRecSignal(GSN_NDB_STTOR, &Dbacc::execNDB_STTOR);
addRecSignal(GSN_DROP_TAB_REQ, &Dbacc::execDROP_TAB_REQ);
- addRecSignal(GSN_FSREMOVECONF, &Dbacc::execFSREMOVECONF);
addRecSignal(GSN_READ_CONFIG_REQ, &Dbacc::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_SET_VAR_REQ, &Dbacc::execSET_VAR_REQ);
@@ -194,9 +128,6 @@ Dbacc::Dbacc(const class Configuration & conf):
&sdDirptr,
&nciOverflowDirptr,
&fragrecptr,
- &fsConnectptr,
- &fsOpptr,
- &lcpConnectptr,
&operationRecPtr,
&idrOperationRecPtr,
&copyInOperPtr,
@@ -246,11 +177,8 @@ Dbacc::Dbacc(const class Configuration & conf):
&rpPageptr,
&slPageptr,
&spPageptr,
- &rootfragrecptr,
&scanPtr,
- &srVersionPtr,
- &tabptr,
- &undopageptr
+ &tabptr
};
init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
}
@@ -271,18 +199,6 @@ Dbacc::~Dbacc()
sizeof(Fragmentrec),
cfragmentsize);
- deallocRecord((void **)&fsConnectrec, "FsConnectrec",
- sizeof(FsConnectrec),
- cfsConnectsize);
-
- deallocRecord((void **)&fsOprec, "FsOprec",
- sizeof(FsOprec),
- cfsOpsize);
-
- deallocRecord((void **)&lcpConnectrec, "LcpConnectrec",
- sizeof(LcpConnectrec),
- clcpConnectsize);
-
deallocRecord((void **)&operationrec, "Operationrec",
sizeof(Operationrec),
coprecsize);
@@ -295,26 +211,13 @@ Dbacc::~Dbacc()
sizeof(Page8),
cpagesize);
- deallocRecord((void **)&rootfragmentrec, "Rootfragmentrec",
- sizeof(Rootfragmentrec),
- crootfragmentsize);
-
deallocRecord((void **)&scanRec, "ScanRec",
sizeof(ScanRec),
cscanRecSize);
- deallocRecord((void **)&srVersionRec, "SrVersionRec",
- sizeof(SrVersionRec),
- csrVersionRecSize);
-
deallocRecord((void **)&tabrec, "Tabrec",
sizeof(Tabrec),
ctablesize);
-
- deallocRecord((void **)&undopage, "Undopage",
- sizeof(Undopage),
- cundopagesize);
-
-}//Dbacc::~Dbacc()
+ }//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
index be8fed27ed3..391405795e6 100644
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -28,9 +28,9 @@
#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.
@@ -41,54 +41,6 @@
#endif
-Uint32
-Dbacc::remainingUndoPages(){
- Uint32 HeadPage = cundoposition >> ZUNDOPAGEINDEXBITS;
- Uint32 TailPage = clastUndoPageIdWritten;
-
- // Head must be larger or same as tail
- ndbrequire(HeadPage>=TailPage);
-
- Uint32 UsedPages = HeadPage - TailPage;
- Int32 Remaining = cundopagesize - UsedPages;
-
- // There can not be more than cundopagesize remaining
- if (Remaining <= 0){
- // No more undolog, crash node
- progError(__LINE__, NDBD_EXIT_NO_MORE_UNDOLOG,
- "There are more than 1Mbyte undolog writes outstanding");
- }
- return Remaining;
-}
-
-void
-Dbacc::updateLastUndoPageIdWritten(Signal* signal, Uint32 aNewValue){
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) {
- clastUndoPageIdWritten = aNewValue;
- if (remainingUndoPages() >= ZMIN_UNDO_PAGES_AT_COMMIT) {
- jam();
- EXECUTE_DIRECT(DBLQH, GSN_ACC_COM_UNBLOCK, signal, 1);
- jamEntry();
- }//if
- } else {
- clastUndoPageIdWritten = aNewValue;
- }//if
-}//Dbacc::updateLastUndoPageIdWritten()
-
-void
-Dbacc::updateUndoPositionPage(Signal* signal, Uint32 aNewValue){
- if (remainingUndoPages() >= ZMIN_UNDO_PAGES_AT_COMMIT) {
- cundoposition = aNewValue;
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) {
- jam();
- EXECUTE_DIRECT(DBLQH, GSN_ACC_COM_BLOCK, signal, 1);
- jamEntry();
- }//if
- } else {
- cundoposition = aNewValue;
- }//if
-}//Dbacc::updateUndoPositionPage()
-
// Signal entries and statement blocks
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
@@ -112,41 +64,11 @@ void Dbacc::execCONTINUEB(Signal* signal)
tdata0 = signal->theData[1];
tresult = 0;
switch (tcase) {
- case ZLOAD_BAL_LCP_TIMER:
- if (clblPageOver == 0) {
- jam();
- clblPageCounter = clblPagesPerTick;
- } else {
- if (clblPageOver > clblPagesPerTick) {
- jam();
- clblPageOver = clblPageOver - clblPagesPerTick;
- } else {
- jam();
- clblPageOver = 0;
- clblPageCounter = clblPagesPerTick - clblPageOver;
- }//if
- }//if
- signal->theData[0] = ZLOAD_BAL_LCP_TIMER;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1);
- return;
- break;
case ZINITIALISE_RECORDS:
jam();
initialiseRecordsLab(signal, signal->theData[3], signal->theData[4]);
return;
break;
- case ZSR_READ_PAGES_ALLOC:
- jam();
- fragrecptr.i = tdata0;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- srReadPagesAllocLab(signal);
- return;
- break;
- case ZSTART_UNDO:
- jam();
- startUndoLab(signal);
- return;
- break;
case ZSEND_SCAN_HBREP:
jam();
sendScanHbRep(signal, tdata0);
@@ -200,17 +122,6 @@ void Dbacc::execCONTINUEB(Signal* signal)
return;
}
- case ZLCP_OP_WRITE_RT_BREAK:
- {
- operationRecPtr.i= signal->theData[1];
- fragrecptr.i= signal->theData[2];
- lcpConnectptr.i= signal->theData[3];
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- lcp_write_op_to_undolog(signal);
- return;
- }
default:
ndbrequire(false);
break;
@@ -218,242 +129,6 @@ void Dbacc::execCONTINUEB(Signal* signal)
return;
}//Dbacc::execCONTINUEB()
-/* ******************--------------------------------------------------------------- */
-/* FSCLOSECONF CLOSE FILE CONF */
-/* ******************------------------------------+ */
-/* SENDER: FS, LEVEL B */
-void Dbacc::execFSCLOSECONF(Signal* signal)
-{
- jamEntry();
- fsConnectptr.i = signal->theData[0];
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- tresult = 0;
- switch (fsConnectptr.p->fsState) {
- case WAIT_CLOSE_UNDO:
- jam();
- releaseFsConnRec(signal);
- break;
- case LCP_CLOSE_DATA:
- jam();
- checkSyncUndoPagesLab(signal);
- return;
- break;
- case SR_CLOSE_DATA:
- jam();
- sendaccSrconfLab(signal);
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbacc::execFSCLOSECONF()
-
-
-/* ******************--------------------------------------------------------------- */
-/* FSOPENCONF OPENFILE CONF */
-/* ******************------------------------------+ */
-/* SENDER: FS, LEVEL B */
-void Dbacc::execFSOPENCONF(Signal* signal)
-{
- jamEntry();
- fsConnectptr.i = signal->theData[0];
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- tuserptr = signal->theData[1];
- tresult = 0; /* RESULT CHECK VALUE */
- switch (fsConnectptr.p->fsState) {
- case WAIT_OPEN_UNDO_LCP:
- jam();
- lcpOpenUndofileConfLab(signal);
- return;
- break;
- case WAIT_OPEN_UNDO_LCP_NEXT:
- jam();
- fsConnectptr.p->fsPtr = tuserptr;
- return;
- break;
- case OPEN_UNDO_FILE_SR:
- jam();
- fsConnectptr.p->fsPtr = tuserptr;
- srStartUndoLab(signal);
- return;
- break;
- case WAIT_OPEN_DATA_FILE_FOR_WRITE:
- jam();
- lcpFsOpenConfLab(signal);
- return;
- break;
- case WAIT_OPEN_DATA_FILE_FOR_READ:
- jam();
- fsConnectptr.p->fsPtr = tuserptr;
- srFsOpenConfLab(signal);
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbacc::execFSOPENCONF()
-
-
-/* ******************--------------------------------------------------------------- */
-/* FSREADCONF OPENFILE CONF */
-/* ******************------------------------------+ */
-/* SENDER: FS, LEVEL B */
-void Dbacc::execFSREADCONF(Signal* signal)
-{
- jamEntry();
- fsConnectptr.i = signal->theData[0];
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- tresult = 0; /* RESULT CHECK VALUE */
- switch (fsConnectptr.p->fsState) {
- case WAIT_READ_PAGE_ZERO:
- jam();
- fragrecptr.i = fsConnectptr.p->fragrecPtr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- srReadPageZeroLab(signal);
- return;
- break;
- case WAIT_READ_DATA:
- jam();
- fragrecptr.i = fsConnectptr.p->fragrecPtr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- storeDataPageInDirectoryLab(signal);
- return;
- break;
- case READ_UNDO_PAGE:
- jam();
- srDoUndoLab(signal);
- return;
- break;
- case READ_UNDO_PAGE_AND_CLOSE:
- jam();
- fsConnectptr.p->fsState = WAIT_CLOSE_UNDO;
- /* ************************ */
- /* FSCLOSEREQ */
- /* ************************ */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = 0;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- /* FLAG = DO NOT DELETE FILE */
- srDoUndoLab(signal);
- return;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbacc::execFSREADCONF()
-
-
-/* ******************--------------------------------------------------------------- */
-/* FSWRITECONF OPENFILE CONF */
-/* ******************------------------------------+ */
-/* SENDER: FS, LEVEL B */
-void Dbacc::execFSWRITECONF(Signal* signal)
-{
- jamEntry();
- fsOpptr.i = signal->theData[0];
- ptrCheckGuard(fsOpptr, cfsOpsize, fsOprec);
- /* FS_OPERATION PTR */
- tresult = 0; /* RESULT CHECK VALUE */
- fsConnectptr.i = fsOpptr.p->fsConptr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- fragrecptr.i = fsOpptr.p->fsOpfragrecPtr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- switch (fsOpptr.p->fsOpstate) {
- case WAIT_WRITE_UNDO:
- jam();
- updateLastUndoPageIdWritten(signal, fsOpptr.p->fsOpMemPage);
- releaseFsOpRec(signal);
- if (fragrecptr.p->nrWaitWriteUndoExit == 0) {
- jam();
- checkSendLcpConfLab(signal);
- return;
- } else {
- jam();
- fragrecptr.p->lastUndoIsStored = ZTRUE;
- }//if
- return;
- break;
- case WAIT_WRITE_UNDO_EXIT:
- jam();
- updateLastUndoPageIdWritten(signal, fsOpptr.p->fsOpMemPage);
- releaseFsOpRec(signal);
- if (fragrecptr.p->nrWaitWriteUndoExit > 0) {
- jam();
- fragrecptr.p->nrWaitWriteUndoExit--;
- }//if
- if (fsConnectptr.p->fsState == WAIT_CLOSE_UNDO) {
- jam();
- /* ************************ */
- /* FSCLOSEREQ */
- /* ************************ */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = ZFALSE;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- }//if
- if (fragrecptr.p->nrWaitWriteUndoExit == 0) {
- if (fragrecptr.p->lastUndoIsStored == ZTRUE) {
- jam();
- fragrecptr.p->lastUndoIsStored = ZFALSE;
- checkSendLcpConfLab(signal);
- return;
- }//if
- }//if
- return;
- break;
- case WAIT_WRITE_DATA:
- jam();
- releaseFsOpRec(signal);
- fragrecptr.p->activeDataFilePage += ZWRITEPAGESIZE;
- fragrecptr.p->activeDataPage = 0;
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- switch (fragrecptr.p->fragState) {
- case LCP_SEND_PAGES:
- jam();
- savepagesLab(signal);
- return;
- break;
- case LCP_SEND_OVER_PAGES:
- jam();
- saveOverPagesLab(signal);
- return;
- break;
- case LCP_SEND_ZERO_PAGE:
- jam();
- saveZeroPageLab(signal);
- return;
- break;
- case WAIT_ZERO_PAGE_STORED:
- jam();
- lcpCloseDataFileLab(signal);
- return;
- break;
- default:
- ndbrequire(false);
- return;
- break;
- }//switch
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbacc::execFSWRITECONF()
-
-
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
@@ -488,8 +163,6 @@ void Dbacc::execNDB_STTOR(Signal* signal)
return;
break;
case ZSPH2:
- cnoLcpPages = 2 * (ZWRITEPAGESIZE + 1);
- initialiseLcpPages(signal);
ndbsttorryLab(signal);
return;
break;
@@ -506,13 +179,9 @@ void Dbacc::execNDB_STTOR(Signal* signal)
//---------------------------------------------
csystemRestart = ZFALSE;
}//if
-
- signal->theData[0] = ZLOAD_BAL_LCP_TIMER;
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 100, 1);
break;
case ZSPH6:
jam();
- clblPagesPerTick = clblPagesPerTickAfterSr;
csystemRestart = ZFALSE;
signal->theData[0] = ZREPORT_MEMORY_USAGE;
@@ -558,19 +227,7 @@ void Dbacc::ndbrestart1Lab(Signal* signal)
czero = 0;
cminusOne = czero - 1;
ctest = 0;
- cundoLogActive = ZFALSE;
csystemRestart = ZTRUE;
- clblPageOver = 0;
- clblPageCounter = 0;
- cactiveUndoFilePage = 0;
- cprevUndoaddress = cminusOne;
- cundoposition = 0;
- clastUndoPageIdWritten = 0;
- cactiveUndoFileVersion = RNIL;
- cactiveOpenUndoFsPtr = RNIL;
- for (Uint32 tmp = 0; tmp < ZMAX_UNDO_VERSION; tmp++) {
- csrVersList[tmp] = RNIL;
- }//for
return;
}//Dbacc::ndbrestart1Lab()
@@ -582,16 +239,10 @@ void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data)
initialiseTableRec(signal);
break;
case 1:
- jam();
- initialiseFsConnectionRec(signal);
- break;
case 2:
- jam();
- initialiseFsOpRec(signal);
break;
case 3:
jam();
- initialiseLcpConnectionRec(signal);
break;
case 4:
jam();
@@ -619,7 +270,6 @@ void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data)
break;
case 10:
jam();
- initialiseRootfragRec(signal);
break;
case 11:
jam();
@@ -627,7 +277,6 @@ void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data)
break;
case 12:
jam();
- initialiseSrVerRec(signal);
{
ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
@@ -678,20 +327,6 @@ void Dbacc::execREAD_CONFIG_REQ(Signal* signal)
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
- Uint32 log_page_size= 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_UNDO_INDEX_BUFFER,
- &log_page_size);
-
- /**
- * Always set page size in half MBytes
- */
- cundopagesize= (log_page_size / sizeof(Undopage));
- Uint32 mega_byte_part= cundopagesize & 15;
- if (mega_byte_part != 0) {
- jam();
- cundopagesize+= (16 - mega_byte_part);
- }
-
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_RANGE, &cdirrangesize));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_ARRAY, &cdirarraysize));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_FRAGMENT, &cfragmentsize));
@@ -699,21 +334,11 @@ void Dbacc::execREAD_CONFIG_REQ(Signal* signal)
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_ROOT_FRAG,
- &crootfragmentsize));
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);
- clblPagesPerTick = 50;
- ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_ACC_SR,
- &clblPagesPerTick);
-
- clblPagesPerTickAfterSr = 50;
- ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_ACC,
- &clblPagesPerTickAfterSr);
-
tdata0 = 0;
initialiseRecordsLab(signal, ref, senderData);
return;
@@ -800,66 +425,6 @@ void Dbacc::initialiseFragRec(Signal* signal)
}//Dbacc::initialiseFragRec()
/* --------------------------------------------------------------------------------- */
-/* INITIALISE_FS_CONNECTION_REC */
-/* INITIALATES THE FS_CONNECTION RECORDS */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseFsConnectionRec(Signal* signal)
-{
- ndbrequire(cfsConnectsize > 0);
- for (fsConnectptr.i = 0; fsConnectptr.i < cfsConnectsize; fsConnectptr.i++) {
- ptrAss(fsConnectptr, fsConnectrec);
- fsConnectptr.p->fsNext = fsConnectptr.i + 1;
- fsConnectptr.p->fsPrev = RNIL;
- fsConnectptr.p->fragrecPtr = RNIL;
- fsConnectptr.p->fsState = WAIT_NOTHING;
- }//for
- fsConnectptr.i = cfsConnectsize - 1;
- ptrAss(fsConnectptr, fsConnectrec);
- fsConnectptr.p->fsNext = RNIL; /* INITIALITES THE LAST CONNECTRECORD */
- cfsFirstfreeconnect = 0; /* INITIATES THE FIRST FREE CONNECT RECORD */
-}//Dbacc::initialiseFsConnectionRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_FS_OP_REC */
-/* INITIALATES THE FS_OP RECORDS */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseFsOpRec(Signal* signal)
-{
- ndbrequire(cfsOpsize > 0);
- for (fsOpptr.i = 0; fsOpptr.i < cfsOpsize; fsOpptr.i++) {
- ptrAss(fsOpptr, fsOprec);
- fsOpptr.p->fsOpnext = fsOpptr.i + 1;
- fsOpptr.p->fsOpfragrecPtr = RNIL;
- fsOpptr.p->fsConptr = RNIL;
- fsOpptr.p->fsOpstate = WAIT_NOTHING;
- }//for
- fsOpptr.i = cfsOpsize - 1;
- ptrAss(fsOpptr, fsOprec);
- fsOpptr.p->fsOpnext = RNIL;
- cfsFirstfreeop = 0;
-}//Dbacc::initialiseFsOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_LCP_CONNECTION_REC */
-/* INITIALATES THE LCP_CONNECTION RECORDS */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseLcpConnectionRec(Signal* signal)
-{
- ndbrequire(clcpConnectsize > 0);
- for (lcpConnectptr.i = 0; lcpConnectptr.i < clcpConnectsize; lcpConnectptr.i++) {
- ptrAss(lcpConnectptr, lcpConnectrec);
- lcpConnectptr.p->nextLcpConn = lcpConnectptr.i + 1;
- lcpConnectptr.p->lcpUserptr = RNIL;
- lcpConnectptr.p->rootrecptr = RNIL;
- lcpConnectptr.p->lcpstate = LCP_FREE;
- }//for
- lcpConnectptr.i = clcpConnectsize - 1;
- ptrAss(lcpConnectptr, lcpConnectrec);
- lcpConnectptr.p->nextLcpConn = RNIL;
- cfirstfreelcpConnect = 0;
-}//Dbacc::initialiseLcpConnectionRec()
-
-/* --------------------------------------------------------------------------------- */
/* INITIALISE_OPERATION_REC */
/* INITIALATES THE OPERATION RECORDS. */
/* --------------------------------------------------------------------------------- */
@@ -912,57 +477,11 @@ void Dbacc::initialisePageRec(Signal* signal)
cnoOfAllocatedPages = 0;
}//Dbacc::initialisePageRec()
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_LCP_PAGES */
-/* INITIALATES THE LCP PAGE RECORDS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseLcpPages(Signal* signal)
-{
- Uint32 tilpIndex;
-
- ndbrequire(cnoLcpPages >= (2 * (ZWRITEPAGESIZE + 1)));
- /* --------------------------------------------------------------------------------- */
- /* AN ABSOLUTE MINIMUM IS THAT WE HAVE 16 LCP PAGES TO HANDLE TWO CONCURRENT */
- /* LCP'S ON LOCAL FRAGMENTS. */
- /* --------------------------------------------------------------------------------- */
- ndbrequire(cpagesize >= (cnoLcpPages + 8));
- /* --------------------------------------------------------------------------------- */
- /* THE NUMBER OF PAGES MUST BE AT LEAST 8 PLUS THE NUMBER OF PAGES REQUIRED BY */
- /* THE LOCAL CHECKPOINT PROCESS. THIS NUMBER IS 8 TIMES THE PARALLELISM OF */
- /* LOCAL CHECKPOINTS. */
- /* --------------------------------------------------------------------------------- */
- /* --------------------------------------------------------------------------------- */
- /* WE SET UP A LINKED LIST OF PAGES FOR EXCLUSIVE USE BY LOCAL CHECKPOINTS. */
- /* --------------------------------------------------------------------------------- */
- cfirstfreeLcpPage = RNIL;
- for (tilpIndex = 0; tilpIndex < cnoLcpPages; tilpIndex++) {
- jam();
- seizePage(signal);
- rlpPageptr = spPageptr;
- releaseLcpPage(signal);
- }//for
-}//Dbacc::initialiseLcpPages()
/* --------------------------------------------------------------------------------- */
/* INITIALISE_ROOTFRAG_REC */
/* INITIALATES THE ROOTFRAG RECORDS. */
/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseRootfragRec(Signal* signal)
-{
- ndbrequire(crootfragmentsize > 0);
- for (rootfragrecptr.i = 0; rootfragrecptr.i < crootfragmentsize; rootfragrecptr.i++) {
- refresh_watch_dog();
- ptrAss(rootfragrecptr, rootfragmentrec);
- rootfragrecptr.p->nextroot = rootfragrecptr.i + 1;
- rootfragrecptr.p->fragmentptr[0] = RNIL;
- rootfragrecptr.p->fragmentptr[1] = RNIL;
- }//for
- rootfragrecptr.i = crootfragmentsize - 1;
- ptrAss(rootfragrecptr, rootfragmentrec);
- rootfragrecptr.p->nextroot = RNIL;
- cfirstfreerootfrag = 0;
-}//Dbacc::initialiseRootfragRec()
-
/* --------------------------------------------------------------------------------- */
/* INITIALISE_SCAN_REC */
/* INITIALATES THE QUE_SCAN RECORDS. */
@@ -983,21 +502,6 @@ void Dbacc::initialiseScanRec(Signal* signal)
cfirstFreeScanRec = 0;
}//Dbacc::initialiseScanRec()
-/* --------------------------------------------------------------------------------- */
-/* INITIALISE_SR_VER_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initialiseSrVerRec(Signal* signal)
-{
- ndbrequire(csrVersionRecSize > 0);
- for (srVersionPtr.i = 0; srVersionPtr.i < csrVersionRecSize; srVersionPtr.i++) {
- ptrAss(srVersionPtr, srVersionRec);
- srVersionPtr.p->nextFreeSr = srVersionPtr.i + 1;
- }//for
- srVersionPtr.i = csrVersionRecSize - 1;
- ptrAss(srVersionPtr, srVersionRec);
- srVersionPtr.p->nextFreeSr = RNIL;
- cfirstFreeSrVersionRec = 0;
-}//Dbacc::initialiseSrVerRec()
/* --------------------------------------------------------------------------------- */
/* INITIALISE_TABLE_REC */
@@ -1033,18 +537,7 @@ void Dbacc::initialiseTableRec(Signal* signal)
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
-void Dbacc::initRootfragrec(Signal* signal)
-{
- const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
- rootfragrecptr.p->mytabptr = req->tableId;
- rootfragrecptr.p->roothashcheck = req->kValue + req->lhFragBits;
- rootfragrecptr.p->noOfElements = 0;
- rootfragrecptr.p->m_commit_count = 0;
- for (Uint32 i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
- rootfragrecptr.p->scan[i] = RNIL;
- }//for
-}//Dbacc::initRootfragrec()
-
+// JONAS This methods "aer ett saall"
void Dbacc::execACCFRAGREQ(Signal* signal)
{
const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
@@ -1066,91 +559,85 @@ void Dbacc::execACCFRAGREQ(Signal* signal)
#endif
ptrCheckGuard(tabptr, ctablesize, tabrec);
ndbrequire((req->reqInfo & 0xF) == ZADDFRAG);
- ndbrequire(!getrootfragmentrec(signal, rootfragrecptr, req->fragId));
- if (cfirstfreerootfrag == RNIL) {
+ ndbrequire(!getfragmentrec(signal, fragrecptr, req->fragId));
+ if (cfirstfreefrag == RNIL) {
jam();
- addFragRefuse(signal, ZFULL_ROOTFRAGRECORD_ERROR);
+ addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
return;
}//if
- seizeRootfragrec(signal);
- if (!addfragtotab(signal, rootfragrecptr.i, req->fragId)) {
+
+ seizeFragrec(signal);
+ initFragGeneral(fragrecptr);
+ initFragAdd(signal, fragrecptr);
+
+ if (!addfragtotab(signal, fragrecptr.i, req->fragId)) {
jam();
- releaseRootFragRecord(signal, rootfragrecptr);
- addFragRefuse(signal, ZFULL_ROOTFRAGRECORD_ERROR);
+ releaseFragRecord(signal, fragrecptr);
+ addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
return;
}//if
- initRootfragrec(signal);
- for (Uint32 i = 0; i < 2; i++) {
+ if (cfirstfreeDirrange == RNIL) {
jam();
- if (cfirstfreefrag == RNIL) {
- jam();
- addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
- return;
- }//if
- seizeFragrec(signal);
- initFragGeneral(fragrecptr);
- initFragAdd(signal, i, rootfragrecptr.i, fragrecptr);
- rootfragrecptr.p->fragmentptr[i] = fragrecptr.i;
- rootfragrecptr.p->fragmentid[i] = fragrecptr.p->myfid;
- if (cfirstfreeDirrange == RNIL) {
- jam();
- 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
- }//for
+ 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;
- rootfragrecptr.p->rootState = ACTIVEROOT;
+ fragrecptr.p->rootState = ACTIVEROOT;
AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
conf->userPtr = userPtr;
- conf->rootFragPtr = rootfragrecptr.i;
- conf->fragId[0] = rootfragrecptr.p->fragmentid[0];
- conf->fragId[1] = rootfragrecptr.p->fragmentid[1];
- conf->fragPtr[0] = rootfragrecptr.p->fragmentptr[0];
- conf->fragPtr[1] = rootfragrecptr.p->fragmentptr[1];
- conf->rootHashCheck = rootfragrecptr.p->roothashcheck;
+ 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()
@@ -1167,7 +654,6 @@ void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode)
return;
}//Dbacc::addFragRefuseEarly()
-
void
Dbacc::execDROP_TAB_REQ(Signal* signal){
jamEntry();
@@ -1187,7 +673,7 @@ Dbacc::execDROP_TAB_REQ(Signal* signal){
void Dbacc::releaseRootFragResources(Signal* signal, Uint32 tableId)
{
- RootfragmentrecPtr rootPtr;
+ FragmentrecPtr rootPtr;
TabrecPtr tabPtr;
tabPtr.i = tableId;
ptrCheckGuard(tabPtr, ctablesize, tabrec);
@@ -1195,40 +681,26 @@ void Dbacc::releaseRootFragResources(Signal* signal, Uint32 tableId)
jam();
if (tabPtr.p->fragholder[i] != RNIL) {
jam();
- Uint32 fragIndex;
- rootPtr.i = tabPtr.p->fragptrholder[i];
- ptrCheckGuard(rootPtr, crootfragmentsize, rootfragmentrec);
- if (rootPtr.p->fragmentptr[0] != RNIL) {
- jam();
- fragIndex = rootPtr.p->fragmentptr[0];
- rootPtr.p->fragmentptr[0] = RNIL;
- } else if (rootPtr.p->fragmentptr[1] != RNIL) {
- jam();
- fragIndex = rootPtr.p->fragmentptr[1];
- rootPtr.p->fragmentptr[1] = RNIL;
- } else {
- jam();
- releaseRootFragRecord(signal, rootPtr);
- tabPtr.p->fragholder[i] = RNIL;
- tabPtr.p->fragptrholder[i] = RNIL;
- continue;
- }//if
- releaseFragResources(signal, fragIndex);
+ tabPtr.p->fragholder[i] = RNIL;
+ releaseFragResources(signal, tabPtr.p->fragptrholder[i]);
return;
}//if
}//for
-
+
/**
* Finished...
*/
- sendFSREMOVEREQ(signal, tableId);
-}//Dbacc::releaseRootFragResources()
-void Dbacc::releaseRootFragRecord(Signal* signal, RootfragmentrecPtr rootPtr)
-{
- rootPtr.p->nextroot = cfirstfreerootfrag;
- cfirstfreerootfrag = rootPtr.i;
-}//Dbacc::releaseRootFragRecord()
+ 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)
{
@@ -1251,31 +723,18 @@ void Dbacc::releaseFragResources(Signal* signal, Uint32 fragIndex)
jam();
releaseDirIndexResources(signal, regFragPtr);
} else {
- RootfragmentrecPtr rootPtr;
jam();
- rootPtr.i = regFragPtr.p->myroot;
- ptrCheckGuard(rootPtr, crootfragmentsize, rootfragmentrec);
+ Uint32 tab = regFragPtr.p->mytabptr;
releaseFragRecord(signal, regFragPtr);
signal->theData[0] = ZREL_ROOT_FRAG;
- signal->theData[1] = rootPtr.p->mytabptr;
+ signal->theData[1] = tab;
sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
}//if
}//Dbacc::releaseFragResources()
void Dbacc::verifyFragCorrect(FragmentrecPtr regFragPtr)
{
- for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) {
- jam();
- ndbrequire(regFragPtr.p->datapages[i] == RNIL);
- }//for
ndbrequire(regFragPtr.p->lockOwnersList == RNIL);
- ndbrequire(regFragPtr.p->firstWaitInQueOp == RNIL);
- ndbrequire(regFragPtr.p->lastWaitInQueOp == RNIL);
- ndbrequire(regFragPtr.p->sentWaitInQueOp == RNIL);
- //ndbrequire(regFragPtr.p->fsConnPtr == RNIL);
- ndbrequire(regFragPtr.p->zeroPagePtr == RNIL);
- ndbrequire(regFragPtr.p->nrWaitWriteUndoExit == 0);
- ndbrequire(regFragPtr.p->sentWaitInQueOp == RNIL);
}//Dbacc::verifyFragCorrect()
void Dbacc::releaseDirResources(Signal* signal,
@@ -1376,42 +835,6 @@ void Dbacc::releaseFragRecord(Signal* signal, FragmentrecPtr regFragPtr)
initFragGeneral(regFragPtr);
}//Dbacc::releaseFragRecord()
-void Dbacc::sendFSREMOVEREQ(Signal* signal, Uint32 tableId)
-{
- FsRemoveReq * const fsReq = (FsRemoveReq *)signal->getDataPtrSend();
- fsReq->userReference = cownBlockref;
- fsReq->userPointer = tableId;
- fsReq->fileNumber[0] = tableId;
- fsReq->fileNumber[1] = (Uint32)-1; // Remove all fragments
- fsReq->fileNumber[2] = (Uint32)-1; // Remove all data files within fragment
- fsReq->fileNumber[3] = 255 | // No P-value used here
- (3 << 8) | // Data-files in D3
- (0 << 16) | // Data-files
- (1 << 24); // Version 1 of fileNumber
- fsReq->directory = 1;
- fsReq->ownDirectory = 1;
- sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, FsRemoveReq::SignalLength, JBA);
-}//Dbacc::sendFSREMOVEREQ()
-
-void Dbacc::execFSREMOVECONF(Signal* signal)
-{
- FsConf * const fsConf = (FsConf *)signal->getDataPtrSend();
- TabrecPtr tabPtr;
- tabPtr.i = fsConf->userPointer;
- ptrCheckGuard(tabPtr, ctablesize, tabrec);
-
- 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::execFSREMOVECONF()
-
-
/* -------------------------------------------------------------------------- */
/* ADDFRAGTOTAB */
/* DESCRIPTION: PUTS A FRAGMENT ID AND A POINTER TO ITS RECORD INTO */
@@ -1566,9 +989,15 @@ void Dbacc::initOpRec(Signal* signal)
// bit to mark lock operation
operationRecPtr.p->isAccLockReq = (Treqinfo >> 31) & 0x1;
-
// undo log is not run via ACCKEYREQ
- operationRecPtr.p->isUndoLogReq = 0;
+
+ if(ERROR_INSERTED(5900) || ERROR_INSERTED(5901))
+ {
+ for(unsigned i = 0; i<8 && i<signal->theData[4]; i++){
+ operationRecPtr.p->keydata[i] = signal->theData[i+7];
+ }
+ }
+
}//Dbacc::initOpRec()
/* --------------------------------------------------------------------------------- */
@@ -1831,13 +1260,6 @@ void Dbacc::insertExistElemLab(Signal* signal)
/* --------------------------------------------------------------------------------- */
void Dbacc::insertelementLab(Signal* signal)
{
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_OPERATION) {
- jam();
- acckeyref1Lab(signal, ZTEMPORARY_ACC_UNDO_FAILURE);
- return;
- }//if
- }//if
if (fragrecptr.p->firstOverflowRec == RNIL) {
jam();
allocOverflowPage(signal);
@@ -1847,23 +1269,28 @@ void Dbacc::insertelementLab(Signal* signal)
return;
}//if
}//if
- if (fragrecptr.p->keyLength != operationRecPtr.p->tupkeylen) {
- // historical
- ndbrequire(fragrecptr.p->keyLength == 0);
- }//if
-
- signal->theData[0] = operationRecPtr.p->userptr;
- Uint32 blockNo = refToBlock(operationRecPtr.p->userblockref);
- EXECUTE_DIRECT(blockNo, GSN_LQH_ALLOCREQ, signal, 1);
- jamEntry();
- if (signal->theData[0] != 0) {
- jam();
- Uint32 result_code = signal->theData[0];
- acckeyref1Lab(signal, result_code);
- return;
- }//if
- Uint32 localKey = (signal->theData[1] << MAX_TUPLES_BITS) + signal->theData[2];
+ ndbrequire(operationRecPtr.p->tupkeylen <= fragrecptr.p->keyLength);
+ Uint32 localKey;
+ if(!operationRecPtr.p->isAccLockReq)
+ {
+ signal->theData[0] = operationRecPtr.p->userptr;
+ Uint32 blockNo = refToBlock(operationRecPtr.p->userblockref);
+ EXECUTE_DIRECT(blockNo, GSN_LQH_ALLOCREQ, signal, 1);
+ jamEntry();
+ if (signal->theData[0] != 0) {
+ jam();
+ Uint32 result_code = signal->theData[0];
+ acckeyref1Lab(signal, result_code);
+ return;
+ }//if
+ localKey = (signal->theData[1] << MAX_TUPLES_BITS) + signal->theData[2];
+ }
+ else
+ {
+ localKey = signal->theData[7];
+ }
+
insertLockOwnersList(signal, operationRecPtr);
const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits;
@@ -1959,7 +1386,6 @@ Uint32 Dbacc::placeReadInLockQueue(Signal* signal)
jam();
queOperPtr.p->nextSerialQue = operationRecPtr.i;
operationRecPtr.p->prevSerialQue = queOperPtr.i;
- putOpInFragWaitQue(signal);
break;
}//switch
} else {
@@ -2027,7 +1453,6 @@ void Dbacc::placeSerialQueueRead(Signal* signal)
operationRecPtr.p->lockMode = readWriteOpPtr.p->lockMode;
break;
}//switch
- putOpInFragWaitQue(signal);
return;
}//if
}//if
@@ -2064,7 +1489,6 @@ void Dbacc::checkOnlyReadEntry(Signal* signal)
operationRecPtr.p->prevSerialQue = readWriteOpPtr.i;
break;
}//switch
- putOpInFragWaitQue(signal);
}//Dbacc::checkOnlyReadEntry()
/* --------------------------------------------------------------------------------- */
@@ -2179,7 +1603,6 @@ void Dbacc::placeSerialQueueWrite(Signal* signal)
/* --------------------------------------------------------------------------------- */
readWriteOpPtr.p->nextSerialQue = operationRecPtr.i;
operationRecPtr.p->prevSerialQue = readWriteOpPtr.i;
- putOpInFragWaitQue(signal);
return;
}//if
readWriteOpPtr.i = readWriteOpPtr.p->nextSerialQue;
@@ -2207,7 +1630,6 @@ void Dbacc::placeSerialQueueWrite(Signal* signal)
readWriteOpPtr.p->nextParallelQue = operationRecPtr.i;
operationRecPtr.p->localdata[0] = readWriteOpPtr.p->localdata[0];
operationRecPtr.p->localdata[1] = readWriteOpPtr.p->localdata[1];
- putOpInFragWaitQue(signal);
return;
}//if
}//if
@@ -2262,23 +1684,6 @@ void Dbacc::execACCMINUPDATE(Signal* signal)
tulkLocalPtr = operationRecPtr.p->elementPointer + operationRecPtr.p->elementIsforward;
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
ptrCheckGuard(ulkPageidptr, cpagesize, page8);
- if (fragrecptr.p->createLcp == ZTRUE) {
- //----------------------------------------------------------
- // To avoid undo log the element header we take care to only
- // undo log the local key part.
- //----------------------------------------------------------
- if (operationRecPtr.p->elementIsforward == 1) {
- jam();
- TlogStart = tulkLocalPtr;
- } else {
- jam();
- TlogStart = tulkLocalPtr - fragrecptr.p->localkeylen + 1;
- }//if
- datapageptr.p = ulkPageidptr.p;
- cundoinfolength = fragrecptr.p->localkeylen;
- cundoElemIndex = TlogStart;
- undoWritingProcess(signal);
- }//if
dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey1);
arrGuard(tulkLocalPtr, 2048);
ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey1;
@@ -2319,15 +1724,13 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
operationRecPtr.p->transactionstate = IDLE;
operationRecPtr.p->operation = ZUNDEFINED_OP;
if(Toperation != ZREAD){
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- rootfragrecptr.p->m_commit_count++;
+ fragrecptr.p->m_commit_count++;
if (Toperation != ZINSERT) {
if (Toperation != ZDELETE) {
return;
} else {
jam();
- rootfragrecptr.p->noOfElements--;
+ fragrecptr.p->noOfElements--;
fragrecptr.p->slack += operationRecPtr.p->insertDeleteLen;
if (fragrecptr.p->slack > fragrecptr.p->slackCheck) {
/* TIME FOR JOIN BUCKETS PROCESS */
@@ -2345,8 +1748,8 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
}//if
}//if
} else {
- jam(); /* EXPAND PROCESS HANDLING */
- rootfragrecptr.p->noOfElements++;
+ jam(); /* EXPAND PROCESS HANDLING */
+ fragrecptr.p->noOfElements++;
fragrecptr.p->slack -= operationRecPtr.p->insertDeleteLen;
if (fragrecptr.p->slack >= (1u << 31)) {
/* IT MEANS THAT IF SLACK < ZERO */
@@ -2359,7 +1762,7 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
}//if
}//if
- }//if
+ }
}
return;
}//Dbacc::execACC_COMMITREQ()
@@ -2423,20 +1826,11 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
if (req->fragPtrI == RNIL) {
for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
jam();
- if (tabptr.p->fragptrholder[i] != RNIL) {
- rootfragrecptr.i = tabptr.p->fragptrholder[i];
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (rootfragrecptr.p->fragmentid[0] == req->fragId) {
- jam();
- req->fragPtrI = rootfragrecptr.p->fragmentptr[0];
- break;
- }
- if (rootfragrecptr.p->fragmentid[1] == req->fragId) {
- jam();
- req->fragPtrI = rootfragrecptr.p->fragmentptr[1];
- break;
- }
- }
+ if (tabptr.p->fragholder[i] == req->fragId){
+ jam();
+ req->fragPtrI = tabptr.p->fragptrholder[i];
+ break;
+ }
}
}
fragrecptr.i = req->fragPtrI;
@@ -2770,13 +2164,6 @@ void Dbacc::insertContainer(Signal* signal)
return;
}//if
tidrContainerlen = tidrContainerlen + fragrecptr.p->elementLength;
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = idrPageptr.p;
- cundoElemIndex = tidrContainerptr;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
if (tidrNextConLen == 0) {
/* EACH SIDE OF THE BUFFER WHICH BELONG TO A FREE */
/* LIST, HAS ZERO AS LENGTH. */
@@ -2821,15 +2208,6 @@ void Dbacc::insertContainer(Signal* signal)
/* STRUCTURE. IT IS RATHER DIFFICULT TO MAINTAIN A LOGICAL STRUCTURE WHERE */
/* DELETES ARE INSERTS AND INSERTS ARE PURELY DELETES. */
/* --------------------------------------------------------------------------------- */
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (tidrForward == ZTRUE) {
- cundoElemIndex = tidrIndex;
- } else {
- cundoElemIndex = (tidrIndex + 1) - fragrecptr.p->elementLength;
- }//if
- cundoinfolength = fragrecptr.p->elementLength;
- undoWritingProcess(signal);
- }//if
dbgWord32(idrPageptr, tidrIndex, tidrElemhead);
idrPageptr.p->word32[tidrIndex] = tidrElemhead; /* INSERTS THE HEAD OF THE ELEMENT */
tidrIndex += tidrForward;
@@ -2865,12 +2243,6 @@ void Dbacc::addnewcontainer(Signal* signal)
{
Uint32 tancTmp1;
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = tancContainerptr;
- datapageptr.p = ancPageptr.p;
- cundoinfolength = 2;
- undoWritingProcess(signal); /* WHEN UNDO PROCESS HAS STARTED, */
- }//if
/* THE OLD DATA IS STORED ON AN UNDO PAGE */
/* --------------------------------------------------------------------------------- */
/* KEEP LENGTH INFORMATION IN BIT 26-31. */
@@ -2974,18 +2346,6 @@ void Dbacc::seizeLeftlist(Signal* signal)
arrGuard(tsllHeadIndex + 1, 2048);
tslNextfree = slPageptr.p->word32[tsllHeadIndex];
tslPrevfree = slPageptr.p->word32[tsllHeadIndex + 1];
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = slPageptr.p;
- cundoElemIndex = tsllHeadIndex;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = ZPOS_EMPTY_LIST;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
if (tslPrevfree == ZEMPTYLIST) {
jam();
/* UPDATE FREE LIST OF LEFT CONTAINER IN PAGE HEAD */
@@ -2999,22 +2359,12 @@ void Dbacc::seizeLeftlist(Signal* signal)
ndbrequire(tslPrevfree < ZEMPTYLIST);
jam();
tsllTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = tsllTmp;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
dbgWord32(slPageptr, tsllTmp, tslNextfree);
slPageptr.p->word32[tsllTmp] = tslNextfree;
}//if
if (tslNextfree < ZEMPTYLIST) {
jam();
tsllTmp = (((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE) + 1;
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = tsllTmp;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
dbgWord32(slPageptr, tsllTmp, tslPrevfree);
slPageptr.p->word32[tsllTmp] = tslPrevfree;
} else {
@@ -3050,11 +2400,6 @@ void Dbacc::seizeLeftlist(Signal* signal)
if (tslNextfree < ZEMPTYLIST) {
jam();
tsllTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = tsllTmp;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
tsllTmp1 = slPageptr.p->word32[tsllTmp] & 0xfe03ffff;
tsllTmp1 = tsllTmp1 | (tslPageindex << 18);
dbgWord32(slPageptr, tsllTmp, tsllTmp1);
@@ -3086,18 +2431,6 @@ void Dbacc::seizeRightlist(Signal* signal)
arrGuard(tsrlHeadIndex + 1, 2048);
tslNextfree = slPageptr.p->word32[tsrlHeadIndex];
tslPrevfree = slPageptr.p->word32[tsrlHeadIndex + 1];
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = slPageptr.p;
- cundoElemIndex = tsrlHeadIndex;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = ZPOS_EMPTY_LIST;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
if (tslPrevfree == ZEMPTYLIST) {
jam();
tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST];
@@ -3107,22 +2440,12 @@ void Dbacc::seizeRightlist(Signal* signal)
ndbrequire(tslPrevfree < ZEMPTYLIST);
jam();
tsrlTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = tsrlTmp;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
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));
- if (fragrecptr.p->createLcp == ZTRUE) {
- cundoElemIndex = tsrlTmp;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
dbgWord32(slPageptr, tsrlTmp, tslPrevfree);
slPageptr.p->word32[tsrlTmp] = tslPrevfree;
} else {
@@ -3156,12 +2479,6 @@ void Dbacc::seizeRightlist(Signal* signal)
if (tslNextfree < ZEMPTYLIST) {
jam();
tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = tsrlTmp;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
tsrlTmp1 = slPageptr.p->word32[tsrlTmp] & 0xfe03ffff;
dbgWord32(slPageptr, tsrlTmp, tsrlTmp1 | (tslPageindex << 18));
slPageptr.p->word32[tsrlTmp] = tsrlTmp1 | (tslPageindex << 18);
@@ -3315,8 +2632,7 @@ void Dbacc::getElement(Signal* signal)
* - table key for ACCKEYREQ, stored in TUP
* - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC
*/
- const bool searchLocalKey =
- operationRecPtr.p->isAccLockReq || operationRecPtr.p->isUndoLogReq;
+ const bool searchLocalKey = operationRecPtr.p->isAccLockReq;
ndbrequire(TelemLen == ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
tgeNextptrtype = ZLEFT;
@@ -3454,21 +2770,23 @@ void Dbacc::getElement(Signal* signal)
/* 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::commitdelete(Signal* signal, bool systemRestart)
+void Dbacc::commitdelete(Signal* signal)
{
- if (!systemRestart) {
- jam();
- signal->theData[0] = fragrecptr.p->myfid;
- signal->theData[1] = fragrecptr.p->myTableId;
- signal->theData[2] = operationRecPtr.p->localdata[0];
- Uint32 localKey = operationRecPtr.p->localdata[0];
- Uint32 pageId = localKey >> MAX_TUPLES_BITS;
- Uint32 pageIndex = localKey & ((1 << MAX_TUPLES_BITS) - 1);
- signal->theData[2] = pageId;
- signal->theData[3] = pageIndex;
- EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 4);
- jamEntry();
- }//if
+ jam();
+ Uint32 localKey = operationRecPtr.p->localdata[0];
+ Uint32 userptr= operationRecPtr.p->userptr;
+
+ signal->theData[0] = fragrecptr.p->myfid;
+ signal->theData[1] = fragrecptr.p->myTableId;
+ signal->theData[2] = operationRecPtr.p->localdata[0];
+ 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;
+ EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 5);
+ jamEntry();
+
getdirindex(signal);
tlastPageindex = tgdiPageindex;
lastPageptr.i = gdiPageptr.i;
@@ -3539,18 +2857,6 @@ void Dbacc::deleteElement(Signal* signal)
goto deleteElement_index_error1;
{
const Uint32 tdeElemhead = lastPageptr.p->word32[tlastElementptr];
- if (fragrecptr.p->createLcp == ZTRUE) {
- datapageptr.p = delPageptr.p;
- cundoinfolength = fragrecptr.p->elementLength;
- if (tdelForward == ZTRUE) {
- jam();
- cundoElemIndex = tdelElementptr;
- } else {
- jam();
- cundoElemIndex = (tdelElementptr + 1) - fragrecptr.p->elementLength;
- }//if
- undoWritingProcess(signal);
- }//if
tlastMoveElemptr = tlastElementptr;
tdelMoveElemptr = tdelElementptr;
guard31 = fragrecptr.p->elementLength - 1;
@@ -3570,16 +2876,10 @@ void Dbacc::deleteElement(Signal* signal)
/* --------------------------------------------------------------------------------- */
deOperationRecPtr.i = ElementHeader::getOpPtrI(tdeElemhead);
ptrCheckGuard(deOperationRecPtr, coprecsize, operationrec);
- if (cundoLogActive == ZFALSE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE DO NOT BOTHER WITH THIS INFORMATION DURING EXECUTION OF THE UNDO LOG. */
- /* --------------------------------------------------------------------------------- */
- deOperationRecPtr.p->elementPage = delPageptr.i;
- deOperationRecPtr.p->elementContainer = tdelContainerptr;
- deOperationRecPtr.p->elementPointer = tdelElementptr;
- deOperationRecPtr.p->elementIsforward = tdelForward;
- }//if
+ 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
@@ -3707,13 +3007,6 @@ void Dbacc::getLastAndRemove(Signal* signal)
/* DELETE THE LAST CONTAINER AND UPDATE THE PREVIOUS CONTAINER. ALSO PUT THIS */
/* CONTAINER IN FREE CONTAINER LIST OF THE PAGE. */
/* --------------------------------------------------------------------------------- */
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = lastPrevpageptr.p;
- cundoElemIndex = tlastPrevconptr;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
ndbrequire(tlastPrevconptr < 2048);
tglrTmp = lastPrevpageptr.p->word32[tlastPrevconptr] >> 9;
dbgWord32(lastPrevpageptr, tlastPrevconptr, tglrTmp << 9);
@@ -3734,13 +3027,6 @@ void Dbacc::getLastAndRemove(Signal* signal)
tglrHead = tlastContainerhead << 6;
tglrHead = tglrHead >> 6;
tglrHead = tglrHead | (tlastContainerlen << 26);
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = lastPageptr.p;
- cundoElemIndex = tlastContainerptr;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
dbgWord32(lastPageptr, tlastContainerptr, tglrHead);
arrGuard(tlastContainerptr, 2048);
lastPageptr.p->word32[tlastContainerptr] = tglrHead;
@@ -3766,19 +3052,6 @@ void Dbacc::releaseLeftlist(Signal* signal)
Uint32 tullTmp;
Uint32 tullTmp1;
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = rlPageptr.p;
- cundoElemIndex = tullIndex;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = ZPOS_EMPTY_LIST;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
/* --------------------------------------------------------------------------------- */
/* 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 */
@@ -3793,12 +3066,6 @@ void Dbacc::releaseLeftlist(Signal* signal)
jam();
tullTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
tullTmp1 = tullTmp1 + ZHEAD_SIZE;
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = tullTmp1;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfe03ffff;
dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlPrevused << 18));
rlPageptr.p->word32[tullTmp1] = tullTmp | (trlPrevused << 18);
@@ -3810,12 +3077,6 @@ void Dbacc::releaseLeftlist(Signal* signal)
jam();
tullTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
tullTmp1 = tullTmp1 + ZHEAD_SIZE;
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = tullTmp1;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfffc07ff;
dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlNextused << 11));
rlPageptr.p->word32[tullTmp1] = tullTmp | (trlNextused << 11);
@@ -3841,12 +3102,6 @@ void Dbacc::releaseLeftlist(Signal* signal)
jam();
tullTmp1 = (tullTmp1 << ZSHIFT_PLUS) - (tullTmp1 << ZSHIFT_MINUS);
tullTmp1 = (tullTmp1 + ZHEAD_SIZE) + 1;
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = tullTmp1;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
dbgWord32(rlPageptr, tullTmp1, trlPageindex);
rlPageptr.p->word32[tullTmp1] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
} else {
@@ -3889,19 +3144,6 @@ void Dbacc::releaseRightlist(Signal* signal)
Uint32 turlTmp1;
Uint32 turlTmp;
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = rlPageptr.p;
- cundoElemIndex = turlIndex;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = ZPOS_EMPTY_LIST;
- cundoinfolength = 2;
- undoWritingProcess(signal);
- }//if
/* --------------------------------------------------------------------------------- */
/* 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 */
@@ -3917,12 +3159,6 @@ void Dbacc::releaseRightlist(Signal* signal)
jam();
turlTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = turlTmp1;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfe03ffff;
dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlPrevused << 18));
rlPageptr.p->word32[turlTmp1] = turlTmp | (trlPrevused << 18);
@@ -3934,12 +3170,6 @@ void Dbacc::releaseRightlist(Signal* signal)
jam();
turlTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = turlTmp1;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfffc07ff;
dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlNextused << 11));
rlPageptr.p->word32[turlTmp1] = turlTmp | (trlNextused << 11);
@@ -3966,12 +3196,6 @@ void Dbacc::releaseRightlist(Signal* signal)
jam();
turlTmp = (turlTmp1 << ZSHIFT_PLUS) - (turlTmp1 << ZSHIFT_MINUS);
turlTmp = turlTmp + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1));
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- cundoElemIndex = turlTmp;
- cundoinfolength = 1;
- undoWritingProcess(signal);
- }//if
dbgWord32(rlPageptr, turlTmp, trlPageindex);
rlPageptr.p->word32[turlTmp] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
} else {
@@ -4002,26 +3226,24 @@ void Dbacc::checkoverfreelist(Signal* signal)
{
Uint32 tcolTmp;
- if (fragrecptr.p->loadingFlag == ZFALSE) {
- 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
+ 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
@@ -4088,7 +3310,7 @@ void Dbacc::abortOperation(Signal* signal)
return;
} else {
jam();
- commitdelete(signal, false);
+ commitdelete(signal);
}//if
}//if
} else {
@@ -4096,7 +3318,6 @@ void Dbacc::abortOperation(Signal* signal)
// We are not the lock owner.
/* --------------------------------------------------------------- */
jam();
- takeOutFragWaitQue(signal);
if (operationRecPtr.p->prevParallelQue != RNIL) {
jam();
/* ---------------------------------------------------------------------------------- */
@@ -4182,28 +3403,31 @@ void Dbacc::commitDeleteCheck()
do {
if (deleteOpPtr.p->operation == 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. */
- /* --------------------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------
+ * 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 = true;
deleteCheckOngoing = false;
} else if ((deleteOpPtr.p->operation == ZREAD) ||
(deleteOpPtr.p->operation == 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. */
- /* --------------------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------
+ * 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 (deleteOpPtr.i == RNIL) {
jam();
@@ -4214,10 +3438,10 @@ void Dbacc::commitDeleteCheck()
}//if
} else {
jam();
- /* --------------------------------------------------------------------------------- */
- /* Finding an UPDATE or INSERT before finding a DELETE means we cannot be deleting */
- /* as the end result of this transaction. */
- /* --------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------ */
+ /* 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);
@@ -4300,7 +3524,7 @@ void Dbacc::commitOperation(Signal* signal)
No queue and elementIsDisappeared is true. We perform the actual delete
operation.
*/
- commitdelete(signal, false);
+ commitdelete(signal);
return;
}//if
} else {
@@ -4482,10 +3706,11 @@ void Dbacc::releaselock(Signal* signal)
trlOperPtr.i = RNIL;
if (operationRecPtr.p->nextParallelQue != RNIL) {
jam();
- /* --------------------------------------------------------------------------------- */
- /* NEXT OPERATION TAKES OVER THE LOCK. We will simply move the info from the leader */
- // to the new queue leader.
- /* --------------------------------------------------------------------------------- */
+ /** ---------------------------------------------------------------------
+ * NEXT OPERATION TAKES OVER THE LOCK.
+ * We will simply move the info from the leader
+ * to the new queue leader.
+ * -------------------------------------------------------------------- */
trlOperPtr.i = operationRecPtr.p->nextParallelQue;
ptrCheckGuard(trlOperPtr, coprecsize, operationrec);
copyInOperPtr = trlOperPtr;
@@ -4494,9 +3719,10 @@ void Dbacc::releaselock(Signal* signal)
trlOperPtr.p->prevParallelQue = RNIL;
if (operationRecPtr.p->nextSerialQue != RNIL) {
jam();
- /* --------------------------------------------------------------------------------- */
- /* THERE IS A SERIAL QUEUE. MOVE IT FROM RELEASED OP REC TO THE NEW LOCK OWNER. */
- /* --------------------------------------------------------------------------------- */
+ /* -----------------------------------------------------------------
+ * THERE IS A SERIAL QUEUE. MOVE IT FROM RELEASED OP REC TO THE
+ * NEW LOCK OWNER.
+ * ------------------------------------------------------------------ */
trlOperPtr.p->nextSerialQue = operationRecPtr.p->nextSerialQue;
trlTmpOperPtr.i = trlOperPtr.p->nextSerialQue;
ptrCheckGuard(trlTmpOperPtr, coprecsize, operationrec);
@@ -4504,17 +3730,13 @@ void Dbacc::releaselock(Signal* signal)
}//if
check_lock_upgrade(signal, copyInOperPtr, operationRecPtr);
- /* --------------------------------------------------------------------------------- */
- /* SINCE THERE ARE STILL ITEMS IN THE PARALLEL QUEUE WE NEED NOT WORRY ABOUT */
- /* STARTING QUEUED OPERATIONS. THUS WE CAN END HERE. */
- /* --------------------------------------------------------------------------------- */
} else {
ndbrequire(operationRecPtr.p->nextSerialQue != RNIL);
jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PARALLEL QUEUE IS EMPTY AND THE SERIAL QUEUE IS NOT EMPTY. WE NEED TO */
- /* REARRANGE LISTS AND START A NUMBER OF OPERATIONS. */
- /* --------------------------------------------------------------------------------- */
+ /** ---------------------------------------------------------------------
+ * THE PARALLEL QUEUE IS EMPTY AND THE SERIAL QUEUE IS NOT EMPTY.
+ * WE NEED TO REARRANGE LISTS AND START A NUMBER OF OPERATIONS.
+ * -------------------------------------------------------------------- */
trlOperPtr.i = operationRecPtr.p->nextSerialQue;
ptrCheckGuard(trlOperPtr, coprecsize, operationrec);
copyOperPtr = operationRecPtr;
@@ -4522,48 +3744,53 @@ void Dbacc::releaselock(Signal* signal)
copyOpInfo(signal);
trlOperPtr.p->prevSerialQue = RNIL;
ndbrequire(trlOperPtr.p->prevParallelQue == RNIL);
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE MOVED TO THE NEXT PARALLEL QUEUE. WE MUST START ALL OF THOSE */
- /* OPERATIONS WHICH UP TILL NOW HAVE BEEN QUEUED WAITING FOR THE LOCK. */
- /* --------------------------------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+ /* WE HAVE MOVED TO THE NEXT PARALLEL QUEUE. WE MUST START ALL OF THOSE */
+ /* OPERATIONS WHICH UP TILL NOW HAVE BEEN QUEUED WAITING FOR THE LOCK. */
+ /* --------------------------------------------------------------------- */
rloOperPtr = operationRecPtr;
trlTmpOperPtr = trlOperPtr;
TelementIsDisappeared = trlOperPtr.p->elementIsDisappeared;
Uint32 ThashValue = trlOperPtr.p->hashValue;
do {
- /* --------------------------------------------------------------------------------- */
- // Ensure that all operations in the queue are assigned with the elementIsDisappeared
- // to ensure that the element is removed after a previous delete. An insert does
- // however revert this decision since the element is put back again. Local checkpoints
- // complicate life here since they do not execute the next operation but simply change
- // the state on the operation. We need to set-up the variable elementIsDisappeared
- // properly even when local checkpoints and inserts/writes after deletes occur.
- /* --------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------ */
+ // Ensure that all operations in the queue are assigned with the
+ // elementIsDisappeared to ensure that the element is removed after
+ // a previous delete. An insert does however revert this decision
+ // since the element is put back again.
+ // Local checkpoints complicate life here since they do not
+ // execute the next operation but simply change
+ // the state on the operation.
+ // We need to set-up the variable elementIsDisappeared
+ // properly even when local checkpoints and inserts/writes after
+ // deletes occur.
+ /* ------------------------------------------------------------------- */
trlTmpOperPtr.p->elementIsDisappeared = TelementIsDisappeared;
if (TelementIsDisappeared == ZTRUE) {
- /* --------------------------------------------------------------------------------- */
- // 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.
- /* --------------------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------- */
+ // 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();
trlTmpOperPtr.p->hashValue = ThashValue;
}//if
trlTmpOperPtr.p->localdata[0] = trlOperPtr.p->localdata[0];
trlTmpOperPtr.p->localdata[1] = trlOperPtr.p->localdata[1];
- /* --------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------- */
// Restart the queued operation.
- /* --------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------- */
operationRecPtr = trlTmpOperPtr;
TelementIsDisappeared = executeNextOperation(signal);
ThashValue = operationRecPtr.p->hashValue;
if (trlTmpOperPtr.p->nextParallelQue != RNIL) {
jam();
- /* --------------------------------------------------------------------------------- */
- // We will continue with the next operation in the parallel queue and start this as
- // well.
- /* --------------------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------- */
+ // We will continue with the next operation in the parallel
+ // queue and start this as well.
+ /* ----------------------------------------------------------------- */
trlTmpOperPtr.i = trlTmpOperPtr.p->nextParallelQue;
ptrCheckGuard(trlTmpOperPtr, coprecsize, operationrec);
} else {
@@ -4623,68 +3850,44 @@ void Dbacc::copyOpInfo(Signal* signal)
Uint32 Dbacc::executeNextOperation(Signal* signal)
{
ndbrequire(operationRecPtr.p->transactionstate == ACTIVE);
- if (fragrecptr.p->stopQueOp == ZTRUE) {
- Uint32 TelemDisappeared;
- jam();
- TelemDisappeared = operationRecPtr.p->elementIsDisappeared;
- if ((operationRecPtr.p->elementIsDisappeared == ZTRUE) &&
- (operationRecPtr.p->prevParallelQue == RNIL) &&
- ((operationRecPtr.p->operation == ZINSERT) ||
- (operationRecPtr.p->operation == ZWRITE))) {
- jam();
- /* --------------------------------------------------------------------------------- */
- // In this case we do not wish to change the elementIsDisappeared since that would
- // create an error the next time this method is called for this operation after local
- // checkpoint starts up operations again. We must however ensure that operations
- // that follow in the queue do not get the value ZTRUE when actually an INSERT/WRITE
- // precedes them (only if the INSERT/WRITE is the first operation).
- /* --------------------------------------------------------------------------------- */
- TelemDisappeared = ZFALSE;
- }//if
- /* --------------------------------------------------------------------------------- */
- /* A LOCAL CHECKPOINT HAS STOPPED OPERATIONS. WE MUST NOT START THE OPERATION */
- /* AT THIS TIME. WE SET THE STATE TO INDICATE THAT WE ARE READY TO START AS */
- /* SOON AS WE ARE ALLOWED. */
- /* --------------------------------------------------------------------------------- */
- operationRecPtr.p->opState = WAIT_EXE_OP;
- return TelemDisappeared;
- }//if
- takeOutFragWaitQue(signal);
if (operationRecPtr.p->elementIsDisappeared == ZTRUE) {
- /* --------------------------------------------------------------------------------- */
- /* PREVIOUS OPERATION WAS DELETE OPERATION AND THE ELEMENT IS ALREADY DELETED. */
- /* --------------------------------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+ /* PREVIOUS OPERATION WAS DELETE OPERATION AND THE ELEMENT IS DELETED. */
+ /* --------------------------------------------------------------------- */
if (((operationRecPtr.p->operation != ZINSERT) &&
(operationRecPtr.p->operation != ZWRITE)) ||
(operationRecPtr.p->prevParallelQue != RNIL)) {
if (operationRecPtr.p->operation != ZSCAN_OP ||
operationRecPtr.p->isAccLockReq) {
jam();
- /* --------------------------------------------------------------------------------- */
- // Updates and reads with a previous delete simply aborts with read error indicating
- // that tuple did not exist. Also inserts and writes not being the first operation.
- /* --------------------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------- */
+ // Updates and reads with a previous delete simply aborts with read
+ // error indicating that tuple did not exist.
+ // Also inserts and writes not being the first operation.
+ /* ----------------------------------------------------------------- */
operationRecPtr.p->transactionstate = WAIT_COMMIT_ABORT;
signal->theData[0] = operationRecPtr.p->userptr;
signal->theData[1] = ZREAD_ERROR;
- sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYREF, signal, 2, JBB);
+ sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYREF, signal,
+ 2, JBB);
return operationRecPtr.p->elementIsDisappeared;
} else {
- /* --------------------------------------------------------------------------------- */
- /* ABORT OF OPERATION NEEDED BUT THE OPERATION IS A SCAN => SPECIAL TREATMENT. */
- /* IF THE SCAN WAITS IN QUEUE THEN WE MUST REMOVE THE OPERATION FROM THE SCAN */
- /* LOCK QUEUE AND IF NO MORE OPERATIONS ARE QUEUED THEN WE SHOULD RESTART THE */
- /* SCAN PROCESS. OTHERWISE WE SIMPLY RELEASE THE OPERATION AND DECREASE THE */
- /* NUMBER OF LOCKS HELD. */
- /* --------------------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------- */
+ /* ABORT OF OPERATION NEEDED BUT THE OPERATION IS A
+ * SCAN => SPECIAL TREATMENT.
+ * IF THE SCAN WAITS IN QUEUE THEN WE MUST REMOVE THE OPERATION
+ * FROM THE SCAN LOCK QUEUE AND IF NO MORE OPERATIONS ARE QUEUED
+ * THEN WE SHOULD RESTART THE SCAN PROCESS. OTHERWISE WE SIMPLY
+ * RELEASE THE OPERATION AND DECREASE THE NUMBER OF LOCKS HELD.
+ * ----------------------------------------------------------------- */
takeOutScanLockQueue(operationRecPtr.p->scanRecPtr);
putReadyScanQueue(signal, operationRecPtr.p->scanRecPtr);
return operationRecPtr.p->elementIsDisappeared;
}//if
}//if
- /* --------------------------------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
// Insert and writes can continue but need to be converted to inserts.
- /* --------------------------------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
jam();
operationRecPtr.p->elementIsDisappeared = ZFALSE;
operationRecPtr.p->operation = ZINSERT;
@@ -4703,14 +3906,15 @@ Uint32 Dbacc::executeNextOperation(Signal* signal)
}//if
if (abortFlag) {
jam();
- /* --------------------------------------------------------------------------------- */
- /* ELEMENT STILL REMAINS AND WE ARE TRYING TO INSERT IT AGAIN. THIS IS CLEARLY */
- /* NOT A GOOD IDEA. */
- /* --------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------- */
+ /* ELEMENT STILL REMAINS AND WE ARE TRYING TO INSERT IT AGAIN. */
+ /* THIS IS CLEARLY NOT A GOOD IDEA. */
+ /* ------------------------------------------------------------------- */
operationRecPtr.p->transactionstate = WAIT_COMMIT_ABORT;
signal->theData[0] = operationRecPtr.p->userptr;
signal->theData[1] = ZWRITE_ERROR;
- sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYREF, signal, 2, JBB);
+ sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYREF, signal,
+ 2, JBB);
return operationRecPtr.p->elementIsDisappeared;
}//if
}
@@ -4739,52 +3943,12 @@ Uint32 Dbacc::executeNextOperation(Signal* signal)
} else {
jam();
sendAcckeyconf(signal);
- sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYCONF, signal, 6, JBB);
+ sendSignal(operationRecPtr.p->userblockref, GSN_ACCKEYCONF,
+ signal, 6, JBB);
}//if
return operationRecPtr.p->elementIsDisappeared;
}//Dbacc::executeNextOperation()
-/* --------------------------------------------------------------------------------- */
-/* TAKE_OUT_FRAG_WAIT_QUE */
-/* DESCRIPTION: AN OPERATION WHICH OWNS A LOCK OF AN ELEMENT, IS IN A LIST */
-/* OF THE FRAGMENT. THIS LIST IS USED TO STOP THE QUEUE OPERATION */
-/* DURING CREATE CHECK POINT PROSESS FOR STOP AND RESTART OF THE */
-/* OPERATIONS. THIS SUBRUTIN TAKES A OPERATION RECORD OUT OF THE LIST */
-/* -------------------------------------------------------------------------------- */
-void Dbacc::takeOutFragWaitQue(Signal* signal)
-{
- OperationrecPtr tofwqOperRecPtr;
-
- if (operationRecPtr.p->opState == WAIT_IN_QUEUE) {
- if (fragrecptr.p->sentWaitInQueOp == operationRecPtr.i) {
- jam();
- fragrecptr.p->sentWaitInQueOp = operationRecPtr.p->nextQueOp;
- }//if
- if (operationRecPtr.p->prevQueOp != RNIL) {
- jam();
- tofwqOperRecPtr.i = operationRecPtr.p->prevQueOp;
- ptrCheckGuard(tofwqOperRecPtr, coprecsize, operationrec);
- tofwqOperRecPtr.p->nextQueOp = operationRecPtr.p->nextQueOp;
- } else {
- jam();
- fragrecptr.p->firstWaitInQueOp = operationRecPtr.p->nextQueOp;
- }//if
- if (operationRecPtr.p->nextQueOp != RNIL) {
- jam();
- tofwqOperRecPtr.i = operationRecPtr.p->nextQueOp;
- ptrCheckGuard(tofwqOperRecPtr, coprecsize, operationrec);
- tofwqOperRecPtr.p->prevQueOp = operationRecPtr.p->prevQueOp;
- } else {
- jam();
- fragrecptr.p->lastWaitInQueOp = operationRecPtr.p->prevQueOp;
- }//if
- operationRecPtr.p->opState = FREE_OP;
- return;
- } else {
- ndbrequire(operationRecPtr.p->opState == FREE_OP);
- }//if
-}//Dbacc::takeOutFragWaitQue()
-
/**
* takeOutLockOwnersList
*
@@ -4797,7 +3961,7 @@ void Dbacc::takeOutLockOwnersList(Signal* signal,
{
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;
@@ -4811,10 +3975,10 @@ void Dbacc::takeOutLockOwnersList(Signal* signal,
}
ndbrequire(inList == true);
#endif
-
+
ndbrequire(outOperPtr.p->lockOwner == ZTRUE);
outOperPtr.p->lockOwner = ZFALSE;
-
+
// Fast path through the code for the common case.
if ((Tprev == RNIL) && (Tnext == RNIL)) {
ndbrequire(fragrecptr.p->lockOwnersList == outOperPtr.i);
@@ -4870,8 +4034,12 @@ void Dbacc::insertLockOwnersList(Signal* signal,
insOperPtr.p->lockOwner = ZTRUE;
insOperPtr.p->prevLockOwnerOp = RNIL;
tmpOperPtr.i = fragrecptr.p->lockOwnersList;
- fragrecptr.p->lockOwnersList = insOperPtr.i;
+ const Uint32 seq = fragrecptr.p->m_current_sequence_no;
insOperPtr.p->nextLockOwnerOp = tmpOperPtr.i;
+ insOperPtr.p->m_sequence_no = seq;
+
+ fragrecptr.p->lockOwnersList = insOperPtr.i;
+ fragrecptr.p->m_current_sequence_no = seq+1;
if (tmpOperPtr.i == RNIL) {
return;
} else {
@@ -5007,19 +4175,16 @@ Uint32 Dbacc::checkScanExpand(Signal* signal)
DirRangePtr TDirRangePtr;
Page8Ptr TPageptr;
ScanRecPtr TscanPtr;
- RootfragmentrecPtr Trootfragrecptr;
- Trootfragrecptr.i = fragrecptr.p->myroot;
TSplit = fragrecptr.p->p;
- ptrCheckGuard(Trootfragrecptr, crootfragmentsize, rootfragmentrec);
for (Ti = 0; Ti < 4; Ti++) {
TreleaseScanIndicator[Ti] = 0;
- if (Trootfragrecptr.p->scan[Ti] != RNIL) {
+ if (fragrecptr.p->scan[Ti] != RNIL) {
//-------------------------------------------------------------
// A scan is ongoing on this particular local fragment. We have
// to check its current state.
//-------------------------------------------------------------
- TscanPtr.i = Trootfragrecptr.p->scan[Ti];
+ TscanPtr.i = fragrecptr.p->scan[Ti];
ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
@@ -5077,7 +4242,7 @@ Uint32 Dbacc::checkScanExpand(Signal* signal)
for (Ti = 0; Ti < 4; Ti++) {
if (TreleaseScanIndicator[Ti] == 1) {
jam();
- scanPtr.i = Trootfragrecptr.p->scan[Ti];
+ scanPtr.i = fragrecptr.p->scan[Ti];
ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
rsbPageidptr = TPageptr;
trsbPageindex = TPageIndex;
@@ -5146,16 +4311,6 @@ void Dbacc::execEXPANDCHECK2(Signal* signal)
/*--------------------------------------------------------------*/
return;
}//if
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_EXPAND) {
- jam();
- /*--------------------------------------------------------------*/
- // We did not have enough undo log buffers to start up an
- // expand operation
- /*--------------------------------------------------------------*/
- return;
- }//if
- }//if
/*--------------------------------------------------------------------------*/
/* WE START BY FINDING THE PAGE, THE PAGE INDEX AND THE PAGE DIRECTORY*/
@@ -5276,38 +4431,34 @@ void Dbacc::reenable_expand_after_redo_log_exection_complete(Signal* signal){
Uint32 fragId = signal->theData[1];
ptrCheckGuard(tabptr, ctablesize, tabrec);
- ndbrequire(getrootfragmentrec(signal, rootfragrecptr, fragId));
+ ndbrequire(getfragmentrec(signal, fragrecptr, fragId));
#if 0
ndbout_c("reenable expand check for table %d fragment: %d",
tabptr.i, fragId);
#endif
- for (Uint32 i = 0; i < 2; i++) {
- fragrecptr.i = rootfragrecptr.p->fragmentptr[i];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- switch(fragrecptr.p->expandFlag){
- case 0:
- /**
- * Hmm... this means that it's alreay has been reenabled...
- */
- ndbassert(false);
- continue;
- case 1:
- /**
- * Nothing is going on start expand check
- */
- case 2:
- /**
- * A shrink is running, do expand check anyway
- * (to reset expandFlag)
- */
- fragrecptr.p->expandFlag = 2;
- signal->theData[0] = fragrecptr.i;
- signal->theData[1] = fragrecptr.p->p;
- signal->theData[2] = fragrecptr.p->maxp;
- sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
- break;
- }
+ 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;
}
}
@@ -5380,20 +4531,6 @@ void Dbacc::expandcontainer(Signal* signal)
idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
- if ((fragrecptr.p->createLcp == ZTRUE) &&
- (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) != 0)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- // During local checkpoints we must ensure that we restore the element header in
- // unlocked state and with the hash value part there with tuple status zeroed.
- // Otherwise a later insert over the same element will write an UNDO log that will
- // ensure that the now removed element is restored together with its locked element
- // header and without the hash value part.
- /* --------------------------------------------------------------------------------- */
- const Uint32 hv = idrOperationRecPtr.p->hashvaluePart;
- const Uint32 eh = ElementHeader::setUnlocked(hv, 0);
- excPageptr.p->word32[cexcElementptr] = eh;
- }//if
}//if
if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
jam();
@@ -5469,20 +4606,6 @@ void Dbacc::expandcontainer(Signal* signal)
idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
- if ((fragrecptr.p->createLcp == ZTRUE) &&
- (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) != 0)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- // During local checkpoints we must ensure that we restore the element header in
- // unlocked state and with the hash value part there with tuple status zeroed.
- // Otherwise a later insert over the same element will write an UNDO log that will
- // ensure that the now removed element is restored together with its locked element
- // header and without the hash value part.
- /* --------------------------------------------------------------------------------- */
- const Uint32 hv = idrOperationRecPtr.p->hashvaluePart;
- const Uint32 eh = ElementHeader::setUnlocked(hv, 0);
- lastPageptr.p->word32[tlastElementptr] = eh;
- }//if
}//if
if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
jam();
@@ -5573,10 +4696,7 @@ Uint32 Dbacc::checkScanShrink(Signal* signal)
DirRangePtr TDirRangePtr;
Page8Ptr TPageptr;
ScanRecPtr TscanPtr;
- RootfragmentrecPtr Trootfragrecptr;
- Trootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(Trootfragrecptr, crootfragmentsize, rootfragmentrec);
if (fragrecptr.p->p == 0) {
jam();
TmergeDest = fragrecptr.p->maxp >> 1;
@@ -5587,8 +4707,8 @@ Uint32 Dbacc::checkScanShrink(Signal* signal)
TmergeSource = fragrecptr.p->maxp + fragrecptr.p->p;
for (Ti = 0; Ti < 4; Ti++) {
TreleaseScanIndicator[Ti] = 0;
- if (Trootfragrecptr.p->scan[Ti] != RNIL) {
- TscanPtr.i = Trootfragrecptr.p->scan[Ti];
+ if (fragrecptr.p->scan[Ti] != RNIL) {
+ TscanPtr.i = fragrecptr.p->scan[Ti];
ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
//-------------------------------------------------------------
@@ -5650,7 +4770,7 @@ Uint32 Dbacc::checkScanShrink(Signal* signal)
for (Ti = 0; Ti < 4; Ti++) {
if (TreleaseScanIndicator[Ti] == 1) {
jam();
- scanPtr.i = Trootfragrecptr.p->scan[Ti];
+ scanPtr.i = fragrecptr.p->scan[Ti];
ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
rsbPageidptr.i = TPageptr.i;
rsbPageidptr.p = TPageptr.p;
@@ -5705,22 +4825,6 @@ void Dbacc::execSHRINKCHECK2(Signal* signal)
return;
}//if
texpDirInd = (fragrecptr.p->maxp + fragrecptr.p->p) >> fragrecptr.p->k;
- if (((fragrecptr.p->maxp + fragrecptr.p->p) & ((1 << fragrecptr.p->k) - 1)) == 0) {
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (fragrecptr.p->fragState == LCP_SEND_PAGES) {
- if (fragrecptr.p->lcpMaxDirIndex > texpDirInd) {
- if (fragrecptr.p->lcpDirIndex <= texpDirInd) {
- jam();
- /*--------------------------------------------------------------*/
- /* WE DO NOT ALLOW ANY SHRINKS THAT REMOVE PAGES THAT ARE */
- /* NEEDED AS PART OF THE LOCAL CHECKPOINT. */
- /*--------------------------------------------------------------*/
- return;
- }//if
- }//if
- }//if
- }//if
- }//if
if (fragrecptr.p->firstOverflowRec == RNIL) {
jam();
allocOverflowPage(signal);
@@ -5748,16 +4852,6 @@ void Dbacc::execSHRINKCHECK2(Signal* signal)
/*--------------------------------------------------------------*/
return;
}//if
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_EXPAND) {
- jam();
- /*--------------------------------------------------------------*/
- // We did not have enough undo log buffers to start up an
- // shrink operation
- /*--------------------------------------------------------------*/
- return;
- }//if
- }//if
if (fragrecptr.p->p == 0) {
jam();
fragrecptr.p->maxp = fragrecptr.p->maxp >> 1;
@@ -5834,13 +4928,6 @@ void Dbacc::execSHRINKCHECK2(Signal* signal)
}//if
tshrTmp1 = ZCON_HEAD_SIZE;
tshrTmp1 = tshrTmp1 << 26;
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- datapageptr.p = excPageptr.p;
- cundoinfolength = 1;
- cundoElemIndex = cexcContainerptr;
- undoWritingProcess(signal);
- }//if
dbgWord32(excPageptr, cexcContainerptr, tshrTmp1);
arrGuard(cexcContainerptr, 2048);
excPageptr.p->word32[cexcContainerptr] = tshrTmp1;
@@ -6022,19 +5109,6 @@ void Dbacc::shrinkcontainer(Signal* signal)
/* --------------------------------------------------------------------------------- */
idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- // During local checkpoints we must ensure that we restore the element header in
- // unlocked state and with the hash value part there with tuple status zeroed.
- // Otherwise a later insert over the same element will write an UNDO log that will
- // ensure that the now removed element is restored together with its locked element
- // header and without the hash value part.
- /* --------------------------------------------------------------------------------- */
- const Uint32 hv = idrOperationRecPtr.p->hashvaluePart;
- const Uint32 eh = ElementHeader::setUnlocked(hv, 0);
- excPageptr.p->word32[tshrElementptr] = eh;
- }//if
}//if
tshrTmp = tshrElementptr + cexcForward;
guard21 = fragrecptr.p->localkeylen - 1;
@@ -6110,1739 +5184,7 @@ void Dbacc::nextcontainerinfoExp(Signal* signal)
}//if
}//Dbacc::nextcontainerinfoExp()
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF EXPAND/SHRINK MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* LOCAL CHECKPOINT MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* LCP_FRAGIDREQ */
-/* SENDER: LQH, LEVEL B */
-/* ENTER LCP_FRAGIDREQ WITH */
-/* TUSERPTR LQH CONNECTION PTR */
-/* TUSERBLOCKREF, LQH BLOCK REFERENCE */
-/* TCHECKPOINTID, THE CHECKPOINT NUMBER TO USE */
-/* (E.G. 1,2 OR 3) */
-/* TABPTR, TABLE ID = TABLE RECORD POINTER */
-/* TFID ROOT FRAGMENT ID */
-/* CACTIVE_UNDO_FILE_VERSION UNDO FILE VERSION 0,1,2 OR 3. */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* LCP_FRAGIDREQ REQUEST FOR LIST OF STOPED OPERATION */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execLCP_FRAGIDREQ(Signal* signal)
-{
- jamEntry();
- tuserptr = signal->theData[0]; /* LQH CONNECTION PTR */
- tuserblockref = signal->theData[1]; /* LQH BLOCK REFERENCE */
- tcheckpointid = signal->theData[2]; /* THE CHECKPOINT NUMBER TO USE */
- /* (E.G. 1,2 OR 3) */
- tabptr.i = signal->theData[3]; /* TABLE ID = TABLE RECORD POINTER */
- ptrCheck(tabptr, ctablesize, tabrec);
- tfid = signal->theData[4]; /* ROOT FRAGMENT ID */
- cactiveUndoFileVersion = signal->theData[5]; /* UNDO FILE VERSION 0,1,2 OR 3. */
- tresult = 0;
- ndbrequire(getrootfragmentrec(signal, rootfragrecptr, tfid));
- ndbrequire(rootfragrecptr.p->rootState == ACTIVEROOT);
- seizeLcpConnectRec(signal);
- initLcpConnRec(signal);
- lcpConnectptr.p->rootrecptr = rootfragrecptr.i;
- rootfragrecptr.p->lcpPtr = lcpConnectptr.i;
- lcpConnectptr.p->localCheckPid = tcheckpointid;
- lcpConnectptr.p->lcpstate = LCP_ACTIVE;
- rootfragrecptr.p->rootState = LCP_CREATION;
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- /* D6 AT FSOPENREQ =#010003FF. */
- tlfrTmp1 = 0x010003ff; /* FILE TYPE = .DATA ,VERSION OF FILENAME = 1 */
- tlfrTmp2 = 0x301; /* D7 CREATE, WRITE ONLY, TRUNCATE TO ZERO */
- ndbrequire(cfsFirstfreeconnect != RNIL);
- seizeFsConnectRec(signal);
- fsConnectptr.p->fragrecPtr = fragrecptr.i;
- fsConnectptr.p->fsState = WAIT_OPEN_DATA_FILE_FOR_WRITE;
- /* ----------- FILENAME (FILESYSTEM)/D3/DBACC/"T"TABID/"F"FRAGID/"S"VERSIONID.DATA ------------ */
- /* ************************ */
- /* FSOPENREQ */
- /* ************************ */
- signal->theData[0] = cownBlockref;
- signal->theData[1] = fsConnectptr.i;
- signal->theData[2] = tabptr.i; /* TABLE IDENTITY */
- signal->theData[3] = rootfragrecptr.p->fragmentid[0]; /* FRAGMENT IDENTITY */
- signal->theData[4] = lcpConnectptr.p->localCheckPid; /* CHECKPOINT ID */
- signal->theData[5] = tlfrTmp1;
- signal->theData[6] = tlfrTmp2;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- return;
-}//Dbacc::execLCP_FRAGIDREQ()
-
-/* ******************--------------------------------------------------------------- */
-/* FSOPENCONF OPENFILE CONF */
-/* SENDER: FS, LEVEL B */
-/* ENTER FSOPENCONF WITH */
-/* FS_CONNECTPTR, FS_CONNECTION PTR */
-/* TUSERPOINTER, FILE POINTER */
-/* ******************--------------------------------------------------------------- */
-void Dbacc::lcpFsOpenConfLab(Signal* signal)
-{
- fsConnectptr.p->fsPtr = tuserptr;
- fragrecptr.i = fsConnectptr.p->fragrecPtr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- rootfragrecptr.i = fragrecptr.p->myroot;
- fragrecptr.p->activeDataFilePage = 1; /* ZERO IS KEPT FOR PAGE_ZERO */
- fragrecptr.p->fsConnPtr = fsConnectptr.i;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- if (rootfragrecptr.p->fragmentptr[0] == fragrecptr.i) {
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[1];
- ptrCheck(fragrecptr, cfragmentsize, fragmentrec);
- /* ----------- FILENAME (FILESYSTEM)/D3/DBACC/"T"TABID/"F"FRAGID/"S"VERSIONID.DATA ------------ */
- /* D6 AT FSOPENREQ =#010003FF. */
- tlfrTmp1 = 0x010003ff; /* FILE TYPE = .DATA ,VERSION OF FILENAME = 1 */
- tlfrTmp2 = 0x301; /* D7 CREATE, WRITE ONLY, TRUNCATE TO ZERO */
- ndbrequire(cfsFirstfreeconnect != RNIL);
- seizeFsConnectRec(signal);
- fsConnectptr.p->fragrecPtr = fragrecptr.i;
- fsConnectptr.p->fsState = WAIT_OPEN_DATA_FILE_FOR_WRITE;
- /* ************************ */
- /* FSOPENREQ */
- /* ************************ */
- signal->theData[0] = cownBlockref;
- signal->theData[1] = fsConnectptr.i;
- signal->theData[2] = rootfragrecptr.p->mytabptr; /* TABLE IDENTITY */
- signal->theData[3] = rootfragrecptr.p->fragmentid[1]; /* FRAGMENT IDENTITY */
- signal->theData[4] = lcpConnectptr.p->localCheckPid; /* CHECKPOINT ID */
- signal->theData[5] = tlfrTmp1;
- signal->theData[6] = tlfrTmp2;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- return;
- } else {
- ndbrequire(rootfragrecptr.p->fragmentptr[1] == fragrecptr.i);
- }//if
- /*---- BOTH DATA FILES ARE OPEN------*/
- /* ----IF THE UNDO FILE IS CLOSED , OPEN IT.----- */
- if (cactiveOpenUndoFsPtr != RNIL) {
- jam();
- sendLcpFragidconfLab(signal);
- return;
- }//if
- cactiveUndoFilePage = 0;
- cprevUndoaddress = cminusOne;
- cundoposition = 0;
- clastUndoPageIdWritten = 0;
- ndbrequire(cfsFirstfreeconnect != RNIL);
- seizeFsConnectRec(signal);
- fsConnectptr.p->fsState = WAIT_OPEN_UNDO_LCP;
- fsConnectptr.p->fsPart = 0; /* FILE INDEX, SECOND FILE IN THE DIRECTORY */
- cactiveOpenUndoFsPtr = fsConnectptr.i;
- cactiveRootfrag = rootfragrecptr.i;
- tlfrTmp1 = 1; /* FILE VERSION */
- tlfrTmp1 = (tlfrTmp1 << 8) + ZLOCALLOGFILE; /* .LOCLOG = 2 */
- tlfrTmp1 = (tlfrTmp1 << 8) + 4; /* ROOT DIRECTORY = D4 */
- tlfrTmp1 = (tlfrTmp1 << 8) + fsConnectptr.p->fsPart; /* P2 */
- tlfrTmp2 = 0x302; /* D7 CREATE , READ / WRITE , TRUNCATE TO ZERO */
- /* ---FILE NAME "D4"/"DBACC"/LCP_CONNECTPTR:LOCAL_CHECK_PID/FS_CONNECTPTR:FS_PART".LOCLOG-- */
- /* ************************ */
- /* FSOPENREQ */
- /* ************************ */
- signal->theData[0] = cownBlockref;
- signal->theData[1] = fsConnectptr.i;
- signal->theData[2] = cminusOne; /* #FFFFFFFF */
- signal->theData[3] = cminusOne; /* #FFFFFFFF */
- signal->theData[4] = cactiveUndoFileVersion;
- /* A GROUP OF UNDO FILES WHICH ARE UPDATED */
- signal->theData[5] = tlfrTmp1;
- signal->theData[6] = tlfrTmp2;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- return;
-}//Dbacc::lcpFsOpenConfLab()
-
-void Dbacc::lcpOpenUndofileConfLab(Signal* signal)
-{
- ptrGuard(fsConnectptr);
- fsConnectptr.p->fsState = WAIT_NOTHING;
- rootfragrecptr.i = cactiveRootfrag;
- ptrCheck(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- fsConnectptr.p->fsPtr = tuserptr;
- sendLcpFragidconfLab(signal);
- return;
-}//Dbacc::lcpOpenUndofileConfLab()
-
-void Dbacc::sendLcpFragidconfLab(Signal* signal)
-{
- ptrGuard(rootfragrecptr);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- /* ************************ */
- /* LCP_FRAGIDCONF */
- /* ************************ */
- signal->theData[0] = lcpConnectptr.p->lcpUserptr;
- signal->theData[1] = lcpConnectptr.i;
- signal->theData[2] = 2;
- /* NO OF LOCAL FRAGMENTS */
- signal->theData[3] = rootfragrecptr.p->fragmentid[0];
- signal->theData[4] = rootfragrecptr.p->fragmentid[1];
- signal->theData[5] = RNIL;
- signal->theData[6] = RNIL;
- sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_LCP_FRAGIDCONF, signal, 7, JBB);
- return;
-}//Dbacc::sendLcpFragidconfLab()
-
-/* ******************--------------------------------------------------------------- */
-/* LCP_HOLDOPERATION REQUEST FOR LIST OF STOPED OPERATION */
-/* SENDER: LQH, LEVEL B */
-/* ENTER LCP_HOLDOPREQ WITH */
-/* LCP_CONNECTPTR CONNECTION POINTER */
-/* TFID, LOCAL FRAGMENT ID */
-/* THOLD_PREV_SENT_OP NR OF SENT OPERATIONS AT */
-/* PREVIOUS SIGNALS */
-/* TLQH_POINTER LQH USER POINTER */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* LCP_HOLDOPERATION REQUEST FOR LIST OF STOPED OPERATION */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execLCP_HOLDOPREQ(Signal* signal)
-{
- Uint32 tholdPrevSentOp;
-
- jamEntry();
- lcpConnectptr.i = signal->theData[0]; /* CONNECTION POINTER */
- tfid = signal->theData[1]; /* LOCAL FRAGMENT ID */
- tholdPrevSentOp = signal->theData[2]; /* NR OF SENT OPERATIONS AT */
- /* PREVIOUS SIGNALS */
- tlqhPointer = signal->theData[3]; /* LQH USER POINTER */
-
- tresult = 0;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE);
- rootfragrecptr.i = lcpConnectptr.p->rootrecptr;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (rootfragrecptr.p->fragmentid[0] == tfid) {
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- } else {
- ndbrequire(rootfragrecptr.p->fragmentid[1] == tfid);
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[1];
- }//if
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- fragrecptr.p->lcpLqhPtr = tlqhPointer;
- if (tholdPrevSentOp != 0) {
- ndbrequire(fragrecptr.p->fragState == SEND_QUE_OP);
- } else if (tholdPrevSentOp == 0) {
- jam();
- fragrecptr.p->fragState = SEND_QUE_OP;
- fragrecptr.p->stopQueOp = ZTRUE;
- fragrecptr.p->sentWaitInQueOp = fragrecptr.p->firstWaitInQueOp;
- }//if
- tholdSentOp = 0; /* NR OF OPERATION WHICH ARE SENT THIS TIME */
- operationRecPtr.i = fragrecptr.p->sentWaitInQueOp;
-
- /* --------------------------------------------- */
- /* GO THROUGH ALL OPERATION IN THE WAIT */
- /* LIST AND SEND THE LQH CONNECTION PTR OF THE */
- /* OPERATIONS TO THE LQH BLOCK. MAX 23 0PERATION */
- /* PER SIGNAL */
- /* --------------------------------------------- */
- while (operationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- ckeys[tholdSentOp] = operationRecPtr.p->userptr;
- operationRecPtr.i = operationRecPtr.p->nextQueOp;
- tholdSentOp++;
- if ((tholdSentOp >= 23) &&
- (operationRecPtr.i != RNIL)) {
- jam();
- /* ----------------------------------------------- */
- /* THERE IS MORE THAN 23 WAIT OPERATION. WE */
- /* HAVE TO SEND THESE 23 AND WAITE FOR NEXT SIGNAL */
- /* ----------------------------------------------- */
- tholdMore = ZTRUE; /* SECOUND DATA AT THE CONF SIGNAL , = MORE */
- fragrecptr.p->sentWaitInQueOp = operationRecPtr.i;
- sendholdconfsignalLab(signal);
- return;
- }//if
- }//while
- /* ----------------------------------------------- */
- /* OPERATION_REC_PTR = RNIL */
- /* THERE IS NO MORE WAITING OPERATION, STATE OF */
- /* THE FRAGMENT RRECORD IS CHANGED AND RETURN */
- /* SIGNAL IS SENT */
- /* ----------------------------------------------- */
- fragrecptr.p->sentWaitInQueOp = RNIL;
- tholdMore = ZFALSE; /* SECOND DATA AT THE CONF SIGNAL , = NOT MORE */
- fragrecptr.p->fragState = WAIT_ACC_LCPREQ;
- sendholdconfsignalLab(signal);
- return;
-}//Dbacc::execLCP_HOLDOPREQ()
-
-void Dbacc::sendholdconfsignalLab(Signal* signal)
-{
- tholdMore = (tholdMore << 16) + tholdSentOp;
- /* SECOND SIGNAL DATA, LENGTH + MORE */
- /* ************************ */
- /* LCP_HOLDOPCONF */
- /* ************************ */
- signal->theData[0] = fragrecptr.p->lcpLqhPtr;
- signal->theData[1] = tholdMore;
- signal->theData[2] = ckeys[0];
- signal->theData[3] = ckeys[1];
- signal->theData[4] = ckeys[2];
- signal->theData[5] = ckeys[3];
- signal->theData[6] = ckeys[4];
- signal->theData[7] = ckeys[5];
- signal->theData[8] = ckeys[6];
- signal->theData[9] = ckeys[7];
- signal->theData[10] = ckeys[8];
- signal->theData[11] = ckeys[9];
- signal->theData[12] = ckeys[10];
- signal->theData[13] = ckeys[11];
- signal->theData[14] = ckeys[12];
- signal->theData[15] = ckeys[13];
- signal->theData[16] = ckeys[14];
- signal->theData[17] = ckeys[15];
- signal->theData[18] = ckeys[16];
- signal->theData[19] = ckeys[17];
- signal->theData[20] = ckeys[18];
- signal->theData[21] = ckeys[19];
- signal->theData[22] = ckeys[20];
- signal->theData[23] = ckeys[21];
- signal->theData[24] = ckeys[22];
- sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_LCP_HOLDOPCONF, signal, 25, JBA);
- return;
-}//Dbacc::sendholdconfsignalLab()
-
-/**
- * execACC_LCPREQ
- * Perform local checkpoint of a fragment
- *
- * SENDER: LQH, LEVEL B
- * ENTER ACC_LCPREQ WITH
- * LCP_CONNECTPTR, OPERATION RECORD PTR
- * TLCP_LQH_CHECK_V, LQH'S LOCAL FRAG CHECK VALUE
- * TLCP_LOCAL_FRAG_ID, LOCAL FRAG ID
- *
- */
-void Dbacc::execACC_LCPREQ(Signal* signal)
-{
- Uint32 tlcpLocalFragId;
- Uint32 tlcpLqhCheckV;
-
- jamEntry();
- lcpConnectptr.i = signal->theData[0]; // CONNECTION PTR
- tlcpLqhCheckV = signal->theData[1]; // LQH'S LOCAL FRAG CHECK VALUE
- tlcpLocalFragId = signal->theData[2]; // LOCAL FRAG ID
- tresult = 0;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE);
-
- rootfragrecptr.i = lcpConnectptr.p->rootrecptr;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (rootfragrecptr.p->fragmentid[0] == tlcpLocalFragId) {
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- } else {
- ndbrequire(rootfragrecptr.p->fragmentid[1] == tlcpLocalFragId);
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[1];
- }//if
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- ndbrequire(fragrecptr.p->fragState == WAIT_ACC_LCPREQ);
- fragrecptr.p->lcpLqhPtr = tlcpLqhCheckV;
-
- Page8Ptr zeroPagePtr;
- seizeLcpPage(zeroPagePtr);
- fragrecptr.p->zeroPagePtr = zeroPagePtr.i;
- fragrecptr.p->prevUndoposition = cminusOne;
- initRootFragPageZero(rootfragrecptr, zeroPagePtr);
- initFragPageZero(fragrecptr, zeroPagePtr);
- /*-----------------------------------------------------------------*/
- /* SEIZE ZERO PAGE FIRST AND THEN SEIZE DATA PAGES IN */
- /* BACKWARDS ORDER. THIS IS TO ENSURE THAT WE GET THE PAGES */
- /* IN ORDER. ON WINDOWS NT THIS WILL BE A BENEFIT SINCE WE */
- /* CAN THEN DO 1 WRITE_FILE INSTEAD OF 8. */
- /* WHEN WE RELEASE THE PAGES WE RELEASE THEM IN THE OPPOSITE */
- /* ORDER. */
- /*-----------------------------------------------------------------*/
- for (Uint32 taspTmp = ZWRITEPAGESIZE - 1; (Uint32)~taspTmp; taspTmp--) {
- Page8Ptr dataPagePtr;
- jam();
- ndbrequire(fragrecptr.p->datapages[taspTmp] == RNIL);
- seizeLcpPage(dataPagePtr);
- fragrecptr.p->datapages[taspTmp] = dataPagePtr.i;
- }//for
- fragrecptr.p->lcpMaxDirIndex = fragrecptr.p->dirsize;
- fragrecptr.p->lcpMaxOverDirIndex = fragrecptr.p->lastOverIndex;
- fragrecptr.p->createLcp = ZTRUE;
- operationRecPtr.i = fragrecptr.p->lockOwnersList;
- lcp_write_op_to_undolog(signal);
-}
-
-void
-Dbacc::lcp_write_op_to_undolog(Signal* signal)
-{
- bool delay_continueb= false;
- Uint32 i, j;
- for (i= 0; i < 16; i++) {
- jam();
- if (remainingUndoPages() <= ZMIN_UNDO_PAGES_AT_COMMIT) {
- jam();
- delay_continueb= true;
- break;
- }
- for (j= 0; j < 32; j++) {
- if (operationRecPtr.i == RNIL) {
- jam();
- break;
- }
- jam();
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
-
- if ((operationRecPtr.p->operation == ZINSERT) ||
- (operationRecPtr.p->elementIsDisappeared == ZTRUE)){
- /*******************************************************************
- * Only log inserts and elements that are marked as dissapeared.
- * All other operations update the element header and that is handled
- * when pages are written to disk
- ********************************************************************/
- undopageptr.i = (cundoposition>>ZUNDOPAGEINDEXBITS) & (cundopagesize-1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
-
- writeUndoOpInfo(signal);/* THE INFORMATION ABOUT ELEMENT HEADER, STORED*/
- /* IN OP REC, IS WRITTEN AT UNDO PAGES */
- cundoElemIndex = 0;/* DEFAULT VALUE USED BY WRITE_UNDO_HEADER SUBROTINE */
- writeUndoHeader(signal, RNIL, UndoHeader::ZOP_INFO); /* WRITE THE HEAD OF THE UNDO ELEMENT */
- checkUndoPages(signal); /* SEND UNDO PAGE TO DISK WHEN A GROUP OF */
- /* UNDO PAGES,CURRENTLY 8, IS FILLED */
- }
- operationRecPtr.i = operationRecPtr.p->nextLockOwnerOp;
- }
- if (operationRecPtr.i == RNIL) {
- jam();
- break;
- }
- }
- if (operationRecPtr.i != RNIL) {
- jam();
- signal->theData[0]= ZLCP_OP_WRITE_RT_BREAK;
- signal->theData[1]= operationRecPtr.i;
- signal->theData[2]= fragrecptr.i;
- signal->theData[3]= lcpConnectptr.i;
- if (delay_continueb) {
- jam();
- sendSignalWithDelay(cownBlockref, GSN_CONTINUEB, signal, 10, 4);
- } else {
- jam();
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB);
- }
- return;
- }
-
- signal->theData[0] = fragrecptr.p->lcpLqhPtr;
- sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_LCPSTARTED,
- signal, 1, JBA);
-
- fragrecptr.p->activeDataPage = 0;
- fragrecptr.p->lcpDirIndex = 0;
- fragrecptr.p->fragState = LCP_SEND_PAGES;
-
- signal->theData[0] = lcpConnectptr.i;
- signal->theData[1] = fragrecptr.i;
- sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB);
-}
-
-/* ******************--------------------------------------------------------------- */
-/* ACC_SAVE_PAGES A GROUP OF PAGES IS ALLOCATED. THE PAGES AND OVERFLOW */
-/* PAGES OF THE FRAGMENT ARE COPIED IN THEM AND IS SEND TO */
-/* THE DATA FILE OF THE CHECK POINT. */
-/* SENDER: ACC, LEVEL B */
-/* ENTER ACC_SAVE_PAGES WITH */
-/* LCP_CONNECTPTR, CONNECTION RECORD PTR */
-/* FRAGRECPTR FRAGMENT RECORD PTR */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACC_SAVE_PAGES REQUEST TO SEND THE PAGE TO DISK */
-/* ******************------------------------------+ UNDO PAGES */
-/* SENDER: ACC, LEVEL B */
-void Dbacc::execACC_SAVE_PAGES(Signal* signal)
-{
- jamEntry();
- lcpConnectptr.i = signal->theData[0];
- /* CONNECTION RECORD PTR */
- fragrecptr.i = signal->theData[1];
- /* FRAGMENT RECORD PTR */
- tresult = 0;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- if (lcpConnectptr.p->lcpstate != LCP_ACTIVE) {
- jam();
- sendSystemerror(signal, __LINE__);
- return;
- }//if
- if (ERROR_INSERTED(3000)) {
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (rootfragrecptr.p->mytabptr == c_errorInsert3000_TableId){
- ndbout << "Delay writing of datapages" << endl;
- // Delay writing of pages
- jam();
- sendSignalWithDelay(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 1000, 2);
- return;
- }
- }
- if (clblPageCounter == 0) {
- jam();
- signal->theData[0] = lcpConnectptr.i;
- signal->theData[1] = fragrecptr.i;
- sendSignalWithDelay(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 100, 2);
- return;
- } else {
- jam();
- clblPageCounter = clblPageCounter - 1;
- }//if
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (fragrecptr.p->fragState == LCP_SEND_PAGES) {
- jam();
- savepagesLab(signal);
- return;
- } else {
- if (fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) {
- jam();
- saveOverPagesLab(signal);
- return;
- } else {
- ndbrequire(fragrecptr.p->fragState == LCP_SEND_ZERO_PAGE);
- jam();
- saveZeroPageLab(signal);
- return;
- }//if
- }//if
-}//Dbacc::execACC_SAVE_PAGES()
-
-void Dbacc::savepagesLab(Signal* signal)
-{
- DirRangePtr spDirRangePtr;
- DirectoryarrayPtr spDirptr;
- Page8Ptr aspPageptr;
- Page8Ptr aspCopyPageptr;
- Uint32 taspDirindex;
- Uint32 taspDirIndex;
- Uint32 taspIndex;
-
- if ((fragrecptr.p->lcpDirIndex >= fragrecptr.p->dirsize) ||
- (fragrecptr.p->lcpDirIndex >= fragrecptr.p->lcpMaxDirIndex)) {
- jam();
- endsavepageLab(signal);
- return;
- }//if
- /* SOME EXPAND PROCESSES HAVE BEEN PERFORMED. */
- /* THE ADDED PAGE ARE NOT SENT TO DISK */
- arrGuard(fragrecptr.p->activeDataPage, 8);
- aspCopyPageptr.i = fragrecptr.p->datapages[fragrecptr.p->activeDataPage];
- ptrCheckGuard(aspCopyPageptr, cpagesize, page8);
- taspDirindex = fragrecptr.p->lcpDirIndex; /* DIRECTORY OF ACTIVE PAGE */
- spDirRangePtr.i = fragrecptr.p->directory;
- taspDirIndex = taspDirindex >> 8;
- taspIndex = taspDirindex & 0xff;
- ptrCheckGuard(spDirRangePtr, cdirrangesize, dirRange);
- arrGuard(taspDirIndex, 256);
- spDirptr.i = spDirRangePtr.p->dirArray[taspDirIndex];
- ptrCheckGuard(spDirptr, cdirarraysize, directoryarray);
- aspPageptr.i = spDirptr.p->pagep[taspIndex];
- ptrCheckGuard(aspPageptr, cpagesize, page8);
- ndbrequire(aspPageptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->lcpDirIndex);
- lcnPageptr = aspPageptr;
- lcnCopyPageptr = aspCopyPageptr;
- lcpCopyPage(signal);
- fragrecptr.p->lcpDirIndex++;
- fragrecptr.p->activeDataPage++;
- if (fragrecptr.p->activeDataPage < ZWRITEPAGESIZE) {
- jam();
- signal->theData[0] = lcpConnectptr.i;
- signal->theData[1] = fragrecptr.i;
- sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB);
- return;
- }//if
- senddatapagesLab(signal);
- return;
-}//Dbacc::savepagesLab()
-
-/* FRAGRECPTR:ACTIVE_DATA_PAGE = ZWRITEPAGESIZE */
-/* SEND A GROUP OF PAGES TO DISK */
-void Dbacc::senddatapagesLab(Signal* signal)
-{
- fsConnectptr.i = fragrecptr.p->fsConnPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- seizeFsOpRec(signal);
- initFsOpRec(signal);
- fsOpptr.p->fsOpstate = WAIT_WRITE_DATA;
- ndbrequire(fragrecptr.p->activeDataPage <= 8);
- for (Uint32 i = 0; i < fragrecptr.p->activeDataPage; i++) {
- signal->theData[i + 6] = fragrecptr.p->datapages[i];
- }//for
- signal->theData[fragrecptr.p->activeDataPage + 6] = fragrecptr.p->activeDataFilePage;
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsOpptr.i;
- signal->theData[3] = 0x2;
- signal->theData[4] = ZPAGE8_BASE_ADD;
- signal->theData[5] = fragrecptr.p->activeDataPage;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 15, JBA);
- return;
-}//Dbacc::senddatapagesLab()
-
-void Dbacc::endsavepageLab(Signal* signal)
-{
- Page8Ptr espPageidptr;
-
- espPageidptr.i = fragrecptr.p->zeroPagePtr;
- ptrCheckGuard(espPageidptr, cpagesize, page8);
- dbgWord32(espPageidptr, ZPAGEZERO_NO_PAGES, fragrecptr.p->lcpDirIndex);
- espPageidptr.p->word32[ZPAGEZERO_NO_PAGES] = fragrecptr.p->lcpDirIndex;
- fragrecptr.p->fragState = LCP_SEND_OVER_PAGES;
- fragrecptr.p->noOfStoredOverPages = 0;
- fragrecptr.p->lcpDirIndex = 0;
- saveOverPagesLab(signal);
- return;
-}//Dbacc::endsavepageLab()
-
-/* ******************--------------------------------------------------------------- */
-/* ACC_SAVE_OVER_PAGES CONTINUE SAVING THE LEFT OVERPAGES. */
-/* ******************--------------------------------------------------------------- */
-void Dbacc::saveOverPagesLab(Signal* signal)
-{
- DirRangePtr sopDirRangePtr;
- DirectoryarrayPtr sopOverflowDirptr;
- Page8Ptr sopPageptr;
- Page8Ptr sopCopyPageptr;
- Uint32 tsopDirindex;
- Uint32 tsopDirInd;
- Uint32 tsopIndex;
-
- if ((fragrecptr.p->lcpDirIndex >= fragrecptr.p->lastOverIndex) ||
- (fragrecptr.p->lcpDirIndex >= fragrecptr.p->lcpMaxOverDirIndex)) {
- jam();
- endsaveoverpageLab(signal);
- return;
- }//if
- arrGuard(fragrecptr.p->activeDataPage, 8);
- sopCopyPageptr.i = fragrecptr.p->datapages[fragrecptr.p->activeDataPage];
- ptrCheckGuard(sopCopyPageptr, cpagesize, page8);
- tsopDirindex = fragrecptr.p->lcpDirIndex;
- sopDirRangePtr.i = fragrecptr.p->overflowdir;
- tsopDirInd = tsopDirindex >> 8;
- tsopIndex = tsopDirindex & 0xff;
- ptrCheckGuard(sopDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tsopDirInd, 256);
- sopOverflowDirptr.i = sopDirRangePtr.p->dirArray[tsopDirInd];
- ptrCheckGuard(sopOverflowDirptr, cdirarraysize, directoryarray);
- sopPageptr.i = sopOverflowDirptr.p->pagep[tsopIndex];
- fragrecptr.p->lcpDirIndex++;
- if (sopPageptr.i != RNIL) {
- jam();
- ptrCheckGuard(sopPageptr, cpagesize, page8);
- ndbrequire(sopPageptr.p->word32[ZPOS_PAGE_ID] == tsopDirindex);
- ndbrequire(((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZNORMAL_PAGE_TYPE);
- lcnPageptr = sopPageptr;
- lcnCopyPageptr = sopCopyPageptr;
- lcpCopyPage(signal);
- fragrecptr.p->noOfStoredOverPages++;
- fragrecptr.p->activeDataPage++;
- if ((sopPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0)) {
- //ndbrequire(((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZOVERFLOW_PAGE_TYPE);
- if (((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) ==
- ZOVERFLOW_PAGE_TYPE) {
- /*--------------------------------------------------------------------------------*/
- /* THE PAGE IS EMPTY AND WAITING TO BE RELEASED. IT COULD NOT BE RELEASED */
- /* EARLIER SINCE IT WAS PART OF A LOCAL CHECKPOINT. */
- /*--------------------------------------------------------------------------------*/
- jam();
- ropPageptr = sopPageptr;
- releaseOverpage(signal);
- } else {
- jam();
- sendSystemerror(signal, __LINE__);
- }
- }//if
- }
- if (fragrecptr.p->activeDataPage == ZWRITEPAGESIZE) {
- jam();
- senddatapagesLab(signal);
- return;
- }//if
- signal->theData[0] = lcpConnectptr.i;
- signal->theData[1] = fragrecptr.i;
- sendSignal(cownBlockref, GSN_ACC_SAVE_PAGES, signal, 2, JBB);
- return;
-}//Dbacc::saveOverPagesLab()
-
-void Dbacc::endsaveoverpageLab(Signal* signal)
-{
- Page8Ptr esoPageidptr;
-
- esoPageidptr.i = fragrecptr.p->zeroPagePtr;
- ptrCheckGuard(esoPageidptr, cpagesize, page8);
- dbgWord32(esoPageidptr, ZPAGEZERO_NO_OVER_PAGE, fragrecptr.p->noOfStoredOverPages);
- esoPageidptr.p->word32[ZPAGEZERO_NO_OVER_PAGE] = fragrecptr.p->noOfStoredOverPages;
- fragrecptr.p->fragState = LCP_SEND_ZERO_PAGE;
- if (fragrecptr.p->activeDataPage != 0) {
- jam();
- senddatapagesLab(signal); /* SEND LEFT PAGES TO DISK */
- return;
- }//if
- saveZeroPageLab(signal);
- return;
-}//Dbacc::endsaveoverpageLab()
-
-/* ******************--------------------------------------------------------------- */
-/* ACC_SAVE_ZERO_PAGE PAGE ZERO IS SENT TO DISK.IT IS THE LAST STAGE AT THE */
-/* CREATION LCP. ACC_LCPCONF IS RETURND. */
-/* ******************--------------------------------------------------------------- */
-void Dbacc::saveZeroPageLab(Signal* signal)
-{
- Page8Ptr szpPageidptr;
- Uint32 Tchs;
- Uint32 Ti;
-
- fragrecptr.p->createLcp = ZFALSE;
- fsConnectptr.i = fragrecptr.p->fsConnPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- szpPageidptr.i = fragrecptr.p->zeroPagePtr;
- ptrCheckGuard(szpPageidptr, cpagesize, page8);
- dbgWord32(szpPageidptr, ZPAGEZERO_PREV_UNDOP, fragrecptr.p->prevUndoposition);
- szpPageidptr.p->word32[ZPAGEZERO_PREV_UNDOP] = fragrecptr.p->prevUndoposition;
- dbgWord32(szpPageidptr, ZPAGEZERO_NEXT_UNDO_FILE, cactiveUndoFileVersion);
- szpPageidptr.p->word32[ZPAGEZERO_NEXT_UNDO_FILE] = cactiveUndoFileVersion;
- fragrecptr.p->fragState = WAIT_ZERO_PAGE_STORED;
-
- /* --------------------------------------------------------------------------------- */
- // Calculate the checksum and store it for the zero page of the fragment.
- /* --------------------------------------------------------------------------------- */
- szpPageidptr.p->word32[ZPOS_CHECKSUM] = 0;
- Tchs = 0;
- for (Ti = 0; Ti < 2048; Ti++) {
- Tchs = Tchs ^ szpPageidptr.p->word32[Ti];
- }//for
- szpPageidptr.p->word32[ZPOS_CHECKSUM] = Tchs;
- dbgWord32(szpPageidptr, ZPOS_CHECKSUM, Tchs);
-
- seizeFsOpRec(signal);
- initFsOpRec(signal);
- fsOpptr.p->fsOpstate = WAIT_WRITE_DATA;
- if (clblPageCounter > 0) {
- jam();
- clblPageCounter = clblPageCounter - 1;
- } else {
- jam();
- clblPageOver = clblPageOver + 1;
- }//if
- /* ************************ */
- /* FSWRITEREQ */
- /* ************************ */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsOpptr.i;
- signal->theData[3] = 0x10;
- /* FLAG = LIST MEM PAGES, LIST FILE PAGES */
- /* SYNC FILE AFTER WRITING */
- signal->theData[4] = ZPAGE8_BASE_ADD;
- signal->theData[5] = 1;
- /* NO OF PAGES */
- signal->theData[6] = fragrecptr.p->zeroPagePtr;
- /* ZERO PAGE */
- signal->theData[7] = 0;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
- /* ZERO PAGE AT DATA FILE */
- return;
-}//Dbacc::saveZeroPageLab()
-
-/* ******************--------------------------------------------------------------- */
-/* FSWRITECONF OPENFILE CONF */
-/* ENTER FSWRITECONF WITH SENDER: FS, LEVEL B */
-/* FS_OPPTR FS_CONNECTION PTR */
-/* ******************--------------------------------------------------------------- */
-void Dbacc::lcpCloseDataFileLab(Signal* signal)
-{
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- fsConnectptr.p->fsState = LCP_CLOSE_DATA;
- /* ************************ */
- /* FSCLOSEREQ */
- /* ************************ */
- /* CLOSE DATA FILE */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = ZFALSE;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- /* FLAG = 0, DO NOT DELETE FILE */
- return;
-}//Dbacc::lcpCloseDataFileLab()
-
-void Dbacc::checkSyncUndoPagesLab(Signal* signal)
-{
- fragrecptr.i = fsConnectptr.p->fragrecPtr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- releaseFsConnRec(signal);
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- switch (lcpConnectptr.p->syncUndopageState) {
- case WAIT_NOTHING:
- jam();
- lcpConnectptr.p->syncUndopageState = WAIT_ONE_CONF;
- break;
- case WAIT_ONE_CONF:
- jam();
- lcpConnectptr.p->syncUndopageState = WAIT_TWO_CONF;
- break;
- default:
- jam();
- sendSystemerror(signal, __LINE__);
- return;
- break;
- }//switch
-
- /* ACTIVE UNDO PAGE ID */
- Uint32 tundoPageId = cundoposition >> ZUNDOPAGEINDEXBITS;
- tmp1 = tundoPageId - (tundoPageId & (ZWRITE_UNDOPAGESIZE - 1));
- /* START PAGE OF THE LAST UNDO PAGES GROUP */
- tmp2 = (tundoPageId - tmp1) + 1; /* NO OF LEFT UNDO PAGES */
- tmp1 = tmp1 & (cundopagesize - 1); /* 1 MBYTE PAGE WINDOW IN MEMORY */
- fsConnectptr.i = cactiveOpenUndoFsPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- seizeFsOpRec(signal);
- initFsOpRec(signal);
- fsOpptr.p->fsOpstate = WAIT_WRITE_UNDO;
- fsOpptr.p->fsOpMemPage = tundoPageId; /* RECORD MEMORY PAGE WRITTEN */
- if (clblPageCounter >= (4 * tmp2)) {
- jam();
- clblPageCounter = clblPageCounter - (4 * tmp2);
- } else {
- jam();
- clblPageOver = clblPageOver + ((4 * tmp2) - clblPageCounter);
- clblPageCounter = 0;
- }//if
- /* ************************ */
- /* FSWRITEREQ */
- /* ************************ */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsOpptr.i;
- /* FLAG = START MEM PAGES, START FILE PAGES */
- /* SYNC FILE AFTER WRITING */
- signal->theData[3] = 0x11;
- signal->theData[4] = ZUNDOPAGE_BASE_ADD;
- /* NO OF UNDO PAGES */
- signal->theData[5] = tmp2;
- /* FIRST MEMORY PAGE */
- signal->theData[6] = tmp1;
- /* ACTIVE PAGE AT UNDO FILE */
- signal->theData[7] = cactiveUndoFilePage;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
-
- return;
-}//Dbacc::checkSyncUndoPagesLab()
-
-void Dbacc::checkSendLcpConfLab(Signal* signal)
-{
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE);
- switch (lcpConnectptr.p->syncUndopageState) {
- case WAIT_ONE_CONF:
- jam();
- lcpConnectptr.p->syncUndopageState = WAIT_NOTHING;
- break;
- case WAIT_TWO_CONF:
- jam();
- lcpConnectptr.p->syncUndopageState = WAIT_ONE_CONF;
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- lcpConnectptr.p->noOfLcpConf++;
- ndbrequire(lcpConnectptr.p->noOfLcpConf <= 4);
- fragrecptr.p->fragState = ACTIVEFRAG;
- rlpPageptr.i = fragrecptr.p->zeroPagePtr;
- ptrCheckGuard(rlpPageptr, cpagesize, page8);
- releaseLcpPage(signal);
- fragrecptr.p->zeroPagePtr = RNIL;
- for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) {
- jam();
- if (fragrecptr.p->datapages[i] != RNIL) {
- jam();
- rlpPageptr.i = fragrecptr.p->datapages[i];
- ptrCheckGuard(rlpPageptr, cpagesize, page8);
- releaseLcpPage(signal);
- fragrecptr.p->datapages[i] = RNIL;
- }//if
- }//for
- signal->theData[0] = fragrecptr.p->lcpLqhPtr;
- sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_LCPCONF, signal, 1, JBB);
- if (lcpConnectptr.p->noOfLcpConf == 4) {
- jam();
- releaseLcpConnectRec(signal);
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- rootfragrecptr.p->rootState = ACTIVEROOT;
- }//if
-}//Dbacc::checkSendLcpConfLab()
-
-/* ******************--------------------------------------------------------------- */
-/* ACC_CONTOPREQ */
-/* SENDER: LQH, LEVEL B */
-/* ENTER ACC_CONTOPREQ WITH */
-/* LCP_CONNECTPTR */
-/* TMP1 LOCAL FRAG ID */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACC_CONTOPREQ COMMIT TRANSACTION */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execACC_CONTOPREQ(Signal* signal)
-{
- Uint32 tcorLocalFrag;
-
- jamEntry();
- lcpConnectptr.i = signal->theData[0];
- /* CONNECTION PTR */
- tcorLocalFrag = signal->theData[1];
- /* LOCAL FRAG ID */
- tresult = 0;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- if(ERROR_INSERTED(3002) && lcpConnectptr.p->noOfLcpConf < 2)
- {
- sendSignalWithDelay(cownBlockref, GSN_ACC_CONTOPREQ, signal, 300,
- signal->getLength());
- return;
- }
-
- ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE);
- rootfragrecptr.i = lcpConnectptr.p->rootrecptr;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (rootfragrecptr.p->fragmentid[0] == tcorLocalFrag) {
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- } else {
- ndbrequire(rootfragrecptr.p->fragmentid[1] == tcorLocalFrag);
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[1];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- }//if
- operationRecPtr.i = fragrecptr.p->firstWaitInQueOp;
- fragrecptr.p->sentWaitInQueOp = RNIL;
- fragrecptr.p->stopQueOp = ZFALSE;
- while (operationRecPtr.i != RNIL) {
- jam();
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- if (operationRecPtr.p->opState == WAIT_EXE_OP) {
- jam();
- //------------------------------------------------------------
- // Indicate that we are now a normal waiter in the queue. We
- // will remove the operation from the queue as part of starting
- // operation again.
- //------------------------------------------------------------
- operationRecPtr.p->opState = WAIT_IN_QUEUE;
- executeNextOperation(signal);
- }//if
- operationRecPtr.i = operationRecPtr.p->nextQueOp;
- }//while
- signal->theData[0] = fragrecptr.p->lcpLqhPtr;
- sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_CONTOPCONF, signal, 1, JBA);
-
- lcpConnectptr.p->noOfLcpConf++;
- if (lcpConnectptr.p->noOfLcpConf == 4) {
- jam();
- releaseLcpConnectRec(signal);
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- rootfragrecptr.p->rootState = ACTIVEROOT;
- }//if
- return; /* ALL QUEUED OPERATION ARE RESTARTED IF NEEDED. */
-}//Dbacc::execACC_CONTOPREQ()
-
-/* ******************--------------------------------------------------------------- */
-/* END_LCPREQ END OF LOCAL CHECK POINT */
-/* ENTER END_LCPREQ WITH SENDER: LQH, LEVEL B */
-/* CLQH_PTR, LQH PTR */
-/* CLQH_BLOCK_REF LQH BLOCK REF */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* END_LCPREQ PERFORM A LOCAL CHECK POINT */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execEND_LCPREQ(Signal* signal)
-{
- jamEntry();
- clqhPtr = signal->theData[0];
- /* LQH PTR */
- clqhBlockRef = signal->theData[1];
- /* LQH BLOCK REF */
- tresult = 0;
- fsConnectptr.i = cactiveOpenUndoFsPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- fsConnectptr.p->fsState = WAIT_CLOSE_UNDO; /* CLOSE FILE AFTER WRITTING */
- /* ************************ */
- /* FSCLOSEREQ */
- /* ************************ */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = ZFALSE;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- /* FLAG = 0, DO NOT DELETE FILE */
- cactiveUndoFileVersion = RNIL;
- cactiveOpenUndoFsPtr = RNIL;
- /* ************************ */
- /* END_LCPCONF */
- /* ************************ */
- signal->theData[0] = clqhPtr;
- sendSignal(clqhBlockRef, GSN_END_LCPCONF, signal, 1, JBB);
- return;
-}//Dbacc::execEND_LCPREQ()
-
-/*-----------------------------------------------------------------*/
-/* WHEN WE COPY THE PAGE WE ALSO WRITE THE ELEMENT HEADER AS */
-/* UNLOCKED IF THEY ARE CURRENTLY LOCKED. */
-/*-----------------------------------------------------------------*/
-void Dbacc::lcpCopyPage(Signal* signal)
-{
- Uint32 tlcnNextContainer;
- Uint32 tlcnTmp;
- Uint32 tlcnConIndex;
- Uint32 tlcnIndex;
- Uint32 Tmp1;
- Uint32 Tmp2;
- Uint32 Tmp3;
- Uint32 Tmp4;
- Uint32 Ti;
- Uint32 Tchs;
- Uint32 Tlimit;
-
- Tchs = 0;
- lupPageptr.p = lcnCopyPageptr.p;
- lcnPageptr.p->word32[ZPOS_CHECKSUM] = Tchs;
- for (Ti = 0; Ti < 32 ; Ti++) {
- Tlimit = 16 + (Ti << 6);
- for (tlcnTmp = (Ti << 6); tlcnTmp < Tlimit; tlcnTmp ++) {
- Tmp1 = lcnPageptr.p->word32[tlcnTmp];
- Tmp2 = lcnPageptr.p->word32[tlcnTmp + 16];
- Tmp3 = lcnPageptr.p->word32[tlcnTmp + 32];
- Tmp4 = lcnPageptr.p->word32[tlcnTmp + 48];
-
- lcnCopyPageptr.p->word32[tlcnTmp] = Tmp1;
- lcnCopyPageptr.p->word32[tlcnTmp + 16] = Tmp2;
- lcnCopyPageptr.p->word32[tlcnTmp + 32] = Tmp3;
- lcnCopyPageptr.p->word32[tlcnTmp + 48] = Tmp4;
-
- Tchs = Tchs ^ Tmp1;
- Tchs = Tchs ^ Tmp2;
- Tchs = Tchs ^ Tmp3;
- Tchs = Tchs ^ Tmp4;
- }//for
- }//for
- tlcnChecksum = Tchs;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- lcpUpdatePage(signal);
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
- /*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
- lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal, __LINE__);
- return;
- }//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
- lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal, __LINE__);
- return;
- }//if
- lcnCopyPageptr.p->word32[ZPOS_CHECKSUM] = tlcnChecksum;
-}//Dbacc::lcpCopyPage()
-
-/* --------------------------------------------------------------------------------- */
-/* THIS SUBROUTINE GOES THROUGH ONE CONTAINER TO CHECK FOR LOCKED ELEMENTS AND */
-/* UPDATING THEM TO ENSURE ALL ELEMENTS ARE UNLOCKED ON DISK. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::lcpUpdatePage(Signal* signal)
-{
- OperationrecPtr lupOperationRecPtr;
- Uint32 tlupElemHead;
- Uint32 tlupElemLen;
- Uint32 tlupElemStep;
- Uint32 tlupConLen;
-
- tlupConLen = lupPageptr.p->word32[tlupIndex] >> 26;
- tlupElemLen = fragrecptr.p->elementLength;
- tlupElemStep = tlupForward * tlupElemLen;
- while (tlupConLen > ZCON_HEAD_SIZE) {
- jam();
- tlupElemHead = lupPageptr.p->word32[tlupElemIndex];
- if (ElementHeader::getLocked(tlupElemHead)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WHEN CHANGING THE ELEMENT HEADER WE ALSO HAVE TO UPDATE THE CHECKSUM. IN */
- /* DOING THIS WE USE THE FORMULA (A XOR B) XOR B = A WHICH MEANS THAT IF WE */
- /* XOR SOMETHING TWICE WITH THE SAME OPERAND THEN WE RETURN TO THE ORIGINAL */
- /* VALUE. THEN WE ALSO HAVE TO USE THE NEW ELEMENT HEADER IN THE CHECKSUM */
- /* CALCULATION. */
- /* --------------------------------------------------------------------------------- */
- tlcnChecksum = tlcnChecksum ^ tlupElemHead;
- lupOperationRecPtr.i = ElementHeader::getOpPtrI(tlupElemHead);
- ptrCheckGuard(lupOperationRecPtr, coprecsize, operationrec);
- const Uint32 hv = lupOperationRecPtr.p->hashvaluePart;
- tlupElemHead = ElementHeader::setUnlocked(hv , 0);
- arrGuard(tlupElemIndex, 2048);
- lupPageptr.p->word32[tlupElemIndex] = tlupElemHead;
- tlcnChecksum = tlcnChecksum ^ tlupElemHead;
- }//if
- tlupConLen = tlupConLen - tlupElemLen;
- tlupElemIndex = tlupElemIndex + tlupElemStep;
- }//while
- if (tlupConLen < ZCON_HEAD_SIZE) {
- jam();
- sendSystemerror(signal, __LINE__);
- }//if
-}//Dbacc::lcpUpdatePage()
-
-/*-----------------------------------------------------------------*/
-// At a system restart we check that the page do not contain any
-// locks that hinder the system restart procedure.
-/*-----------------------------------------------------------------*/
-void Dbacc::srCheckPage(Signal* signal)
-{
- Uint32 tlcnNextContainer;
- Uint32 tlcnConIndex;
- Uint32 tlcnIndex;
-
- lupPageptr.p = lcnCopyPageptr.p;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
- /*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- tresult = 4;
- return;
- }//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- tresult = 4;
- return;
- }//if
-}//Dbacc::srCheckPage()
-
-/* --------------------------------------------------------------------------------- */
-/* THIS SUBROUTINE GOES THROUGH ONE CONTAINER TO CHECK FOR LOCKED ELEMENTS AND */
-/* UPDATING THEM TO ENSURE ALL ELEMENTS ARE UNLOCKED ON DISK. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::srCheckContainer(Signal* signal)
-{
- Uint32 tlupElemLen;
- Uint32 tlupElemStep;
- Uint32 tlupConLen;
-
- tlupConLen = lupPageptr.p->word32[tlupIndex] >> 26;
- tlupElemLen = fragrecptr.p->elementLength;
- tlupElemStep = tlupForward * tlupElemLen;
- while (tlupConLen > ZCON_HEAD_SIZE) {
- jam();
- const Uint32 tlupElemHead = lupPageptr.p->word32[tlupElemIndex];
- if (ElementHeader::getLocked(tlupElemHead)){
- jam();
- //-------------------------------------------------------
- // This is absolutely undesirable. We have a lock remaining
- // after the system restart. We send a crash signal that will
- // enter the trace file.
- //-------------------------------------------------------
- tresult = 2;
- return;
- }//if
- tlupConLen = tlupConLen - tlupElemLen;
- tlupElemIndex = tlupElemIndex + tlupElemStep;
- }//while
- if (tlupConLen < ZCON_HEAD_SIZE) {
- jam();
- tresult = 3;
- }//if
- return;
-}//Dbacc::srCheckContainer()
-
-/* ------------------------------------------------------------------------- */
-/* CHECK_UNDO_PAGES */
-/* DESCRIPTION: CHECKS WHEN A PAGE OR A GROUP OF UNDO PAGES IS FILLED.WHEN */
-/* A PAGE IS FILLED, CUNDOPOSITION WILL BE UPDATE, THE NEW */
-/* POSITION IS THE BEGNING OF THE NEXT UNDO PAGE. */
-/* IN CASE THAT A GROUP IS FILLED THE PAGES ARE SENT TO DISK, */
-/* AND A NEW GROUP IS CHOSEN. */
-/* ------------------------------------------------------------------------- */
-void Dbacc::checkUndoPages(Signal* signal)
-{
-
- fragrecptr.p->prevUndoposition = cundoposition;
- cprevUndoaddress = cundoposition;
-
- // Calculate active undo page id
- Uint32 tundoPageId = cundoposition >> ZUNDOPAGEINDEXBITS;
-
- /**
- * WE WILL WRITE UNTIL WE HAVE ABOUT 8 KBYTE REMAINING ON THE 32 KBYTE
- * PAGE. THIS IS TO ENSURE THAT WE DO NOT HAVE ANY UNDO LOG RECORDS THAT PASS
- * A PAGE BOUNDARIE. THIS SIMPLIFIES CODING TRADING SOME INEFFICIENCY.
- */
- static const Uint32 ZMAXUNDOPAGEINDEX = 7100;
- if (tundoindex < ZMAXUNDOPAGEINDEX) {
- jam();
- cundoposition = (tundoPageId << ZUNDOPAGEINDEXBITS) + tundoindex;
- return;
- }//if
-
- /**
- * WE CHECK IF MORE THAN 1 MBYTE OF WRITES ARE OUTSTANDING TO THE UNDO FILE.
- * IF SO WE HAVE TO CRASH SINCE WE HAVE NO MORE SPACE TO WRITE UNDO LOG
- * RECORDS IN
- */
- Uint16 nextUndoPageId = tundoPageId + 1;
- updateUndoPositionPage(signal, nextUndoPageId << ZUNDOPAGEINDEXBITS);
-
- if ((tundoPageId & (ZWRITE_UNDOPAGESIZE - 1)) == (ZWRITE_UNDOPAGESIZE - 1)) {
- jam();
- /* ---------- SEND A GROUP OF UNDO PAGES TO DISK --------- */
- fsConnectptr.i = cactiveOpenUndoFsPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- Uint32 tcupTmp1 = (tundoPageId - ZWRITE_UNDOPAGESIZE) + 1;
- tcupTmp1 = tcupTmp1 & (cundopagesize - 1); /* 1 MBYTE PAGE WINDOW */
- seizeFsOpRec(signal);
- initFsOpRec(signal);
- fsOpptr.p->fsOpstate = WAIT_WRITE_UNDO_EXIT;
- fsOpptr.p->fsOpMemPage = tundoPageId;
- fragrecptr.p->nrWaitWriteUndoExit++;
- if (clblPageCounter >= 8) {
- jam();
- clblPageCounter = clblPageCounter - 8;
- } else {
- jam();
- clblPageOver = clblPageOver + (8 - clblPageCounter);
- clblPageCounter = 0;
- }//if
- /* ************************ */
- /* FSWRITEREQ */
- /* ************************ */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsOpptr.i;
- signal->theData[3] = 0x1;
- /* FLAG = START MEM PAGES, START FILE PAGES */
- signal->theData[4] = ZUNDOPAGE_BASE_ADD;
- signal->theData[5] = ZWRITE_UNDOPAGESIZE;
- signal->theData[6] = tcupTmp1;
- signal->theData[7] = cactiveUndoFilePage;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
- cactiveUndoFilePage = cactiveUndoFilePage + ZWRITE_UNDOPAGESIZE;
- }//if
-}//Dbacc::checkUndoPages()
-
-/* --------------------------------------------------------------------------------- */
-/* UNDO_WRITING_PROCESS */
-/* INPUT: FRAGRECPTR, CUNDO_ELEM_INDEX, DATAPAGEPTR, CUNDOINFOLENGTH */
-/* DESCRIPTION: WHEN THE PROCESS OF CREATION LOCAL CHECK POINT HAS */
-/* STARTED. IF THE ACTIVE PAGE IS NOT ALREADY SENT TO DISK, THE */
-/* OLD VALUE OF THE ITEM WHICH IS GOING TO BE CHECKED IS STORED ON */
-/* THE ACTIVE UNDO PAGE. INFORMATION ABOUT UNDO PROCESS IN THE */
-/* BLOCK AND IN THE FRAGMENT WILL BE UPDATED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::undoWritingProcess(Signal* signal)
-{
- const Uint32 tactivePageDir = datapageptr.p->word32[ZPOS_PAGE_ID];
- const Uint32 tpageType = (datapageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3;
- if (fragrecptr.p->fragState == LCP_SEND_PAGES) {
- if (tpageType == ZNORMAL_PAGE_TYPE) {
- /* --------------------------------------------------------------------------- */
- /* HANDLING OF LOG OF NORMAL PAGES DURING WRITE OF NORMAL PAGES. */
- /* --------------------------------------------------------------------------- */
- if (tactivePageDir < fragrecptr.p->lcpDirIndex) {
- jam();
- /* ------------------------------------------------------------------- */
- /* THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT. */
- /* ------------------------------------------------------------------- */
- /*empty*/;
- } else {
- if (tactivePageDir >= fragrecptr.p->lcpMaxDirIndex) {
- jam();
- /* --------------------------------------------------------------------------- */
- /* OBVIOUSLY THE FRAGMENT HAS EXPANDED SINCE THE START OF THE LOCAL CHECKPOINT.*/
- /* WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID NOT EXIST AT START OF LCP. */
- /* --------------------------------------------------------------------------- */
- /*empty*/;
- } else {
- jam();
- /* --------------------------------------------------------------------------- */
- /* IN ALL OTHER CASES WE HAVE TO WRITE TO THE UNDO LOG. */
- /* --------------------------------------------------------------------------- */
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZPAGE_INFO);
- tundoElemIndex = cundoElemIndex;
- writeUndoDataInfo(signal);
- checkUndoPages(signal);
- }//if
- }//if
- } else if (tpageType == ZOVERFLOW_PAGE_TYPE) {
- /* --------------------------------------------------------------------------------- */
- /* OVERFLOW PAGE HANDLING DURING WRITE OF NORMAL PAGES. */
- /* --------------------------------------------------------------------------------- */
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */
- /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/
- /* NOT EXIST AT START OF LCP. */
- /* --------------------------------------------------------------------------------- */
- /*empty*/;
- } else {
- jam();
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZOVER_PAGE_INFO);
- tundoElemIndex = cundoElemIndex;
- writeUndoDataInfo(signal);
- checkUndoPages(signal);
- }//if
- } else {
- jam();
- /* --------------------------------------------------------------------------- */
- /* ONLY PAGE INFO AND OVERFLOW PAGE INFO CAN BE LOGGED BY THIS ROUTINE. A */
- /* SERIOUS ERROR. */
- /* --------------------------------------------------------------------------- */
- sendSystemerror(signal, __LINE__);
- }
- } else {
- if (fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* DURING WRITE OF OVERFLOW PAGES WE NEED NOT WORRY ANYMORE ABOUT NORMAL PAGES.*/
- /* --------------------------------------------------------------------------------- */
- if (tpageType == ZOVERFLOW_PAGE_TYPE) {
- if (tactivePageDir < fragrecptr.p->lcpDirIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT. */
- /* --------------------------------------------------------------------------------- */
- /*empty*/;
- } else {
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */
- /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/
- /* NOT EXIST AT START OF LCP. */
- /* --------------------------------------------------------------------------------- */
- /*empty*/;
- } else {
- jam();
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZOVER_PAGE_INFO);
- tundoElemIndex = cundoElemIndex;
- writeUndoDataInfo(signal);
- checkUndoPages(signal);
- }//if
- }//if
- }
- }//if
- }//if
-}//Dbacc::undoWritingProcess()
-
-/* --------------------------------------------------------------------------------- */
-/* OTHER STATES MEANS THAT WE HAVE ALREADY WRITTEN ALL PAGES BUT NOT YET RESET */
-/* THE CREATE_LCP FLAG. */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* WRITE_UNDO_DATA_INFO */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::writeUndoDataInfo(Signal* signal)
-{
- Uint32 twudiIndex;
- Uint32 guard22;
-
- guard22 = cundoinfolength;
- arrGuard((tundoindex + guard22 - 1), 8192);
- arrGuard((tundoElemIndex + guard22 - 1), 2048);
- for (twudiIndex = 1; twudiIndex <= guard22; twudiIndex++) {
- undopageptr.p->undoword[tundoindex] = datapageptr.p->word32[tundoElemIndex];
- tundoindex++;
- tundoElemIndex++;
- }//for
-}//Dbacc::writeUndoDataInfo()
-
-/* --------------------------------------------------------------------------------- */
-/* WRITE_UNDO_HEADER */
-/* THE HEAD OF UNDO ELEMENT IS 24 BYTES AND CONTAINS THE FOLLOWING INFORMATION: */
-/* TABLE IDENTITY 32 BITS */
-/* ROOT FRAGMENT IDENTITY 32 BITS */
-/* LOCAL FRAGMENT IDENTITY 32 BITS */
-/* LENGTH OF ELEMENT INF0 (BIT 31 - 18) 14 BITS */
-/* INFO TYPE (BIT 17 - 14) 4 BITS */
-/* PAGE INDEX OF THE FIRST FIELD IN THE FRAGMENT (BIT 13 - 0) 14 BITS */
-/* DIRECTORY INDEX OF THE PAGE IN THE FRAGMENT 32 BITS */
-/* ADDRESS OF THE PREVIOUS ELEMENT OF THE FRAGMENT 64 BITS */
-/* ADDRESS OF THE PREVIOUS ELEMENT IN THE UNDO PAGES 64 BITS */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::writeUndoHeader(Signal* signal,
- Uint32 logicalPageId,
- UndoHeader::UndoHeaderType pageType)
-{
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- arrGuard(theadundoindex + 6, 8192);
-
- // Set the structpointer to point at the undo page at the right address.
- UndoHeader * const & undoHeaderPtr =
- (UndoHeader *) &undopageptr.p->undoword[theadundoindex];
-
- undoHeaderPtr->tableId = rootfragrecptr.p->mytabptr;
- undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0] >> 1;
- undoHeaderPtr->localFragId = fragrecptr.p->myfid;
- ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
- Uint32 Ttmp = cundoinfolength;
- Ttmp = (Ttmp << 4) + pageType;
- Ttmp = Ttmp << 14;
- undoHeaderPtr->variousInfo = Ttmp + cundoElemIndex;
- undoHeaderPtr->logicalPageId = logicalPageId;
- undoHeaderPtr->prevUndoAddressForThisFrag = fragrecptr.p->prevUndoposition;
- undoHeaderPtr->prevUndoAddress = cprevUndoaddress;
-}//Dbacc::writeUndoHeader()
-
-/* --------------------------------------------------------------------------------- */
-/* WRITE_UNDO_OP_INFO */
-/* FOR A LOCKED ELEMENT, OPERATION TYPE, UNDO OF ELEMENT HEADER AND THE LENGTH OF*/
-/* THE TUPLE KEY HAVE TO BE SAVED IN UNDO PAGES. IN THIS CASE AN UNDO ELEMENT */
-/* INCLUDES THE FLLOWING ITEMS. */
-/* OPERATION TYPE 32 BITS */
-/* HASH VALUE 32 BITS */
-/* LENGTH OF THE TUPLE = N 32 BITS */
-/* TUPLE KEYS N * 32 BITS */
-/* */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::writeUndoOpInfo(Signal* signal)
-{
- Page8Ptr locPageptr;
-
- arrGuard((tundoindex + 3), 8192);
- undopageptr.p->undoword[tundoindex] = operationRecPtr.p->operation;
- undopageptr.p->undoword[tundoindex + 1] = operationRecPtr.p->hashValue;
- undopageptr.p->undoword[tundoindex + 2] = operationRecPtr.p->tupkeylen;
- tundoindex = tundoindex + 3;
- // log localkey1
- locPageptr.i = operationRecPtr.p->elementPage;
- ptrCheckGuard(locPageptr, cpagesize, page8);
- Uint32 Tforward = operationRecPtr.p->elementIsforward;
- Uint32 TelemPtr = operationRecPtr.p->elementPointer;
- TelemPtr += Tforward; // ZELEM_HEAD_SIZE
- arrGuard(tundoindex+1, 8192);
- undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr];
- tundoindex++;
- cundoinfolength = ZOP_HEAD_INFO_LN + 1;
-}//Dbacc::writeUndoOpInfo()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF LOCAL CHECKPOINT MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* SYSTEM RESTART MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* SR_FRAGIDREQ REQUEST FOR RESTART OF A FRAGMENT */
-/* SENDER: LQH, LEVEL B */
-/* ENTER SR_FRAGIDREQ WITH */
-/* TUSERPTR, LQH CONNECTION PTR */
-/* TUSERBLOCKREF, LQH BLOCK REFERENCE */
-/* TCHECKPOINTID, THE CHECKPOINT NUMBER TO USE */
-/* (E.G. 1,2 OR 3) */
-/* TABPTR, TABLE ID = TABLE RECORD POINTER */
-/* TFID, ROOT FRAGMENT ID */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* SR_FRAGIDREQ REQUEST FOR LIST OF STOPED OPERATION */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execSR_FRAGIDREQ(Signal* signal)
-{
- jamEntry();
- tuserptr = signal->theData[0]; /* LQH CONNECTION PTR */
- tuserblockref = signal->theData[1]; /* LQH BLOCK REFERENCE */
- tcheckpointid = signal->theData[2]; /* THE CHECKPOINT NUMBER TO USE */
- /* (E.G. 1,2 OR 3) */
- tabptr.i = signal->theData[3];
- ptrCheckGuard(tabptr, ctablesize, tabrec);
- /* TABLE ID = TABLE RECORD POINTER */
- tfid = signal->theData[4]; /* ROOT FRAGMENT ID */
- tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
- seizeLcpConnectRec(signal);
- initLcpConnRec(signal);
-
- ndbrequire(getrootfragmentrec(signal, rootfragrecptr, tfid));
- rootfragrecptr.p->lcpPtr = lcpConnectptr.i;
- lcpConnectptr.p->rootrecptr = rootfragrecptr.i;
- lcpConnectptr.p->localCheckPid = tcheckpointid;
- for (Uint32 i = 0; i < 2; i++) {
- Page8Ptr zeroPagePtr;
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[i];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- seizeLcpPage(zeroPagePtr);
- fragrecptr.p->zeroPagePtr = zeroPagePtr.i;
- }//for
-
- /* ---------------------------OPEN THE DATA FILE WHICH BELONGS TO TFID AND TCHECK POINT ---- */
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- tfid = rootfragrecptr.p->fragmentid[0];
- tmp = 0;
- srOpenDataFileLoopLab(signal);
-
- return;
-}//Dbacc::execSR_FRAGIDREQ()
-
-void Dbacc::srOpenDataFileLoopLab(Signal* signal)
-{
- /* D6 AT FSOPENREQ. FILE TYPE = .DATA */
- tmp1 = 0x010003ff; /* VERSION OF FILENAME = 1 */
- tmp2 = 0x0; /* D7 DON'T CREATE, READ ONLY */
- ndbrequire(cfsFirstfreeconnect != RNIL);
- seizeFsConnectRec(signal);
-
- fragrecptr.p->fsConnPtr = fsConnectptr.i;
- fsConnectptr.p->fragrecPtr = fragrecptr.i;
- fsConnectptr.p->fsState = WAIT_OPEN_DATA_FILE_FOR_READ;
- fsConnectptr.p->activeFragId = tmp; /* LOCAL FRAG INDEX */
- /* ************************ */
- /* FSOPENREQ */
- /* ************************ */
- signal->theData[0] = cownBlockref;
- signal->theData[1] = fsConnectptr.i;
- signal->theData[2] = rootfragrecptr.p->mytabptr; /* TABLE IDENTITY */
- signal->theData[3] = tfid; /* FRAGMENT IDENTITY */
- signal->theData[4] = lcpConnectptr.p->localCheckPid; /* CHECKPOINT ID */
- signal->theData[5] = tmp1;
- signal->theData[6] = tmp2;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- return;
-}//Dbacc::srOpenDataFileLoopLab()
-
-void Dbacc::srFsOpenConfLab(Signal* signal)
-{
- fsConnectptr.p->fsState = WAIT_READ_PAGE_ZERO;
- /* ------------------------ READ ZERO PAGE ---------- */
- fragrecptr.i = fsConnectptr.p->fragrecPtr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = 0x0;
- /* FLAG = LIST MEM PAGES, LIST FILE PAGES */
- signal->theData[4] = ZPAGE8_BASE_ADD;
- signal->theData[5] = 1; /* NO OF PAGES */
- signal->theData[6] = fragrecptr.p->zeroPagePtr; /* ZERO PAGE */
- signal->theData[7] = 0; /* PAGE ZERO OF THE DATA FILE */
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
- return;
-}//Dbacc::srFsOpenConfLab()
-
-void Dbacc::srReadPageZeroLab(Signal* signal)
-{
- Page8Ptr srzPageptr;
-
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- fragrecptr.p->activeDataFilePage = 1;
- srzPageptr.i = fragrecptr.p->zeroPagePtr;
- ptrCheckGuard(srzPageptr, cpagesize, page8);
- /* --------------------------------------------------------------------------------- */
- // Check that the checksum of the zero page is ok.
- /* --------------------------------------------------------------------------------- */
- ccoPageptr.p = srzPageptr.p;
- checksumControl(signal, (Uint32)0);
- if (tresult > 0) {
- jam();
- return; // We will crash through a DEBUG_SIG
- }//if
-
- ndbrequire(srzPageptr.p->word32[ZPAGEZERO_FRAGID0] == rootfragrecptr.p->fragmentid[0]);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- if (fsConnectptr.p->activeFragId == 0) {
- jam();
- rootfragrecptr.p->fragmentid[1] = srzPageptr.p->word32[ZPAGEZERO_FRAGID1];
- /* ---------------------------OPEN THE DATA FILE FOR NEXT LOCAL FRAGMENT ----------- ---- */
- tfid = rootfragrecptr.p->fragmentid[1];
- tmp = 1; /* LOCAL FRAG INDEX */
- fragrecptr.i = rootfragrecptr.p->fragmentptr[1];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- srOpenDataFileLoopLab(signal);
- return;
- } else {
- jam();
- lcpConnectptr.p->lcpstate = LCP_ACTIVE;
- signal->theData[0] = lcpConnectptr.p->lcpUserptr;
- signal->theData[1] = lcpConnectptr.i;
- signal->theData[2] = 2; /* NO OF LOCAL FRAGMENTS */
- signal->theData[3] = srzPageptr.p->word32[ZPAGEZERO_FRAGID0];
- /* ROOTFRAGRECPTR:FRAGMENTID(0) */
- signal->theData[4] = srzPageptr.p->word32[ZPAGEZERO_FRAGID1];
- /* ROOTFRAGRECPTR:FRAGMENTID(1) */
- signal->theData[5] = RNIL;
- signal->theData[6] = RNIL;
- signal->theData[7] = rootfragrecptr.p->fragmentptr[0];
- signal->theData[8] = rootfragrecptr.p->fragmentptr[1];
- signal->theData[9] = srzPageptr.p->word32[ZPAGEZERO_HASH_CHECK];
- sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_SR_FRAGIDCONF, signal, 10, JBB);
- }//if
- return;
-}//Dbacc::srReadPageZeroLab()
-
void Dbacc::initFragAdd(Signal* signal,
- Uint32 rootFragIndex,
- Uint32 rootIndex,
FragmentrecPtr regFragPtr)
{
const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
@@ -7855,8 +5197,7 @@ void Dbacc::initFragAdd(Signal* signal,
}//if
regFragPtr.p->fragState = ACTIVEFRAG;
// NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
- regFragPtr.p->myfid = (req->fragId << 1) | rootFragIndex;
- regFragPtr.p->myroot = rootIndex;
+ 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 */
@@ -7868,7 +5209,7 @@ void Dbacc::initFragAdd(Signal* signal,
*
* Is later restored to 0 by LQH at end of REDO log execution
*/
- regFragPtr.p->expandFlag = (getNodeState().getSystemRestartInProgress()?1:0);
+ regFragPtr.p->expandFlag = 0;
regFragPtr.p->p = 0;
regFragPtr.p->maxp = (1 << req->kValue) - 1;
regFragPtr.p->minloadfactor = minLoadFactor;
@@ -7881,7 +5222,6 @@ void Dbacc::initFragAdd(Signal* signal,
regFragPtr.p->nodetype = (req->reqInfo >> 4) & 0x3;
regFragPtr.p->lastOverIndex = 0;
regFragPtr.p->dirsize = 1;
- regFragPtr.p->loadingFlag = ZFALSE;
regFragPtr.p->keyLength = req->keyLength;
ndbrequire(req->keyLength != 0);
regFragPtr.p->elementLength = ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen;
@@ -7889,194 +5229,32 @@ void Dbacc::initFragAdd(Signal* signal,
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->fsConnPtr = RNIL;
regFragPtr.p->firstOverflowRec = RNIL;
regFragPtr.p->lastOverflowRec = RNIL;
- regFragPtr.p->firstWaitInQueOp = RNIL;
- regFragPtr.p->lastWaitInQueOp = RNIL;
- regFragPtr.p->sentWaitInQueOp = RNIL;
regFragPtr.p->lockOwnersList = RNIL;
regFragPtr.p->firstFreeDirindexRec = RNIL;
- regFragPtr.p->zeroPagePtr = RNIL;
regFragPtr.p->activeDataPage = 0;
- regFragPtr.p->createLcp = ZFALSE;
- regFragPtr.p->stopQueOp = ZFALSE;
regFragPtr.p->hasCharAttr = ZFALSE;
regFragPtr.p->nextAllocPage = 0;
- regFragPtr.p->nrWaitWriteUndoExit = 0;
- regFragPtr.p->lastUndoIsStored = ZFALSE;
- regFragPtr.p->loadingFlag = ZFALSE;
regFragPtr.p->fragState = FREEFRAG;
- for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) {
- regFragPtr.p->datapages[i] = RNIL;
- }//for
- for (Uint32 j = 0; j < 4; j++) {
- regFragPtr.p->longKeyPageArray[j] = RNIL;
- }//for
}//Dbacc::initFragGeneral()
-void Dbacc::initFragSr(FragmentrecPtr regFragPtr, Page8Ptr regPagePtr)
-{
- regFragPtr.p->prevUndoposition = regPagePtr.p->word32[ZPAGEZERO_PREV_UNDOP];
- regFragPtr.p->noOfStoredOverPages = regPagePtr.p->word32[ZPAGEZERO_NO_OVER_PAGE];
- regFragPtr.p->noStoredPages = regPagePtr.p->word32[ZPAGEZERO_NO_PAGES];
- regFragPtr.p->dirsize = regPagePtr.p->word32[ZPAGEZERO_DIRSIZE];
- regFragPtr.p->expandCounter = regPagePtr.p->word32[ZPAGEZERO_EXPCOUNTER];
- regFragPtr.p->slack = regPagePtr.p->word32[ZPAGEZERO_SLACK];
- regFragPtr.p->hashcheckbit = regPagePtr.p->word32[ZPAGEZERO_HASHCHECKBIT];
- regFragPtr.p->k = regPagePtr.p->word32[ZPAGEZERO_K];
- regFragPtr.p->lhfragbits = regPagePtr.p->word32[ZPAGEZERO_LHFRAGBITS];
- regFragPtr.p->lhdirbits = regPagePtr.p->word32[ZPAGEZERO_LHDIRBITS];
- regFragPtr.p->localkeylen = regPagePtr.p->word32[ZPAGEZERO_LOCALKEYLEN];
- regFragPtr.p->maxp = regPagePtr.p->word32[ZPAGEZERO_MAXP];
- regFragPtr.p->maxloadfactor = regPagePtr.p->word32[ZPAGEZERO_MAXLOADFACTOR];
- regFragPtr.p->minloadfactor = regPagePtr.p->word32[ZPAGEZERO_MINLOADFACTOR];
- regFragPtr.p->myfid = regPagePtr.p->word32[ZPAGEZERO_MYFID];
- regFragPtr.p->lastOverIndex = regPagePtr.p->word32[ZPAGEZERO_LAST_OVER_INDEX];
- regFragPtr.p->nodetype = regPagePtr.p->word32[ZPAGEZERO_NODETYPE];
- regFragPtr.p->p = regPagePtr.p->word32[ZPAGEZERO_P];
- regFragPtr.p->elementLength = regPagePtr.p->word32[ZPAGEZERO_ELEMENT_LENGTH];
- regFragPtr.p->keyLength = regPagePtr.p->word32[ZPAGEZERO_KEY_LENGTH];
- regFragPtr.p->slackCheck = regPagePtr.p->word32[ZPAGEZERO_SLACK_CHECK];
-
- regFragPtr.p->loadingFlag = ZTRUE;
-
-}//Dbacc::initFragSr()
-
-void Dbacc::initFragPageZero(FragmentrecPtr regFragPtr, Page8Ptr regPagePtr)
-{
- //------------------------------------------------------------------
- // PREV_UNDOP, NEXT_UNDO_FILE, NO_OVER_PAGE, NO_PAGES
- // is set at end of copy phase
- //------------------------------------------------------------------
- regPagePtr.p->word32[ZPAGEZERO_DIRSIZE] = regFragPtr.p->dirsize;
- regPagePtr.p->word32[ZPAGEZERO_EXPCOUNTER] = regFragPtr.p->expandCounter;
- regPagePtr.p->word32[ZPAGEZERO_SLACK] = regFragPtr.p->slack;
- regPagePtr.p->word32[ZPAGEZERO_HASHCHECKBIT] = regFragPtr.p->hashcheckbit;
- regPagePtr.p->word32[ZPAGEZERO_K] = regFragPtr.p->k;
- regPagePtr.p->word32[ZPAGEZERO_LHFRAGBITS] = regFragPtr.p->lhfragbits;
- regPagePtr.p->word32[ZPAGEZERO_LHDIRBITS] = regFragPtr.p->lhdirbits;
- regPagePtr.p->word32[ZPAGEZERO_LOCALKEYLEN] = regFragPtr.p->localkeylen;
- regPagePtr.p->word32[ZPAGEZERO_MAXP] = regFragPtr.p->maxp;
- regPagePtr.p->word32[ZPAGEZERO_MAXLOADFACTOR] = regFragPtr.p->maxloadfactor;
- regPagePtr.p->word32[ZPAGEZERO_MINLOADFACTOR] = regFragPtr.p->minloadfactor;
- regPagePtr.p->word32[ZPAGEZERO_MYFID] = regFragPtr.p->myfid;
- regPagePtr.p->word32[ZPAGEZERO_LAST_OVER_INDEX] = regFragPtr.p->lastOverIndex;
- regPagePtr.p->word32[ZPAGEZERO_NODETYPE] = regFragPtr.p->nodetype;
- regPagePtr.p->word32[ZPAGEZERO_P] = regFragPtr.p->p;
- regPagePtr.p->word32[ZPAGEZERO_ELEMENT_LENGTH] = regFragPtr.p->elementLength;
- regPagePtr.p->word32[ZPAGEZERO_KEY_LENGTH] = regFragPtr.p->keyLength;
- regPagePtr.p->word32[ZPAGEZERO_SLACK_CHECK] = regFragPtr.p->slackCheck;
-}//Dbacc::initFragPageZero()
-
-void Dbacc::initRootFragPageZero(RootfragmentrecPtr rootPtr, Page8Ptr regPagePtr)
-{
- regPagePtr.p->word32[ZPAGEZERO_TABID] = rootPtr.p->mytabptr;
- regPagePtr.p->word32[ZPAGEZERO_FRAGID0] = rootPtr.p->fragmentid[0];
- regPagePtr.p->word32[ZPAGEZERO_FRAGID1] = rootPtr.p->fragmentid[1];
- regPagePtr.p->word32[ZPAGEZERO_HASH_CHECK] = rootPtr.p->roothashcheck;
- regPagePtr.p->word32[ZPAGEZERO_NO_OF_ELEMENTS] = rootPtr.p->noOfElements;
-}//Dbacc::initRootFragPageZero()
-
-void Dbacc::initRootFragSr(RootfragmentrecPtr rootPtr, Page8Ptr regPagePtr)
-{
- rootPtr.p->roothashcheck = regPagePtr.p->word32[ZPAGEZERO_HASH_CHECK];
- rootPtr.p->noOfElements = regPagePtr.p->word32[ZPAGEZERO_NO_OF_ELEMENTS];
-}//Dbacc::initRootFragSr()
-
-/* ******************--------------------------------------------------------------- */
-/* ACC_SRREQ SYSTEM RESTART OF A LOCAL CHECK POINT */
-/* SENDER: LQH, LEVEL B */
-/* ENTER ACC_SRREQ WITH */
-/* LCP_CONNECTPTR, OPERATION RECORD PTR */
-/* TMP2, LQH'S LOCAL FRAG CHECK VALUE */
-/* TFID, LOCAL FRAG ID */
-/* TMP1, LOCAL CHECKPOINT ID */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACC_SRREQ PERFORM A LOCAL CHECK POINT */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execACC_SRREQ(Signal* signal)
-{
- Page8Ptr asrPageidptr;
- jamEntry();
- lcpConnectptr.i = signal->theData[0];
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- Uint32 lqhPtr = signal->theData[1];
- Uint32 fragId = signal->theData[2];
- Uint32 lcpId = signal->theData[3];
- tresult = 0;
- ndbrequire(lcpConnectptr.p->lcpstate == LCP_ACTIVE);
- rootfragrecptr.i = lcpConnectptr.p->rootrecptr;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (rootfragrecptr.p->fragmentid[0] == fragId) {
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- } else {
- ndbrequire(rootfragrecptr.p->fragmentid[1] == fragId);
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[1];
- }//if
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- fragrecptr.p->lcpLqhPtr = lqhPtr;
- fragrecptr.p->localCheckpId = lcpId;
- asrPageidptr.i = fragrecptr.p->zeroPagePtr;
- ptrCheckGuard(asrPageidptr, cpagesize, page8);
- ndbrequire(asrPageidptr.p->word32[ZPAGEZERO_TABID] == rootfragrecptr.p->mytabptr);
- ndbrequire(asrPageidptr.p->word32[ZPAGEZERO_FRAGID0] == rootfragrecptr.p->fragmentid[0]);
- ndbrequire(asrPageidptr.p->word32[ZPAGEZERO_FRAGID1] == rootfragrecptr.p->fragmentid[1]);
- initRootFragSr(rootfragrecptr, asrPageidptr);
- initFragSr(fragrecptr, asrPageidptr);
- for (Uint32 i = 0; i < ZMAX_UNDO_VERSION; i++) {
- jam();
- if (csrVersList[i] != RNIL) {
- jam();
- srVersionPtr.i = csrVersList[i];
- ptrCheckGuard(srVersionPtr, csrVersionRecSize, srVersionRec);
- if (fragrecptr.p->localCheckpId == srVersionPtr.p->checkPointId) {
- jam();
- ndbrequire(srVersionPtr.p->checkPointId == asrPageidptr.p->word32[ZPAGEZERO_NEXT_UNDO_FILE]);
- /*--------------------------------------------------------------------------------*/
- /* SINCE -1 IS THE END OF LOG CODE WE MUST TREAT THIS CODE WITH CARE. WHEN */
- /* COMPARING IT IS LARGER THAN EVERYTHING ELSE BUT SHOULD BE TREATED AS THE */
- /* SMALLEST POSSIBLE VALUE, MEANING EMPTY. */
- /*--------------------------------------------------------------------------------*/
- if (fragrecptr.p->prevUndoposition != cminusOne) {
- if (srVersionPtr.p->prevAddress < fragrecptr.p->prevUndoposition) {
- jam();
- srVersionPtr.p->prevAddress = fragrecptr.p->prevUndoposition;
- } else if (srVersionPtr.p->prevAddress == cminusOne) {
- jam();
- srVersionPtr.p->prevAddress = fragrecptr.p->prevUndoposition;
- }//if
- }//if
- srAllocPage0011Lab(signal);
- return;
- }//if
- } else {
- jam();
- seizeSrVerRec(signal);
- srVersionPtr.p->checkPointId = fragrecptr.p->localCheckpId;
- srVersionPtr.p->prevAddress = fragrecptr.p->prevUndoposition;
- csrVersList[i] = srVersionPtr.i;
- srAllocPage0011Lab(signal);
- return;
- }//if
- }//for
- ndbrequire(false);
-}//Dbacc::execACC_SRREQ()
void
Dbacc::releaseLogicalPage(Fragmentrec * fragP, Uint32 logicalPageId){
@@ -8101,1021 +5279,6 @@ Dbacc::releaseLogicalPage(Fragmentrec * fragP, Uint32 logicalPageId){
dirArrPtr.p->pagep[lp2] = RNIL;
}
-void Dbacc::srAllocPage0011Lab(Signal* signal)
-{
- releaseLogicalPage(fragrecptr.p, 0);
-
-#if JONAS
- ndbrequire(cfirstfreeDirrange != RNIL);
- seizeDirrange(signal);
- fragrecptr.p->directory = newDirRangePtr.i;
- ndbrequire(cfirstfreeDirrange != RNIL);
- seizeDirrange(signal);
- fragrecptr.p->overflowdir = newDirRangePtr.i;
- seizeDirectory(signal);
- ndbrequire(tresult < ZLIMIT_OF_ERROR);
- newDirRangePtr.p->dirArray[0] = sdDirptr.i;
-#endif
-
- fragrecptr.p->nextAllocPage = 0;
- fragrecptr.p->fragState = SR_READ_PAGES;
- srReadPagesLab(signal);
- return;
-}//Dbacc::srAllocPage0011Lab()
-
-void Dbacc::srReadPagesLab(Signal* signal)
-{
- if (fragrecptr.p->nextAllocPage >= fragrecptr.p->noStoredPages) {
- /*--------------------------------------------------------------------------------*/
- /* WE HAVE NOW READ ALL NORMAL PAGES FROM THE FILE. */
- /*--------------------------------------------------------------------------------*/
- if (fragrecptr.p->nextAllocPage == fragrecptr.p->dirsize) {
- jam();
- /*--------------------------------------------------------------------------------*/
- /* WE HAVE NOW READ ALL NORMAL PAGES AND ALLOCATED ALL THE NEEDED PAGES. */
- /*--------------------------------------------------------------------------------*/
- fragrecptr.p->nextAllocPage = 0; /* THE NEXT OVER FLOW PAGE WHICH WILL BE READ */
- fragrecptr.p->fragState = SR_READ_OVER_PAGES;
- srReadOverPagesLab(signal);
- } else {
- ndbrequire(fragrecptr.p->nextAllocPage < fragrecptr.p->dirsize);
- jam();
- /*--------------------------------------------------------------------------------*/
- /* WE NEEDED TO ALLOCATE PAGES THAT WERE DEALLOCATED DURING THE LOCAL */
- /* CHECKPOINT. */
- /* ALLOCATE THE PAGE AND INITIALISE IT. THEN WE INSERT A REAL-TIME BREAK. */
- /*--------------------------------------------------------------------------------*/
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- tipPageId = fragrecptr.p->nextAllocPage;
- inpPageptr.i = spPageptr.i;
- ptrCheckGuard(inpPageptr, cpagesize, page8);
- initPage(signal);
- fragrecptr.p->noOfExpectedPages = 1;
- fragrecptr.p->datapages[0] = spPageptr.i;
- signal->theData[0] = ZSR_READ_PAGES_ALLOC;
- signal->theData[1] = fragrecptr.i;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
- return;
- }//if
- Uint32 limitLoop;
- if ((fragrecptr.p->noStoredPages - fragrecptr.p->nextAllocPage) < ZWRITEPAGESIZE) {
- jam();
- limitLoop = fragrecptr.p->noStoredPages - fragrecptr.p->nextAllocPage;
- } else {
- jam();
- limitLoop = ZWRITEPAGESIZE;
- }//if
- ndbrequire(limitLoop <= 8);
- for (Uint32 i = 0; i < limitLoop; i++) {
- jam();
- seizePage(signal);
- ndbrequireErr(tresult <= ZLIMIT_OF_ERROR, NDBD_EXIT_SR_OUT_OF_INDEXMEMORY);
- fragrecptr.p->datapages[i] = spPageptr.i;
- signal->theData[i + 6] = spPageptr.i;
- }//for
- signal->theData[limitLoop + 6] = fragrecptr.p->activeDataFilePage;
- fragrecptr.p->noOfExpectedPages = limitLoop;
- /* -----------------SEND READ PAGES SIGNAL TO THE FILE MANAGER --------- */
- fsConnectptr.i = fragrecptr.p->fsConnPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- fsConnectptr.p->fsState = WAIT_READ_DATA;
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = 2;
- /* FLAG = LIST MEM PAGES, RANGE OF FILE PAGES */
- signal->theData[4] = ZPAGE8_BASE_ADD;
- signal->theData[5] = fragrecptr.p->noOfExpectedPages;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA);
- return;
-}//Dbacc::srReadPagesLab()
-
-void Dbacc::storeDataPageInDirectoryLab(Signal* signal)
-{
- fragrecptr.p->activeDataFilePage += fragrecptr.p->noOfExpectedPages;
- srReadPagesAllocLab(signal);
- return;
-}//Dbacc::storeDataPageInDirectoryLab()
-
-void Dbacc::srReadPagesAllocLab(Signal* signal)
-{
- DirRangePtr srpDirRangePtr;
- DirectoryarrayPtr srpDirptr;
- DirectoryarrayPtr srpOverflowDirptr;
- Page8Ptr srpPageidptr;
-
- if (fragrecptr.p->fragState == SR_READ_PAGES) {
- jam();
- for (Uint32 i = 0; i < fragrecptr.p->noOfExpectedPages; i++) {
- jam();
- tmpP = fragrecptr.p->nextAllocPage;
- srpDirRangePtr.i = fragrecptr.p->directory;
- tmpP2 = tmpP >> 8;
- tmp = tmpP & 0xff;
- ptrCheckGuard(srpDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- if (srpDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- seizeDirectory(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- srpDirptr.i = sdDirptr.i;
- srpDirRangePtr.p->dirArray[tmpP2] = srpDirptr.i;
- } else {
- jam();
- srpDirptr.i = srpDirRangePtr.p->dirArray[tmpP2];
- }//if
- ptrCheckGuard(srpDirptr, cdirarraysize, directoryarray);
- arrGuard(i, 8);
- srpDirptr.p->pagep[tmp] = fragrecptr.p->datapages[i];
- srpPageidptr.i = fragrecptr.p->datapages[i];
- ptrCheckGuard(srpPageidptr, cpagesize, page8);
- ndbrequire(srpPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
- ndbrequire(((srpPageidptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == 0);
- ccoPageptr.p = srpPageidptr.p;
- checksumControl(signal, (Uint32)1);
- if (tresult > 0) {
- jam();
- return; // We will crash through a DEBUG_SIG
- }//if
- dbgWord32(srpPageidptr, ZPOS_OVERFLOWREC, RNIL);
- srpPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- fragrecptr.p->datapages[i] = RNIL;
- fragrecptr.p->nextAllocPage++;
- }//for
- srReadPagesLab(signal);
- return;
- } else {
- ndbrequire(fragrecptr.p->fragState == SR_READ_OVER_PAGES);
- for (Uint32 i = 0; i < fragrecptr.p->noOfExpectedPages; i++) {
- jam();
- arrGuard(i, 8);
- srpPageidptr.i = fragrecptr.p->datapages[i];
- ptrCheckGuard(srpPageidptr, cpagesize, page8);
- tmpP = srpPageidptr.p->word32[ZPOS_PAGE_ID]; /* DIR INDEX OF THE OVERFLOW PAGE */
- /*--------------------------------------------------------------------------------*/
- /* IT IS POSSIBLE THAT WE HAVE LOGICAL PAGES WHICH ARE NOT PART OF THE LOCAL*/
- /* CHECKPOINT. THUS WE USE THE LOGICAL PAGE ID FROM THE PAGE HERE. */
- /*--------------------------------------------------------------------------------*/
- srpDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(srpDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- if (srpDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- seizeDirectory(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- srpDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- }//if
- srpOverflowDirptr.i = srpDirRangePtr.p->dirArray[tmpP2];
- ndbrequire(((srpPageidptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != 0);
- ndbrequire(((srpPageidptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != 3);
- ptrCheckGuard(srpOverflowDirptr, cdirarraysize, directoryarray);
- ndbrequire(srpOverflowDirptr.p->pagep[tmpP] == RNIL);
- srpOverflowDirptr.p->pagep[tmpP] = srpPageidptr.i;
- ccoPageptr.p = srpPageidptr.p;
- checksumControl(signal, (Uint32)1);
- ndbrequire(tresult == 0);
- dbgWord32(srpPageidptr, ZPOS_OVERFLOWREC, RNIL);
- srpPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- fragrecptr.p->nextAllocPage++;
- }//for
- srReadOverPagesLab(signal);
- return;
- }//if
-}//Dbacc::srReadPagesAllocLab()
-
-void Dbacc::srReadOverPagesLab(Signal* signal)
-{
- if (fragrecptr.p->nextAllocPage >= fragrecptr.p->noOfStoredOverPages) {
- fragrecptr.p->nextAllocPage = 0;
- if (fragrecptr.p->prevUndoposition == cminusOne) {
- jam();
- /* ************************ */
- /* ACC_OVER_REC */
- /* ************************ */
- /*--------------------------------------------------------------------------------*/
- /* UPDATE FREE LIST OF OVERFLOW PAGES AS PART OF SYSTEM RESTART AFTER */
- /* READING PAGES AND EXECUTING THE UNDO LOG. */
- /*--------------------------------------------------------------------------------*/
- signal->theData[0] = fragrecptr.i;
- sendSignal(cownBlockref, GSN_ACC_OVER_REC, signal, 1, JBB);
- } else {
- jam();
- srCloseDataFileLab(signal);
- }//if
- return;
- }//if
- Uint32 limitLoop;
- if ((fragrecptr.p->noOfStoredOverPages - fragrecptr.p->nextAllocPage) < ZWRITEPAGESIZE) {
- jam();
- limitLoop = fragrecptr.p->noOfStoredOverPages - fragrecptr.p->nextAllocPage;
- } else {
- jam();
- limitLoop = ZWRITEPAGESIZE;
- }//if
- ndbrequire(limitLoop <= 8);
- for (Uint32 i = 0; i < limitLoop; i++) {
- jam();
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- fragrecptr.p->datapages[i] = spPageptr.i;
- signal->theData[i + 6] = spPageptr.i;
- }//for
- fragrecptr.p->noOfExpectedPages = limitLoop;
- signal->theData[limitLoop + 6] = fragrecptr.p->activeDataFilePage;
- /* -----------------SEND READ PAGES SIGNAL TO THE FILE MANAGER --------- */
- fsConnectptr.i = fragrecptr.p->fsConnPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- fsConnectptr.p->fsState = WAIT_READ_DATA;
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = 2;
- signal->theData[4] = ZPAGE8_BASE_ADD;
- signal->theData[5] = fragrecptr.p->noOfExpectedPages;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA);
- return;
-}//Dbacc::srReadOverPagesLab()
-
-void Dbacc::srCloseDataFileLab(Signal* signal)
-{
- fsConnectptr.i = fragrecptr.p->fsConnPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- fsConnectptr.p->fsState = SR_CLOSE_DATA;
- /* ************************ */
- /* FSCLOSEREQ */
- /* ************************ */
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = 0;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- return;
-}//Dbacc::srCloseDataFileLab()
-
-/* ************************ */
-/* ACC_SRCONF */
-/* ************************ */
-void Dbacc::sendaccSrconfLab(Signal* signal)
-{
- fragrecptr.i = fsConnectptr.p->fragrecPtr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- releaseFsConnRec(signal);
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- lcpConnectptr.i = rootfragrecptr.p->lcpPtr;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- fragrecptr.p->fragState = ACTIVEFRAG;
- fragrecptr.p->fsConnPtr = RNIL;
- for (Uint32 i = 0; i < ZWRITEPAGESIZE; i++) {
- fragrecptr.p->datapages[i] = RNIL;
- }//for
- rlpPageptr.i = fragrecptr.p->zeroPagePtr;
- ptrCheckGuard(rlpPageptr, cpagesize, page8);
- releaseLcpPage(signal);
- fragrecptr.p->zeroPagePtr = RNIL;
- signal->theData[0] = fragrecptr.p->lcpLqhPtr;
- sendSignal(lcpConnectptr.p->lcpUserblockref, GSN_ACC_SRCONF, signal, 1, JBB);
- lcpConnectptr.p->noOfLcpConf++;
- if (lcpConnectptr.p->noOfLcpConf == 2) {
- jam();
- releaseLcpConnectRec(signal);
- rootfragrecptr.p->lcpPtr = RNIL;
- rootfragrecptr.p->rootState = ACTIVEROOT;
- }//if
- return;
-}//Dbacc::sendaccSrconfLab()
-
-/* --------------------------------------------------------------------------------- */
-/* CHECKSUM_CONTROL */
-/* INPUT: CCO_PAGEPTR */
-/* OUTPUT: TRESULT */
-/* */
-/* CHECK THAT CHECKSUM IN PAGE IS CORRECT TO ENSURE THAT NO ONE HAS CORRUPTED */
-/* THE PAGE INFORMATION. WHEN CALCULATING THE CHECKSUM WE REMOVE THE CHECKSUM */
-/* ITSELF FROM THE CHECKSUM BY XOR'ING THE CHECKSUM TWICE. WHEN CALCULATING */
-/* THE CHECKSUM THE CHECKSUM WORD IS ZERO WHICH MEANS NO CHANGE FROM XOR'ING. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::checksumControl(Signal* signal, Uint32 checkPage)
-{
- Uint32 Tchs;
- Uint32 tccoIndex;
- Uint32 Ti;
- Uint32 Tmp1;
- Uint32 Tmp2;
- Uint32 Tmp3;
- Uint32 Tmp4;
- Uint32 Tlimit;
-
- Tchs = 0;
- for (Ti = 0; Ti < 32 ; Ti++) {
- Tlimit = 16 + (Ti << 6);
- for (tccoIndex = (Ti << 6); tccoIndex < Tlimit; tccoIndex ++) {
- Tmp1 = ccoPageptr.p->word32[tccoIndex];
- Tmp2 = ccoPageptr.p->word32[tccoIndex + 16];
- Tmp3 = ccoPageptr.p->word32[tccoIndex + 32];
- Tmp4 = ccoPageptr.p->word32[tccoIndex + 48];
-
- Tchs = Tchs ^ Tmp1;
- Tchs = Tchs ^ Tmp2;
- Tchs = Tchs ^ Tmp3;
- Tchs = Tchs ^ Tmp4;
- }//for
- }//for
- if (Tchs == 0) {
- tresult = 0;
- if (checkPage != 0) {
- jam();
- lcnCopyPageptr.p = ccoPageptr.p;
- srCheckPage(signal);
- }//if
- } else {
- tresult = 1;
- }//if
- if (tresult != 0) {
- jam();
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- signal->theData[0] = RNIL;
- signal->theData[1] = rootfragrecptr.p->mytabptr;
- signal->theData[2] = fragrecptr.p->myfid;
- signal->theData[3] = ccoPageptr.p->word32[ZPOS_PAGE_ID];
- signal->theData[4] = tlupElemIndex;
- signal->theData[5] = ccoPageptr.p->word32[ZPOS_PAGE_TYPE];
- signal->theData[6] = tresult;
- sendSignal(cownBlockref, GSN_DEBUG_SIG, signal, 7, JBA);
- }//if
-}//Dbacc::checksumControl()
-
-/* ******************--------------------------------------------------------------- */
-/* START_RECREQ REQUEST TO START UNDO PROCESS */
-/* SENDER: LQH, LEVEL B */
-/* ENTER START_RECREQ WITH */
-/* CLQH_PTR, LQH CONNECTION PTR */
-/* CLQH_BLOCK_REF, LQH BLOCK REFERENCE */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* START_RECREQ REQUEST TO START UNDO PROCESS */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
-void Dbacc::execSTART_RECREQ(Signal* signal)
-{
- jamEntry();
- clqhPtr = signal->theData[0]; /* LQH CONNECTION PTR */
- clqhBlockRef = signal->theData[1]; /* LQH BLOCK REFERENCE */
- tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
- for (int i = 0; i < UndoHeader::ZNO_UNDORECORD_TYPES; i++)
- cSrUndoRecords[i] = 0;
- startUndoLab(signal);
- return;
-}//Dbacc::execSTART_RECREQ()
-
-void Dbacc::startUndoLab(Signal* signal)
-{
- cundoLogActive = ZTRUE;
- /* ----- OPEN UNDO FILES --------- */
- for (tmp = 0; tmp <= ZMAX_UNDO_VERSION - 1; tmp++) {
- jam();
- if (csrVersList[tmp] != RNIL) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* SELECT THE NEXT SYSTEM RESTART RECORD WHICH CONTAINS AN UNDO LOG */
- /* THAT NEEDS TO BE EXECUTED AND SET UP THE DATA TO EXECUTE IT. */
- /*---------------------------------------------------------------------------*/
- srVersionPtr.i = csrVersList[tmp];
- csrVersList[tmp] = RNIL;
- ptrCheckGuard(srVersionPtr, csrVersionRecSize, srVersionRec);
- cactiveUndoFilePage = srVersionPtr.p->prevAddress >> 13;
- cprevUndoaddress = srVersionPtr.p->prevAddress;
- cactiveCheckpId = srVersionPtr.p->checkPointId;
-
- releaseSrRec(signal);
- startActiveUndo(signal);
- return;
- }//if
- }//for
-
- // Send report of how many undo log records where executed
- signal->theData[0] = NDB_LE_UNDORecordsExecuted;
- signal->theData[1] = DBACC; // From block
- signal->theData[2] = 0; // Total records executed
- for (int i = 0; i < 10; i++){
- if (i < UndoHeader::ZNO_UNDORECORD_TYPES){
- signal->theData[i+3] = cSrUndoRecords[i];
- signal->theData[2] += cSrUndoRecords[i];
- }else{
- signal->theData[i+3] = 0;
- }
- }
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 12, JBB);
-
- /* ******************************< */
- /* START_RECCONF */
- /* ******************************< */
- /*---------------------------------------------------------------------------*/
- /* REPORT COMPLETION OF UNDO LOG EXECUTION. */
- /*---------------------------------------------------------------------------*/
- cundoLogActive = ZFALSE;
- signal->theData[0] = clqhPtr;
- sendSignal(clqhBlockRef, GSN_START_RECCONF, signal, 1, JBB);
- /* LQH CONNECTION PTR */
- return;
-}//Dbacc::startUndoLab()
-
-/*---------------------------------------------------------------------------*/
-/* START THE UNDO OF AN UNDO LOG FILE BY OPENING THE UNDO LOG FILE. */
-/*---------------------------------------------------------------------------*/
-void Dbacc::startActiveUndo(Signal* signal)
-{
- if (cprevUndoaddress == cminusOne) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* THERE WAS NO UNDO LOG INFORMATION IN THIS LOG FILE. WE GET THE NEXT */
- /* OR REPORT COMPLETION. */
- /*---------------------------------------------------------------------------*/
- signal->theData[0] = ZSTART_UNDO;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 1, JBB);
- } else {
- jam();
- /*---------------------------------------------------------------------------*/
- /* OPEN THE LOG FILE PERTAINING TO THIS UNDO LOG. */
- /*---------------------------------------------------------------------------*/
- if (cfsFirstfreeconnect == RNIL) {
- jam();
- sendSystemerror(signal, __LINE__);
- }//if
- seizeFsConnectRec(signal);
- cactiveSrFsPtr = fsConnectptr.i;
- fsConnectptr.p->fsState = OPEN_UNDO_FILE_SR;
- fsConnectptr.p->fsPart = 0;
- tmp1 = 1; /* FILE VERSION ? */
- tmp1 = (tmp1 << 8) + ZLOCALLOGFILE; /* .LOCLOG = 2 */
- tmp1 = (tmp1 << 8) + 4; /* ROOT DIRECTORY = D4 */
- tmp1 = (tmp1 << 8) + fsConnectptr.p->fsPart; /* P2 */
- tmp2 = 0x0; /* D7 DON'T CREATE , READ ONLY */
- /* DON'T TRUNCATE TO ZERO */
- /* ---FILE NAME "D4"/"DBACC"/LCP_CONNECTPTR:LOCAL_CHECK_PID/FS_CONNECTPTR:FS_PART".LOCLOG-- */
- /* ************************ */
- /* FSOPENREQ */
- /* ************************ */
- signal->theData[0] = cownBlockref;
- signal->theData[1] = fsConnectptr.i;
- signal->theData[2] = cminusOne; /* #FFFFFFFF */
- signal->theData[3] = cminusOne; /* #FFFFFFFF */
- signal->theData[4] = cactiveCheckpId; /* CHECKPOINT VERSION */
- signal->theData[5] = tmp1;
- signal->theData[6] = tmp2;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- }//if
-}//Dbacc::startActiveUndo()
-
-/* ------- READ A GROUP OF UNDO PAGES --------------- */
-void Dbacc::srStartUndoLab(Signal* signal)
-{
- /*---------------------------------------------------------------------------*/
- /* ALL LOG FILES HAVE BEEN OPENED. WE CAN NOW READ DATA FROM THE LAST */
- /* PAGE IN THE LAST LOG FILE AND BACKWARDS UNTIL WE REACH THE VERY */
- /* FIRST UNDO LOG RECORD. */
- /*---------------------------------------------------------------------------*/
- if (cactiveUndoFilePage >= ZWRITE_UNDOPAGESIZE) {
- jam();
- tmp1 = ZWRITE_UNDOPAGESIZE; /* NO OF READ UNDO PAGES */
- cactiveSrUndoPage = ZWRITE_UNDOPAGESIZE - 1; /* LAST PAGE */
- } else {
- jam();
- tmp1 = cactiveUndoFilePage + 1; /* NO OF READ UNDO PAGES */
- cactiveSrUndoPage = cactiveUndoFilePage;
- }//if
- fsConnectptr.i = cactiveSrFsPtr;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- signal->theData[0] = fsConnectptr.p->fsPtr;
- signal->theData[1] = cownBlockref;
- signal->theData[2] = fsConnectptr.i;
- signal->theData[3] = 0;
- /* FLAG = LIST MEM PAGES, LIST FILE PAGES */
- signal->theData[4] = ZUNDOPAGE_BASE_ADD;
- signal->theData[5] = tmp1;
- signal->theData[6] = 0;
- signal->theData[7] = (cactiveUndoFilePage - tmp1) + 1;
- signal->theData[8] = 1;
- signal->theData[9] = cactiveUndoFilePage;
-
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 10, JBA);
- if (tmp1 > cactiveUndoFilePage) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* THIS IS THE LAST READ IN THIS LOG FILE. WE SET THE ACTIVE FILE */
- /* POINTER. IF IT IS THE FIRST WE SHOULD NEVER ATTEMPT ANY MORE READS */
- /* SINCE WE SHOULD ENCOUNTER A FIRST LOG RECORD WITH PREVIOUS PAGE ID */
- /* EQUAL TO RNIL. */
- /*---------------------------------------------------------------------------*/
- cactiveSrFsPtr = RNIL;
- fsConnectptr.p->fsState = READ_UNDO_PAGE_AND_CLOSE;
- } else {
- jam();
- /*---------------------------------------------------------------------------*/
- /* WE STILL HAVE MORE INFORMATION IN THIS LOG FILE. WE ONLY MOVE BACK */
- /* THE FILE PAGE. */
- /*---------------------------------------------------------------------------*/
- cactiveUndoFilePage = cactiveUndoFilePage - tmp1;
- fsConnectptr.p->fsState = READ_UNDO_PAGE;
- }//if
- return;
-}//Dbacc::srStartUndoLab()
-
-/* ------- DO UNDO ---------------------------*/
-/* ******************--------------------------------------------------------------- */
-/* NEXTOPERATION ORD FOR EXECUTION OF NEXT OP */
-/* ******************------------------------------+ */
-/* SENDER: ACC, LEVEL B */
-void Dbacc::execNEXTOPERATION(Signal* signal)
-{
- jamEntry();
- tresult = 0;
- srDoUndoLab(signal);
- return;
-}//Dbacc::execNEXTOPERATION()
-
-void Dbacc::srDoUndoLab(Signal* signal)
-{
- DirRangePtr souDirRangePtr;
- DirectoryarrayPtr souDirptr;
- Page8Ptr souPageidptr;
- Uint32 tundoPageindex;
- UndoHeader *undoHeaderPtr;
- Uint32 tmpindex;
-
- jam();
- undopageptr.i = cactiveSrUndoPage;
- ptrCheckGuard(undopageptr, cundopagesize, undopage);
- /*---------------------------------------------------------------------------*/
- /* LAYOUT OF AN UNDO LOG RECORD: */
- /* ***************************** */
- /* */
- /* |----------------------------------------------------| */
- /* | TABLE ID | */
- /* |----------------------------------------------------| */
- /* | ROOT FRAGMENT ID | */
- /* |----------------------------------------------------| */
- /* | LOCAL FRAGMENT ID | */
- /* |----------------------------------------------------| */
- /* | UNDO INFO LEN 14 b | TYPE 4 b | PAGE INDEX 14 b | */
- /* |----------------------------------------------------| */
- /* | INDEX INTO PAGE DIRECTORY (LOGICAL PAGE ID) | */
- /* |----------------------------------------------------| */
- /* | PREVIOUS UNDO LOG RECORD FOR THE FRAGMENT | */
- /* |----------------------------------------------------| */
- /* | PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS | */
- /* |----------------------------------------------------| */
- /* | TYPE SPECIFIC PART | */
- /* |----------------------------------------------------| */
- /*---------------------------------------------------------------------------*/
- /*---------------------------------------------------------------------------*/
- /* SET THE PAGE POINTER. WE ONLY WORK WITH TWO PAGES IN THIS RESTART */
- /* ACTIVITY. GET THE PAGE POINTER AND THE PAGE INDEX TO READ FROM. */
- /*---------------------------------------------------------------------------*/
- tundoindex = cprevUndoaddress & ZUNDOPAGEINDEX_MASK; //0x1fff, 13 bits.
- undoHeaderPtr = (UndoHeader *) &undopageptr.p->undoword[tundoindex];
- tundoindex = tundoindex + ZUNDOHEADSIZE;
-
- /*------------------------------------------------------------------------*/
- /* READ TABLE ID AND ROOT FRAGMENT ID AND USE THIS TO GET ROOT RECORD. */
- /*------------------------------------------------------------------------*/
- arrGuard((tundoindex + 6), 8192);
-
- // TABLE ID
- tabptr.i = undoHeaderPtr->tableId;
- ptrCheckGuard(tabptr, ctablesize, tabrec);
-
- // ROOT FRAGMENT ID
- tfid = undoHeaderPtr->rootFragId;
- ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
- if (!getrootfragmentrec(signal, rootfragrecptr, tfid)) {
- jam();
- /*---------------------------------------------------------------------*/
- /* THE ROOT RECORD WAS NOT FOUND. OBVIOUSLY WE ARE NOT RESTARTING THIS */
- /* FRAGMENT. WE THUS IGNORE THIS LOG RECORD AND PROCEED WITH THE NEXT. */
- /*---------------------------------------------------------------------*/
- creadyUndoaddress = cprevUndoaddress;
- // PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS
- cprevUndoaddress = undoHeaderPtr->prevUndoAddress;
- undoNext2Lab(signal);
-#ifdef VM_TRACE
- ndbout_c("ignoring root fid %d", (int)tfid);
-#endif
- return;
- }//if
- /*-----------------------------------------------------------------------*/
- /* READ THE LOCAL FRAGMENT ID AND VERIFY THAT IT IS CORRECT. */
- /*-----------------------------------------------------------------------*/
- if (rootfragrecptr.p->fragmentid[0] == undoHeaderPtr->localFragId) {
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- } else {
- if (rootfragrecptr.p->fragmentid[1] == undoHeaderPtr->localFragId) {
- jam();
- fragrecptr.i = rootfragrecptr.p->fragmentptr[1];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- } else {
- jam();
- progError(__LINE__, NDBD_EXIT_SR_UNDOLOG,
- "Invalid local fragment id in undo log");
- return;
- }//if
- }//if
- /*------------------------------------------------------------------------*/
- /* READ UNDO INFO LENGTH, TYPE OF LOG RECORD AND PAGE INDEX WHERE TO */
- /* APPLY THIS LOG RECORD. ALSO STEP INDEX TO PREPARE READ OF LOGICAL */
- /* PAGE ID. SET TMPINDEX TO INDEX THE FIRST WORD IN THE TYPE SPECIFIC */
- /* PART. */
- /*------------------------------------------------------------------------*/
- // UNDO INFO LENGTH 14 b | TYPE 4 b | PAGE INDEX 14 b
- const Uint32 tmp1 = undoHeaderPtr->variousInfo;
- cundoinfolength = tmp1 >> 18;
- const Uint32 tpageType = (tmp1 >> 14) & 0xf;
- tundoPageindex = tmp1 & 0x3fff;
-
- // INDEX INTO PAGE DIRECTORY (LOGICAL PAGE ID)
- tmpP = undoHeaderPtr->logicalPageId ;
- tmpindex = tundoindex;
- arrGuard((tmpindex + cundoinfolength - 1), 8192);
- if (fragrecptr.p->localCheckpId != cactiveCheckpId) {
- jam();
- /*-----------------------------------------------------------------------*/
- /* THE FRAGMENT DID EXIST BUT IS NOT AFFECTED BY THIS UNDO LOG */
- /* EXECUTION. EITHER IT BELONGS TO ANOTHER OR IT IS CREATED AND ONLY IN */
- /* NEED OF EXECUTION OF REDO LOG RECORDS FROM LQH. */
- /*-----------------------------------------------------------------------*/
- creadyUndoaddress = cprevUndoaddress;
- // PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS
- cprevUndoaddress = undoHeaderPtr->prevUndoAddress;
-
- undoNext2Lab(signal);
- return;
- }//if
- /*-----------------------------------------------------------------------*/
- /* VERIFY CONSISTENCY OF UNDO LOG RECORDS. */
- /*-----------------------------------------------------------------------*/
- ndbrequire(fragrecptr.p->prevUndoposition == cprevUndoaddress);
- cSrUndoRecords[tpageType]++;
- switch(tpageType){
-
- case UndoHeader::ZPAGE_INFO:{
- jam();
- /*----------------------------------------------------------------------*/
- /* WE HAVE TO UNDO UPDATES IN A NORMAL PAGE. GET THE PAGE POINTER BY */
- /* USING THE LOGICAL PAGE ID. THEN RESET THE OLD VALUE IN THE PAGE BY */
- /* USING THE OLD DATA WHICH IS STORED IN THIS UNDO LOG RECORD. */
- /*----------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->directory;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- souPageidptr.i = souDirptr.p->pagep[tmpP];
- ptrCheckGuard(souPageidptr, cpagesize, page8);
- Uint32 loopLimit = tundoPageindex + cundoinfolength;
- ndbrequire(loopLimit <= 2048);
- for (Uint32 tmp = tundoPageindex; tmp < loopLimit; tmp++) {
- dbgWord32(souPageidptr, tmp, undopageptr.p->undoword[tmpindex]);
- souPageidptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
- break;
- }
-
- case UndoHeader::ZOVER_PAGE_INFO:{
- jam();
- /*----------------------------------------------------------------------*/
- /* WE HAVE TO UNDO UPDATES IN AN OVERFLOW PAGE. GET THE PAGE POINTER BY*/
- /* USING THE LOGICAL PAGE ID. THEN RESET THE OLD VALUE IN THE PAGE BY */
- /* USING THE OLD DATA WHICH IS STORED IN THIS UNDO LOG RECORD. */
- /*----------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- souPageidptr.i = souDirptr.p->pagep[tmpP];
- ptrCheckGuard(souPageidptr, cpagesize, page8);
- Uint32 loopLimit = tundoPageindex + cundoinfolength;
- ndbrequire(loopLimit <= 2048);
- for (Uint32 tmp = tundoPageindex; tmp < loopLimit; tmp++) {
- dbgWord32(souPageidptr, tmp, undopageptr.p->undoword[tmpindex]);
- souPageidptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
- break;
- }
-
- case UndoHeader::ZOP_INFO: {
- jam();
- /*---------------------------------------------------------------------*/
- /* AN OPERATION WAS ACTIVE WHEN LOCAL CHECKPOINT WAS EXECUTED. WE NEED */
- /* TO RESET THE LOCKS IT HAS SET. IF THE OPERATION WAS AN INSERT OR */
- /* THE ELEMENT WAS MARKED AS DISSAPEARED IT WILL ALSO BE REMOVED */
- /* FROM THE PAGE */
- /* */
- /* BEGIN BY SEARCHING AFTER THE ELEMENT, WHEN FOUND UNDO THE */
- /* CHANGES ON THE ELEMENT HEADER. IF IT WAS AN INSERT OPERATION OR */
- /* MARKED AS DISSAPEARED PROCEED BY REMOVING THE ELEMENT. */
- /*---------------------------------------------------------------------*/
- seizeOpRec(signal);
- // Initialise the opRec
- operationRecPtr.p->transId1 = 0;
- operationRecPtr.p->transId2 = RNIL;
- operationRecPtr.p->transactionstate = ACTIVE;
- operationRecPtr.p->commitDeleteCheckFlag = ZFALSE;
- operationRecPtr.p->lockMode = 0;
- operationRecPtr.p->dirtyRead = 0;
- operationRecPtr.p->nodeType = 0;
- operationRecPtr.p->fid = fragrecptr.p->myfid;
- operationRecPtr.p->nextParallelQue = RNIL;
- operationRecPtr.p->prevParallelQue = RNIL;
- operationRecPtr.p->nextQueOp = RNIL;
- operationRecPtr.p->prevQueOp = RNIL;
- operationRecPtr.p->nextSerialQue = RNIL;
- operationRecPtr.p->prevSerialQue = RNIL;
- operationRecPtr.p->elementPage = RNIL;
- operationRecPtr.p->keyinfoPage = RNIL;
- operationRecPtr.p->insertIsDone = ZFALSE;
- operationRecPtr.p->lockOwner = ZFALSE;
- operationRecPtr.p->elementIsDisappeared = ZFALSE;
- operationRecPtr.p->insertDeleteLen = fragrecptr.p->elementLength;
- operationRecPtr.p->longPagePtr = RNIL;
- operationRecPtr.p->longKeyPageIndex = RNIL;
- operationRecPtr.p->scanRecPtr = RNIL;
- operationRecPtr.p->isAccLockReq = ZFALSE;
- operationRecPtr.p->isUndoLogReq = ZTRUE;
-
- // Read operation values from undo page
- operationRecPtr.p->operation = undopageptr.p->undoword[tmpindex];
- tmpindex++;
- operationRecPtr.p->hashValue = undopageptr.p->undoword[tmpindex];
- tmpindex++;
- const Uint32 tkeylen = undopageptr.p->undoword[tmpindex];
- tmpindex++;
- operationRecPtr.p->tupkeylen = tkeylen;
- operationRecPtr.p->xfrmtupkeylen = 0; // not used
- operationRecPtr.p->fragptr = fragrecptr.i;
-
- ndbrequire(fragrecptr.p->keyLength != 0 &&
- fragrecptr.p->keyLength == tkeylen);
-
- // Read localkey1 from undo page
- signal->theData[7 + 0] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- arrGuard((tmpindex - 1), 8192);
- getElement(signal);
- if (tgeResult != ZTRUE) {
- jam();
- signal->theData[0] = RNIL;
- signal->theData[1] = tabptr.i;
- signal->theData[2] = cactiveCheckpId;
- signal->theData[3] = cprevUndoaddress;
- signal->theData[4] = operationRecPtr.p->operation;
- signal->theData[5] = operationRecPtr.p->hashValue;
- signal->theData[6] = operationRecPtr.p->tupkeylen;
- sendSignal(cownBlockref, GSN_DEBUG_SIG, signal, 11, JBA);
- return;
- }//if
-
- operationRecPtr.p->elementPage = gePageptr.i;
- operationRecPtr.p->elementContainer = tgeContainerptr;
- operationRecPtr.p->elementPointer = tgeElementptr;
- operationRecPtr.p->elementIsforward = tgeForward;
-
- commitdelete(signal, true);
- releaseOpRec(signal);
- break;
- }
-
- default:
- jam();
- progError(__LINE__, NDBD_EXIT_SR_UNDOLOG, "Invalid pagetype in undo log");
- break;
-
- }//switch(tpageType)
-
- /*----------------------------------------------------------------------*/
- /* READ THE PAGE ID AND THE PAGE INDEX OF THE PREVIOUS UNDO LOG RECORD */
- /* FOR THIS FRAGMENT. */
- /*----------------------------------------------------------------------*/
- fragrecptr.p->prevUndoposition = undoHeaderPtr->prevUndoAddressForThisFrag;
- /*----------------------------------------------------------------------*/
- /* READ THE PAGE ID AND THE PAGE INDEX OF THE PREVIOUS UNDO LOG RECORD */
- /* FOR THIS UNDO LOG. */
- /*----------------------------------------------------------------------*/
- creadyUndoaddress = cprevUndoaddress;
- cprevUndoaddress = undoHeaderPtr->prevUndoAddress;
-
- if (fragrecptr.p->prevUndoposition == cminusOne) {
- jam();
- /*---------------------------------------------------------------------*/
- /* WE HAVE NOW EXECUTED ALL UNDO LOG RECORDS FOR THIS FRAGMENT. WE */
- /* NOW NEED TO UPDATE THE FREE LIST OF OVERFLOW PAGES. */
- /*---------------------------------------------------------------------*/
- ndbrequire(fragrecptr.p->nextAllocPage == 0);
-
- signal->theData[0] = fragrecptr.i;
- sendSignal(cownBlockref, GSN_ACC_OVER_REC, signal, 1, JBB);
- return;
- }//if
- undoNext2Lab(signal);
- return;
-}//Dbacc::srDoUndoLab()
-
-void Dbacc::undoNext2Lab(Signal* signal)
-{
- /*---------------------------------------------------------------------------*/
- /* EXECUTE NEXT UNDO LOG RECORD. */
- /*---------------------------------------------------------------------------*/
- if (cprevUndoaddress == cminusOne) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* WE HAVE EXECUTED THIS UNDO LOG TO COMPLETION. IT IS NOW TIME TO TAKE*/
- /* OF THE NEXT UNDO LOG OR REPORT COMPLETION OF UNDO LOG EXECUTION. */
- /*---------------------------------------------------------------------------*/
- signal->theData[0] = ZSTART_UNDO;
- sendSignal(cownBlockref, GSN_CONTINUEB, signal, 1, JBB);
- return;
- }//if
- if ((creadyUndoaddress >> 13) != (cprevUndoaddress >> 13)) {
- /*---------------------------------------------------------------------------*/
- /* WE ARE CHANGING PAGE. */
- /*---------------------------------------------------------------------------*/
- if (cactiveSrUndoPage == 0) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* WE HAVE READ AND EXECUTED ALL UNDO LOG INFORMATION IN THE CURRENTLY */
- /* READ PAGES. WE STILL HAVE MORE INFORMATION TO READ FROM FILE SINCE */
- /* WE HAVEN'T FOUND THE FIRST LOG RECORD IN THE LOG FILE YET. */
- /*---------------------------------------------------------------------------*/
- srStartUndoLab(signal);
- return;
- } else {
- jam();
- /*---------------------------------------------------------------------------*/
- /* WE HAVE ANOTHER PAGE READ THAT WE NEED TO EXECUTE. */
- /*---------------------------------------------------------------------------*/
- cactiveSrUndoPage = cactiveSrUndoPage - 1;
- }//if
- }//if
- /*---------------------------------------------------------------------------*/
- /* REAL-TIME BREAK */
- /*---------------------------------------------------------------------------*/
- /* ******************************< */
- /* NEXTOPERATION */
- /* ******************************< */
- sendSignal(cownBlockref, GSN_NEXTOPERATION, signal, 1, JBB);
- return;
-}//Dbacc::undoNext2Lab()
-
-/*-----------------------------------------------------------------------------------*/
-/* AFTER COMPLETING THE READING OF DATA PAGES FROM DISK AND EXECUTING THE UNDO */
-/* LOG WE ARE READY TO UPDATE THE FREE LIST OF OVERFLOW PAGES. THIS LIST MUST */
-/* BE BUILT AGAIN SINCE IT IS NOT CHECKPOINTED. WHEN THE PAGES ARE ALLOCATED */
-/* THEY ARE NOT PART OF ANY LIST. PAGES CAN EITHER BE PUT IN FREE LIST, NOT */
-/* IN FREE LIST OR BE PUT INTO LIST OF LONG KEY PAGES. */
-/*-----------------------------------------------------------------------------------*/
-void Dbacc::execACC_OVER_REC(Signal* signal)
-{
- DirRangePtr pnoDirRangePtr;
- DirectoryarrayPtr pnoOverflowDirptr;
- Page8Ptr pnoPageidptr;
- Uint32 tpnoPageType;
- Uint32 toverPageCheck;
-
- jamEntry();
- fragrecptr.i = signal->theData[0];
- toverPageCheck = 0;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- ndbrequire((fragrecptr.p->nextAllocPage != 0) ||
- (fragrecptr.p->firstOverflowRec == RNIL));
- /*-----------------------------------------------------------------------------------*/
- /* WHO HAS PUT SOMETHING INTO THE LIST BEFORE WE EVEN STARTED PUTTING THINGS */
- /* THERE. */
- /*-----------------------------------------------------------------------------------*/
- ndbrequire(fragrecptr.p->loadingFlag == ZTRUE);
- /*---------------------------------------------------------------------------*/
- /* LOADING HAS STOPPED BEFORE WE HAVE LOADED, SYSTEM ERROR. */
- /*---------------------------------------------------------------------------*/
- while (toverPageCheck < ZNO_OF_OP_PER_SIGNAL) {
- jam();
- if (fragrecptr.p->nextAllocPage >= fragrecptr.p->lastOverIndex) {
- jam();
- fragrecptr.p->loadingFlag = ZFALSE;
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (rootfragrecptr.p->lcpPtr != RNIL) {
- jam();
- srCloseDataFileLab(signal);
- } else {
- jam();
- undoNext2Lab(signal);
- }//if
- return;
- }//if
- tmpP = fragrecptr.p->nextAllocPage;
- pnoDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- arrGuard(tmpP2, 256);
- ptrCheckGuard(pnoDirRangePtr, cdirrangesize, dirRange);
- if (pnoDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- pnoPageidptr.i = RNIL;
- } else {
- pnoOverflowDirptr.i = pnoDirRangePtr.p->dirArray[tmpP2];
- if (pnoOverflowDirptr.i == RNIL) {
- jam();
- pnoPageidptr.i = RNIL;
- } else {
- jam();
- ptrCheckGuard(pnoOverflowDirptr, cdirarraysize, directoryarray);
- pnoPageidptr.i = pnoOverflowDirptr.p->pagep[tmpP];
- }//if
- }//if
- if (pnoPageidptr.i == RNIL) {
- jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = fragrecptr.p->nextAllocPage;
- sorOverflowRecPtr.p->overpage = RNIL;
- priOverflowRecPtr = sorOverflowRecPtr;
- putRecInFreeOverdir(signal);
- } else {
- ptrCheckGuard(pnoPageidptr, cpagesize, page8);
- tpnoPageType = pnoPageidptr.p->word32[ZPOS_PAGE_TYPE];
- tpnoPageType = (tpnoPageType >> ZPOS_PAGE_TYPE_BIT) & 3;
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
- jam();
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
- } else {
- jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID];
- ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage);
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
- sorOverflowRecPtr.p->overpage = pnoPageidptr.i;
- porOverflowRecPtr = sorOverflowRecPtr;
- putOverflowRecInFrag(signal);
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) {
- jam();
- ropPageptr = pnoPageidptr;
- releaseOverpage(signal);
- }//if
- }//if
- }//if
- fragrecptr.p->nextAllocPage++;
- toverPageCheck++;
- }//while
- signal->theData[0] = fragrecptr.i;
- sendSignal(cownBlockref, GSN_ACC_OVER_REC, signal, 1, JBB);
-}//Dbacc::execACC_OVER_REC()
-
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* END OF SYSTEM RESTART MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* */
-/* SCAN MODULE */
-/* */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACC_SCANREQ START OF A SCAN PROCESS */
-/* SENDER: LQH, LEVEL B */
-/* ENTER ACC_SCANREQ WITH */
-/* TUSERPTR, LQH SCAN_CONNECT POINTER */
-/* TUSERBLOCKREF, LQH BLOCK REFERENCE */
-/* TABPTR, TABLE IDENTITY AND PTR */
-/* TFID ROOT FRAGMENT IDENTITY */
-/* TSCAN_FLAG , = ZCOPY, ZSCAN, ZSCAN_LOCK_ALL */
-/* ZREADLOCK, ZWRITELOCK */
-/* TSCAN_TRID1 , TRANSACTION ID PART 1 */
-/* TSCAN_TRID2 TRANSACTION ID PART 2 */
-/* ******************--------------------------------------------------------------- */
-/* ******************--------------------------------------------------------------- */
-/* ACC_SCANREQ START OF A SCAN PROCESS */
-/* ******************------------------------------+ */
-/* SENDER: LQH, LEVEL B */
void Dbacc::execACC_SCANREQ(Signal* signal)
{
jamEntry();
@@ -9130,12 +5293,12 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
tresult = 0;
ptrCheckGuard(tabptr, ctablesize, tabrec);
- ndbrequire(getrootfragmentrec(signal,rootfragrecptr, tfid));
+ ndbrequire(getfragmentrec(signal, fragrecptr, tfid));
Uint32 i;
for (i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
jam();
- if (rootfragrecptr.p->scan[i] == RNIL) {
+ if (fragrecptr.p->scan[i] == RNIL) {
jam();
break;
}
@@ -9144,7 +5307,7 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
ndbrequire(cfirstFreeScanRec != RNIL);
seizeScanRec(signal);
- rootfragrecptr.p->scan[i] = scanPtr.i;
+ fragrecptr.p->scan[i] = scanPtr.i;
scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag);
scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag);
@@ -9157,7 +5320,6 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
scanPtr.p->scanUserblockref = tuserblockref;
scanPtr.p->scanTrid1 = tscanTrid1;
scanPtr.p->scanTrid2 = tscanTrid2;
- scanPtr.p->rootPtr = rootfragrecptr.i;
scanPtr.p->scanLockHeld = 0;
scanPtr.p->scanOpsAllocated = 0;
scanPtr.p->scanFirstActiveOp = RNIL;
@@ -9166,8 +5328,6 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
scanPtr.p->scanFirstLockedOp = RNIL;
scanPtr.p->scanLastLockedOp = RNIL;
scanPtr.p->scanState = ScanRec::WAIT_NEXT;
- fragrecptr.i = rootfragrecptr.p->fragmentptr[0];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
initScanFragmentPart(signal);
/*------------------------------------------------------*/
@@ -9187,10 +5347,9 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
/* ************************ */
signal->theData[0] = scanPtr.p->scanUserptr;
signal->theData[1] = scanPtr.i;
- signal->theData[2] = 2;
- /* NR OF LOCAL FRAGMENT */
- signal->theData[3] = rootfragrecptr.p->fragmentid[0];
- signal->theData[4] = rootfragrecptr.p->fragmentid[1];
+ 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 */
@@ -9230,24 +5389,14 @@ void Dbacc::execNEXT_SCANREQ(Signal* signal)
case ZCOPY_NEXT_COMMIT:
case ZCOPY_COMMIT:
jam();
- /* --------------------------------------------------------------------------------- */
- /* COMMIT ACTIVE OPERATION. SEND NEXT SCAN ELEMENT IF IT IS ZCOPY_NEXT_COMMIT. */
- /* --------------------------------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+ /* 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) {
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) {
- jam();
- /*--------------------------------------------------------------*/
- // We did not have enough undo log buffers to safely commit an
- // operation. Try again in 10 milliseconds.
- /*--------------------------------------------------------------*/
- sendSignalWithDelay(cownBlockref, GSN_NEXT_SCANREQ, signal, 10, 3);
- return;
- }//if
- }//if
commitOperation(signal);
}//if
takeOutActiveScanOp(signal);
@@ -9265,19 +5414,6 @@ void Dbacc::execNEXT_SCANREQ(Signal* signal)
jam();
fragrecptr.i = scanPtr.p->activeLocalFrag;
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (!scanPtr.p->scanReadCommittedFlag) {
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_OPERATION) {
- jam();
- /*--------------------------------------------------------------*/
- // We did not have enough undo log buffers to commit a set of
- // operations. Try again in 10 milliseconds.
- /*--------------------------------------------------------------*/
- sendSignalWithDelay(cownBlockref, GSN_NEXT_SCANREQ, signal, 10, 3);
- return;
- }//if
- }//if
- }//if
/* --------------------------------------------------------------------------------- */
/* THE SCAN PROCESS IS FINISHED. RELOCK ALL LOCKED EL. RELESE ALL INVOLVED REC. */
/* --------------------------------------------------------------------------------- */
@@ -9509,38 +5645,10 @@ void Dbacc::checkNextBucketLab(Signal* signal)
void Dbacc::checkNextFragmentLab(Signal* signal)
{
- RootfragmentrecPtr cnfRootfragrecptr;
-
- cnfRootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(cnfRootfragrecptr, crootfragmentsize, rootfragmentrec);
- if (scanPtr.p->activeLocalFrag == cnfRootfragrecptr.p->fragmentptr[0]) {
- jam();
- fragrecptr.i = cnfRootfragrecptr.p->fragmentptr[1];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- initScanFragmentPart(signal);
- signal->theData[0] = scanPtr.i;
- signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- return;
- } else {
- if (scanPtr.p->activeLocalFrag == cnfRootfragrecptr.p->fragmentptr[1]) {
- jam();
- /* --------------------------------------------------------------------------------- */
- // Both fragments have completed their scan part and we can indicate that the scan is
- // now completed.
- /* --------------------------------------------------------------------------------- */
- scanPtr.p->scanBucketState = ScanRec::SCAN_COMPLETED;
- /*empty*/;
- } else {
- jam();
- /* ALL ELEMENTS ARE SENT */
- sendSystemerror(signal, __LINE__);
- }//if
- }//if
- /* --------------------------------------------------------------------------------- */
- // The scan is completed. ACC_CHECK_SCAN will perform all the necessary checks to see
+ 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);
@@ -9589,13 +5697,13 @@ void Dbacc::releaseScanLab(Signal* signal)
releaseAndCommitQueuedOps(signal);
releaseAndAbortLockedOps(signal);
- rootfragrecptr.i = scanPtr.p->rootPtr;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
+ fragrecptr.i = scanPtr.p->activeLocalFrag;
+ ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
for (tmp = 0; tmp < MAX_PARALLEL_SCANS_PER_FRAG; tmp++) {
jam();
- if (rootfragrecptr.p->scan[tmp] == scanPtr.i) {
+ if (fragrecptr.p->scan[tmp] == scanPtr.i) {
jam();
- rootfragrecptr.p->scan[tmp] = RNIL;
+ fragrecptr.p->scan[tmp] = RNIL;
}//if
}//for
// Stops the heartbeat.
@@ -9691,10 +5799,11 @@ void Dbacc::execACC_CHECK_SCAN(Signal* signal)
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.
- //----------------------------------------------------------------------------
+ //---------------------------------------------------------------------
+ // 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);
@@ -9702,17 +5811,6 @@ void Dbacc::execACC_CHECK_SCAN(Signal* signal)
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
if (operationRecPtr.p->elementIsDisappeared == ZTRUE) {
jam();
- if (fragrecptr.p->createLcp == ZTRUE) {
- if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_COMMIT) {
- jam();
- /*--------------------------------------------------------------*/
- // We did not have enough undo log buffers to safely abort an
- // operation. Try again in 10 milliseconds.
- /*--------------------------------------------------------------*/
- sendSignalWithDelay(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 10, 2);
- return;
- }//if
- }//if
abortOperation(signal);
releaseOpRec(signal);
scanPtr.p->scanOpsAllocated--;
@@ -9922,7 +6020,6 @@ void Dbacc::initScanOpRec(Signal* signal)
operationRecPtr.p->elementPointer = tisoElementptr;
operationRecPtr.p->elementPage = isoPageptr.i;
operationRecPtr.p->isAccLockReq = ZFALSE;
- operationRecPtr.p->isUndoLogReq = ZFALSE;
tisoLocalPtr = tisoElementptr + tisoIsforward;
guard24 = fragrecptr.p->localkeylen - 1;
for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
@@ -10474,14 +6571,14 @@ void Dbacc::takeOutReadyScanQueue(Signal* signal)
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
-bool Dbacc::getrootfragmentrec(Signal* signal, RootfragmentrecPtr& rootPtr, Uint32 fid)
+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();
- rootPtr.i = tabptr.p->fragptrholder[i];
- ptrCheckGuard(rootPtr, crootfragmentsize, rootfragmentrec);
+ fragrecptr.i = tabptr.p->fragptrholder[i];
+ ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
return true;
}//if
}//for
@@ -10489,26 +6586,6 @@ bool Dbacc::getrootfragmentrec(Signal* signal, RootfragmentrecPtr& rootPtr, Uint
}//Dbacc::getrootfragmentrec()
/* --------------------------------------------------------------------------------- */
-/* INIT_FS_OP_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initFsOpRec(Signal* signal)
-{
- fsOpptr.p->fsOpfragrecPtr = fragrecptr.i;
- fsOpptr.p->fsConptr = fsConnectptr.i;
-}//Dbacc::initFsOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* INIT_LCP_CONN_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initLcpConnRec(Signal* signal)
-{
- lcpConnectptr.p->lcpUserblockref = tuserblockref;
- lcpConnectptr.p->lcpUserptr = tuserptr;
- lcpConnectptr.p->noOfLcpConf = 0; /* NO OF RETUREND CONF SIGNALS */
- lcpConnectptr.p->syncUndopageState = WAIT_NOTHING;
-}//Dbacc::initLcpConnRec()
-
-/* --------------------------------------------------------------------------------- */
/* INIT_OVERPAGE */
/* INPUT. IOP_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */
/* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
@@ -10666,40 +6743,6 @@ void Dbacc::initPage(Signal* signal)
}//Dbacc::initPage()
/* --------------------------------------------------------------------------------- */
-/* PUT_OP_IN_FRAG_WAIT_QUE */
-/* DESCRIPTION: AN OPERATION WHICH OWNS A LOCK OF AN ELEMENT, IS PUT IN A */
-/* LIST OF THE FRAGMENT. THIS LIST IS USED TO STOP THE QUEUE */
-/* OPERATION DURING CREATE CHECK POINT PROSESS FOR STOP AND */
-/* RESTART OF THE OPERATIONS. */
-/* */
-/* IF CONTINUEB SIGNALS ARE INTRODUCED AFTER STARTING TO EXECUTE ACCKEYREQ WE */
-/* MUST PUT IT IN THIS LIST BEFORE EXITING TO ENSURE THAT WE ARE NOT BEING */
-/* LOCKED AFTER THAT LQH HAS RECEIVED ALL LCP_HOLDOP'S. THEN THE LCP WILL NEVER*/
-/* PROCEED. WE ALSO PUT IT INTO THIS LIST WHEN WAITING FOR LONG KEYS. THIS IS */
-/* ONLY NEEDED IF SIGNALS CAN ENTER BETWEEN THE KEYDATA CARRYING SIGNALS. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::putOpInFragWaitQue(Signal* signal)
-{
- OperationrecPtr tpiwOperRecPtr;
-
- if (operationRecPtr.p->operation != ZSCAN_OP) {
- if (fragrecptr.p->firstWaitInQueOp == RNIL) {
- jam();
- fragrecptr.p->firstWaitInQueOp = operationRecPtr.i;
- } else {
- jam();
- tpiwOperRecPtr.i = fragrecptr.p->lastWaitInQueOp;
- ptrCheckGuard(tpiwOperRecPtr, coprecsize, operationrec);
- tpiwOperRecPtr.p->nextQueOp = operationRecPtr.i;
- }//if
- operationRecPtr.p->opState = WAIT_IN_QUEUE;
- operationRecPtr.p->nextQueOp = RNIL;
- operationRecPtr.p->prevQueOp = fragrecptr.p->lastWaitInQueOp;
- fragrecptr.p->lastWaitInQueOp = operationRecPtr.i;
- }//if
-}//Dbacc::putOpInFragWaitQue()
-
-/* --------------------------------------------------------------------------------- */
/* 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 */
@@ -10818,37 +6861,6 @@ void Dbacc::releaseDirrange(Signal* signal)
}//Dbacc::releaseDirrange()
/* --------------------------------------------------------------------------------- */
-/* RELEASE_FS_CONN_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseFsConnRec(Signal* signal)
-{
- fsConnectptr.p->fsNext = cfsFirstfreeconnect;
- cfsFirstfreeconnect = fsConnectptr.i;
- fsConnectptr.p->fsState = WAIT_NOTHING;
-}//Dbacc::releaseFsConnRec()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_FS_OP_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseFsOpRec(Signal* signal)
-{
- fsOpptr.p->fsOpnext = cfsFirstfreeop;
- cfsFirstfreeop = fsOpptr.i;
- fsOpptr.p->fsOpstate = WAIT_NOTHING;
-}//Dbacc::releaseFsOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_LCP_CONNECT_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseLcpConnectRec(Signal* signal)
-{
- lcpConnectptr.p->lcpstate = LCP_FREE;
- lcpConnectptr.p->nextLcpConn = cfirstfreelcpConnect;
- lcpConnectptr.p->lcpstate = LCP_FREE;
- cfirstfreelcpConnect = lcpConnectptr.i;
-}//Dbacc::releaseLcpConnectRec()
-
-/* --------------------------------------------------------------------------------- */
/* RELEASE OP RECORD */
/* PUT A FREE OPERATION IN A FREE LIST OF THE OPERATIONS */
/* --------------------------------------------------------------------------------- */
@@ -10917,30 +6929,6 @@ void Dbacc::releaseOverpage(Signal* signal)
jam();
return; /* THERE IS ONLY ONE OVERFLOW PAGE */
}//if
- if ((fragrecptr.p->createLcp == ZTRUE) &&
- (fragrecptr.p->lcpMaxOverDirIndex > ropPageptr.p->word32[ZPOS_PAGE_ID])) {
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE PARTICIPATES IN THE LOCAL CHECKPOINT. */
- /* --------------------------------------------------------------------------------- */
- if (fragrecptr.p->fragState == LCP_SEND_PAGES) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE PARTICIPATES IN THE LOCAL CHECKPOINT AND THE WRITE TO DISK HAS NOT */
- /* YET BEEN COMPLETED. WE MUST KEEP IT A WHILE LONGER SINCE AN EMPTY PAGE IS */
- /* NOT EQUIVALENT TO AN INITIALISED PAGE SINCE THE FREE LISTS CAN DIFFER. */
- /* --------------------------------------------------------------------------------- */
- return;
- } else {
- if ((fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) &&
- (fragrecptr.p->lcpDirIndex <= ropPageptr.p->word32[ZPOS_PAGE_ID])) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* SEE COMMENT ABOVE */
- /* --------------------------------------------------------------------------------- */
- return;
- }//if
- }//if
- }//if
#if kalle
logicalPage = 0;
@@ -10964,9 +6952,9 @@ void Dbacc::releaseOverpage(Signal* signal)
#endif
- /* --------------------------------------------------------------------------------- */
- /* IT WAS OK TO RELEASE THE PAGE. */
- /* --------------------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------------- */
+ /* IT WAS OK TO RELEASE THE PAGE. */
+ /* ----------------------------------------------------------------------- */
ptrCheckGuard(ropOverflowRecPtr, coverflowrecsize, overflowRecord);
tfoOverflowRecPtr = ropOverflowRecPtr;
takeRecOutOfFreeOverpage(signal);
@@ -10988,10 +6976,10 @@ void Dbacc::releaseOverpage(Signal* signal)
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. */
- /* --------------------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------------- */
+ /* 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) {
@@ -11009,10 +6997,10 @@ void Dbacc::releaseOverpage(Signal* signal)
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. */
- /* --------------------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------------- */
+ /* 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) {
@@ -11032,9 +7020,9 @@ void Dbacc::releaseOverpage(Signal* signal)
}//while
}//Dbacc::releaseOverpage()
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_PAGE */
-/* --------------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+/* RELEASE_PAGE */
+/* ------------------------------------------------------------------------- */
void Dbacc::releasePage(Signal* signal)
{
#ifdef VM_TRACE
@@ -11060,24 +7048,6 @@ void Dbacc::releasePage(Signal* signal)
}//Dbacc::releasePage()
/* --------------------------------------------------------------------------------- */
-/* RELEASE_LCP_PAGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseLcpPage(Signal* signal)
-{
- rlpPageptr.p->word32[0] = cfirstfreeLcpPage;
- cfirstfreeLcpPage = rlpPageptr.i;
-}//Dbacc::releaseLcpPage()
-
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_SR_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseSrRec(Signal* signal)
-{
- srVersionPtr.p->nextFreeSr = cfirstFreeSrVersionRec;
- cfirstFreeSrVersionRec = srVersionPtr.i;
-}//Dbacc::releaseSrRec()
-
-/* --------------------------------------------------------------------------------- */
/* SEIZE_DIRECTORY */
/* DESCRIPTION: A DIRECTORY BLOCK (ZDIRBLOCKSIZE NUMBERS OF DIRECTORY */
/* RECORDS WILL BE ALLOCATED AND RETURNED. */
@@ -11139,40 +7109,6 @@ void Dbacc::seizeFragrec(Signal* signal)
}//Dbacc::seizeFragrec()
/* --------------------------------------------------------------------------------- */
-/* SEIZE_FS_CONNECT_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeFsConnectRec(Signal* signal)
-{
- fsConnectptr.i = cfsFirstfreeconnect;
- ptrCheckGuard(fsConnectptr, cfsConnectsize, fsConnectrec);
- cfsFirstfreeconnect = fsConnectptr.p->fsNext;
- fsConnectptr.p->fsNext = RNIL;
- fsConnectptr.p->fsState = WAIT_NOTHING;
-}//Dbacc::seizeFsConnectRec()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_FS_OP_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeFsOpRec(Signal* signal)
-{
- fsOpptr.i = cfsFirstfreeop;
- ptrCheckGuard(fsOpptr, cfsOpsize, fsOprec);
- cfsFirstfreeop = fsOpptr.p->fsOpnext;
- fsOpptr.p->fsOpnext = RNIL;
-}//Dbacc::seizeFsOpRec()
-
-/* --------------------------------------------------------------------------------- */
-/* SEIZE_LCP_CONNECT_REC */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeLcpConnectRec(Signal* signal)
-{
- lcpConnectptr.i = cfirstfreelcpConnect;
- ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
- cfirstfreelcpConnect = lcpConnectptr.p->nextLcpConn;
- lcpConnectptr.p->nextLcpConn = RNIL;
-}//Dbacc::seizeLcpConnectRec()
-
-/* --------------------------------------------------------------------------------- */
/* SEIZE_OP_REC */
/* --------------------------------------------------------------------------------- */
void Dbacc::seizeOpRec(Signal* signal)
@@ -11240,25 +7176,8 @@ void Dbacc::seizePage(Signal* signal)
}//Dbacc::seizePage()
/* --------------------------------------------------------------------------------- */
-/* SEIZE_PAGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeLcpPage(Page8Ptr& regPagePtr)
-{
- regPagePtr.i = cfirstfreeLcpPage;
- ptrCheckGuard(regPagePtr, cpagesize, page8);
- cfirstfreeLcpPage = regPagePtr.p->word32[0];
-}//Dbacc::seizeLcpPage()
-
-/* --------------------------------------------------------------------------------- */
/* SEIZE_ROOTFRAGREC */
/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeRootfragrec(Signal* signal)
-{
- rootfragrecptr.i = cfirstfreerootfrag;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
- cfirstfreerootfrag = rootfragrecptr.p->nextroot;
- rootfragrecptr.p->nextroot = RNIL;
-}//Dbacc::seizeRootfragrec()
/* --------------------------------------------------------------------------------- */
/* SEIZE_SCAN_REC */
@@ -11274,13 +7193,6 @@ void Dbacc::seizeScanRec(Signal* signal)
/* --------------------------------------------------------------------------------- */
/* SEIZE_SR_VERSION_REC */
/* --------------------------------------------------------------------------------- */
-void Dbacc::seizeSrVerRec(Signal* signal)
-{
- srVersionPtr.i = cfirstFreeSrVersionRec;
- ptrCheckGuard(srVersionPtr, csrVersionRecSize, srVersionRec);
- cfirstFreeSrVersionRec = srVersionPtr.p->nextFreeSr;
-}//Dbacc::seizeSrVerRec()
-
/* --------------------------------------------------------------------------------- */
/* SEND_SYSTEMERROR */
/* --------------------------------------------------------------------------------- */
@@ -11376,11 +7288,10 @@ Dbacc::execDUMP_STATE_ORD(Signal* signal)
scanPtr.i, scanPtr.p->scanState,scanPtr.p->scanTrid1,
scanPtr.p->scanTrid2);
infoEvent(" timer=%d, continueBCount=%d, "
- "activeLocalFrag=%d, root=%d, nextBucketIndex=%d",
+ "activeLocalFrag=%d, nextBucketIndex=%d",
scanPtr.p->scanTimer,
scanPtr.p->scanContinuebCounter,
scanPtr.p->activeLocalFrag,
- scanPtr.p->rootPtr,
scanPtr.p->nextBucketIndex);
infoEvent(" scanNextfreerec=%d firstActOp=%d firstLockedOp=%d, "
"scanLastLockedOp=%d firstQOp=%d lastQOp=%d",
@@ -11682,15 +7593,13 @@ Dbacc::execREAD_PSEUDO_REQ(Signal* signal){
fragrecptr.i = signal->theData[0];
Uint32 attrId = signal->theData[1];
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
Uint64 tmp;
switch(attrId){
case AttributeHeader::ROW_COUNT:
- tmp = rootfragrecptr.p->noOfElements;
+ tmp = fragrecptr.p->noOfElements;
break;
case AttributeHeader::COMMIT_COUNT:
- tmp = rootfragrecptr.p->m_commit_count;
+ tmp = fragrecptr.p->m_commit_count;
break;
default:
tmp = 0;
@@ -11703,4 +7612,3 @@ Dbacc::execREAD_PSEUDO_REQ(Signal* signal){
// signal->theData[0] = src[0];
// signal->theData[1] = src[1];
}
-
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 54e0a39abe4..9755a65aa53 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -55,6 +55,10 @@
#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>
@@ -78,6 +82,10 @@
#include <NdbSleep.h>
#include <signaldata/ApiBroadcast.hpp>
+#include <signaldata/DropObj.hpp>
+#include <signaldata/CreateObj.hpp>
+#include <SLList.hpp>
+
#define ZNOT_FOUND 626
#define ZALREADYEXIST 630
@@ -85,29 +93,122 @@
//#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, 0,
+ 0, 0
+ }
+};
+
Uint32
-alter_table_inc_schema_version(Uint32 old)
+alter_obj_inc_schema_version(Uint32 old)
{
return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000);
}
static
Uint32
-alter_table_dec_schema_version(Uint32 old)
+alter_obj_dec_schema_version(Uint32 old)
{
return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000);
}
static
Uint32
-create_table_inc_schema_version(Uint32 old)
+create_obj_inc_schema_version(Uint32 old)
{
return (old + 0x00000001) & 0x00FFFFFF;
}
@@ -177,6 +278,14 @@ Dbdict::execDUMP_STATE_ORD(Signal* 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_file_pool", c_file_pool);
+ MEMINFO("c_filegroup_pool", c_filegroup_pool);
+ MEMINFO("c_opRecordPool", c_opRecordPool);
+ MEMINFO("c_rope_pool", c_rope_pool);
+ }
return;
}//Dbdict::execDUMP_STATE_ORD()
@@ -193,7 +302,7 @@ void Dbdict::execCONTINUEB(Signal* signal)
switch (signal->theData[0]) {
case ZPACK_TABLE_INTO_PAGES :
jam();
- packTableIntoPages(signal, signal->theData[1], signal->theData[2]);
+ packTableIntoPages(signal);
break;
case ZSEND_GET_TAB_RESPONSE :
@@ -214,32 +323,67 @@ void Dbdict::execCONTINUEB(Signal* signal)
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
-void Dbdict::packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId)
+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;
- TableRecordPtr tablePtr;
c_pageRecordArray.getPtr(pagePtr, pageId);
-
+
memset(&pagePtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
- c_tableRecordPool.getPtr(tablePtr, tableId);
LinearWriter w(&pagePtr.p->word[ZPAGE_HEADER_SIZE],
8 * ZSIZE_OF_PAGES_IN_WORDS);
-
w.first();
- packTableIntoPagesImpl(w, tablePtr, signal);
-
+ 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));
+ packFilegroupIntoPages(w, fg_ptr);
+ 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 =
- DIV(wordsOfTable + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ 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:
- case PackTable::PTS_ADD_TABLE_MASTER:
- case PackTable::PTS_ADD_TABLE_SLAVE:
- case PackTable::PTS_RESTART:
ndbrequire(false);
break;
case PackTable::PTS_GET_TAB:
@@ -255,17 +399,20 @@ void Dbdict::packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId)
}//packTableIntoPages()
void
-Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
+Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
TableRecordPtr tablePtr,
Signal* signal){
- w.add(DictTabInfo::TableName, tablePtr.p->tableName);
+ union {
+ char tableName[MAX_TAB_NAME_SIZE];
+ char frmData[MAX_FRM_DATA_SIZE];
+ 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);
-#ifdef HAVE_TABLE_REORG
- w.add(DictTabInfo::SecondTableId, tablePtr.p->secondTable);
-#else
- w.add(DictTabInfo::SecondTableId, (Uint32)0);
-#endif
w.add(DictTabInfo::TableVersion, tablePtr.p->tableVersion);
w.add(DictTabInfo::NoOfKeyAttr, tablePtr.p->noOfPrimkey);
w.add(DictTabInfo::NoOfAttributes, tablePtr.p->noOfAttributes);
@@ -307,7 +454,9 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
if (tablePtr.p->primaryTableId != RNIL){
TableRecordPtr primTab;
c_tableRecordPool.getPtr(primTab, tablePtr.p->primaryTableId);
- w.add(DictTabInfo::PrimaryTable, primTab.p->tableName);
+ 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);
@@ -315,16 +464,31 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
w.add(DictTabInfo::DeleteTriggerId, tablePtr.p->deleteTriggerId);
w.add(DictTabInfo::CustomTriggerId, tablePtr.p->customTriggerId);
}
- w.add(DictTabInfo::FrmLen, tablePtr.p->frmLen);
- w.add(DictTabInfo::FrmData, tablePtr.p->frmData, tablePtr.p->frmLen);
+
+ ConstRope frm(c_rope_pool, tablePtr.p->frmData);
+ frm.copy(frmData);
- Uint32 nextAttribute = tablePtr.p->firstAttribute;
+ w.add(DictTabInfo::FrmLen, frm.size());
+ w.add(DictTabInfo::FrmData, frmData, frm.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;
- do {
+ LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
+ tablePtr.p->m_attributes);
+ for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
jam();
- c_attributeRecordPool.getPtr(attrPtr, nextAttribute);
-
- w.add(DictTabInfo::AttributeName, attrPtr.p->attributeName);
+
+ 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);
@@ -332,12 +496,16 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
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);
@@ -346,15 +514,88 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
w.add(DictTabInfo::AttributeAutoIncrement,
(Uint32)attrPtr.p->autoIncrement);
- w.add(DictTabInfo::AttributeDefaultValue, attrPtr.p->defaultValue);
+
+ 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);
- nextAttribute = attrPtr.p->nextAttrInTable;
- } while (nextAttribute != RNIL);
+ }
w.add(DictTabInfo::TableEnd, 1);
}
+void
+Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w,
+ FilegroupPtr fg_ptr){
+
+ 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_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.FileNo = f_ptr.p->key;
+
+ 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.
@@ -564,15 +805,14 @@ Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
- Uint32 sz = tabInfoPtr.sz + ZPAGE_HEADER_SIZE;
-
- c_writeTableRecord.noOfPages = DIV(sz, ZSIZE_OF_PAGES_IN_WORDS);
+ 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(c_writeTableRecord.noOfPages < 8);
-
+ ndbrequire(pages == 1);
+
PageRecordPtr pageRecPtr;
c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
copy(&pageRecPtr.p->word[ZPAGE_HEADER_SIZE], tabInfoPtr);
@@ -580,10 +820,9 @@ Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
pageRecPtr.p->word[ZPOS_CHECKSUM] =
computeChecksum(&pageRecPtr.p->word[0],
- c_writeTableRecord.noOfPages * ZSIZE_OF_PAGES_IN_WORDS);
+ pages * ZSIZE_OF_PAGES_IN_WORDS);
startWriteTableFile(signal, tableId);
-
}
void Dbdict::startWriteTableFile(Signal* signal, Uint32 tableId)
@@ -602,9 +841,7 @@ void Dbdict::openTableFile(Signal* signal,
Uint32 tableId,
bool writeFlag)
{
- TableRecordPtr tablePtr;
FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
- c_tableRecordPool.getPtr(tablePtr, tableId);
fsOpenReq->userReference = reference();
fsOpenReq->userPointer = fsConPtr;
@@ -619,14 +856,13 @@ void Dbdict::openTableFile(Signal* signal,
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, tablePtr.p->tableVersion);
+ FsOpenReq::v1_setS(fsOpenReq->fileNumber, 0);
FsOpenReq::v1_setP(fsOpenReq->fileNumber, 255);
/* ---------------------------------------------------------------- */
// File name : D1/DBDICT/T0/S1.TableList
@@ -650,7 +886,7 @@ void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
fsRWReq->varIndex = ZBAT_TABLE_FILE;
- fsRWReq->numberOfPages = c_writeTableRecord.noOfPages;
+ 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);
@@ -727,7 +963,7 @@ void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
fsRWReq->varIndex = ZBAT_TABLE_FILE;
- fsRWReq->numberOfPages = c_readTableRecord.noOfPages;
+ 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);
@@ -750,7 +986,8 @@ void Dbdict::readTableConf(Signal* signal,
PageRecordPtr tmpPagePtr;
c_pageRecordArray.getPtr(tmpPagePtr, c_readTableRecord.pageId);
- Uint32 sz = c_readTableRecord.noOfPages * ZSIZE_OF_PAGES_IN_WORDS;
+ 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);
@@ -809,7 +1046,7 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
case SchemaFile::ADD_STARTED:
jam();
ok = true;
- ndbrequire(create_table_inc_schema_version(oldVersion) == newVersion);
+ ndbrequire(create_obj_inc_schema_version(oldVersion) == newVersion);
ndbrequire(oldState == SchemaFile::INIT ||
oldState == SchemaFile::DROP_TABLE_COMMITTED);
break;
@@ -817,12 +1054,13 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
jam();
ok = true;
ndbrequire(newVersion == oldVersion);
- ndbrequire(oldState == SchemaFile::ADD_STARTED);
+ ndbrequire(oldState == SchemaFile::ADD_STARTED ||
+ oldState == SchemaFile::DROP_TABLE_STARTED);
break;
case SchemaFile::ALTER_TABLE_COMMITTED:
jam();
ok = true;
- ndbrequire(alter_table_inc_schema_version(oldVersion) == newVersion);
+ ndbrequire(alter_obj_inc_schema_version(oldVersion) == newVersion);
ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED ||
oldState == SchemaFile::ALTER_TABLE_COMMITTED);
break;
@@ -831,7 +1069,6 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
case SchemaFile::DROP_TABLE_COMMITTED:
jam();
ok = true;
- ndbrequire(false);
break;
case SchemaFile::INIT:
jam();
@@ -1189,9 +1426,10 @@ Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf)
Dbdict::Dbdict(const class Configuration & conf):
SimulatedBlock(DBDICT, conf),
- c_tableRecordHash(c_tableRecordPool),
c_attributeRecordHash(c_attributeRecordPool),
- c_triggerRecordHash(c_triggerRecordPool),
+ 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),
@@ -1205,7 +1443,12 @@ Dbdict::Dbdict(const class Configuration & conf):
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)
+
{
BLOCK_CONSTRUCTOR(Dbdict);
@@ -1345,7 +1588,39 @@ Dbdict::Dbdict(const class Configuration & conf):
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);
+
}//Dbdict::Dbdict()
Dbdict::~Dbdict()
@@ -1403,7 +1678,7 @@ void Dbdict::initSendSchemaRecord()
void Dbdict::initReadTableRecord()
{
- c_readTableRecord.noOfPages = (Uint32)-1;
+ c_readTableRecord.no_of_words= 0;
c_readTableRecord.pageId = RNIL;
c_readTableRecord.tableId = ZNIL;
c_readTableRecord.inUse = false;
@@ -1411,7 +1686,7 @@ void Dbdict::initReadTableRecord()
void Dbdict::initWriteTableRecord()
{
- c_writeTableRecord.noOfPages = (Uint32)-1;
+ c_writeTableRecord.no_of_words= 0;
c_writeTableRecord.pageId = RNIL;
c_writeTableRecord.noOfTableFilesHandled = 3;
c_writeTableRecord.tableId = ZNIL;
@@ -1453,6 +1728,7 @@ void Dbdict::initRestartRecord()
{
c_restartRecord.gciToRestart = 0;
c_restartRecord.activeTable = ZNIL;
+ c_restartRecord.m_pass = 0;
}//Dbdict::initRestartRecord()
void Dbdict::initNodeRecords()
@@ -1491,25 +1767,21 @@ void 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->firstAttribute = RNIL;
tablePtr.p->firstPage = RNIL;
- tablePtr.p->lastAttribute = 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;
- memset(tablePtr.p->tableName, 0, sizeof(tablePtr.p->tableName));
tablePtr.p->gciTableCreated = 0;
tablePtr.p->noOfAttributes = ZNIL;
tablePtr.p->noOfNullAttr = 0;
tablePtr.p->ngLen = 0;
memset(tablePtr.p->ngData, 0, sizeof(tablePtr.p->ngData));
- tablePtr.p->frmLen = 0;
- memset(tablePtr.p->frmData, 0, sizeof(tablePtr.p->frmData));
tablePtr.p->fragmentCount = 0;
/*
tablePtr.p->lh3PageIndexBits = 0;
@@ -1552,9 +1824,9 @@ void Dbdict::initTriggerRecords()
void Dbdict::initialiseTriggerRecord(TriggerRecordPtr triggerPtr)
{
+ new (triggerPtr.p) TriggerRecord();
triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
triggerPtr.p->triggerLocal = 0;
- memset(triggerPtr.p->triggerName, 0, sizeof(triggerPtr.p->triggerName));
triggerPtr.p->triggerId = RNIL;
triggerPtr.p->tableId = RNIL;
triggerPtr.p->triggerType = (TriggerType::Value)~0;
@@ -1577,53 +1849,50 @@ Uint32 Dbdict::getFsConnRecord()
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);
- TableRecordPtr tablePtr;
- TableRecordPtr firstTablePtr;
- bool firstFound = false;
- Uint32 tabSize = c_tableRecordPool.getSize();
- for (tablePtr.i = minId; tablePtr.i < tabSize ; tablePtr.i++) {
- jam();
- c_tableRecordPool.getPtr(tablePtr);
- if (tablePtr.p->tabState == TableRecord::NOT_DEFINED) {
- jam();
- initialiseTableRecord(tablePtr);
- tablePtr.p->tabState = TableRecord::DEFINING;
- firstFound = true;
- firstTablePtr.i = tablePtr.i;
- firstTablePtr.p = tablePtr.p;
- break;
- }//if
- }//for
- if (!firstFound) {
+ Uint32 i = getFreeObjId(minId);
+ if (i == RNIL) {
jam();
return RNIL;
- }//if
-#ifdef HAVE_TABLE_REORG
- bool secondFound = false;
- for (tablePtr.i = firstTablePtr.i + 1; tablePtr.i < tabSize ; tablePtr.i++) {
- jam();
- c_tableRecordPool.getPtr(tablePtr);
- if (tablePtr.p->tabState == TableRecord::NOT_DEFINED) {
- jam();
- initialiseTableRecord(tablePtr);
- tablePtr.p->tabState = TableRecord::REORG_TABLE_PREPARED;
- tablePtr.p->secondTable = firstTablePtr.i;
- firstTablePtr.p->secondTable = tablePtr.i;
- secondFound = true;
- break;
- }//if
- }//for
- if (!secondFound) {
+ }
+ if (i >= c_tableRecordPool.getSize()) {
jam();
- firstTablePtr.p->tabState = TableRecord::NOT_DEFINED;
return RNIL;
- }//if
-#endif
- return firstTablePtr.i;
-}//Dbdict::getFreeTableRecord()
+ }
+ 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()
{
@@ -1641,39 +1910,6 @@ Uint32 Dbdict::getFreeTriggerRecord()
return RNIL;
}
-bool
-Dbdict::getNewAttributeRecord(TableRecordPtr tablePtr,
- AttributeRecordPtr & attrPtr)
-{
- c_attributeRecordPool.seize(attrPtr);
- if(attrPtr.i == RNIL){
- return false;
- }
-
- memset(attrPtr.p->attributeName, 0, sizeof(attrPtr.p->attributeName));
- attrPtr.p->attributeDescriptor = 0x00012255; //Default value
- attrPtr.p->attributeId = ZNIL;
- attrPtr.p->nextAttrInTable = RNIL;
- attrPtr.p->tupleKey = 0;
- memset(attrPtr.p->defaultValue, 0, sizeof(attrPtr.p->defaultValue));
-
- /* ---------------------------------------------------------------- */
- // A free attribute record has been acquired. We will now link it
- // to the table record.
- /* ---------------------------------------------------------------- */
- if (tablePtr.p->lastAttribute == RNIL) {
- jam();
- tablePtr.p->firstAttribute = attrPtr.i;
- } else {
- jam();
- AttributeRecordPtr lastAttrPtr;
- c_attributeRecordPool.getPtr(lastAttrPtr, tablePtr.p->lastAttribute);
- lastAttrPtr.p->nextAttrInTable = attrPtr.i;
- }//if
- tablePtr.p->lastAttribute = attrPtr.i;
- return true;
-}//Dbdict::getNewAttributeRecord()
-
/* **************************************************************** */
/* ---------------------------------------------------------------- */
/* MODULE: START/RESTART HANDLING ------------------------ */
@@ -1743,10 +1979,17 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
c_tableRecordPool.setSize(tablerecSize);
- c_tableRecordHash.setSize(tablerecSize);
g_key_descriptor_pool.setSize(tablerecSize);
c_triggerRecordPool.setSize(c_maxNoOfTriggers);
- c_triggerRecordHash.setSize(c_maxNoOfTriggers);
+
+ c_obj_pool.setSize(tablerecSize+c_maxNoOfTriggers);
+ c_obj_hash.setSize((tablerecSize+c_maxNoOfTriggers+1)/2);
+
+ c_file_pool.setSize(10);
+ c_file_hash.setSize(16);
+ c_filegroup_pool.setSize(10);
+ c_filegroup_hash.setSize(16);
+
c_opRecordPool.setSize(256); // XXX need config params
c_opCreateTable.setSize(8);
c_opDropTable.setSize(8);
@@ -1770,6 +2013,11 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
(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);
+ c_rope_pool.setSize(100000/28);
+
// Initialize BAT for interface to file system
NewVARIABLE* bat = allocateBat(2);
bat[0].WA = &c_schemaPageRecordArray.getPtr(0)->word[0];
@@ -1791,6 +2039,30 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
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();
+ }
+
+ {
+ Ptr<File> ptr;
+ SLList<File> objs(c_file_pool);
+ while(objs.seize(ptr))
+ new (ptr.p) File();
+ objs.release();
+ }
+
+ {
+ Ptr<Filegroup> ptr;
+ SLList<Filegroup> objs(c_filegroup_pool);
+ while(objs.seize(ptr))
+ new (ptr.p) Filegroup();
+ objs.release();
+ }
}//execSIZEALT_REP()
/* ---------------------------------------------------------------- */
@@ -2088,6 +2360,7 @@ void Dbdict::execDICTSTARTREQ(Signal* signal)
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);
@@ -2215,6 +2488,8 @@ void Dbdict::execSCHEMA_INFO(Signal* signal)
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()
@@ -2235,6 +2510,9 @@ Dbdict::restart_checkSchemaStatusComplete(Signal * signal,
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::restart_writeSchemaConf);
+ for(Uint32 i = 0; i<xsf->noOfPages; i++)
+ computeChecksum(xsf, i);
+
startWriteSchemaFile(signal);
}
@@ -2277,6 +2555,37 @@ void Dbdict::execSCHEMA_INFOCONF(Signal* signal)
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;
+ case DictTabInfo::Tablespace:
+ return pass == 1;
+ case DictTabInfo::Datafile:
+ case DictTabInfo::Undofile:
+ return pass == 2;
+ case DictTabInfo::SystemTable:
+ case DictTabInfo::UserTable:
+ return pass == 3;
+ case DictTabInfo::UniqueHashIndex:
+ case DictTabInfo::HashIndex:
+ case DictTabInfo::UniqueOrderedIndex:
+ case DictTabInfo::OrderedIndex:
+ return pass == 4;
+ }
+
+ return false;
+}
+
void Dbdict::checkSchemaStatus(Signal* signal)
{
XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
@@ -2303,6 +2612,12 @@ void Dbdict::checkSchemaStatus(Signal* signal)
continue;
}//if
+ if(!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
+ continue;
+
+ if(!::checkSchemaStatus(newEntry->m_tableType, c_restartRecord.m_pass))
+ continue;
+
switch(schemaState){
case SchemaFile::INIT:{
jam();
@@ -2380,7 +2695,7 @@ void Dbdict::checkSchemaStatus(Signal* signal)
// Table was added in the master node but not in our node. We can
// retrieve the table definition from the master.
//------------------------------------------------------------------
- restartCreateTab(signal, tableId, oldEntry, false);
+ restartCreateTab(signal, tableId, oldEntry, newEntry, false);
return;
break;
case SchemaFile::TABLE_ADD_COMMITTED:
@@ -2392,17 +2707,16 @@ void Dbdict::checkSchemaStatus(Signal* signal)
// Table was added in both our node and the master node. We can
// retrieve the table definition from our own disk.
//------------------------------------------------------------------
- if(* newEntry == * oldEntry){
- jam();
-
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- tablePtr.p->tableVersion = oldEntry->m_tableVersion;
- tablePtr.p->tableType = (DictTabInfo::TableType)oldEntry->m_tableType;
-
+ if(newEntry->m_tableVersion == oldEntry->m_tableVersion)
+ {
+ jam();
+ ndbrequire(newEntry->m_gcp == oldEntry->m_gcp);
+ ndbrequire(newEntry->m_tableType == oldEntry->m_tableType);
+ Uint32 type= oldEntry->m_tableType;
// On NR get index from master because index state is not on file
- const bool file = c_systemRestart || tablePtr.p->isTable();
- restartCreateTab(signal, tableId, oldEntry, file);
+ const bool file = c_systemRestart || !DictTabInfo::isIndex(type);
+ newEntry->m_info_words= oldEntry->m_info_words;
+ restartCreateTab(signal, tableId, oldEntry, newEntry, file);
return;
} else {
@@ -2417,7 +2731,7 @@ void Dbdict::checkSchemaStatus(Signal* signal)
ndbrequire(newEntry->m_tableVersion != oldEntry->m_tableVersion);
jam();
- restartCreateTab(signal, tableId, oldEntry, false);
+ restartCreateTab(signal, tableId, oldEntry, newEntry, false);
return;
}//if
}
@@ -2470,7 +2784,7 @@ void Dbdict::checkSchemaStatus(Signal* signal)
// Table was altered in the master node but not in our node. We can
// retrieve the altered table definition from the master.
//------------------------------------------------------------------
- restartCreateTab(signal, tableId, oldEntry, false);
+ restartCreateTab(signal, tableId, oldEntry, newEntry, false);
return;
break;
case SchemaFile::ALTER_TABLE_COMMITTED:
@@ -2481,15 +2795,13 @@ void Dbdict::checkSchemaStatus(Signal* signal)
// Table was altered in both our node and the master node. We can
// retrieve the table definition from our own disk.
//------------------------------------------------------------------
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- tablePtr.p->tableVersion = oldEntry->m_tableVersion;
- tablePtr.p->tableType = (DictTabInfo::TableType)oldEntry->m_tableType;
// On NR get index from master because index state is not on file
- const bool file = c_systemRestart || tablePtr.p->isTable();
- restartCreateTab(signal, tableId, oldEntry, file);
-
+ Uint32 type= oldEntry->m_tableType;
+ const bool file = c_systemRestart || !DictTabInfo::isIndex(type);
+ newEntry->m_info_words= oldEntry->m_info_words;
+ restartCreateTab(signal, tableId, oldEntry, newEntry, file);
+
return;
}
ndbrequire(ok);
@@ -2498,13 +2810,46 @@ void Dbdict::checkSchemaStatus(Signal* signal)
}
}
- execute(signal, c_schemaRecord.m_callback, 0);
+ c_restartRecord.m_pass++;
+ c_restartRecord.activeTable= 0;
+ if(c_restartRecord.m_pass <= 4)
+ {
+ checkSchemaStatus(signal);
+ }
+ else
+ {
+ execute(signal, c_schemaRecord.m_callback, 0);
+ }
}//checkSchemaStatus()
void
Dbdict::restartCreateTab(Signal* signal, Uint32 tableId,
- const SchemaFile::TableEntry * te, bool file){
+ 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);
@@ -2524,8 +2869,7 @@ Dbdict::restartCreateTab(Signal* signal, Uint32 tableId,
if(file && !ERROR_INSERTED(6002)){
jam();
- c_readTableRecord.noOfPages =
- DIV(te->m_info_words + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ 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 =
@@ -2569,17 +2913,17 @@ Dbdict::restartCreateTab_readTableConf(Signal* signal,
parseRecord.requestType = DictTabInfo::GetTabInfoConf;
parseRecord.errorCode = 0;
- Uint32 sz = c_readTableRecord.noOfPages * ZSIZE_OF_PAGES_IN_WORDS;
- SimplePropertiesLinearReader r(&pageRecPtr.p->word[0], sz);
+ Uint32 sz = c_readTableRecord.no_of_words;
+ SimplePropertiesLinearReader r(pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz);
handleTabInfoInit(r, &parseRecord);
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.noOfPages = c_readTableRecord.noOfPages;
+ 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;
@@ -2599,9 +2943,53 @@ Dbdict::execGET_TABINFO_CONF(Signal* signal){
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
+ {
+ jam();
+ restartCreateObj_getTabInfoConf(signal);
+ }
+ return;
+ }
+
const Uint32 tableId = conf->tableId;
const Uint32 senderData = conf->senderData;
-
+
SegmentedSectionPtr tabInfoPtr;
signal->getSection(tabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
@@ -2620,6 +3008,11 @@ Dbdict::execGET_TABINFO_CONF(Signal* signal){
SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
handleTabInfoInit(r, &parseRecord);
ndbrequire(parseRecord.errorCode == 0);
+
+ 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;
@@ -2721,7 +3114,6 @@ Dbdict::restartDropTab(Signal* signal, Uint32 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;
@@ -2747,6 +3139,234 @@ Dbdict::restartDropTab_complete(Signal* signal,
checkSchemaStatus(signal);
}
+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);
+}
+
/* **************************************************************** */
/* ---------------------------------------------------------------- */
/* MODULE: NODE FAILURE HANDLING ------------------------- */
@@ -3181,7 +3801,7 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal)
// Send prepare request to all alive nodes
SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPagesImpl(w, parseRecord.tablePtr);
+ packTableIntoPages(w, parseRecord.tablePtr);
SegmentedSectionPtr tabInfoPtr;
w.getPtr(tabInfoPtr);
@@ -3251,7 +3871,7 @@ Dbdict::alterTable_backup_mutex_locked(Signal* signal,
lreq->clientData = alterTabPtr.p->m_senderData;
lreq->changeMask = alterTabPtr.p->m_changeMask;
lreq->tableId = tablePtr.p->tableId;
- lreq->tableVersion = alter_table_inc_schema_version(tablePtr.p->tableVersion);
+ lreq->tableVersion = alter_obj_inc_schema_version(tablePtr.p->tableVersion);
lreq->gci = tablePtr.p->gciTableCreated;
lreq->requestType = AlterTabReq::AlterTablePrepare;
@@ -3381,7 +4001,7 @@ Dbdict::execALTER_TAB_REQ(Signal * signal)
}
ndbrequire(ok);
- if(alter_table_inc_schema_version(tablePtr.p->tableVersion) != tableVersion){
+ if(alter_obj_inc_schema_version(tablePtr.p->tableVersion) != tableVersion){
jam();
alterTabRef(signal, req, AlterTableRef::InvalidTableVersion);
return;
@@ -3555,7 +4175,7 @@ void Dbdict::execALTER_TAB_REF(Signal * signal){
Uint32 tableVersion = tablePtr.p->tableVersion;
Uint32 gci = tablePtr.p->gciTableCreated;
SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPagesImpl(w, tablePtr);
+ packTableIntoPages(w, tablePtr);
SegmentedSectionPtr spDataPtr;
w.getPtr(spDataPtr);
signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
@@ -3691,7 +4311,7 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){
Uint32 tableVersion = tablePtr.p->tableVersion;
Uint32 gci = tablePtr.p->gciTableCreated;
SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPagesImpl(w, tablePtr);
+ packTableIntoPages(w, tablePtr);
SegmentedSectionPtr spDataPtr;
w.getPtr(spDataPtr);
signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
@@ -3720,7 +4340,7 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){
TableRecordPtr tablePtr;
c_tableRecordPool.getPtr(tablePtr, tableId);
SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPagesImpl(w, tablePtr);
+ packTableIntoPages(w, tablePtr);
SegmentedSectionPtr spDataPtr;
w.getPtr(spDataPtr);
signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
@@ -3803,13 +4423,16 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){
inline
void Dbdict::printTables()
{
- DLHashTable<TableRecord>::Iterator iter;
- bool moreTables = c_tableRecordHash.first(iter);
- printf("TABLES IN DICT:\n");
+ DLHashTable<DictObject>::Iterator iter;
+ bool moreTables = c_obj_hash.first(iter);
+ printf("OBJECTS IN DICT:\n");
+ char name[MAX_TAB_NAME_SIZE];
while (moreTables) {
- TableRecordPtr tablePtr = iter.curr;
- printf("%s ", tablePtr.p->tableName);
- moreTables = c_tableRecordHash.next(iter);
+ 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");
}
@@ -3819,31 +4442,58 @@ int Dbdict::handleAlterTab(AlterTabReq * req,
TableRecordPtr origTablePtr,
TableRecordPtr newTablePtr)
{
+ bool supportedAlteration = false;
Uint32 changeMask = req->changeMask;
if (AlterTableReq::getNameFlag(changeMask)) {
jam();
// Table rename
+ supportedAlteration = true;
// Remove from hashtable
-#ifdef VM_TRACE
- TableRecordPtr tmp;
- ndbrequire(c_tableRecordHash.find(tmp, *origTablePtr.p));
-#endif
- c_tableRecordHash.remove(origTablePtr);
- strcpy(alterTabPtrP->previousTableName, origTablePtr.p->tableName);
- strcpy(origTablePtr.p->tableName, newTablePtr.p->tableName);
+ 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()));
+ }
+
+ if (supportedAlteration)
+ {
// Set new schema version
origTablePtr.p->tableVersion = newTablePtr.p->tableVersion;
- // Put it back
-#ifdef VM_TRACE
- ndbrequire(!c_tableRecordHash.find(tmp, *origTablePtr.p));
-#endif
- c_tableRecordHash.add(origTablePtr);
-
return 0;
}
- jam();
- return -1;
+ else
+ {
+ jam();
+ return -1;
+ }
}
void Dbdict::revertAlterTable(Signal * signal,
@@ -3851,31 +4501,51 @@ void Dbdict::revertAlterTable(Signal * signal,
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
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, tableId);
- // Remove from hashtable
-#ifdef VM_TRACE
- TableRecordPtr tmp;
- ndbrequire(c_tableRecordHash.find(tmp, * tablePtr.p));
-#endif
- c_tableRecordHash.remove(tablePtr);
- // Restore name
- strcpy(tablePtr.p->tableName, alterTabPtrP->previousTableName);
- // Revert schema version
- tablePtr.p->tableVersion = alter_table_dec_schema_version(tablePtr.p->tableVersion);
+
+ 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
-#ifdef VM_TRACE
- ndbrequire(!c_tableRecordHash.find(tmp, * tablePtr.p));
-#endif
- c_tableRecordHash.add(tablePtr);
+ c_obj_hash.add(obj_ptr);
+ }
- return;
+ 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);
}
@@ -3947,7 +4617,7 @@ Dbdict::alterTab_writeTableConf(Signal* signal,
AlterTableRep* rep = (AlterTableRep*)api->theData;
rep->tableId = tabPtr.p->tableId;
- rep->tableVersion = alter_table_dec_schema_version(tabPtr.p->tableVersion);
+ rep->tableVersion = alter_obj_dec_schema_version(tabPtr.p->tableVersion);
rep->changeType = AlterTableRep::CT_ALTERED;
LinearSectionPtr ptr[3];
@@ -4010,13 +4680,14 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
SchemaFile::TableEntry * tabEntry = getTableEntry(xsf, tabPtr.i);
- tabPtr.p->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
+ tabPtr.p->tableVersion =
+ create_obj_inc_schema_version(tabEntry->m_tableVersion);
/**
* Pack
*/
SimplePropertiesSectionWriter w(getSectionSegmentPool());
- packTableIntoPagesImpl(w, tabPtr);
+ packTableIntoPages(w, tabPtr);
SegmentedSectionPtr spDataPtr;
w.getPtr(spDataPtr);
@@ -4039,7 +4710,7 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
req->gci = 0;
req->tableId = tabPtr.i;
- req->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
+ req->tableVersion = create_obj_inc_schema_version(tabEntry->m_tableVersion);
sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal,
CreateTabReq::SignalLength, JBB);
@@ -4323,6 +4994,13 @@ Dbdict::createTab_prepare(Signal* signal, CreateTabReq * req){
safe_cast(&Dbdict::createTab_writeSchemaConf1);
updateSchemaState(signal, tableId, &tabEntry, &callback);
+
+ if (tabPtr.p->m_tablespace_id != RNIL)
+ {
+ FilegroupPtr ptr;
+ ndbrequire(c_filegroup_hash.find(ptr, tabPtr.p->m_tablespace_id));
+ increase_ref_count(ptr.p->m_obj_ptr_i);
+ }
}
void getSection(SegmentedSectionPtr & ptr, Uint32 i);
@@ -4408,34 +5086,39 @@ Dbdict::createTab_dih(Signal* signal,
new (desc) KeyDescriptor();
Uint32 key = 0;
- Uint32 tAttr = tabPtr.p->firstAttribute;
- while (tAttr != RNIL)
+ Ptr<AttributeRecord> attrPtr;
+ LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
+ tabPtr.p->m_attributes);
+ for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr))
{
- jam();
- AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
- if (aRec->tupleKey)
+ AttributeRecord* aRec = attrPtr.p;
+ if (aRec->tupleKey)
{
+ Uint32 attr = aRec->attributeDescriptor;
+
desc->noOfKeyAttr ++;
- desc->keyAttr[key].attributeDescriptor = aRec->attributeDescriptor;
-
+ desc->keyAttr[key].attributeDescriptor = attr;
Uint32 csNumber = (aRec->extPrecision >> 16);
- if(csNumber)
+ if (csNumber)
{
- desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
- ndbrequire(all_charsets[csNumber]);
- desc->hasCharAttr = 1;
+ desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
+ ndbrequire(all_charsets[csNumber] != 0);
+ desc->hasCharAttr = 1;
}
else
{
- desc->keyAttr[key].charsetInfo = 0;
+ desc->keyAttr[key].charsetInfo = 0;
+ }
+ if (AttributeDescriptor::getDKey(attr))
+ {
+ desc->noOfDistrKeys ++;
}
- if(AttributeDescriptor::getDKey(aRec->attributeDescriptor))
+ if (AttributeDescriptor::getArrayType(attr) != NDB_ARRAYTYPE_FIXED)
{
- desc->noOfDistrKeys ++;
+ desc->noOfVarKeys ++;
}
key++;
}
- tAttr = aRec->nextAttrInTable;
}
ndbrequire(key == tabPtr.p->noOfPrimkey);
}
@@ -4532,11 +5215,11 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
// noOfCharsets passed to TUP in upper half
req->noOfNewAttr |= (tabPtr.p->noOfCharsets << 16);
req->checksumIndicator = 1;
- req->noOfAttributeGroups = 1;
req->GCPIndicator = 0;
req->startGci = startGci;
req->tableType = tabPtr.p->tableType;
req->primaryTableId = tabPtr.p->primaryTableId;
+ req->tablespace_id= tabPtr.p->m_tablespace_id;
sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
LqhFragReq::SignalLength, JBB);
}
@@ -4572,7 +5255,7 @@ Dbdict::execLQHFRAGCONF(Signal * signal){
TableRecordPtr tabPtr;
c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
- sendLQHADDATTRREQ(signal, createTabPtr, tabPtr.p->firstAttribute);
+ sendLQHADDATTRREQ(signal, createTabPtr, tabPtr.p->m_attributes.firstItem);
}
void
@@ -4596,7 +5279,7 @@ Dbdict::sendLQHADDATTRREQ(Signal* signal,
entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
if (tabPtr.p->isIndex()) {
Uint32 primaryAttrId;
- if (attrPtr.p->nextAttrInTable != RNIL) {
+ if (attrPtr.p->nextList != RNIL) {
getIndexAttr(tabPtr, attributePtrI, &primaryAttrId);
} else {
primaryAttrId = ZNIL;
@@ -4605,7 +5288,7 @@ Dbdict::sendLQHADDATTRREQ(Signal* signal,
}
entry.attrId |= (primaryAttrId << 16);
}
- attributePtrI = attrPtr.p->nextAttrInTable;
+ attributePtrI = attrPtr.p->nextList;
}
req->lqhFragPtr = createTabPtr.p->m_lqhFragPtr;
req->senderData = createTabPtr.p->key;
@@ -4734,7 +5417,6 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){
signal->theData[4] = (Uint32)tabPtr.p->tableType;
signal->theData[5] = createTabPtr.p->key;
signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
-
sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
return;
}
@@ -4891,6 +5573,13 @@ Dbdict::createTab_drop(Signal* signal, CreateTabReq * req){
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
@@ -4963,6 +5652,42 @@ Dbdict::execTC_SCHVERCONF(Signal* signal){
// 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)
@@ -5004,23 +5729,15 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
// TODO
/* ---------------------------------------------------------------- */
const Uint32 tableNameLength = strlen(tableDesc.TableName) + 1;
+ const Uint32 name_hash = Rope::hash(tableDesc.TableName, tableNameLength);
- TableRecord keyRecord;
- tabRequire(tableNameLength <= sizeof(keyRecord.tableName),
- CreateTableRef::TableNameTooLong);
- strcpy(keyRecord.tableName, tableDesc.TableName);
-
- TableRecordPtr tablePtr;
- c_tableRecordHash.find(tablePtr, keyRecord);
-
- if (checkExist){
+ if(checkExist){
jam();
- /* ---------------------------------------------------------------- */
- // Check if table already existed.
- /* ---------------------------------------------------------------- */
- tabRequire(tablePtr.i == RNIL, CreateTableRef::TableAlreadyExist);
+ tabRequire(get_object(tableDesc.TableName, tableNameLength) == 0,
+ CreateTableRef::TableAlreadyExist);
}
-
+
+ TableRecordPtr tablePtr;
switch (parseP->requestType) {
case DictTabInfo::CreateTableFromAPI: {
jam();
@@ -5061,21 +5778,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
jam();
tablePtr.p->tabState = TableRecord::DEFINING;
}//if
-#ifdef HAVE_TABLE_REORG
-/* ---------------------------------------------------------------- */
-// Get id of second table id and check that table doesn't already exist
-// and set up links between first and second table.
-/* ---------------------------------------------------------------- */
- TableRecordPtr secondTablePtr;
- secondTablePtr.i = tableDesc.SecondTableId;
- c_tableRecordPool.getPtr(secondTablePtr);
- ndbrequire(secondTablePtr.p->tabState == TableRecord::NOT_DEFINED);
-
- initialiseTableRecord(secondTablePtr);
- secondTablePtr.p->tabState = TableRecord::REORG_TABLE_PREPARED;
- secondTablePtr.p->secondTable = tablePtr.i;
- tablePtr.p->secondTable = secondTablePtr.i;
-#endif
+
/* ---------------------------------------------------------------- */
// Set table version
/* ---------------------------------------------------------------- */
@@ -5090,21 +5793,28 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
}//switch
parseP->tablePtr = tablePtr;
- strcpy(tablePtr.p->tableName, keyRecord.tableName);
+ {
+ Rope name(c_rope_pool, tablePtr.p->tableName);
+ ndbrequire(name.assign(tableDesc.TableName, tableNameLength, name_hash));
+ }
+
+ 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 = 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, version=%u",
- tablePtr.p->tableName, tablePtr.i, tablePtr.p->tableVersion);
- TableRecordPtr tmp;
- ndbrequire(!c_tableRecordHash.find(tmp, * tablePtr.p));
+ ndbout_c("Dbdict: name=%s,id=%u,obj_ptr_i=%d",
+ tableDesc.TableName, tablePtr.i, tablePtr.p->m_obj_ptr_i);
#endif
- c_tableRecordHash.add(tablePtr);
}
- //tablePtr.p->noOfPrimkey = tableDesc.NoOfKeyAttr;
- //tablePtr.p->noOfNullAttr = tableDesc.NoOfNullable;
- //tablePtr.p->tupKeyLength = tableDesc.KeyLength;
tablePtr.p->noOfAttributes = tableDesc.NoOfAttributes;
tablePtr.p->storedTable = tableDesc.TableLoggedFlag;
tablePtr.p->minLoadFactor = tableDesc.MinLoadFactor;
@@ -5113,10 +5823,13 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->tableType = (DictTabInfo::TableType)tableDesc.TableType;
tablePtr.p->kValue = tableDesc.TableKValue;
tablePtr.p->fragmentCount = tableDesc.FragmentCount;
-
- tablePtr.p->frmLen = tableDesc.FrmLen;
- memcpy(tablePtr.p->frmData, tableDesc.FrmData, tableDesc.FrmLen);
-
+ tablePtr.p->m_tablespace_id = tableDesc.TablespaceId;
+
+ {
+ Rope frm(c_rope_pool, tablePtr.p->frmData);
+ ndbrequire(frm.assign(tableDesc.FrmData, tableDesc.FrmLen));
+ }
+
tablePtr.p->ngLen = tableDesc.FragmentDataLen;
memcpy(tablePtr.p->ngData, tableDesc.FragmentData,
tableDesc.FragmentDataLen);
@@ -5140,8 +5853,8 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->buildTriggerId = RNIL;
tablePtr.p->indexLocal = 0;
- handleTabInfo(it, parseP);
-
+ handleTabInfo(it, parseP, tableDesc.TablespaceVersion);
+
if(parseP->errorCode != 0)
{
/**
@@ -5152,7 +5865,8 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
}//handleTabInfoInit()
void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
- ParseDictTabInfoRecord * parseP)
+ ParseDictTabInfoRecord * parseP,
+ Uint32 tablespaceVersion)
{
TableRecordPtr tablePtr = parseP->tablePtr;
@@ -5168,6 +5882,11 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
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++){
/**
@@ -5178,6 +5897,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
DictTabInfo::AttributeMapping,
DictTabInfo::AttributeMappingSize,
true, true);
+
if(status != SimpleProperties::Break){
parseP->errorCode = CreateTableRef::InvalidFormat;
parseP->status = status;
@@ -5189,32 +5909,45 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
/**
* Check that attribute is not defined twice
*/
- AttributeRecord tmpAttr;
+ const size_t len = strlen(attrDesc.AttributeName)+1;
+ const Uint32 name_hash = Rope::hash(attrDesc.AttributeName, len);
{
- strcpy(tmpAttr.attributeName, attrDesc.AttributeName);
+ 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);
- AttributeRecordPtr attrPtr;
- c_attributeRecordHash.find(attrPtr, tmpAttr);
-
- if(attrPtr.i != RNIL){
+ if(old_ptr.i != RNIL){
parseP->errorCode = CreateTableRef::AttributeNameTwice;
return;
}
}
- if(!getNewAttributeRecord(tablePtr, attrPtr)){
+ 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
*/
- strcpy(attrPtr.p->attributeName, attrDesc.AttributeName);
- attrPtr.p->attributeId = attrDesc.AttributeId;
+ {
+ Rope name(c_rope_pool, attrPtr.p->attributeName);
+ name.assign(attrDesc.AttributeName, len, name_hash);
+ }
+ 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;
@@ -5262,20 +5995,30 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
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::setArray(desc, attrDesc.AttributeArraySize);
+ 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;
- strcpy(attrPtr.p->defaultValue, attrDesc.AttributeDefaultValue);
-
- tabRequire(attrDesc.AttributeId == i, CreateTableRef::InvalidFormat);
+ {
+ Rope defaultValue(c_rope_pool, attrPtr.p->defaultValue);
+ defaultValue.assign(attrDesc.AttributeDefaultValue);
+ }
- attrCount ++;
keyCount += attrDesc.AttributeKeyFlag;
nullCount += attrDesc.AttributeNullableFlag;
@@ -5313,8 +6056,21 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
}
}
- if (parseP->requestType != DictTabInfo::AlterTableFromAPI)
- c_attributeRecordHash.add(attrPtr);
+ 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;
@@ -5335,7 +6091,25 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
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 != tablespaceVersion)
+ {
+ tabRequire(false, CreateTableRef::InvalidTablespaceVersion);
+ }
+ }
}//handleTabInfo()
@@ -5863,6 +6637,13 @@ Dbdict::execDROP_TAB_REQ(Signal* signal){
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>
@@ -6030,35 +6811,26 @@ Dbdict::dropTab_writeSchemaConf(Signal* signal,
void Dbdict::releaseTableObject(Uint32 tableId, bool removeFromHash)
{
TableRecordPtr tablePtr;
- AttributeRecordPtr attrPtr;
c_tableRecordPool.getPtr(tablePtr, tableId);
- if (removeFromHash)
- {
-#ifdef VM_TRACE
- TableRecordPtr tmp;
- ndbrequire(c_tableRecordHash.find(tmp, * tablePtr.p));
-#endif
- c_tableRecordHash.remove(tablePtr);
+ if (removeFromHash){
+ jam();
+ release_object(tablePtr.p->m_obj_ptr_i);
}
+
+ Rope frm(c_rope_pool, tablePtr.p->frmData);
+ frm.erase();
tablePtr.p->tabState = TableRecord::NOT_DEFINED;
-
- Uint32 nextAttrRecord = tablePtr.p->firstAttribute;
- while (nextAttrRecord != RNIL) {
- jam();
-/* ---------------------------------------------------------------- */
-// Release all attribute records
-/* ---------------------------------------------------------------- */
- c_attributeRecordPool.getPtr(attrPtr, nextAttrRecord);
- nextAttrRecord = attrPtr.p->nextAttrInTable;
- c_attributeRecordPool.release(attrPtr);
- }//if
-#ifdef HAVE_TABLE_REORG
- Uint32 secondTableId = tablePtr.p->secondTable;
- initialiseTableRecord(tablePtr);
- c_tableRecordPool.getPtr(tablePtr, secondTableId);
- initialiseTableRecord(tablePtr);
-#endif
- return;
+
+ 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()
/**
@@ -6122,36 +6894,29 @@ void Dbdict::execGET_TABLEDID_REQ(Signal * signal)
}
char tableName[MAX_TAB_NAME_SIZE];
- TableRecord keyRecord;
SegmentedSectionPtr ssPtr;
signal->getSection(ssPtr,GetTableIdReq::TABLE_NAME);
copy((Uint32*)tableName, ssPtr);
- strcpy(keyRecord.tableName, tableName);
releaseSections(signal);
-
- if(len > sizeof(keyRecord.tableName)){
- jam();
- sendGET_TABLEID_REF((Signal*)signal,
- (GetTableIdReq *)req,
- GetTableIdRef::TableNameTooLong);
- return;
- }
-
- TableRecordPtr tablePtr;
- if(!c_tableRecordHash.find(tablePtr, keyRecord)) {
+
+ 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*)signal,
+ 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;
+ conf->tableId = tablePtr.p->tableId;
+ conf->schemaVersion = tablePtr.p->tableVersion;
+ conf->senderData = senderData;
sendSignal(senderRef, GSN_GET_TABLEID_CONF, signal,
GetTableIdConf::SignalLength, JBB);
-
}
@@ -6220,15 +6985,14 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal)
const bool useLongSig = (req->requestType & GetTabInfoReq::LongSignalConf);
const Uint32 reqType = req->requestType & (~GetTabInfoReq::LongSignalConf);
-
- TableRecordPtr tablePtr;
+
+ Uint32 obj_id = RNIL;
if(reqType == GetTabInfoReq::RequestByName){
jam();
ndbrequire(signal->getNoOfSections() == 1);
const Uint32 len = req->tableNameLen;
- TableRecord keyRecord;
- if(len > sizeof(keyRecord.tableName)){
+ if(len > MAX_TAB_NAME_SIZE){
jam();
releaseSections(signal);
sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNameTooLong);
@@ -6240,33 +7004,37 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal)
signal->getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
r0.reset(); // undo implicit first()
- if(r0.getWords((Uint32*)tableName, ((len + 3)/4)))
- memcpy(keyRecord.tableName, tableName, len);
- else {
+ if(!r0.getWords((Uint32*)tableName, (len+3)/4)){
jam();
releaseSections(signal);
sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
return;
}
releaseSections(signal);
- // memcpy(keyRecord.tableName, req->tableName, len);
- //ntohS(&keyRecord.tableName[0], len);
-
- c_tableRecordHash.find(tablePtr, keyRecord);
+
+ DictObject * old_ptr_p = old_ptr_p = get_object(tableName, len);
+ if(old_ptr_p)
+ obj_id = old_ptr_p->m_id;
} else {
jam();
- c_tableRecordPool.getPtr(tablePtr, req->tableId, false);
+ 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(tablePtr.i == RNIL){
+ if(objEntry == 0){
jam();
- sendGET_TABINFOREF(signal, req, GetTabInfoRef::InvalidTableId);
+ sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
return;
}//if
- if (! (tablePtr.p->tabState == TableRecord::DEFINED ||
- tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)) {
+ if (objEntry->m_tableState != SchemaFile::TABLE_ADD_COMMITTED &&
+ objEntry->m_tableState != SchemaFile::ALTER_TABLE_COMMITTED){
jam();
sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
return;
@@ -6275,16 +7043,34 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal)
c_retrieveRecord.busyState = true;
c_retrieveRecord.blockRef = req->senderRef;
c_retrieveRecord.m_senderData = req->senderData;
- c_retrieveRecord.tableId = tablePtr.i;
+ 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;
-
- signal->theData[0] = ZPACK_TABLE_INTO_PAGES;
- signal->theData[1] = tablePtr.i;
- signal->theData[2] = c_retrieveRecord.retrievePage;
- sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
+
+ if(objEntry->m_tableType==DictTabInfo::Datafile)
+ {
+ jam();
+ GetTabInfoReq *req= (GetTabInfoReq*)signal->theData;
+ 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
+ {
+ 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)
@@ -6306,7 +7092,8 @@ void Dbdict::sendGetTabResponse(Signal* signal)
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;
@@ -6340,18 +7127,6 @@ void Dbdict::sendGET_TABINFOREF(Signal* signal,
sendSignal(retRef, GSN_GET_TABINFOREF, signal, signal->length(), JBB);
}//sendGET_TABINFOREF()
-Uint32 convertEndian(Uint32 in) {
-#ifdef WORDS_BIGENDIAN
- Uint32 ut = 0;
- ut += ((in >> 24) & 255);
- ut += (((in >> 16) & 255) << 8);
- ut += (((in >> 8) & 255) << 16);
- ut += ((in & 255) << 24);
- return ut;
-#else
- return in;
-#endif
-}
void
Dbdict::execLIST_TABLES_REQ(Signal* signal)
{
@@ -6370,144 +7145,125 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
conf->senderData = senderData;
conf->counter = 0;
Uint32 pos = 0;
- for (i = 0; i < c_tableRecordPool.getSize(); i++) {
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, i);
- // filter
- if (tablePtr.p->tabState == TableRecord::NOT_DEFINED ||
- tablePtr.p->tabState == TableRecord::REORG_TABLE_PREPARED)
- continue;
-
- if ((reqTableType != (Uint32)0) && (reqTableType != (unsigned)tablePtr.p->tableType))
+ 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 && reqTableId != tablePtr.p->primaryTableId)
+
+ if (reqListIndexes && !DictTabInfo::isIndex(type))
continue;
- conf->tableData[pos] = 0;
- // id
- conf->setTableId(pos, tablePtr.i);
- // type
- conf->setTableType(pos, tablePtr.p->tableType);
- // state
- if (tablePtr.p->isTable()) {
- switch (tablePtr.p->tabState) {
- case TableRecord::DEFINING:
- case TableRecord::CHECKED:
- 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;
+
+ 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:
+ case TableRecord::CHECKED:
+ 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;
+ }
+ }
+ // store
+ if (! tablePtr.p->storedTable) {
+ conf->setTableStore(pos, DictTabInfo::StoreTemporary);
+ } else {
+ conf->setTableStore(pos, DictTabInfo::StorePermanent);
+ }
+ pos++;
}
- 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;
+ 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->setTableState(pos, DictTabInfo::StateBroken);
+ break;
}
- }
- // store
- if (! tablePtr.p->storedTable) {
conf->setTableStore(pos, DictTabInfo::StoreTemporary);
- } else {
- conf->setTableStore(pos, DictTabInfo::StorePermanent);
- }
- pos++;
- if (pos >= ListTablesConf::DataLength) {
- sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::SignalLength, JBB);
- conf->counter++;
- pos = 0;
- }
- if (! reqListNames)
- continue;
- const Uint32 size = strlen(tablePtr.p->tableName) + 1;
- conf->tableData[pos] = size;
- pos++;
- if (pos >= ListTablesConf::DataLength) {
- sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::SignalLength, JBB);
- conf->counter++;
- pos = 0;
+ pos++;
}
- Uint32 k = 0;
- while (k < size) {
- char* p = (char*)&conf->tableData[pos];
- for (Uint32 j = 0; j < 4; j++) {
- if (k < size)
- *p++ = tablePtr.p->tableName[k++];
- else
- *p++ = 0;
- }
+ if (DictTabInfo::isFilegroup(type)){
+ jam();
+ conf->tableData[pos] = 0;
+ conf->setTableId(pos, iter.curr.p->m_id);
+ conf->setTableType(pos, type); // type
pos++;
- if (pos >= ListTablesConf::DataLength) {
- sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::SignalLength, JBB);
- conf->counter++;
- pos = 0;
- }
}
- }
- // XXX merge with above somehow
- for (i = 0; i < c_triggerRecordPool.getSize(); i++) {
- if (reqListIndexes)
- break;
- TriggerRecordPtr triggerPtr;
- c_triggerRecordPool.getPtr(triggerPtr, i);
- if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED)
- continue;
- // constant 10 hardcoded
- Uint32 type = 10 + triggerPtr.p->triggerType;
- if (reqTableType != 0 && reqTableType != type)
- continue;
- 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;
+ if (DictTabInfo::isFile(type)){
+ jam();
+ conf->tableData[pos] = 0;
+ conf->setTableId(pos, iter.curr.p->m_id);
+ conf->setTableType(pos, type); // type
+ pos++;
}
- conf->setTableStore(pos, DictTabInfo::StoreTemporary);
- pos++;
+
if (pos >= ListTablesConf::DataLength) {
sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
- ListTablesConf::SignalLength, JBB);
+ ListTablesConf::SignalLength, JBB);
conf->counter++;
pos = 0;
}
+
if (! reqListNames)
continue;
- const Uint32 size = strlen(triggerPtr.p->triggerName) + 1;
+
+ Rope name(c_rope_pool, iter.curr.p->m_name);
+ const Uint32 size = name.size();
conf->tableData[pos] = size;
pos++;
if (pos >= ListTablesConf::DataLength) {
@@ -6516,21 +7272,23 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
conf->counter++;
pos = 0;
}
- Uint32 k = 0;
- while (k < size) {
+ 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 (k < size)
- *p++ = triggerPtr.p->triggerName[k++];
- else
- *p++ = 0;
+ 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;
+ sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
+ ListTablesConf::SignalLength, JBB);
+ conf->counter++;
+ pos = 0;
}
}
}
@@ -6771,8 +7529,13 @@ Dbdict::createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr)
void
Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
{
- Uint32 attrid_map[MAX_ATTRIBUTES_IN_INDEX];
+ 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
@@ -6836,6 +7599,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
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;
@@ -6846,13 +7610,16 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
jam();
unsigned current_id= opPtr.p->m_attrList.id[k];
- AttributeRecord* aRec= NULL;
- Uint32 tAttr= tablePtr.p->firstAttribute;
- for (; tAttr != RNIL; tAttr= aRec->nextAttrInTable)
+ Uint32 tAttr = tablePtr.p->m_attributes.firstItem;
+ AttributeRecord* aRec = NULL;
+ for (; tAttr != RNIL; )
{
aRec = c_attributeRecordPool.getPtr(tAttr);
if (aRec->attributeId != current_id)
- continue;
+ {
+ tAttr= aRec->nextList;
+ continue;
+ }
jam();
break;
}
@@ -6869,21 +7636,29 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
opPtr.p->m_errorLine = __LINE__;
return;
}
- mask.set(current_id);
-
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;
- // reorder the attributes according to the tableid order
- // for unque indexes
+
for (; kk > 0 && current_id < attrid_map[kk-1]>>16; kk--)
attrid_map[kk]= attrid_map[kk-1];
}
attrid_map[kk]= k | (current_id << 16);
}
+
indexPtr.p->noOfPrimkey = indexPtr.p->noOfAttributes;
// plus concatenated primary table key attribute
indexPtr.p->noOfAttributes += 1;
@@ -6893,15 +7668,15 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
w.add(DictTabInfo::TableLoggedFlag, indexPtr.p->storedTable);
w.add(DictTabInfo::FragmentTypeVal, indexPtr.p->fragmentType);
w.add(DictTabInfo::TableTypeVal, indexPtr.p->tableType);
- w.add(DictTabInfo::PrimaryTable, tablePtr.p->tableName);
+ 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);
// write index key attributes
- AttributeRecordPtr aRecPtr;
- c_attributeRecordPool.getPtr(aRecPtr, tablePtr.p->firstAttribute);
for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
// insert the attributes in the order decided above in attrid_map
// k is new order, current_id is in previous order
@@ -6909,16 +7684,20 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
// passed up to NdbDictionary
unsigned current_id= opPtr.p->m_attrList.id[attrid_map[k] & 0xffff];
jam();
- for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
+ for (Uint32 tAttr = tablePtr.p->m_attributes.firstItem; tAttr != RNIL; ) {
AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
- tAttr = aRec->nextAttrInTable;
+ 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);
- w.add(DictTabInfo::AttributeName, aRec->attributeName);
+ // computed
w.add(DictTabInfo::AttributeId, k);
if (indexPtr.p->isHashIndex()) {
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
@@ -6928,6 +7707,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
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);
@@ -6937,9 +7717,26 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
}
if (indexPtr.p->isHashIndex()) {
jam();
- // write concatenated primary table key attribute
+
+ 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);
@@ -6951,6 +7748,8 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
// 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);
@@ -7139,24 +7938,28 @@ Dbdict::execDROP_INDX_REQ(Signal* signal)
// forward initial request plus operation key to all
Uint32 indexId= req->getIndexId();
Uint32 indexVersion= req->getIndexVersion();
- TableRecordPtr tmp;
- int res = getMetaTablePtr(tmp, indexId, indexVersion);
- switch(res){
- case MetaData::InvalidArgument:
+
+ if(indexId >= c_tableRecordPool.getSize())
+ {
err = DropIndxRef::IndexNotFound;
goto error;
- case MetaData::TableNotFound:
- case MetaData::InvalidTableVersion:
+ }
+
+ 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);
@@ -7165,7 +7968,7 @@ Dbdict::execDROP_INDX_REQ(Signal* signal)
req->setOpKey(++c_opRecordSequence);
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
sendSignal(rg, GSN_DROP_INDX_REQ,
- signal, DropIndxReq::SignalLength + 1, JBB);
+ signal, DropIndxReq::SignalLength + 1, JBB);
return;
}
// seize operation record
@@ -7604,18 +8407,18 @@ Dbdict::prepareTransactionEventSysTable (Callback *pcallback,
UtilPrepareReq::OperationTypeValue prepReq)
{
// find table id for event system table
- TableRecord keyRecord;
- strcpy(keyRecord.tableName, EVENT_SYSTEM_TABLE_NAME);
+ DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
+ sizeof(EVENT_SYSTEM_TABLE_NAME));
+ ndbrequire(opj_ptr_p != 0);
TableRecordPtr tablePtr;
- c_tableRecordHash.find(tablePtr, keyRecord);
-
+ 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:
@@ -8320,13 +9123,8 @@ void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
evntRecPtr.p->m_eventRec.TABLEVERSION));
// find table id for event table
- TableRecord keyRecord;
- strcpy(keyRecord.tableName, evntRecPtr.p->m_eventRec.TABLE_NAME);
-
- TableRecordPtr tablePtr;
- c_tableRecordHash.find(tablePtr, keyRecord);
-
- if (tablePtr.i == RNIL) {
+ 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__;
@@ -8336,6 +9134,8 @@ void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
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);
@@ -10841,21 +11641,14 @@ Dbdict::execCREATE_TRIG_REQ(Signal* signal)
}
}
releaseSections(signal);
- {
- // check that trigger name is unique
- TriggerRecordPtr triggerPtr;
- TriggerRecord keyRecord;
- strcpy(keyRecord.triggerName, opPtr.p->m_triggerName);
- c_triggerRecordHash.find(triggerPtr, keyRecord);
- if (triggerPtr.i != RNIL) {
- jam();
- opPtr.p->m_errorCode = CreateTrigRef::TriggerExists;
- opPtr.p->m_errorLine = __LINE__;
- createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
- return;
- }
+ 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;
@@ -11084,7 +11877,10 @@ Dbdict::createTrigger_slaveCreate(Signal* signal, OpCreateTriggerPtr opPtr)
c_triggerRecordPool.getPtr(triggerPtr, triggerId);
initialiseTriggerRecord(triggerPtr);
// fill in trigger data
- strcpy(triggerPtr.p->triggerName, opPtr.p->m_triggerName);
+ {
+ Rope name(c_rope_pool, triggerPtr.p->triggerName);
+ ndbrequire(name.assign(opPtr.p->m_triggerName));
+ }
triggerPtr.p->triggerId = triggerId;
triggerPtr.p->tableId = req->getTableId();
triggerPtr.p->indexId = RNIL;
@@ -11097,7 +11893,16 @@ Dbdict::createTrigger_slaveCreate(Signal* signal, OpCreateTriggerPtr opPtr)
triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
// add to hash table
// ndbout_c("++++++++++++ Adding trigger id %u, %s", triggerPtr.p->triggerId, triggerPtr.p->triggerName);
- c_triggerRecordHash.add(triggerPtr);
+ {
+ 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();
@@ -11261,7 +12066,7 @@ Dbdict::execDROP_TRIG_REQ(Signal* signal)
if (signal->getNoOfSections() > 0) {
ndbrequire(signal->getNoOfSections() == 1);
jam();
- TriggerRecord keyRecord;
+ char triggerName[MAX_TAB_NAME_SIZE];
OpDropTrigger opTmp;
opPtr.p=&opTmp;
@@ -11269,7 +12074,7 @@ Dbdict::execDROP_TRIG_REQ(Signal* signal)
signal->getSection(ssPtr, DropTrigReq::TRIGGER_NAME_SECTION);
SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
if (ssReader.getKey() != DropTrigReq::TriggerNameKey ||
- ! ssReader.getString(keyRecord.triggerName)) {
+ ! ssReader.getString(triggerName)) {
jam();
opPtr.p->m_errorCode = DropTrigRef::InvalidName;
opPtr.p->m_errorLine = __LINE__;
@@ -11279,16 +12084,16 @@ Dbdict::execDROP_TRIG_REQ(Signal* signal)
}
releaseSections(signal);
- TriggerRecordPtr triggerPtr;
-
- // ndbout_c("++++++++++++++ Looking for trigger %s", keyRecord.triggerName);
- c_triggerRecordHash.find(triggerPtr, keyRecord);
- if (triggerPtr.i == RNIL) {
+ //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);
+ //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);
}
@@ -11558,9 +12363,9 @@ Dbdict::dropTrigger_slaveCommit(Signal* signal, OpDropTriggerPtr opPtr)
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);
- c_triggerRecordHash.remove(triggerPtr);
+ //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;
}
@@ -12134,12 +12939,15 @@ Dbdict::getTableKeyList(TableRecordPtr tablePtr,
jam();
list.sz = 0;
list.id[list.sz++] = AttributeHeader::FRAGMENT;
- for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
- AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
- if (aRec->tupleKey)
- list.id[list.sz++] = aRec->attributeId;
- tAttr = aRec->nextAttrInTable;
+ 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 == tablePtr.p->noOfPrimkey + 1);
ndbrequire(list.sz <= MAX_ATTRIBUTES_IN_INDEX + 1);
}
@@ -12148,16 +12956,27 @@ 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);
- for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
- AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
- if (iaRec->equal(*aRec)) {
- id[0] = aRec->attributeId;
+ {
+ 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;
}
- tAttr = aRec->nextAttrInTable;
}
ndbrequire(false);
}
@@ -12166,34 +12985,39 @@ void
Dbdict::getIndexAttrList(TableRecordPtr indexPtr, AttributeList& list)
{
jam();
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
list.sz = 0;
memset(list.id, 0, sizeof(list.id));
ndbrequire(indexPtr.p->noOfAttributes >= 2);
- Uint32 itAttr = indexPtr.p->firstAttribute;
- for (Uint32 i = 0; i < (Uint32)indexPtr.p->noOfAttributes - 1; i++) {
- getIndexAttr(indexPtr, itAttr, &list.id[list.sz++]);
- AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
- itAttr = iaRec->nextAttrInTable;
+
+ 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();
- TableRecordPtr tablePtr;
- c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
mask.clear();
ndbrequire(indexPtr.p->noOfAttributes >= 2);
- Uint32 itAttr = indexPtr.p->firstAttribute;
- for (Uint32 i = 0; i < (Uint32)indexPtr.p->noOfAttributes - 1; i++) {
+
+ 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, itAttr, &id);
+ getIndexAttr(indexPtr, currPtr.i, &id);
mask.set(id);
- AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
- itAttr = iaRec->nextAttrInTable;
}
}
@@ -12298,107 +13122,2146 @@ Dbdict::getTableEntry(XSchemaFile * xsf, Uint32 tableId)
return &sf->TableEntries[i];
}
-// global metadata support
+//******************************************
+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 {
+ Ptr<SchemaTransaction> trans_ptr;
+ if (! c_Trans.seize(trans_ptr)){
+ ref->errorCode = CreateFileRef::Busy;
+ ref->status = 0;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ 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;
-int
-Dbdict::getMetaTablePtr(TableRecordPtr& tablePtr, Uint32 tableId, Uint32 tableVersion)
+ {
+ Uint32 objId = getFreeObjId(0);
+ if (objId == RNIL) {
+ 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);
+ 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 {
+ Ptr<SchemaTransaction> trans_ptr;
+ if (! c_Trans.seize(trans_ptr)){
+ ref->errorCode = CreateFilegroupRef::Busy;
+ ref->status = 0;
+ ref->errorKey = 0;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ 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;
+ }
+
+ 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) {
+ 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);
+ 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)
{
- if (tableId >= c_tableRecordPool.getSize()) {
- return MetaData::InvalidArgument;
+ jamEntry();
+
+ if(!assembleFragments(signal)){
+ jam();
+ return;
}
- c_tableRecordPool.getPtr(tablePtr, tableId);
- if (tablePtr.p->tabState == TableRecord::NOT_DEFINED) {
- return MetaData::TableNotFound;
- }
- if (tablePtr.p->tableVersion != tableVersion) {
- return MetaData::InvalidTableVersion;
- }
- // online flag is not maintained by DICT
- tablePtr.p->online =
- tablePtr.p->isTable() &&
- (tablePtr.p->tabState == TableRecord::DEFINED ||
- tablePtr.p->tabState == TableRecord::BACKUP_ONGOING) ||
- tablePtr.p->isIndex() && tablePtr.p->indexState == TableRecord::IS_ONLINE;
- return 0;
+
+ 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 {
+ Ptr<File> file_ptr;
+ if (!c_file_hash.find(file_ptr, objId))
+ {
+ ref->errorCode = DropFileRef::NoSuchFile;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ Ptr<SchemaTransaction> trans_ptr;
+ if (! c_Trans.seize(trans_ptr))
+ {
+ ref->errorCode = CreateFileRef::Busy;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ 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);
+ return;
+ } while(0);
+
+ ref->senderData = senderData;
+ ref->masterNodeId = c_masterNodeId;
+ sendSignal(senderRef, GSN_DROP_FILE_REF,signal,
+ DropFileRef::SignalLength, JBB);
}
-int
-Dbdict::getMetaTable(MetaData::Table& table, Uint32 tableId, Uint32 tableVersion)
+void
+Dbdict::execDROP_FILEGROUP_REQ(Signal* signal)
{
- int ret;
- TableRecordPtr tablePtr;
- if ((ret = getMetaTablePtr(tablePtr, tableId, tableVersion)) < 0) {
- return ret;
+ jamEntry();
+
+ if(!assembleFragments(signal)){
+ jam();
+ return;
}
- new (&table) MetaData::Table(*tablePtr.p);
- return 0;
+
+ 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 {
+ Ptr<Filegroup> filegroup_ptr;
+ if (!c_filegroup_hash.find(filegroup_ptr, objId))
+ {
+ ref->errorCode = DropFilegroupRef::NoSuchFilegroup;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ Ptr<SchemaTransaction> trans_ptr;
+ if (! c_Trans.seize(trans_ptr))
+ {
+ ref->errorCode = CreateFilegroupRef::Busy;
+ ref->errorLine = __LINE__;
+ break;
+ }
+
+ 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);
+ return;
+ } while(0);
+
+ ref->senderData = senderData;
+ ref->masterNodeId = c_masterNodeId;
+ sendSignal(senderRef, GSN_DROP_FILEGROUP_REF,signal,
+ DropFilegroupRef::SignalLength, JBB);
}
-int
-Dbdict::getMetaTable(MetaData::Table& table, const char* tableName)
+void
+Dbdict::execCREATE_OBJ_REF(Signal* signal){
+ jamEntry();
+
+ CreateObjRef * const ref = (CreateObjRef*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
+
+ if(ref->errorCode != CreateObjRef::NF_FakeErrorREF){
+ 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){
+ jamEntry();
+
+ CreateObjConf * const conf = (CreateObjConf*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ 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)
{
- int ret;
- TableRecordPtr tablePtr;
- if (strlen(tableName) + 1 > MAX_TAB_NAME_SIZE) {
- return MetaData::InvalidArgument;
+ {
+ SafeCounter tmp(c_counterMgr, trans_ptr_p->m_counter);
+ if(!tmp.clearWaitingFor(nodeId)){
+ jam();
+ return;
+ }
}
- TableRecord keyRecord;
- strcpy(keyRecord.tableName, tableName);
- c_tableRecordHash.find(tablePtr, keyRecord);
- if (tablePtr.i == RNIL) {
- return MetaData::TableNotFound;
+
+ switch(trans_ptr_p->m_op.m_state){
+ case DictObjOp::Preparing:{
+
+ if(trans_ptr_p->m_errorCode != 0)
+ {
+ jam();
+ /**
+ * 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)
+ (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_start)
+ (signal, trans_ptr_p);
+ else
+ 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)
+ (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_start)
+ (signal, trans_ptr_p);
+ else
+ execute(signal, trans_ptr_p->m_callback, 0);
+ return;
}
- if ((ret = getMetaTablePtr(tablePtr, tablePtr.i, tablePtr.p->tableVersion)) < 0) {
- return ret;
+ case DictObjOp::Committing: {
+ jam();
+ 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)
+ (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_complete)
+ (signal, trans_ptr_p);
+ else
+ execute(signal, trans_ptr_p->m_callback, 0);
+ return;
}
- new (&table) MetaData::Table(*tablePtr.p);
- return 0;
+ case DictObjOp::Aborting:{
+ jam();
+
+ 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)
+ (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_complete)
+ (signal, trans_ptr_p);
+ else
+ execute(signal, trans_ptr_p->m_callback, 0);
+ return;
+ }
+ case DictObjOp::Defined:
+ case DictObjOp::Prepared:
+ case DictObjOp::Committed:
+ case DictObjOp::Aborted:
+ break;
+ }
+ ndbrequire(false);
}
-int
-Dbdict::getMetaAttribute(MetaData::Attribute& attr, const MetaData::Table& table, Uint32 attributeId)
+void
+Dbdict::trans_commit_start_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 retValue){
+ jamEntry();
+
+ ndbrequire(retValue == 0);
+
+ Ptr<SchemaTransaction> trans_ptr;
+ 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){
+ jamEntry();
+
+ ndbrequire(retValue == 0);
+
+ Ptr<SchemaTransaction> trans_ptr;
+ 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;
+ 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;
+ 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;
+
+ //@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();
+ 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();
+ 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);
+ c_blockState = BS_IDLE;
+ return;
+}
+
+void
+Dbdict::trans_abort_start_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 retValue){
+ jamEntry();
+
+ ndbrequire(retValue == 0);
+
+ Ptr<SchemaTransaction> trans_ptr;
+ 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){
+ jamEntry();
+
+ ndbrequire(retValue == 0);
+
+ Ptr<SchemaTransaction> trans_ptr;
+ 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();
+ 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();
+ 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();
+ 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();
+ 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);
+ 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_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:
+ createObjPtr.p->m_vt_index = 0;
+ break;
+ case DictTabInfo::Datafile:
+ case DictTabInfo::Undofile:
+ /**
+ * Use restart code to impl. ForceCreateFile
+ */
+ if (requestInfo & CreateFileReq::ForceCreateFile)
+ createObjPtr.p->m_restart= 2;
+ 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)
{
- int ret;
- TableRecordPtr tablePtr;
- if ((ret = getMetaTablePtr(tablePtr, table.tableId, table.tableVersion)) < 0) {
- return ret;
+ DictCommitReq* req = (DictCommitReq*)signal->getDataPtr();
+
+ Ptr<SchemaOp> op;
+ 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;
+ 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){
+ jamEntry();
+
+ DictCommitRef * const ref = (DictCommitRef*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
+
+ if(ref->errorCode != DictCommitRef::NF_FakeErrorREF){
+ trans_ptr.p->setErrorCode(ref->errorCode);
}
- AttributeRecordPtr attrPtr;
- attrPtr.i = tablePtr.p->firstAttribute;
- while (attrPtr.i != RNIL) {
- c_attributeRecordPool.getPtr(attrPtr);
- if (attrPtr.p->attributeId == attributeId)
- break;
- attrPtr.i = attrPtr.p->nextAttrInTable;
+ Uint32 node = refToNode(ref->senderRef);
+ schemaOp_reply(signal, trans_ptr.p, node);
+}
+
+void
+Dbdict::execDICT_COMMIT_CONF(Signal* signal){
+ jamEntry();
+
+ DictCommitConf * const conf = (DictCommitConf*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
+ schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
+}
+
+void
+Dbdict::execDICT_ABORT_REF(Signal* signal){
+ jamEntry();
+
+ DictAbortRef * const ref = (DictAbortRef*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
+
+ if(ref->errorCode != DictAbortRef::NF_FakeErrorREF){
+ trans_ptr.p->setErrorCode(ref->errorCode);
}
- if (attrPtr.i == RNIL) {
- return MetaData::AttributeNotFound;
+ Uint32 node = refToNode(ref->senderRef);
+ schemaOp_reply(signal, trans_ptr.p, node);
+}
+
+void
+Dbdict::execDICT_ABORT_CONF(Signal* signal){
+ jamEntry();
+
+ DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ 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){
+
+ ndbrequire(returnCode == 0);
+
+ CreateObjRecordPtr createObjPtr;
+ ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
+
+ SegmentedSectionPtr objInfoPtr;
+ 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;
}
- new (&attr) MetaData::Attribute(*attrPtr.p);
- return 0;
+
+ 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);
}
-int
-Dbdict::getMetaAttribute(MetaData::Attribute& attr, const MetaData::Table& table, const char* attributeName)
+void
+Dbdict::createObj_writeSchemaConf1(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode){
+ jam();
+
+ ndbrequire(returnCode == 0);
+
+ CreateObjRecordPtr createObjPtr;
+ ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
+
+ Callback callback;
+ callback.m_callbackData = createObjPtr.p->key;
+ callback.m_callbackFunction = safe_cast(&Dbdict::createObj_writeObjConf);
+
+ SegmentedSectionPtr objInfoPtr;
+ 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){
+ jam();
+
+ ndbrequire(returnCode == 0);
+
+ CreateObjRecordPtr createObjPtr;
+ 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){
+ jam();
+
+ ndbrequire(returnCode == 0);
+
+ CreateObjRecordPtr createObjPtr;
+ 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){
+ jam();
+
+ 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)
+ (this->*f_dict_op[createObj->m_vt_index].m_commit_start)(signal, createObj);
+ else
+ execute(signal, createObj->m_callback, 0);
+}
+
+void
+Dbdict::createObj_commit_start_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode){
+
+ jam();
+
+ ndbrequire(returnCode == 0);
+
+ CreateObjRecordPtr createObjPtr;
+ 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){
+ jam();
+
+ 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)
+ (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::createObj_commit_complete_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode){
+ jam();
+
+ CreateObjRecordPtr createObjPtr;
+ 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)
{
- int ret;
- TableRecordPtr tablePtr;
- if ((ret = getMetaTablePtr(tablePtr, table.tableId, table.tableVersion)) < 0) {
- return ret;
+ jam();
+
+ 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)
+ (this->*f_dict_op[createObj->m_vt_index].m_abort_start)(signal, createObj);
+ else
+ execute(signal, createObj->m_callback, 0);
+}
+
+void
+Dbdict::createObj_abort_start_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode){
+ jam();
+
+ CreateObjRecordPtr createObjPtr;
+ 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)
+{
+ jam();
+
+ 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)
+ (this->*f_dict_op[createObjPtr.p->m_vt_index].m_abort_complete)
+ (signal, createObjPtr.p);
+ else
+ execute(signal, createObjPtr.p->m_callback, 0);
+}
+
+void
+Dbdict::createObj_abort_complete_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode)
+{
+ jam();
+
+ CreateObjRecordPtr createObjPtr;
+ 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;
}
- AttributeRecordPtr attrPtr;
- attrPtr.i = tablePtr.p->firstAttribute;
- while (attrPtr.i != RNIL) {
- c_attributeRecordPool.getPtr(attrPtr);
- if (strcmp(attrPtr.p->attributeName, attributeName) == 0)
+
+ DropObjReq * const req = (DropObjReq*)signal->getDataPtr();
+
+ const Uint32 objId = req->objId;
+ const Uint32 objVersion = req->objVersion;
+ const Uint32 objType = req->objType;
+ const Uint32 requestInfo = req->requestInfo;
+
+ 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:
+ {
+ dropObjPtr.p->m_vt_index = 3;
+ Ptr<Filegroup> fg_ptr;
+ ndbrequire(c_filegroup_hash.find(fg_ptr, objId));
+ dropObjPtr.p->m_obj_ptr_i = fg_ptr.i;
+ break;
+
+ }
+ case DictTabInfo::Datafile:
+ {
+ dropObjPtr.p->m_vt_index = 2;
+ Ptr<File> file_ptr;
+ ndbrequire(c_file_hash.find(file_ptr, objId));
+ dropObjPtr.p->m_obj_ptr_i = file_ptr.i;
+ break;
+ }
+ case DictTabInfo::Undofile:
+ 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)
+{
+ ndbrequire(returnCode == 0);
+
+ DropObjRecordPtr dropObjPtr;
+ ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
+
+ Callback cb;
+ 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;
+ }
+
+ 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)
+{
+ ndbrequire(returnCode == 0);
+
+ DropObjRecordPtr dropObjPtr;
+ 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)
+ (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::dropObj_prepare_complete_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode)
+{
+ ndbrequire(returnCode == 0);
+
+ DropObjRecordPtr dropObjPtr;
+ ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
+
+ //@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){
+ jam();
+
+ 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)
+ (this->*f_dict_op[dropObj->m_vt_index].m_commit_start)(signal, dropObj);
+ else
+ execute(signal, dropObj->m_callback, 0);
+}
+
+void
+Dbdict::dropObj_commit_start_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode)
+{
+ jam();
+ ndbrequire(returnCode == 0);
+
+ DropObjRecordPtr dropObjPtr;
+ 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)
+{
+ jam();
+ ndbrequire(returnCode == 0);
+
+ DropObjRecordPtr dropObjPtr;
+ 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)
+ (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::dropObj_commit_complete_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode)
+{
+ DropObjRecordPtr dropObjPtr;
+ 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){
+ jam();
+
+ 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)
+ (this->*f_dict_op[dropObj->m_vt_index].m_abort_start)(signal, dropObj);
+ else
+ execute(signal, dropObj->m_callback, 0);
+}
+
+void
+Dbdict::dropObj_abort_start_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode)
+{
+ jam();
+ ndbrequire(returnCode == 0);
+
+ DropObjRecordPtr dropObjPtr;
+ 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
+ {
+ execute(signal, callback, 0);
+ }
+}
+
+void
+Dbdict::dropObj_abort_writeSchemaConf(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode)
+{
+ jam();
+ ndbrequire(returnCode == 0);
+
+ DropObjRecordPtr dropObjPtr;
+ 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)
+ (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_abort_complete)
+ (signal, dropObjPtr.p);
+ else
+ execute(signal, dropObjPtr.p->m_callback, 0);
+}
+
+void
+Dbdict::dropObj_abort_complete_done(Signal* signal,
+ Uint32 callbackData,
+ Uint32 returnCode)
+{
+ DropObjRecordPtr dropObjPtr;
+ ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
+
+ DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
+ 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;
+ getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
+ SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
+
+ SimpleProperties::UnpackStatus status;
+ DictFilegroupInfo::Filegroup fg; fg.init();
+ do {
+ status = SimpleProperties::unpack(it, &fg,
+ DictFilegroupInfo::Mapping,
+ DictFilegroupInfo::MappingSize,
+ true, true);
+
+ if(status != SimpleProperties::Eof)
+ {
+ op->m_errorCode = CreateTableRef::InvalidFormat;
break;
- attrPtr.i = attrPtr.p->nextAttrInTable;
+ }
+
+ if(fg.FilegroupType == DictTabInfo::Tablespace)
+ {
+ if(!fg.TS_ExtentSize)
+ {
+ op->m_errorCode = CreateFilegroupRef::InvalidExtentSize;
+ break;
+ }
+ }
+ else if(fg.FilegroupType == DictTabInfo::LogfileGroup)
+ {
+ if(!fg.LF_UndoBufferSize)
+ {
+ 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){
+ op->m_errorCode = CreateTableRef::TableAlreadyExist;
+ break;
+ }
+
+ Ptr<DictObject> obj_ptr;
+ if(!c_obj_pool.seize(obj_ptr)){
+ op->m_errorCode = CreateTableRef::NoMoreTableRecords;
+ break;
+ }
+
+ FilegroupPtr fg_ptr;
+ if(!c_filegroup_pool.seize(fg_ptr)){
+ c_obj_pool.release(obj_ptr);
+ op->m_errorCode = CreateTableRef::NoMoreTableRecords;
+ break;
+ }
+
+ {
+ Rope name(c_rope_pool, obj_ptr.p->m_name);
+ if(!name.assign(fg.FilegroupName, len, hash)){
+ op->m_errorCode = CreateTableRef::TableNameTooLong;
+ c_obj_pool.release(obj_ptr);
+ c_filegroup_pool.release(fg_ptr);
+ 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))
+ {
+ op->m_errorCode = CreateFilegroupRef::NoSuchLogfileGroup;
+ goto error;
+ }
+
+ if (lg_ptr.p->m_version != fg.TS_LogfileGroupVersion)
+ {
+ op->m_errorCode = CreateFilegroupRef::InvalidFilegroupVersion;
+ goto error;
+ }
+ increase_ref_count(lg_ptr.p->m_obj_ptr_i);
+ break;
+ case DictTabInfo::LogfileGroup:
+ 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:
+ 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();
+
+ 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:
+ 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:
+ ref = LGMAN_REF;
+ len = CreateFilegroupImplReq::LogfileGroupLength;
+ req->logfile_group.buffer_size =
+ fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
+ break;
+ default:
+ ndbrequire(false);
}
- if (attrPtr.i == RNIL) {
- return MetaData::AttributeNotFound;
+
+ sendSignal(ref, GSN_CREATE_FILEGROUP_REQ, signal, len, JBB);
+}
+
+void
+Dbdict::execCREATE_FILEGROUP_REF(Signal* signal){
+ jamEntry();
+
+ CreateFilegroupImplRef * ref = (CreateFilegroupImplRef*)signal->getDataPtr();
+
+ CreateObjRecordPtr op_ptr;
+ 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){
+ jamEntry();
+
+ CreateFilegroupImplConf * rep =
+ (CreateFilegroupImplConf*)signal->getDataPtr();
+
+ CreateObjRecordPtr op_ptr;
+ 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){
+ execute(signal, op->m_callback, 0);
+ abort();
+}
+
+void
+Dbdict::create_fg_abort_complete(Signal* signal, SchemaOp* op){
+ execute(signal, op->m_callback, 0);
+ abort();
+}
+
+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());
+
+ DictFilegroupInfo::File f; f.init();
+ SimpleProperties::UnpackStatus status;
+ status = SimpleProperties::unpack(it, &f,
+ DictFilegroupInfo::FileMapping,
+ DictFilegroupInfo::FileMappingSize,
+ true, true);
+
+ do {
+ if(status != SimpleProperties::Eof){
+ op->m_errorCode = CreateFileRef::InvalidFormat;
+ break;
+ }
+
+ // Get Filegroup
+ FilegroupPtr fg_ptr;
+ if(!c_filegroup_hash.find(fg_ptr, f.FilegroupId)){
+ op->m_errorCode = CreateFileRef::NoSuchFilegroup;
+ break;
+ }
+
+ if(fg_ptr.p->m_version != f.FilegroupVersion){
+ op->m_errorCode = CreateFileRef::InvalidFilegroupVersion;
+ break;
+ }
+
+ switch(f.FileType){
+ case DictTabInfo::Datafile:
+ if(fg_ptr.p->m_type != DictTabInfo::Tablespace)
+ op->m_errorCode = CreateFileRef::InvalidFileType;
+ break;
+ case DictTabInfo::Undofile:
+ if(fg_ptr.p->m_type != DictTabInfo::LogfileGroup)
+ op->m_errorCode = CreateFileRef::InvalidFileType;
+ break;
+ default:
+ op->m_errorCode = CreateFileRef::InvalidFileType;
+ }
+
+ if(op->m_errorCode)
+ break;
+
+ Uint32 len = strlen(f.FileName) + 1;
+ Uint32 hash = Rope::hash(f.FileName, len);
+ if(get_object(f.FileName, len, hash) != 0){
+ op->m_errorCode = CreateFileRef::FilenameAlreadyExists;
+ break;
+ }
+
+ // Loop through all filenames...
+ Ptr<DictObject> obj_ptr;
+ if(!c_obj_pool.seize(obj_ptr)){
+ op->m_errorCode = CreateTableRef::NoMoreTableRecords;
+ break;
+ }
+
+ FilePtr filePtr;
+ if (! c_file_pool.seize(filePtr)){
+ op->m_errorCode = CreateFileRef::OutOfFileRecords;
+ c_obj_pool.release(obj_ptr);
+ break;
+ }
+
+ {
+ Rope name(c_rope_pool, obj_ptr.p->m_name);
+ if(!name.assign(f.FileName, len, hash)){
+ op->m_errorCode = CreateTableRef::TableNameTooLong;
+ c_obj_pool.release(obj_ptr);
+ c_file_pool.release(filePtr);
+ break;
+ }
+ }
+
+ switch(fg_ptr.p->m_type){
+ case DictTabInfo::Tablespace:
+ increase_ref_count(fg_ptr.p->m_obj_ptr_i);
+ break;
+ case DictTabInfo::LogfileGroup:
+ {
+ LocalDLList<File> 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;
+
+ 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);
+
+ 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;
+ c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
+
+ FilegroupPtr fg_ptr;
+ 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:
+ req->requestInfo = CreateFileImplReq::Create;
+ break;
+ case 1:
+ req->requestInfo = CreateFileImplReq::Open;
+ if(getNodeState().getNodeRestartInProgress())
+ req->requestInfo = CreateFileImplReq::CreateForce;
+ break;
+ case 2:
+ req->requestInfo = CreateFileImplReq::CreateForce;
+ break;
}
- new (&attr) MetaData::Attribute(*attrPtr.p);
- return 0;
+
+ 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:
+ ref = TSMAN_REF;
+ len = CreateFileImplReq::DatafileLength;
+ req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
+ break;
+ case DictTabInfo::Undofile:
+ 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){
+ jamEntry();
+
+ CreateFileImplRef * ref = (CreateFileImplRef*)signal->getDataPtr();
+
+ CreateObjRecordPtr op_ptr;
+ 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){
+ jamEntry();
+
+ CreateFileImplConf * rep =
+ (CreateFileImplConf*)signal->getDataPtr();
+
+ CreateObjRecordPtr op_ptr;
+ 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;
+ c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
+
+ FilegroupPtr fg_ptr;
+ 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:
+ ref = TSMAN_REF;
+ break;
+ case DictTabInfo::Undofile:
+ 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();
+
+ FilePtr f_ptr;
+ c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
+
+ FilegroupPtr fg_ptr;
+ 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:
+ ref = TSMAN_REF;
+ break;
+ case DictTabInfo::Undofile:
+ ref = LGMAN_REF;
+ break;
+ default:
+ ndbrequire(false);
+ }
+
+ sendSignal(ref, GSN_CREATE_FILE_REQ, signal,
+ CreateFileImplReq::AbortLength, JBB);
+}
+
+void
+Dbdict::create_file_abort_complete(Signal* signal, SchemaOp* op)
+{
+ FilePtr f_ptr;
+ c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
+
+ FilegroupPtr fg_ptr;
+ ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
+
+ switch(fg_ptr.p->m_type){
+ case DictTabInfo::Tablespace:
+ decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
+ break;
+ case DictTabInfo::LogfileGroup:
+ {
+ LocalDLList<File> 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);
+
+ execute(signal, op->m_callback, 0);
}
CArray<KeyDescriptor> g_key_descriptor_pool;
+
+void
+Dbdict::drop_file_prepare_start(Signal* signal, SchemaOp* op)
+{
+ send_drop_file(signal, op, DropFileImplReq::Prepare);
+}
+
+void
+Dbdict::drop_undofile_prepare_start(Signal* signal, SchemaOp* op)
+{
+ op->m_errorCode = DropFileRef::DropUndoFileNotSupported;
+ execute(signal, op->m_callback, 0);
+}
+
+void
+Dbdict::drop_file_commit_start(Signal* signal, SchemaOp* op)
+{
+ send_drop_file(signal, op, DropFileImplReq::Commit);
+}
+
+void
+Dbdict::drop_file_commit_complete(Signal* signal, SchemaOp* op)
+{
+ FilePtr f_ptr;
+ c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
+
+ FilegroupPtr fg_ptr;
+ 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);
+
+ execute(signal, op->m_callback, 0);
+}
+
+void
+Dbdict::drop_file_abort_start(Signal* signal, SchemaOp* op)
+{
+ 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;
+ c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
+
+ FilegroupPtr fg_ptr;
+ 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:
+ ref = TSMAN_REF;
+ break;
+ case DictTabInfo::Undofile:
+ ref = LGMAN_REF;
+ break;
+ default:
+ ndbrequire(false);
+ }
+
+ sendSignal(ref, GSN_DROP_FILE_REQ, signal,
+ DropFileImplReq::SignalLength, JBB);
+}
+
+void
+Dbdict::execDROP_OBJ_REF(Signal* signal){
+ jamEntry();
+
+ DropObjRef * const ref = (DropObjRef*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
+
+ if(ref->errorCode != DropObjRef::NF_FakeErrorREF){
+ 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){
+ jamEntry();
+
+ DropObjConf * const conf = (DropObjConf*)signal->getDataPtr();
+
+ Ptr<SchemaTransaction> trans_ptr;
+ ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
+ schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
+}
+
+void
+Dbdict::execDROP_FILE_REF(Signal* signal){
+ jamEntry();
+
+ DropFileImplRef * ref = (DropFileImplRef*)signal->getDataPtr();
+
+ DropObjRecordPtr op_ptr;
+ 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){
+ jamEntry();
+
+ DropFileImplConf * rep =
+ (DropFileImplConf*)signal->getDataPtr();
+
+ DropObjRecordPtr op_ptr;
+ ndbrequire(c_opDropObj.find(op_ptr, rep->senderData));
+
+ execute(signal, op_ptr.p->m_callback, 0);
+}
+
+void
+Dbdict::execDROP_FILEGROUP_REF(Signal* signal){
+ jamEntry();
+
+ DropFilegroupImplRef * ref = (DropFilegroupImplRef*)signal->getDataPtr();
+
+ DropObjRecordPtr op_ptr;
+ 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){
+ jamEntry();
+
+ DropFilegroupImplConf * rep =
+ (DropFilegroupImplConf*)signal->getDataPtr();
+
+ DropObjRecordPtr op_ptr;
+ 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)
+ {
+ op->m_errorCode = DropFilegroupRef::FilegroupInUse;
+ execute(signal, op->m_callback, 0);
+ }
+ else
+ {
+ 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)
+ {
+
+ /**
+ * Mark all undofiles as dropped
+ */
+ Ptr<File> filePtr;
+ LocalDLList<File> 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))
+ {
+ 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);
+ }
+ list.release();
+ }
+ else if(op->m_obj_type == DictTabInfo::Tablespace)
+ {
+ FilegroupPtr lg_ptr;
+ 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);
+ }
+
+ 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);
+
+ release_object(fg_ptr.p->m_obj_ptr_i);
+
+ execute(signal, op->m_callback, 0);
+}
+
+void
+Dbdict::drop_fg_abort_start(Signal* signal, SchemaOp* op)
+{
+ 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);
+}
+
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index 1424b4e3146..112543d5831 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -20,14 +20,16 @@
/**
* Dict : Dictionary Block
*/
-
#include <ndb_limits.h>
#include <trigger_definitions.h>
#include <pc.hpp>
#include <ArrayList.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>
@@ -54,6 +56,10 @@
#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
@@ -105,8 +111,6 @@
/**
* Systable NDB$EVENTS_0
*/
-
-#define EVENT_SYSTEM_TABLE_NAME "sys/def/NDB$EVENTS_0"
#define EVENT_SYSTEM_TABLE_LENGTH 8
struct sysTab_NDBEVENTS_0 {
@@ -128,11 +132,151 @@ 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 : public MetaData::Table {
+ struct TableRecord {
+ TableRecord(){}
+ /* 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;
+
+ /* 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;
+
+ /*
+ * Used when shrinking to decide when to merge buckets. Hysteresis
+ * is thus possible. Should be smaller but not much smaller than
+ * maxLoadFactor
+ */
+ Uint8 minLoadFactor;
+
+ /* Is the table logged (i.e. data survives system restart) */
+ bool storedTable;
+
+ /* 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
****************************************************/
@@ -144,30 +288,13 @@ public:
Uint32 filePtr[2];
/** Pointer to first attribute in table */
- Uint32 firstAttribute;
+ DLFifoList<AttributeRecord>::Head m_attributes;
/* Pointer to first page of table description */
Uint32 firstPage;
- /** Pointer to last attribute in table */
- Uint32 lastAttribute;
-
-#ifdef HAVE_TABLE_REORG
- /* Second table used by this table (for table reorg) */
- Uint32 secondTable;
-#endif
- /* Next record in Pool */
Uint32 nextPool;
- /* Next record in hash table */
- Uint32 nextHash;
-
- /* Previous record in Pool */
- Uint32 prevPool;
-
- /* Previous record in hash table */
- Uint32 prevHash;
-
enum TabState {
NOT_DEFINED = 0,
REORG_TABLE_PREPARED = 1,
@@ -218,75 +345,26 @@ public:
Uint32 noOfNullBits;
- inline bool equal(TableRecord & rec) const {
- return strcmp(tableName, rec.tableName) == 0;
- }
-
- inline Uint32 hashValue() const {
- Uint32 h = 0;
- for (const char* p = tableName; *p != 0; p++)
- h = (h << 5) + h + (*p);
- return h;
- }
-
/** frm data for this table */
- /** TODO Could preferrably be made dynamic size */
- Uint32 frmLen;
- char frmData[MAX_FRM_DATA_SIZE];
+ RopeHandle frmData;
/** Node Group and Tablespace id for this table */
/** TODO Could preferrably be made dynamic size */
Uint32 ngLen;
Uint16 ngData[MAX_NDB_PARTITIONS];
Uint32 fragmentCount;
+ Uint32 m_tablespace_id;
};
typedef Ptr<TableRecord> TableRecordPtr;
ArrayPool<TableRecord> c_tableRecordPool;
- DLHashTable<TableRecord> c_tableRecordHash;
-
- /**
- * Table attributes. Permanent data.
- *
- * Indexes have an attribute list which duplicates primary table
- * attributes. This is wrong but convenient.
- */
- struct AttributeRecord : public MetaData::Attribute {
- union {
- /** Pointer to the next attribute used by ArrayPool */
- Uint32 nextPool;
-
- /** Pointer to the next attribute used by DLHash */
- Uint32 nextHash;
- };
-
- /** Pointer to the previous attribute used by DLHash */
- Uint32 prevHash;
-
- /** Pointer to the next attribute in table */
- Uint32 nextAttrInTable;
-
- inline bool equal(AttributeRecord & rec) const {
- return strcmp(attributeName, rec.attributeName) == 0;
- }
-
- inline Uint32 hashValue() const {
- Uint32 h = 0;
- for (const char* p = attributeName; *p != 0; p++)
- h = (h << 5) + h + (*p);
- return h;
- }
- };
-
- typedef Ptr<AttributeRecord> AttributeRecordPtr;
- ArrayPool<AttributeRecord> c_attributeRecordPool;
- DLHashTable<AttributeRecord> c_attributeRecordHash;
/**
* 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 {
@@ -307,10 +385,11 @@ public:
Uint32 triggerLocal;
/** Trigger name, used by DICT to identify the trigger */
- char triggerName[MAX_TAB_NAME_SIZE];
+ 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;
@@ -339,39 +418,17 @@ public:
/** Index id, only used by secondary_index triggers */
Uint32 indexId;
- union {
/** Pointer to the next attribute used by ArrayPool */
Uint32 nextPool;
-
- /** Next record in hash table */
- Uint32 nextHash;
- };
-
- /** Previous record in hash table */
- Uint32 prevHash;
-
- /** Equal function, used by DLHashTable */
- inline bool equal(TriggerRecord & rec) const {
- return strcmp(triggerName, rec.triggerName) == 0;
- }
-
- /** Hash value function, used by DLHashTable */
- inline Uint32 hashValue() const {
- Uint32 h = 0;
- for (const char* p = triggerName; *p != 0; p++)
- h = (h << 5) + h + (*p);
- return h;
- }
};
Uint32 c_maxNoOfTriggers;
typedef Ptr<TriggerRecord> TriggerRecordPtr;
ArrayPool<TriggerRecord> c_triggerRecordPool;
- DLHashTable<TriggerRecord> c_triggerRecordHash;
/**
* Information for each FS connection.
- ****************************************************************************/
+ ***************************************************************************/
struct FsConnectRecord {
enum FsState {
IDLE = 0,
@@ -410,7 +467,7 @@ public:
/**
* This record stores all the information about a node and all its attributes
- ****************************************************************************/
+ ***************************************************************************/
struct NodeRecord {
enum NodeState {
API_NODE = 0,
@@ -425,9 +482,6 @@ public:
CArray<NodeRecord> c_nodes;
NdbNodeBitmask c_aliveNodes;
- /**
- * This record stores all the information about a table and all its attributes
- ****************************************************************************/
struct PageRecord {
Uint32 word[8192];
};
@@ -446,6 +500,119 @@ public:
*/
PageRecord c_indexPage;
+ struct File {
+ File() {}
+
+ Uint32 key;
+ Uint32 m_obj_ptr_i;
+ Uint32 m_filegroup_id;
+ Uint32 m_type;
+ Uint64 m_file_size;
+ 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;
+
+ struct Filegroup {
+ Filegroup(){}
+
+ Uint32 key;
+ Uint32 m_obj_ptr_i;
+
+ 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;
+ DLList<File>::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;
+
+ ArrayPool<File> c_file_pool;
+ KeyTable<File> c_file_hash;
+ ArrayPool<Filegroup> c_filegroup_pool;
+ KeyTable<Filegroup> 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(const class Configuration &);
virtual ~Dbdict();
@@ -590,6 +757,21 @@ private:
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);
+
/*
* 2.4 COMMON STORED VARIABLES
*/
@@ -620,7 +802,7 @@ private:
****************************************************************************/
struct ReadTableRecord {
/** Number of Pages */
- Uint32 noOfPages;
+ Uint32 no_of_words;
/** Page Id*/
Uint32 pageId;
/** Table Id of read table */
@@ -637,7 +819,7 @@ private:
****************************************************************************/
struct WriteTableRecord {
/** Number of Pages */
- Uint32 noOfPages;
+ Uint32 no_of_words;
/** Page Id*/
Uint32 pageId;
/** Table Files Handled, local state variable */
@@ -713,6 +895,8 @@ private:
/** The active table at restart process */
BlockReference returnBlockRef;
+
+ Uint32 m_pass; // 0 tablespaces/logfilegroups, 1 tables, 2 indexes
};
RestartRecord c_restartRecord;
@@ -740,6 +924,8 @@ private:
/** Table id of retrieved table */
Uint32 tableId;
+ Uint32 m_table_type;
+
/** Starting page to retrieve data from */
Uint32 retrievePage;
@@ -832,10 +1018,7 @@ private:
enum PackTableState {
PTS_IDLE = 0,
- PTS_ADD_TABLE_MASTER = 1,
- PTS_ADD_TABLE_SLAVE = 2,
- PTS_GET_TAB = 3,
- PTS_RESTART = 4
+ PTS_GET_TAB = 3
} m_state;
} c_packTable;
@@ -899,6 +1082,11 @@ private:
/* 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;
@@ -1672,6 +1860,64 @@ private:
};
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;
+ 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) );
@@ -1687,6 +1933,7 @@ public:
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 {
@@ -1703,6 +1950,7 @@ private:
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;
@@ -1721,6 +1969,10 @@ private:
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;
@@ -1742,13 +1994,15 @@ private:
/* ------------------------------------------------------------ */
// General Stuff
/* ------------------------------------------------------------ */
+ Uint32 getFreeObjId(Uint32 minId);
Uint32 getFreeTableRecord(Uint32 primaryTableId);
Uint32 getFreeTriggerRecord();
bool getNewAttributeRecord(TableRecordPtr tablePtr,
AttributeRecordPtr & attrPtr);
- void packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId);
- void packTableIntoPagesImpl(SimpleProperties::Writer &, TableRecordPtr,
- Signal* signal= 0);
+ void packTableIntoPages(Signal* signal);
+ void packTableIntoPages(SimpleProperties::Writer &, TableRecordPtr, Signal* =0);
+ void packFilegroupIntoPages(SimpleProperties::Writer &, FilegroupPtr);
+ void packFileIntoPages(SimpleProperties::Writer &, FilePtr, const Uint32);
void sendGET_TABINFOREQ(Signal* signal,
Uint32 tableId);
@@ -1771,7 +2025,8 @@ private:
void handleTabInfoInit(SimpleProperties::Reader &,
ParseDictTabInfoRecord *,
bool checkExist = true);
- void handleTabInfo(SimpleProperties::Reader & it, ParseDictTabInfoRecord *);
+ void handleTabInfo(SimpleProperties::Reader & it, ParseDictTabInfoRecord *,
+ Uint32 tablespaceVersion);
void handleAddTableFailure(Signal* signal,
Uint32 failureLine,
@@ -2134,7 +2389,9 @@ private:
void createTab_reply(Signal* signal, CreateTableRecordPtr, Uint32 nodeId);
void alterTab_activate(Signal*, CreateTableRecordPtr, Callback*);
- void restartCreateTab(Signal*, Uint32, const SchemaFile::TableEntry *, bool);
+ 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);
@@ -2149,13 +2406,128 @@ private:
void sendSchemaComplete(Signal*, Uint32 callbackData, Uint32);
- // global metadata support
- friend class MetaData;
- int getMetaTablePtr(TableRecordPtr& tablePtr, Uint32 tableId, Uint32 tableVersion);
- int getMetaTable(MetaData::Table& table, Uint32 tableId, Uint32 tableVersion);
- int getMetaTable(MetaData::Table& table, const char* tableName);
- int getMetaAttribute(MetaData::Attribute& attribute, const MetaData::Table& table, Uint32 attributeId);
- int getMetaAttribute(MetaData::Attribute& attribute, const MetaData::Table& table, const char* attributeName);
+ 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*);
};
+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/Makefile.am b/storage/ndb/src/kernel/blocks/dbdict/Makefile.am
index 367e3cf203b..f14b7f1e127 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/Makefile.am
+++ b/storage/ndb/src/kernel/blocks/dbdict/Makefile.am
@@ -1,10 +1,7 @@
noinst_LIBRARIES = libdbdict.a
-EXTRA_PROGRAMS = printSchemaFile
libdbdict_a_SOURCES = Dbdict.cpp
-printSchemaFile_SOURCES = printSchemaFile.cpp
-
include $(top_srcdir)/storage/ndb/config/common.mk.am
include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
@@ -15,6 +12,14 @@ LDADD += \
$(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
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp b/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
index f73654fd9d5..d3a4e72c3f0 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
+++ b/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
@@ -21,6 +21,7 @@
#include <NdbMain.h>
#include <NdbOut.hpp>
#include <SchemaFile.hpp>
+#include <kernel_types.h>
static const char* progname = 0;
static bool allflag = false;
@@ -87,6 +88,13 @@ print_head(const char * filename, const SchemaFile * sf)
return retcode;
}
+inline
+Uint32
+table_version_minor(Uint32 ver)
+{
+ return ver >> 24;
+}
+
static int
print_old(const char * filename, const SchemaFile * sf, Uint32 sz)
{
@@ -103,10 +111,11 @@ print_old(const char * filename, const SchemaFile * sf, Uint32 sz)
if (! checkonly)
ndbout << "Table " << i << ":"
<< " State = " << te.m_tableState
- << " version = " << te.m_tableVersion
+ << " 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;
+ << " noOfPages = " << te.m_noOfPages
+ << " gcp: " << te.m_gcp << endl;
}
}
return retcode;
@@ -159,7 +168,8 @@ print(const char * filename, const SchemaFile * xsf, Uint32 sz)
if (! checkonly)
ndbout << "Table " << j << ":"
<< " State = " << te.m_tableState
- << " version = " << te.m_tableVersion
+ << " 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;
diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
index d6f6b772516..ca969a2300a 100644
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
+++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
@@ -25,19 +25,6 @@ void Dbdih::initData()
{
cpageFileSize = ZPAGEREC;
- 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;
-
// Records with constant sizes
createReplicaRecord = (CreateReplicaRecord*)
allocRecord("CreateReplicaRecord", sizeof(CreateReplicaRecord),
@@ -263,17 +250,18 @@ Dbdih::Dbdih(const class Configuration & config):
addRecSignal(GSN_CREATE_FRAGMENTATION_REQ,
&Dbdih::execCREATE_FRAGMENTATION_REQ);
- apiConnectRecord = 0;
- connectRecord = 0;
- fileRecord = 0;
+ apiConnectRecord = 0;
+ connectRecord = 0;
+ fileRecord = 0;
fragmentstore = 0;
- pageRecord = 0;
- replicaRecord = 0;
+ pageRecord = 0;
+ replicaRecord = 0;
tabRecord = 0;
- createReplicaRecord = 0;
- nodeGroupRecord = 0;
- nodeRecord = 0;
takeOverRecord = 0;
+ createReplicaRecord = 0;
+ nodeGroupRecord = 0;
+ nodeRecord = 0;
+ c_nextNodeGroup = 0;
}//Dbdih::Dbdih()
Dbdih::~Dbdih()
diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index f43010ab2e9..ae629ae437c 100644
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -639,9 +639,11 @@ void Dbdih::execCOPY_GCIREQ(Signal* signal)
c_copyGCISlave.m_expectedNextWord += CopyGCIReq::DATA_SIZE;
return;
}//if
-
+
+ Uint32 tmp= SYSFILE->m_restart_seq;
memcpy(sysfileData, cdata, sizeof(sysfileData));
-
+ SYSFILE->m_restart_seq = tmp;
+
c_copyGCISlave.m_copyReason = reason;
c_copyGCISlave.m_senderRef = signal->senderBlockRef();
c_copyGCISlave.m_senderData = copyGCI->anyData;
@@ -1613,12 +1615,15 @@ void Dbdih::execSTART_MECONF(Signal* signal)
*
* 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];
@@ -3473,6 +3478,7 @@ void Dbdih::readingGcpLab(Signal* signal, FileRecordPtr filePtr)
/* 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()
@@ -7907,6 +7913,10 @@ void Dbdih::writingCopyGciLab(Signal* signal, FileRecordPtr filePtr)
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();
@@ -11191,6 +11201,8 @@ void Dbdih::initRestartInfo()
SYSFILE->takeOver[i] = 0;
}//for
Sysfile::setInitialStartOngoing(SYSFILE->systemRestartBits);
+ srand(time(0));
+ globalData.m_restart_seq = SYSFILE->m_restart_seq = 0;
}//Dbdih::initRestartInfo()
/*--------------------------------------------------------------------*/
diff --git a/storage/ndb/src/kernel/blocks/dbdih/Makefile.am b/storage/ndb/src/kernel/blocks/dbdih/Makefile.am
index 1fe98a415be..7a3e610b1ba 100644
--- a/storage/ndb/src/kernel/blocks/dbdih/Makefile.am
+++ b/storage/ndb/src/kernel/blocks/dbdih/Makefile.am
@@ -1,16 +1,20 @@
+
noinst_LIBRARIES = libdbdih.a
-EXTRA_PROGRAMS = ndbd_sysfile_reader
libdbdih_a_SOURCES = DbdihInit.cpp DbdihMain.cpp
-ndbd_sysfile_reader_SOURCES = printSysfile/printSysfile.cpp
+
+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
-LDADD += \
- $(top_builddir)/ndb/src/common/util/libgeneral.la \
- $(top_builddir)/ndb/src/common/portlib/libportlib.la
-
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp b/storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp
index 3e2f3b0dd48..4548ad1a30c 100644
--- a/storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp
+++ b/storage/ndb/src/kernel/blocks/dbdih/Sysfile.hpp
@@ -33,11 +33,6 @@
#define NO_NODE_GROUP_ID ((1 << NODEID_BITS) - 1)
/**
- * Dummy macro to make emacs indent better
- */
-#define _F(x) x
-
-/**
* No of 32 bits word in sysfile
*
* 5 +
@@ -47,7 +42,7 @@
* NODE_ARRAY_SIZE(MAX_NDB_NODES, NODEID_BITS) + // takeOver
* NodeBitmask::NDB_NODE_BITMASK_SIZE // Lcp Active
*/
-#define _SYSFILE_SIZE32 (5 + \
+#define _SYSFILE_SIZE32 (6 + \
MAX_NDB_NODES + \
NODE_ARRAY_SIZE(MAX_NDB_NODES, 4) + \
NODE_ARRAY_SIZE(MAX_NDB_NODES, NODEID_BITS) + \
@@ -67,6 +62,11 @@ public:
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);
diff --git a/storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp b/storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp
new file mode 100644
index 00000000000..e4d4f6018db
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbdih/printSysfile.cpp
@@ -0,0 +1,160 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+
+#include <NdbMain.h>
+#include <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/dblqh/Dblqh.hpp b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index 14b61e10942..40a7fd9e6a9 100644
--- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -20,6 +20,7 @@
#include <pc.hpp>
#include <ndb_limits.h>
#include <SimulatedBlock.hpp>
+#include <SLList.hpp>
#include <DLList.hpp>
#include <DLFifoList.hpp>
#include <DLHashTable.hpp>
@@ -30,7 +31,9 @@
#include <signaldata/LqhFrag.hpp>
// primary key is stored in TUP
-#include <../dbtup/Dbtup.hpp>
+#include "../dbtup/Dbtup.hpp"
+
+#include "../dbacc/Dbacc.hpp"
#ifdef DBLQH_C
// Constants
@@ -230,7 +233,6 @@
#define ZSCAN_TC_CONNECT 13
#define ZINITIALISE_RECORDS 14
#define ZINIT_GCP_REC 15
-#define ZRESTART_OPERATIONS_AFTER_STOP 16
#define ZCHECK_LCP_STOP_BLOCKED 17
#define ZSCAN_MARKERS 18
#define ZOPERATION_EVENT_REP 19
@@ -418,24 +420,18 @@ public:
enum ExecUndoLogState {
EULS_IDLE = 0,
EULS_STARTED = 1,
- EULS_COMPLETED = 2,
- EULS_ACC_COMPLETED = 3,
- EULS_TUP_COMPLETED = 4
+ EULS_COMPLETED = 2
};
struct AddFragRecord {
enum AddFragStatus {
FREE = 0,
ACC_ADDFRAG = 1,
- WAIT_TWO_TUP = 2,
- WAIT_ONE_TUP = 3,
- WAIT_TWO_TUX = 4,
- WAIT_ONE_TUX = 5,
+ WAIT_TUP = 3,
+ WAIT_TUX = 5,
WAIT_ADD_ATTR = 6,
- TUP_ATTR_WAIT1 = 7,
- TUP_ATTR_WAIT2 = 8,
- TUX_ATTR_WAIT1 = 9,
- TUX_ATTR_WAIT2 = 10
+ TUP_ATTR_WAIT = 7,
+ TUX_ATTR_WAIT = 9
};
LqhAddAttrReq::Entry attributes[LqhAddAttrReq::MAX_ATTRIBUTES];
UintR accConnectptr;
@@ -445,10 +441,8 @@ public:
UintR nextAddfragrec;
UintR noOfAllocPages;
UintR schemaVer;
- UintR tup1Connectptr;
- UintR tup2Connectptr;
- UintR tux1Connectptr;
- UintR tux2Connectptr;
+ UintR tupConnectptr;
+ UintR tuxConnectptr;
UintR checksumIndicator;
UintR GCPIndicator;
BlockReference dictBlockref;
@@ -457,8 +451,6 @@ public:
Uint16 attrSentToTup;
Uint16 attrReceived;
Uint16 addFragid;
- Uint16 fragid1;
- Uint16 fragid2;
Uint16 noOfAttr;
Uint16 noOfNull;
Uint16 tabId;
@@ -470,6 +462,7 @@ public:
Uint16 lh3DistrBits;
Uint16 tableType;
Uint16 primaryTableId;
+ Uint32 tablespace_id;
};// Size 108 bytes
typedef Ptr<AddFragRecord> AddFragRecordPtr;
@@ -595,6 +588,8 @@ public:
typedef Ptr<ScanRecord> ScanRecordPtr;
struct Fragrecord {
+ Fragrecord() {}
+
enum ExecSrStatus {
IDLE = 0,
ACTIVE_REMOVE_AFTER = 1,
@@ -695,7 +690,7 @@ public:
/**
* The fragment pointers in ACC
*/
- UintR accFragptr[2];
+ 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
@@ -725,54 +720,38 @@ public:
/**
* The fragment pointers in TUP and TUX
*/
- UintR tupFragptr[2];
- UintR tuxFragptr[2];
- /**
- * This queue is where operations are put when blocked in ACC
- * during start of a local chkp.
- */
- UintR accBlockedList;
- /**
- * This is the queue where all operations that are active on the
- * fragment is put.
- * This is used to deduct when the fragment do
- * no longer contain any active operations.
- * This is needed when starting a local checkpoint.
- */
- UintR activeList;
+ 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;
+
/**
* Indicates a local checkpoint is active and thus can generate
* UNDO log records.
*/
UintR fragActiveStatus;
- /**
- * Reference to current LCP record.
- * If no LCP is ongoing on the fragment then the value is RNIL.
- * If LCP_REF /= RNIL then a local checkpoint is ongoing in the
- * fragment.
- * LCP_STATE in LCP_RECORD specifies the state of the
- * local checkpoint.
- */
- UintR lcpRef;
+
/**
* This flag indicates whether logging is currently activated at
* the fragment.
@@ -789,7 +768,12 @@ public:
* Reference to the next fragment record in a free list of fragment
* records.
*/
- UintR nextFrag;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+
/**
* The newest GCI that has been committed on fragment
*/
@@ -804,18 +788,21 @@ public:
* 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.
*/
@@ -969,6 +956,36 @@ public:
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 $$$$$$$ */
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
/**
@@ -985,18 +1002,17 @@ public:
LCP_WAIT_FRAGID = 3,
LCP_WAIT_TUP_PREPLCP = 4,
LCP_WAIT_HOLDOPS = 5,
- LCP_WAIT_ACTIVE_FINISH = 6,
LCP_START_CHKP = 7,
LCP_BLOCKED_COMP = 8,
LCP_SR_WAIT_FRAGID = 9,
LCP_SR_STARTED = 10,
LCP_SR_COMPLETED = 11
};
- Uint32 firstLcpLocAcc;
- Uint32 firstLcpLocTup;
- Uint32 lcpAccptr;
+ LcpLocRecord m_acc;
+ LcpLocRecord m_tup;
LcpState lcpState;
+ bool firstFragmentFlag;
bool lastFragmentFlag;
struct FragOrd {
@@ -1010,50 +1026,11 @@ public:
bool reportEmpty;
NdbNodeBitmask m_EMPTY_LCP_REQ;
+
+ Uint32 m_outstanding;
}; // Size 76 bytes
typedef Ptr<LcpRecord> LcpRecordPtr;
-
- /* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
- /* $$$$$$ 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
- };
- enum WaitingBlock {
- ACC = 0,
- TUP = 1,
- NONE = 2
- };
- LcpLocstate lcpLocstate;
- UintR locFragid;
- UintR masterLcpRec;
- UintR nextLcpLoc;
- UintR tupRef;
- WaitingBlock waitingBlock;
- Uint32 accContCounter;
- }; // 28 bytes
- typedef Ptr<LcpLocRecord> LcpLocRecordPtr;
-
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
/* */
@@ -1874,6 +1851,7 @@ public:
Uint16 tableType;
Uint16 primaryTableId;
Uint32 schemaVersion;
+ Uint8 m_disk_table;
Uint32 usageCount;
NdbNodeBitmask waitingTC;
@@ -1884,8 +1862,6 @@ public:
struct TcConnectionrec {
enum ListState {
NOT_IN_LIST = 0,
- IN_ACTIVE_LIST = 1,
- ACC_BLOCK_LIST = 2,
WAIT_QUEUE_LIST = 3
};
enum LogWriteState {
@@ -1925,6 +1901,7 @@ public:
LOG_COMMIT_QUEUED = 11,
COMMIT_QUEUED = 12,
COMMITTED = 13,
+ WAIT_TUP_COMMIT= 35,
/* -------------------------------------------------------------------- */
// Abort in progress states
@@ -2041,7 +2018,6 @@ public:
Uint8 dirtyOp;
Uint8 indTakeOver;
Uint8 lastReplicaNo;
- Uint8 localFragptr;
Uint8 lockType;
Uint8 nextSeqNoReplica;
Uint8 opSimple;
@@ -2053,6 +2029,8 @@ public:
Uint8 simpleRead;
Uint8 seqNoReplica;
Uint8 tcNodeFailrec;
+ Uint8 m_disk_table;
+ Uint32 m_local_key;
}; /* p2c: size = 280 bytes */
typedef Ptr<TcConnectionrec> TcConnectionrecPtr;
@@ -2083,6 +2061,9 @@ public:
public:
Dblqh(const class Configuration &);
virtual ~Dblqh();
+
+ void receive_keyinfo(Signal*, Uint32 * data, Uint32 len);
+ void receive_attrinfo(Signal*, Uint32 * data, Uint32 len);
private:
BLOCK_DEFINES(Dblqh);
@@ -2108,6 +2089,10 @@ private:
void execEXEC_SRREQ(Signal* signal);
void execEXEC_SRCONF(Signal* signal);
void execREAD_PSEUDO_REQ(Signal* signal);
+
+ void build_acc(Signal*, Uint32 fragPtrI);
+ void execBUILDINDXREF(Signal*signal);
+ void execBUILDINDXCONF(Signal*signal);
void execDUMP_STATE_ORD(Signal* signal);
void execACC_COM_BLOCK(Signal* signal);
@@ -2161,32 +2146,13 @@ private:
void execLQH_TRANSREQ(Signal* signal);
void execTRANSID_AI(Signal* signal);
void execINCL_NODEREQ(Signal* signal);
- void execACC_LCPCONF(Signal* signal);
- void execACC_LCPREF(Signal* signal);
- void execACC_LCPSTARTED(Signal* signal);
- void execACC_CONTOPCONF(Signal* signal);
- void execLCP_FRAGIDCONF(Signal* signal);
- void execLCP_FRAGIDREF(Signal* signal);
- void execLCP_HOLDOPCONF(Signal* signal);
- void execLCP_HOLDOPREF(Signal* signal);
- void execTUP_PREPLCPCONF(Signal* signal);
- void execTUP_PREPLCPREF(Signal* signal);
- void execTUP_LCPCONF(Signal* signal);
- void execTUP_LCPREF(Signal* signal);
- void execTUP_LCPSTARTED(Signal* signal);
- void execEND_LCPCONF(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 execSR_FRAGIDCONF(Signal* signal);
- void execSR_FRAGIDREF(Signal* signal);
- void execACC_SRCONF(Signal* signal);
- void execACC_SRREF(Signal* signal);
- void execTUP_SRCONF(Signal* signal);
- void execTUP_SRREF(Signal* signal);
+
void execGCP_SAVEREQ(Signal* signal);
void execFSOPENCONF(Signal* signal);
void execFSCLOSECONF(Signal* signal);
@@ -2251,17 +2217,13 @@ private:
void sendCompleteLqh(Signal* signal, BlockReference alqhBlockref);
void sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr);
void sendPackedSignalTc(Signal* signal, HostRecord * ahostptr);
- Uint32 handleLongTupKey(Signal* signal,
- Uint32 lenSofar,
- Uint32 primKeyLen,
- Uint32* dataPtr);
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(Signal* signal,
+ void initScanTc(const class ScanFragReq *,
Uint32 transid1,
Uint32 transid2,
Uint32 fragId,
@@ -2281,8 +2243,6 @@ private:
void getNextFragForLcp(Signal* signal);
void initLcpLocAcc(Signal* signal, Uint32 fragId);
void initLcpLocTup(Signal* signal, Uint32 fragId);
- void moveAccActiveFrag(Signal* signal);
- void moveActiveToAcc(Signal* signal);
void releaseLocalLcps(Signal* signal);
void seizeLcpLoc(Signal* signal);
void sendAccContOp(Signal* signal);
@@ -2361,7 +2321,6 @@ private:
void initLogPointers(Signal* signal);
void initReqinfoExecSr(Signal* signal);
bool insertFragrec(Signal* signal, Uint32 fragId);
- void linkActiveFrag(Signal* signal);
void linkFragQueue(Signal* signal);
void linkWaitLog(Signal* signal, LogPartRecordPtr regLogPartPtr);
void logNextStart(Signal* signal);
@@ -2377,10 +2336,7 @@ private:
Uint32 readLogword(Signal* signal);
Uint32 readLogwordExec(Signal* signal);
void readSinglePage(Signal* signal, Uint32 pageNo);
- void releaseAccList(Signal* signal);
void releaseActiveCopy(Signal* signal);
- void releaseActiveFrag(Signal* signal);
- void releaseActiveList(Signal* signal);
void releaseAddfragrec(Signal* signal);
void releaseFragrec();
void releaseLcpLoc(Signal* signal);
@@ -2429,6 +2385,7 @@ private:
void readFileInInvalidate(Signal *signal);
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);
@@ -2469,7 +2426,7 @@ private:
void completeTransNotLastLab(Signal* signal);
void completedLab(Signal* signal);
void copyCompletedLab(Signal* signal);
- void completeLcpRoundLab(Signal* signal);
+ void completeLcpRoundLab(Signal* signal, Uint32 lcpId);
void continueAfterLogAbortWriteLab(Signal* signal);
void sendAttrinfoLab(Signal* signal);
void sendExecConf(Signal* signal);
@@ -2561,7 +2518,6 @@ private:
void restartOperationsLab(Signal* signal);
void lqhTransNextLab(Signal* signal);
void restartOperationsAfterStopLab(Signal* signal);
- void sttorStartphase1Lab(Signal* signal);
void startphase1Lab(Signal* signal, Uint32 config, Uint32 nodeId);
void tupkeyConfLab(Signal* signal);
void copyTupkeyConfLab(Signal* signal);
@@ -2584,8 +2540,49 @@ private:
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;
Uint32 readPrimaryKeys(ScanRecord*, TcConnectionrec*, Uint32 * dst);
+
+ void acckeyconf_tupkeyreq(Signal*, TcConnectionrec*, Fragrecord*, Uint32, Uint32);
+ void acckeyconf_load_diskpage(Signal*,TcConnectionrecPtr,Fragrecord*,Uint32);
+
+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
@@ -2622,10 +2619,8 @@ private:
UintR cdatabufFileSize;
// Configurable
- Fragrecord *fragrecord;
FragrecordPtr fragptr;
- UintR cfirstfreeFragrec;
- UintR cfragrecFileSize;
+ ArrayPool<Fragrecord> c_fragment_pool;
#define ZGCPREC_FILE_SIZE 1
GcpRecord *gcpRecord;
@@ -2642,11 +2637,6 @@ private:
UintR cfirstfreeLcpLoc;
UintR clcpFileSize;
-#define ZLCP_LOCREC_FILE_SIZE 4
- LcpLocRecord *lcpLocRecord;
- LcpLocRecordPtr lcpLocptr;
- UintR clcpLocrecFileSize;
-
#define ZLOG_PART_FILE_SIZE 4
LogPartRecord *logPartRecord;
LogPartRecordPtr logPartPtr;
@@ -2777,17 +2767,10 @@ private:
/*THIS VARIABLE IS THE HEAD OF A LINKED LIST OF FRAGMENTS WAITING TO BE */
/*RESTORED FROM DISK. */
/* ------------------------------------------------------------------------- */
- UintR cfirstWaitFragSr;
-/* ------------------------------------------------------------------------- */
-/*THIS VARIABLE IS THE HEAD OF A LINKED LIST OF FRAGMENTS THAT HAVE BEEN */
-/*RESTORED FROM DISK THAT AWAITS EXECUTION OF THE FRAGMENT LOG. */
-/* ------------------------------------------------------------------------- */
- UintR cfirstCompletedFragSr;
-
- /**
- * List of fragment that the log execution is completed for
- */
- Uint32 c_redo_log_complete_frags;
+ DLList<Fragrecord> c_lcp_waiting_fragments; // StartFragReq'ed
+ DLList<Fragrecord> c_lcp_restoring_fragments; // Restoring as we speek
+ DLList<Fragrecord> c_lcp_complete_fragments; // Restored
+ DLList<Fragrecord> c_redo_complete_fragments; // Redo'ed
/* ------------------------------------------------------------------------- */
/*USED DURING SYSTEM RESTART, INDICATES THE OLDEST GCI THAT CAN BE RESTARTED */
@@ -2887,6 +2870,10 @@ private:
Uint32 c_diskless;
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*);
+
/**
*
*/
@@ -2963,4 +2950,41 @@ Dblqh::i_get_acc_ptr(ScanRecord* scanP, Uint32* &acc_ptr, Uint32 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);
+}
+
+
#endif
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
index 13251df53bd..ca7a8bb9631 100644
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
@@ -28,11 +28,9 @@ void Dblqh::initData()
cattrinbufFileSize = ZATTRINBUF_FILE_SIZE;
c_no_attrinbuf_recs= ZATTRINBUF_FILE_SIZE;
cdatabufFileSize = ZDATABUF_FILE_SIZE;
- cfragrecFileSize = 0;
cgcprecFileSize = ZGCPREC_FILE_SIZE;
chostFileSize = MAX_NDB_NODES;
clcpFileSize = ZNO_CONCURRENT_LCP;
- clcpLocrecFileSize = ZLCP_LOCREC_FILE_SIZE;
clfoFileSize = ZLFO_FILE_SIZE;
clogFileFileSize = 0;
clogPartFileSize = ZLOG_PART_FILE_SIZE;
@@ -45,11 +43,9 @@ void Dblqh::initData()
addFragRecord = 0;
attrbuf = 0;
databuf = 0;
- fragrecord = 0;
gcpRecord = 0;
hostRecord = 0;
lcpRecord = 0;
- lcpLocRecord = 0;
logPartRecord = 0;
logFileRecord = 0;
logFileOperationRecord = 0;
@@ -64,7 +60,7 @@ void Dblqh::initData()
cLqhTimeOutCount = 0;
cLqhTimeOutCheckCount = 0;
cbookedAccOps = 0;
- c_redo_log_complete_frags = RNIL;
+ m_backup_ptr = RNIL;
}//Dblqh::initData()
void Dblqh::initRecords()
@@ -81,10 +77,6 @@ void Dblqh::initRecords()
sizeof(Databuf),
cdatabufFileSize);
- fragrecord = (Fragrecord*)allocRecord("Fragrecord",
- sizeof(Fragrecord),
- cfragrecFileSize);
-
gcpRecord = (GcpRecord*)allocRecord("GcpRecord",
sizeof(GcpRecord),
cgcprecFileSize);
@@ -101,10 +93,6 @@ void Dblqh::initRecords()
new (&lcpRecord[i])LcpRecord();
}
- lcpLocRecord = (LcpLocRecord*)allocRecord("LcpLocRecord",
- sizeof(LcpLocRecord),
- clcpLocrecFileSize);
-
logPartRecord = (LogPartRecord*)allocRecord("LogPartRecord",
sizeof(LogPartRecord),
clogPartFileSize);
@@ -172,6 +160,10 @@ void Dblqh::initRecords()
Dblqh::Dblqh(const class Configuration & conf):
SimulatedBlock(DBLQH, conf),
+ c_lcp_waiting_fragments(c_fragment_pool),
+ c_lcp_restoring_fragments(c_fragment_pool),
+ c_lcp_complete_fragments(c_fragment_pool),
+ c_redo_complete_fragments(c_fragment_pool),
m_commitAckMarkerHash(m_commitAckMarkerPool),
c_scanTakeOverHash(c_scanRecordPool)
{
@@ -206,7 +198,6 @@ Dblqh::Dblqh(const class Configuration & conf):
#ifdef VM_TRACE
addRecSignal(GSN_TESTSIG, &Dblqh::execTESTSIG);
#endif
- addRecSignal(GSN_LQH_RESTART_OP, &Dblqh::execLQH_RESTART_OP);
addRecSignal(GSN_CONTINUEB, &Dblqh::execCONTINUEB);
addRecSignal(GSN_START_RECREQ, &Dblqh::execSTART_RECREQ);
addRecSignal(GSN_START_RECCONF, &Dblqh::execSTART_RECCONF);
@@ -281,19 +272,8 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_LQH_TRANSREQ, &Dblqh::execLQH_TRANSREQ);
addRecSignal(GSN_TRANSID_AI, &Dblqh::execTRANSID_AI);
addRecSignal(GSN_INCL_NODEREQ, &Dblqh::execINCL_NODEREQ);
- addRecSignal(GSN_ACC_LCPCONF, &Dblqh::execACC_LCPCONF);
- addRecSignal(GSN_ACC_LCPREF, &Dblqh::execACC_LCPREF);
- addRecSignal(GSN_ACC_LCPSTARTED, &Dblqh::execACC_LCPSTARTED);
- addRecSignal(GSN_ACC_CONTOPCONF, &Dblqh::execACC_CONTOPCONF);
- addRecSignal(GSN_LCP_FRAGIDCONF, &Dblqh::execLCP_FRAGIDCONF);
- addRecSignal(GSN_LCP_FRAGIDREF, &Dblqh::execLCP_FRAGIDREF);
- addRecSignal(GSN_LCP_HOLDOPCONF, &Dblqh::execLCP_HOLDOPCONF);
- addRecSignal(GSN_LCP_HOLDOPREF, &Dblqh::execLCP_HOLDOPREF);
- addRecSignal(GSN_TUP_PREPLCPCONF, &Dblqh::execTUP_PREPLCPCONF);
- addRecSignal(GSN_TUP_PREPLCPREF, &Dblqh::execTUP_PREPLCPREF);
- addRecSignal(GSN_TUP_LCPCONF, &Dblqh::execTUP_LCPCONF);
- addRecSignal(GSN_TUP_LCPREF, &Dblqh::execTUP_LCPREF);
- addRecSignal(GSN_TUP_LCPSTARTED, &Dblqh::execTUP_LCPSTARTED);
+ 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);
@@ -301,12 +281,6 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_START_FRAGREQ, &Dblqh::execSTART_FRAGREQ);
addRecSignal(GSN_START_RECREF, &Dblqh::execSTART_RECREF);
- addRecSignal(GSN_SR_FRAGIDCONF, &Dblqh::execSR_FRAGIDCONF);
- addRecSignal(GSN_SR_FRAGIDREF, &Dblqh::execSR_FRAGIDREF);
- addRecSignal(GSN_ACC_SRCONF, &Dblqh::execACC_SRCONF);
- addRecSignal(GSN_ACC_SRREF, &Dblqh::execACC_SRREF);
- addRecSignal(GSN_TUP_SRCONF, &Dblqh::execTUP_SRCONF);
- addRecSignal(GSN_TUP_SRREF, &Dblqh::execTUP_SRREF);
addRecSignal(GSN_GCP_SAVEREQ, &Dblqh::execGCP_SAVEREQ);
addRecSignal(GSN_FSOPENCONF, &Dblqh::execFSOPENCONF);
addRecSignal(GSN_FSCLOSECONF, &Dblqh::execFSCLOSECONF);
@@ -336,6 +310,18 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_READ_PSEUDO_REQ, &Dblqh::execREAD_PSEUDO_REQ);
+ addRecSignal(GSN_BUILDINDXREF, &Dblqh::execBUILDINDXREF);
+ addRecSignal(GSN_BUILDINDXCONF, &Dblqh::execBUILDINDXCONF);
+
+ 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);
+
initData();
#ifdef VM_TRACE
@@ -347,7 +333,6 @@ Dblqh::Dblqh(const class Configuration & conf):
&fragptr,
&gcpPtr,
&lcpPtr,
- &lcpLocptr,
&logPartPtr,
&logFilePtr,
&lfoPtr,
@@ -381,11 +366,6 @@ Dblqh::~Dblqh()
sizeof(Databuf),
cdatabufFileSize);
- deallocRecord((void**)&fragrecord,
- "Fragrecord",
- sizeof(Fragrecord),
- cfragrecFileSize);
-
deallocRecord((void**)&gcpRecord,
"GcpRecord",
sizeof(GcpRecord),
@@ -401,11 +381,6 @@ Dblqh::~Dblqh()
sizeof(LcpRecord),
clcpFileSize);
- deallocRecord((void**)&lcpLocRecord,
- "LcpLocRecord",
- sizeof(LcpLocRecord),
- clcpLocrecFileSize);
-
deallocRecord((void**)&logPartRecord,
"LogPartRecord",
sizeof(LogPartRecord),
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 7177f6fd46c..822f32d9ccd 100644
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -53,8 +53,14 @@
#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>
// Use DEBUG to print messages that should be
@@ -235,7 +241,7 @@ void Dblqh::execCONTINUEB(Signal* signal)
tcConnectptr.i = logPartPtr.p->firstLogQueue;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if ((cCommitBlocked == true) &&
(fragptr.p->fragActiveStatus == ZTRUE)) {
jam();
@@ -389,26 +395,13 @@ void Dblqh::execCONTINUEB(Signal* signal)
initGcpRecLab(signal);
return;
break;
- case ZRESTART_OPERATIONS_AFTER_STOP:
- jam();
- tcConnectptr.i = data0;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- if (tcConnectptr.p->listState != TcConnectionrec::WAIT_QUEUE_LIST) {
- jam();
- return;
- }//if
- releaseWaitQueue(signal);
- linkActiveFrag(signal);
- restartOperationsAfterStopLab(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;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
checkLcpStopBlockedLab(signal);
return;
case ZSCAN_MARKERS:
@@ -492,11 +485,16 @@ void Dblqh::execSTTOR(Signal* signal)
case ZSTART_PHASE1:
jam();
cstartPhase = tstartPhase;
- sttorStartphase1Lab(signal);
c_tup = (Dbtup*)globalData.getBlock(DBTUP);
- ndbrequire(c_tup != 0);
+ c_acc = (Dbacc*)globalData.getBlock(DBACC);
+ ndbrequire(c_tup != 0 && c_acc != 0);
+ sendsttorryLab(signal);
return;
break;
+ case 4:
+ jam();
+ define_backup(signal);
+ break;
default:
jam();
/*empty*/;
@@ -506,6 +504,42 @@ void Dblqh::execSTTOR(Signal* signal)
}//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;
+ 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 */
/* ***************************************> */
@@ -571,21 +605,11 @@ void Dblqh::execNDB_STTOR(Signal* signal)
}//switch
}//Dblqh::execNDB_STTOR()
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* +++++++ START PHASE 1 +++++++ */
-/* LOAD OUR BLOCK REFERENCE AND OUR PROCESSOR ID */
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-void Dblqh::sttorStartphase1Lab(Signal* signal)
-{
- sendsttorryLab(signal);
- return;
-}//Dblqh::sttorStartphase1Lab()
-
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
-/* +++++++ START PHASE 2 +++++++ */
-/* */
-/* INITIATE ALL RECORDS WITHIN THE BLOCK */
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/* +++++++ START PHASE 2 +++++++ */
+/* */
+/* INITIATE ALL RECORDS WITHIN THE BLOCK */
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
void Dblqh::startphase1Lab(Signal* signal, Uint32 _dummy, Uint32 ownNodeId)
{
UintR Ti;
@@ -854,8 +878,9 @@ void Dblqh::sendsttorryLab(Signal* signal)
signal->theData[1] = 3; /* BLOCK CATEGORY */
signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
signal->theData[3] = ZSTART_PHASE1;
- signal->theData[4] = 255;
- sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
+ signal->theData[4] = 4;
+ signal->theData[5] = 255;
+ sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
return;
}//Dblqh::sendsttorryLab()
@@ -889,7 +914,6 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
&cnoLogFiles));
ndbrequire(cnoLogFiles > 0);
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &cfragrecFileSize));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TABLE, &ctabrecFileSize));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_TC_CONNECT,
&ctcConnectrecFileSize));
@@ -899,6 +923,10 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &c_diskless));
+ Uint32 tmp= 0;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_LQH_FRAG, &tmp));
+ c_fragment_pool.setSize(tmp);
+
initRecords();
initialiseRecordsLab(signal, 0, ref, senderData);
@@ -946,11 +974,11 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
Uint32 noOfKeyAttr = req->noOfKeyAttr;
Uint32 noOfNewAttr = req->noOfNewAttr;
Uint32 checksumIndicator = req->checksumIndicator;
- Uint32 noOfAttributeGroups = req->noOfAttributeGroups;
Uint32 gcpIndicator = req->GCPIndicator;
Uint32 startGci = req->startGci;
Uint32 tableType = req->tableType;
Uint32 primaryTableId = req->primaryTableId;
+ Uint32 tablespace= req->tablespace_id;
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
bool tempTable = ((reqinfo & LqhFragReq::TemporaryTable) != 0);
@@ -959,8 +987,10 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
if (tabptr.p->tableStatus == Tablerec::NOT_DEFINED){
tabptr.p->tableStatus = Tablerec::ADD_TABLE_ONGOING;
tabptr.p->tableType = tableType;
- tabptr.p->primaryTableId = primaryTableId;
+ 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){
@@ -1053,16 +1083,14 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
addfragptr.p->noOfKeyAttr = noOfKeyAttr;
addfragptr.p->noOfNewAttr = noOfNewAttr;
addfragptr.p->checksumIndicator = checksumIndicator;
- addfragptr.p->noOfAttributeGroups = noOfAttributeGroups;
addfragptr.p->GCPIndicator = gcpIndicator;
addfragptr.p->lh3DistrBits = tlhstar;
addfragptr.p->tableType = tableType;
addfragptr.p->primaryTableId = primaryTableId;
+ addfragptr.p->tablespace_id= tablespace;
//
- addfragptr.p->tup1Connectptr = RNIL;
- addfragptr.p->tup2Connectptr = RNIL;
- addfragptr.p->tux1Connectptr = RNIL;
- addfragptr.p->tux2Connectptr = RNIL;
+ addfragptr.p->tupConnectptr = RNIL;
+ addfragptr.p->tuxConnectptr = RNIL;
if (DictTabInfo::isTable(tableType) ||
DictTabInfo::isHashIndex(tableType)) {
@@ -1080,21 +1108,18 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
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. */
- /* ----------------------------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+ /* 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);
+ signal, AccFragReq::SignalLength, JBB);
return;
}
if (DictTabInfo::isOrderedIndex(tableType)) {
jam();
- // NOTE: next 2 lines stolen from ACC
- addfragptr.p->fragid1 = (fragId << 1) | 0;
- addfragptr.p->fragid2 = (fragId << 1) | 1;
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
+ addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
sendAddFragReq(signal);
return;
}
@@ -1109,22 +1134,17 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
jamEntry();
addfragptr.i = signal->theData[0];
Uint32 taccConnectptr = signal->theData[1];
- Uint32 fragId1 = signal->theData[2];
- Uint32 fragId2 = signal->theData[3];
+ //Uint32 fragId1 = signal->theData[2];
Uint32 accFragPtr1 = signal->theData[4];
- Uint32 accFragPtr2 = signal->theData[5];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
addfragptr.p->accConnectptr = taccConnectptr;
- addfragptr.p->fragid1 = fragId1;
- addfragptr.p->fragid2 = fragId2;
fragptr.i = addfragptr.p->fragmentPtr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- fragptr.p->accFragptr[0] = accFragPtr1;
- fragptr.p->accFragptr[1] = accFragPtr2;
+ c_fragment_pool.getPtr(fragptr);
+ fragptr.p->accFragptr = accFragPtr1;
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
+ addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUP;
sendAddFragReq(signal);
}//Dblqh::execACCFRAGCONF()
@@ -1137,50 +1157,27 @@ void Dblqh::execTUPFRAGCONF(Signal* signal)
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 */
+ //Uint32 localFragId = signal->theData[3]; /* LOCAL FRAGMENT ID */
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
fragptr.i = addfragptr.p->fragmentPtr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (localFragId == addfragptr.p->fragid1) {
- jam();
- fragptr.p->tupFragptr[0] = tupFragPtr;
- } else if (localFragId == addfragptr.p->fragid2) {
- jam();
- fragptr.p->tupFragptr[1] = tupFragPtr;
- } else {
- ndbrequire(false);
- return;
- }//if
+ c_fragment_pool.getPtr(fragptr);
+ fragptr.p->tupFragptr = tupFragPtr;
switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::WAIT_TWO_TUP:
+ case AddFragRecord::WAIT_TUP:
jam();
- fragptr.p->tupFragptr[0] = tupFragPtr;
- addfragptr.p->tup1Connectptr = tupConnectptr;
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_ONE_TUP;
- sendAddFragReq(signal);
- break;
- case AddFragRecord::WAIT_ONE_TUP:
- jam();
- fragptr.p->tupFragptr[1] = tupFragPtr;
- addfragptr.p->tup2Connectptr = tupConnectptr;
+ fragptr.p->tupFragptr = tupFragPtr;
+ addfragptr.p->tupConnectptr = tupConnectptr;
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUX;
+ addfragptr.p->addfragStatus = AddFragRecord::WAIT_TUX;
sendAddFragReq(signal);
break;
}
goto done_with_frag;
break;
- case AddFragRecord::WAIT_TWO_TUX:
+ case AddFragRecord::WAIT_TUX:
jam();
- fragptr.p->tuxFragptr[0] = tupFragPtr;
- addfragptr.p->tux1Connectptr = tupConnectptr;
- addfragptr.p->addfragStatus = AddFragRecord::WAIT_ONE_TUX;
- sendAddFragReq(signal);
- break;
- case AddFragRecord::WAIT_ONE_TUX:
- jam();
- fragptr.p->tuxFragptr[1] = tupFragPtr;
- addfragptr.p->tux2Connectptr = tupConnectptr;
+ fragptr.p->tuxFragptr = tupFragPtr;
+ addfragptr.p->tuxConnectptr = tupConnectptr;
goto done_with_frag;
break;
done_with_frag:
@@ -1193,7 +1190,7 @@ void Dblqh::execTUPFRAGCONF(Signal* signal)
conf->senderData = addfragptr.p->dictConnectptr;
conf->lqhFragPtr = addfragptr.i;
sendSignal(addfragptr.p->dictBlockref, GSN_LQHFRAGCONF,
- signal, LqhFragConf::SignalLength, JBB);
+ signal, LqhFragConf::SignalLength, JBB);
}
break;
default:
@@ -1218,9 +1215,8 @@ void
Dblqh::sendAddFragReq(Signal* signal)
{
fragptr.i = addfragptr.p->fragmentPtr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUP ||
- addfragptr.p->addfragStatus == AddFragRecord::WAIT_ONE_TUP) {
+ c_fragment_pool.getPtr(fragptr);
+ if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUP){
if (DictTabInfo::isTable(addfragptr.p->tableType) ||
DictTabInfo::isHashIndex(addfragptr.p->tableType)) {
jam();
@@ -1229,9 +1225,7 @@ Dblqh::sendAddFragReq(Signal* signal)
signal->theData[2] = 0; /* ADD TABLE */
signal->theData[3] = addfragptr.p->tabId;
signal->theData[4] = addfragptr.p->noOfAttr;
- signal->theData[5] =
- addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUP
- ? addfragptr.p->fragid1 : addfragptr.p->fragid2;
+ signal->theData[5] = addfragptr.p->addFragid;
signal->theData[6] = (addfragptr.p->noOfAllocPages >> 1) + 1;
signal->theData[7] = addfragptr.p->noOfNull;
signal->theData[8] = addfragptr.p->schemaVer;
@@ -1240,8 +1234,9 @@ Dblqh::sendAddFragReq(Signal* signal)
signal->theData[11] = addfragptr.p->checksumIndicator;
signal->theData[12] = addfragptr.p->noOfAttributeGroups;
signal->theData[13] = addfragptr.p->GCPIndicator;
+ signal->theData[14] = addfragptr.p->tablespace_id;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
- signal, TupFragReq::SignalLength, JBB);
+ signal, TupFragReq::SignalLength, JBB);
return;
}
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
@@ -1251,9 +1246,7 @@ Dblqh::sendAddFragReq(Signal* signal)
signal->theData[2] = 0; /* ADD TABLE */
signal->theData[3] = addfragptr.p->tabId;
signal->theData[4] = 1; /* ordered index: one array attr */
- signal->theData[5] =
- addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUP
- ? addfragptr.p->fragid1 : addfragptr.p->fragid2;
+ signal->theData[5] = addfragptr.p->addFragid;
signal->theData[6] = (addfragptr.p->noOfAllocPages >> 1) + 1;
signal->theData[7] = 0; /* ordered index: no nullable */
signal->theData[8] = addfragptr.p->schemaVer;
@@ -1263,12 +1256,11 @@ Dblqh::sendAddFragReq(Signal* signal)
signal->theData[12] = addfragptr.p->noOfAttributeGroups;
signal->theData[13] = addfragptr.p->GCPIndicator;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
- signal, TupFragReq::SignalLength, JBB);
+ signal, TupFragReq::SignalLength, JBB);
return;
}
}
- if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX ||
- addfragptr.p->addfragStatus == AddFragRecord::WAIT_ONE_TUX) {
+ if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TUX) {
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
jam();
TuxFragReq* const tuxreq = (TuxFragReq*)signal->getDataPtrSend();
@@ -1278,26 +1270,22 @@ Dblqh::sendAddFragReq(Signal* signal)
tuxreq->tableId = addfragptr.p->tabId;
ndbrequire(addfragptr.p->noOfAttr >= 2);
tuxreq->noOfAttr = addfragptr.p->noOfAttr - 1; /* skip NDB$TNODE */
- tuxreq->fragId =
- addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX
- ? addfragptr.p->fragid1: addfragptr.p->fragid2;
+ 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 =
- addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX ?
- fragptr.p->tupFragptr[0] : fragptr.p->tupFragptr[1];
+ tuxreq->tupIndexFragPtrI = fragptr.p->tupFragptr;
// pointers to table fragments in TUP and ACC
FragrecordPtr tFragPtr;
tFragPtr.i = fragptr.p->tableFragptr;
- ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
- tuxreq->tupTableFragPtrI[0] = tFragPtr.p->tupFragptr[0];
- tuxreq->tupTableFragPtrI[1] = tFragPtr.p->tupFragptr[1];
- tuxreq->accTableFragPtrI[0] = tFragPtr.p->accFragptr[0];
- tuxreq->accTableFragPtrI[1] = tFragPtr.p->accFragptr[1];
+ 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);
+ signal, TuxFragReq::SignalLength, JBB);
return;
}
}
@@ -1326,11 +1314,18 @@ void Dblqh::execLQHADDATTREQ(Signal* signal)
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_WAIT1;
+ addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
sendAddAttrReq(signal);
}//Dblqh::execLQHADDATTREQ()
@@ -1345,35 +1340,18 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
const bool lastAttr = signal->theData[1];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::TUP_ATTR_WAIT1:
- jam();
- if (lastAttr)
- addfragptr.p->tup1Connectptr = RNIL;
- addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT2;
- sendAddAttrReq(signal);
- break;
- case AddFragRecord::TUP_ATTR_WAIT2:
- jam();
- if (lastAttr)
- addfragptr.p->tup2Connectptr = RNIL;
+ case AddFragRecord::TUP_ATTR_WAIT:
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
- addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT1;
+ addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT;
sendAddAttrReq(signal);
break;
}
goto done_with_attr;
break;
- case AddFragRecord::TUX_ATTR_WAIT1:
- jam();
- if (lastAttr)
- addfragptr.p->tux1Connectptr = RNIL;
- addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT2;
- sendAddAttrReq(signal);
- break;
- case AddFragRecord::TUX_ATTR_WAIT2:
+ case AddFragRecord::TUX_ATTR_WAIT:
jam();
if (lastAttr)
- addfragptr.p->tux2Connectptr = RNIL;
+ addfragptr.p->tuxConnectptr = RNIL;
goto done_with_attr;
break;
done_with_attr:
@@ -1383,7 +1361,7 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
if (addfragptr.p->attrSentToTup < addfragptr.p->attrReceived) {
// more in this batch
jam();
- addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT1;
+ addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT;
sendAddAttrReq(signal);
} else if (addfragptr.p->totalAttrReceived < addfragptr.p->noOfAttr) {
// more batches to receive
@@ -1394,10 +1372,10 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
conf->senderAttrPtr = addfragptr.p->m_senderAttrPtr;
conf->fragId = addfragptr.p->addFragid;
sendSignal(addfragptr.p->dictBlockref, GSN_LQHADDATTCONF,
- signal, LqhAddAttrConf::SignalLength, JBB);
+ signal, LqhAddAttrConf::SignalLength, JBB);
} else {
fragptr.i = addfragptr.p->fragmentPtr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ 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
@@ -1451,18 +1429,15 @@ Dblqh::sendAddAttrReq(Signal* signal)
const Uint32 attrId = entry.attrId & 0xffff;
const Uint32 primaryAttrId = entry.attrId >> 16;
fragptr.i = addfragptr.p->fragmentPtr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (addfragptr.p->addfragStatus == AddFragRecord::TUP_ATTR_WAIT1 ||
- addfragptr.p->addfragStatus == AddFragRecord::TUP_ATTR_WAIT2) {
+ 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->addfragStatus == AddFragRecord::TUP_ATTR_WAIT1
- ? addfragptr.p->tup1Connectptr : addfragptr.p->tup2Connectptr;
+ tupreq->tupConnectPtr = addfragptr.p->tupConnectptr;
tupreq->notused1 = 0;
tupreq->attrId = attrId;
tupreq->attrDescriptor = entry.attrDescriptor;
@@ -1479,27 +1454,24 @@ Dblqh::sendAddAttrReq(Signal* signal)
tupconf->userPtr = addfragptr.i;
tupconf->lastAttr = false;
sendSignal(reference(), GSN_TUP_ADD_ATTCONF,
- signal, TupAddAttrConf::SignalLength, JBB);
+ signal, TupAddAttrConf::SignalLength, JBB);
return;
}
}
- if (addfragptr.p->addfragStatus == AddFragRecord::TUX_ATTR_WAIT1 ||
- addfragptr.p->addfragStatus == AddFragRecord::TUX_ATTR_WAIT2) {
+ 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->addfragStatus == AddFragRecord::TUX_ATTR_WAIT1
- ? addfragptr.p->tux1Connectptr : addfragptr.p->tux2Connectptr;
+ 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);
+ signal, TuxAddAttrReq::SignalLength, JBB);
return;
}
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType) &&
@@ -1510,7 +1482,7 @@ Dblqh::sendAddAttrReq(Signal* signal)
tuxconf->userPtr = addfragptr.i;
tuxconf->lastAttr = false;
sendSignal(reference(), GSN_TUX_ADD_ATTRCONF,
- signal, TuxAddAttrConf::SignalLength, JBB);
+ signal, TuxAddAttrConf::SignalLength, JBB);
return;
}
}
@@ -1579,31 +1551,19 @@ void Dblqh::fragrefLab(Signal* signal,
void Dblqh::abortAddFragOps(Signal* signal)
{
fragptr.i = addfragptr.p->fragmentPtr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
signal->theData[0] = (Uint32)-1;
- if (addfragptr.p->tup1Connectptr != RNIL) {
- jam();
- signal->theData[1] = addfragptr.p->tup1Connectptr;
- sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
- addfragptr.p->tup1Connectptr = RNIL;
- }
- if (addfragptr.p->tup2Connectptr != RNIL) {
+ if (addfragptr.p->tupConnectptr != RNIL) {
jam();
- signal->theData[1] = addfragptr.p->tup2Connectptr;
+ signal->theData[1] = addfragptr.p->tupConnectptr;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
- addfragptr.p->tup2Connectptr = RNIL;
+ addfragptr.p->tupConnectptr = RNIL;
}
- if (addfragptr.p->tux1Connectptr != RNIL) {
+ if (addfragptr.p->tuxConnectptr != RNIL) {
jam();
- signal->theData[1] = addfragptr.p->tux1Connectptr;
+ signal->theData[1] = addfragptr.p->tuxConnectptr;
sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
- addfragptr.p->tux1Connectptr = RNIL;
- }
- if (addfragptr.p->tux2Connectptr != RNIL) {
- jam();
- signal->theData[1] = addfragptr.p->tux2Connectptr;
- sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
- addfragptr.p->tux2Connectptr = RNIL;
+ addfragptr.p->tuxConnectptr = RNIL;
}
}
@@ -1638,21 +1598,15 @@ void Dblqh::execTUPFRAGREF(Signal* signal)
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
terrorCode = signal->theData[1];
fragptr.i = addfragptr.p->fragmentPtr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
addfragptr.p->addfragErrorCode = terrorCode;
// no operation to release, just add some jams
switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::WAIT_TWO_TUP:
+ case AddFragRecord::WAIT_TUP:
jam();
break;
- case AddFragRecord::WAIT_ONE_TUP:
- jam();
- break;
- case AddFragRecord::WAIT_TWO_TUX:
- jam();
- break;
- case AddFragRecord::WAIT_ONE_TUX:
+ case AddFragRecord::WAIT_TUX:
jam();
break;
default:
@@ -1691,25 +1645,15 @@ void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
// operation was released on the other side
switch (addfragptr.p->addfragStatus) {
- case AddFragRecord::TUP_ATTR_WAIT1:
- jam();
- ndbrequire(addfragptr.p->tup1Connectptr != RNIL);
- addfragptr.p->tup1Connectptr = RNIL;
- break;
- case AddFragRecord::TUP_ATTR_WAIT2:
- jam();
- ndbrequire(addfragptr.p->tup2Connectptr != RNIL);
- addfragptr.p->tup2Connectptr = RNIL;
- break;
- case AddFragRecord::TUX_ATTR_WAIT1:
+ case AddFragRecord::TUP_ATTR_WAIT:
jam();
- ndbrequire(addfragptr.p->tux1Connectptr != RNIL);
- addfragptr.p->tux1Connectptr = RNIL;
+ ndbrequire(addfragptr.p->tupConnectptr != RNIL);
+ addfragptr.p->tupConnectptr = RNIL;
break;
- case AddFragRecord::TUX_ATTR_WAIT2:
+ case AddFragRecord::TUX_ATTR_WAIT:
jam();
- ndbrequire(addfragptr.p->tux2Connectptr != RNIL);
- addfragptr.p->tux2Connectptr = RNIL;
+ ndbrequire(addfragptr.p->tuxConnectptr != RNIL);
+ addfragptr.p->tuxConnectptr = RNIL;
break;
default:
ndbrequire(false);
@@ -2023,7 +1967,7 @@ void Dblqh::removeTable(Uint32 tableId)
tabptr.i = tableId;
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
- for (Uint32 i = (MAX_FRAG_PER_NODE - 1); (Uint32)~i; i--) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
jam();
if (tabptr.p->fragid[i] != ZNIL) {
jam();
@@ -2105,146 +2049,11 @@ void Dblqh::execTIME_SIGNAL(Signal* signal)
<< " cLqhTimeOutCount = " << cLqhTimeOutCount << endl
<< " tcTimer="<<tTcConptr.p->tcTimer<<endl
<< " tcTimer+120="<<tTcConptr.p->tcTimer + 120<<endl;
-
- ndbout << " transactionState = " << tTcConptr.p->transactionState<<endl;
- ndbout << " operation = " << tTcConptr.p->operation<<endl;
- ndbout << " tcNodeFailrec = " << tTcConptr.p->tcNodeFailrec
- << " seqNoReplica = " << tTcConptr.p->seqNoReplica
- << " simpleRead = " << tTcConptr.p->simpleRead
- << endl;
- ndbout << " replicaType = " << tTcConptr.p->replicaType
- << " reclenAiLqhkey = " << tTcConptr.p->reclenAiLqhkey
- << " opExec = " << tTcConptr.p->opExec
- << endl;
- ndbout << " opSimple = " << tTcConptr.p->opSimple
- << " nextSeqNoReplica = " << tTcConptr.p->nextSeqNoReplica
- << " lockType = " << tTcConptr.p->lockType
- << " localFragptr = " << tTcConptr.p->localFragptr
- << endl;
- ndbout << " lastReplicaNo = " << tTcConptr.p->lastReplicaNo
- << " indTakeOver = " << tTcConptr.p->indTakeOver
- << " dirtyOp = " << tTcConptr.p->dirtyOp
- << endl;
- ndbout << " activeCreat = " << tTcConptr.p->activeCreat
- << " tcBlockref = " << hex << tTcConptr.p->tcBlockref
- << " reqBlockref = " << hex << tTcConptr.p->reqBlockref
- << " primKeyLen = " << tTcConptr.p->primKeyLen
- << endl;
- ndbout << " nextReplica = " << tTcConptr.p->nextReplica
- << " tcBlockref = " << hex << tTcConptr.p->tcBlockref
- << " reqBlockref = " << hex << tTcConptr.p->reqBlockref
- << " primKeyLen = " << tTcConptr.p->primKeyLen
- << endl;
- ndbout << " logStopPageNo = " << tTcConptr.p->logStopPageNo
- << " logStartPageNo = " << tTcConptr.p->logStartPageNo
- << " logStartPageIndex = " << tTcConptr.p->logStartPageIndex
- << endl;
- ndbout << " errorCode = " << tTcConptr.p->errorCode
- << " clientBlockref = " << hex << tTcConptr.p->clientBlockref
- << " applRef = " << hex << tTcConptr.p->applRef
- << " totSendlenAi = " << tTcConptr.p->totSendlenAi
- << endl;
- ndbout << " totReclenAi = " << tTcConptr.p->totReclenAi
- << " tcScanRec = " << tTcConptr.p->tcScanRec
- << " tcScanInfo = " << tTcConptr.p->tcScanInfo
- << " tcOprec = " << hex << tTcConptr.p->tcOprec
- << endl;
- ndbout << " tableref = " << tTcConptr.p->tableref
- << " simpleTcConnect = " << tTcConptr.p->simpleTcConnect
- << " storedProcId = " << tTcConptr.p->storedProcId
- << " schemaVersion = " << tTcConptr.p->schemaVersion
- << endl;
- ndbout << " reqinfo = " << tTcConptr.p->reqinfo
- << " reqRef = " << tTcConptr.p->reqRef
- << " readlenAi = " << tTcConptr.p->readlenAi
- << " prevTc = " << tTcConptr.p->prevTc
- << endl;
- ndbout << " prevLogTcrec = " << tTcConptr.p->prevLogTcrec
- << " prevHashRec = " << tTcConptr.p->prevHashRec
- << " nodeAfterNext0 = " << tTcConptr.p->nodeAfterNext[0]
- << " nodeAfterNext1 = " << tTcConptr.p->nodeAfterNext[1]
- << endl;
- ndbout << " nextTcConnectrec = " << tTcConptr.p->nextTcConnectrec
- << " nextTc = " << tTcConptr.p->nextTc
- << " nextTcLogQueue = " << tTcConptr.p->nextTcLogQueue
- << " nextLogTcrec = " << tTcConptr.p->nextLogTcrec
- << endl;
- ndbout << " nextHashRec = " << tTcConptr.p->nextHashRec
- << " logWriteState = " << tTcConptr.p->logWriteState
- << " logStartFileNo = " << tTcConptr.p->logStartFileNo
- << " listState = " << tTcConptr.p->listState
- << endl;
- ndbout << " lastAttrinbuf = " << tTcConptr.p->lastAttrinbuf
- << " lastTupkeybuf = " << tTcConptr.p->lastTupkeybuf
- << " hashValue = " << tTcConptr.p->hashValue
- << endl;
- ndbout << " gci = " << tTcConptr.p->gci
- << " fragmentptr = " << tTcConptr.p->fragmentptr
- << " fragmentid = " << tTcConptr.p->fragmentid
- << " firstTupkeybuf = " << tTcConptr.p->firstTupkeybuf
- << endl;
- ndbout << " firstAttrinbuf = " << tTcConptr.p->firstAttrinbuf
- << " currTupAiLen = " << tTcConptr.p->currTupAiLen
- << " currReclenAi = " << tTcConptr.p->currReclenAi
- << endl;
- ndbout << " tcTimer = " << tTcConptr.p->tcTimer
- << " clientConnectrec = " << tTcConptr.p->clientConnectrec
- << " applOprec = " << hex << tTcConptr.p->applOprec
- << " abortState = " << tTcConptr.p->abortState
- << endl;
- ndbout << " transid0 = " << hex << tTcConptr.p->transid[0]
- << " transid1 = " << hex << tTcConptr.p->transid[1]
- << " tupkeyData0 = " << tTcConptr.p->tupkeyData[0]
- << " tupkeyData1 = " << tTcConptr.p->tupkeyData[1]
- << endl;
- ndbout << " tupkeyData2 = " << tTcConptr.p->tupkeyData[2]
- << " tupkeyData3 = " << tTcConptr.p->tupkeyData[3]
- << endl;
- switch (tTcConptr.p->transactionState) {
-
- case TcConnectionrec::SCAN_STATE_USED:
- if (tTcConptr.p->tcScanRec < cscanrecFileSize){
- ScanRecordPtr TscanPtr;
- c_scanRecordPool.getPtr(TscanPtr, tTcConptr.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
- << " scanLocalFragid="<<TscanPtr.p->scanLocalFragid
- << 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;
- }//switch
+ signal->theData[0] = 2307;
+ signal->theData[1] = tTcConptr.i;
+ execDUMP_STATE_ORD(signal);
+
// Reset the timer
tTcConptr.p->tcTimer = 0;
}//if
@@ -2630,9 +2439,9 @@ Dblqh::execREAD_PSEUDO_REQ(Signal* signal){
jam();
FragrecordPtr regFragptr;
regFragptr.i = regTcPtr.p->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(regFragptr);
- signal->theData[0] = regFragptr.p->accFragptr[regTcPtr.p->localFragptr];
+ signal->theData[0] = regFragptr.p->accFragptr;
EXECUTE_DIRECT(DBACC, GSN_READ_PSEUDO_REQ, signal, 2);
}
else
@@ -2659,6 +2468,12 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
jamEntry();
tcConnectptr.i = tcIndex;
ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
+
+ FragrecordPtr regFragptr;
+ regFragptr.i = tcConnectptr.p->fragmentptr;
+ c_fragment_pool.getPtr(regFragptr);
+ fragptr = regFragptr;
+
switch (tcConnectptr.p->transactionState) {
case TcConnectionrec::WAIT_TUP:
jam();
@@ -2680,7 +2495,6 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
// Abort was not ready to start until this signal came back. Now we are ready
// to start the abort.
/* ------------------------------------------------------------------------- */
- releaseActiveFrag(signal);
abortCommonLab(signal);
break;
case TcConnectionrec::WAIT_ACC_ABORT:
@@ -2707,10 +2521,15 @@ void Dblqh::execTUPKEYREF(Signal* signal)
tcConnectptr.i = tupKeyRef->userRef;
terrorCode = tupKeyRef->errorCode;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+
+ FragrecordPtr regFragptr;
+ regFragptr.i = tcConnectptr.p->fragmentptr;
+ c_fragment_pool.getPtr(regFragptr);
+ fragptr = regFragptr;
+
switch (tcConnectptr.p->transactionState) {
case TcConnectionrec::WAIT_TUP:
jam();
- releaseActiveFrag(signal);
abortErrorLab(signal);
break;
case TcConnectionrec::COPY_TUPKEY:
@@ -2726,7 +2545,6 @@ void Dblqh::execTUPKEYREF(Signal* signal)
// Abort was not ready to start until this signal came back. Now we are ready
// to start the abort.
/* ------------------------------------------------------------------------- */
- releaseActiveFrag(signal);
abortCommonLab(signal);
break;
case TcConnectionrec::WAIT_ACC_ABORT:
@@ -2859,6 +2677,7 @@ 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) {
@@ -2877,7 +2696,7 @@ void Dblqh::sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref)
lqhKeyConf = (LqhKeyConf *)
&Thostptr.p->packedWordsTc[Thostptr.p->noOfPackedWordsTc];
Thostptr.p->noOfPackedWordsTc += LqhKeyConf::SignalLength;
- } else {
+ } else if(refToBlock(atcBlockref) == DBLQH){
jam();
/*******************************************************************
// This signal was intended for DBLQH as part of log execution or
@@ -2893,7 +2712,10 @@ void Dblqh::sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref)
lqhKeyConf = (LqhKeyConf *)
&Thostptr.p->packedWordsLqh[Thostptr.p->noOfPackedWordsLqh];
Thostptr.p->noOfPackedWordsLqh += LqhKeyConf::SignalLength;
- }//if
+ } else {
+ packed= false;
+ lqhKeyConf = (LqhKeyConf *)signal->getDataPtrSend();
+ }
Uint32 ptrAndType = tcConnectptr.i | (ZLQHKEYCONF << 28);
Uint32 tcOprec = tcConnectptr.p->tcOprec;
Uint32 ownRef = cownref;
@@ -2908,6 +2730,21 @@ void Dblqh::sendLqhkeyconfTc(Signal* signal, BlockReference atcBlockref)
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()
/* ************************************************************************>>
@@ -2925,6 +2762,16 @@ void Dblqh::execKEYINFO(Signal* signal)
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 &&
@@ -2937,10 +2784,10 @@ void Dblqh::execKEYINFO(Signal* signal)
/*****************************************************************************/
return;
}//if
- Uint32 errorCode = handleLongTupKey(signal,
- (Uint32)regTcPtr->save1,
- (Uint32)regTcPtr->primKeyLen,
- &signal->theData[3]);
+
+ Uint32 errorCode =
+ handleLongTupKey(signal, data, len);
+
if (errorCode != 0) {
if (errorCode == 1) {
jam();
@@ -2958,7 +2805,7 @@ void Dblqh::execKEYINFO(Signal* signal)
{
FragrecordPtr regFragptr;
regFragptr.i = regTcPtr->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(regFragptr);
fragptr = regFragptr;
endgettupkeyLab(signal);
}
@@ -2969,14 +2816,14 @@ void Dblqh::execKEYINFO(Signal* signal)
/* FILL IN KEY DATA INTO DATA BUFFERS. */
/* ------------------------------------------------------------------------- */
Uint32 Dblqh::handleLongTupKey(Signal* signal,
- Uint32 keyLength,
- Uint32 primKeyLength,
- Uint32* dataPtr)
+ Uint32* dataPtr,
+ Uint32 len)
{
TcConnectionrec * const regTcPtr = tcConnectptr.p;
Uint32 dataPos = 0;
- while (true) {
- keyLength += 4;
+ Uint32 total = regTcPtr->save1 + len;
+ Uint32 primKeyLen = regTcPtr->primKeyLen;
+ while (dataPos < len) {
if (cfirstfreeDatabuf == RNIL) {
jam();
return ZGET_DATAREC_ERROR;
@@ -2992,18 +2839,10 @@ Uint32 Dblqh::handleLongTupKey(Signal* signal,
regDataPtr->data[2] = data2;
regDataPtr->data[3] = data3;
dataPos += 4;
- if (keyLength < primKeyLength) {
- if (dataPos > 16) {
- jam();
-/* SAVE STATE AND WAIT FOR KEYINFO */
- regTcPtr->save1 = keyLength;
- return 1;
- }//if
- } else {
- jam();
- return 0;
- }//if
- }//while
+ }
+
+ regTcPtr->save1 = total;
+ return (total >= primKeyLen ? 0 : 1);
}//Dblqh::handleLongTupKey()
/* ------------------------------------------------------------------------- */
@@ -3027,22 +2866,26 @@ void Dblqh::execATTRINFO(Signal* signal)
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 length = signal->length() - 3;
Uint32 totReclenAi = regTcPtr->totReclenAi;
Uint32 currReclenAi = regTcPtr->currReclenAi + length;
- Uint32* dataPtr = &signal->theData[3];
regTcPtr->currReclenAi = currReclenAi;
if (totReclenAi == currReclenAi) {
switch (regTcPtr->transactionState) {
case TcConnectionrec::WAIT_ATTR:
{
- Fragrecord *regFragrecord = fragrecord;
- Uint32 fragIndex = regTcPtr->fragmentptr;
- Uint32 tfragrecFileSize = cfragrecFileSize;
jam();
- fragptr.i = fragIndex;
- ptrCheckGuard(fragptr, tfragrecFileSize, regFragrecord);
+ fragptr.i = regTcPtr->fragmentptr;
+ c_fragment_pool.getPtr(fragptr);
lqhAttrinfoLab(signal, dataPtr, length);
endgettupkeyLab(signal);
return;
@@ -3110,7 +2953,7 @@ void Dblqh::execATTRINFO(Signal* signal)
}//switch
}//if
return;
-}//Dblqh::execATTRINFO()
+}
/* ************************************************************************>> */
/* TUP_ATTRINFO: Interpreted execution in DBTUP generates redo-log info */
@@ -3162,11 +3005,7 @@ void Dblqh::lqhAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
}//if
}//if
}//if
- Uint32 sig0 = regTcPtr->tupConnectrec;
- Uint32 blockNo = refToBlock(regTcPtr->tcTupBlockref);
- signal->theData[0] = sig0;
- EXECUTE_DIRECT(blockNo, GSN_ATTRINFO, signal, length + 3);
- jamEntry();
+ c_tup->receive_attrinfo(signal, regTcPtr->tupConnectrec, dataPtr, length);
}//Dblqh::lqhAttrinfoLab()
/* ------------------------------------------------------------------------- */
@@ -3206,21 +3045,28 @@ int Dblqh::findTransaction(UintR Transid1, UintR Transid2, UintR TcOprec)
/* ------- SAVE ATTRINFO FROM TUP IN ATTRINBUF ------- */
/* */
/* ------------------------------------------------------------------------- */
-int Dblqh::saveTupattrbuf(Signal* signal, Uint32* dataPtr, Uint32 length)
+int Dblqh::saveTupattrbuf(Signal* signal, Uint32* dataPtr, Uint32 len)
{
- Uint32 tfirstfreeAttrinbuf = cfirstfreeAttrinbuf;
TcConnectionrec * const regTcPtr = tcConnectptr.p;
- 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;
+ 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()
@@ -3538,15 +3384,20 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
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
- regTcPtr->localFragptr = regTcPtr->hashValue & 1;
Uint8 TcopyType = fragptr.p->fragCopy;
tfragDistKey = fragptr.p->fragDistributionKey;
if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
@@ -3623,16 +3474,10 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
sig2 = lqhKeyReq->variableData[nextPos + 2];
sig3 = lqhKeyReq->variableData[nextPos + 3];
sig4 = lqhKeyReq->variableData[nextPos + 4];
-
- signal->theData[0] = regTcPtr->tupConnectrec;
- signal->theData[3] = sig0;
- signal->theData[4] = sig1;
- signal->theData[5] = sig2;
- signal->theData[6] = sig3;
- signal->theData[7] = sig4;
- EXECUTE_DIRECT(refToBlock(regTcPtr->tcTupBlockref), GSN_ATTRINFO,
- signal, TreclenAiLqhkey + 3);
- jamEntry();
+
+ c_tup->receive_attrinfo(signal, regTcPtr->tupConnectrec,
+ lqhKeyReq->variableData+nextPos, TreclenAiLqhkey);
+
if (signal->theData[0] == (UintR)-1) {
LQHKEY_abort(signal, 2);
return;
@@ -3667,6 +3512,57 @@ void Dblqh::endgettupkeyLab(Signal* signal)
regTcPtr->transactionState = TcConnectionrec::WAIT_ATTR;
return;
}//if
+//#define TRACE_LQHKEYREQ
+#ifdef TRACE_LQHKEYREQ
+ {
+ ndbout << (regTcPtr->operation == ZREAD ? "READ" :
+ regTcPtr->operation == ZUPDATE ? "UPDATE" :
+ regTcPtr->operation == ZINSERT ? "INSERT" :
+ regTcPtr->operation == ZDELETE ? "DELETE" : "<Other>")
+ << "(" << (int)regTcPtr->operation << ")"
+ << " from=(" << getBlockName(refToBlock(regTcPtr->clientBlockref))
+ << ", " << refToNode(regTcPtr->clientBlockref) << ")"
+ << " table=" << regTcPtr->tableref << " ";
+
+ ndbout << "hash: " << hex << regTcPtr->hashValue << endl;
+
+ ndbout << "key=[" << hex;
+ Uint32 i;
+ for(i = 0; i<regTcPtr->primKeyLen && i < 4; i++){
+ ndbout << 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++)
+ ndbout << hex << regDatabufptr.p->data[j] << " ";
+ }
+ ndbout << "]" << endl;
+
+ ndbout << "attr=[" << hex;
+ for(i = 0; i<regTcPtr->reclenAiLqhkey && i < 5; i++)
+ ndbout << hex << regTcPtr->firstAttrinfo[i] << " ";
+
+ AttrbufPtr regAttrinbufptr;
+ regAttrinbufptr.i= regTcPtr->firstAttrinbuf;
+ while(i < regTcPtr->totReclenAi)
+ {
+ ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
+ Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
+ ndbrequire(dataLen != 0);
+ ndbrequire(i + dataLen <= regTcPtr->totReclenAi);
+ for(Uint32 j= 0; j<dataLen; j++, i++)
+ ndbout << hex << regAttrinbufptr.p->attrbuf[j] << " ";
+
+ regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
+ }
+
+ ndbout << "]" << endl;
+ }
+#endif
/* ---------------------------------------------------------------------- */
/* NOW RECEPTION OF LQHKEYREQ IS COMPLETED THE NEXT STEP IS TO START*/
/* PROCESSING THE MESSAGE. IF THE MESSAGE IS TO A STAND-BY NODE */
@@ -3685,7 +3581,6 @@ void Dblqh::endgettupkeyLab(Signal* signal)
case Fragrecord::FSACTIVE:
case Fragrecord::CRASH_RECOVERING:
case Fragrecord::ACTIVE_CREATION:
- linkActiveFrag(signal);
prepareContinueAfterBlockedLab(signal);
return;
break;
@@ -3740,7 +3635,6 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
}
if (scanptr.i == RNIL) {
jam();
- releaseActiveFrag(signal);
takeOverErrorLab(signal);
return;
}//if
@@ -3749,7 +3643,6 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
true);
if (accOpPtr == RNIL) {
jam();
- releaseActiveFrag(signal);
takeOverErrorLab(signal);
return;
}//if
@@ -3798,10 +3691,9 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
/* ************ */
/* ACCKEYREQ < */
/* ************ */
- ndbrequire(regTcPtr->localFragptr < 2);
Uint32 sig0, sig1, sig2, sig3, sig4;
sig0 = regTcPtr->accConnectrec;
- sig1 = fragptr.p->accFragptr[regTcPtr->localFragptr];
+ sig1 = fragptr.p->accFragptr;
sig2 = regTcPtr->hashValue;
sig3 = regTcPtr->primKeyLen;
sig4 = regTcPtr->transid[0];
@@ -3876,11 +3768,10 @@ void Dblqh::execLQH_ALLOCREQ(Signal* signal)
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
regFragptr.i = regTcPtr.p->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(regFragptr);
- ndbrequire(regTcPtr.p->localFragptr < 2);
signal->theData[0] = regTcPtr.p->tupConnectrec;
- signal->theData[1] = regFragptr.p->tupFragptr[regTcPtr.p->localFragptr];
+ 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);
@@ -3894,9 +3785,8 @@ void Dblqh::execACCKEYCONF(Signal* signal)
TcConnectionrec *regTcConnectionrec = tcConnectionrec;
Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
Uint32 tcIndex = signal->theData[0];
- Uint32 Tfragid = signal->theData[2];
Uint32 localKey1 = signal->theData[3];
- Uint32 localKey2 = signal->theData[4];
+ //Uint32 localKey2 = signal->theData[4];
Uint32 localKeyFlag = signal->theData[5];
jamEntry();
tcConnectptr.i = tcIndex;
@@ -3906,11 +3796,8 @@ void Dblqh::execACCKEYCONF(Signal* signal)
LQHKEY_abort(signal, 3);
return;
}//if
- /* ------------------------------------------------------------------------
- * Set transaction state and also reset the activeCreat since that is only
- * valid in cases where the record was not present.
- * ------------------------------------------------------------------------ */
- regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
+
+ // reset the activeCreat since that is only valid in cases where the record was not present.
regTcPtr->activeCreat = ZFALSE;
/* ------------------------------------------------------------------------
* IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
@@ -3930,13 +3817,50 @@ void Dblqh::execACCKEYCONF(Signal* signal)
else
{
warningEvent("Convering %d to ZUPDATE", op);
- regTcPtr->operation = ZUPDATE;
+ op = regTcPtr->operation = ZUPDATE;
}
}//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);
- localKey2 = localKey1 & MAX_TUPLES_PER_PAGE;
- localKey1 = localKey1 >> MAX_TUPLES_BITS;
+ 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)
+{
+ 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 localKey2 = local_key & MAX_TUPLES_PER_PAGE;
+ Uint32 localKey1 = local_key >> MAX_TUPLES_BITS;
+#ifdef TRACE_LQHKEYREQ
+ ndbout << "localkey: [ " << hex << localKey1 << " " << localKey2 << "]"
+ << endl;
+#endif
Uint32 Ttupreq = regTcPtr->dirtyOp;
Ttupreq = Ttupreq + (regTcPtr->opSimple << 1);
Ttupreq = Ttupreq + (regTcPtr->operation << 6);
@@ -3951,35 +3875,27 @@ void Dblqh::execACCKEYCONF(Signal* signal)
/* ************< */
/* TUPKEYREQ < */
/* ************< */
- TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
Uint32 sig0, sig1, sig2, sig3;
-
sig0 = regTcPtr->tupConnectrec;
- sig1 = regTcPtr->tableref;
+
+ TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
tupKeyReq->connectPtr = sig0;
tupKeyReq->request = Ttupreq;
- tupKeyReq->tableRef = sig1;
- tupKeyReq->fragId = Tfragid;
tupKeyReq->keyRef1 = localKey1;
tupKeyReq->keyRef2 = localKey2;
sig0 = regTcPtr->totReclenAi;
sig1 = regTcPtr->applOprec;
sig2 = regTcPtr->applRef;
- sig3 = regTcPtr->schemaVersion;
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+
tupKeyReq->attrBufLen = sig0;
tupKeyReq->opRef = sig1;
tupKeyReq->applRef = sig2;
- tupKeyReq->schemaVersion = sig3;
- ndbrequire(regTcPtr->localFragptr < 2);
sig0 = regTcPtr->storedProcId;
sig1 = regTcPtr->transid[0];
sig2 = regTcPtr->transid[1];
- sig3 = regFragptr.p->tupFragptr[regTcPtr->localFragptr];
+ sig3 = regFragptrP->tupFragptr;
Uint32 tup = refToBlock(regTcPtr->tcTupBlockref);
tupKeyReq->storedProcedure = sig0;
@@ -3990,10 +3906,73 @@ void Dblqh::execACCKEYCONF(Signal* signal)
tupKeyReq->coordinatorTC = tcConnectptr.p->tcBlockref;
tupKeyReq->tcOpIndex = tcConnectptr.p->tcOprec;
tupKeyReq->savePointId = tcConnectptr.p->savePointId;
+ tupKeyReq->disk_page= disk_page;
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_local_key = local_key;
+ }
+ else
+ {
+ 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_local_key,
+ disk_page);
+ }
+ else if (state != TcConnectionrec::WAIT_TUP)
+ {
+ ndbrequire(state == TcConnectionrec::WAIT_TUP_TO_ABORT);
+ abortCommonLab(signal);
+ return;
+ }
+ else
+ {
+ TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
+ ref->userRef= callbackData;
+ ref->errorCode= disk_page;
+ execTUPKEYREF(signal);
+ }
+}
+
/* --------------------------------------------------------------------------
* ------- ENTER TUP... -------
* ENTER TUPKEYCONF WITH
@@ -4020,7 +3999,6 @@ void Dblqh::tupkeyConfLab(Signal* signal)
* WE HAVE ALREADY SENT THE RESPONSE SO WE ARE NOT INTERESTED IN READ LENGTH
* ---------------------------------------------------------------------- */
regTcPtr->gci = cnewestGci;
- releaseActiveFrag(signal);
commitContinueAfterBlockedLab(signal);
return;
}//if
@@ -4055,22 +4033,18 @@ void Dblqh::rwConcludedLab(Signal* signal)
* A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL THE
* COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
* ---------------------------------------------------------------------- */
- releaseActiveFrag(signal);
packLqhkeyreqLab(signal);
return;
} else {
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+ 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.
- * ------------------------------------------------------------------ */
+ * ----------------------------------------------------------------- */
regTcPtr->gci = cnewestGci;
- releaseActiveFrag(signal);
commitContinueAfterBlockedLab(signal);
return;
} else {
@@ -4080,7 +4054,6 @@ void Dblqh::rwConcludedLab(Signal* signal)
* WE WILL PACK THE REQUEST/RESPONSE TO THE NEXT NODE/TO TC.
* ------------------------------------------------------------------ */
regTcPtr->logWriteState = TcConnectionrec::NOT_WRITTEN;
- releaseActiveFrag(signal);
packLqhkeyreqLab(signal);
return;
}//if
@@ -4093,7 +4066,6 @@ void Dblqh::rwConcludedLab(Signal* signal)
* A NORMAL WRITE OPERATION THAT NEEDS LOGGING AND WILL NOT BE
* PREMATURELY COMMITTED.
* -------------------------------------------------------------------- */
- releaseActiveFrag(signal);
logLqhkeyreqLab(signal);
return;
}//if
@@ -4128,13 +4100,13 @@ void Dblqh::rwConcludedAiLab(Signal* signal)
* A NORMAL READ OPERATION IS NOT LOGGED BUT IS NOT COMMITTED UNTIL
* THE COMMIT SIGNAL ARRIVES. THUS WE CONTINUE PACKING THE RESPONSE.
* -------------------------------------------------------------------- */
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
packLqhkeyreqLab(signal);
return;
}//if
} else {
jam();
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if (fragptr.p->logFlag == Fragrecord::STATE_FALSE) {
if (regTcPtr->dirtyOp == ZTRUE) {
/* ------------------------------------------------------------------
@@ -4901,99 +4873,11 @@ void Dblqh::deleteTransidHash(Signal* signal)
}//if
}//Dblqh::deleteTransidHash()
-/* --------------------------------------------------------------------------
- * ------- LINK OPERATION IN ACTIVE LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME: LAF
-// Input Pointers:
-// tcConnectptr
-// fragptr
- * ------------------------------------------------------------------------- */
-void Dblqh::linkActiveFrag(Signal* signal)
-{
- TcConnectionrecPtr lafTcConnectptr;
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- Fragrecord * const regFragPtr = fragptr.p;
- Uint32 tcIndex = tcConnectptr.i;
- lafTcConnectptr.i = regFragPtr->activeList;
- regTcPtr->prevTc = RNIL;
- regFragPtr->activeList = tcIndex;
- ndbrequire(regTcPtr->listState == TcConnectionrec::NOT_IN_LIST);
- regTcPtr->nextTc = lafTcConnectptr.i;
- regTcPtr->listState = TcConnectionrec::IN_ACTIVE_LIST;
- if (lafTcConnectptr.i == RNIL) {
- return;
- } else {
- jam();
- ptrCheckGuard(lafTcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- lafTcConnectptr.p->prevTc = tcIndex;
- }//if
- return;
-}//Dblqh::linkActiveFrag()
-
/* -------------------------------------------------------------------------
* ------- RELEASE OPERATION FROM ACTIVE LIST ON FRAGMENT -------
*
* SUBROUTINE SHORT NAME = RAF
* ------------------------------------------------------------------------- */
-void Dblqh::releaseActiveFrag(Signal* signal)
-{
- TcConnectionrec * const regTcPtr = tcConnectptr.p;
- TcConnectionrecPtr ralTcNextConnectptr;
- TcConnectionrecPtr ralTcPrevConnectptr;
- fragptr.i = regTcPtr->fragmentptr;
- ralTcPrevConnectptr.i = regTcPtr->prevTc;
- ralTcNextConnectptr.i = regTcPtr->nextTc;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- Fragrecord * const regFragPtr = fragptr.p;
- ndbrequire(regTcPtr->listState == TcConnectionrec::IN_ACTIVE_LIST);
- regTcPtr->listState = TcConnectionrec::NOT_IN_LIST;
-
- if (ralTcNextConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(ralTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- ralTcNextConnectptr.p->prevTc = ralTcPrevConnectptr.i;
- }//if
- if (ralTcPrevConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(ralTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- ralTcPrevConnectptr.p->nextTc = regTcPtr->nextTc;
- } else {
- jam();
- /* ----------------------------------------------------------------------
- * OPERATION RECORD IS FIRST IN ACTIVE LIST
- * THIS MEANS THAT THERE EXISTS NO PREVIOUS TC THAT NEEDS TO BE UPDATED.
- * --------------------------------------------------------------------- */
- regFragPtr->activeList = ralTcNextConnectptr.i;
- }//if
- if (regFragPtr->lcpRef != RNIL) {
- jam();
- lcpPtr.i = regFragPtr->lcpRef;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_ACTIVE_FINISH);
-
- /* --------------------------------------------------------------------
- * IF A FRAGMENT IS CURRENTLY STARTING A LOCAL CHECKPOINT AND IT
- * IS WAITING FOR ACTIVE OPERATIONS TO BE COMPLETED WITH THE
- * CURRENT PHASE, THEN IT IS CHECKED WHETHER THE
- * LAST ACTIVE OPERATION WAS NOW COMPLETED.
- * ------------------------------------------------------------------- */
- if (regFragPtr->activeList == RNIL) {
- jam();
- /* ------------------------------------------------------------------
- * ACTIVE LIST ON FRAGMENT IS EMPTY AND WE ARE WAITING FOR
- * THIS TO HAPPEN.
- * WE WILL NOW START THE CHECKPOINT IN TUP AND ACC.
- * ----------------------------------------------------------------- */
- /* SEND START LOCAL CHECKPOINT TO ACC AND TUP */
- /* ----------------------------------------------------------------- */
- fragptr.p->lcpRef = RNIL;
- lcpPtr.p->lcpState = LcpRecord::LCP_START_CHKP;
- sendStartLcp(signal);
- }//if
- }//if
-}//Dblqh::releaseActiveFrag()
-
/* ######################################################################### */
/* ####### TRANSACTION MODULE ####### */
/* THIS MODULE HANDLES THE COMMIT AND THE COMPLETE PHASE. */
@@ -5236,6 +5120,7 @@ void Dblqh::execCOMMITREQ(Signal* signal)
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;
@@ -5350,6 +5235,7 @@ void Dblqh::execCOMPLETEREQ(Signal* signal)
/* THE NORMAL CASE. */
/*---------------------------------------------------------*/
case TcConnectionrec::COMMIT_STOPPED:
+ case TcConnectionrec::WAIT_TUP_COMMIT:
jam();
/*---------------------------------------------------------*/
/* FOR SOME REASON THE COMPLETE PHASE STARTED AFTER */
@@ -5556,7 +5442,7 @@ void Dblqh::localCommitLab(Signal* signal)
{
FragrecordPtr regFragptr;
regFragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(regFragptr);
Fragrecord::FragStatus status = regFragptr.p->fragStatus;
fragptr = regFragptr;
switch (status) {
@@ -5640,6 +5526,13 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
tupCommitReq->hashValue = regTcPtr->hashValue;
EXECUTE_DIRECT(tup, GSN_TUP_COMMITREQ, signal,
TupCommitReq::SignalLength);
+
+ if(signal->theData[0] != 0)
+ {
+ regTcPtr->transactionState = TcConnectionrec::WAIT_TUP_COMMIT;
+ return; // TUP_COMMIT was timesliced
+ }
+
Uint32 acc = refToBlock(regTcPtr->tcAccBlockref);
signal->theData[0] = regTcPtr->accConnectrec;
EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
@@ -5649,10 +5542,9 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
signal->theData[0] = regTcPtr->accConnectrec;
EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
}
- }
- jamEntry();
- if (simpleRead) {
- jam();
+
+ if (simpleRead) {
+ jam();
/* ------------------------------------------------------------------------- */
/*THE OPERATION WAS A SIMPLE READ THUS THE COMMIT PHASE IS ONLY NEEDED TO */
/*RELEASE THE LOCKS. AT THIS POINT IN THE CODE THE LOCKS ARE RELEASED AND WE */
@@ -5660,10 +5552,45 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal)
/*RESOURCES BELONGING TO THIS OPERATION SINCE NO MORE WORK WILL BE */
/*PERFORMED. */
/* ------------------------------------------------------------------------- */
- cleanUp(signal);
- return;
- }//if
+ cleanUp(signal);
+ return;
+ }//if
+ }
}//if
+ jamEntry();
+ tupcommit_conf(signal, regTcPtr, regFragptr);
+}
+
+void
+Dblqh::tupcommit_conf_callback(Signal* signal, Uint32 tcPtrI)
+{
+ jamEntry();
+
+ tcConnectptr.i = tcPtrI;
+ ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+ TcConnectionrec * const tcPtr = tcConnectptr.p;
+
+ ndbrequire(tcPtr->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
+
+ FragrecordPtr regFragptr;
+ regFragptr.i = tcPtr->fragmentptr;
+ c_fragment_pool.getPtr(regFragptr);
+ fragptr = regFragptr;
+
+ Uint32 acc = refToBlock(tcPtr->tcAccBlockref);
+ signal->theData[0] = tcPtr->accConnectrec;
+ EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1);
+ jamEntry();
+
+ tupcommit_conf(signal, tcPtr, regFragptr.p);
+}
+
+void
+Dblqh::tupcommit_conf(Signal* signal,
+ TcConnectionrec * regTcPtr,
+ Fragrecord * regFragptr)
+{
+ Uint32 dirtyOp = regTcPtr->dirtyOp;
Uint32 seqNoReplica = regTcPtr->seqNoReplica;
if (regTcPtr->gci > regFragptr->newestGci) {
jam();
@@ -5982,7 +5909,6 @@ void Dblqh::execACC_TO_REF(Signal* signal)
{
jamEntry();
terrorCode = signal->theData[1];
- releaseActiveFrag(signal);
abortErrorLab(signal);
return;
}//Dblqh::execACC_TO_REF()
@@ -6000,7 +5926,6 @@ void Dblqh::execACCKEYREF(Signal* signal)
switch (tcPtr->transactionState) {
case TcConnectionrec::WAIT_ACC:
jam();
- releaseActiveFrag(signal);
break;
case TcConnectionrec::WAIT_ACC_ABORT:
case TcConnectionrec::ABORT_STOPPED:
@@ -6148,18 +6073,6 @@ void Dblqh::abortStateHandlerLab(Signal* signal)
return;
case TcConnectionrec::WAIT_ACC:
jam();
- if (regTcPtr->listState == TcConnectionrec::ACC_BLOCK_LIST) {
- jam();
-/* ------------------------------------------------------------------------- */
-// If the operation is in the ACC Blocked list the operation is not allowed
-// to start yet. We release it from the ACC Blocked list and will go through
-// the gate in abortCommonLab(..) where it will be blocked.
-/* ------------------------------------------------------------------------- */
- fragptr.i = regTcPtr->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- releaseAccList(signal);
- } else {
- 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
@@ -6168,9 +6081,8 @@ void Dblqh::abortStateHandlerLab(Signal* signal)
// We cannot accept being blocked before aborting ACC here since that would
// lead to seriously complex issues.
/* ------------------------------------------------------------------------- */
- abortContinueAfterBlockedLab(signal, false);
- return;
- }//if
+ abortContinueAfterBlockedLab(signal, false);
+ return;
break;
case TcConnectionrec::LOG_QUEUED:
jam();
@@ -6216,6 +6128,7 @@ void Dblqh::abortStateHandlerLab(Signal* signal)
/* ------------------------------------------------------------------------- */
return;
break;
+ case TcConnectionrec::WAIT_TUP_COMMIT:
case TcConnectionrec::COMMIT_STOPPED:
case TcConnectionrec::LOG_COMMIT_QUEUED:
case TcConnectionrec::COMMIT_QUEUED:
@@ -6312,13 +6225,12 @@ void Dblqh::abortCommonLab(Signal* signal)
fragptr.i = regTcPtr->fragmentptr;
if (fragptr.i != RNIL) {
jam();
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
case Fragrecord::CRASH_RECOVERING:
case Fragrecord::ACTIVE_CREATION:
jam();
- linkActiveFrag(signal);
abortContinueAfterBlockedLab(signal, true);
return;
break;
@@ -6358,7 +6270,7 @@ void Dblqh::abortContinueAfterBlockedLab(Signal* signal, bool canBlock)
* ------------------------------------------------------------------------ */
TcConnectionrec * const regTcPtr = tcConnectptr.p;
fragptr.i = regTcPtr->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if ((cCommitBlocked == true) &&
(fragptr.p->fragActiveStatus == ZTRUE) &&
(canBlock == true) &&
@@ -6380,7 +6292,6 @@ void Dblqh::abortContinueAfterBlockedLab(Signal* signal, bool canBlock)
// log part to ensure that we don't get a buffer explosion in the delayed
// signal buffer instead.
/*---------------------------------------------------------------------------*/
- releaseActiveFrag(signal);
logPartPtr.i = regTcPtr->hashValue & 3;
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
linkWaitLog(signal, logPartPtr);
@@ -6424,17 +6335,17 @@ void Dblqh::execACC_ABORTCONF(Signal* signal)
if (regTcPtr->currTupAiLen == regTcPtr->totReclenAi) {
jam();
regTcPtr->abortState = TcConnectionrec::ABORT_IDLE;
+ fragptr.i = regTcPtr->fragmentptr;
+ c_fragment_pool.getPtr(fragptr);
rwConcludedLab(signal);
return;
} else {
ndbrequire(regTcPtr->currTupAiLen < regTcPtr->totReclenAi);
jam();
- releaseActiveFrag(signal);
regTcPtr->transactionState = TcConnectionrec::WAIT_AI_AFTER_ABORT;
return;
}//if
}//if
- releaseActiveFrag(signal);
continueAbortLab(signal);
return;
}//Dblqh::execACC_ABORTCONF()
@@ -6726,39 +6637,39 @@ void Dblqh::lqhTransNextLab(Signal* signal)
} else {
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
- if (scanptr.p->scanType == ScanRecord::COPY) {
+ 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.
- * ------------------------------------------------------------ */
+ * ----------------------------------------------------------- */
tcConnectptr.p->tcNodeFailrec = tcNodeFailptr.i;
tcConnectptr.p->abortState = TcConnectionrec::NEW_FROM_TC;
closeCopyRequestLab(signal);
return;
- }//if
- } else {
- if (scanptr.p->scanType == 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
- } else {
- jam();
- /* ------------------------------------------------------------
- * THIS IS AN ERROR THAT SHOULD NOT OCCUR. WE CRASH THE SYSTEM.
- * ------------------------------------------------------------ */
- systemErrorLab(signal, __LINE__);
- return;
- }//if
- }//if
+ }
+ 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
@@ -6899,6 +6810,9 @@ void Dblqh::execNEXT_SCANCONF(Signal* signal)
nextScanConf->localKey[0] & MAX_TUPLES_PER_PAGE;
nextScanConf->localKey[0] = nextScanConf->localKey[0] >> MAX_TUPLES_BITS;
}//if
+
+ fragptr.i = scanptr.p->fragPtrI;
+ c_fragment_pool.getPtr(fragptr);
switch (scanptr.p->scanState) {
case ScanRecord::WAIT_CLOSE_SCAN:
jam();
@@ -6955,7 +6869,6 @@ void Dblqh::execSTORED_PROCCONF(Signal* signal)
break;
case ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN:
jam();
- releaseActiveFrag(signal);
tupScanCloseConfLab(signal);
break;
case ScanRecord::WAIT_STORED_PROC_COPY:
@@ -6965,7 +6878,6 @@ void Dblqh::execSTORED_PROCCONF(Signal* signal)
break;
case ScanRecord::WAIT_DELETE_STORED_PROC_ID_COPY:
jam();
- releaseActiveFrag(signal);
tupCopyCloseConfLab(signal);
break;
default:
@@ -7092,7 +7004,7 @@ void Dblqh::execSCAN_NEXTREQ(Signal* signal)
}//if
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
/**
* Change parameters while running
@@ -7158,7 +7070,6 @@ void Dblqh::scanReleaseLocksLab(Signal* signal)
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
break;
case Fragrecord::BLOCKED:
jam();
@@ -7262,7 +7173,7 @@ void Dblqh::closeScanRequestLab(Signal* signal)
scanptr.p->scanCompletedStatus = ZTRUE;
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if (scanptr.p->scanLockHold == ZTRUE) {
if (scanptr.p->m_curr_batch_size_rows > 0) {
@@ -7342,7 +7253,6 @@ void Dblqh::scanLockReleasedLab(Signal* signal)
{
tcConnectptr.i = scanptr.p->scanTcrec;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- releaseActiveFrag(signal);
if (scanptr.p->scanReleaseCounter == scanptr.p->m_curr_batch_size_rows) {
if ((scanptr.p->scanErrorCounter > 0) ||
@@ -7461,7 +7371,6 @@ Dblqh::get_acc_ptr_from_scan_record(ScanRecord* scanP,
bool crash_flag)
{
Uint32* acc_ptr;
- Uint32 attr_buf_rec, attr_buf_index;
if (!((index < MAX_PARALLEL_OP_PER_SCAN) &&
index < scanP->scan_acc_index)) {
ndbrequire(crash_flag);
@@ -7560,7 +7469,7 @@ void Dblqh::execSCAN_FRAGREQ(Signal* signal)
}//if
ndbrequire(c_scanRecordPool.seize(scanptr));
- initScanTc(signal,
+ initScanTc(scanFragReq,
transid1,
transid2,
fragId,
@@ -7683,7 +7592,7 @@ void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
c_scanRecordPool.getPtr(scanptr);
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
finishScanrec(signal);
releaseScanrec(signal);
tcConnectptr.p->transactionState = TcConnectionrec::IDLE;
@@ -7969,7 +7878,7 @@ Dblqh::copy_bounds(Uint32 * dst, TcConnectionrec* tcPtrP)
void Dblqh::storedProcConfScanLab(Signal* signal)
{
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if (scanptr.p->scanCompletedStatus == ZTRUE) {
jam();
// STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
@@ -7979,7 +7888,6 @@ void Dblqh::storedProcConfScanLab(Signal* signal)
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
break;
case Fragrecord::BLOCKED:
jam();
@@ -8028,10 +7936,9 @@ void Dblqh::execCHECK_LCP_STOP(Signal* signal)
tcConnectptr.i = scanptr.p->scanTcrec;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if (signal->theData[1] == ZTRUE) {
jam();
- releaseActiveFrag(signal);
signal->theData[0] = ZCHECK_LCP_STOP_BLOCKED;
signal->theData[1] = scanptr.i;
sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 2);
@@ -8040,7 +7947,6 @@ void Dblqh::execCHECK_LCP_STOP(Signal* signal)
}//if
if (fragptr.p->fragStatus != Fragrecord::FSACTIVE) {
ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED);
- releaseActiveFrag(signal);
linkFragQueue(signal);
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_CHECK_STOPPED;
signal->theData[0] = RNIL;
@@ -8052,7 +7958,6 @@ void Dblqh::checkLcpStopBlockedLab(Signal* signal)
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
continueAfterCheckLcpStopBlocked(signal);
break;
case Fragrecord::BLOCKED:
@@ -8105,7 +8010,6 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
* REQUEST IS RECEIVED. IF WE DO NOT HAVE ANY NEED FOR
* LOCKS WE CAN CLOSE THE SCAN IMMEDIATELY.
* --------------------------------------------------------------------- */
- releaseActiveFrag(signal);
/*************************************************************
* STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
************************************************************ */
@@ -8150,7 +8054,6 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
* STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
************************************************************ */
if (scanptr.p->scanCompletedStatus == ZTRUE) {
- releaseActiveFrag(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8165,7 +8068,6 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
if (scanptr.p->m_curr_batch_size_rows > 0) {
jam();
- releaseActiveFrag(signal);
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
sendScanFragConf(signal, ZFALSE);
return;
@@ -8195,7 +8097,6 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
* ---------------------------------------------------------------------- */
if (scanptr.p->scanCompletedStatus == ZTRUE) {
jam();
- releaseActiveFrag(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8206,55 +8107,127 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
closeScanLab(signal);
return;
}//if
- jam();
- Uint32 tableRef;
- Uint32 tupFragPtr;
- Uint32 reqinfo = (scanptr.p->scanLockHold == ZFALSE);
- reqinfo = reqinfo + (tcConnectptr.p->operation << 6);
- reqinfo = reqinfo + (tcConnectptr.p->opExec << 10);
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_TUPKEY;
- fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (! scanptr.p->rangeScan) {
- tableRef = tcConnectptr.p->tableref;
- tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
- } else {
+
+ Fragrecord* fragPtrP= fragptr.p;
+ if (scanptr.p->rangeScan) {
jam();
// for ordered index use primary table
- FragrecordPtr tFragPtr;
- tFragPtr.i = fragptr.p->tableFragptr;
- ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
- tableRef = tFragPtr.p->tabRef;
- tupFragPtr = tFragPtr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
+ 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;
+ local_key = scanptr.p->scanLocalref[0] << MAX_TUPLES_BITS;
+ local_key += scanptr.p->scanLocalref[1];
+
+ 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();
- TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
-
- tupKeyReq->connectPtr = tcConnectptr.p->tupConnectrec;
- tupKeyReq->request = reqinfo;
- tupKeyReq->tableRef = tableRef;
- tupKeyReq->fragId = scanptr.p->scanLocalFragid;
- tupKeyReq->keyRef1 = scanptr.p->scanLocalref[0];
- tupKeyReq->keyRef2 = scanptr.p->scanLocalref[1];
- tupKeyReq->attrBufLen = 0;
- tupKeyReq->opRef = scanptr.p->scanApiOpPtr;
- tupKeyReq->applRef = scanptr.p->scanApiBlockref;
- tupKeyReq->schemaVersion = scanptr.p->scanSchemaVersion;
- tupKeyReq->storedProcedure = scanptr.p->scanStoredProcId;
- tupKeyReq->transId1 = tcConnectptr.p->transid[0];
- tupKeyReq->transId2 = tcConnectptr.p->transid[1];
- tupKeyReq->fragPtr = tupFragPtr;
- tupKeyReq->primaryReplica = (tcConnectptr.p->seqNoReplica == 0)?true:false;
- tupKeyReq->coordinatorTC = tcConnectptr.p->tcBlockref;
- tupKeyReq->tcOpIndex = tcConnectptr.p->tcOprec;
- tupKeyReq->savePointId = tcConnectptr.p->savePointId;
- Uint32 blockNo = refToBlock(tcConnectptr.p->tcTupBlockref);
- EXECUTE_DIRECT(blockNo, GSN_TUPKEYREQ, signal,
- TupKeyReq::SignalLength);
+ 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->scanLocalref[0];
+ tupKeyReq->keyRef2 = scanPtr.p->scanLocalref[1];
+ 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.
* -------------------------------------------------------------------------
@@ -8287,7 +8260,7 @@ Dblqh::readPrimaryKeys(ScanRecord *scanP, TcConnectionrec *tcConP, Uint32 *dst)
// for ordered index use primary table
FragrecordPtr tFragPtr;
tFragPtr.i = fragptr.p->tableFragptr;
- ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(tFragPtr);
tableId = tFragPtr.p->tabRef;
}
@@ -8313,7 +8286,6 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
scanptr.i = tcConnectptr.p->tcScanRec;
- releaseActiveFrag(signal);
c_scanRecordPool.getPtr(scanptr);
if (scanptr.p->scanCompletedStatus == ZTRUE) {
/* ---------------------------------------------------------------------
@@ -8368,7 +8340,6 @@ void Dblqh::scanNextLoopLab(Signal* signal)
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
break;
case Fragrecord::BLOCKED:
jam();
@@ -8431,7 +8402,6 @@ void Dblqh::scanTupkeyRefLab(Signal* signal)
{
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
scanptr.i = tcConnectptr.p->tcScanRec;
- releaseActiveFrag(signal);
c_scanRecordPool.getPtr(scanptr);
if (scanptr.p->scanCompletedStatus == ZTRUE) {
/* ---------------------------------------------------------------------
@@ -8502,11 +8472,10 @@ void Dblqh::scanTupkeyRefLab(Signal* signal)
void Dblqh::closeScanLab(Signal* signal)
{
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
break;
case Fragrecord::BLOCKED:
jam();
@@ -8556,7 +8525,6 @@ void Dblqh::accScanCloseConfLab(Signal* signal)
scanptr.p->scanCompletedStatus != ZTRUE)
{
jam();
- releaseActiveFrag(signal);
continueAfterReceivingAllAiLab(signal);
return;
}
@@ -8579,7 +8547,7 @@ void Dblqh::accScanCloseConfLab(Signal* signal)
void Dblqh::tupScanCloseConfLab(Signal* signal)
{
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
jam();
tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
@@ -8680,7 +8648,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
*/
FragrecordPtr tFragPtr;
tFragPtr.i = fragptr.p->tableFragptr;
- ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(tFragPtr);
scanptr.p->fragPtrI = fragptr.p->tableFragptr;
/**
@@ -8738,7 +8706,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
*
* SUBROUTINE SHORT NAME = IST
* ========================================================================= */
-void Dblqh::initScanTc(Signal* signal,
+void Dblqh::initScanTc(const ScanFragReq* req,
Uint32 transid1,
Uint32 transid2,
Uint32 fragId,
@@ -8763,6 +8731,13 @@ void Dblqh::initScanTc(Signal* signal,
tcConnectptr.p->commitAckMarker = RNIL;
tcConnectptr.p->m_offset_current_keybuf = 0;
tcConnectptr.p->m_scan_curr_range_no = 0;
+ tcConnectptr.p->m_disk_table = tabptr.p->m_disk_table;
+
+ 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()
@@ -8800,7 +8775,7 @@ void Dblqh::finishScanrec(Signal* signal)
FragrecordPtr tFragPtr;
tFragPtr.i = scanptr.p->fragPtrI;
- ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(tFragPtr);
const Uint32 scanNumber = scanptr.p->scanNumber;
ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
@@ -8844,10 +8819,12 @@ void Dblqh::finishScanrec(Signal* signal)
#endif
}
- restart.p->scanState = ScanRecord::SCAN_FREE; // set in initScanRec
+ /**
+ * 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)
{
- jam();
scanptr = restart;
continueAfterReceivingAllAiLab(signal);
}
@@ -8855,6 +8832,7 @@ void Dblqh::finishScanrec(Signal* signal)
{
ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_SCAN_AI);
}
+
scanptr = tmpScan;
tcConnectptr = tmpTc;
}//Dblqh::finishScanrec()
@@ -8892,9 +8870,9 @@ Uint32 Dblqh::sendKeyinfo20(Signal* signal,
const Uint32 scanOp = scanP->m_curr_batch_size_rows;
const Uint32 nodeId = refToNode(ref);
const bool connectedToNode = getNodeInfo(nodeId).m_connected;
- const Uint32 type = getNodeInfo(nodeId).m_type;
- const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
- const bool old_dest = (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
+ //const Uint32 type = getNodeInfo(nodeId).m_type;
+ //const bool is_api= (type >= NodeInfo::API && type <= NodeInfo::REP);
+ //const bool old_dest= (getNodeInfo(nodeId).m_version < MAKE_VERSION(3,5,0));
const bool longable = true; // TODO is_api && !old_dest;
Uint32 * dst = keyInfo->keyData;
@@ -8995,7 +8973,7 @@ void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
return;
}
ScanFragConf * conf = (ScanFragConf*)&signal->theData[0];
- NodeId tc_node_id= refToNode(tcConnectptr.p->clientBlockref);
+ //NodeId tc_node_id= refToNode(tcConnectptr.p->clientBlockref);
Uint32 trans_id1= tcConnectptr.p->transid[0];
Uint32 trans_id2= tcConnectptr.p->transid[1];
@@ -9090,6 +9068,7 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
scanptr.p->rangeScan = 0;
scanptr.p->tupScan = 0;
seizeTcrec();
+ tcConnectptr.p->clientBlockref = userRef;
/**
* Remove implicit cast/usage of CopyFragReq
@@ -9097,7 +9076,6 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
//initCopyrec(signal);
scanptr.p->copyPtr = copyPtr;
scanptr.p->scanType = ScanRecord::COPY;
- scanptr.p->scanApiBlockref = userRef;
scanptr.p->scanNodeId = nodeId;
scanptr.p->scanTcrec = tcConnectptr.i;
scanptr.p->scanSchemaVersion = copyFragReq->schemaVersion;
@@ -9106,10 +9084,13 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
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 = DBACC_REF;
-
- initScanTc(signal,
+ scanptr.p->scanLockHold = ZFALSE;
+
+ initScanTc(0,
0,
(DBLQH << 20) + (cownNodeid << 8),
fragId,
@@ -9176,7 +9157,7 @@ void Dblqh::storedProcConfCopyLab(Signal* signal)
/* PRECONDITION: SCAN_STATE = WAIT_STORED_PROC_COPY */
/*---------------------------------------------------------------------------*/
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if (scanptr.p->scanCompletedStatus == ZTRUE) {
jam();
/*---------------------------------------------------------------------------*/
@@ -9191,7 +9172,6 @@ void Dblqh::storedProcConfCopyLab(Signal* signal)
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
break;
case Fragrecord::BLOCKED:
jam();
@@ -9256,7 +9236,6 @@ void Dblqh::nextScanConfCopyLab(Signal* signal)
/* THERE ARE NO MORE TUPLES TO FETCH. WE NEED TO CLOSE */
/* THE COPY IN ACC AND DELETE THE STORED PROCEDURE IN TUP */
/*---------------------------------------------------------------------------*/
- releaseActiveFrag(signal);
if (tcConnectptr.p->copyCountWords == 0) {
closeCopyLab(signal);
return;
@@ -9280,48 +9259,21 @@ void Dblqh::nextScanConfCopyLab(Signal* signal)
set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
initCopyTc(signal);
- copySendTupkeyReqLab(signal);
- return;
-}//Dblqh::nextScanConfCopyLab()
-void Dblqh::copySendTupkeyReqLab(Signal* signal)
-{
- Uint32 reqinfo = 0;
- Uint32 tupFragPtr;
-
- reqinfo = reqinfo + (tcConnectptr.p->operation << 6);
- reqinfo = reqinfo + (tcConnectptr.p->opExec << 10);
- tcConnectptr.p->transactionState = TcConnectionrec::COPY_TUPKEY;
+ Fragrecord* fragPtrP= fragptr.p;
scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
- fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
+ tcConnectptr.p->transactionState = TcConnectionrec::COPY_TUPKEY;
+ if(tcConnectptr.p->m_disk_table)
{
- TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
-
- tupKeyReq->connectPtr = tcConnectptr.p->tupConnectrec;
- tupKeyReq->request = reqinfo;
- tupKeyReq->tableRef = tcConnectptr.p->tableref;
- tupKeyReq->fragId = scanptr.p->scanLocalFragid;
- tupKeyReq->keyRef1 = scanptr.p->scanLocalref[0];
- tupKeyReq->keyRef2 = scanptr.p->scanLocalref[1];
- tupKeyReq->attrBufLen = 0;
- tupKeyReq->opRef = tcConnectptr.i;
- tupKeyReq->applRef = cownref;
- tupKeyReq->schemaVersion = scanptr.p->scanSchemaVersion;
- tupKeyReq->storedProcedure = scanptr.p->scanStoredProcId;
- tupKeyReq->transId1 = tcConnectptr.p->transid[0];
- tupKeyReq->transId2 = tcConnectptr.p->transid[1];
- tupKeyReq->fragPtr = tupFragPtr;
- tupKeyReq->primaryReplica = (tcConnectptr.p->seqNoReplica == 0)?true:false;
- tupKeyReq->coordinatorTC = tcConnectptr.p->tcBlockref;
- tupKeyReq->tcOpIndex = tcConnectptr.p->tcOprec;
- tupKeyReq->savePointId = tcConnectptr.p->savePointId;
- Uint32 blockNo = refToBlock(tcConnectptr.p->tcTupBlockref);
- EXECUTE_DIRECT(blockNo, GSN_TUPKEYREQ, signal,
- TupKeyReq::SignalLength);
+ next_scanconf_load_diskpage(signal, scanptr, tcConnectptr,fragPtrP);
}
-}//Dblqh::copySendTupkeyReqLab()
+ else
+ {
+ next_scanconf_tupkeyreq(signal, scanptr, tcConnectptr.p, fragPtrP, RNIL);
+ }
+ return;
+}//Dblqh::nextScanConfCopyLab()
+
/*---------------------------------------------------------------------------*/
/* USED IN COPYING OPERATION TO RECEIVE ATTRINFO FROM TUP. */
@@ -9374,7 +9326,6 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
ScanRecord* scanP = scanptr.p;
- releaseActiveFrag(signal);
if (tcConnectptr.p->errorCode != 0) {
jam();
closeCopyLab(signal);
@@ -9512,7 +9463,7 @@ void Dblqh::copyCompletedLab(Signal* signal)
void Dblqh::nextRecordCopy(Signal* signal)
{
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
if (scanptr.p->scanState != ScanRecord::WAIT_LQHKEY_COPY) {
@@ -9529,7 +9480,6 @@ void Dblqh::nextRecordCopy(Signal* signal)
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
break;
case Fragrecord::BLOCKED:
jam();
@@ -9596,14 +9546,13 @@ void Dblqh::closeCopyLab(Signal* signal)
tcConnectptr.p->transid[0] = 0;
tcConnectptr.p->transid[1] = 0;
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
scanptr.p->scanState = ScanRecord::WAIT_CLOSE_COPY;
switch (fragptr.p->fragStatus) {
case Fragrecord::FSACTIVE:
jam();
- linkActiveFrag(signal);
break;
case Fragrecord::BLOCKED:
jam();
@@ -9681,7 +9630,7 @@ void Dblqh::accCopyCloseConfLab(Signal* signal)
void Dblqh::tupCopyCloseConfLab(Signal* signal)
{
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
fragptr.p->copyFragState = ZIDLE;
if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
@@ -9700,7 +9649,7 @@ void Dblqh::tupCopyCloseConfLab(Signal* signal)
ref->tableId = fragptr.p->tabRef;
ref->fragId = fragptr.p->fragId;
ref->errorCode = ZNODE_FAILURE_ERROR;
- sendSignal(scanptr.p->scanApiBlockref, GSN_COPY_FRAGREF, signal,
+ sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
CopyFragRef::SignalLength, JBB);
} else {
if (scanptr.p->scanErrorCounter > 0) {
@@ -9712,7 +9661,7 @@ void Dblqh::tupCopyCloseConfLab(Signal* signal)
ref->tableId = fragptr.p->tabRef;
ref->fragId = fragptr.p->fragId;
ref->errorCode = tcConnectptr.p->errorCode;
- sendSignal(scanptr.p->scanApiBlockref, GSN_COPY_FRAGREF, signal,
+ sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGREF, signal,
CopyFragRef::SignalLength, JBB);
} else {
jam();
@@ -9722,7 +9671,7 @@ void Dblqh::tupCopyCloseConfLab(Signal* signal)
conf->startingNodeId = scanptr.p->scanNodeId;
conf->tableId = tcConnectptr.p->tableref;
conf->fragId = tcConnectptr.p->fragmentid;
- sendSignal(scanptr.p->scanApiBlockref, GSN_COPY_FRAGCONF, signal,
+ sendSignal(tcConnectptr.p->clientBlockref, GSN_COPY_FRAGCONF, signal,
CopyFragConf::SignalLength, JBB);
}//if
}//if
@@ -9929,7 +9878,7 @@ void Dblqh::execCOPY_STATEREQ(Signal* signal)
jam();
break;
}//if
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
if (fragptr.p->copyFragState != ZIDLE) {
jam();
/*---------------------------------------------------------------------------*/
@@ -10073,11 +10022,32 @@ void Dblqh::execEMPTY_LCP_REQ(Signal* signal)
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;
@@ -10093,7 +10063,7 @@ void Dblqh::execLCP_FRAG_ORD(Signal* signal)
* -------------------------------------------------------- */
if (cnoOfFragsCheckpointed > 0) {
jam();
- completeLcpRoundLab(signal);
+ completeLcpRoundLab(signal, lcpId);
} else {
jam();
sendLCP_COMPLETE_REP(signal, lcpId);
@@ -10113,17 +10083,18 @@ void Dblqh::execLCP_FRAG_ORD(Signal* signal)
lcpPtr.i = 0;
ptrAss(lcpPtr, lcpRecord);
ndbrequire(!lcpPtr.p->lcpQueued);
+
if (c_lcpId < lcpFragOrd->lcpId) {
jam();
- /**
- * A new LCP
- */
+
+ 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;
- }//if
+ }
cnoOfFragsCheckpointed++;
if(tabptr.p->tableStatus == Tablerec::PREP_DROP_TABLE_DONE){
@@ -10149,567 +10120,131 @@ void Dblqh::execLCP_FRAG_ORD(Signal* signal)
sendLCP_FRAGIDREQ(signal);
}//Dblqh::execLCP_FRAGORD()
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_PTR:LCP_STATE = WAIT_FRAGID
- * --------------------------------------------------------------------------
- * WE NOW HAVE THE LOCAL FRAGMENTS THAT THE LOCAL CHECKPOINT WILL USE.
- * -------------------------------------------------------------------------- */
-void Dblqh::execLCP_FRAGIDCONF(Signal* signal)
+void Dblqh::execLCP_PREPARE_REF(Signal* signal)
{
- UintR Tfragid[4];
-
jamEntry();
- lcpPtr.i = signal->theData[0];
+ LcpPrepareRef* ref= (LcpPrepareRef*)signal->getDataPtr();
- Uint32 TaccPtr = signal->theData[1];
- Uint32 noLocfrag = signal->theData[2];
- Tfragid[0] = signal->theData[3];
- Tfragid[1] = signal->theData[4];
-
+ lcpPtr.i = ref->senderData;
ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_FRAGID);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECKING OF TNO_LOCFRAG VALUE. OUT OF BOUND WILL IMPLY THAT AN
- * INDEX OUT OF RANGE WILL CAUSE A SYSTEM RESTART WHICH IS DESIRED.
- * ------------------------------------------------------------------------ */
- lcpPtr.p->lcpAccptr = TaccPtr;
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- ndbrequire(noLocfrag - 1 < 2);
- for (Uint32 Tindex = 0; Tindex < noLocfrag; Tindex++) {
- jam();
- Uint32 fragId = Tfragid[Tindex];
- /* ----------------------------------------------------------------------
- * THERE IS NO ERROR CHECKING ON PURPOSE. IT IS POSSIBLE TO CALCULATE HOW
- * MANY LOCAL LCP RECORDS THERE SHOULD BE. IT SHOULD NEVER HAPPEN THAT
- * THERE IS NO ONE FREE. IF THERE IS NO ONE IT WILL ALSO BE A POINTER
- * OUT OF RANGE WHICH IS AN ERROR CODE IN ITSELF. REUSES ERROR HANDLING
- * IN AXE VM.
- * ---------------------------------------------------------------------- */
- seizeLcpLoc(signal);
- initLcpLocAcc(signal, fragId);
- seizeLcpLoc(signal);
- initLcpLocTup(signal, fragId);
- signal->theData[0] = lcpLocptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- signal->theData[3] = lcpLocptr.p->locFragid;
- signal->theData[4] = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
- signal->theData[5] = lcpPtr.p->currentFragment.lcpFragOrd.lcpId % MAX_LCP_STORED;
- sendSignal(fragptr.p->tupBlockref, GSN_TUP_PREPLCPREQ, signal, 6, JBB);
- }//for
- lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_TUP_PREPLCP;
- return;
-}//Dblqh::execLCP_FRAGIDCONF()
-
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_STATE = WAIT_TUPPREPLCP
- * --------------------------------------------------------------------------
- * WE HAVE NOW PREPARED A LOCAL FRAGMENT IN TUP FOR LCP EXECUTION.
- * -------------------------------------------------------------------------- */
-void Dblqh::execTUP_PREPLCPCONF(Signal* signal)
-{
- UintR ttupPtr;
-
- jamEntry();
- lcpLocptr.i = signal->theData[0];
- ttupPtr = signal->theData[1];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
-
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- ndbrequire(lcpLocptr.p->lcpLocstate == LcpLocRecord::WAIT_TUP_PREPLCP);
-
- lcpLocptr.p->tupRef = ttupPtr;
- lcpLocptr.p->lcpLocstate = LcpLocRecord::IDLE;
- checkLcpTupprep(signal);
- if (lcpPtr.p->lcpState != LcpRecord::LCP_WAIT_HOLDOPS) {
- jam();
- return;
- }//if
+
fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- lcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- do {
- jam();
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- lcpLocptr.p->lcpLocstate = LcpLocRecord::WAIT_LCPHOLDOP;
- signal->theData[0] = lcpPtr.p->lcpAccptr;
- signal->theData[1] = lcpLocptr.p->locFragid;
- signal->theData[2] = 0;
- signal->theData[3] = lcpLocptr.i;
- sendSignal(fragptr.p->accBlockref, GSN_LCP_HOLDOPREQ, signal, 4, JBA);
- lcpLocptr.i = lcpLocptr.p->nextLcpLoc;
- } while (lcpLocptr.i != RNIL);
- /* ------------------------------------------------------------------------
- * SET STATE ON FRAGMENT TO BLOCKED TO ENSURE THAT NO MORE OPERATIONS ARE
- * STARTED FROM LQH IN TUP AND ACC UNTIL THE START CHECKPOINT HAS BEEN
- * COMPLETED. ALSO SET THE LOCAL CHECKPOINT STATE TO WAIT FOR
- * LCP_HOLDOPCONF
- * ----------------------------------------------------------------------- */
- fragptr.p->fragStatus = Fragrecord::BLOCKED;
- fragptr.p->fragActiveStatus = ZTRUE;
- lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_HOLDOPS;
- return;
-}//Dblqh::execTUP_PREPLCPCONF()
-
-void Dblqh::execTUP_PREPLCPREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execTUP_PREPLCPREF()
+ c_fragment_pool.getPtr(fragptr);
+
+ ndbrequire(ref->tableId == fragptr.p->tabRef);
+ ndbrequire(ref->fragmentId == fragptr.p->fragId);
-void Dblqh::execLCP_FRAGIDREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execLCP_FRAGIDREF()
+ tabptr.i = ref->tableId;
+ ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
+
+ lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
+ lcpPtr.p->m_acc.lcpLocstate = LcpLocRecord::ACC_COMPLETED;
+ contChkpNextFragLab(signal);
+}
/* --------------------------------------------------------------------------
- * A NUMBER OF OPERATIONS THAT HAVE BEEN SET ON HOLD IN ACC. MOVE THOSE TO
- * LIST OF BLOCKED ACC OPERATIONS. IF MORE OPERATIONS ARE BLOCKED GET THOSE
- * OTHERWISE CONTINUE THE LOCAL CHECKPOINT BY REQUESTING TUP AND ACC TO
- * WRITE THEIR START CHECKPOINT.
+ * PRECONDITION: LCP_PTR:LCP_STATE = WAIT_FRAGID
* --------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_LOCSTATE = WAIT_LCPHOLDOP
- * ------------------------------------------------------------------------- */
-/* ***************>> */
-/* LCP_HOLDOPCONF > */
-/* ***************>> */
-void Dblqh::execLCP_HOLDOPCONF(Signal* signal)
+ * WE NOW HAVE THE LOCAL FRAGMENTS THAT THE LOCAL CHECKPOINT WILL USE.
+ * -------------------------------------------------------------------------- */
+void Dblqh::execLCP_PREPARE_CONF(Signal* signal)
{
- UintR tnoHoldops;
- Uint32 Tdata[23];
- Uint32 Tlength;
-
jamEntry();
- lcpLocptr.i = signal->theData[0];
- Tlength = signal->theData[1];
- for (Uint32 i = 0; i < 23; i++)
- Tdata[i] = signal->theData[i + 2];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- ndbrequire(lcpLocptr.p->lcpLocstate == LcpLocRecord::WAIT_LCPHOLDOP);
-
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- /* ------------------------------------------------------------------------
- * NO ERROR CHECK ON USING VALUE IN MASTER_LCP_REC. ERROR IN THIS
- * REFERENCE WILL CAUSE POINTER OUT OF RANGE WHICH CAUSES A SYSTEM RESTART.
- * ----------------------------------------------------------------------- */
- tnoHoldops = Tlength & 65535;
+
+ 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;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- ndbrequire(tnoHoldops <= 23);
- for (Uint32 Tindex = 0; Tindex < tnoHoldops; Tindex++) {
- jam();
- tcConnectptr.i = Tdata[Tindex];
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- moveActiveToAcc(signal);
- }//for
- if ((Tlength >> 16) == 1) {
- jam();
- /* MORE HOLDOPS NEEDED */
- signal->theData[0] = lcpPtr.p->lcpAccptr;
- signal->theData[1] = lcpLocptr.p->locFragid;
- signal->theData[2] = 1;
- signal->theData[3] = lcpLocptr.i;
- sendSignal(fragptr.p->accBlockref, GSN_LCP_HOLDOPREQ, signal, 4, JBA);
- return;
- } else {
- jam();
-
- /* NO MORE HOLDOPS NEEDED */
- lcpLocptr.p->lcpLocstate = LcpLocRecord::HOLDOP_READY;
- checkLcpHoldop(signal);
+ c_fragment_pool.getPtr(fragptr);
+
+ ndbrequire(conf->tableId == fragptr.p->tabRef);
+ ndbrequire(conf->fragmentId == fragptr.p->fragId);
- if (lcpPtr.p->lcpState == LcpRecord::LCP_WAIT_ACTIVE_FINISH) {
- if (fragptr.p->activeList == RNIL) {
- jam();
- /* ------------------------------------------------------------------
- * THERE ARE NO MORE ACTIVE OPERATIONS. IT IS NOW OK TO START THE
- * LOCAL CHECKPOINT IN BOTH TUP AND ACC.
- * ----------------------------------------------------------------- */
- sendStartLcp(signal);
- lcpPtr.p->lcpState = LcpRecord::LCP_START_CHKP;
- } else {
- jam();
- // Set this to signal releaseActiveFrag
- // that it should check to see if itäs time to call sendStartLcp
- fragptr.p->lcpRef = lcpPtr.i;
- }//if
- }//if
- }//if
+ lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_HOLDOPS;
+ lcpPtr.p->m_acc.lcpLocstate = LcpLocRecord::WAIT_LCPHOLDOP;
- /* ----------------------- */
- /* ELSE */
- /* ------------------------------------------------------------------------
- * THERE ARE STILL MORE ACTIVE OPERATIONS. WAIT UNTIL THEY ARE FINSIHED.
- * THIS IS DISCOVERED WHEN RELEASE_ACTIVE_FRAG IS EXECUTED.
- * ------------------------------------------------------------------------
- * DO NOTHING, EXIT IS EXECUTED BELOW
- * ----------------------------------------------------------------------- */
- return;
-}//Dblqh::execLCP_HOLDOPCONF()
+ lcpPtr.p->lcpState = LcpRecord::LCP_START_CHKP;
+ lcpPtr.p->m_acc.lcpLocstate = LcpLocRecord::HOLDOP_READY;
+
+ /* ----------------------------------------------------------------------
+ * 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;
-/* ***************> */
-/* LCP_HOLDOPREF > */
-/* ***************> */
-void Dblqh::execLCP_HOLDOPREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execLCP_HOLDOPREF()
+ {
+ LcpFragOrd *ord= (LcpFragOrd*)signal->getDataPtrSend();
+ *ord = lcpPtr.p->currentFragment.lcpFragOrd;
+ EXECUTE_DIRECT(LGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
+ jamEntry();
-/* ************************************************************************>>
- * ACC_LCPSTARTED: Confirm that ACC started local checkpoint and undo
- * logging is on.
- * ************************************************************************>>
- * --------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_LOCSTATE = ACC_WAIT_STARTED
- * ------------------------------------------------------------------------- */
-void Dblqh::execACC_LCPSTARTED(Signal* signal)
-{
- jamEntry();
- lcpLocptr.i = signal->theData[0];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- ndbrequire(lcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED);
+ *ord = lcpPtr.p->currentFragment.lcpFragOrd;
+ EXECUTE_DIRECT(DBTUP, GSN_LCP_FRAG_ORD, signal, signal->length());
+ jamEntry();
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECK ON USING VALUE IN MASTER_LCP_REC. ERROR IN THIS
- * REFERENCE WILL CAUSE POINTER OUT OF RANGE WHICH CAUSES A SYSTEM RESTART.
- * ----------------------------------------------------------------------- */
- lcpLocptr.p->lcpLocstate = LcpLocRecord::ACC_STARTED;
- lcpStartedLab(signal);
- return;
-}//Dblqh::execACC_LCPSTARTED()
+ if(lcpPtr.p->firstFragmentFlag)
+ {
+ jam();
+ lcpPtr.p->firstFragmentFlag= false;
+ *ord = lcpPtr.p->currentFragment.lcpFragOrd;
+ EXECUTE_DIRECT(PGMAN, GSN_LCP_FRAG_ORD, signal, signal->length());
+ jamEntry();
-/* ******************************************> */
-/* TUP_LCPSTARTED: Same as above but for TUP. */
-/* ******************************************> */
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_LOCSTATE = TUP_WAIT_STARTED
- * ------------------------------------------------------------------------- */
-void Dblqh::execTUP_LCPSTARTED(Signal* signal)
-{
- jamEntry();
- lcpLocptr.i = signal->theData[0];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- ndbrequire(lcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_WAIT_STARTED);
+ /**
+ * First fragment mean that last LCP is complete :-)
+ */
+ EXECUTE_DIRECT(TSMAN, GSN_END_LCP_REQ, signal, signal->length());
+ jamEntry();
+ }
+ }
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECK ON USING VALUE IN MASTER_LCP_REC. ERROR IN THIS REFERENCE
- * WILL CAUSE POINTER OUT OF RANGE WHICH CAUSES A SYSTEM RESTART.
- * ----------------------------------------------------------------------- */
- lcpLocptr.p->lcpLocstate = LcpLocRecord::TUP_STARTED;
- lcpStartedLab(signal);
- return;
-}//Dblqh::execTUP_LCPSTARTED()
+ 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;
-void Dblqh::lcpStartedLab(Signal* signal)
-{
- if (checkLcpStarted(signal))
+#ifdef NDB_DEBUG_FULL
+ if(ERROR_INSERTED(5904))
{
- jam();
- /* ----------------------------------------------------------------------
- * THE LOCAL CHECKPOINT HAS BEEN STARTED. IT IS NOW TIME TO
- * RESTART THE TRANSACTIONS WHICH HAVE BEEN BLOCKED.
- * --------------------------------------------------------------------- */
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- /* ----------------------------------------------------------------------
- * 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;
- sendAccContOp(signal); /* START OPERATIONS IN ACC */
- moveAccActiveFrag(signal); /* MOVE FROM ACC BLOCKED LIST TO ACTIVE LIST
- ON FRAGMENT */
+ g_trace_lcp.sendSignal(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal,
+ BackupFragmentReq::SignalLength, JBB);
}
- /*---------------*/
- /* ELSE */
- /*-------------------------------------------------------------------------*/
- /* THE LOCAL CHECKPOINT HAS NOT BEEN STARTED. EXIT AND WAIT FOR
- * MORE SIGNALS */
- /*-------------------------------------------------------------------------*/
- /* DO NOTHING, EXIT IS EXECUTED BELOW */
- /*-------------------------------------------------------------------------*/
- return;
-}//Dblqh::lcpStartedLab()
-
-/*---------------------------------------------------------------------------
- * ACC HAVE RESTARTED THE BLOCKED OPERATIONS AGAIN IN ONE FRAGMENT PART.
- * IT IS NOW OUR TURN TO RESTART ALL OPERATIONS QUEUED IN LQH IF ALL
- * FRAGMENT PARTS ARE COMPLETED.
- *-------------------------------------------------------------------------- */
-void Dblqh::execACC_CONTOPCONF(Signal* signal)
-{
- if(ERROR_INSERTED(5035) && signal->getSendersBlockRef() != reference()){
- sendSignalWithDelay(reference(), GSN_ACC_CONTOPCONF, signal, 1000,
- signal->length());
- return;
+ else
+#endif
+ {
+ sendSignal(BACKUP_REF, GSN_BACKUP_FRAGMENT_REQ, signal,
+ BackupFragmentReq::SignalLength, JBB);
}
+
+ lcpPtr.p->m_acc.lcpLocstate = LcpLocRecord::ACC_STARTED;
+ lcpPtr.p->m_tup.lcpLocstate = LcpLocRecord::TUP_COMPLETED;
+}
- jamEntry();
- lcpLocptr.i = signal->theData[0];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- lcpLocptr.p->accContCounter = 1;
-
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- lcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- do {
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (lcpLocptr.p->accContCounter == 0) {
- jam();
- return;
- }//if
- lcpLocptr.i = lcpLocptr.p->nextLcpLoc;
- } while (lcpLocptr.i != RNIL);
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- restartOperationsLab(signal);
- return;
-}//Dblqh::execACC_CONTOPCONF()
-
-/* ********************************************************* */
-/* LQH_RESTART_OP: Restart operations after beeing blocked. */
-/* ********************************************************* */
-/*---------------------------------------------------------------------------*/
-/* PRECONDITION: FRAG_STATUS = BLOCKED AND LCP_STATE = STARTED */
-/*---------------------------------------------------------------------------*/
-void Dblqh::execLQH_RESTART_OP(Signal* signal)
-{
- jamEntry();
- fragptr.i = signal->theData[0];
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
-
- lcpPtr.i = signal->theData[1];
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- ndbrequire(fragptr.p->fragStatus == Fragrecord::BLOCKED);
- restartOperationsLab(signal);
-}//Dblqh::execLQH_RESTART_OP()
-
-void Dblqh::restartOperationsLab(Signal* signal)
-{
- Uint32 loopCount = 0;
- tcConnectptr.i = fragptr.p->firstWaitQueue;
- do {
- if (tcConnectptr.i != RNIL) {
- jam();
-/*---------------------------------------------------------------------------*/
-/* START UP THE TRANSACTION AGAIN. WE START IT AS A SEPARATE SIGNAL. */
-/*---------------------------------------------------------------------------*/
- signal->theData[0] = ZRESTART_OPERATIONS_AFTER_STOP;
- signal->theData[1] = tcConnectptr.i;
- signal->theData[2] = fragptr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- tcConnectptr.i = tcConnectptr.p->nextTc;
- } else {
- jam();
-/*--------------------------------------------------------------------------*/
-/* NO MORE OPERATIONS TO RESTART. WE CAN NOW RESET THE STATE TO ACTIVE AND */
-/* RESTART NORMAL ACTIVITIES ON THE FRAGMENT WHILE THE FUZZY PART OF THE */
-/* LOCAL CHECKPOINT IS COMPLETING. */
-/* IF THE CHECKPOINT WAS COMPLETED ALREADY ON THIS FRAGMENT WE PROCEED WITH */
-/* THE NEXT FRAGMENT NOW THAT WE HAVE COMPLETED THIS CHECKPOINT. */
-/*--------------------------------------------------------------------------*/
- fragptr.p->fragStatus = Fragrecord::FSACTIVE;
- if (lcpPtr.p->lcpState == LcpRecord::LCP_BLOCKED_COMP) {
- jam();
- contChkpNextFragLab(signal);
- return;
- }//if
- return;
- }//if
- loopCount++;
- if (loopCount > 16) {
- jam();
- signal->theData[0] = fragptr.i;
- signal->theData[1] = lcpPtr.i;
- sendSignal(cownref, GSN_LQH_RESTART_OP, signal, 2, JBB);
- return;
- }//if
- } while (1);
-}//Dblqh::restartOperationsLab()
-
-void Dblqh::restartOperationsAfterStopLab(Signal* signal)
-{
- /*-------------------------------------------------------------------------
- * WHEN ARRIVING HERE THE OPERATION IS ALREADY SET IN THE ACTIVE LIST.
- * THUS WE CAN IMMEDIATELY CALL THE METHODS THAT EXECUTE FROM WHERE
- * THE OPERATION WAS STOPPED.
- *------------------------------------------------------------------------ */
- switch (tcConnectptr.p->transactionState) {
- case TcConnectionrec::STOPPED:
- jam();
- /*-----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND ACCKEYREQ
- *---------------------------------------------------------------------- */
- prepareContinueAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::COMMIT_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND ACC_COMMITREQ
- * --------------------------------------------------------------------- */
- releaseActiveFrag(signal);
- commitContinueAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::ABORT_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND ACC_ABORTREQ
- * --------------------------------------------------------------------- */
- abortContinueAfterBlockedLab(signal, true);
- return;
- break;
- case TcConnectionrec::COPY_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING COPY FRAGMENT
- * --------------------------------------------------------------------- */
- continueCopyAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::COPY_FIRST_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING COPY FRAGMENT
- * --------------------------------------------------------------------- */
- continueFirstCopyAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::SCAN_FIRST_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN
- * --------------------------------------------------------------------- */
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
- continueFirstScanAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::SCAN_CHECK_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN
- * --------------------------------------------------------------------- */
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
- continueAfterCheckLcpStopBlocked(signal);
- return;
- break;
- case TcConnectionrec::SCAN_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING SCAN
- * --------------------------------------------------------------------- */
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
- continueScanAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::SCAN_RELEASE_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING RELEASE
- * LOCKS IN SCAN
- * --------------------------------------------------------------------- */
- tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
- continueScanReleaseAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::SCAN_CLOSE_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING CLOSE OF SCAN
- * --------------------------------------------------------------------- */
- continueCloseScanAfterBlockedLab(signal);
- return;
- break;
- case TcConnectionrec::COPY_CLOSE_STOPPED:
- jam();
- /* ----------------------------------------------------------------------
- * STOPPED BEFORE TRYING TO SEND NEXT_SCANREQ DURING CLOSE OF COPY
- * --------------------------------------------------------------------- */
- continueCloseCopyAfterBlockedLab(signal);
- return;
- break;
- default:
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- break;
- }//switch
-}//Dblqh::restartOperationsAfterStopLab()
-
-/* *************** */
-/* ACC_LCPCONF > */
-/* *************** */
-/*---------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_LOCSTATE = ACC_STARTED
- *-------------------------------------------------------------------------- */
-void Dblqh::execACC_LCPCONF(Signal* signal)
+void Dblqh::execBACKUP_FRAGMENT_REF(Signal* signal)
{
- jamEntry();
- lcpLocptr.i = signal->theData[0];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- ndbrequire(lcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_STARTED);
-
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECK ON USING VALUE IN MASTER_LCP_REC. ERROR IN
- * THIS REFERENCE WILL CAUSE POINTER OUT OF RANGE WHICH CAUSES A
- * SYSTEM RESTART.
- * ----------------------------------------------------------------------- */
- lcpLocptr.p->lcpLocstate = LcpLocRecord::ACC_COMPLETED;
- lcpCompletedLab(signal);
- return;
-}//Dblqh::execACC_LCPCONF()
+ ndbrequire(false);
+}
-/* *************** */
-/* TUP_LCPCONF > */
-/* *************** */
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_LOCSTATE = TUP_STARTED
- * ------------------------------------------------------------------------- */
-void Dblqh::execTUP_LCPCONF(Signal* signal)
+void Dblqh::execBACKUP_FRAGMENT_CONF(Signal* signal)
{
jamEntry();
- lcpLocptr.i = signal->theData[0];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- ndbrequire(lcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_STARTED);
+ //BackupFragmentConf* conf= (BackupFragmentConf*)signal->getDataPtr();
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
+ lcpPtr.i = 0;
ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECK ON USING VALUE IN MASTER_LCP_REC. ERROR IN THIS
- * REFERENCE WILL CAUSE POINTER OUT OF RANGE WHICH CAUSES A SYSTEM RESTART.
- * ----------------------------------------------------------------------- */
- lcpLocptr.p->lcpLocstate = LcpLocRecord::TUP_COMPLETED;
- lcpCompletedLab(signal);
- return;
-}//Dblqh::execTUP_LCPCONF()
+ ndbrequire(lcpPtr.p->m_acc.lcpLocstate == LcpLocRecord::ACC_STARTED);
+ lcpPtr.p->m_acc.lcpLocstate = LcpLocRecord::ACC_COMPLETED;
+ lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
-void Dblqh::lcpCompletedLab(Signal* signal)
-{
- checkLcpCompleted(signal);
- if (lcpPtr.p->lcpState != LcpRecord::LCP_COMPLETED) {
- jam();
- /* ----------------------------------------------------------------------
- * THE LOCAL CHECKPOINT HAS NOT BEEN COMPLETED, EXIT & WAIT
- * FOR MORE SIGNALS
- * --------------------------------------------------------------------- */
- return;
- }//if
/* ------------------------------------------------------------------------
* THE LOCAL CHECKPOINT HAS BEEN COMPLETED. IT IS NOW TIME TO START
* A LOCAL CHECKPOINT ON THE NEXT FRAGMENT OR COMPLETE THIS LCP ROUND.
@@ -10718,9 +10253,9 @@ void Dblqh::lcpCompletedLab(Signal* signal)
* TO CATER FOR NODE CRASHES WE SEND IT IN PARALLEL TO ALL NODES.
* ----------------------------------------------------------------------- */
fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
fragptr.p->fragActiveStatus = ZFALSE;
-
+
contChkpNextFragLab(signal);
return;
}//Dblqh::lcpCompletedLab()
@@ -10729,10 +10264,8 @@ void
Dblqh::sendLCP_FRAG_REP(Signal * signal,
const LcpRecord::FragOrd & fragOrd) const {
- FragrecordPtr fragPtr;
- fragPtr.i = fragOrd.fragPtrI;
- ptrCheckGuard(fragPtr, cfragrecFileSize, fragrecord);
-
+ 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;
@@ -10740,8 +10273,8 @@ Dblqh::sendLCP_FRAG_REP(Signal * signal,
lcpReport->lcpNo = fragOrd.lcpFragOrd.lcpNo;
lcpReport->tableId = fragOrd.lcpFragOrd.tableId;
lcpReport->fragId = fragOrd.lcpFragOrd.fragmentId;
- lcpReport->maxGciCompleted = fragPtr.p->maxGciCompletedInLcp;
- lcpReport->maxGciStarted = fragPtr.p->maxGciInLcp;
+ lcpReport->maxGciCompleted = fragPtrP->maxGciCompletedInLcp;
+ lcpReport->maxGciStarted = fragPtrP->maxGciInLcp;
for (Uint32 i = 0; i < cnoOfNodes; i++) {
jam();
@@ -10769,7 +10302,6 @@ void Dblqh::contChkpNextFragLab(Signal* signal)
* but restarting of operations isn't
*/
lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP;
- //restartOperationsLab(signal);
return;
}//if
@@ -10781,7 +10313,6 @@ void Dblqh::contChkpNextFragLab(Signal* signal)
/* ------------------------------------------------------------------------
* WE ALSO RELEASE THE LOCAL LCP RECORDS.
* ----------------------------------------------------------------------- */
- releaseLocalLcps(signal);
if (lcpPtr.p->lcpQueued) {
jam();
/* ----------------------------------------------------------------------
@@ -10803,7 +10334,7 @@ void Dblqh::contChkpNextFragLab(Signal* signal)
/* ----------------------------------------------------------------------
* NOW THE COMPLETE LOCAL CHECKPOINT ROUND IS COMPLETED.
* --------------------------------------------------------------------- */
- completeLcpRoundLab(signal);
+ completeLcpRoundLab(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
return;
}//if
@@ -10816,9 +10347,6 @@ void Dblqh::contChkpNextFragLab(Signal* signal)
void Dblqh::sendLCP_FRAGIDREQ(Signal* signal)
{
- ndbrequire(lcpPtr.p->firstLcpLocTup == RNIL);
- ndbrequire(lcpPtr.p->firstLcpLocAcc == RNIL);
-
TablerecPtr tabPtr;
tabPtr.i = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
ptrAss(tabPtr, tablerec);
@@ -10828,20 +10356,24 @@ void Dblqh::sendLCP_FRAGIDREQ(Signal* signal)
/**
* Fake that the fragment is done
*/
- lcpCompletedLab(signal);
+ contChkpNextFragLab(signal);
return;
}
ndbrequire(tabPtr.p->tableStatus == Tablerec::TABLE_DEFINED);
lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_FRAGID;
- signal->theData[0] = lcpPtr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
- signal->theData[3] = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- signal->theData[4] = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
- signal->theData[5] = lcpPtr.p->currentFragment.lcpFragOrd.lcpId % MAX_LCP_STORED;
- sendSignal(fragptr.p->accBlockref, GSN_LCP_FRAGIDREQ, signal, 6, JBB);
+ 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)
@@ -10886,63 +10418,50 @@ void Dblqh::sendEMPTY_LCP_CONF(Signal* signal, bool idle)
lcpPtr.p->m_EMPTY_LCP_REQ.clear();
}//Dblqh::sendEMPTY_LCPCONF()
-void Dblqh::execACC_LCPREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execACC_LCPREF()
-
-void Dblqh::execTUP_LCPREF(Signal* signal)
-{
- jamEntry();
- ndbrequire(false);
-}//Dblqh::execTUP_LCPREF()
-
/* --------------------------------------------------------------------------
* THE LOCAL CHECKPOINT ROUND IS NOW COMPLETED. SEND COMPLETED MESSAGE
* TO THE MASTER DIH.
* ------------------------------------------------------------------------- */
-void Dblqh::completeLcpRoundLab(Signal* signal)
+void Dblqh::completeLcpRoundLab(Signal* signal, Uint32 lcpId)
{
clcpCompletedState = LCP_CLOSE_STARTED;
- signal->theData[0] = caccBlockref;
- signal->theData[1] = cownref;
- sendSignal(caccBlockref, GSN_END_LCPREQ, signal, 2, JBB);
- signal->theData[0] = ctupBlockref;
- signal->theData[1] = cownref;
- sendSignal(ctupBlockref, GSN_END_LCPREQ, signal, 2, JBB);
+
+ 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);
+
+ lcpPtr.i = 0;
+ ptrAss(lcpPtr, lcpRecord);
+ lcpPtr.p->m_outstanding = 3;
return;
}//Dblqh::completeLcpRoundLab()
void Dblqh::execEND_LCPCONF(Signal* signal)
{
jamEntry();
- BlockReference userpointer = signal->theData[0];
- if (userpointer == caccBlockref) {
- if (clcpCompletedState == LCP_CLOSE_STARTED) {
- jam();
- clcpCompletedState = ACC_LCP_CLOSE_COMPLETED;
- return;
- } else {
- jam();
- ndbrequire(clcpCompletedState == TUP_LCP_CLOSE_COMPLETED);
- clcpCompletedState = LCP_IDLE;
- }//if
- } else {
- ndbrequire(userpointer == ctupBlockref);
- if (clcpCompletedState == LCP_CLOSE_STARTED) {
- jam();
- clcpCompletedState = TUP_LCP_CLOSE_COMPLETED;
- return;
- } else {
- jam();
- ndbrequire(clcpCompletedState == ACC_LCP_CLOSE_COMPLETED);
- clcpCompletedState = LCP_IDLE;
- }//if
- }//if
lcpPtr.i = 0;
ptrAss(lcpPtr, lcpRecord);
- sendLCP_COMPLETE_REP(signal, lcpPtr.p->currentFragment.lcpFragOrd.lcpId);
+
+ 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)
@@ -10955,6 +10474,7 @@ void Dblqh::sendLCP_COMPLETE_REP(Signal* signal, Uint32 lcpId)
lcpPtr.i = 0;
ptrAss(lcpPtr, lcpRecord);
lcpPtr.p->lastFragmentFlag = false;
+ lcpPtr.p->firstFragmentFlag = false;
LcpCompleteRep* rep = (LcpCompleteRep*)signal->getDataPtrSend();
rep->nodeId = getOwnNodeId();
@@ -10978,269 +10498,9 @@ void Dblqh::sendLCP_COMPLETE_REP(Signal* signal, Uint32 lcpId)
sendEMPTY_LCP_CONF(signal, true);
}
return;
-}//Dblqh::sendCOMP_LCP_ROUND()
-
-/* ==========================================================================
- * ======= CHECK IF ALL PARTS OF A LOCAL CHECKPOINT ARE COMPLETED =======
- *
- * SUBROUTINE SHORT NAME = CLC
- * ========================================================================= */
-void Dblqh::checkLcpCompleted(Signal* signal)
-{
- LcpLocRecordPtr clcLcpLocptr;
-
- clcLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- while (clcLcpLocptr.i != RNIL) {
- ptrCheckGuard(clcLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (clcLcpLocptr.p->lcpLocstate != LcpLocRecord::ACC_COMPLETED) {
- jam();
- ndbrequire((clcLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED) ||
- (clcLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_STARTED));
- return;
- }//if
- clcLcpLocptr.i = clcLcpLocptr.p->nextLcpLoc;
- }
-
- clcLcpLocptr.i = lcpPtr.p->firstLcpLocTup;
- while (clcLcpLocptr.i != RNIL){
- ptrCheckGuard(clcLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (clcLcpLocptr.p->lcpLocstate != LcpLocRecord::TUP_COMPLETED) {
- jam();
- ndbrequire((clcLcpLocptr.p->lcpLocstate==LcpLocRecord::TUP_WAIT_STARTED)
- ||(clcLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_STARTED));
- return;
- }//if
- clcLcpLocptr.i = clcLcpLocptr.p->nextLcpLoc;
- }
-
- lcpPtr.p->lcpState = LcpRecord::LCP_COMPLETED;
-}//Dblqh::checkLcpCompleted()
-
-/* ==========================================================================
- * ======= CHECK IF ALL HOLD OPERATIONS ARE COMPLETED =======
- *
- * SUBROUTINE SHORT NAME = CHO
- * ========================================================================= */
-void Dblqh::checkLcpHoldop(Signal* signal)
-{
- LcpLocRecordPtr choLcpLocptr;
-
- choLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- do {
- ptrCheckGuard(choLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (choLcpLocptr.p->lcpLocstate != LcpLocRecord::HOLDOP_READY) {
- ndbrequire(choLcpLocptr.p->lcpLocstate == LcpLocRecord::WAIT_LCPHOLDOP);
- return;
- }//if
- choLcpLocptr.i = choLcpLocptr.p->nextLcpLoc;
- } while (choLcpLocptr.i != RNIL);
- lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_ACTIVE_FINISH;
-}//Dblqh::checkLcpHoldop()
-
-/* ==========================================================================
- * ======= CHECK IF ALL PARTS OF A LOCAL CHECKPOINT ARE STARTED =======
- *
- * SUBROUTINE SHORT NAME = CLS
- * ========================================================================== */
-bool
-Dblqh::checkLcpStarted(Signal* signal)
-{
- LcpLocRecordPtr clsLcpLocptr;
-
- terrorCode = ZOK;
- clsLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- int i = 0;
- do {
- ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::ACC_WAIT_STARTED){
- return false;
- }//if
- clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc;
- i++;
- } while (clsLcpLocptr.i != RNIL);
-
- i = 0;
- clsLcpLocptr.i = lcpPtr.p->firstLcpLocTup;
- do {
- ptrCheckGuard(clsLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (clsLcpLocptr.p->lcpLocstate == LcpLocRecord::TUP_WAIT_STARTED){
- return false;
- }//if
- clsLcpLocptr.i = clsLcpLocptr.p->nextLcpLoc;
- i++;
- } while (clsLcpLocptr.i != RNIL);
-
- return true;
-}//Dblqh::checkLcpStarted()
-
-/* ==========================================================================
- * ======= CHECK IF ALL PREPARE TUP OPERATIONS ARE COMPLETED =======
- *
- * SUBROUTINE SHORT NAME = CLT
- * ========================================================================== */
-void Dblqh::checkLcpTupprep(Signal* signal)
-{
- LcpLocRecordPtr cltLcpLocptr;
- cltLcpLocptr.i = lcpPtr.p->firstLcpLocTup;
- do {
- ptrCheckGuard(cltLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (cltLcpLocptr.p->lcpLocstate != LcpLocRecord::IDLE) {
- ndbrequire(cltLcpLocptr.p->lcpLocstate == LcpLocRecord::WAIT_TUP_PREPLCP);
- return;
- }//if
- cltLcpLocptr.i = cltLcpLocptr.p->nextLcpLoc;
- } while (cltLcpLocptr.i != RNIL);
- lcpPtr.p->lcpState = LcpRecord::LCP_WAIT_HOLDOPS;
-}//Dblqh::checkLcpTupprep()
-
-/* ==========================================================================
- * ======= INITIATE LCP LOCAL RECORD USED TOWARDS ACC =======
- *
- * ========================================================================== */
-void Dblqh::initLcpLocAcc(Signal* signal, Uint32 fragId)
-{
- lcpLocptr.p->nextLcpLoc = lcpPtr.p->firstLcpLocAcc;
- lcpPtr.p->firstLcpLocAcc = lcpLocptr.i;
- lcpLocptr.p->locFragid = fragId;
- lcpLocptr.p->waitingBlock = LcpLocRecord::ACC;
- lcpLocptr.p->lcpLocstate = LcpLocRecord::IDLE;
- lcpLocptr.p->masterLcpRec = lcpPtr.i;
- lcpLocptr.p->tupRef = RNIL;
-}//Dblqh::initLcpLocAcc()
-
-/* ==========================================================================
- * ======= INITIATE LCP LOCAL RECORD USED TOWARDS TUP =======
- *
- * ========================================================================== */
-void Dblqh::initLcpLocTup(Signal* signal, Uint32 fragId)
-{
- lcpLocptr.p->nextLcpLoc = lcpPtr.p->firstLcpLocTup;
- lcpPtr.p->firstLcpLocTup = lcpLocptr.i;
- lcpLocptr.p->locFragid = fragId;
- lcpLocptr.p->waitingBlock = LcpLocRecord::TUP;
- lcpLocptr.p->lcpLocstate = LcpLocRecord::WAIT_TUP_PREPLCP;
- lcpLocptr.p->masterLcpRec = lcpPtr.i;
- lcpLocptr.p->tupRef = RNIL;
-}//Dblqh::initLcpLocTup()
-
-/* --------------------------------------------------------------------------
- * ------- MOVE OPERATION FROM ACC WAITING LIST ON FRAGMENT -------
- * ------- TO ACTIVE LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME = MAA
- * -------------------------------------------------------------------------- */
-void Dblqh::moveAccActiveFrag(Signal* signal)
-{
- UintR maaTcNextConnectptr;
-
- tcConnectptr.i = fragptr.p->accBlockedList;
- fragptr.p->accBlockedList = RNIL;
- /* ------------------------------------------------------------------------
- * WE WILL MOVE ALL RECORDS FROM THE ACC BLOCKED LIST AT ONCE.
- * ------------------------------------------------------------------------ */
- while (tcConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- maaTcNextConnectptr = tcConnectptr.p->nextTc;
- ndbrequire(tcConnectptr.p->listState == TcConnectionrec::ACC_BLOCK_LIST);
- tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
- linkActiveFrag(signal);
- tcConnectptr.i = maaTcNextConnectptr;
- }//while
-}//Dblqh::moveAccActiveFrag()
-
-/* --------------------------------------------------------------------------
- * ------- MOVE OPERATION FROM ACTIVE LIST ON FRAGMENT -------
- * ------- TO ACC BLOCKED LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME = MAT
- * -------------------------------------------------------------------------- */
-void Dblqh::moveActiveToAcc(Signal* signal)
-{
- TcConnectionrecPtr matTcNextConnectptr;
-
- releaseActiveList(signal);
- /* ------------------------------------------------------------------------
- * PUT OPERATION RECORD FIRST IN ACC BLOCKED LIST.
- * ------------------------------------------------------------------------ */
- matTcNextConnectptr.i = fragptr.p->accBlockedList;
- tcConnectptr.p->nextTc = matTcNextConnectptr.i;
- tcConnectptr.p->prevTc = RNIL;
- tcConnectptr.p->listState = TcConnectionrec::ACC_BLOCK_LIST;
- fragptr.p->accBlockedList = tcConnectptr.i;
- if (matTcNextConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(matTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- matTcNextConnectptr.p->prevTc = tcConnectptr.i;
- }//if
-}//Dblqh::moveActiveToAcc()
-
-/* ------------------------------------------------------------------------- */
-/* ---- RELEASE LOCAL LCP RECORDS AFTER COMPLETION OF A LOCAL CHECKPOINT---- */
-/* */
-/* SUBROUTINE SHORT NAME = RLL */
-/* ------------------------------------------------------------------------- */
-void Dblqh::releaseLocalLcps(Signal* signal)
-{
- lcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- while (lcpLocptr.i != RNIL){
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- Uint32 tmp = lcpLocptr.p->nextLcpLoc;
- releaseLcpLoc(signal);
- lcpLocptr.i = tmp;
- }
- lcpPtr.p->firstLcpLocAcc = RNIL;
- lcpLocptr.i = lcpPtr.p->firstLcpLocTup;
- while (lcpLocptr.i != RNIL){
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- Uint32 tmp = lcpLocptr.p->nextLcpLoc;
- releaseLcpLoc(signal);
- lcpLocptr.i = tmp;
- }
- lcpPtr.p->firstLcpLocTup = RNIL;
-
-}//Dblqh::releaseLocalLcps()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEIZE LCP LOCAL RECORD ------- */
-/* */
-/* ------------------------------------------------------------------------- */
-void Dblqh::seizeLcpLoc(Signal* signal)
-{
- lcpLocptr.i = cfirstfreeLcpLoc;
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- cfirstfreeLcpLoc = lcpLocptr.p->nextLcpLoc;
- lcpLocptr.p->nextLcpLoc = RNIL;
-}//Dblqh::seizeLcpLoc()
-
-/* ------------------------------------------------------------------------- */
-/* ------- SEND ACC_CONT_OP ------- */
-/* */
-/* INPUT: LCP_PTR LOCAL CHECKPOINT RECORD */
-/* FRAGPTR FRAGMENT RECORD */
-/* */
-/* SUBROUTINE SHORT NAME = SAC */
-/* ------------------------------------------------------------------------- */
-void Dblqh::sendAccContOp(Signal* signal)
-{
- LcpLocRecordPtr sacLcpLocptr;
+}//Dblqh::sendCOMP_LCP_ROUND()
- int count = 0;
- sacLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- do {
- ptrCheckGuard(sacLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- sacLcpLocptr.p->accContCounter = 0;
- /* ------------------------------------------------------------------- */
- /*SEND START OPERATIONS TO ACC AGAIN */
- /* ------------------------------------------------------------------- */
- signal->theData[0] = lcpPtr.p->lcpAccptr;
- signal->theData[1] = sacLcpLocptr.p->locFragid;
- sendSignal(fragptr.p->accBlockref, GSN_ACC_CONTOPREQ, signal, 2, JBA);
- sacLcpLocptr.i = sacLcpLocptr.p->nextLcpLoc;
- } while (sacLcpLocptr.i != RNIL);
-
-}//Dblqh::sendAccContOp()
/* ------------------------------------------------------------------------- */
/* ------- SEND ACC_LCPREQ AND TUP_LCPREQ ------- */
@@ -11251,39 +10511,6 @@ void Dblqh::sendAccContOp(Signal* signal)
/* ------------------------------------------------------------------------- */
void Dblqh::sendStartLcp(Signal* signal)
{
- LcpLocRecordPtr stlLcpLocptr;
- stlLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
- do {
- jam();
- ptrCheckGuard(stlLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- stlLcpLocptr.p->lcpLocstate = LcpLocRecord::ACC_WAIT_STARTED;
- signal->theData[0] = lcpPtr.p->lcpAccptr;
- signal->theData[1] = stlLcpLocptr.i;
- signal->theData[2] = stlLcpLocptr.p->locFragid;
- sendSignal(fragptr.p->accBlockref, GSN_ACC_LCPREQ, signal, 3, JBA);
- stlLcpLocptr.i = stlLcpLocptr.p->nextLcpLoc;
- } while (stlLcpLocptr.i != RNIL);
-
- stlLcpLocptr.i = lcpPtr.p->firstLcpLocTup;
- do {
- jam();
- ptrCheckGuard(stlLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- stlLcpLocptr.p->lcpLocstate = LcpLocRecord::TUP_WAIT_STARTED;
- signal->theData[0] = stlLcpLocptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = stlLcpLocptr.p->tupRef;
- if(ERROR_INSERTED(5077))
- sendSignalWithDelay(fragptr.p->tupBlockref, GSN_TUP_LCPREQ,
- signal, 5000, 3);
- else
- sendSignal(fragptr.p->tupBlockref, GSN_TUP_LCPREQ, signal, 3, JBA);
- stlLcpLocptr.i = stlLcpLocptr.p->nextLcpLoc;
- } while (stlLcpLocptr.i != RNIL);
-
- if(ERROR_INSERTED(5077))
- {
- ndbout_c("Delayed TUP_LCPREQ with 5 sec");
- }
}//Dblqh::sendStartLcp()
/* ------------------------------------------------------------------------- */
@@ -13429,42 +12656,99 @@ void Dblqh::execSTART_FRAGREQ(Signal* signal)
}//if
tabptr.p->tableStatus = Tablerec::TABLE_DEFINED;
- initFragrecSr(signal);
- if (startFragReq->lcpNo == ZNIL) {
+ 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();
- /* ----------------------------------------------------------------------
- * THERE WAS NO LOCAL CHECKPOINT AVAILABLE FOR THIS FRAGMENT. WE DO
- * NOT NEED TO READ IN THE LOCAL FRAGMENT. WE HAVE ALREADY ADDED THE
- * FRAGMENT AS AN EMPTY FRAGMENT AT THIS POINT. THUS WE CAN SIMPLY
- * EXIT AND THE FRAGMENT WILL PARTICIPATE IN THE EXECUTION OF THE LOG.
- * PUT FRAGMENT ON LIST OF COMPLETED FRAGMENTS FOR EXECUTION OF LOG.
- * ---------------------------------------------------------------------- */
- fragptr.p->nextFrag = cfirstCompletedFragSr;
- cfirstCompletedFragSr = fragptr.i;
- return;
+ fragptr.p->lcpId[lcpNo] = lcpId;
+ fragptr.p->nextLcp = 0;
+ } else if (lcpNo < (MAX_LCP_STORED - 1)) {
+ jam();
+ fragptr.p->lcpId[lcpNo] = lcpId;
+ fragptr.p->nextLcp = lcpNo + 1;
+ } else {
+ ndbrequire(lcpNo == ZNIL);
+ jam();
+ fragptr.p->nextLcp = 0;
}//if
- if (cfirstWaitFragSr == RNIL) {
+ fragptr.p->srNoLognodes = noOfLogNodes;
+ fragptr.p->logFlag = Fragrecord::STATE_FALSE;
+ fragptr.p->srStatus = Fragrecord::SS_IDLE;
+
+ if (noOfLogNodes > 0) {
jam();
- lcpPtr.i = 0;
- ptrAss(lcpPtr, lcpRecord);
- if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE) {
+ for (Uint32 i = 0; i < noOfLogNodes; i++) {
jam();
- initLcpSr(signal, startFragReq->lcpNo,
- startFragReq->lcpId, tabptr.i,
- fragId, fragptr.i);
- signal->theData[0] = lcpPtr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
- signal->theData[3] = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- signal->theData[4] = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
- sendSignal(fragptr.p->accBlockref, GSN_SR_FRAGIDREQ, signal, 5, JBB);
- return;
- }//if
+ 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 || fragptr.i != tabptr.p->fragrec[0])
+ {
+ 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);
+
+ if(lcpNo == ZNIL)
+ {
+ for (Uint32 i = 0; i<MAX_FRAG_PER_NODE; i++)
+ {
+ if (tabptr.p->fragrec[i] != RNIL)
+ {
+ signal->theData[0] = tabptr.i;
+ signal->theData[1] = tabptr.p->fragid[i];
+ sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB);
+ }
+ }
+ }
+
+ return;
}//if
- fragptr.p->nextFrag = cfirstWaitFragSr;
- cfirstWaitFragSr = fragptr.i;
+
+ 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];
@@ -13477,256 +12761,66 @@ void Dblqh::startFragRefLab(Signal* signal)
return;
}//Dblqh::startFragRefLab()
-/* ***************>> */
-/* SR_FRAGIDCONF > */
-/* ***************>> */
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_PTR:LCP_STATE = SR_WAIT_FRAGID
- * -------------------------------------------------------------------------- */
-void Dblqh::execSR_FRAGIDCONF(Signal* signal)
-{
- SrFragidConf * const srFragidConf = (SrFragidConf *)&signal->theData[0];
- jamEntry();
-
- lcpPtr.i = srFragidConf->lcpPtr;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- ndbrequire(lcpPtr.p->lcpState == LcpRecord::LCP_SR_WAIT_FRAGID);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECKING OF TNO_LOCFRAG VALUE. OUT OF BOUND WILL IMPLY THAT AN
- * INDEX OUT OF RANGE WILL CAUSE A SYSTEM RESTART WHICH IS DESIRED.
- * ------------------------------------------------------------------------ */
- lcpPtr.p->lcpAccptr = srFragidConf->accPtr;
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- fragptr.p->accFragptr[0] = srFragidConf->fragPtr[0];
- fragptr.p->accFragptr[1] = srFragidConf->fragPtr[1];
- Uint32 noLocFrag = srFragidConf->noLocFrag;
- ndbrequire(noLocFrag == 2);
- Uint32 fragid[2];
- Uint32 i;
- for (i = 0; i < noLocFrag; i++) {
- fragid[i] = srFragidConf->fragId[i];
- }//for
-
- for (i = 0; i < noLocFrag; i++) {
- jam();
- Uint32 fragId = fragid[i];
- /* ----------------------------------------------------------------------
- * THERE IS NO ERROR CHECKING ON PURPOSE. IT IS POSSIBLE TO CALCULATE HOW
- * MANY LOCAL LCP RECORDS THERE SHOULD BE. IT SHOULD NEVER HAPPEN THAT
- * THERE IS NO ONE FREE. IF THERE IS NO ONE IT WILL ALSO BE A POINTER
- * OUT OF RANGE WHICH IS AN ERROR CODE IN ITSELF. REUSES ERROR
- * HANDLING IN AXE VM.
- * ---------------------------------------------------------------------- */
- seizeLcpLoc(signal);
- initLcpLocAcc(signal, fragId);
- lcpLocptr.p->lcpLocstate = LcpLocRecord::SR_ACC_STARTED;
- signal->theData[0] = lcpPtr.p->lcpAccptr;
- signal->theData[1] = lcpLocptr.i;
- signal->theData[2] = lcpLocptr.p->locFragid;
- signal->theData[3] = lcpPtr.p->currentFragment.lcpFragOrd.lcpId % MAX_LCP_STORED;
- sendSignal(fragptr.p->accBlockref, GSN_ACC_SRREQ, signal, 4, JBB);
- seizeLcpLoc(signal);
- initLcpLocTup(signal, fragId);
- lcpLocptr.p->lcpLocstate = LcpLocRecord::SR_TUP_STARTED;
- signal->theData[0] = lcpLocptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- signal->theData[3] = lcpLocptr.p->locFragid;
- signal->theData[4] = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
- sendSignal(fragptr.p->tupBlockref, GSN_TUP_SRREQ, signal, 5, JBB);
- }//for
- lcpPtr.p->lcpState = LcpRecord::LCP_SR_STARTED;
- return;
-}//Dblqh::execSR_FRAGIDCONF()
-
-/* ***************> */
-/* SR_FRAGIDREF > */
-/* ***************> */
-void Dblqh::execSR_FRAGIDREF(Signal* signal)
+void Dblqh::execRESTORE_LCP_REF(Signal* signal)
{
jamEntry();
ndbrequire(false);
-}//Dblqh::execSR_FRAGIDREF()
-
-/* ************>> */
-/* ACC_SRCONF > */
-/* ************>> */
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_LOCSTATE = SR_ACC_STARTED
- * -------------------------------------------------------------------------- */
-void Dblqh::execACC_SRCONF(Signal* signal)
-{
- jamEntry();
- lcpLocptr.i = signal->theData[0];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (lcpLocptr.p->lcpLocstate != LcpLocRecord::SR_ACC_STARTED) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
-
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECK ON USING VALUE IN MASTER_LCP_REC. ERROR IN THIS REFERENCE
- * WILL CAUSE POINTER OUT OF RANGE WHICH CAUSES A SYSTEM RESTART.
- * ------------------------------------------------------------------------ */
- lcpLocptr.p->lcpLocstate = LcpLocRecord::SR_ACC_COMPLETED;
- srCompletedLab(signal);
return;
-}//Dblqh::execACC_SRCONF()
+}
-/* ************> */
-/* ACC_SRREF > */
-/* ************> */
-void Dblqh::execACC_SRREF(Signal* signal)
+void Dblqh::execRESTORE_LCP_CONF(Signal* signal)
{
jamEntry();
- terrorCode = signal->theData[1];
- systemErrorLab(signal, __LINE__);
- return;
-}//Dblqh::execACC_SRREF()
+ RestoreLcpConf* conf= (RestoreLcpConf*)signal->getDataPtr();
+ fragptr.i = conf->senderData;
+ c_fragment_pool.getPtr(fragptr);
-/* ************>> */
-/* TUP_SRCONF > */
-/* ************>> */
-/* --------------------------------------------------------------------------
- * PRECONDITION: LCP_LOCPTR:LCP_LOCSTATE = SR_TUP_STARTED
- * -------------------------------------------------------------------------- */
-void Dblqh::execTUP_SRCONF(Signal* signal)
-{
- jamEntry();
- lcpLocptr.i = signal->theData[0];
- ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- Uint32 tupFragPtr = signal->theData[1];
- ndbrequire(lcpLocptr.p->lcpLocstate == LcpLocRecord::SR_TUP_STARTED);
+ c_lcp_restoring_fragments.remove(fragptr);
+ c_lcp_complete_fragments.add(fragptr);
- lcpPtr.i = lcpLocptr.p->masterLcpRec;
- ptrCheckGuard(lcpPtr, clcpFileSize, lcpRecord);
- /* ------------------------------------------------------------------------
- * NO ERROR CHECK ON USING VALUE IN MASTER_LCP_REC. ERROR IN THIS REFERENCE
- * WILL CAUSE POINTER OUT OF RANGE WHICH CAUSES A SYSTEM RESTART.
- * ------------------------------------------------------------------------ */
- lcpLocptr.p->lcpLocstate = LcpLocRecord::SR_TUP_COMPLETED;
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (lcpLocptr.i == lcpPtr.p->firstLcpLocTup) {
- jam();
- fragptr.p->tupFragptr[1] = tupFragPtr;
- } else {
- jam();
- fragptr.p->tupFragptr[0] = tupFragPtr;
- }//if
- srCompletedLab(signal);
- return;
-}//Dblqh::execTUP_SRCONF()
-
-void Dblqh::srCompletedLab(Signal* signal)
-{
- checkSrCompleted(signal);
- if (lcpPtr.p->lcpState == LcpRecord::LCP_SR_COMPLETED) {
+ /**
+ * Disable expand check in ACC
+ * before running REDO
+ */
+ tabptr.i = fragptr.p->tabRef;
+ ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
+ for (Uint32 i = 0; i<MAX_FRAG_PER_NODE; i++)
+ {
+ if (tabptr.p->fragrec[i] != RNIL)
+ {
+ signal->theData[0] = tabptr.i;
+ signal->theData[1] = tabptr.p->fragid[i];
+ 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 == ZTRUE)
+ {
jam();
- /* ----------------------------------------------------------------------
- * THE SYSTEM RESTART OF THIS FRAGMENT HAS BEEN COMPLETED. IT IS NOW
- * TIME TO START A SYSTEM RESTART ON THE NEXT FRAGMENT OR CONTINUE
- * WITH THE NEXT STEP OF THE SYSTEM RESTART. THIS STEP IS TO EXECUTE
- * THE FRAGMENT LOGS.
- * ----------------------------------------------------------------------
- * WE RELEASE THE LOCAL LCP RECORDS.
- * --------------------------------------------------------------------- */
- releaseLocalLcps(signal);
- /* ----------------------------------------------------------------------
- * PUT FRAGMENT ON LIST OF FRAGMENTS WHICH HAVE BEEN STARTED AS PART OF
- * THE SYSTEM RESTART. THEY ARE NOW WAITING TO EXECUTE THE FRAGMENT LOG.
- * --------------------------------------------------------------------- */
- fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- fragptr.p->nextFrag = cfirstCompletedFragSr;
- cfirstCompletedFragSr = fragptr.i;
- if (cfirstWaitFragSr != RNIL) {
- jam();
- /* --------------------------------------------------------------------
- * ANOTHER FRAGMENT IS WAITING FOR SYSTEM RESTART. RESTART THIS
- * FRAGMENT AS WELL.
- * -------------------------------------------------------------------- */
- fragptr.i = cfirstWaitFragSr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- cfirstWaitFragSr = fragptr.p->nextFrag;
- /* --------------------------------------------------------------------
- * RETRIEVE DATA FROM THE FRAGMENT RECORD.
- * -------------------------------------------------------------------- */
- ndbrequire(fragptr.p->srChkpnr < MAX_LCP_STORED);
- initLcpSr(signal,
- fragptr.p->srChkpnr,
- fragptr.p->lcpId[fragptr.p->srChkpnr],
- fragptr.p->tabRef,
- fragptr.p->fragId,
- fragptr.i);
- signal->theData[0] = lcpPtr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = lcpPtr.p->currentFragment.lcpFragOrd.lcpNo;
- signal->theData[3] = lcpPtr.p->currentFragment.lcpFragOrd.tableId;
- signal->theData[4] = lcpPtr.p->currentFragment.lcpFragOrd.fragmentId;
- sendSignal(fragptr.p->accBlockref, GSN_SR_FRAGIDREQ, signal, 5, JBB);
- return;
- } else {
- jam();
- /* --------------------------------------------------------------------
- * NO MORE FRAGMENTS ARE WAITING FOR SYSTEM RESTART.
- * -------------------------------------------------------------------- */
- lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
- if (cstartRecReq == ZTRUE) {
- 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;
- signal->theData[0] = caccBlockref;
- signal->theData[1] = cownref;
- sendSignal(caccBlockref, GSN_START_RECREQ, signal, 2, JBB);
- signal->theData[0] = ctupBlockref;
- signal->theData[1] = cownref;
- sendSignal(ctupBlockref, GSN_START_RECREQ, signal, 2, JBB);
- return;
- } else {
- jam();
- /* ----------------------------------------------------------------
- * WE HAVE NOT RECEIVED ALL FRAGMENTS YET OR AT LEAST NOT WE
- * HAVE NOT RECEIVED THE START_RECREQ SIGNAL. EXIT AND WAIT
- * FOR MORE.
- * ---------------------------------------------------------------- */
- return;
- }//if
- }//if
- }//if
- /*---------------*/
- /* ELSE */
- /*-------------------------------------------------------------------------
- * THE SYSTEM RESTART ON THIS FRAGMENT HAS NOT BEEN COMPLETED,
- * EXIT AND WAIT FOR MORE SIGNALS
- *-------------------------------------------------------------------------
- * DO NOTHING, EXIT IS EXECUTED BELOW
- *------------------------------------------------------------------------- */
- return;
-}//Dblqh::srCompletedLab()
-
-/* ************> */
-/* TUP_SRREF > */
-/* ************> */
-void Dblqh::execTUP_SRREF(Signal* signal)
-{
- jamEntry();
- terrorCode = signal->theData[1];
- systemErrorLab(signal, __LINE__);
- return;
-}//Dblqh::execTUP_SRREF()
+ /* ----------------------------------------------------------------
+ * 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(TSMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
+ return;
+ }
+}
/* ***************> */
/* START_RECREQ > */
@@ -13773,35 +12867,19 @@ void Dblqh::execSTART_RECREQ(Signal* signal)
StartRecConf::SignalLength, JBB);
return;
}//if
- if (cfirstWaitFragSr == RNIL) {
- /* ----------------------------------------------------------------------
- * THERE ARE NO FRAGMENTS WAITING TO BE RESTARTED.
- * --------------------------------------------------------------------- */
+
+ if (c_lcp_restoring_fragments.isEmpty())
+ {
+ jam();
+ csrExecUndoLogState = EULS_STARTED;
+
lcpPtr.i = 0;
ptrAss(lcpPtr, lcpRecord);
- if (lcpPtr.p->lcpState == LcpRecord::LCP_IDLE) {
- jam();
- /* --------------------------------------------------------------------
- * THERE ARE NO FRAGMENTS THAT ARE CURRENTLY PERFORMING THEIR
- * SYSTEM RESTART.
- * --------------------------------------------------------------------
- * 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;
- signal->theData[0] = caccBlockref;
- signal->theData[1] = cownref;
- sendSignal(caccBlockref, GSN_START_RECREQ, signal, 2, JBB);
- signal->theData[0] = ctupBlockref;
- signal->theData[1] = cownref;
- sendSignal(ctupBlockref, GSN_START_RECREQ, signal, 2, JBB);
- }//if
+ lcpPtr.p->m_outstanding = 1;
+
+ signal->theData[0] = c_lcpId;
+ sendSignal(TSMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
}//if
- /* -----------------------------------------------------------------------
- * EXIT AND WAIT FOR COMPLETION OF ALL FRAGMENTS.
- * ----------------------------------------------------------------------- */
- return;
}//Dblqh::execSTART_RECREQ()
/* ***************>> */
@@ -13810,38 +12888,95 @@ void Dblqh::execSTART_RECREQ(Signal* signal)
void Dblqh::execSTART_RECCONF(Signal* signal)
{
jamEntry();
- BlockReference userRef = signal->theData[0];
- if (userRef == caccBlockref) {
- if (csrExecUndoLogState == EULS_STARTED) {
- jam();
- csrExecUndoLogState = EULS_ACC_COMPLETED;
- } else {
- ndbrequire(csrExecUndoLogState == EULS_TUP_COMPLETED);
- jam();
- csrExecUndoLogState = EULS_COMPLETED;
- /* --------------------------------------------------------------------
- * START THE FIRST PHASE OF EXECUTION OF THE LOG.
- * ------------------------------------------------------------------- */
- startExecSr(signal);
- }//if
- } else {
- ndbrequire(userRef == ctupBlockref);
- if (csrExecUndoLogState == EULS_STARTED) {
- jam();
- csrExecUndoLogState = EULS_TUP_COMPLETED;
- } else {
- ndbrequire(csrExecUndoLogState == EULS_ACC_COMPLETED);
- jam();
- csrExecUndoLogState = EULS_COMPLETED;
- /* --------------------------------------------------------------------
- * START THE FIRST PHASE OF EXECUTION OF THE LOG.
- * ------------------------------------------------------------------- */
- startExecSr(signal);
- }//if
- }//if
+ 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();
+ lcpPtr.p->m_outstanding++;
+ signal->theData[0] = c_lcpId;
+ sendSignal(LGMAN_REF, GSN_START_RECREQ, signal, 1, JBB);
+ return;
+ case LGMAN:
+ jam();
+ break;
+ default:
+ ndbrequire(false);
+ }
+
+ jam();
+ csrExecUndoLogState = EULS_COMPLETED;
+ c_lcp_complete_fragments.first(fragptr);
+ build_acc(signal, fragptr.i);
return;
}//Dblqh::execSTART_RECCONF()
+void
+Dblqh::build_acc(Signal* signal, Uint32 fragPtrI)
+{
+ fragptr.i = fragPtrI;
+ while(fragptr.i != RNIL)
+ {
+ c_lcp_complete_fragments.getPtr(fragptr);
+ tabptr.i = fragptr.p->tabRef;
+ ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
+
+ if(true || fragptr.i != tabptr.p->fragrec[0])
+ {
+ // Only need to send 1 build per table, TUP will rebuild all
+ fragptr.i = fragptr.p->nextList;
+ continue;
+ }
+
+ BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
+ req->setUserRef(reference());
+ req->setConnectionPtr(fragptr.i);
+ req->setRequestType(BuildIndxReq::RT_SYSTEMRESTART);
+ req->setBuildId(0); // not used
+ req->setBuildKey(0); // not used
+ req->setIndexType(RNIL);
+ req->setIndexId(RNIL);
+ req->setTableId(tabptr.i);
+ req->setParallelism(0);
+
+ sendSignal(DBTUP_REF, GSN_BUILDINDXREQ, signal,
+ BuildIndxReq::SignalLength, JBB);
+ return;
+ }
+
+ startExecSr(signal);
+}
+
+void
+Dblqh::execBUILDINDXREF(Signal* signal)
+{
+ ndbrequire(false);
+}
+
+void
+Dblqh::execBUILDINDXCONF(Signal* signal)
+{
+ BuildIndxConf* conf = (BuildIndxConf*)signal->getDataPtrSend();
+ Uint32 fragPtrI = conf->getConnectionPtr();
+
+ fragptr.i = fragPtrI;
+ c_fragment_pool.getPtr(fragptr);
+ infoEvent("LQH: primary key index %u rebuild done", fragptr.p->tabRef);
+ build_acc(signal, fragptr.p->nextList);
+}
+
/* ***************> */
/* START_RECREF > */
/* ***************> */
@@ -13856,10 +12991,10 @@ void Dblqh::execSTART_RECREF(Signal* signal)
/* ***************>> */
void Dblqh::execSTART_EXEC_SR(Signal* signal)
{
- FragrecordPtr prevFragptr;
jamEntry();
fragptr.i = signal->theData[0];
- prevFragptr.i = signal->theData[1];
+ Uint32 next = RNIL;
+
if (fragptr.i == RNIL) {
jam();
ndbrequire(cnoOfNodes < MAX_NDB_NODES);
@@ -13881,15 +13016,17 @@ void Dblqh::execSTART_EXEC_SR(Signal* signal)
sendSignal(ref, GSN_EXEC_SRREQ, signal, 1, JBB);
}//if
}//for
+ return;
} else {
jam();
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_lcp_complete_fragments.getPtr(fragptr);
if (fragptr.p->srNoLognodes > csrPhasesCompleted) {
jam();
Uint32 index = csrPhasesCompleted;
arrGuard(index, 4);
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
@@ -13902,9 +13039,10 @@ void Dblqh::execSTART_EXEC_SR(Signal* signal)
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);
- prevFragptr.i = fragptr.i;
- fragptr.i = fragptr.p->nextFrag;
+ sendSignal(ref, GSN_EXEC_FRAGREQ, signal,
+ ExecFragReq::SignalLength, JBB);
+
+ next = fragptr.p->nextList;
} else {
jam();
/* --------------------------------------------------------------------
@@ -13914,38 +13052,19 @@ void Dblqh::execSTART_EXEC_SR(Signal* signal)
* ALSO SEND START_FRAGCONF TO DIH AND SET THE STATE TO ACTIVE ON THE
* FRAGMENT.
* ------------------------------------------------------------------- */
- Uint32 next = fragptr.p->nextFrag;
- if (prevFragptr.i != RNIL) {
- jam();
- ptrCheckGuard(prevFragptr, cfragrecFileSize, fragrecord);
- prevFragptr.p->nextFrag = next;
- } else {
- jam();
- cfirstCompletedFragSr = next;
- }//if
-
- /**
- * Put fragment on list which has completed REDO log
- */
- fragptr.p->nextFrag = c_redo_log_complete_frags;
- c_redo_log_complete_frags = fragptr.i;
+ next = fragptr.p->nextList;
+ c_lcp_complete_fragments.remove(fragptr);
+ c_redo_complete_fragments.add(fragptr);
fragptr.p->fragStatus = Fragrecord::FSACTIVE;
fragptr.p->logFlag = Fragrecord::STATE_TRUE;
signal->theData[0] = fragptr.p->srUserptr;
signal->theData[1] = cownNodeid;
sendSignal(fragptr.p->srBlockref, GSN_START_FRAGCONF, signal, 2, JBB);
- /* --------------------------------------------------------------------
- * WE HAVE TO ENSURE THAT THIS FRAGMENT IS NOT PUT BACK ON THE LIST BY
- * MISTAKE. WE DO THIS BY ALSO REMOVING IT AS PREVIOUS IN START_EXEC_SR
- * THIS IS PERFORMED BY KEEPING PREV_FRAGPTR AS PREV_FRAGPTR BUT MOVING
- * FRAGPTR TO THE NEXT FRAGMENT IN THE LIST.
- * ------------------------------------------------------------------- */
- fragptr.i = next;
- }//if
- signal->theData[0] = fragptr.i;
- signal->theData[1] = prevFragptr.i;
- sendSignal(cownref, GSN_START_EXEC_SR, signal, 2, JBB);
+
+ } //if
+ signal->theData[0] = next;
+ sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
}//if
return;
}//Dblqh::execSTART_EXEC_SR()
@@ -14012,7 +13131,7 @@ void Dblqh::execEXEC_FRAGCONF(Signal* signal)
{
jamEntry();
fragptr.i = signal->theData[0];
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
fragptr.p->srStatus = Fragrecord::SS_COMPLETED;
return;
}//Dblqh::execEXEC_FRAGCONF()
@@ -14054,6 +13173,7 @@ void Dblqh::execEXEC_SRCONF(Signal* signal)
}//if
}//if
}//for
+
/* ------------------------------------------------------------------------
* CLEAR NODE SYSTEM RESTART EXECUTION STATE TO PREPARE FOR NEXT PHASE OF
* LOG EXECUTION.
@@ -14061,22 +13181,21 @@ void Dblqh::execEXEC_SRCONF(Signal* signal)
for (nodeId = 0; nodeId < MAX_NDB_NODES; nodeId++) {
cnodeExecSrState[nodeId] = ZSTART_SR;
}//for
+
/* ------------------------------------------------------------------------
* NOW CHECK IF ALL FRAGMENTS IN THIS PHASE HAVE COMPLETED. IF SO START THE
* NEXT PHASE.
* ----------------------------------------------------------------------- */
- fragptr.i = cfirstCompletedFragSr;
- if (fragptr.i == RNIL) {
- jam();
- execSrCompletedLab(signal);
- return;
- }//if
- do {
+ c_lcp_complete_fragments.first(fragptr);
+ while (fragptr.i != RNIL)
+ {
jam();
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- ndbrequire(fragptr.p->srStatus == Fragrecord::SS_COMPLETED);
- fragptr.i = fragptr.p->nextFrag;
- } while (fragptr.i != RNIL);
+ if(fragptr.p->srStatus != Fragrecord::SS_COMPLETED)
+ {
+ return;
+ }
+ c_lcp_complete_fragments.next(fragptr);
+ }
execSrCompletedLab(signal);
return;
}//Dblqh::execEXEC_SRCONF()
@@ -14257,8 +13376,9 @@ void Dblqh::srPhase3Start(Signal* signal)
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
} else {
jam();
+ c_lcp_complete_fragments.first(fragptr);
signal->theData[0] = ZSR_GCI_LIMITS;
- signal->theData[1] = 0;
+ signal->theData[1] = fragptr.i;
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
}//if
return;
@@ -14270,43 +13390,49 @@ void Dblqh::srPhase3Start(Signal* signal)
* ------------------------------------------------------------------------- */
void Dblqh::srGciLimits(Signal* signal)
{
- LogPartRecordPtr tmpLogPartPtr;
-
jamEntry();
fragptr.i = signal->theData[0];
Uint32 loopCount = 0;
logPartPtr.i = 0;
ptrAss(logPartPtr, logPartRecord);
- while (fragptr.i < cfragrecFileSize) {
+ while (fragptr.i != RNIL){
jam();
- ptrAss(fragptr, fragrecord);
- if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
+ c_lcp_complete_fragments.getPtr(fragptr);
+ ndbrequire(fragptr.p->execSrNoReplicas - 1 < 4);
+ for (Uint32 i = 0; i < fragptr.p->execSrNoReplicas; i++) {
jam();
- 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];
- }//if
- }//for
- }//if
+ 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.i + 1;
+ signal->theData[1] = fragptr.p->nextList;
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
return;
} else {
jam();
- fragptr.i++;
+ fragptr.i = fragptr.p->nextList;
}//if
- }//while
+ }
+
+ 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();
/* --------------------------------------------------------------------
@@ -14316,11 +13442,7 @@ void Dblqh::srGciLimits(Signal* signal)
* ------------------------------------------------------------------- */
logPartPtr.p->logStartGci = logPartPtr.p->logLastGci;
}//if
- for (tmpLogPartPtr.i = 1; tmpLogPartPtr.i < 4; tmpLogPartPtr.i++) {
- ptrAss(tmpLogPartPtr, logPartRecord);
- tmpLogPartPtr.p->logStartGci = logPartPtr.p->logStartGci;
- tmpLogPartPtr.p->logLastGci = logPartPtr.p->logLastGci;
- }//for
+
for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) {
jam();
ptrAss(logPartPtr, logPartRecord);
@@ -14968,7 +14090,7 @@ void Dblqh::execLogRecord(Signal* signal)
tcConnectptr.i = logPartPtr.p->logTcConrec;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
// Read a log record and prepare it for execution
readLogHeader(signal);
readKey(signal);
@@ -15220,8 +14342,9 @@ void Dblqh::execLogComp(Signal* signal)
* ----------------------------------------------------------------------- */
if (cstartType != NodeState::ST_NODE_RESTART) {
jam();
+ c_lcp_complete_fragments.first(fragptr);
signal->theData[0] = ZSEND_EXEC_CONF;
- signal->theData[1] = 0;
+ signal->theData[1] = fragptr.i;
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
} else {
jam();
@@ -15247,8 +14370,9 @@ void Dblqh::sendExecConf(Signal* signal)
jamEntry();
fragptr.i = signal->theData[0];
Uint32 loopCount = 0;
- while (fragptr.i < cfragrecFileSize) {
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ 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);
@@ -15267,6 +14391,7 @@ void Dblqh::sendExecConf(Signal* signal)
Uint32 fragId = fragptr.p->fragId;
tabptr.i = fragptr.p->tabRef;
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
+ c_lcp_complete_fragments.remove(fragptr);
deleteFragrec(fragId);
}//if
fragptr.p->execSrNoReplicas = 0;
@@ -15275,18 +14400,18 @@ void Dblqh::sendExecConf(Signal* signal)
if (loopCount > 20) {
jam();
signal->theData[0] = ZSEND_EXEC_CONF;
- signal->theData[1] = fragptr.i + 1;
+ signal->theData[1] = next;
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
return;
} else {
jam();
- fragptr.i++;
+ fragptr.i = next;
}//if
}//while
- /* ----------------------------------------------------------------------
- * WE HAVE NOW SENT ALL EXEC_FRAGCONF. NOW IT IS TIME TO SEND
- * EXEC_SRCONF TO ALL NODES.
- * --------------------------------------------------------------------- */
+ /* ----------------------------------------------------------------------
+ * WE HAVE NOW SENT ALL EXEC_FRAGCONF. NOW IT IS TIME TO SEND
+ * EXEC_SRCONF TO ALL NODES.
+ * --------------------------------------------------------------------- */
srPhase3Comp(signal);
}//Dblqh::sendExecConf()
@@ -15550,20 +14675,23 @@ void Dblqh::srFourthComp(Signal* signal)
} else if ((cstartType == NodeState::ST_NODE_RESTART) ||
(cstartType == NodeState::ST_SYSTEM_RESTART)) {
jam();
+
+
+
StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend();
conf->startingNodeId = getOwnNodeId();
sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal,
StartRecConf::SignalLength, JBB);
if(cstartType == NodeState::ST_SYSTEM_RESTART){
- fragptr.i = c_redo_log_complete_frags;
+ c_redo_complete_fragments.first(fragptr);
while(fragptr.i != RNIL){
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
signal->theData[0] = fragptr.p->tabRef;
signal->theData[1] = fragptr.p->fragId;
sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB);
- fragptr.i = fragptr.p->nextFrag;
+ c_redo_complete_fragments.next(fragptr);
}
+ c_redo_complete_fragments.remove();
}
} else {
ndbrequire(false);
@@ -15751,13 +14879,6 @@ void Dblqh::execMEMCHECKREQ(Signal* signal)
dataPtr[index]++;
}//while
index++;
- fragptr.i = cfirstfreeFragrec;
- while (fragptr.i != RNIL) {
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- fragptr.i = fragptr.p->nextFrag;
- dataPtr[index]++;
- }//while
- index++;
for (tabptr.i = 0;
tabptr.i < ctabrecFileSize;
tabptr.i++) {
@@ -15904,7 +15025,7 @@ void Dblqh::checkScanTcCompleted(Signal* signal)
{
tcConnectptr.p->logWriteState = TcConnectionrec::NOT_STARTED;
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
fragptr.p->activeTcCounter = fragptr.p->activeTcCounter - 1;
if (fragptr.p->activeTcCounter == 0) {
jam();
@@ -15922,44 +15043,19 @@ void Dblqh::checkScanTcCompleted(Signal* signal)
* ========================================================================= */
void Dblqh::checkSrCompleted(Signal* signal)
{
- LcpLocRecordPtr cscLcpLocptr;
-
terrorCode = ZOK;
ptrGuard(lcpPtr);
- cscLcpLocptr.i = lcpPtr.p->firstLcpLocAcc;
-CSC_ACC_DOWHILE:
- ptrCheckGuard(cscLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (cscLcpLocptr.p->lcpLocstate != LcpLocRecord::SR_ACC_COMPLETED) {
- jam();
- if (cscLcpLocptr.p->lcpLocstate != LcpLocRecord::SR_ACC_STARTED) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
+ if(lcpPtr.p->m_acc.lcpLocstate != LcpLocRecord::SR_ACC_COMPLETED)
+ {
+ ndbrequire(lcpPtr.p->m_acc.lcpLocstate == LcpLocRecord::SR_ACC_STARTED);
return;
- }//if
- cscLcpLocptr.i = cscLcpLocptr.p->nextLcpLoc;
- if (cscLcpLocptr.i != RNIL) {
- jam();
- goto CSC_ACC_DOWHILE;
- }//if
- cscLcpLocptr.i = lcpPtr.p->firstLcpLocTup;
-CSC_TUP_DOWHILE:
- ptrCheckGuard(cscLcpLocptr, clcpLocrecFileSize, lcpLocRecord);
- if (cscLcpLocptr.p->lcpLocstate != LcpLocRecord::SR_TUP_COMPLETED) {
- jam();
- if (cscLcpLocptr.p->lcpLocstate != LcpLocRecord::SR_TUP_STARTED) {
- jam();
- systemErrorLab(signal, __LINE__);
- return;
- }//if
+ }
+
+ if(lcpPtr.p->m_tup.lcpLocstate != LcpLocRecord::SR_TUP_COMPLETED)
+ {
+ ndbrequire(lcpPtr.p->m_tup.lcpLocstate == LcpLocRecord::SR_TUP_STARTED);
return;
- }//if
- cscLcpLocptr.i = cscLcpLocptr.p->nextLcpLoc;
- if (cscLcpLocptr.i != RNIL) {
- jam();
- goto CSC_TUP_DOWHILE;
- }//if
+ }
lcpPtr.p->lcpState = LcpRecord::LCP_SR_COMPLETED;
}//Dblqh::checkSrCompleted()
@@ -16103,7 +15199,7 @@ void Dblqh::deleteFragrec(Uint32 fragId)
{
Uint32 indexFound= RNIL;
fragptr.i = RNIL;
- for (Uint32 i = (MAX_FRAG_PER_NODE - 1); (Uint32)~i; i--) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
jam();
if (tabptr.p->fragid[i] == fragId) {
fragptr.i = tabptr.p->fragrec[i];
@@ -16113,10 +15209,11 @@ void Dblqh::deleteFragrec(Uint32 fragId)
}//for
if (fragptr.i != RNIL) {
jam();
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
tabptr.p->fragid[indexFound] = ZNIL;
tabptr.p->fragrec[indexFound] = RNIL;
- releaseFragrec();
+ fragptr.p->fragStatus = Fragrecord::FREE;
+ c_fragment_pool.release(fragptr);
}//if
}//Dblqh::deleteFragrec()
@@ -16211,11 +15308,11 @@ void Dblqh::getFirstInLogQueue(Signal* signal)
/* ---------------------------------------------------------------- */
bool Dblqh::getFragmentrec(Signal* signal, Uint32 fragId)
{
- for (Uint32 i = (MAX_FRAG_PER_NODE - 1); (UintR)~i; i--) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
jam();
if (tabptr.p->fragid[i] == fragId) {
fragptr.i = tabptr.p->fragrec[i];
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
return true;
}//if
}//for
@@ -16297,24 +15394,18 @@ void Dblqh::initialiseDatabuf(Signal* signal)
/* ========================================================================= */
void Dblqh::initialiseFragrec(Signal* signal)
{
- if (cfragrecFileSize != 0) {
- for (fragptr.i = 0; fragptr.i < cfragrecFileSize; fragptr.i++) {
- refresh_watch_dog();
- ptrAss(fragptr, fragrecord);
- fragptr.p->fragStatus = Fragrecord::FREE;
- fragptr.p->fragActiveStatus = ZFALSE;
- fragptr.p->execSrStatus = Fragrecord::IDLE;
- fragptr.p->srStatus = Fragrecord::SS_IDLE;
- fragptr.p->nextFrag = fragptr.i + 1;
- }//for
- fragptr.i = cfragrecFileSize - 1;
- ptrAss(fragptr, fragrecord);
- fragptr.p->nextFrag = RNIL;
- cfirstfreeFragrec = 0;
- } else {
- jam();
- cfirstfreeFragrec = RNIL;
- }//if
+
+ SLList<Fragrecord> tmp(c_fragment_pool);
+ while(tmp.seize(fragptr))
+ {
+ refresh_watch_dog();
+ new (fragptr.p) Fragrecord();
+ fragptr.p->fragStatus = Fragrecord::FREE;
+ fragptr.p->fragActiveStatus = ZFALSE;
+ fragptr.p->execSrStatus = Fragrecord::IDLE;
+ fragptr.p->srStatus = Fragrecord::SS_IDLE;
+ }
+ tmp.release();
}//Dblqh::initialiseFragrec()
/* ========================================================================= */
@@ -16347,39 +15438,14 @@ void Dblqh::initialiseLcpRec(Signal* signal)
ptrAss(lcpPtr, lcpRecord);
lcpPtr.p->lcpState = LcpRecord::LCP_IDLE;
lcpPtr.p->lcpQueued = false;
- lcpPtr.p->firstLcpLocAcc = RNIL;
- lcpPtr.p->firstLcpLocTup = RNIL;
lcpPtr.p->reportEmpty = false;
+ lcpPtr.p->firstFragmentFlag = false;
lcpPtr.p->lastFragmentFlag = false;
}//for
}//if
}//Dblqh::initialiseLcpRec()
/* ========================================================================= */
-/* ====== INITIATE LCP LOCAL RECORD ======= */
-/* */
-/* ========================================================================= */
-void Dblqh::initialiseLcpLocrec(Signal* signal)
-{
- if (clcpLocrecFileSize != 0) {
- for (lcpLocptr.i = 0; lcpLocptr.i < clcpLocrecFileSize; lcpLocptr.i++) {
- ptrAss(lcpLocptr, lcpLocRecord);
- lcpLocptr.p->nextLcpLoc = lcpLocptr.i + 1;
- lcpLocptr.p->lcpLocstate = LcpLocRecord::IDLE;
- lcpLocptr.p->masterLcpRec = RNIL;
- lcpLocptr.p->waitingBlock = LcpLocRecord::NONE;
- }//for
- lcpLocptr.i = clcpLocrecFileSize - 1;
- ptrAss(lcpLocptr, lcpLocRecord);
- lcpLocptr.p->nextLcpLoc = RNIL;
- cfirstfreeLcpLoc = 0;
- } else {
- jam();
- cfirstfreeLcpLoc = RNIL;
- }//if
-}//Dblqh::initialiseLcpLocrec()
-
-/* ========================================================================= */
/* ====== INITIATE LOG FILE OPERATION RECORD ======= */
/* */
/* ========================================================================= */
@@ -16517,8 +15583,6 @@ void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data,
cnewestCompletedGci = (UintR)-1;
crestartOldestGci = 0;
crestartNewestGci = 0;
- cfirstWaitFragSr = RNIL;
- cfirstCompletedFragSr = RNIL;
csrPhaseStarted = ZSR_NO_PHASE_STARTED;
csrPhasesCompleted = 0;
cmasterDihBlockref = 0;
@@ -16548,7 +15612,6 @@ void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data,
jam();
initialiseGcprec(signal);
initialiseLcpRec(signal);
- initialiseLcpLocrec(signal);
break;
case 6:
jam();
@@ -16637,7 +15700,7 @@ void Dblqh::initialiseTabrec(Signal* signal)
ptrAss(tabptr, tablerec);
tabptr.p->tableStatus = Tablerec::NOT_DEFINED;
tabptr.p->usageCount = 0;
- for (Uint32 i = 0; i <= (MAX_FRAG_PER_NODE - 1); i++) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
tabptr.p->fragid[i] = ZNIL;
tabptr.p->fragrec[i] = RNIL;
}//for
@@ -16706,15 +15769,12 @@ void Dblqh::initFragrec(Signal* signal,
new (fragptr.p) Fragrecord();
fragptr.p->m_scanNumberMask.set(); // All is free
fragptr.p->accBlockref = caccBlockref;
- fragptr.p->accBlockedList = RNIL;
- fragptr.p->activeList = RNIL;
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->lcpRef = RNIL;
fragptr.p->logFlag = Fragrecord::STATE_TRUE;
fragptr.p->lcpFlag = Fragrecord::LCP_STATE_TRUE;
for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
@@ -16723,7 +15783,6 @@ void Dblqh::initFragrec(Signal* signal,
fragptr.p->maxGciCompletedInLcp = 0;
fragptr.p->maxGciInLcp = 0;
fragptr.p->copyFragState = ZIDLE;
- fragptr.p->nextFrag = RNIL;
fragptr.p->newestGci = cnewestGci;
fragptr.p->nextLcp = 0;
fragptr.p->tabRef = tableId;
@@ -16741,45 +15800,6 @@ void Dblqh::initFragrec(Signal* signal,
*
* SUBROUTINE SHORT NAME = IFS
* ========================================================================= */
-void Dblqh::initFragrecSr(Signal* signal)
-{
- const StartFragReq * const startFragReq = (StartFragReq *)&signal->theData[0];
- Uint32 lcpNo = startFragReq->lcpNo;
- Uint32 noOfLogNodes = startFragReq->noOfLogNodes;
- 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] = startFragReq->lcpId;
- fragptr.p->nextLcp = 0;
- } else if (lcpNo < (MAX_LCP_STORED - 1)) {
- jam();
- fragptr.p->lcpId[lcpNo] = startFragReq->lcpId;
- fragptr.p->nextLcp = lcpNo + 1;
- } else {
- ndbrequire(lcpNo == ZNIL);
- jam();
- fragptr.p->nextLcp = 0;
- }//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
-}//Dblqh::initFragrecSr()
/* ==========================================================================
* ======= INITIATE INFORMATION ABOUT GLOBAL CHECKPOINTS =======
@@ -16849,9 +15869,6 @@ void Dblqh::initLcpSr(Signal* signal,
lcpPtr.p->currentFragment.lcpFragOrd.tableId = tableId;
lcpPtr.p->currentFragment.lcpFragOrd.fragmentId = fragId;
lcpPtr.p->lcpState = LcpRecord::LCP_SR_WAIT_FRAGID;
- lcpPtr.p->firstLcpLocAcc = RNIL;
- lcpPtr.p->firstLcpLocTup = RNIL;
- lcpPtr.p->lcpAccptr = RNIL;
}//Dblqh::initLcpSr()
/* ==========================================================================
@@ -16953,13 +15970,12 @@ void Dblqh::initReqinfoExecSr(Signal* signal)
bool Dblqh::insertFragrec(Signal* signal, Uint32 fragId)
{
terrorCode = ZOK;
- if (cfirstfreeFragrec == RNIL) {
- jam();
+ if(c_fragment_pool.seize(fragptr) == false)
+ {
terrorCode = ZNO_FREE_FRAGMENTREC;
return false;
- }//if
- seizeFragmentrec(signal);
- for (Uint32 i = (MAX_FRAG_PER_NODE - 1); (Uint32)~i; i--) {
+ }
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
jam();
if (tabptr.p->fragid[i] == ZNIL) {
jam();
@@ -16968,6 +15984,7 @@ bool Dblqh::insertFragrec(Signal* signal, Uint32 fragId)
return true;
}//if
}//for
+ c_fragment_pool.release(fragptr);
terrorCode = ZTOO_MANY_FRAGMENTS;
return false;
}//Dblqh::insertFragrec()
@@ -17502,44 +16519,6 @@ void Dblqh::readSinglePage(Signal* signal, Uint32 pageNo)
sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
}//Dblqh::readSinglePage()
-/* --------------------------------------------------------------------------
- * ------- RELEASE OPERATION FROM ACTIVE LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME = RAC
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseAccList(Signal* signal)
-{
- TcConnectionrecPtr racTcNextConnectptr;
- TcConnectionrecPtr racTcPrevConnectptr;
-
- fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- racTcPrevConnectptr.i = tcConnectptr.p->prevTc;
- racTcNextConnectptr.i = tcConnectptr.p->nextTc;
- if (tcConnectptr.p->listState != TcConnectionrec::ACC_BLOCK_LIST) {
- jam();
- systemError(signal, __LINE__);
- }//if
- tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
- if (racTcNextConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(racTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- racTcNextConnectptr.p->prevTc = racTcPrevConnectptr.i;
- }//if
- if (racTcPrevConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(racTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- racTcPrevConnectptr.p->nextTc = tcConnectptr.p->nextTc;
- } else {
- jam();
- /* ---------------------------------------------------------------------
- * OPERATION RECORD IS FIRST IN ACTIVE LIST
- * THIS MEANS THAT THERE EXISTS NO PREVIOUS TC THAT NEEDS TO BE UPDATED.
- * --------------------------------------------------------------------- */
- fragptr.p->accBlockedList = racTcNextConnectptr.i;
- }//if
-}//Dblqh::releaseAccList()
-
/* --------------------------------------------------------------------------
* ------- REMOVE COPY FRAGMENT FROM ACTIVE COPY LIST -------
*
@@ -17572,37 +16551,6 @@ void Dblqh::releaseActiveCopy(Signal* signal)
cnoActiveCopy--;
}//Dblqh::releaseActiveCopy()
-/* --------------------------------------------------------------------------
- * ------- RELEASE OPERATION FROM ACTIVE LIST ON FRAGMENT -------
- *
- * SUBROUTINE SHORT NAME = RAL
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseActiveList(Signal* signal)
-{
- TcConnectionrecPtr ralTcNextConnectptr;
- TcConnectionrecPtr ralTcPrevConnectptr;
- ralTcPrevConnectptr.i = tcConnectptr.p->prevTc;
- ralTcNextConnectptr.i = tcConnectptr.p->nextTc;
- ndbrequire(tcConnectptr.p->listState == TcConnectionrec::IN_ACTIVE_LIST);
- tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
- if (ralTcNextConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(ralTcNextConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- ralTcNextConnectptr.p->prevTc = ralTcPrevConnectptr.i;
- }//if
- if (ralTcPrevConnectptr.i != RNIL) {
- jam();
- ptrCheckGuard(ralTcPrevConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- ralTcPrevConnectptr.p->nextTc = tcConnectptr.p->nextTc;
- } else {
- jam();
- /* ----------------------------------------------------------------------
- * OPERATION RECORD IS FIRST IN ACTIVE LIST
- * THIS MEANS THAT THERE EXISTS NO PREVIOUS TC THAT NEEDS TO BE UPDATED.
- * --------------------------------------------------------------------- */
- fragptr.p->activeList = ralTcNextConnectptr.i;
- }//if
-}//Dblqh::releaseActiveList()
/* --------------------------------------------------------------------------
* ------- RELEASE ADD FRAGMENT RECORD -------
@@ -17616,28 +16564,6 @@ void Dblqh::releaseAddfragrec(Signal* signal)
}//Dblqh::releaseAddfragrec()
/* --------------------------------------------------------------------------
- * ------- RELEASE FRAGMENT RECORD -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseFragrec()
-{
- fragptr.p->fragStatus = Fragrecord::FREE;
- fragptr.p->nextFrag = cfirstfreeFragrec;
- cfirstfreeFragrec = fragptr.i;
-}//Dblqh::releaseFragrec()
-
-/* --------------------------------------------------------------------------
- * ------- RELEASE LCP LOCAL RECORD -------
- *
- * ------------------------------------------------------------------------- */
-void Dblqh::releaseLcpLoc(Signal* signal)
-{
- lcpLocptr.p->lcpLocstate = LcpLocRecord::IDLE;
- lcpLocptr.p->nextLcpLoc = cfirstfreeLcpLoc;
- cfirstfreeLcpLoc = lcpLocptr.i;
-}//Dblqh::releaseLcpLoc()
-
-/* --------------------------------------------------------------------------
* ------- RELEASE A PAGE REFERENCE RECORD. -------
*
* ------------------------------------------------------------------------- */
@@ -17692,7 +16618,7 @@ void Dblqh::releaseWaitQueue(Signal* signal)
TcConnectionrecPtr rwaTcPrevConnectptr;
fragptr.i = tcConnectptr.p->fragmentptr;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ c_fragment_pool.getPtr(fragptr);
rwaTcPrevConnectptr.i = tcConnectptr.p->prevTc;
rwaTcNextConnectptr.i = tcConnectptr.p->nextTc;
if (tcConnectptr.p->listState != TcConnectionrec::WAIT_QUEUE_LIST) {
@@ -17846,14 +16772,6 @@ void Dblqh::seizeAddfragrec(Signal* signal)
* ------- SEIZE FRAGMENT RECORD -------
*
* ------------------------------------------------------------------------- */
-void Dblqh::seizeFragmentrec(Signal* signal)
-{
- fragptr.i = cfirstfreeFragrec;
- ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- cfirstfreeFragrec = fragptr.p->nextFrag;
- fragptr.p->nextFrag = RNIL;
-}//Dblqh::seizeFragmentrec()
-
/* ------------------------------------------------------------------------- */
/* ------- SEIZE A PAGE REFERENCE RECORD. ------- */
/* */
@@ -17936,9 +16854,9 @@ void Dblqh::sendLqhTransconf(Signal* signal, LqhTransConf::OperationStatus stat)
void Dblqh::startExecSr(Signal* signal)
{
cnoFragmentsExecSr = 0;
- signal->theData[0] = cfirstCompletedFragSr;
- signal->theData[1] = RNIL;
- sendSignal(cownref, GSN_START_EXEC_SR, signal, 2, JBB);
+ c_lcp_complete_fragments.first(fragptr);
+ signal->theData[0] = fragptr.i;
+ sendSignal(cownref, GSN_START_EXEC_SR, signal, 1, JBB);
}//Dblqh::startExecSr()
/* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
@@ -18297,7 +17215,9 @@ void Dblqh::writeNextLog(Signal* signal)
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(),
@@ -18451,12 +17371,9 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
// Print information about the current local checkpoint
TlcpPtr.i = 0;
ptrAss(TlcpPtr, lcpRecord);
- infoEvent(" lcpState=%d firstLcpLocTup=%d firstLcpLocAcc=%d",
- TlcpPtr.p->lcpState,
- TlcpPtr.p->firstLcpLocTup,
- TlcpPtr.p->firstLcpLocAcc);
+ infoEvent(" lcpState=%d", TlcpPtr.p->lcpState);
infoEvent(" lcpAccptr=%d lastFragmentFlag=%d",
- TlcpPtr.p->lcpAccptr,
+ TlcpPtr.p->m_acc.lcpRef,
TlcpPtr.p->lastFragmentFlag);
infoEvent("currentFragment.fragPtrI=%d",
TlcpPtr.p->currentFragment.fragPtrI);
@@ -18472,7 +17389,187 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
return;
}
- Uint32 arg= dumpState->args[0];
+ 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
+ << " simpleRead = " << tcRec.p->simpleRead
+ << 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
+ << 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]
+ << 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
+ << " scanLocalFragid="<<TscanPtr.p->scanLocalFragid
+ << 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
+#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();
@@ -18639,6 +17736,57 @@ Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){
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)
{
diff --git a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index 958404108e8..1270e56de56 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -879,7 +879,7 @@ public:
Uint8 distributionKeyIndicator;
Uint8 m_special_hash; // collation or distribution key
- Uint8 unused2;
+ Uint8 m_no_disk_flag;
Uint8 lenAiInTckeyreq; /* LENGTH OF ATTRIBUTE INFORMATION IN TCKEYREQ */
Uint8 fragmentDistributionKey; /* DIH generation no */
@@ -968,7 +968,8 @@ public:
Uint8 noOfKeyAttr;
Uint8 hasCharAttr;
Uint8 noOfDistrKeys;
-
+ Uint8 hasVarKeys;
+
bool checkTable(Uint32 schemaVersion) const {
return enabled && !dropping &&
(table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
index 31f73e98142..5c2df9d7a78 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
@@ -41,18 +41,6 @@ void Dbtc::initData()
clqhblockref = DBLQH_REF;
cerrorBlockref = NDBCNTR_REF;
- 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;
// Records with constant sizes
tcFailRecord = (TcFailRecord*)allocRecord("TcFailRecord",
sizeof(TcFailRecord), 1);
@@ -320,6 +308,18 @@ Dbtc::Dbtc(const class Configuration & conf):
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()
diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 91fc8780fae..79c0d9ede62 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -340,7 +340,7 @@ void Dbtc::execTC_SCHVERREQ(Signal* signal)
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);
@@ -2302,14 +2302,15 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen,
{
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 hasDistKeys = tabPtrP->noOfDistrKeys > 0;
+ 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)
+ if(hasCharAttr || (compute_distkey && hasVarKeys))
{
keyPartLenPtr = keyPartLen;
dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr);
@@ -2324,7 +2325,7 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen,
md5_hash(dstHash, (Uint64*)dst, dstPos);
- if(distr && hasDistKeys)
+ if(compute_distkey)
{
jam();
@@ -2728,12 +2729,14 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TDirtyFlag = tcKeyReq->getDirtyFlag(Treqinfo);
Uint8 TInterpretedFlag = tcKeyReq->getInterpretedFlag(Treqinfo);
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
+ Uint8 TNoDiskFlag = TcKeyReq::getNoDiskFlag(Treqinfo);
Uint8 TexecuteFlag = TexecFlag;
regCachePtr->opSimple = TSimpleFlag;
regCachePtr->opExec = TInterpretedFlag;
regTcPtr->dirtyOp = TDirtyFlag;
regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
+ regCachePtr->m_no_disk_flag = TNoDiskFlag;
//-------------------------------------------------------------
// The next step is to read the upto three conditional words.
@@ -3198,6 +3201,8 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
LqhKeyReq::setSimpleFlag(Tdata10, regCachePtr->opSimple);
LqhKeyReq::setOperation(Tdata10, regTcPtr->operation);
+ LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
+
/* -----------------------------------------------------------------------
* Sequential Number of first LQH = 0, bit 22-23
* IF ATTRIBUTE INFORMATION IS SENT IN TCKEYREQ,
@@ -8763,6 +8768,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
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;
@@ -10120,6 +10126,7 @@ void Dbtc::initTable(Signal* signal)
tabptr.p->noOfKeyAttr = 0;
tabptr.p->hasCharAttr = 0;
tabptr.p->noOfDistrKeys = 0;
+ tabptr.p->hasVarKeys = 0;
}//for
}//Dbtc::initTable()
@@ -11154,7 +11161,6 @@ void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
ApiConnectRecordPtr transPtr;
TcConnectRecord *localTcConnectRecord = tcConnectRecord;
TcConnectRecordPtr opPtr;
-
/**
* TODO
* Check transid,
diff --git a/storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp b/storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp
index 2c62adab3e5..89b11e20760 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp
@@ -31,7 +31,10 @@ private:
static Uint32 getNullFlagPos(const Uint32 &);
static Uint32 getNullFlagOffset(const Uint32 &);
static Uint32 getNullFlagBitOffset(const Uint32 &);
- static bool isNULL(const Uint32 &, const Uint32 &);
+
+ Uint32 m_data;
+
+ friend class NdbOut& operator<<(class NdbOut&, const AttributeOffset&);
};
/**
@@ -66,6 +69,7 @@ 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);
}
@@ -126,11 +130,7 @@ AttributeOffset::getNullFlagBitOffset(const Uint32 & desc)
return (getNullFlagPos(desc) & AO_NULL_FLAG_WORD_MASK);
}
-inline
-bool
-AttributeOffset::isNULL(const Uint32 & pageWord, const Uint32 & desc)
-{
- return (((pageWord >> getNullFlagBitOffset(desc)) & 1) == 1);
-}
+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
index bf07a39f00d..ebb3cc98de0 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -29,11 +29,27 @@
#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>
#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
//------------------------------------------------------------------
@@ -53,18 +69,16 @@
// DbtupFixAlloc.cpp 6000
// DbtupTrigger.cpp 7000
// DbtupAbort.cpp 9000
-// DbtupLCP.cpp 10000
-// DbtupUndoLog.cpp 12000
// DbtupPageMap.cpp 14000
// DbtupPagMan.cpp 16000
// DbtupStoredProcDef.cpp 18000
// DbtupMeta.cpp 20000
// DbtupTabDesMan.cpp 22000
// DbtupGen.cpp 24000
-// DbtupSystemRestart.cpp 26000
// DbtupIndex.cpp 28000
// DbtupDebug.cpp 30000
-// DbtupScan.cpp 32000
+// DbtupVarAlloc.cpp 32000
+// DbtupScan.cpp 33000
//------------------------------------------------------------------
/*
@@ -78,37 +92,13 @@
#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 ZNO_OF_LCP_REC 10 /* NUMBER OF CONCURRENT CHECKPOINTS*/
#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 */
-#define ZNO_OF_PARALLELL_UNDO_FILES 16 /* NUMBER OF PARALLEL UNDO FILES */
-#define ZNO_OF_RESTART_INFO_REC 10 /* MAXIMUM PARALLELL RESTART INFOS */
- /* 24 SEGMENTS WITH 8 PAGES IN EACH*/
- /* PLUS ONE UNDO BUFFER CACHE */
-// Undo record identifiers are 32-bits with page index 13-bits
-#define ZUNDO_RECORD_ID_PAGE_INDEX 13 /* 13 BITS = 8192 WORDS/PAGE */
-#define ZUNDO_RECORD_ID_PAGE_INDEX_MASK (ZWORDS_ON_PAGE - 1) /* 1111111111111 */
-
// Trigger constants
#define ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE 16
/* ---------------------------------------------------------------- */
-// VARIABLE NUMBERS OF PAGE_WORD, UNDO_WORD AND LOGIC_WORD FOR
-// COMMUNICATION WITH FILE SYSTEM
-/* ---------------------------------------------------------------- */
-#define ZBASE_ADDR_PAGE_WORD 1 /* BASE ADDRESS OF PAGE_WORD VAR */
-#define ZBASE_ADDR_UNDO_WORD 2 /* BASE ADDRESS OF UNDO_WORD VAR */
-#define ZBASE_ADDR_LOGIC_WORD 3 /* BASE ADDRESS OF LOGIC_WORD VAR */
-
-/* ---------------------------------------------------------------- */
-// NUMBER OF PAGES SENT TO DISK IN DATA BUFFER AND UNDO BUFFER WHEN
-// OPTIMUM PERFORMANCE IS ACHIEVED.
-/* ---------------------------------------------------------------- */
-#define ZUB_SEGMENT_SIZE 8 /* SEGMENT SIZE OF UNDO BUFFER */
-#define ZDB_SEGMENT_SIZE 8 /* SEGMENT SIZE OF DATA BUFFER */
-
-/* ---------------------------------------------------------------- */
/* 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 */
@@ -117,12 +107,11 @@
/**
* #defines moved into include/kernel/Interpreter.hpp
*/
-#define ZMAX_REGISTER 21
#define ZINSERT_DELETE 0
+#define ZUPDATE_ALL 8
/* ---------------------------------------------------------------- */
/* THE MINIMUM SIZE OF AN 'EMPTY' TUPLE HEADER IN R-WORDS */
/* ---------------------------------------------------------------- */
-#define ZTUP_HEAD_MINIMUM_SIZE 2
/* 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 */
@@ -134,31 +123,10 @@
/* TUPLE ATTRIBUTE INDEX CLUSTERS, ATTRIBUTE */
/* CLUSTERS AND A DYNAMIC ATTRIBUTE HEADER. */
-#define ZTH_TYPE3 2 /* TUPLE HEADER THAT MAY HAVE A POINTER TO */
- /* A DYNAMIC ATTRIBUTE HEADER. IT MAY ALSO */
- /* CONTAIN SHORT ATTRIBUTES AND POINTERS */
- /* TO LONG ATTRIBUTE HEADERS. */
-
/* 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. */
-#define ZFIXED_ARRAY 2 /* ZFIXED ARRAY FIELD. */
-#define ZNON_ARRAY 1 /* NORMAL FIELD. */
-#define ZVAR_ARRAY 0 /* VARIABLE ARRAY FIELD */
-#define ZNOT_STORE 3 /* THE ATTR IS STORED IN THE INDEX BLOCK */
-#define ZMAX_SMALL_VAR_ARRAY 256
-
- /* PLEASE OBSERVE THAT THEESE CONSTANTS CORRESPONDS TO THE NUMBER */
- /* OF BITS NEEDED TO REPRESENT THEM D O N O T C H A N G E */
-#define Z1BIT_VAR 0 /* 1 BIT VARIABLE. */
-#define Z2BIT_VAR 1 /* 2 BIT VARIABLE. */
-#define Z4BIT_VAR 2 /* 4 BIT VARIABLE. */
-#define Z8BIT_VAR 3 /* 8 BIT VARIABLE. */
-#define Z16BIT_VAR 4 /* 16 BIT VARIABLE. */
-#define Z32BIT_VAR 5 /* 32 BIT VARIABLE. */
-#define Z64BIT_VAR 6 /* 64 BIT VARIABLE. */
-#define Z128BIT_VAR 7 /* 128 BIT VARIABLE. */
/* 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 */
@@ -212,37 +180,12 @@
/* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */
-#define ZPAGE_STATE_POS 0 /* POSITION OF PAGE STATE */
-#define ZPAGE_NEXT_POS 1 /* POSITION OF THE NEXT POINTER WHEN IN FREELIST */
-#define ZPAGE_PREV_POS 2 /* POSITION OF THE PREVIOUS POINTER WHEN IN FREELIST */
-#define ZFREELIST_HEADER_POS 3 /* POSITION OF THE FIRST FREELIST */
-#define ZPAGE_FRAG_PAGE_ID_POS 4 /* POSITION OF FRAG PAGE ID WHEN USED*/
-#define ZPAGE_NEXT_CLUST_POS 5 /* POSITION OF NEXT FREE SET OF PAGES */
-#define ZPAGE_FIRST_CLUST_POS 2 /* POSITION OF THE POINTER TO THE FIRST PAGE IN A CLUSTER */
-#define ZPAGE_LAST_CLUST_POS 6 /* POSITION OF THE POINTER TO THE LAST PAGE IN A CLUSTER */
-#define ZPAGE_PREV_CLUST_POS 7 /* POSITION OF THE PREVIOUS POINTER */
-#define ZPAGE_HEADER_SIZE 32 /* NUMBER OF WORDS IN MEM PAGEHEADER */
-#define ZDISK_PAGE_HEADER_SIZE 32 /* NUMBER OF WORDS IN DISK PAGEHEADER */
-#define ZNO_OF_FREE_BLOCKS 3 /* NO OF FREE BLOCK IN THE DISK PAGE */
-#define ZDISK_PAGE_ID 8 /* ID OF THE PAGE ON THE DISK */
-#define ZBLOCK_LIST 9
-#define ZCOPY_OF_PAGE 10
-#define ZPAGE_PHYSICAL_INDEX 11
-#define ZNEXT_IN_PAGE_USED_LIST 12
-#define ZPREV_IN_PAGE_USED_LIST 13
-#define ZDISK_USED_TYPE 14
+
#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 ZAC_MM_FREE 5 /* PAGE STATE, ATTRIBUTE CLUSTER PAGE WITH FREE AREA */
-#define ZTH_MM_FREE_COPY 7 /* PAGE STATE, TH COPY PAGE WITH FREE AREA */
-#define ZTH_MM_FULL_COPY 8 /* PAGE STATE, TH COPY PAGE WHICH IS FULL */
-#define ZAC_MM_FREE_COPY 9 /* PAGE STATE, AC COPY PAGE WITH FREE AREA */
-#define ZMAX_NO_COPY_PAGES 4 /* THE MAXIMUM NUMBER OF COPY PAGES ALLOWED PER FRAGMENT */
-
- /* CONSTANTS USED TO HANDLE TABLE DESCRIPTOR RECORDS */
- /* ALL POSITIONS AND SIZES IS BASED ON R-WORDS (32-BIT ON APZ 212) */
+
#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 */
@@ -285,143 +228,81 @@
#define ZADDFRAG 0
- /* CHECKPOINT RECORD TYPES */
-#define ZLCPR_TYPE_INSERT_TH 0 /* INSERT TUPLE HEADER */
-#define ZLCPR_TYPE_DELETE_TH 1 /* DELETE TUPLE HEADER */
-#define ZLCPR_TYPE_UPDATE_TH 2 /* DON'T CREATE IT, JUST UPDETE */
-#define ZLCPR_TYPE_INSERT_TH_NO_DATA 3 /* INSERT TUPLE HEADER */
-#define ZLCPR_ABORT_UPDATE 4 /* UNDO AN UPDATE OPERATION THAT WAS ACTIVE IN LCP */
-#define ZLCPR_ABORT_INSERT 5 /* UNDO AN INSERT OPERATION THAT WAS ACTIVE IN LCP */
-#define ZTABLE_DESCRIPTOR 6 /* TABLE DESCRIPTOR */
-#define ZINDICATE_NO_OP_ACTIVE 7 /* ENSURE THAT NO OPERATION ACTIVE AFTER RESTART */
-#define ZLCPR_UNDO_LOG_PAGE_HEADER 8 /* CHANGE IN PAGE HEADER IS UNDO LOGGED */
-#define ZLCPR_TYPE_UPDATE_GCI 9 /* Update GCI at commit time */
-#define ZNO_CHECKPOINT_RECORDS 10 /* NUMBER OF CHECKPOINTRECORD TYPES */
-
- /* RESULT CODES */
- /* ELEMENT POSITIONS IN SYSTEM RESTART INFO PAGE OF THE DATA FILE */
-#define ZSRI_NO_OF_FRAG_PAGES_POS 10 /* NUMBER OF FRAGMENT PAGES WHEN CHECKPOINT STARTED */
-#define ZSRI_TUP_RESERVED_SIZE_POS 11 /* RESERVED SIZE OF THE TUPLE WHEN CP STARTED */
-#define ZSRI_TUP_FIXED_AREA_POS 12 /* SIZE OF THE TUPLE FIXED AREA WHEN CP STARTED */
-#define ZSRI_TAB_DESCR_SIZE 13 /* SIZE OF THE TABLE DESCRIPTOR WHEN CP STARTED */
-#define ZSRI_NO_OF_ATTRIBUTES_POS 14 /* NUMBER OF ATTRIBUTES */
-#define ZSRI_UNDO_LOG_END_REC_ID 15 /* LAST UNDO LOG RECORD ID FOR THIS CHECKPOINT */
-#define ZSRI_UNDO_LOG_END_PAGE_ID 16 /* LAST USED LOG PAGE ID FOR THIS CHECKPOINT */
-#define ZSRI_TH_FREE_FIRST 17 /* FIRST FREE PAGE OF TUPLE HEADERS */
-#define ZSRI_TH_FREE_COPY_FIRST 18 /* FIRST FREE PAGE OF TUPLE HEADER COPIES */
-#define ZSRI_EMPTY_PRIM_PAGE 27 /* FIRST EMPTY PAGE */
-#define ZSRI_NO_COPY_PAGES_ALLOC 28 /* NO COPY PAGES IN FRAGMENT AT LOCAL CHECKPOINT */
-#define ZSRI_UNDO_FILE_VER 29 /* CHECK POINT ID OF THE UNDO FILE */
-#define ZSRI_NO_OF_INDEX_ATTR 30 /* No of index attributes */
-#define ZNO_OF_PAGES_CLUSTER_REC 0
-
//------------------------------------------------------------
// TUP_CONTINUEB codes
//------------------------------------------------------------
-#define ZSTART_EXEC_UNDO_LOG 0
-#define ZCONT_START_SAVE_CL 1
-#define ZCONT_SAVE_DP 2
-#define ZCONT_EXECUTE_LC 3
-#define ZCONT_LOAD_DP 4
-#define ZLOAD_BAL_LCP_TIMER 5
#define ZINITIALISE_RECORDS 6
#define ZREL_FRAG 7
#define ZREPORT_MEMORY_USAGE 8
#define ZBUILD_INDEX 9
+#define ZFREE_EXTENT 10
+#define ZUNMAP_PAGES 11
-#define ZINDEX_STORAGE 0
-#define ZDATA_WORD_AT_DISK_PAGE 2030
-#define ZALLOC_DISK_PAGE_LAST_INDEX 2047
-#define ZWORD_IN_BLOCK 127 /* NO OF WORD IN A BLOCK */
-#define ZNO_DISK_PAGES_FILE_REC 100
-#define ZMASK_PAGE_INDEX 0x7ff
-#define ZBIT_PAGE_INDEX 11 /* 8 KBYT PAGE = 2048 WORDS */
#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 ZUNDO_PAGE_HEADER_SIZE 2 /* SIZE OF UNDO PAGE HEADER */
+
#endif
class Dbtup: public SimulatedBlock {
- friend class Suma;
+friend class Suma;
public:
-
- typedef bool (Dbtup::* ReadFunction)(Uint32*,
- AttributeHeader*,
- Uint32,
+struct KeyReqStruct;
+typedef bool (Dbtup::* ReadFunction)(Uint32*,
+ KeyReqStruct*,
+ AttributeHeader*,
+ Uint32);
+typedef bool (Dbtup::* UpdateFunction)(Uint32*,
+ KeyReqStruct*,
Uint32);
- typedef bool (Dbtup::* UpdateFunction)(Uint32*,
- Uint32,
- 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_INITIAL_INSERT = 0,
+ TUPLE_PREPARED = 1,
+ TUPLE_ALREADY_ABORTED = 2,
+ TUPLE_TO_BE_COMMITTED = 3
+};
+
enum State {
NOT_INITIALIZED = 0,
COMMON_AREA_PAGES = 1,
- UNDO_RESTART_PAGES = 2,
- UNDO_PAGES = 3,
- READ_ONE_PAGE = 4,
- CHECKPOINT_DATA_READ = 7,
- CHECKPOINT_DATA_READ_PAGE_ZERO = 8,
- CHECKPOINT_DATA_WRITE = 9,
- CHECKPOINT_DATA_WRITE_LAST = 10,
- CHECKPOINT_DATA_WRITE_FLUSH = 11,
- CHECKPOINT_UNDO_READ = 12,
- CHECKPOINT_UNDO_READ_FIRST = 13,
- CHECKPOINT_UNDO_WRITE = 14,
- CHECKPOINT_UNDO_WRITE_FLUSH = 15,
- CHECKPOINT_TD_READ = 16,
IDLE = 17,
ACTIVE = 18,
SYSTEM_RESTART = 19,
- NO_OTHER_OP = 20,
- COMMIT_DELETE = 21,
- TO_BE_COMMITTED = 22,
- ABORTED = 23,
- ALREADY_ABORTED_INSERT = 24,
- ALREADY_ABORTED = 25,
- ABORT_INSERT = 26,
- ABORT_UPDATE = 27,
- INIT = 28,
- INITIAL_READ = 29,
- INTERPRETED_EXECUTION = 30,
- FINAL_READ = 31,
- FINAL_UPDATE = 32,
- DISCONNECTED = 33,
DEFINED = 34,
- ERROR_WAIT_TUPKEYREQ = 35,
- STARTED = 36,
NOT_DEFINED = 37,
- COMPLETED = 38,
- WAIT_ABORT = 39,
NORMAL_PAGE = 40,
- COPY_PAGE = 41,
- DELETE_BLOCK = 42,
- WAIT_STORED_PROCEDURE_ATTR_INFO = 43,
- DATA_FILE_READ = 45,
- DATA_FILE_WRITE = 46,
- LCP_DATA_FILE_READ = 47,
- LCP_DATA_FILE_WRITE = 48,
- LCP_DATA_FILE_WRITE_WITH_UNDO = 49,
- LCP_DATA_FILE_CLOSE = 50,
- LCP_UNDO_FILE_READ = 51,
- LCP_UNDO_FILE_CLOSE = 52,
- LCP_UNDO_FILE_WRITE = 53,
- OPENING_DATA_FILE = 54,
- INITIATING_RESTART_INFO = 55,
- INITIATING_FRAGMENT = 56,
- OPENING_UNDO_FILE = 57,
- READING_RESTART_INFO = 58,
- INIT_UNDO_SEGMENTS = 59,
- READING_TAB_DESCR = 60,
- READING_DATA_PAGES = 61,
- WAIT_COPY_PROCEDURE = 62,
- TOO_MUCH_AI = 63,
- SAME_PAGE = 64,
DEFINING = 65,
- TUPLE_BLOCKED = 66,
- ERROR_WAIT_STORED_PROCREQ = 67,
DROPPING = 68
};
@@ -435,67 +316,7 @@ struct Attrbufrec {
typedef Ptr<Attrbufrec> AttrbufrecPtr;
-/* ********** CHECKPOINT INFORMATION ************ */
-/* THIS RECORD HOLDS INFORMATION NEEDED TO */
-/* PERFORM A CHECKPOINT. IT'S POSSIBLE TO RUN */
-/* MULTIPLE CHECKPOINTS AT A TIME. THIS RECORD */
-/* MAKES IT POSSIBLE TO DISTINGER BETWEEN THE */
-/* DIFFERENT CHECKPOINTS. */
-/* ********************************************** */
-struct CheckpointInfo {
- Uint32 lcpNextRec; /* NEXT RECORD IN FREELIST */
- Uint32 lcpCheckpointVersion; /* VERSION OF THE CHECKPOINT */
- Uint32 lcpLocalLogInfoP; /* POINTER TO A LOCAL LOG INFO RECORD */
- Uint32 lcpUserptr; /* USERPOINTER TO THE BLOCK REQUESTING THE CP */
- Uint32 lcpFragmentP; /* FRAGMENT POINTER TO WHICH THE CHECKPOINT APPLIES */
- Uint32 lcpFragmentId; /* FRAGMENT ID */
- Uint32 lcpTabPtr; /* TABLE POINTER */
- Uint32 lcpDataBufferSegmentP; /* POINTER TO A DISK BUFFER SEGMENT POINTER (DATA) */
- Uint32 lcpDataFileHandle; /* FILE HANDLES FOR DATA FILE. LOG FILE HANDLE IN LOCAL_LOG_INFO_RECORD */
- /* FILE HANDLE TO THE OPEN DATA FILE */
- Uint32 lcpNoOfPages;
- Uint32 lcpThFreeFirst;
- Uint32 lcpThFreeCopyFirst;
- Uint32 lcpEmptyPrimPage;
- Uint32 lcpNoCopyPagesAlloc;
- Uint32 lcpTmpOperPtr; /* TEMPORARY STORAGE OF OPER_PTR DURING SAVE */
- BlockReference lcpBlockref; /* BLOCKREFERENCE TO THE BLOCK REQUESTING THE CP */
-};
-typedef Ptr<CheckpointInfo> CheckpointInfoPtr;
-
-/* *********** DISK BUFFER SEGMENT INFO ********* */
-/* THIS RECORD HOLDS INFORMATION NEEDED DURING */
-/* A WRITE OF THE DATA BUFFER TO DISK. WHEN THE */
-/* WRITE SIGNAL IS SENT A POINTER TO THIS RECORD */
-/* IS INCLUDED. WHEN THE WRITE IS COMPLETED AND */
-/* CONFIRMED THE PTR TO THIS RECORD IS RETURNED */
-/* AND THE BUFFER PAGES COULD EASILY BE LOCATED */
-/* AND DEALLOCATED. THE CHECKPOINT_INFO_VERSION */
-/* KEEPS TRACK OF THE CHECPOINT_INFO_RECORD THAT */
-/* INITIATED THE WRITE AND THE CP_PAGE_TO_DISK */
-/* ELEMENT COULD BE INCREASED BY THE NUMBER OF */
-/* PAGES WRITTEN. */
-/* ********************************************** */
-struct DiskBufferSegmentInfo {
- Uint32 pdxDataPage[16]; /* ARRAY OF DATA BUFFER PAGES */
- Uint32 pdxUndoBufferSet[2];
- Uint32 pdxNextRec;
- State pdxBuffertype;
- State pdxOperation;
- /*---------------------------------------------------------------------------*/
- /* PDX_FLAGS BITS AND THEIR USAGE: */
- /* BIT 0 1 COMMENT */
- /*---------------------------------------------------------------------------*/
- /* 0 SEGMENT INVALID SEGMENT VALID USED DURING READS */
- /* 1-15 NOT USED */
- /*---------------------------------------------------------------------------*/
- Uint32 pdxCheckpointInfoP; /* USED DURING LOCAL CHKP */
- Uint32 pdxRestartInfoP; /* USED DURING RESTART */
- Uint32 pdxLocalLogInfoP; /* POINTS TO A LOCAL LOG INFO */
- Uint32 pdxFilePage; /* START PAGE IN FILE */
- Uint32 pdxNumDataPages; /* NUMBER OF DATA PAGES */
-};
-typedef Ptr<DiskBufferSegmentInfo> DiskBufferSegmentInfoPtr;
+
struct Fragoperrec {
bool definingFragment;
@@ -505,10 +326,10 @@ struct Fragoperrec {
Uint32 tableidFrag;
Uint32 fragPointer;
Uint32 attributeCount;
- Uint32 currNullBit;
- Uint32 noOfNullBits;
- Uint32 noOfNewAttrCount;
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;
};
@@ -516,16 +337,15 @@ typedef Ptr<Fragoperrec> FragoperrecPtr;
// Position for use by scan
struct PagePos {
- Uint32 m_fragId; // "base" fragment id
- Uint32 m_fragBit; // two fragments in 5.0
- Uint32 m_pageId;
- Uint32 m_tupleNo;
+ Uint32 m_extent_info_ptr_i;
+ Local_key m_key;
bool m_match;
};
// Tup scan op (compare Dbtux::ScanOp)
struct ScanOp {
- enum {
+ ScanOp() {}
+ enum { // state
Undef = 0,
First = 1, // before first entry
Locked = 4, // at current entry (no lock needed)
@@ -534,12 +354,18 @@ typedef Ptr<Fragoperrec> FragoperrecPtr;
Invalid = 9 // cannot return REF to LQH currently
};
Uint16 m_state;
- Uint16 m_lockwait; // unused
+
+ STATIC_CONST( SCAN_DD = 0x1 );
+ STATIC_CONST( SCAN_VS = 0x2 );
+ STATIC_CONST( SCAN_LCP = 0x4 );
+ STATIC_CONST( SCAN_DD_VS = 0x8 );
+ Uint16 m_bits;
+
Uint32 m_userPtr; // scanptr.i in LQH
Uint32 m_userRef;
Uint32 m_tableId;
Uint32 m_fragId; // "base" fragment id
- Uint32 m_fragPtrI[2];
+ Uint32 m_fragPtrI;
Uint32 m_transId1;
Uint32 m_transId2;
PagePos m_scanPos;
@@ -552,11 +378,132 @@ typedef Ptr<Fragoperrec> FragoperrecPtr;
typedef Ptr<ScanOp> ScanOpPtr;
ArrayPool<ScanOp> c_scanOpPool;
- void scanFirst(Signal* signal, ScanOpPtr scanPtr);
- void scanNext(Signal* signal, ScanOpPtr scanPtr);
- void scanClose(Signal* signal, ScanOpPtr scanPtr);
- void releaseScanOp(ScanOpPtr& scanPtr);
+ typedef Tup_page Page;
+ typedef Ptr<Page> PagePtr;
+
+ struct Page_request
+ {
+ Page_request() {}
+ Local_key m_key;
+ Uint16 m_estimated_free_space; // in bytes/records
+ Uint16 m_list_index; // in Disk_alloc_info.m_page_requests
+ Uint32 m_frag_ptr_i;
+ Uint32 m_extent_info_ptr;
+ Uint16 m_ref_count; // Waiters for page
+ Uint16 m_uncommitted_used_space;
+ union {
+ Uint32 nextList;
+ Uint32 nextPool;
+ };
+ Uint32 prevList;
+ }; // 32 bytes
+
+ 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
+ {
+ 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;
+ }
+ 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 LocalDLList<Extent_info> Extent_list;
+ typedef LocalDLList<Page_request> Page_request_list;
+
+ struct Tablerec;
+ struct Disk_alloc_info
+ {
+ Disk_alloc_info() {}
+ Disk_alloc_info(const Tablerec* tabPtrP,
+ Uint32 extent_size_in_pages);
+
+ /**
+ * 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"
+ */
+ DLList<Page_request>::Head m_page_requests[MAX_FREE_LIST];
+
+ /**
+ * Current extent
+ */
+ Uint32 m_curr_extent_info_ptr_i;
+
+ /**
+ *
+ */
+ STATIC_CONST( SZ = EXTENT_SEARCH_MATRIX_SIZE );
+ Uint32 m_extent_search_matrix[SZ]; // 4x4
+ DLList<Extent_info>::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;
+ }
+
+ SLList<Extent_info, Extent_list_t>::Head m_extent_list;
+ };
+
struct Fragrecord {
Uint32 nextStartRange;
Uint32 currentPageRange;
@@ -564,122 +511,154 @@ struct Fragrecord {
Uint32 noOfPages;
Uint32 emptyPrimPage;
- Uint32 firstusedOprec;
- Uint32 lastusedOprec;
-
Uint32 thFreeFirst;
- Uint32 thFreeCopyFirst;
- Uint32 noCopyPagesAlloc;
+ Uint32 m_lcp_scan_op;
- Uint32 checkpointVersion;
- Uint32 minPageNotWrittenInCheckpoint;
- Uint32 maxPageWrittenInCheckpoint;
State fragStatus;
Uint32 fragTableId;
Uint32 fragmentId;
Uint32 nextfreefrag;
+ Uint32 free_var_page_array[MAX_FREE_LIST];
+
+ DLList<ScanOp>::Head m_scanList;
- DLList<ScanOp> m_scanList;
- Fragrecord(ArrayPool<ScanOp> & scanOpPool) : m_scanList(scanOpPool) {}
+ bool m_undo_complete;
+ Uint32 m_tablespace_id;
+ Uint32 m_logfile_group_id;
+ Disk_alloc_info m_disk_alloc_info;
};
typedef Ptr<Fragrecord> FragrecordPtr;
- /* ************ LOCAL LOG FILE INFO ************* */
- /* THIS RECORD HOLDS INFORMATION NEEDED DURING */
- /* CHECKPOINT AND RESTART. THERE ARE FOUR */
- /* PARALLELL UNDO LOG FILES, EACH ONE REPRESENTED */
- /* BY AN ENTITY OF THIS RECORD. */
- /* BECAUSE EACH FILE IS SHARED BETWEEN FOUR */
- /* TABLES AND HAS ITS OWN PAGEPOINTERS AND */
- /* WORDPOINTERS. */
- /* ********************************************** */
-struct LocalLogInfo {
- Uint32 lliActiveLcp; /* NUMBER OF ACTIVE LOCAL CHECKPOINTS ON THIS FILE */
- Uint32 lliEndPageId; /* PAGE IDENTIFIER OF LAST PAGE WITH LOG DATA */
- Uint32 lliPrevRecordId; /* PREVIOUS RECORD IN THIS LOGFILE */
- Uint32 lliLogFilePage; /* PAGE IN LOGFILE */
- Uint32 lliNumFragments; /* NO OF FRAGMENTS RESTARTING FROM THIS LOCAL LOG */
- Uint32 lliUndoBufferSegmentP; /* POINTER TO A DISK BUFFER SEGMENT POINTER (UNDO) */
- Uint32 lliUndoFileHandle; /* FILE HANDLE OF UNDO LOG FILE */
- Uint32 lliUndoPage; /* UNDO PAGE IN BUFFER */
- Uint32 lliUndoWord;
- Uint32 lliUndoPagesToDiskWithoutSynch;
-};
-typedef Ptr<LocalLogInfo> LocalLogInfoPtr;
+ void scanFirst(Signal* signal, Fragrecord*, ScanOpPtr scanPtr);
+ void scanNext(Signal* signal, Fragrecord*, ScanOpPtr scanPtr);
+ void scanClose(Signal* signal, ScanOpPtr scanPtr);
+ void releaseScanOp(ScanOpPtr& scanPtr);
+
struct Operationrec {
-// Easy to remove (2 words)
- Uint32 attroutbufLen;
- Uint32 logSize;
-
-// Needed (20 words)
- State tupleState;
- Uint32 prevActiveOp;
- Uint32 nextActiveOp;
- Uint32 nextOprecInList;
- Uint32 prevOprecInList;
- Uint32 tableRef;
- Uint32 fragId;
+ /*
+ * 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
+ };
+
+ 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
+ };
+ 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;
- Uint32 fragPageId;
- Uint32 realPageId;
- bool undoLogged;
- Uint32 realPageIdC;
- Uint32 fragPageIdC;
- Uint32 firstAttrinbufrec;
- Uint32 lastAttrinbufrec;
- Uint32 attrinbufLen;
- Uint32 currentAttrinbufLen;
+
+ /*
+ * 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;
- State transstate;
- Uint32 savePointId;
-
-// Easy to remove (3 words)
- Uint32 tcOperationPtr;
- Uint32 transid1;
- Uint32 transid2;
-
-// Needed (2 words)
- Uint16 pageIndex;
- Uint16 pageOffset;
- Uint16 pageOffsetC;
- Uint16 pageIndexC;
-// Hard to remove
- Uint16 tupVersion;
-// Easy to remove (1.5 word)
- BlockReference recBlockref;
- BlockReference userblockref;
- Uint16 storedProcedureId;
-
- Uint8 inFragList;
- Uint8 inActiveOpList;
- Uint8 deleteInsertFlag;
-
-// Needed (1 word)
- Uint8 dirtyOp;
- Uint8 interpretedExec;
- Uint8 optype;
- Uint8 opSimple;
-
-// Used by triggers
- Uint32 primaryReplica;
- BlockReference coordinatorTC;
- Uint32 tcOpIndex;
- Uint32 gci;
- Uint32 noFiredTriggers;
+ /*
+ * 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 hashValue; // only used in TUP_COMMITREQ
- Uint32 lastRow;
+ Uint32 savepointId;
+ Uint32 m_commit_disk_callback_page;
+ };
+
+ /*
+ * We use 64 bits to save change mask for the most common cases.
+ */
+ union {
+ Uint32 saved_change_mask[2];
+ Uint64 m_mask;
};
- Bitmask<MAXNROFATTRIBUTESINWORDS> changeMask;
-};
-typedef Ptr<Operationrec> OperationrecPtr;
-struct Page {
- Uint32 pageWord[ZWORDS_ON_PAGE];
+ /*
+ * 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<Page> PagePtr;
+typedef Ptr<Operationrec> OperationrecPtr;
/* ****************************** PAGE RANGE RECORD ************************** */
/* PAGE RANGES AND BASE PAGE ID. EACH RANGE HAS A CORRESPONDING BASE PAGE ID */
@@ -703,39 +682,6 @@ struct PageRange {
};
typedef Ptr<PageRange> PageRangePtr;
- /* *********** PENDING UNDO WRITE INFO ********** */
- /* THIS RECORD HOLDS INFORMATION NEEDED DURING */
- /* A FILE OPEN OPERATION */
- /* IF THE FILE OPEN IS A PART OF A CHECKPOINT THE */
- /* CHECKPOINT_INFO_P WILL HOLD A POINTER TO THE */
- /* CHECKPOINT_INFOR_PTR RECORD */
- /* IF IT IS A PART OF RESTART THE PFO_RESTART_INFO*/
- /* ELEMENT WILL POINT TO A RESTART INFO RECORD */
- /* ********************************************** */
-struct PendingFileOpenInfo {
- Uint32 pfoNextRec;
- State pfoOpenType;
- Uint32 pfoCheckpointInfoP;
- Uint32 pfoRestartInfoP;
-};
-typedef Ptr<PendingFileOpenInfo> PendingFileOpenInfoPtr;
-
-struct RestartInfoRecord {
- Uint32 sriNextRec;
- State sriState; /* BLOCKREFERENCE TO THE REQUESTING BLOCK */
- Uint32 sriUserptr; /* USERPOINTER TO THE REQUESTING BLOCK */
- Uint32 sriDataBufferSegmentP; /* POINTER TO A DISK BUFFER SEGMENT POINTER (DATA) */
- Uint32 sriDataFileHandle; /* FILE HANDLE TO THE OPEN DATA FILE */
- Uint32 sriCheckpointVersion; /* CHECKPOINT VERSION TO RESTART FROM */
- Uint32 sriFragid; /* FRAGMENT ID */
- Uint32 sriFragP; /* FRAGMENT POINTER */
- Uint32 sriTableId; /* TABLE ID */
- Uint32 sriLocalLogInfoP; /* POINTER TO A LOCAL LOG INFO RECORD */
- Uint32 sriNumDataPages; /* NUMBER OF DATA PAGES TO READ */
- Uint32 sriCurDataPageFromBuffer; /* THE CHECKPOINT IS COMPLETED */
- BlockReference sriBlockref;
-};
-typedef Ptr<RestartInfoRecord> RestartInfoRecordPtr;
/* ************* TRIGGER DATA ************* */
/* THIS RECORD FORMS LISTS OF ACTIVE */
@@ -819,80 +765,171 @@ typedef Ptr<TupTriggerData> TriggerPtr;
*/
ArrayPool<TupTriggerData> c_triggerPool;
- /* ************ TABLE RECORD ************ */
- /* THIS RECORD FORMS A LIST OF TABLE */
- /* REFERENCE INFORMATION. ONE RECORD */
- /* PER TABLE REFERENCE. */
- /* ************************************** */
-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;
-
- ReadFunction* readFunctionArray;
- UpdateFunction* updateFunctionArray;
- CHARSET_INFO** charsetArray;
-
- Uint32 readKeyArray;
- Uint32 tabDescriptor;
- Uint32 attributeGroupDescriptor;
-
- bool GCPIndicator;
- bool checksumIndicator;
-
- Uint16 tupheadsize;
- Uint16 noOfAttr;
- Uint16 noOfKeyAttr;
- Uint16 noOfCharsets;
- Uint16 noOfNewAttr;
- Uint16 noOfNullAttr;
- Uint16 noOfAttributeGroups;
-
- Uint8 tupChecksumIndex;
- Uint8 tupNullIndex;
- Uint8 tupNullWords;
- Uint8 tupGCPIndex;
-
- // Lists of trigger data for active triggers
- ArrayList<TupTriggerData> afterInsertTriggers;
- ArrayList<TupTriggerData> afterDeleteTriggers;
- ArrayList<TupTriggerData> afterUpdateTriggers;
- ArrayList<TupTriggerData> subscriptionInsertTriggers;
- ArrayList<TupTriggerData> subscriptionDeleteTriggers;
- ArrayList<TupTriggerData> subscriptionUpdateTriggers;
- ArrayList<TupTriggerData> constraintUpdateTriggers;
-
- // List of ordered indexes
- ArrayList<TupTriggerData> tuxCustomTriggers;
-
- Uint32 fragid[2 * MAX_FRAG_PER_NODE];
- Uint32 fragrec[2 * MAX_FRAG_PER_NODE];
-
- struct {
- Uint32 tabUserPtr;
- Uint32 tabUserRef;
- } m_dropTable;
- State tableStatus;
-};
+ /* ************ 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;
+
+ ReadFunction* readFunctionArray;
+ UpdateFunction* updateFunctionArray;
+ CHARSET_INFO** charsetArray;
+
+ Uint32 readKeyArray;
+ Uint32 tabDescriptor;
+ Uint32 m_real_order_descriptor;
+
+ bool checksumIndicator;
+ 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
+ union {
+ Uint16 m_varpart_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 {
+ Uint32 cnt= m_attributes[mm].m_no_of_varsize;
+ Uint32 off= m_offsets[mm].m_varpart_offset;
+ return off - (cnt ? 0 : Tuple_header::HeaderSize);
+ }
+
+ struct {
+ Uint16 m_no_of_fixsize;
+ Uint16 m_no_of_varsize;
+ } m_attributes[2];
+
+ // Lists of trigger data for active triggers
+ ArrayList<TupTriggerData> afterInsertTriggers;
+ ArrayList<TupTriggerData> afterDeleteTriggers;
+ ArrayList<TupTriggerData> afterUpdateTriggers;
+ ArrayList<TupTriggerData> subscriptionInsertTriggers;
+ ArrayList<TupTriggerData> subscriptionDeleteTriggers;
+ ArrayList<TupTriggerData> subscriptionUpdateTriggers;
+ ArrayList<TupTriggerData> constraintUpdateTriggers;
+
+ // List of ordered indexes
+ ArrayList<TupTriggerData> tuxCustomTriggers;
+
+ Uint32 fragid[MAX_FRAG_PER_NODE];
+ Uint32 fragrec[MAX_FRAG_PER_NODE];
+
+ struct {
+ Uint32 tabUserPtr;
+ Uint32 tabUserRef;
+ } 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
+ };
+
+ 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
+ };
+ };
+
+ ArrayPool<Extent_info> c_extent_pool;
+ ArrayPool<Page_request> c_page_request_pool;
+ DLHashTable<Extent_info> c_extent_hash;
-typedef Ptr<Tablerec> TablerecPtr;
+ typedef Ptr<Tablerec> TablerecPtr;
-struct storedProc {
- Uint32 storedLinkFirst;
- Uint32 storedLinkLast;
- Uint32 storedCounter;
- Uint32 nextPool;
- Uint16 storedCode;
- Uint16 storedProcLength;
+ struct storedProc {
+ Uint32 storedLinkFirst;
+ Uint32 storedLinkLast;
+ Uint32 storedCounter;
+ Uint32 nextPool;
+ Uint16 storedCode;
+ Uint16 storedProcLength;
};
typedef Ptr<storedProc> StoredProcPtr;
@@ -1007,27 +1044,18 @@ struct HostBuffer {
};
typedef Ptr<HostBuffer> HostBufferPtr;
- /* **************** UNDO PAGE RECORD ******************* */
- /* THIS RECORD FORMS AN UNDO PAGE CONTAINING A NUMBER OF */
- /* DATA WORDS. CURRENTLY THERE ARE 2048 WORDS ON A PAGE */
- /* EACH OF 32 BITS (4 BYTES) WHICH FORMS AN UNDO PAGE */
- /* WITH A TOTAL OF 8192 BYTES */
- /* ***************************************************** */
-struct UndoPage {
- Uint32 undoPageWord[ZWORDS_ON_PAGE]; /* 32 KB */
-};
-typedef Ptr<UndoPage> UndoPagePtr;
-
/*
* Build index operation record.
*/
struct BuildIndexRec {
// request cannot use signal class due to extra members
Uint32 m_request[BuildIndxReq::SignalLength];
- Uint32 m_triggerPtrI; // the index trigger
+ 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 (pageIndex >> 1)
+ Uint32 m_tupleNo; // tuple number on page
+ Uint32 m_buildRef; // Where to send tuples
BuildIndxRef::ErrorCode m_errorCode;
union {
Uint32 nextPool;
@@ -1040,8 +1068,178 @@ typedef Ptr<UndoPage> UndoPagePtr;
ArrayList<BuildIndexRec> c_buildIndexList;
Uint32 c_noOfBuildIndexRec;
+ /**
+ * Reference to variable part when a tuple is chained
+ */
+ struct Var_part_ref
+ {
+ Uint32 m_ref;
+ };
+
+ struct Tuple_header
+ {
+ union {
+ 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( FREE = 0x00800000 ); // On free list of page
+ STATIC_CONST( LCP_SKIP = 0x01000000 ); // Should not be returned in LCP
+
+ 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;
+ }
+
+ Uint32* get_var_part_ptr(const Tablerec* tabPtrP) {
+ return m_data + tabPtrP->m_offsets[MM].m_varpart_offset;
+ }
+
+ const Uint32* get_var_part_ptr(const Tablerec* tabPtrP) const {
+ return m_data + tabPtrP->m_offsets[MM].m_varpart_offset;
+ }
+
+ 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;
+ }
+ };
+
+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;
+ Page* m_page_ptr_p;
+ Var_page* m_varpart_page_ptr_p;// could be same as m_page_ptr_p
+ PagePtr m_disk_page_ptr; //
+
+ bool dirty_op;
+ bool interpreted_exec;
+ bool last_row;
+
+ 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;
+ 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(const class Configuration &);
+ Dbtup(const class Configuration &, Pgman*);
virtual ~Dbtup();
/*
@@ -1085,6 +1283,14 @@ public:
*/
bool tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, 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);
+
+ void start_restore_lcp(Uint32 tableId, Uint32 fragmentId);
+ void complete_restore_lcp(Uint32 tableId, Uint32 fragmentId);
private:
BLOCK_DEFINES(Dbtup);
@@ -1093,6 +1299,7 @@ private:
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);
@@ -1107,18 +1314,11 @@ private:
void execTUP_ADD_ATTRREQ(Signal* signal);
void execTUP_COMMITREQ(Signal* signal);
void execTUP_ABORTREQ(Signal* signal);
- void execTUP_SRREQ(Signal* signal);
- void execTUP_PREPLCPREQ(Signal* signal);
- void execFSOPENCONF(Signal* signal);
- void execFSCLOSECONF(Signal* signal);
- void execFSWRITECONF(Signal* signal);
- void execFSREADCONF(Signal* signal);
void execNDB_STTOR(Signal* signal);
void execREAD_CONFIG_REQ(Signal* signal);
void execSET_VAR_REQ(Signal* signal);
void execDROP_TAB_REQ(Signal* signal);
void execALTER_TAB_REQ(Signal* signal);
- void execFSREMOVECONF(Signal* signal);
void execTUP_ALLOCREQ(Signal* signal);
void execTUP_DEALLOCREQ(Signal* signal);
void execTUP_WRITELOG_REQ(Signal* signal);
@@ -1314,10 +1514,15 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
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
//------------------------------------------------------------------
@@ -1334,6 +1539,7 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
void handleATTRINFOforTUPKEYREQ(Signal* signal,
+ const Uint32* data,
Uint32 length,
Operationrec * const regOperPtr);
@@ -1345,7 +1551,7 @@ private:
int handleReadReq(Signal* signal,
Operationrec* const regOperPtr,
Tablerec* const regTabPtr,
- Page* pagePtr);
+ KeyReqStruct* req_struct);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -1353,15 +1559,16 @@ private:
Operationrec* const regOperPtr,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
- Page* const pagePtr);
+ KeyReqStruct* req_struct,
+ bool disk);
//------------------------------------------------------------------
//------------------------------------------------------------------
int handleInsertReq(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
+ Ptr<Operationrec> regOperPtr,
+ Ptr<Fragrecord>,
Tablerec* const regTabPtr,
- Page* const pagePtr);
+ KeyReqStruct* req_struct);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -1369,14 +1576,15 @@ private:
Operationrec* const regOperPtr,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
- Page* const pagePtr);
+ KeyReqStruct* req_struct);
//------------------------------------------------------------------
//------------------------------------------------------------------
int updateStartLab(Signal* signal,
Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
- Page* const pagePtr);
+ KeyReqStruct* req_struct);
// *****************************************************************
// Interpreter Handling methods.
@@ -1385,14 +1593,12 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
int interpreterStartLab(Signal* signal,
- Page* const pagePtr,
- Uint32 TupHeadOffset);
+ KeyReqStruct *req_struct);
//------------------------------------------------------------------
//------------------------------------------------------------------
int interpreterNextLab(Signal* signal,
- Page* const pagePtr,
- Uint32 TupHeadOffset,
+ KeyReqStruct *req_struct,
Uint32* logMemory,
Uint32* mainProgram,
Uint32 TmainProgLen,
@@ -1407,6 +1613,7 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
void sendReadAttrinfo(Signal* signal,
+ KeyReqStruct *req_struct,
Uint32 TnoOfData,
const Operationrec * const regOperPtr);
@@ -1418,9 +1625,9 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
- void sendTUPKEYCONF(Signal* signal, Operationrec *
- const regOperPtr,
- Uint32 TlogSize);
+ void sendTUPKEYCONF(Signal* signal,
+ KeyReqStruct *req_struct,
+ Operationrec * const regOperPtr);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -1430,8 +1637,7 @@ private:
// *****************************************************************
//------------------------------------------------------------------
//------------------------------------------------------------------
- int readAttributes(Page* const pagePtr,
- Uint32 TupHeadOffset,
+ int readAttributes(KeyReqStruct* req_struct,
const Uint32* inBuffer,
Uint32 inBufLen,
Uint32* outBuffer,
@@ -1440,258 +1646,199 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
- int readAttributesWithoutHeader(Page* const pagePtr,
- Uint32 TupHeadOffset,
- Uint32* inBuffer,
- Uint32 inBufLen,
- Uint32* outBuffer,
- Uint32* attrBuffer,
- Uint32 TmaxRead);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- int updateAttributes(Page* const pagePtr,
- Uint32 TupHeadOffset,
+ int updateAttributes(KeyReqStruct *req_struct,
Uint32* inBuffer,
Uint32 inBufLen);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool readFixedSizeTHOneWordNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool updateFixedSizeTHOneWordNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool readFixedSizeTHTwoWordNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool updateFixedSizeTHTwoWordNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool readFixedSizeTHOneWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool updateFixedSizeTHOneWordNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool readFixedSizeTHTwoWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool updateFixedSizeTHTwoWordNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool readFixedSizeTHManyWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool readFixedSizeTHZeroWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool updateFixedSizeTHManyWordNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool readVariableSizedAttr(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateVariableSizedAttr(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readVarSizeUnlimitedNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateVarSizeUnlimitedNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool readVarSizeNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool readVarSizeUnlimitedNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool updateVarSizeNotNULL(Uint32* inBuffer,
+ KeyReqStruct *req_struct,
+ Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool updateVarSizeUnlimitedNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool readVarSizeNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool readBigVarSizeNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
+ bool updateVarSizeNULLable(Uint32* inBuffer,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool updateBigVarSizeNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readBigVarSizeNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateBigVarSizeNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readSmallVarSizeNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateSmallVarSizeNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readSmallVarSizeNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateSmallVarSizeNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
-
-//------------------------------------------------------------------
-//------------------------------------------------------------------
bool readDynFixedSize(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
bool updateDynFixedSize(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool readDynVarSizeUnlimited(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool readDynVarSize(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool updateDynVarSizeUnlimited(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool updateDynVarSize(Uint32* inBuffer,
+ KeyReqStruct *req_struct,
+ Uint32 attrDes2);
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readDynBigVarSize(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool readCharNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2);
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool updateDynBigVarSize(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool readCharNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2);
-//------------------------------------------------------------------
-//------------------------------------------------------------------
- bool readDynSmallVarSize(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- 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 updateDynSmallVarSize(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ 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 readBitsNULLable(Uint32* outBuffer, AttributeHeader*, Uint32, Uint32);
- bool updateBitsNULLable(Uint32* inBuffer, Uint32, Uint32);
- bool readBitsNotNULL(Uint32* outBuffer, AttributeHeader*, Uint32, Uint32);
- bool updateBitsNotNULL(Uint32* inBuffer, Uint32, Uint32);
//------------------------------------------------------------------
//------------------------------------------------------------------
- bool nullFlagCheck(Uint32 attrDes2);
- Uint32 read_pseudo(Uint32 attrId, Uint32* outBuffer);
+ 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);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -1700,13 +1847,26 @@ private:
// *****************************************************************
// 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(Signal* signal, Operationrec * const regOperPtr, Uint32* inBuffer);
+ void copyAttrinfo(Operationrec * const regOperPtr, Uint32* inBuffer);
//------------------------------------------------------------------
//------------------------------------------------------------------
- void initOpConnection(Operationrec* regOperPtr, Fragrecord*);
+ void initOpConnection(Operationrec* regOperPtr);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -1715,19 +1875,15 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
int initStoredOperationrec(Operationrec* const regOperPtr,
+ KeyReqStruct* req_struct,
Uint32 storedId);
//------------------------------------------------------------------
//------------------------------------------------------------------
- void insertActiveOpList(Signal* signal,
- OperationrecPtr regOperPtr,
- Page * const pagePtr,
- Uint32 pageOffset);
+ bool insertActiveOpList(OperationrecPtr, KeyReqStruct* req_struct);
//------------------------------------------------------------------
//------------------------------------------------------------------
- void linkOpIntoFragList(OperationrecPtr regOperPtr,
- Fragrecord* const regFragPtr);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -1736,64 +1892,70 @@ private:
//------------------------------------------------------------------
// Trigger handling routines
//------------------------------------------------------------------
- ArrayList<TupTriggerData>* findTriggerList(Tablerec* table,
- TriggerType::Value ttype,
- TriggerActionTime::Value ttime,
- TriggerEvent::Value tevent);
+ ArrayList<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);
- void checkImmediateTriggersAfterInsert(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const tablePtr);
+ void
+ checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const tablePtr);
- void checkImmediateTriggersAfterUpdate(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const tablePtr);
+ void
+ checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const tablePtr);
- void checkImmediateTriggersAfterDelete(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const tablePtr);
+ void
+ checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const tablePtr);
#if 0
void checkDeferredTriggers(Signal* signal,
Operationrec* const regOperPtr,
Tablerec* const regTablePtr);
#endif
- void checkDetachedTriggers(Signal* signal,
+ void checkDetachedTriggers(KeyReqStruct *req_struct,
Operationrec* const regOperPtr,
Tablerec* const regTablePtr);
- void fireImmediateTriggers(Signal* signal,
+ void fireImmediateTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr);
- void fireDeferredTriggers(Signal* signal,
+ void fireDeferredTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr);
- void fireDetachedTriggers(Signal* signal,
+ void fireDetachedTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr);
- void executeTriggers(Signal* signal,
+ void executeTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr);
- void executeTrigger(Signal* signal,
+ void executeTrigger(KeyReqStruct *req_struct,
TupTriggerData* const trigPtr,
Operationrec* const regOperPtr);
bool readTriggerInfo(TupTriggerData* const trigPtr,
- Operationrec* const regOperPtr,
+ Operationrec* const regOperPtr,
+ KeyReqStruct * const req_struct,
+ Fragrecord* const regFragPtr,
Uint32* const keyBuffer,
Uint32& noPrimKey,
- Uint32* const mainBuffer,
- Uint32& noMainWords,
- Uint32* const copyBuffer,
- Uint32& noCopyWords);
+ Uint32* const afterBuffer,
+ Uint32& noAfterWords,
+ Uint32* const beforeBuffer,
+ Uint32& noBeforeWords);
void sendTrigAttrInfo(Signal* signal,
Uint32* data,
@@ -1806,8 +1968,10 @@ private:
Uint32* inBuffer);
void sendFireTrigOrd(Signal* signal,
- Operationrec * const regOperPtr,
+ KeyReqStruct *req_struct,
+ Operationrec * const regOperPtr,
TupTriggerData* const trigPtr,
+ Uint32 fragmentId,
Uint32 noPrimKeySignals,
Uint32 noBeforeSignals,
Uint32 noAfterSignals);
@@ -1817,16 +1981,19 @@ private:
// these set terrorCode and return non-zero on error
int executeTuxInsertTriggers(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTabPtr);
+ Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr);
int executeTuxUpdateTriggers(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTabPtr);
+ Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr);
int executeTuxDeleteTriggers(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTabPtr);
+ Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr);
int addTuxEntries(Signal* signal,
Operationrec* regOperPtr,
@@ -1836,10 +2003,12 @@ private:
void executeTuxCommitTriggers(Signal* signal,
Operationrec* regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr);
void executeTuxAbortTriggers(Signal* signal,
Operationrec* regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr);
void removeTuxEntries(Signal* signal,
@@ -1881,7 +2050,7 @@ private:
//
// 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 owner
+// we will set the delete state on the record that becomes the ownerd
// of the record.
//
// Commit of Update:
@@ -1921,40 +2090,58 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
-#if 0
+#if 0
void checkPages(Fragrecord* const regFragPtr);
#endif
- void printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit);
+ 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 setup_fixed_part(KeyReqStruct* req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const regTabPtr);
+
+ void send_TUPKEYREF(Signal* signal,
+ Operationrec* const regOperPtr);
+ void early_tupkey_error(Signal* signal);
- bool checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr);
+ void printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit);
- void setNullBits(Page* const regPage, Tablerec* const regTabPtr, Uint32 pageOffset);
- bool checkNullAttributes(Operationrec* const, Tablerec* const);
- bool getPage(PagePtr& pagePtr,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr);
+ bool checkUpdateOfPrimaryKey(KeyReqStruct *req_struct,
+ Uint32* updateBuffer,
+ Tablerec* const regTabPtr);
+ void setNullBits(Uint32*, Tablerec* const regTabPtr);
+ bool checkNullAttributes(KeyReqStruct * const, Tablerec* const);
+ bool setup_read(KeyReqStruct* req_struct,
+ Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr,
+ bool disk);
+
bool getPageLastCommitted(Operationrec* const regOperPtr,
Operationrec* const leaderOpPtr);
bool getPageThroughSavePoint(Operationrec* const regOperPtr,
Operationrec* const leaderOpPtr);
- Uint32 calculateChecksum(Page* const pagePtr, Uint32 tupHeadOffset, Uint32 tupHeadSize);
- void setChecksum(Page* const pagePtr, Uint32 tupHeadOffset, Uint32 tupHeadSize);
-
- void commitSimple(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr);
+ Uint32 calculateChecksum(Tuple_header*, Tablerec* const regTabPtr);
+ void setChecksum(Tuple_header*, Tablerec* const regTabPtr);
- void commitRecord(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr);
+ void complexTrigger(Signal* signal,
+ KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr);
void setTupleStatesSetOpType(Operationrec* const regOperPtr,
+ KeyReqStruct *req_struct,
Page* const pagePtr,
Uint32& opType,
OperationrecPtr& firstOpPtr);
@@ -1964,29 +2151,19 @@ private:
void calculateChangeMask(Page* const PagePtr,
Tablerec* const regTabPtr,
- Uint32 pageOffset,
- Bitmask<MAXNROFATTRIBUTESINWORDS>& attributeMask);
+ KeyReqStruct * const req_struct);
- void updateGcpId(Signal* signal,
+ void updateGcpId(KeyReqStruct *req_struct,
Operationrec* const regOperPtr,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr);
- void abortUpdate(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr);
- void commitUpdate(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const 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);
+ void removeActiveOpList(Operationrec* const regOperPtr, Tuple_header*);
void updatePackedList(Signal* signal, Uint16 ahostIndex);
@@ -2039,129 +2216,15 @@ private:
Uint32 fragId);
- void checkLcpActiveBufferPage(Uint32 minPageNotWrittenInCheckpoint, DiskBufferSegmentInfoPtr dbsiPtr);
- void lcpWriteListDataPageSegment(Signal* signal,
- DiskBufferSegmentInfoPtr dbsiPtr,
- CheckpointInfoPtr ciPtr,
- bool flushFlag);
- void lcpFlushLogLab(Signal* signal, CheckpointInfoPtr ciPtr);
- void lcpClosedDataFileLab(Signal* signal, CheckpointInfoPtr ciPtr);
- void lcpEndconfLab(Signal* signal);
- void lcpSaveDataPageLab(Signal* signal, Uint32 ciIndex);
- void lcpCompletedLab(Signal* signal, Uint32 ciIndex);
- void lcpFlushRestartInfoLab(Signal* signal, Uint32 ciIndex);
- void lcpSaveCopyListLab(Signal* signal, CheckpointInfoPtr ciPtr);
-
- void sendFSREMOVEREQ(Signal* signal, TablerecPtr tabPtr);
void releaseFragment(Signal* signal, Uint32 tableId);
-
- void allocDataBufferSegment(Signal* signal, DiskBufferSegmentInfoPtr& dbsiPtr);
- void allocRestartUndoBufferSegment(Signal* signal, DiskBufferSegmentInfoPtr& dbsiPtr, LocalLogInfoPtr lliPtr);
- void freeDiskBufferSegmentRecord(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr);
- void freeUndoBufferPages(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr);
-
- void releaseCheckpointInfoRecord(CheckpointInfoPtr ciPtr);
- void releaseDiskBufferSegmentRecord(DiskBufferSegmentInfoPtr dbsiPtr);
- void releaseFragoperrec(FragoperrecPtr fragOperPtr);
- void releaseFragrec(FragrecordPtr regFragPtr);
- void releasePendingFileOpenInfoRecord(PendingFileOpenInfoPtr pfoPtr);
- void releaseRestartInfoRecord(RestartInfoRecordPtr riPtr);
-
- void seizeDiskBufferSegmentRecord(DiskBufferSegmentInfoPtr& dbsiPtr);
- void seizeCheckpointInfoRecord(CheckpointInfoPtr& ciPtr);
- void seizeFragoperrec(FragoperrecPtr& fragOperPtr);
- void seizeFragrecord(FragrecordPtr& regFragPtr);
- void seizeOpRec(OperationrecPtr& regOperPtr);
- void seizePendingFileOpenInfoRecord(PendingFileOpenInfoPtr& pfoiPtr);
- void seizeRestartInfoRecord(RestartInfoRecordPtr& riPtr);
-
+ void drop_fragment_free_exent(Signal*, TablerecPtr, FragrecordPtr, Uint32);
+ void drop_fragment_unmap_pages(Signal*, TablerecPtr, FragrecordPtr, Uint32);
+ void drop_fragment_unmap_page_callback(Signal* signal, Uint32, Uint32);
+
// Initialisation
void initData();
void initRecords();
- void rfrClosedDataFileLab(Signal* signal, Uint32 restartIndex);
- void rfrCompletedLab(Signal* signal, RestartInfoRecordPtr riPtr);
- void rfrInitRestartInfoLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr);
- void rfrLoadDataPagesLab(Signal* signal, RestartInfoRecordPtr riPtr, DiskBufferSegmentInfoPtr dbsiPtr);
- void rfrReadFirstUndoSegment(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr);
- void rfrReadNextDataSegment(Signal* signal, RestartInfoRecordPtr riPtr, DiskBufferSegmentInfoPtr dbsiPtr);
- void rfrReadNextUndoSegment(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr);
- void rfrReadRestartInfoLab(Signal* signal, RestartInfoRecordPtr riPtr);
- void rfrReadSecondUndoLogLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr);
-
- void startExecUndoLogLab(Signal* signal, Uint32 lliIndex);
- void readExecUndoLogLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr);
- void closeExecUndoLogLab(Signal* signal, LocalLogInfoPtr lliPtr);
- void endExecUndoLogLab(Signal* signal, Uint32 lliIndex);
-
- struct XlcStruct {
- Uint32 PageId;
- Uint32 PageIndex;
- Uint32 LogRecordType;
- Uint32 FragId;
- FragrecordPtr FragPtr;
- LocalLogInfoPtr LliPtr;
- DiskBufferSegmentInfoPtr DbsiPtr;
- UndoPagePtr UPPtr;
- TablerecPtr TabPtr;
- };
-
- void xlcGetNextRecordLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr);
- void xlcRestartCompletedLab(Signal* signal);
-
- void xlcCopyData(XlcStruct& xlcStruct, Uint32 pageOffset, Uint32 noOfWords, PagePtr pagePtr);
- void xlcGetLogHeader(XlcStruct& xlcStruct);
- Uint32 xlcGetLogWord(XlcStruct& xlcStruct);
-
- void xlcAbortInsert(Signal* signal, XlcStruct& xlcStruct);
- void xlcAbortUpdate(Signal* signal, XlcStruct& xlcStruct);
- void xlcDeleteTh(XlcStruct& xlcStruct);
- void xlcIndicateNoOpActive(XlcStruct& xlcStruct);
- void xlcInsertTh(XlcStruct& xlcStruct);
- void xlcTableDescriptor(XlcStruct& xlcStruct);
- void xlcUndoLogPageHeader(XlcStruct& xlcStruct);
- void xlcUpdateTh(XlcStruct& xlcStruct);
- void xlcUpdateGCI(XlcStruct& xlcStruct);
-
-
- void cprAddData(Signal* signal,
- Fragrecord* const regFragPtr,
- Uint32 pageIndex,
- Uint32 noOfWords,
- Uint32 startOffset);
- void cprAddGCIUpdate(Signal* signal,
- Uint32 prevGCI,
- Fragrecord* const regFragPtr);
- void cprAddLogHeader(Signal* signal,
- LocalLogInfo* const lliPtr,
- Uint32 recordType,
- Uint32 tableId,
- Uint32 fragId);
- void cprAddUndoLogPageHeader(Signal* signal,
- Page* const regPagePtr,
- Fragrecord* const regFragPtr);
- void cprAddUndoLogRecord(Signal* signal,
- Uint32 recordType,
- Uint32 pageId,
- Uint32 pageIndex,
- Uint32 tableId,
- Uint32 fragId,
- Uint32 localLogIndex);
- void cprAddAbortUpdate(Signal* signal,
- LocalLogInfo* const lliPtr,
- Operationrec* const regOperPtr);
- void cprAddUndoLogWord(Signal* signal,
- LocalLogInfo* const lliPtr,
- Uint32 undoWord);
- bool isUndoLoggingNeeded(Fragrecord* const regFragPtr, Uint32 pageId);
- bool isUndoLoggingActive(Fragrecord* const regFragPtr);
- bool isUndoLoggingBlocked(Fragrecord* const regFragPtr);
- bool isPageUndoLogged(Fragrecord* const regFragPtr, Uint32 pageId);
-
- void seizeUndoBufferSegment(Signal* signal, UndoPagePtr& regUndoPagePtr);
- void lcpWriteUndoSegment(Signal* signal, LocalLogInfo* const lliPtr, bool flushFlag);
-
-
void deleteScanProcedure(Signal* signal, Operationrec* regOperPtr);
void copyProcedure(Signal* signal,
TablerecPtr regTabPtr,
@@ -2173,8 +2236,8 @@ private:
Operationrec* regOperPtr);
bool storedProcedureAttrInfo(Signal* signal,
Operationrec* regOperPtr,
+ const Uint32* data,
Uint32 length,
- Uint32 firstWord,
bool copyProc);
//-----------------------------------------------------------------------------
@@ -2194,10 +2257,15 @@ private:
void insertTdArea(Uint32 sizeOfChunk, Uint32 tabDesRef, Uint32 list);
Uint32 itdaMergeTabDescr(Uint32 retRef, Uint32 retNo);
-//------------------------------------------------------------------------------------------------------
+ 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,
@@ -2246,89 +2314,75 @@ private:
Uint32 c_noOfFreePageRanges;
Uint32 cnoOfPageRangeRec;
-//------------------------------------------------------------------------------------------------------
-// Fixed Allocator
+//---------------------------------------------------------------
+// Variable Allocator
// Allocates and deallocates tuples of fixed size on a fragment.
-//------------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------
//
// Public methods
- bool allocTh(Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr,
- Uint32 pageType,
- Signal* signal,
- Uint32& pageOffset,
- PagePtr& pagePtr);
-
- void freeThSr(Tablerec* const regTabPtr,
- Page* const regPagePtr,
- Uint32 freePageOffset);
-
- void freeTh(Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr,
- Signal* signal,
- Page* const regPagePtr,
- Uint32 freePageOffset);
-
- void getThAtPageSr(Page* const regPagePtr,
- Uint32& pageOffset);
+
+ void init_list_sizes(void);
// Private methods
- void convertThPage(Uint32 Tupheadsize,
- Page* const regPagePtr);
- void getThAtPage(Fragrecord* const regFragPtr,
- Page* const regPagePtr,
- Signal* signal,
- Uint32& pageOffset);
+ Uint32 get_alloc_page(Fragrecord* const, Uint32);
+ void update_free_page_list(Fragrecord* const, Var_page*);
- void getEmptyPageThCopy(Fragrecord* const regFragPtr,
- Signal* signal,
- Page* const regPagePtr);
+#if 0
+ Uint32 calc_free_list(const Tablerec* regTabPtr, Uint32 sz) const {
+ return regTabPtr->m_disk_alloc_info.calc_page_free_bits(sz);
+ }
+#endif
- void getEmptyPageTh(Fragrecord* const regFragPtr,
- Signal* signal,
- Page* const regPagePtr);
+ Uint32 calculate_free_list_impl(Uint32) const ;
+ void remove_free_page(Fragrecord*, Var_page*, Uint32);
+ void insert_free_page(Fragrecord*, Var_page*, Uint32);
-//------------------------------------------------------------------------------------------------------
-// Temporary variables used for storing commonly used variables in certain modules
-//------------------------------------------------------------------------------------------------------
+//---------------------------------------------------------------
+// Fixed Allocator
+// Allocates and deallocates tuples of fixed size on a fragment.
+//---------------------------------------------------------------
+//
+// Public methods
+ Uint32* alloc_var_rec(Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*,
+ Uint32 base);
+ void free_var_part(Fragrecord*, Tablerec*, Var_part_ref, Uint32 chain);
+ void free_var_part(Fragrecord*, Tablerec*, Local_key*, Var_page*, Uint32 chain);
+
+ void validate_page(Tablerec*, Var_page* page);
+
+ Uint32* alloc_fix_rec(Fragrecord*, Tablerec*, Local_key*, Uint32 *);
+ void free_fix_rec(Fragrecord*, Tablerec*, Local_key*, Fix_page*);
+
+// Private methods
+ void convertThPage(Uint32 Tupheadsize,
+ Fix_page* const regPagePtr);
+
+ /**
+ * Return offset
+ */
+ Uint32 alloc_tuple_from_page(Fragrecord* const regFragPtr,
+ Fix_page* const 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
- Uint32 tCheckOffset;
- Uint32 tMaxRead;
- Uint32 tOutBufIndex;
- Uint32* tTupleHeader;
- bool tXfrmFlag;
-
-// updateAttributes module
- Uint32 tInBufIndex;
- Uint32 tInBufLen;
-
- Uint32 terrorCode;
-
//------------------------------------------------------------------------------------------------------
// Common stored variables. Variables that have a valid value always.
//------------------------------------------------------------------------------------------------------
- Uint32 cnoOfLcpRec;
- Uint32 cnoOfParallellUndoFiles;
- Uint32 cnoOfUndoPage;
-
Attrbufrec *attrbufrec;
Uint32 cfirstfreeAttrbufrec;
Uint32 cnoOfAttrbufrec;
Uint32 cnoFreeAttrbufrec;
- CheckpointInfo *checkpointInfo;
- Uint32 cfirstfreeLcp;
-
- DiskBufferSegmentInfo *diskBufferSegmentInfo;
- Uint32 cfirstfreePdx;
- Uint32 cnoOfConcurrentWriteOp;
-
Fragoperrec *fragoperrec;
Uint32 cfirstfreeFragopr;
Uint32 cnoOfFragoprec;
@@ -2339,39 +2393,18 @@ private:
HostBuffer *hostBuffer;
- LocalLogInfo *localLogInfo;
- Uint32 cnoOfLocalLogInfo;
-
- Uint32 cfirstfreeOprec;
- Operationrec *operationrec;
- Uint32 cnoOfOprec;
+ ArrayPool<Operationrec> c_operation_pool;
- Page *page;
+ Page *cpage;
Uint32 cnoOfPage;
Uint32 cnoOfAllocatedPages;
- PendingFileOpenInfo *pendingFileOpenInfo;
- Uint32 cfirstfreePfo;
- Uint32 cnoOfConcurrentOpenOp;
-
- RestartInfoRecord *restartInfoRecord;
- Uint32 cfirstfreeSri;
- Uint32 cnoOfRestartInfoRec;
-
Tablerec *tablerec;
Uint32 cnoOfTablerec;
TableDescriptor *tableDescriptor;
Uint32 cnoOfTabDescrRec;
-
- UndoPage *undoPage;
- Uint32 cfirstfreeUndoSeg;
- Int32 cnoFreeUndoSeg;
-
-
-
- Uint32 cnoOfDataPagesToDiskWithoutSynch;
-
+
Uint32 cdata[32];
Uint32 cdataPages[16];
Uint32 cpackedListIndex;
@@ -2385,7 +2418,6 @@ private:
Uint32 clqhUserpointer;
Uint32 cminusOne;
BlockReference cndbcntrRef;
- Uint32 cundoFileVersion;
BlockReference cownref;
Uint32 cownNodeId;
Uint32 czero;
@@ -2395,18 +2427,19 @@ private:
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;
- // Counters for num UNDO log records executed
- Uint32 cSrUndoRecords[9];
-
STATIC_CONST(MAX_PARALLELL_TUP_SRREQ = 2);
Uint32 c_sr_free_page_0;
-
+
Uint32 c_errorInsert4000TableId;
+ 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);
@@ -2419,48 +2452,277 @@ private:
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(Ptr<Var_page>*, Var_part_ref);
+ Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*);
+ Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*, Uint32 mm);
+
+ /**
+ * 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<GlobalPage>);
+
+ 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_update_free_space(Fragrecord*, Ptr<Page_request>,
+ DLList<Page_request>::Head list[],
+ Uint32 i, Uint32 sz);
+ void disk_page_update_free_space(Fragrecord*, PagePtr, Uint32 i,
+ Int32 uncommitted_delta,
+ Int32 extent_delta);
+
+ void disk_page_commit_callback(Signal*, Uint32 opPtrI, Uint32 page_id);
+
+ void disk_page_log_buffer_callback(Signal*, Uint32 opPtrI, 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);
+
+ /**
+ * Disk restart code
+ */
+public:
+ int disk_page_load_hook(Uint32 page_id);
+
+ void disk_page_unmap_callback(Uint32 page_id);
+
+ 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 old_bits, 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;
+ Local_key m_key;
+ };
+
+private:
+ void disk_restart_undo_next(Signal*);
+ void disk_restart_undo_lcp(Uint32, Uint32);
+ 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(Apply_undo*);
+
+#ifdef VM_TRACE
+ void verify_page_lists(Disk_alloc_info&);
+#else
+ void verify_page_lists(Disk_alloc_info&) {}
+#endif
+
+ void fix_commit_order(OperationrecPtr);
+ void commit_operation(Signal*, Uint32, Tuple_header*, Page*,
+ 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* const regFragPtr,
+ Tablerec* const 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);
};
inline
-bool Dbtup::isUndoLoggingNeeded(Fragrecord* const regFragPtr,
- Uint32 pageId)
+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;
+}
+
+inline
+Dbtup::TransState
+Dbtup::get_trans_state(Operationrec * const regOperPtr)
+{
+ return (Dbtup::TransState)regOperPtr->op_struct.trans_state;
+}
+
+inline
+void
+Dbtup::set_trans_state(Operationrec* const regOperPtr,
+ Dbtup::TransState trans_state)
+{
+ regOperPtr->op_struct.trans_state= (Uint32)trans_state;
+}
+
+inline
+Dbtup::TupleState
+Dbtup::get_tuple_state(Operationrec * const regOperPtr)
+{
+ return (Dbtup::TupleState)regOperPtr->op_struct.tuple_state;
+}
+
+inline
+void
+Dbtup::set_tuple_state(Operationrec* const 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 * const regOperPtr)
{
- if ((regFragPtr->checkpointVersion != RNIL) &&
- (pageId >= regFragPtr->minPageNotWrittenInCheckpoint) &&
- (pageId < regFragPtr->maxPageWrittenInCheckpoint)) {
- return true;
- }//if
- return false;
-}//Dbtup::isUndoLoggingNeeded()
+ return (Dbtup::ChangeMaskState)regOperPtr->op_struct.change_mask_state;
+}
inline
-bool Dbtup::isUndoLoggingActive(Fragrecord* const regFragPtr)
+void
+Dbtup::set_change_mask_state(Operationrec * const regOperPtr,
+ ChangeMaskState new_state)
{
- if (regFragPtr->checkpointVersion != RNIL) {
- return true;
- }//if
- return false;
-}//Dbtup::isUndoLoggingNeeded()
+ regOperPtr->op_struct.change_mask_state= (Uint32)new_state;
+}
inline
-bool Dbtup::isUndoLoggingBlocked(Fragrecord* const regFragPtr)
+void
+Dbtup::update_change_mask_info(KeyReqStruct * const req_struct,
+ Operationrec * const regOperPtr)
{
- if ((regFragPtr->checkpointVersion != RNIL) &&
- (cnoFreeUndoSeg < ZMIN_PAGE_LIMIT_TUPKEYREQ)) {
- return true;
- }//if
- return false;
-}//Dbtup::isUndoLoggingNeeded()
+ //Save change mask
+ if (req_struct->max_attr_id_updated == 0) {
+ set_change_mask_state(regOperPtr, USE_SAVED_CHANGE_MASK);
+ memcpy(regOperPtr->saved_change_mask, &req_struct->changeMask,
+ sizeof(regOperPtr->saved_change_mask));
+ } 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
-bool Dbtup::isPageUndoLogged(Fragrecord* const regFragPtr,
- Uint32 pageId)
+Uint32*
+Dbtup::get_ptr(Var_part_ref ref)
{
- if ((pageId >= regFragPtr->minPageNotWrittenInCheckpoint) &&
- (pageId < regFragPtr->maxPageWrittenInCheckpoint)) {
- return true;
- }//if
- return false;
-}//Dbtup::isUndoLoggingNeeded()
+ Ptr<Var_page> tmp;
+ return get_ptr(&tmp, ref);
+}
+
+inline
+Uint32*
+Dbtup::get_ptr(Ptr<Var_page>* pagePtr, Var_part_ref ref)
+{
+ PagePtr tmp;
+ Uint32 page_idx= ref.m_ref & MAX_TUPLES_PER_PAGE;
+ tmp.i= ref.m_ref >> MAX_TUPLES_BITS;
+
+ ptrCheckGuard(tmp, cnoOfPage, cpage);
+ memcpy(pagePtr, &tmp, sizeof(tmp));
+ return ((Var_page*)tmp.p)->get_ptr(page_idx);
+}
+
+inline
+Uint32*
+Dbtup::get_ptr(PagePtr* pagePtr,
+ const Local_key* key, const Tablerec* regTabPtr)
+{
+ PagePtr tmp;
+ tmp.i= key->m_page_no;
+ ptrCheckGuard(tmp, cnoOfPage, cpage);
+ memcpy(pagePtr, &tmp, sizeof(tmp));
+
+ if(regTabPtr->m_attributes[MM].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[MM].m_fix_header_size);
+}
+
+inline
+Uint32*
+Dbtup::get_ptr(PagePtr* pagePtr,
+ const Local_key* key, const Tablerec* regTabPtr, Uint32 mm)
+{
+ PagePtr tmp;
+ tmp.i= key->m_page_no;
+ if(mm == MM)
+ {
+ ptrCheckGuard(tmp, cnoOfPage, cpage);
+ }
+ else
+ {
+ tmp.p= (Page*)m_global_page_pool.getPtr(tmp.i);
+ }
+ memcpy(pagePtr, &tmp, sizeof(tmp));
+
+ if(regTabPtr->m_attributes[mm].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[mm].m_fix_header_size);
+}
+
+NdbOut&
+operator<<(NdbOut&, const Dbtup::Tablerec&);
#endif
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
index e9043a8b52d..2b1e43f80ec 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
@@ -25,14 +25,14 @@
void Dbtup::freeAllAttrBuffers(Operationrec* const regOperPtr)
{
- if (regOperPtr->storedProcedureId == ZNIL) {
+ if (regOperPtr->storedProcedureId == RNIL) {
ljam();
freeAttrinbufrec(regOperPtr->firstAttrinbufrec);
} else {
+ ljam();
StoredProcPtr storedPtr;
c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->storedProcedureId);
ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
- ljam();
storedPtr.p->storedCounter--;
regOperPtr->storedProcedureId = ZNIL;
}//if
@@ -58,9 +58,9 @@ void Dbtup::freeAttrinbufrec(Uint32 anAttrBuf)
cnoFreeAttrbufrec = RnoFree;
}//Dbtup::freeAttrinbufrec()
-/* ----------------------------------------------------------------- */
-/* ----------- ABORT THIS PART OF THE TRANSACTION ------------------ */
-/* ----------------------------------------------------------------- */
+/**
+ * Abort abort this operation and all after (nextActiveOp's)
+ */
void Dbtup::execTUP_ABORTREQ(Signal* signal)
{
OperationrecPtr regOperPtr;
@@ -69,172 +69,120 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
ljamEntry();
regOperPtr.i = signal->theData[0];
- ptrCheckGuard(regOperPtr, cnoOfOprec, operationrec);
- ndbrequire((regOperPtr.p->transstate == STARTED) ||
- (regOperPtr.p->transstate == TOO_MUCH_AI) ||
- (regOperPtr.p->transstate == ERROR_WAIT_TUPKEYREQ) ||
- (regOperPtr.p->transstate == IDLE));
- if (regOperPtr.p->optype == ZREAD) {
+ 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) {
ljam();
freeAllAttrBuffers(regOperPtr.p);
- initOpConnection(regOperPtr.p, 0);
+ initOpConnection(regOperPtr.p);
return;
}//if
- regTabPtr.i = regOperPtr.p->tableRef;
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
regFragPtr.i = regOperPtr.p->fragmentPtr;
ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- // XXX should be integrated into the code that comes after
- if (!regTabPtr.p->tuxCustomTriggers.isEmpty() &&
- regOperPtr.p->tupleState == NO_OTHER_OP) {
+ regTabPtr.i = regFragPtr.p->fragTableId;
+ ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
+
+ if (get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
+ {
ljam();
- executeTuxAbortTriggers(signal,
- regOperPtr.p,
- regTabPtr.p);
+ if (!regTabPtr.p->tuxCustomTriggers.isEmpty())
+ executeTuxAbortTriggers(signal,
+ regOperPtr.p,
+ regFragPtr.p,
+ regTabPtr.p);
+
OperationrecPtr loopOpPtr;
- loopOpPtr.i = regOperPtr.p->prevActiveOp;
+ loopOpPtr.i = regOperPtr.p->nextActiveOp;
while (loopOpPtr.i != RNIL) {
ljam();
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- if (loopOpPtr.p->tupleState != ALREADY_ABORTED) {
+ c_operation_pool.getPtr(loopOpPtr);
+ if (get_tuple_state(loopOpPtr.p) != TUPLE_ALREADY_ABORTED &&
+ !regTabPtr.p->tuxCustomTriggers.isEmpty()) {
ljam();
executeTuxAbortTriggers(signal,
loopOpPtr.p,
+ regFragPtr.p,
regTabPtr.p);
}
- loopOpPtr.i = loopOpPtr.p->prevActiveOp;
+ set_tuple_state(loopOpPtr.p, TUPLE_ALREADY_ABORTED);
+ loopOpPtr.i = loopOpPtr.p->nextActiveOp;
}
}
- Uint32 prevActiveOp = regOperPtr.p->prevActiveOp;
- removeActiveOpList(regOperPtr.p);
- if (regOperPtr.p->tupleState == NO_OTHER_OP) {
- if (prevActiveOp == RNIL) {
- ljam();
- abortUpdate(signal, regOperPtr.p, regFragPtr.p, regTabPtr.p);
- } else { //prevActiveOp != RNIL
- setTupleStateOnPreviousOps(prevActiveOp);
- if (regOperPtr.p->optype == ZDELETE) {
- ljam();
- OperationrecPtr prevOpPtr;
- prevOpPtr.i = prevActiveOp;
- ptrCheckGuard(prevOpPtr, cnoOfOprec, operationrec);
- ndbrequire(prevOpPtr.p->realPageIdC != RNIL);
- ndbrequire(prevOpPtr.p->optype == ZINSERT);
- abortUpdate(signal, prevOpPtr.p, regFragPtr.p, regTabPtr.p);
- } else {
- jam();
- abortUpdate(signal, regOperPtr.p, regFragPtr.p, regTabPtr.p);
- }//if
- }//if
- } else {
- ndbrequire(regOperPtr.p->tupleState == ALREADY_ABORTED);
- commitUpdate(signal, regOperPtr.p, regFragPtr.p, regTabPtr.p);
- }//if
- initOpConnection(regOperPtr.p, regFragPtr.p);
-}//execTUP_ABORTREQ()
-
-void Dbtup::setTupleStateOnPreviousOps(Uint32 prevOpIndex)
-{
- OperationrecPtr loopOpPtr;
- loopOpPtr.i = prevOpIndex;
- do {
- ljam();
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- loopOpPtr.p->tupleState = ALREADY_ABORTED;
- loopOpPtr.i = loopOpPtr.p->prevActiveOp;
- } while (loopOpPtr.i != RNIL);
-}//Dbtup::setTupleStateOnPreviousOps()
-
-/* ---------------------------------------------------------------- */
-/* ------------ PERFORM AN ABORT OF AN UPDATE OPERATION ----------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::abortUpdate(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr)
-{
- /* RESTORE THE ORIGINAL DATA */
- /* THE OPER_PTR ALREADY CONTAINS BOTH THE PAGE AND THE COPY PAGE */
- if (regOperPtr->realPageIdC != RNIL) {
- ljam();
- /***********************/
- /* CHECKPOINT SPECIFIC */
- /***********************/
- if (isUndoLoggingNeeded(regFragPtr, regOperPtr->fragPageIdC)) {
- if (regOperPtr->undoLogged) {
- ljam();
-/* ---------------------------------------------------------------- */
-/* THE UPDATE WAS MADE AFTER THE LOCAL CHECKPOINT STARTED. */
-/* THUS THE ORIGINAL TUPLE WILL BE RESTORED BY A LOG RECORD */
-/* CREATED WHEN UPDATING. THUS IT IS ENOUGH TO LOG THE UNDO */
-/* OF THE COPY RELEASE == INSERT THE COPY TUPLE HEADER WITH */
-/* NO DATA. */
-/* ---------------------------------------------------------------- */
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_INSERT_TH_NO_DATA,
- regOperPtr->fragPageIdC,
- regOperPtr->pageIndexC,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- } else {
- ljam();
-/* ---------------------------------------------------------------- */
-/* THE UPDATE WAS MADE BEFORE THE LOCAL CHECKPOINT STARTED. */
-/* THE TUPLE WILL THUS BE RESTORED BY COPYING FROM THE COPY. */
-/* THUS WE DO NOT NEED TO RESTORE THE DATA IN THE ORIGINAL. */
-/* WE DO HOWEVER NEED TO ENSURE THAT THE COPY CONTAINS THE */
-/* CORRECT DATA. */
-/* ---------------------------------------------------------------- */
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_INSERT_TH,
- regOperPtr->fragPageIdC,
- regOperPtr->pageIndexC,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- cprAddData(signal,
- regFragPtr,
- regOperPtr->realPageIdC,
- regTabPtr->tupheadsize,
- regOperPtr->pageOffsetC);
- }//if
- }//if
- Uint32 rpid = regOperPtr->realPageId;
- Uint32 rpid_copy = regOperPtr->realPageIdC;
- Uint32 offset = regOperPtr->pageOffset;
- Uint32 offset_copy = regOperPtr->pageOffsetC;
- Uint32 tuple_size = regTabPtr->tupheadsize;
- Uint32 end = offset + tuple_size;
- Uint32 end_copy = offset_copy + tuple_size;
- ndbrequire(rpid < cnoOfPage &&
- rpid_copy < cnoOfPage &&
- end <= ZWORDS_ON_PAGE &&
- end_copy <= ZWORDS_ON_PAGE);
- void* Tdestination = (void*)&page[rpid].pageWord[offset + 1];
- const void* Tsource = (void*)&page[rpid_copy].pageWord[offset_copy + 1];
- MEMCOPY_NO_WORDS(Tdestination, Tsource, (tuple_size - 1));
+ PagePtr page;
+ Tuple_header *tuple_ptr= (Tuple_header*)
+ get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
+
+ 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)
{
- PagePtr pagePtr;
-
- pagePtr.i = rpid_copy;
- ptrAss(pagePtr, page);
- freeTh(regFragPtr,
- regTabPtr,
- signal,
- pagePtr.p,
- offset_copy);
+ 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);
}
- regOperPtr->realPageIdC = RNIL;
- regOperPtr->fragPageIdC = RNIL;
- regOperPtr->pageOffsetC = ZNIL;
- regOperPtr->pageIndexC = ZNIL;
- }//if
-}//Dbtup::abortUpdate()
+
+ Uint32 bits= copy->m_header_bits;
+ if(! (bits & Tuple_header::ALLOC))
+ {
+ if(bits & Tuple_header::MM_GROWN)
+ {
+ ndbout_c("abort grow");
+ Var_page *pageP= (Var_page*)page.p;
+ Uint32 idx= regOperPtr.p->m_tuple_location.m_page_idx, sz;
+ Uint32 mm_vars= regTabPtr.p->m_attributes[MM].m_no_of_varsize;
+ Uint32 *var_part;
+ if(! (tuple_ptr->m_header_bits & Tuple_header::CHAINED_ROW))
+ {
+ var_part= tuple_ptr->get_var_part_ptr(regTabPtr.p);
+ sz= Tuple_header::HeaderSize +
+ regTabPtr.p->m_offsets[MM].m_fix_header_size;
+ }
+ else
+ {
+ Ptr<Var_page> vpage;
+ Uint32 ref= * tuple_ptr->get_var_part_ptr(regTabPtr.p);
+ Local_key tmp;
+ tmp=ref;
+
+ sz= 0;
+ idx= tmp.m_page_idx;
+ var_part= get_ptr(&vpage, *(Var_part_ref*)&ref);
+ pageP= vpage.p;
+ }
+ Uint32 len= pageP->get_entry_len(idx) & ~Var_page::CHAIN;
+ 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, pageP);
+ }
+ else if(bits & Tuple_header::MM_SHRINK)
+ {
+ ndbout_c("abort shrink");
+ }
+ }
+ }
+
+ 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 **************** */
@@ -242,76 +190,12 @@ void Dbtup::abortUpdate(Signal* signal,
int Dbtup::TUPKEY_abort(Signal* signal, int error_type)
{
switch(error_type) {
- case 0:
- ndbrequire(false);
- break;
-// Not used currently
-
case 1:
//tmupdate_alloc_error:
+ terrorCode= ZMEM_NOMEM_ERROR;
ljam();
break;
- case 2:
- ndbrequire(false);
- break;
-// Not used currently
-
- break;
-
- case 3:
-//tmupdate_alloc_error:
- ljam();
- break;
-
- case 4:
-//Trying to read non-existing attribute identity
- ljam();
- terrorCode = ZATTRIBUTE_ID_ERROR;
- break;
-
- case 6:
- ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- break;
-
- case 7:
- ljam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
- break;
-
- case 8:
- ljam();
- terrorCode = ZATTR_INTERPRETER_ERROR;
- break;
-
- case 9:
- ljam();
-//Trying to read non-existing attribute identity
- ljam();
- terrorCode = ZATTRIBUTE_ID_ERROR;
- break;
-
- case 11:
- ljam();
- terrorCode = ZATTR_INTERPRETER_ERROR;
- break;
-
- case 12:
- ljam();
- ndbrequire(false);
- break;
-
- case 13:
- ljam();
- ndbrequire(false);
- break;
-
- case 14:
- ljam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
case 15:
ljam();
terrorCode = ZREGISTER_INIT_ERROR;
@@ -327,11 +211,6 @@ int Dbtup::TUPKEY_abort(Signal* signal, int error_type)
terrorCode = ZNO_ILLEGAL_NULL_ATTR;
break;
- case 18:
- ljam();
- terrorCode = ZNOT_NULL_ATTR;
- break;
-
case 19:
ljam();
terrorCode = ZTRY_TO_UPDATE_ERROR;
@@ -342,11 +221,6 @@ int Dbtup::TUPKEY_abort(Signal* signal, int error_type)
terrorCode = ZREGISTER_INIT_ERROR;
break;
- case 21:
- ljam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
case 22:
ljam();
terrorCode = ZTOTAL_LEN_ERROR;
@@ -362,11 +236,6 @@ int Dbtup::TUPKEY_abort(Signal* signal, int error_type)
terrorCode = ZREGISTER_INIT_ERROR;
break;
- case 25:
- ljam();
- terrorCode = ZREGISTER_INIT_ERROR;
- break;
-
case 26:
ljam();
terrorCode = ZREGISTER_INIT_ERROR;
@@ -416,58 +285,74 @@ int Dbtup::TUPKEY_abort(Signal* signal, int error_type)
terrorCode = ZTOO_MANY_INSTRUCTIONS_ERROR;
break;
- case 36:
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- break;
-
- case 37:
- ljam();
- terrorCode = ZTEMPORARY_RESOURCE_FAILURE;
- break;
-
case 38:
ljam();
terrorCode = ZTEMPORARY_RESOURCE_FAILURE;
break;
case 39:
- ljam();
- if (operPtr.p->transstate == TOO_MUCH_AI) {
+ if (get_trans_state(operPtr.p) == TRANS_TOO_MUCH_AI) {
ljam();
terrorCode = ZTOO_MUCH_ATTRINFO_ERROR;
- } else if (operPtr.p->transstate == ERROR_WAIT_TUPKEYREQ) {
+ } else if (get_trans_state(operPtr.p) == TRANS_ERROR_WAIT_TUPKEYREQ) {
ljam();
terrorCode = ZSEIZE_ATTRINBUFREC_ERROR;
} else {
ndbrequire(false);
}//if
break;
-
default:
ndbrequire(false);
break;
}//switch
tupkeyErrorLab(signal);
return -1;
-}//Dbtup::TUPKEY_abort()
+}
+
+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);
- freeAllAttrBuffers(regOperPtr);
- abortUpdate(signal, regOperPtr, fragptr.p, tabptr.p);
- removeActiveOpList(regOperPtr);
- initOpConnection(regOperPtr, fragptr.p);
- regOperPtr->transstate = IDLE;
- regOperPtr->tupleState = NO_OTHER_OP;
- TupKeyRef * const tupKeyRef = (TupKeyRef *)signal->getDataPtrSend();
+ 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)
+ {
+ c_lgman->free_log_space(fragPtr.p->m_logfile_group_id,
+ regOperPtr->m_undo_buffer_space);
+ }
+
+ PagePtr tmp;
+ Uint32 *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(regOperPtr->userblockref, GSN_TUPKEYREF, signal,
+ sendSignal(DBLQH_REF, GSN_TUPKEYREF, signal,
TupKeyRef::SignalLength, JBB);
- return;
-}//Dbtup::tupkeyErrorLab()
+}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
index 0c825af9f4b..328fa98b593 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp
@@ -28,46 +28,46 @@ void Dbtup::execSEND_PACKED(Signal* signal)
{
Uint16 hostId;
Uint32 i;
- Uint32 TpackedListIndex = cpackedListIndex;
+ Uint32 TpackedListIndex= cpackedListIndex;
ljamEntry();
- for (i = 0; i < TpackedListIndex; i++) {
+ for (i= 0; i < TpackedListIndex; i++) {
ljam();
- hostId = cpackedList[i];
+ hostId= cpackedList[i];
ndbrequire((hostId - 1) < (MAX_NODES - 1)); // Also check not zero
- Uint32 TpacketTA = hostBuffer[hostId].noOfPacketsTA;
+ Uint32 TpacketTA= hostBuffer[hostId].noOfPacketsTA;
if (TpacketTA != 0) {
ljam();
- BlockReference TBref = numberToRef(API_PACKED, hostId);
- Uint32 TpacketLen = hostBuffer[hostId].packetLenTA;
+ 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;
- }//if
- hostBuffer[hostId].inPackedList = false;
+ hostBuffer[hostId].noOfPacketsTA= 0;
+ hostBuffer[hostId].packetLenTA= 0;
+ }
+ hostBuffer[hostId].inPackedList= false;
}//for
- cpackedListIndex = 0;
-}//Dbtup::execSEND_PACKED()
+ cpackedListIndex= 0;
+}
void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
Uint32 Tlen)
{
- if(Tlen == 3)
+ if (Tlen == 3)
return;
- Uint32 hostId = refToNode(aRef);
- Uint32 Theader = ((refToBlock(aRef) << 16)+(Tlen-3));
+ 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];
+ 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);
+ BlockReference TBref= numberToRef(API_PACKED, hostId);
if ((Tlen + TpacketLen + 1) <= 25) {
// ----------------------------------------------------------------
@@ -81,14 +81,14 @@ void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
// 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),
+ 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;
+ TpacketLen= 0;
+ TnoOfPackets= 0;
} else {
// ----------------------------------------------------------------
// The buffer is full but at least two packets. Send those in
@@ -98,70 +98,71 @@ void Dbtup::bufferTRANSID_AI(Signal* signal, BlockReference aRef,
&hostBuffer[hostId].packetBufferTA[0],
TpacketLen);
sendSignal(TBref, GSN_TRANSID_AI, signal, TpacketLen, JBB);
- TpacketLen = 0;
- TnoOfPackets = 0;
- }//if
+ 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;
+ 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);
-}//Dbtup::bufferTRANSID_AI()
+}
void Dbtup::updatePackedList(Signal* signal, Uint16 hostId)
{
if (hostBuffer[hostId].inPackedList == false) {
- Uint32 TpackedListIndex = cpackedListIndex;
+ Uint32 TpackedListIndex= cpackedListIndex;
ljam();
- hostBuffer[hostId].inPackedList = true;
- cpackedList[TpackedListIndex] = hostId;
- cpackedListIndex = TpackedListIndex + 1;
- }//if
-}//Dbtup::updatePackedList()
+ 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 * const regOperPtr)
{
if(ToutBufIndex == 0)
return;
+
+ const BlockReference recBlockref= req_struct->rec_blockref;
+ const Uint32 block= refToBlock(recBlockref);
+ const Uint32 nodeId= refToNode(recBlockref);
- const BlockReference recBlockref = regOperPtr->recBlockref;
- const Uint32 sig0 = regOperPtr->tcOperationPtr;
- const Uint32 sig1 = regOperPtr->transid1;
- const Uint32 sig2 = regOperPtr->transid2;
-
- 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;
- 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));
- const Uint32 TpacketTA = hostBuffer[nodeId].noOfPacketsTA;
- const Uint32 TpacketLen = hostBuffer[nodeId].packetLenTA;
-
if (ERROR_INSERTED(4006) && (nodeId != getOwnNodeId())){
// Use error insert to turn routing on
ljam();
- connectedToNode = false;
+ connectedToNode= false;
}
- TransIdAI * transIdAI = (TransIdAI *)signal->getDataPtrSend();
- transIdAI->connectPtr = sig0;
- transIdAI->transId[0] = sig1;
- transIdAI->transId[1] = sig2;
-
+ 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
@@ -172,7 +173,7 @@ void Dbtup::sendReadAttrinfo(Signal* signal,
/**
* Send long sig
*/
- if(ToutBufIndex >= 22 && is_api && !old_dest) {
+ if (ToutBufIndex >= 22 && is_api && !old_dest) {
ljam();
/**
* Flush buffer so that order is maintained
@@ -191,8 +192,8 @@ void Dbtup::sendReadAttrinfo(Signal* signal,
transIdAI->transId[1] = sig2;
}//if
LinearSectionPtr ptr[3];
- ptr[0].p = &signal->theData[25];
- ptr[0].sz = ToutBufIndex;
+ ptr[0].p= &signal->theData[25];
+ ptr[0].sz= ToutBufIndex;
sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3, JBB, ptr, 1);
return;
}
@@ -205,14 +206,14 @@ void Dbtup::sendReadAttrinfo(Signal* signal,
ljam();
bufferTRANSID_AI(signal, recBlockref, 3+ToutBufIndex);
return;
- }//if
+ }
#endif
/**
* rest -> old send sig
*/
- Uint32 * src = signal->theData+25;
- if(ToutBufIndex >= 22){
+ Uint32 * src= signal->theData+25;
+ if (ToutBufIndex >= 22){
do {
ljam();
MEMCOPY_NO_WORDS(&signal->theData[3], src, 22);
@@ -222,7 +223,7 @@ void Dbtup::sendReadAttrinfo(Signal* signal,
} while(ToutBufIndex >= 22);
}
- if(ToutBufIndex > 0){
+ if (ToutBufIndex > 0){
ljam();
MEMCOPY_NO_WORDS(&signal->theData[3], src, ToutBufIndex);
sendSignal(recBlockref, GSN_TRANSID_AI, signal, 3+ToutBufIndex, JBB);
@@ -239,14 +240,14 @@ void Dbtup::sendReadAttrinfo(Signal* signal,
* to the receiving node we want to send the signals
* routed via the node that controls this read
*/
- Uint32 routeBlockref = regOperPtr->coordinatorTC;
+ Uint32 routeBlockref= req_struct->TC_ref;
- if(true){ // TODO is_api && !old_dest){
+ if (true){ // TODO is_api && !old_dest){
ljam();
- transIdAI->attrData[0] = recBlockref;
+ transIdAI->attrData[0]= recBlockref;
LinearSectionPtr ptr[3];
- ptr[0].p = &signal->theData[25];
- ptr[0].sz = ToutBufIndex;
+ ptr[0].p= &signal->theData[25];
+ ptr[0].sz= ToutBufIndex;
sendSignal(routeBlockref, GSN_TRANSID_AI_R, signal, 4, JBB, ptr, 1);
return;
}
@@ -256,21 +257,21 @@ void Dbtup::sendReadAttrinfo(Signal* signal,
* 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;
+ Uint32 tot= ToutBufIndex;
+ Uint32 sent= 0;
+ Uint32 maxLen= TransIdAI::DataLength - 1;
while (sent < tot) {
ljam();
- Uint32 dataLen = (tot - sent > maxLen) ? maxLen : tot - sent;
- Uint32 sigLen = dataLen + TransIdAI::HeaderLength + 1;
+ 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;
+ transIdAI->attrData[dataLen]= recBlockref;
sendSignal(routeBlockref, GSN_TRANSID_AI_R,
signal, sigLen, JBB);
sent += dataLen;
}
-}//Dbtup::sendReadAttrinfo()
+}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
index 470b98fd04c..b981d4d65c1 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
@@ -20,247 +20,412 @@
#include <ndb_limits.h>
#include <pc.hpp>
#include <signaldata/TupCommit.hpp>
+#include "../dblqh/Dblqh.hpp"
#define ljam() { jamLine(5000 + __LINE__); }
#define ljamEntry() { jamEntryLine(5000 + __LINE__); }
+void Dbtup::execTUP_DEALLOCREQ(Signal* signal)
+{
+ TablerecPtr regTabPtr;
+ FragrecordPtr regFragPtr;
+ Uint32 frag_page_id, frag_id;
+
+ ljamEntry();
+
+ 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) == ~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);
+
+ if (regTabPtr.p->m_attributes[MM].m_no_of_varsize)
+ {
+ ljam();
+
+ if(ptr->m_header_bits & Tuple_header::CHAINED_ROW)
+ {
+ free_var_part(regFragPtr.p, regTabPtr.p,
+ *(Var_part_ref*)ptr->get_var_part_ptr(regTabPtr.p),
+ Var_page::CHAIN);
+ }
+ free_var_part(regFragPtr.p, regTabPtr.p, &tmp, (Var_page*)pagePtr.p, 0);
+ } 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];
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- while (loopOpPtr.p->nextActiveOp != RNIL) {
+ loopOpPtr.i= signal->theData[0];
+ Uint32 gci= signal->theData[1];
+ c_operation_pool.getPtr(loopOpPtr);
+ while (loopOpPtr.p->prevActiveOp != RNIL) {
ljam();
- loopOpPtr.i = loopOpPtr.p->nextActiveOp;
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- }//while
+ loopOpPtr.i= loopOpPtr.p->prevActiveOp;
+ c_operation_pool.getPtr(loopOpPtr);
+ }
do {
- Uint32 blockNo = refToBlock(loopOpPtr.p->userblockref);
- ndbrequire(loopOpPtr.p->transstate == STARTED);
- signal->theData[0] = loopOpPtr.p->userpointer;
- signal->theData[1] = gci;
- if (loopOpPtr.p->prevActiveOp == RNIL) {
+ ndbrequire(get_trans_state(loopOpPtr.p) == TRANS_STARTED);
+ signal->theData[0]= loopOpPtr.p->userpointer;
+ signal->theData[1]= gci;
+ if (loopOpPtr.p->nextActiveOp == RNIL) {
ljam();
- EXECUTE_DIRECT(blockNo, GSN_LQH_WRITELOG_REQ, signal, 2);
+ EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 2);
return;
- }//if
+ }
ljam();
- EXECUTE_DIRECT(blockNo, GSN_LQH_WRITELOG_REQ, signal, 2);
+ EXECUTE_DIRECT(DBLQH, GSN_LQH_WRITELOG_REQ, signal, 2);
jamEntry();
- loopOpPtr.i = loopOpPtr.p->prevActiveOp;
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
+ loopOpPtr.i= loopOpPtr.p->nextActiveOp;
+ c_operation_pool.getPtr(loopOpPtr);
} while (true);
-}//Dbtup::execTUP_WRITELOG_REQ()
+}
-void Dbtup::execTUP_DEALLOCREQ(Signal* signal)
+void Dbtup::removeActiveOpList(Operationrec* const regOperPtr,
+ Tuple_header *tuple_ptr)
{
- TablerecPtr regTabPtr;
- FragrecordPtr regFragPtr;
-
- jamEntry();
+ OperationrecPtr raoOperPtr;
+
+ /**
+ * Release copy tuple
+ */
+ if(regOperPtr->op_struct.op_type != ZDELETE &&
+ !regOperPtr->m_copy_tuple_location.isNull())
+ 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) {
+ ljam();
+ raoOperPtr.i= regOperPtr->nextActiveOp;
+ c_operation_pool.getPtr(raoOperPtr);
+ raoOperPtr.p->prevActiveOp= regOperPtr->prevActiveOp;
+ } else {
+ ljam();
+ tuple_ptr->m_operation_ptr_i = regOperPtr->prevActiveOp;
+ }
+ if (regOperPtr->prevActiveOp != RNIL) {
+ ljam();
+ raoOperPtr.i= regOperPtr->prevActiveOp;
+ c_operation_pool.getPtr(raoOperPtr);
+ raoOperPtr.p->nextActiveOp= regOperPtr->nextActiveOp;
+ }
+ regOperPtr->prevActiveOp= RNIL;
+ regOperPtr->nextActiveOp= RNIL;
+ }
+}
- Uint32 fragId = signal->theData[0];
- regTabPtr.i = signal->theData[1];
- Uint32 fragPageId = signal->theData[2];
- Uint32 pageIndex = signal->theData[3];
+/* ---------------------------------------------------------------- */
+/* 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->m_undo_buffer_space= 0;
+}
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
- getFragmentrec(regFragPtr, fragId, regTabPtr.p);
- ndbrequire(regFragPtr.p != NULL);
-
- PagePtr pagePtr;
- pagePtr.i = getRealpid(regFragPtr.p, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageIndexScaled = pageIndex >> 1;
- ndbrequire((pageIndex & 1) == 0);
- Uint32 pageOffset = ZPAGE_HEADER_SIZE +
- (regTabPtr.p->tupheadsize * pageIndexScaled);
-//---------------------------------------------------
-/* --- Deallocate a tuple as requested by ACC --- */
-//---------------------------------------------------
- if (isUndoLoggingNeeded(regFragPtr.p, fragPageId)) {
- ljam();
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_INSERT_TH,
- fragPageId,
- pageIndex,
- regTabPtr.i,
- fragId,
- regFragPtr.p->checkpointVersion);
- cprAddData(signal,
- regFragPtr.p,
- pagePtr.i,
- regTabPtr.p->tupheadsize,
- pageOffset);
- }//if
+void
+Dbtup::dealloc_tuple(Signal* signal,
+ Uint32 gci,
+ Page* page,
+ Tuple_header* ptr,
+ Operationrec* regOperPtr,
+ Fragrecord* regFragPtr,
+ Tablerec* regTabPtr)
+{
+ if (ptr->m_header_bits & Tuple_header::DISK_PART)
{
- freeTh(regFragPtr.p,
- regTabPtr.p,
- signal,
- pagePtr.p,
- pageOffset);
+ Local_key disk;
+ memcpy(&disk, ptr->get_disk_ref_ptr(regTabPtr), sizeof(disk));
+ Ptr<GlobalPage> disk_page;
+ m_global_page_pool.getPtr(disk_page,
+ regOperPtr->m_commit_disk_callback_page);
+ disk_page_free(signal, regTabPtr, regFragPtr,
+ &disk, *(PagePtr*)&disk_page, gci);
}
}
-/* ---------------------------------------------------------------- */
-/* ------------ PERFORM A COMMIT ON AN UPDATE OPERATION ---------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::commitUpdate(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr)
+static
+inline
+bool
+operator>=(const Local_key& key1, const Local_key& key2)
{
- if (regOperPtr->realPageIdC != RNIL) {
- if (isUndoLoggingNeeded(regFragPtr, regOperPtr->fragPageIdC)) {
-/* ------------------------------------------------------------------------ */
-/* IF THE COPY WAS CREATED WITHIN THIS CHECKPOINT WE ONLY HAVE */
-/* TO LOG THE CREATION OF THE COPY. IF HOWEVER IT WAS CREATED BEFORE SAVE */
-/* THIS CHECKPOINT, WE HAVE TO THE DATA AS WELL. */
-/* ------------------------------------------------------------------------ */
- if (regOperPtr->undoLogged) {
- ljam();
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_INSERT_TH_NO_DATA,
- regOperPtr->fragPageIdC,
- regOperPtr->pageIndexC,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- } else {
- ljam();
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_INSERT_TH,
- regOperPtr->fragPageIdC,
- regOperPtr->pageIndexC,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- cprAddData(signal,
- regFragPtr,
- regOperPtr->realPageIdC,
- regTabPtr->tupheadsize,
- regOperPtr->pageOffsetC);
- }//if
- }//if
-
- PagePtr copyPagePtr;
- copyPagePtr.i = regOperPtr->realPageIdC;
- ptrCheckGuard(copyPagePtr, cnoOfPage, page);
- freeTh(regFragPtr,
- regTabPtr,
- signal,
- copyPagePtr.p,
- (Uint32)regOperPtr->pageOffsetC);
- regOperPtr->realPageIdC = RNIL;
- regOperPtr->fragPageIdC = RNIL;
- regOperPtr->pageOffsetC = ZNIL;
- regOperPtr->pageIndexC = ZNIL;
- }//if
-}//Dbtup::commitUpdate()
+ 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::commitSimple(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr)
+Dbtup::commit_operation(Signal* signal,
+ Uint32 gci,
+ Tuple_header* tuple_ptr,
+ Page* page,
+ Operationrec* regOperPtr,
+ Fragrecord* regFragPtr,
+ Tablerec* regTabPtr)
{
- operPtr.p = regOperPtr;
- fragptr.p = regFragPtr;
- tabptr.p = regTabPtr;
+ ndbassert(regOperPtr->op_struct.op_type != ZDELETE);
+
+ 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 fix_size= regTabPtr->m_offsets[MM].m_fix_header_size;
+ Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
+ if(mm_vars == 0)
+ {
+ memcpy(tuple_ptr, copy, 4*fix_size);
+ //ndbout_c("commit: memcpy %p %p %d", tuple_ptr, copy, 4*fix_size);
+ disk_ptr= (Tuple_header*)(((Uint32*)copy)+fix_size);
+ }
+ else if(bits & Tuple_header::CHAINED_ROW)
+ {
+ Uint32 *ref= tuple_ptr->get_var_part_ptr(regTabPtr);
+ memcpy(tuple_ptr, copy, 4*(Tuple_header::HeaderSize+fix_size));
+
+ Local_key tmp; tmp= *ref;
+ if(0) printf("%p %d %d (%d bytes) - ref: %x ", tuple_ptr,
+ regOperPtr->m_tuple_location.m_page_no,
+ regOperPtr->m_tuple_location.m_page_idx,
+ 4*(Tuple_header::HeaderSize+fix_size),
+ *ref);
+ Ptr<Var_page> vpagePtr;
+ Uint32 *dst= get_ptr(&vpagePtr, *(Var_part_ref*)ref);
+ Uint32 *src= copy->get_var_part_ptr(regTabPtr);
+ Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)src)[mm_vars]);
+ ndbassert(4*vpagePtr.p->get_entry_len(tmp.m_page_idx) >= sz);
+ memcpy(dst, src, sz);
+ if(0) printf("ptr: %p %d ref: %x - chain commit", dst, sz, *ref);
+ copy_bits |= Tuple_header::CHAINED_ROW;
+
+ if(0)
+ {
+ for(Uint32 i = 0; i<((sz+3)>>2); i++)
+ printf(" %.8x", src[i]);
+ printf("\n");
+ }
+
+ if(copy_bits & Tuple_header::MM_SHRINK)
+ {
+ if(0) printf(" - shrink %d -> %d - ",
+ vpagePtr.p->get_entry_len(tmp.m_page_idx), (sz + 3) >> 2);
+ vpagePtr.p->shrink_entry(tmp.m_page_idx, (sz + 3) >> 2);
+ if(0)ndbout_c("%p->shrink_entry(%d, %d)", vpagePtr.p, tmp.m_page_idx,
+ (sz + 3) >> 2);
+ update_free_page_list(regFragPtr, vpagePtr.p);
+ }
+ if(0) ndbout_c("");
+ disk_ptr = (Tuple_header*)
+ (((Uint32*)copy)+Tuple_header::HeaderSize+fix_size+((sz + 3) >> 2));
+ }
+ else
+ {
+ Uint32 *var_part= copy->get_var_part_ptr(regTabPtr);
+ Uint32 sz= Tuple_header::HeaderSize + fix_size +
+ ((((mm_vars + 1) << 1) + (((Uint16*)var_part)[mm_vars]) + 3)>> 2);
+ ndbassert(((Var_page*)page)->
+ get_entry_len(regOperPtr->m_tuple_location.m_page_idx) >= sz);
+ memcpy(tuple_ptr, copy, 4*sz);
+ if(0) ndbout_c("%p %d %d (%d bytes)", tuple_ptr,
+ regOperPtr->m_tuple_location.m_page_no,
+ regOperPtr->m_tuple_location.m_page_idx,
+ 4*sz);
+ if(copy_bits & Tuple_header::MM_SHRINK)
+ {
+ ((Var_page*)page)->shrink_entry(regOperPtr->m_tuple_location.m_page_idx,
+ sz);
+ if(0)ndbout_c("%p->shrink_entry(%d, %d)",
+ page, regOperPtr->m_tuple_location.m_page_idx, sz);
+ update_free_page_list(regFragPtr, (Var_page*)page);
+ }
+ disk_ptr = (Tuple_header*)(((Uint32*)copy)+sz);
+ }
+
+ if (regTabPtr->m_no_of_disk_attributes &&
+ (copy_bits & Tuple_header::DISK_INLINE))
+ {
+ Local_key key;
+ memcpy(&key, copy->get_disk_ref_ptr(regTabPtr), sizeof(Local_key));
+ Uint32 logfile_group_id= regFragPtr->m_logfile_group_id;
+ Uint32 lcpScan_ptr_i= regFragPtr->m_lcp_scan_op;
+
+ PagePtr pagePtr = *(PagePtr*)&m_pgman.m_ptr;
+ ndbassert(pagePtr.p->m_page_no == key.m_page_no);
+ ndbassert(pagePtr.p->m_file_no == key.m_file_no);
+ Uint32 sz, *dst;
+ if(copy_bits & Tuple_header::DISK_ALLOC)
+ {
+ disk_page_alloc(signal, regTabPtr, regFragPtr, &key, pagePtr, gci);
+
+ if(lcpScan_ptr_i != RNIL)
+ {
+ 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)
+ {
+ copy_bits |= Tuple_header::LCP_SKIP;
+ }
+ }
+ }
+
+ if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0)
+ {
+ sz= regTabPtr->m_offsets[DD].m_fix_header_size;
+ dst= ((Fix_page*)pagePtr.p)->get_ptr(key.m_page_idx, sz);
+ }
+ else
+ {
+ dst= ((Var_page*)pagePtr.p)->get_ptr(key.m_page_idx);
+ sz= ((Var_page*)pagePtr.p)->get_entry_len(key.m_page_idx);
+ }
+
+ if(! (copy_bits & Tuple_header::DISK_ALLOC))
+ {
+ disk_page_undo_update(pagePtr.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;
+ }
- // Checking detached triggers
- checkDetachedTriggers(signal,
- regOperPtr,
- regTabPtr);
+
+ Uint32 clear=
+ Tuple_header::ALLOC |
+ 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->checksumIndicator) {
+ jam();
+ setChecksum(tuple_ptr, regTabPtr);
+ }
+}
- removeActiveOpList(regOperPtr);
- if (regOperPtr->optype == ZUPDATE) {
- ljam();
- commitUpdate(signal, regOperPtr, regFragPtr, regTabPtr);
- if (regTabPtr->GCPIndicator) {
- updateGcpId(signal, regOperPtr, regFragPtr, regTabPtr);
- }//if
- } else if (regOperPtr->optype == ZINSERT) {
- ljam();
- if (regTabPtr->GCPIndicator) {
- updateGcpId(signal, regOperPtr, regFragPtr, regTabPtr);
- }//if
- } else {
- ndbrequire(regOperPtr->optype == ZDELETE);
- }//if
-}//Dbtup::commitSimple()
+void
+Dbtup::disk_page_commit_callback(Signal* signal,
+ Uint32 opPtrI, Uint32 page_id)
+{
+ Uint32 hash_value;
+ Uint32 gci;
+ OperationrecPtr regOperPtr;
-void Dbtup::removeActiveOpList(Operationrec* const regOperPtr)
+ ljamEntry();
+
+ 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;
+
+ 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);
+
+ execTUP_COMMITREQ(signal);
+ if(signal->theData[0] == 0)
+ c_lqh->tupcommit_conf_callback(signal, regOperPtr.p->userpointer);
+}
+
+void
+Dbtup::disk_page_log_buffer_callback(Signal* signal,
+ Uint32 opPtrI,
+ Uint32 unused)
{
- if (regOperPtr->inActiveOpList == ZTRUE) {
- OperationrecPtr raoOperPtr;
- regOperPtr->inActiveOpList = ZFALSE;
- if (regOperPtr->prevActiveOp != RNIL) {
- ljam();
- raoOperPtr.i = regOperPtr->prevActiveOp;
- ptrCheckGuard(raoOperPtr, cnoOfOprec, operationrec);
- raoOperPtr.p->nextActiveOp = regOperPtr->nextActiveOp;
- } else {
- ljam();
- PagePtr pagePtr;
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- ndbrequire(regOperPtr->pageOffset < ZWORDS_ON_PAGE);
- pagePtr.p->pageWord[regOperPtr->pageOffset] = regOperPtr->nextActiveOp;
- }//if
- if (regOperPtr->nextActiveOp != RNIL) {
- ljam();
- raoOperPtr.i = regOperPtr->nextActiveOp;
- ptrCheckGuard(raoOperPtr, cnoOfOprec, operationrec);
- raoOperPtr.p->prevActiveOp = regOperPtr->prevActiveOp;
- }//if
- regOperPtr->prevActiveOp = RNIL;
- regOperPtr->nextActiveOp = RNIL;
- }//if
-}//Dbtup::removeActiveOpList()
+ Uint32 hash_value;
+ Uint32 gci;
+ OperationrecPtr regOperPtr;
-/* ---------------------------------------------------------------- */
-/* INITIALIZATION OF ONE CONNECTION RECORD TO PREPARE FOR NEXT OP. */
-/* ---------------------------------------------------------------- */
-void Dbtup::initOpConnection(Operationrec* regOperPtr,
- Fragrecord * fragPtrP)
+ ljamEntry();
+
+ 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;
+
+ Uint32 page= regOperPtr.p->m_commit_disk_callback_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);
+}
+
+void
+Dbtup::fix_commit_order(OperationrecPtr opPtr)
{
- Uint32 RinFragList = regOperPtr->inFragList;
- regOperPtr->transstate = IDLE;
- regOperPtr->currentAttrinbufLen = 0;
- regOperPtr->optype = ZREAD;
- if (RinFragList == ZTRUE) {
- OperationrecPtr tropNextLinkPtr;
- OperationrecPtr tropPrevLinkPtr;
-/*----------------------------------------------------------------- */
-/* TO ENSURE THAT WE HAVE SUCCESSFUL ABORTS OF FOLLOWING */
-/* OPERATIONS WHICH NEVER STARTED WE SET THE OPTYPE TO READ. */
-/*----------------------------------------------------------------- */
-/* REMOVE IT FROM THE DOUBLY LINKED LIST ON THE FRAGMENT */
-/*----------------------------------------------------------------- */
- tropPrevLinkPtr.i = regOperPtr->prevOprecInList;
- tropNextLinkPtr.i = regOperPtr->nextOprecInList;
- regOperPtr->inFragList = ZFALSE;
- if (tropPrevLinkPtr.i == RNIL) {
- ljam();
- fragPtrP->firstusedOprec = tropNextLinkPtr.i;
- } else {
- ljam();
- ptrCheckGuard(tropPrevLinkPtr, cnoOfOprec, operationrec);
- tropPrevLinkPtr.p->nextOprecInList = tropNextLinkPtr.i;
- }//if
- if (tropNextLinkPtr.i == RNIL) {
- fragPtrP->lastusedOprec = tropPrevLinkPtr.i;
- } else {
- ptrCheckGuard(tropNextLinkPtr, cnoOfOprec, operationrec);
- tropNextLinkPtr.p->prevOprecInList = tropPrevLinkPtr.i;
- }
- regOperPtr->prevOprecInList = RNIL;
- regOperPtr->nextOprecInList = RNIL;
- }//if
-}//Dbtup::initOpConnection()
+ ndbassert(!opPtr.p->is_first_operation());
+ OperationrecPtr firstPtr = opPtr;
+ while(firstPtr.p->prevActiveOp != RNIL)
+ {
+ firstPtr.i = firstPtr.p->prevActiveOp;
+ c_operation_pool.getPtr(firstPtr);
+ }
+
+ ndbout_c("fix_commit_order (swapping %d and %d)",
+ opPtr.i, firstPtr.i);
+
+ /**
+ * Swap data between first and curr
+ */
+ Uint32 prev= opPtr.p->prevActiveOp;
+ Uint32 next= opPtr.p->nextActiveOp;
+ Uint32 seco= firstPtr.p->nextActiveOp;
+
+ Operationrec tmp = *opPtr.p;
+ * opPtr.p = * firstPtr.p;
+ * firstPtr.p = tmp;
+
+ c_operation_pool.getPtr(seco)->prevActiveOp = opPtr.i;
+ c_operation_pool.getPtr(prev)->nextActiveOp = firstPtr.i;
+ if(next != RNIL)
+ c_operation_pool.getPtr(next)->prevActiveOp = firstPtr.i;
+}
/* ----------------------------------------------------------------- */
/* --------------- COMMIT THIS PART OF A TRANSACTION --------------- */
@@ -270,319 +435,231 @@ 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, hash_value, gci;
- TupCommitReq * const tupCommitReq = (TupCommitReq *)signal->getDataPtr();
+ TupCommitReq * const tupCommitReq= (TupCommitReq *)signal->getDataPtr();
+ regOperPtr.i= tupCommitReq->opPtr;
ljamEntry();
- regOperPtr.i = tupCommitReq->opPtr;
- ptrCheckGuard(regOperPtr, cnoOfOprec, operationrec);
-
- ndbrequire(regOperPtr.p->transstate == STARTED);
- regOperPtr.p->gci = tupCommitReq->gci;
- regOperPtr.p->hashValue = tupCommitReq->hashValue;
- regFragPtr.i = regOperPtr.p->fragmentPtr;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
-
- regTabPtr.i = regOperPtr.p->tableRef;
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
- if (!regTabPtr.p->tuxCustomTriggers.isEmpty()) {
- ljam();
- executeTuxCommitTriggers(signal,
- regOperPtr.p,
- regTabPtr.p);
+ c_operation_pool.getPtr(regOperPtr);
+ if(!regOperPtr.p->is_first_operation())
+ {
+ /**
+ * Out of order commit
+ */
+ fix_commit_order(regOperPtr);
}
+ ndbassert(regOperPtr.p->is_first_operation());
+
+ regFragPtr.i= regOperPtr.p->fragmentPtr;
+ trans_state= get_trans_state(regOperPtr.p);
- if (regOperPtr.p->tupleState == NO_OTHER_OP) {
- if ((regOperPtr.p->prevActiveOp == RNIL) &&
- (regOperPtr.p->nextActiveOp == RNIL)) {
- ljam();
-/* ---------------------------------------------------------- */
-// We handle the simple case separately as an optimisation
-/* ---------------------------------------------------------- */
- commitSimple(signal,
- regOperPtr.p,
- regFragPtr.p,
- regTabPtr.p);
- } else {
-/* ---------------------------------------------------------- */
-// This is the first commit message of this record in this
-// transaction. We will commit this record completely for this
-// transaction. If there are other operations they will be
-// responsible to release their own resources. Also commit of
-// a delete is postponed until the last operation is committed
-// on the tuple.
-//
-// As part of this commitRecord we will also handle detached
-// triggers and release of resources for this operation.
-/* ---------------------------------------------------------- */
- ljam();
- commitRecord(signal,
- regOperPtr.p,
- regFragPtr.p,
- regTabPtr.p);
- removeActiveOpList(regOperPtr.p);
- }//if
- } else {
- ljam();
-/* ---------------------------------------------------------- */
-// Release any copy tuples
-/* ---------------------------------------------------------- */
- ndbrequire(regOperPtr.p->tupleState == TO_BE_COMMITTED);
- commitUpdate(signal, regOperPtr.p, regFragPtr.p, regTabPtr.p);
- removeActiveOpList(regOperPtr.p);
- }//if
- initOpConnection(regOperPtr.p, regFragPtr.p);
-}//execTUP_COMMITREQ()
+ no_of_fragrec= cnoOfFragrec;
-void
-Dbtup::updateGcpId(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr)
-{
- PagePtr pagePtr;
- ljam();
-//--------------------------------------------------------------------
-// Is this code safe for UNDO logging. Not sure currently. RONM
-//--------------------------------------------------------------------
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 temp = regOperPtr->pageOffset + regTabPtr->tupGCPIndex;
- ndbrequire((temp < ZWORDS_ON_PAGE) &&
- (regTabPtr->tupGCPIndex < regTabPtr->tupheadsize));
- if (isUndoLoggingNeeded(regFragPtr, regOperPtr->fragPageId)) {
- Uint32 prevGCI = pagePtr.p->pageWord[temp];
- ljam();
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_UPDATE_GCI,
- regOperPtr->fragPageId,
- regOperPtr->pageIndex,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- cprAddGCIUpdate(signal,
- prevGCI,
- regFragPtr);
- }//if
- pagePtr.p->pageWord[temp] = regOperPtr->gci;
- if (regTabPtr->checksumIndicator) {
- ljam();
- setChecksum(pagePtr.p, regOperPtr->pageOffset, regTabPtr->tupheadsize);
- }//if
-}//Dbtup::updateGcpId()
+ ndbrequire(trans_state == TRANS_STARTED);
+ ptrCheckGuard(regFragPtr, no_of_fragrec, fragrecord);
-void
-Dbtup::commitRecord(Signal* signal,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr)
-{
- Uint32 opType;
- OperationrecPtr firstOpPtr;
- PagePtr pagePtr;
-
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
+ no_of_tablerec= cnoOfTablerec;
+ regTabPtr.i= regFragPtr.p->fragTableId;
+ hash_value= tupCommitReq->hashValue;
+ gci= tupCommitReq->gci;
- setTupleStatesSetOpType(regOperPtr, pagePtr.p, opType, firstOpPtr);
+ req_struct.signal= signal;
+ req_struct.hash_value= hash_value;
+ req_struct.gci= gci;
- fragptr.p = regFragPtr;
- tabptr.p = regTabPtr;
+ ptrCheckGuard(regTabPtr, no_of_tablerec, tablerec);
- if (opType == ZINSERT_DELETE) {
- ljam();
-//--------------------------------------------------------------------
-// We started by inserting the tuple and ended by deleting. Seen from
-// transactions point of view no changes were made.
-//--------------------------------------------------------------------
- commitUpdate(signal, regOperPtr, regFragPtr, regTabPtr);
- return;
- } else if (opType == ZINSERT) {
- ljam();
-//--------------------------------------------------------------------
-// We started by inserting whereafter we made several changes to the
-// tuple that could include updates, deletes and new inserts. The final
-// state of the tuple is the original tuple. This is reached from this
-// operation. We change the optype on this operation to ZINSERT to
-// ensure proper operation of the detached trigger.
-// We restore the optype after executing triggers although not really
-// needed.
-//--------------------------------------------------------------------
- Uint32 saveOpType = regOperPtr->optype;
- regOperPtr->optype = ZINSERT;
- operPtr.p = regOperPtr;
-
- checkDetachedTriggers(signal,
- regOperPtr,
- regTabPtr);
-
- regOperPtr->optype = saveOpType;
- } else if (opType == ZUPDATE) {
- ljam();
-//--------------------------------------------------------------------
-// We want to use the first operation which contains a copy tuple
-// reference. This operation contains the before value of this record
-// for this transaction. Then this operation is used for executing
-// triggers with optype set to update.
-//--------------------------------------------------------------------
- OperationrecPtr befOpPtr;
- findBeforeValueOperation(befOpPtr, firstOpPtr);
-
- Uint32 saveOpType = befOpPtr.p->optype;
- Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
- Bitmask<MAXNROFATTRIBUTESINWORDS> saveAttributeMask;
-
- calculateChangeMask(pagePtr.p,
- regTabPtr,
- befOpPtr.p->pageOffset,
- attributeMask);
-
- saveAttributeMask.clear();
- saveAttributeMask.bitOR(befOpPtr.p->changeMask);
- befOpPtr.p->changeMask.clear();
- befOpPtr.p->changeMask.bitOR(attributeMask);
- befOpPtr.p->gci = regOperPtr->gci;
+ PagePtr page;
+ Tuple_header* tuple_ptr= 0;
+ if(regOperPtr.p->op_struct.m_load_diskpage_on_commit)
+ {
+ ndbassert(regOperPtr.p->is_first_operation() &&
+ regOperPtr.p->is_last_operation());
+
+ Page_cache_client::Request req;
+ /**
+ * Check for page
+ */
+ if(!regOperPtr.p->m_copy_tuple_location.isNull())
+ {
+ 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));
+ }
+ else
+ {
+ // initial delete
+ ndbassert(regOperPtr.p->op_struct.op_type == ZDELETE);
+ tuple_ptr= (Tuple_header*)
+ get_ptr(&page, &regOperPtr.p->m_tuple_location, regTabPtr.p);
+ memcpy(&req.m_page,
+ tuple_ptr->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key));
+ }
+ req.m_callback.m_callbackData= regOperPtr.i;
+ req.m_callback.m_callbackFunction =
+ safe_cast(&Dbtup::disk_page_commit_callback);
+
+ int flags= regOperPtr.p->op_struct.op_type |
+ Page_cache_client::COMMIT_REQ | Page_cache_client::STRICT_ORDER;
+ int res= m_pgman.get_page(signal, req, flags);
+ switch(res){
+ case 0:
+ /**
+ * Timeslice
+ */
+ signal->theData[0] = 1;
+ return;
+ case -1:
+ ndbrequire("NOT YET IMPLEMENTED" == 0);
+ break;
+ }
+ 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)
+ {
+ ndbassert(regOperPtr.p->is_first_operation() &&
+ regOperPtr.p->is_last_operation());
- operPtr.p = befOpPtr.p;
- checkDetachedTriggers(signal,
- befOpPtr.p,
- regTabPtr);
-
- befOpPtr.p->changeMask.clear();
- befOpPtr.p->changeMask.bitOR(saveAttributeMask);
-
- befOpPtr.p->optype = saveOpType;
- } else if (opType == ZDELETE) {
- ljam();
-//--------------------------------------------------------------------
-// We want to use the first operation which contains a copy tuple.
-// We benefit from the fact that we know that it cannot be a simple
-// delete and it cannot be an insert followed by a delete. Thus there
-// must either be an update or a insert following a delete. In both
-// cases we will find a before value in a copy tuple.
-//
-// An added complexity is that the trigger handling assumes that the
-// before value is located in the original tuple so we have to move the
-// copy tuple reference to the original tuple reference and afterwards
-// restore it again.
-//--------------------------------------------------------------------
- OperationrecPtr befOpPtr;
- findBeforeValueOperation(befOpPtr, firstOpPtr);
- Uint32 saveOpType = befOpPtr.p->optype;
-
- Uint32 realPageId = befOpPtr.p->realPageId;
- Uint32 pageOffset = befOpPtr.p->pageOffset;
- Uint32 fragPageId = befOpPtr.p->fragPageId;
- Uint32 pageIndex = befOpPtr.p->pageIndex;
-
- befOpPtr.p->realPageId = befOpPtr.p->realPageIdC;
- befOpPtr.p->pageOffset = befOpPtr.p->pageOffsetC;
- befOpPtr.p->fragPageId = befOpPtr.p->fragPageIdC;
- befOpPtr.p->pageIndex = befOpPtr.p->pageIndexC;
- befOpPtr.p->gci = regOperPtr->gci;
-
- operPtr.p = befOpPtr.p;
- checkDetachedTriggers(signal,
- befOpPtr.p,
- regTabPtr);
-
- befOpPtr.p->realPageId = realPageId;
- befOpPtr.p->pageOffset = pageOffset;
- befOpPtr.p->fragPageId = fragPageId;
- befOpPtr.p->pageIndex = pageIndex;
- befOpPtr.p->optype = saveOpType;
- } else {
- ndbrequire(false);
- }//if
-
- commitUpdate(signal, regOperPtr, regFragPtr, regTabPtr);
- if (regTabPtr->GCPIndicator) {
- updateGcpId(signal, regOperPtr, regFragPtr, regTabPtr);
- }//if
-}//Dbtup::commitRecord()
+ 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);
+ switch(res){
+ case 0:
+ signal->theData[0] = 1;
+ return;
+ case -1:
+ ndbrequire("NOT YET IMPLEMENTED" == 0);
+ break;
+ }
+ }
+
+ if(!tuple_ptr)
+ {
+ req_struct.m_tuple_ptr= tuple_ptr = (Tuple_header*)
+ get_ptr(&page, &regOperPtr.p->m_tuple_location,regTabPtr.p);
+ }
+
+ if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
+ {
+ /**
+ * Execute all tux triggers at first commit
+ * since previous tuple is otherwise removed...
+ * btw...is this a "good" solution??
+ *
+ * why can't we instead remove "own version" (when approriate ofcourse)
+ */
+ if (!regTabPtr.p->tuxCustomTriggers.isEmpty()) {
+ ljam();
+ OperationrecPtr loopPtr= regOperPtr;
+ while(loopPtr.i != RNIL)
+ {
+ c_operation_pool.getPtr(loopPtr);
+ executeTuxCommitTriggers(signal,
+ loopPtr.p,
+ regFragPtr.p,
+ regTabPtr.p);
+ set_tuple_state(loopPtr.p, TUPLE_TO_BE_COMMITTED);
+ loopPtr.i = loopPtr.p->nextActiveOp;
+ }
+ }
+ }
+
+ if(regOperPtr.p->is_last_operation())
+ {
+ /**
+ * Perform "real" commit
+ */
+ set_change_mask_info(&req_struct, regOperPtr.p);
+ checkDetachedTriggers(&req_struct, regOperPtr.p, regTabPtr.p);
+
+ if(regOperPtr.p->op_struct.op_type != ZDELETE)
+ {
+ commit_operation(signal, gci, tuple_ptr, page.p,
+ regOperPtr.p, regFragPtr.p, regTabPtr.p);
+ removeActiveOpList(regOperPtr.p, tuple_ptr);
+ }
+ else
+ {
+ removeActiveOpList(regOperPtr.p, tuple_ptr);
+ dealloc_tuple(signal, gci, page.p, tuple_ptr,
+ regOperPtr.p, regFragPtr.p, regTabPtr.p);
+ }
+ }
+ else
+ {
+ removeActiveOpList(regOperPtr.p, tuple_ptr);
+ }
+
+ initOpConnection(regOperPtr.p);
+ signal->theData[0] = 0;
+}
void
-Dbtup::setTupleStatesSetOpType(Operationrec* const regOperPtr,
- Page* const pagePtr,
- Uint32& opType,
- OperationrecPtr& firstOpPtr)
+Dbtup::set_change_mask_info(KeyReqStruct * const req_struct,
+ Operationrec * const regOperPtr)
{
- OperationrecPtr loopOpPtr;
- OperationrecPtr lastOpPtr;
-
- ndbrequire(regOperPtr->pageOffset < ZWORDS_ON_PAGE);
- loopOpPtr.i = pagePtr->pageWord[regOperPtr->pageOffset];
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- lastOpPtr = loopOpPtr;
- if (loopOpPtr.p->optype == ZDELETE) {
+ ChangeMaskState change_mask= get_change_mask_state(regOperPtr);
+ if (change_mask == USE_SAVED_CHANGE_MASK) {
ljam();
- opType = ZDELETE;
- } else {
+ req_struct->changeMask.setWord(0, regOperPtr->saved_change_mask[0]);
+ req_struct->changeMask.setWord(1, regOperPtr->saved_change_mask[1]);
+ //get saved state
+ } else if (change_mask == RECALCULATE_CHANGE_MASK) {
ljam();
- opType = ZUPDATE;
- }//if
- do {
+ //Recompute change mask, for now set all bits
+ req_struct->changeMask.set();
+ } else if (change_mask == SET_ALL_MASK) {
ljam();
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- firstOpPtr = loopOpPtr;
- loopOpPtr.p->tupleState = TO_BE_COMMITTED;
- loopOpPtr.i = loopOpPtr.p->nextActiveOp;
- } while (loopOpPtr.i != RNIL);
- if (opType == ZDELETE) {
- ljam();
- if (firstOpPtr.p->optype == ZINSERT) {
- ljam();
- opType = ZINSERT_DELETE;
- }//if
+ req_struct->changeMask.set();
} else {
ljam();
- if (firstOpPtr.p->optype == ZINSERT) {
- ljam();
- opType = ZINSERT;
- }//if
- }///if
-}//Dbtup::setTupleStatesSetOpType()
-
-void Dbtup::findBeforeValueOperation(OperationrecPtr& befOpPtr,
- OperationrecPtr firstOpPtr)
-{
- befOpPtr = firstOpPtr;
- if (befOpPtr.p->realPageIdC != RNIL) {
- ljam();
- return;
- } else {
- ljam();
- befOpPtr.i = befOpPtr.p->prevActiveOp;
- ptrCheckGuard(befOpPtr, cnoOfOprec, operationrec);
- ndbrequire(befOpPtr.p->realPageIdC != RNIL);
- }//if
-}//Dbtup::findBeforeValueOperation()
+ ndbrequire(change_mask == DELETE_CHANGES);
+ }
+}
void
Dbtup::calculateChangeMask(Page* const pagePtr,
Tablerec* const regTabPtr,
- Uint32 pageOffset,
- Bitmask<MAXNROFATTRIBUTESINWORDS>& attributeMask)
+ KeyReqStruct * const req_struct)
{
OperationrecPtr loopOpPtr;
-
- attributeMask.clear();
- ndbrequire(pageOffset < ZWORDS_ON_PAGE);
- loopOpPtr.i = pagePtr->pageWord[pageOffset];
+ Uint32 saved_word1= 0;
+ Uint32 saved_word2= 0;
+ loopOpPtr.i= req_struct->m_tuple_ptr->m_operation_ptr_i;
do {
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- if (loopOpPtr.p->optype == ZUPDATE) {
+ 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) {
ljam();
- attributeMask.bitOR(loopOpPtr.p->changeMask);
- } else if (loopOpPtr.p->optype == ZINSERT) {
+ saved_word1|= loopOpPtr.p->saved_change_mask[0];
+ saved_word2|= loopOpPtr.p->saved_change_mask[1];
+ } else if (change_mask == RECALCULATE_CHANGE_MASK) {
ljam();
- attributeMask.set();
+ //Recompute change mask, for now set all bits
+ req_struct->changeMask.set();
return;
} else {
- ndbrequire(loopOpPtr.p->optype == ZDELETE);
- }//if
- loopOpPtr.i = loopOpPtr.p->nextActiveOp;
+ ndbrequire(change_mask == SET_ALL_MASK);
+ ljam();
+ req_struct->changeMask.set();
+ return;
+ }
+ loopOpPtr.i= loopOpPtr.p->prevActiveOp;
} while (loopOpPtr.i != RNIL);
-}//Dbtup::calculateChangeMask()
+ 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
index 8c43de52a75..a5e076d216f 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
@@ -38,7 +38,7 @@ void Dbtup::execDEBUG_SIG(Signal* signal)
PagePtr regPagePtr;
ljamEntry();
regPagePtr.i = signal->theData[0];
- ptrCheckGuard(regPagePtr, cnoOfPage, page);
+ ptrCheckGuard(regPagePtr, cnoOfPage, cpage);
}//Dbtup::execDEBUG_SIG()
#ifdef TEST_MR
@@ -213,8 +213,8 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal)
for(Uint32 i = 0; i<chunk.pageCount; i++){
PagePtr pagePtr;
pagePtr.i = chunk.pageId + i;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ pagePtr.p->page_state = ~ZFREE_COMMON;
}
if(alloc == 1 && free > 0)
@@ -237,10 +237,16 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal)
/* ---------------------------------------------------------------- */
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;
- DiskBufferSegmentInfoPtr dbsiPtr;
- CheckpointInfoPtr ciPtr;
- UndoPagePtr regUndoPagePtr;
Uint32* data = &signal->theData[0];
ljamEntry();
@@ -255,33 +261,13 @@ void Dbtup::execMEMCHECKREQ(Signal* signal)
ljam();
while (regPagePtr.i != RNIL) {
ljam();
- ptrCheckGuard(regPagePtr, cnoOfPage, page);
- regPagePtr.i = regPagePtr.p->pageWord[ZPAGE_NEXT_POS];
+ ptrCheckGuard(regPagePtr, cnoOfPage, cpage);
+ regPagePtr.i = regPagePtr.p->next_page;
data[0]++;
}//while
}//for
- regUndoPagePtr.i = cfirstfreeUndoSeg;
- while (regUndoPagePtr.i != RNIL) {
- ljam();
- ptrCheckGuard(regUndoPagePtr, cnoOfUndoPage, undoPage);
- regUndoPagePtr.i = regUndoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS];
- data[1] += ZUB_SEGMENT_SIZE;
- }//while
- ciPtr.i = cfirstfreeLcp;
- while (ciPtr.i != RNIL) {
- ljam();
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- ciPtr.i = ciPtr.p->lcpNextRec;
- data[2]++;
- }//while
- dbsiPtr.i = cfirstfreePdx;
- while (dbsiPtr.i != ZNIL) {
- ljam();
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- dbsiPtr.i = dbsiPtr.p->pdxNextRec;
- data[3]++;
- }//while
sendSignal(blockref, GSN_MEMCHECKCONF, signal, 25, JBB);
+#endif
}//Dbtup::memCheck()
// ------------------------------------------------------------------------
@@ -294,10 +280,9 @@ void Dbtup::printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit)
PagePtr tmpPageP;
FragrecordPtr tmpFragP;
TablerecPtr tmpTableP;
- Uint32 tmpTupleSize;
tmpPageP.i = pageid;
- ptrCheckGuard(tmpPageP, cnoOfPage, page);
+ ptrCheckGuard(tmpPageP, cnoOfPage, cpage);
tmpFragP.i = fragid;
ptrCheckGuard(tmpFragP, cnoOfFragrec, fragrecord);
@@ -305,36 +290,11 @@ void Dbtup::printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit)
tmpTableP.i = tmpFragP.p->fragTableId;
ptrCheckGuard(tmpTableP, cnoOfTablerec, tablerec);
- tmpTupleSize = tmpTableP.p->tupheadsize;
-
ndbout << "Fragid: " << fragid << " Pageid: " << pageid << endl
<< "----------------------------------------" << endl;
ndbout << "PageHead : ";
- for (Uint32 i1 = 0; i1 < ZPAGE_HEADER_SIZE; i1++) {
- if (i1 == 3)
- ndbout << (tmpPageP.p->pageWord[i1] >> 16) << "," << (tmpPageP.p->pageWord[i1] & 0xffff) << " ";
- else if (tmpPageP.p->pageWord[i1] == 4059165169u)
- ndbout << "F1F1F1F1 ";
- else if (tmpPageP.p->pageWord[i1] == 268435455u)
- ndbout << "RNIL ";
- else
- ndbout << tmpPageP.p->pageWord[i1] << " ";
- }//for
ndbout << endl;
- for (Uint32 i = ZPAGE_HEADER_SIZE; i < printLimit; i += tmpTupleSize) {
- ndbout << "pagepos " << i << " : ";
-
- for (Uint32 j = i; j < i + tmpTupleSize; j++) {
- if (tmpPageP.p->pageWord[j] == 4059165169u)
- ndbout << "F1F1F1F1 ";
- else if (tmpPageP.p->pageWord[j] == 268435455u)
- ndbout << "RNIL ";
- else
- ndbout << tmpPageP.p->pageWord[j] << " ";
- }//for
- ndbout << endl;
- }//for
}//Dbtup::printoutTuplePage
#ifdef VM_TRACE
@@ -343,37 +303,22 @@ operator<<(NdbOut& out, const Dbtup::Operationrec& op)
{
out << "[Operationrec " << hex << &op;
// table
- out << " [tableRef " << dec << op.tableRef << "]";
- out << " [fragId " << dec << op.fragId << "]";
out << " [fragmentPtr " << hex << op.fragmentPtr << "]";
// type
- out << " [optype " << dec << op.optype << "]";
- out << " [deleteInsertFlag " << dec << op.deleteInsertFlag << "]";
- out << " [dirtyOp " << dec << op.dirtyOp << "]";
- out << " [interpretedExec " << dec << op.interpretedExec << "]";
- out << " [opSimple " << dec << op.opSimple << "]";
+ out << " [op_type " << dec << op.op_struct.op_type << "]";
+ out << " [delete_insert_flag " << dec;
+ out << op.op_struct.delete_insert_flag << "]";
// state
- out << " [tupleState " << dec << (Uint32) op.tupleState << "]";
- out << " [transstate " << dec << (Uint32) op.transstate << "]";
- out << " [inFragList " << dec << op.inFragList << "]";
- out << " [inActiveOpList " << dec << op.inActiveOpList << "]";
- out << " [undoLogged " << dec << (Uint32) op.undoLogged << "]";
+ 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 << " [fragPageId " << dec << op.fragPageId << "]";
- out << " [pageIndex " << dec << op.pageIndex << "]";
- out << " [realPageId " << hex << op.realPageId << "]";
- out << " [pageOffset " << dec << op.pageOffset << "]";
- out << " [fragPageIdC " << dec << op.fragPageIdC << "]";
- out << " [pageIndexC " << dec << op.pageIndexC << "]";
- out << " [realPageIdC " << hex << op.realPageIdC << "]";
- out << " [pageOffsetC " << dec << op.pageOffsetC << "]";
- // trans
- out << " [transid1 " << hex << op.transid1 << "]";
- out << " [transid2 " << hex << op.transid2 << "]";
+ out << " [m_tuple_location " << op.m_tuple_location << "]";
+ out << " [m_copy_tuple_location " << op.m_copy_tuple_location << "]";
out << "]";
return out;
}
@@ -392,13 +337,11 @@ operator<<(NdbOut& out, const Dbtup::Th& th)
if (tab.checksumIndicator)
out << " [checksum " << hex << th.data[i++] << "]";
out << " [nullbits";
- for (unsigned j = 0; j < tab.tupNullWords; j++)
+ for (unsigned j = 0; j < tab.m_offsets[Dbtup::MM].m_null_words; j++)
out << " " << hex << th.data[i++];
out << "]";
- if (tab.GCPIndicator)
- out << " [gcp " << dec << th.data[i++] << "]";
out << " [data";
- while (i < tab.tupheadsize)
+ while (i < tab.m_offsets[Dbtup::MM].m_fix_header_size)
out << " " << hex << th.data[i++];
out << "]";
out << "]";
@@ -409,3 +352,69 @@ operator<<(NdbOut& out, const Dbtup::Th& th)
#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
+ << " var_off: " << off.m_varpart_offset
+ << " 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.checksumIndicator
+ << " 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
new file mode 100644
index 00000000000..972e6c6e399
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp
@@ -0,0 +1,1511 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#define DBTUP_C
+#include "Dbtup.hpp"
+
+Dbtup::Disk_alloc_info::Disk_alloc_info(const Tablerec* tabPtrP,
+ Uint32 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;
+ Uint32 var_size= tabPtrP->m_offsets[DD].m_max_var_offset;
+
+ if (tabPtrP->m_attributes[DD].m_no_of_varsize == 0)
+ {
+ Uint32 recs_per_page= (4*Tup_fixsize_page::DATA_WORDS)/min_size;
+ Uint32 pct_free= 0;
+ 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 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_extent_search_matrix[i] < sz)
+ {
+ i = (i + mask) & ~mask;
+ continue;
+ }
+
+ if (!m_free_extents[i].isEmpty())
+ {
+ return i;
+ }
+ }
+
+ 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
+ */
+ {
+
+ printf("free space %d free_page_thresholds ", free);
+ for(Uint32 i = 0; i<EXTENT_SEARCH_MATRIX_ROWS; i++)
+ printf("%d ", m_total_extent_free_space_thresholds[i]);
+ ndbout_c("");
+
+ 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);
+
+ printf("free space %d free_page_count ", free);
+ for(Uint32 i = 0; i<EXTENT_SEARCH_MATRIX_COLS; i++)
+ printf("%d ", extP->m_free_page_count[i]);
+ ndbout_c(" -> row: %d col: %d -> pos= %d", row, col, pos);
+
+ assert(pos < EXTENT_SEARCH_MATRIX_SIZE);
+ return pos;
+}
+
+/**
+ * - 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%
+ *
+ */
+
+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);
+
+ /**
+ * 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> page;
+ m_global_page_pool.getPtr(page, ptrI);
+
+ disk_page_prealloc_dirty_page(alloc, *(PagePtr*)&page, i, sz);
+ key->m_page_no= ((Page*)page.p)->m_page_no;
+ key->m_file_no= ((Page*)page.p)->m_file_no;
+ 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;
+ //ndbout_c("found transit page");
+ return 0;
+ }
+ }
+
+ /**
+ * We need to request a page...
+ */
+ if (!c_page_request_pool.seize(req))
+ {
+ err= 1;
+ //XXX set error code
+ ndbout_c("no free request");
+ return -err;
+ }
+
+ new (req.p) Page_request();
+
+ 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)
+ {
+ jam();
+ found= true;
+ }
+ else
+ {
+ jam();
+ /**
+ * The current extent is not in a free list
+ * and since it couldn't accomadate the request
+ * we put it on the free list
+ */
+ Uint32 pos= alloc.calc_extent_pos(ext.p);
+ LocalDLList<Extent_info> list(c_extent_pool, alloc.m_free_extents[pos]);
+ list.add(ext);
+ }
+ }
+
+ if (!found)
+ {
+ Uint32 pos;
+ if ((pos= alloc.find_extent(sz)) != RNIL)
+ {
+ jam();
+ LocalDLList<Extent_info> list(c_extent_pool, alloc.m_free_extents[pos]);
+ list.first(ext);
+ list.remove(ext);
+ }
+ else
+ {
+ jam();
+ /**
+ * We need to alloc an extent
+ */
+ if (!c_extent_pool.seize(ext))
+ {
+ //XXX
+ err= 2;
+ c_page_request_pool.release(req);
+ ndbout_c("no free extent info");
+ return -err;
+ }
+
+ if ((err= tsman.alloc_extent(&ext.p->m_key)) < 0)
+ {
+ //XXX
+ c_extent_pool.release(ext);
+ c_page_request_pool.release(req);
+ ndbout_c("no free extent");
+ return -err;
+ }
+
+ int pages= err;
+ ndbout << "allocated " << pages << " pages: " << ext.p->m_key << endl;
+ 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);
+
+ LocalSLList<Extent_info, Extent_list_t>
+ 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);
+ ndbassert(pageBits >= 0);
+ }
+
+ /**
+ * We have a page from an extent
+ */
+ *key= req.p->m_key= ext.p->m_key;
+
+ /**
+ * 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);
+
+ ndbassert(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)
+ {
+ ndbassert(ext.p->m_free_page_count[pageBits] > 0);
+ ext.p->m_free_page_count[pageBits]--;
+ ext.p->m_free_page_count[newPageBits]++;
+ }
+ ndbassert(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);
+ {
+ LocalDLList<Page_request> 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)
+ {
+ //XXX empty page -> fast to map
+ flags |= Page_cache_client::EMPTY_PAGE | Page_cache_client::NO_HOOK;
+ preq.m_callback.m_callbackFunction =
+ safe_cast(&Dbtup::disk_page_prealloc_initial_callback);
+ }
+
+ int res= m_pgman.get_page(signal, preq, flags);
+ switch(res)
+ {
+ case 0:
+ break;
+ case -1:
+ ndbassert(false);
+ break;
+ default:
+ execute(signal, preq.m_callback, res); // run callback
+ }
+
+ return res;
+}
+
+void
+Dbtup::disk_page_prealloc_dirty_page(Disk_alloc_info & alloc,
+ Ptr<Page> pagePtr,
+ Uint32 old_idx, Uint32 sz)
+{
+ ndbassert(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;
+
+ ndbassert(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)
+ {
+ 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);
+
+ ndbassert(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;
+ ndbassert(extentPtr.p->m_free_space >= sz);
+ extentPtr.p->m_free_space -= sz;
+ Uint32 old_pos= extentPtr.p->m_free_matrix_pos;
+ if (old_pos != RNIL) // Current extent
+ {
+ jam();
+ Uint32 new_pos= alloc.calc_extent_pos(extentPtr.p);
+ if (old_pos != new_pos)
+ {
+ jam();
+ Extent_list old_list(c_extent_pool, alloc.m_free_extents[old_pos]);
+ Extent_list new_list(c_extent_pool, alloc.m_free_extents[new_pos]);
+ old_list.remove(extentPtr);
+ new_list.add(extentPtr);
+ extentPtr.p->m_free_matrix_pos= new_pos;
+ }
+ }
+}
+
+
+void
+Dbtup::disk_page_prealloc_transit_page(Disk_alloc_info& alloc,
+ Ptr<Page_request> req,
+ Uint32 old_idx, Uint32 sz)
+{
+ ndbassert(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);
+
+ ndbassert(free >= sz);
+ Uint32 new_idx= alloc.calc_page_free_bits(free - sz);
+
+ if (old_idx != new_idx)
+ {
+ DLList<Page_request>::Head *lists = alloc.m_page_requests;
+ LocalDLList<Page_request> old_list(c_page_request_pool, lists[old_idx]);
+ LocalDLList<Page_request> new_list(c_page_request_pool, lists[new_idx]);
+ old_list.remove(req);
+ new_list.add(req);
+
+ ndbassert(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;
+ ndbassert(extentPtr.p->m_free_space >= sz);
+ extentPtr.p->m_free_space -= sz;
+ Uint32 old_pos= extentPtr.p->m_free_matrix_pos;
+ if (old_pos != RNIL) // Current extent
+ {
+ jam();
+ Uint32 new_pos= alloc.calc_extent_pos(extentPtr.p);
+ if (old_pos != new_pos)
+ {
+ jam();
+ Extent_list old_list(c_extent_pool, alloc.m_free_extents[old_pos]);
+ Extent_list new_list(c_extent_pool, alloc.m_free_extents[new_pos]);
+ old_list.remove(extentPtr);
+ new_list.add(extentPtr);
+ extentPtr.p->m_free_matrix_pos= new_pos;
+ }
+ }
+}
+
+
+void
+Dbtup::disk_page_prealloc_callback(Signal* signal,
+ Uint32 page_request, Uint32 page_id)
+{
+ //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);
+
+ disk_page_prealloc_callback_common(signal, req, fragPtr, gpage);
+}
+
+void
+Dbtup::disk_page_prealloc_initial_callback(Signal*signal,
+ Uint32 page_request,
+ Uint32 page_id)
+{
+ //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);
+
+ 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);
+
+ Page* page= (Page*)gpage.p;
+ page->m_page_no= req.p->m_key.m_page_no;
+ page->m_file_no= req.p->m_key.m_file_no;
+ page->m_table_id= fragPtr.p->fragTableId;
+ page->m_fragment_id = fragPtr.p->fragmentId;
+ page->m_extent_no = extentPtr.p->m_key.m_page_idx; // logical extent no
+ page->m_extent_info_ptr= req.p->m_extent_info_ptr;
+ page->m_restart_seq = globalData.m_restart_seq;
+ page->list_index = 0x8000;
+ page->uncommitted_used_space = 0;
+ page->nextList = page->prevList = RNIL;
+
+ if (tabPtr.p->m_attributes[DD].m_no_of_varsize == 0)
+ {
+ convertThPage(tabPtr.p->m_offsets[DD].m_fix_header_size,
+ (Fix_page*)gpage.p);
+ }
+ else
+ {
+ abort();
+ }
+ disk_page_prealloc_callback_common(signal, req, fragPtr, gpage);
+}
+
+void
+Dbtup::disk_page_prealloc_callback_common(Signal* signal,
+ Ptr<Page_request> req,
+ Ptr<Fragrecord> fragPtr,
+ Ptr<GlobalPage> pagePtr)
+{
+ Page* page= (Page*)pagePtr.p;
+
+ /**
+ * 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
+ */
+ ndbassert((page->list_index & 0x8000) == 0x8000);
+ ndbassert(page->m_extent_info_ptr == req.p->m_extent_info_ptr);
+ ndbassert(page->m_page_no == req.p->m_key.m_page_no);
+ ndbassert(page->m_file_no == req.p->m_key.m_file_no);
+ Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
+
+ 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 = page->free_space;
+ Uint32 real_used = used + page->uncommitted_used_space;
+
+ ndbassert(real_free >= free);
+ ndbassert(real_free >= real_used);
+ ndbassert(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(*(Ptr<Page>*)&pagePtr);
+ page->uncommitted_used_space = real_used;
+ page->list_index = new_idx;
+
+ if (old_idx != new_idx || free != real_free)
+ {
+ Ptr<Extent_info> extentPtr;
+ c_extent_pool.getPtr(extentPtr, ext);
+
+ extentPtr.p->m_free_space += (real_free - free);
+
+ if (old_idx != new_idx)
+ {
+ ndbassert(extentPtr.p->m_free_page_count[old_idx]);
+ extentPtr.p->m_free_page_count[old_idx]--;
+ extentPtr.p->m_free_page_count[new_idx]++;
+ }
+
+ Uint32 old_pos= extentPtr.p->m_free_matrix_pos;
+ if (old_pos != RNIL) // Current extent
+ {
+ jam();
+ Uint32 new_pos= alloc.calc_extent_pos(extentPtr.p);
+ if (old_pos != new_pos)
+ {
+ jam();
+ Extent_list old_list(c_extent_pool, alloc.m_free_extents[old_pos]);
+ Extent_list new_list(c_extent_pool, alloc.m_free_extents[new_pos]);
+ old_list.remove(extentPtr);
+ new_list.add(extentPtr);
+ extentPtr.p->m_free_matrix_pos= new_pos;
+ }
+ }
+ }
+
+ {
+ Page_request_list list(c_page_request_pool,
+ alloc.m_page_requests[old_idx]);
+ list.release(req);
+ }
+}
+
+int
+Dbtup::disk_page_load_hook(Uint32 page_id)
+{
+ Ptr<GlobalPage> gpage;
+ m_global_page_pool.getPtr(gpage, page_id);
+
+ PagePtr pagePtr= *(PagePtr*)&gpage;
+ 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))
+ {
+ ndbassert(false);
+ return 0;
+ }
+
+ pagePtr.p->list_index |= 0x8000;
+ pagePtr.p->nextList = pagePtr.p->prevList = RNIL;
+
+ Local_key key;
+ key.m_page_no = pagePtr.p->m_page_no;
+ key.m_file_no = pagePtr.p->m_file_no;
+
+ if (unlikely(pagePtr.p->m_restart_seq != globalData.m_restart_seq))
+ {
+ pagePtr.p->m_restart_seq = globalData.m_restart_seq;
+ pagePtr.p->uncommitted_used_space = 0;
+
+ 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 idx= alloc.calc_page_free_bits(pagePtr.p->free_space);
+
+ pagePtr.p->list_index = idx | 0x8000;
+
+ 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;
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+Dbtup::disk_page_unmap_callback(Uint32 page_id)
+{
+ Ptr<GlobalPage> gpage;
+ m_global_page_pool.getPtr(gpage, page_id);
+ PagePtr pagePtr= *(PagePtr*)&gpage;
+
+ 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))
+ {
+ return ;
+ }
+
+ Uint32 i = pagePtr.p->list_index;
+
+ Local_key key;
+ key.m_page_no = pagePtr.p->m_page_no;
+ key.m_file_no = pagePtr.p->m_file_no;
+
+ if ((i & 0x8000) == 0)
+ {
+ 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;
+
+ ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
+ LocalDLList<Page> old(*pool, alloc.m_dirty_pages[i]);
+ old.remove(pagePtr);
+
+ if (pagePtr.p->uncommitted_used_space == 0)
+ {
+ Tablespace_client tsman(0, c_tsman,
+ fragPtr.p->fragTableId,
+ fragPtr.p->fragmentId,
+ fragPtr.p->m_tablespace_id);
+
+ tsman.unmap_page(&key);
+ }
+ }
+ pagePtr.p->list_index = i | 0x8000;
+}
+
+void
+Dbtup::disk_page_alloc(Signal* signal,
+ Tablerec* tabPtrP, Fragrecord* fragPtrP,
+ Local_key* key, PagePtr pagePtr, Uint32 gci)
+{
+ Uint32 logfile_group_id= fragPtrP->m_logfile_group_id;
+
+ Uint64 lsn;
+ Uint32 old_free = pagePtr.p->free_space;
+ Uint32 old_bits= fragPtrP->m_disk_alloc_info.calc_page_free_bits(old_free);
+ if (tabPtrP->m_attributes[DD].m_no_of_varsize == 0)
+ {
+ ndbassert(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;
+ ndbassert(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);
+ }
+
+ Uint32 new_free = pagePtr.p->free_space;
+ Uint32 new_bits= fragPtrP->m_disk_alloc_info.calc_page_free_bits(new_free);
+
+ if (old_bits != new_bits)
+ {
+ Tablespace_client tsman(signal, c_tsman,
+ fragPtrP->fragTableId,
+ fragPtrP->fragmentId,
+ fragPtrP->m_tablespace_id);
+
+ tsman.update_page_free_bits(key, new_bits, lsn);
+ }
+}
+
+void
+Dbtup::disk_page_free(Signal *signal,
+ Tablerec *tabPtrP, Fragrecord * fragPtrP,
+ Local_key* key, PagePtr pagePtr, Uint32 gci)
+{
+ 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 old_bits= alloc.calc_page_free_bits(old_free);
+
+ 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);
+ 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 new_bits = alloc.calc_page_free_bits(new_free);
+
+ if (old_bits != new_bits)
+ {
+ Tablespace_client tsman(signal, c_tsman,
+ fragPtrP->fragTableId,
+ fragPtrP->fragmentId,
+ fragPtrP->m_tablespace_id);
+
+ tsman.update_page_free_bits(key, new_bits, lsn);
+ }
+
+ Uint32 ext = pagePtr.p->m_extent_info_ptr;
+ Uint32 used = pagePtr.p->uncommitted_used_space;
+ ndbassert(old_free >= used);
+ ndbassert(new_free >= used);
+ ndbassert(new_free >= old_free);
+ page_idx = pagePtr.p->list_index;
+ Uint32 old_idx = page_idx & 0x7FFF;
+ Uint32 new_idx = alloc.calc_page_free_bits(new_free - used);
+ ndbassert(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)
+ {
+ ndbassert(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)
+ {
+ 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
+ {
+ pagePtr.p->list_index = new_idx | 0x8000;
+ }
+ }
+
+ extentPtr.p->m_free_space += sz;
+ Uint32 old_pos = extentPtr.p->m_free_matrix_pos;
+ if (old_pos != RNIL)
+ {
+ Uint32 pos= alloc.calc_extent_pos(extentPtr.p);
+
+ if (pos != old_pos)
+ {
+ Extent_list old_list(c_extent_pool, alloc.m_free_extents[old_pos]);
+ Extent_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;
+ }
+ }
+}
+
+void
+Dbtup::disk_page_abort_prealloc(Signal *signal, Fragrecord* fragPtrP,
+ Local_key* key, Uint32 sz)
+{
+ 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);
+ switch(res)
+ {
+ case 0:
+ case -1:
+ break;
+ default:
+ Ptr<GlobalPage> page;
+ m_global_page_pool.getPtr(page, (Uint32)res);
+ disk_page_abort_prealloc_callback_1(signal, fragPtrP, *(PagePtr*)&page,
+ 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);
+
+ Ptr<GlobalPage> gpage;
+ m_global_page_pool.getPtr(gpage, page_id);
+
+ PagePtr pagePtr= *(PagePtr*)&gpage;
+
+ 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)
+{
+ 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;
+ ndbassert(free >= used);
+ ndbassert(used >= sz);
+ ndbassert(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)
+ {
+ ndbassert(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)
+ {
+ 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
+ {
+ pagePtr.p->list_index = new_idx | 0x8000;
+ }
+ }
+
+ pagePtr.p->uncommitted_used_space = used - sz;
+ extentPtr.p->m_free_space += sz;
+
+ Uint32 old_pos = extentPtr.p->m_free_matrix_pos;
+ if (old_pos != RNIL)
+ {
+ Uint32 pos= alloc.calc_extent_pos(extentPtr.p);
+
+ if (pos != old_pos)
+ {
+ Extent_list old_list(c_extent_pool, alloc.m_free_extents[old_pos]);
+ Extent_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;
+ }
+ }
+}
+
+Uint64
+Dbtup::disk_page_undo_alloc(Page* page, const Local_key* key,
+ Uint32 sz, Uint32 gci, Uint32 logfile_group_id)
+{
+ Logfile_client lsman(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= lsman.add_entry<1>(c);
+ m_pgman.update_lsn(* key, lsn);
+
+ 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)
+{
+ Logfile_client lsman(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= lsman.add_entry<3>(c);
+ m_pgman.update_lsn(* key, lsn);
+
+ 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)
+{
+ Logfile_client lsman(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= lsman.add_entry<3>(c);
+ m_pgman.update_lsn(* key, lsn);
+
+ return lsn;
+}
+
+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.isNull())
+ {
+ Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
+
+ Ptr<Extent_info> ext;
+ ndbrequire(c_extent_pool.seize(ext));
+
+ ext.p->m_key = *key;
+ ndbout << "allocated " << pages << " pages: " << ext.p->m_key << endl;
+ 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
+
+ if (alloc.m_curr_extent_info_ptr_i != RNIL)
+ {
+ 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);
+ Extent_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);
+
+ LocalSLList<Extent_info, Extent_list_t>
+ 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 old_bits, Uint32 bits)
+{
+ 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);
+ Uint32 old_size= alloc.calc_page_free_space(old_bits);
+
+ if (bits != old_bits)
+ {
+ ndbassert(ext.p->m_free_page_count[old_bits] > 0);
+ ndbassert(ext.p->m_free_space >= old_size);
+
+ ext.p->m_free_page_count[bits]++;
+ ext.p->m_free_page_count[old_bits]--;
+
+ ext.p->m_free_space += size;
+ ext.p->m_free_space -= old_size;
+
+ Uint32 old_pos = ext.p->m_free_matrix_pos;
+ if (old_pos != RNIL)
+ {
+ Uint32 pos= alloc.calc_extent_pos(ext.p);
+
+ if (pos != old_pos)
+ {
+ Extent_list old_list(c_extent_pool, alloc.m_free_extents[old_pos]);
+ Extent_list new_list(c_extent_pool, alloc.m_free_extents[pos]);
+ old_list.remove(ext);
+ new_list.add(ext);
+ ext.p->m_free_matrix_pos= pos;
+ }
+ }
+ }
+}
+
+#include <signaldata/LgmanContinueB.hpp>
+
+static Dbtup::Apply_undo f_undo;
+
+void
+Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn,
+ Uint32 type, const Uint32 * ptr, Uint32 len)
+{
+ 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:
+ {
+ ndbrequire(len == 3);
+ Uint32 tableId = ptr[1] >> 16;
+ Uint32 fragId = ptr[1] & 0xFFFF;
+ disk_restart_undo_lcp(tableId, fragId);
+ disk_restart_undo_next(signal);
+ return;
+ }
+ case File_formats::Undofile::UNDO_TUP_ALLOC:
+ {
+ 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:
+ {
+ 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:
+ {
+ 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:
+ /**
+ *
+ */
+ {
+ 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]);
+ disk_restart_undo_next(signal);
+ 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 = Page_cache_client::NO_HOOK;
+ int res= m_pgman.get_page(signal, preq, flags);
+ 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_undo_lcp(Uint32 tableId, Uint32 fragId)
+{
+ Ptr<Tablerec> tabPtr;
+ tabPtr.i= tableId;
+ ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
+
+ if (tabPtr.p->tableStatus == DEFINED)
+ {
+ FragrecordPtr fragPtr;
+ getFragmentrec(fragPtr, fragId, tabPtr.p);
+ if (!fragPtr.isNull())
+ {
+ fragPtr.p->m_undo_complete = true;
+ }
+ }
+}
+
+void
+Dbtup::disk_restart_undo_callback(Signal* signal,
+ Uint32 id,
+ Uint32 page_id)
+{
+ jamEntry();
+ Ptr<GlobalPage> page;
+ m_global_page_pool.getPtr(page, page_id);
+
+ Page* pageP = (Page*)page.p;
+
+ bool update = false;
+ if (! (pageP->list_index & 0x8000) ||
+ pageP->nextList != RNIL ||
+ pageP->prevList != RNIL)
+ {
+ update = true;
+ pageP->list_index |= 0x8000;
+ pageP->nextList = pageP->prevList = RNIL;
+ }
+
+ Ptr<Tablerec> tabPtr;
+ tabPtr.i= pageP->m_table_id;
+ ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
+
+ if (tabPtr.p->tableStatus != DEFINED)
+ {
+ disk_restart_undo_next(signal);
+ return;
+ }
+
+ Ptr<Fragrecord> fragPtr;
+ getFragmentrec(fragPtr, pageP->m_fragment_id, tabPtr.p);
+ if(fragPtr.isNull())
+ {
+ disk_restart_undo_next(signal);
+ return;
+ }
+
+ Local_key key;
+ key.m_page_no = pageP->m_page_no;
+ key.m_file_no = pageP->m_file_no;
+
+ if (pageP->m_restart_seq != globalData.m_restart_seq)
+ {
+ {
+ Extent_info key;
+ key.m_key.m_file_no = pageP->m_file_no;
+ key.m_key.m_page_idx = pageP->m_extent_no;
+ Ptr<Extent_info> extentPtr;
+ if (c_extent_hash.find(extentPtr, key))
+ {
+ pageP->m_extent_info_ptr = extentPtr.i;
+ }
+ else
+ {
+ /**
+ * Extent was not allocated at start of LCP
+ * (or was freed during)
+ * I.e page does not need to be undoed as it's
+ * really free
+ */
+ disk_restart_undo_next(signal);
+ return;
+ }
+ }
+
+ update= true;
+ pageP->m_restart_seq = globalData.m_restart_seq;
+ pageP->uncommitted_used_space = 0;
+
+ Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info;
+ Uint32 idx= alloc.calc_page_free_bits(pageP->free_space);
+
+ pageP->list_index = idx | 0x8000;
+
+ }
+
+ Uint64 lsn = 0;
+ lsn += pageP->m_page_header.m_page_lsn_hi; lsn <<= 32;
+ lsn += pageP->m_page_header.m_page_lsn_lo;
+
+ if (f_undo.m_lsn <= lsn)
+ {
+ Uint32 tableId= pageP->m_table_id;
+ Uint32 fragId = pageP->m_fragment_id;
+
+ f_undo.m_table_ptr.i= tableId;
+ if (tableId < cnoOfTablerec)
+ {
+ ptrCheckGuard(f_undo.m_table_ptr, cnoOfTablerec, tablerec);
+
+ if (f_undo.m_table_ptr.p->tableStatus == DEFINED)
+ {
+ getFragmentrec(f_undo.m_fragment_ptr, fragId, f_undo.m_table_ptr.p);
+ if (!f_undo.m_fragment_ptr.isNull())
+ {
+ if (!f_undo.m_fragment_ptr.p->m_undo_complete)
+ {
+ f_undo.m_page_ptr.i = page_id;
+ f_undo.m_page_ptr.p = pageP;
+
+ update = true;
+ ndbout_c("applying %lld", f_undo.m_lsn);
+ /**
+ * Apply undo record
+ */
+ switch(f_undo.m_type){
+ case File_formats::Undofile::UNDO_TUP_ALLOC:
+ disk_restart_undo_alloc(&f_undo);
+ break;
+ case File_formats::Undofile::UNDO_TUP_UPDATE:
+ disk_restart_undo_update(&f_undo);
+ break;
+ case File_formats::Undofile::UNDO_TUP_FREE:
+ disk_restart_undo_free(&f_undo);
+ break;
+ default:
+ ndbrequire(false);
+ }
+
+ disk_restart_undo_page_bits(&f_undo);
+
+ lsn = f_undo.m_lsn - 1; // make sure undo isn't run again...
+ }
+ else
+ {
+ ndbout_c("lsn %lld frag undo complete", f_undo.m_lsn);
+ }
+ }
+ else
+ {
+ ndbout_c("lsn %lld table not defined", f_undo.m_lsn);
+ }
+ }
+ else
+ {
+ ndbout_c("lsn %lld no such table", f_undo.m_lsn);
+ }
+ }
+ else
+ {
+ ndbout_c("f_undo.m_lsn %lld > lsn %lld -> skip",
+ f_undo.m_lsn, lsn);
+ }
+
+ if (update)
+ {
+ m_pgman.update_lsn(f_undo.m_key, lsn);
+ }
+ }
+
+ 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(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)
+ */
+ Ptr<Extent_info> extentPtr;
+ c_extent_pool.getPtr(extentPtr, undo->m_page_ptr.p->m_extent_info_ptr);
+
+ Uint32 currExtI = alloc.m_curr_extent_info_ptr_i;
+ if (extentPtr.i != currExtI && currExtI != RNIL)
+ {
+ Ptr<Extent_info> currExtPtr;
+ c_extent_pool.getPtr(currExtPtr, currExtI);
+ ndbrequire(currExtPtr.p->m_free_matrix_pos == RNIL);
+
+ Uint32 pos= alloc.calc_extent_pos(currExtPtr.p);
+ Extent_list new_list(c_extent_pool, alloc.m_free_extents[pos]);
+ new_list.add(currExtPtr);
+ currExtPtr.p->m_free_matrix_pos= pos;
+ //ndbout_c("moving extent from %d to %d", old_pos, new_pos);
+ }
+
+ if (extentPtr.i != currExtI)
+ {
+ Uint32 old_pos = extentPtr.p->m_free_matrix_pos;
+ Extent_list old_list(c_extent_pool, alloc.m_free_extents[old_pos]);
+ old_list.remove(extentPtr);
+ alloc.m_curr_extent_info_ptr_i = extentPtr.i;
+ extentPtr.p->m_free_matrix_pos = RNIL;
+ }
+ else
+ {
+ ndbrequire(extentPtr.p->m_free_matrix_pos == RNIL);
+ }
+
+ /**
+ * Compute and update free bits for this page
+ */
+ Uint32 free = undo->m_page_ptr.p->free_space;
+ Uint32 bits = alloc.calc_page_free_bits(free);
+
+ Tablespace_client tsman(0, c_tsman,
+ fragPtrP->fragTableId,
+ fragPtrP->fragmentId,
+ fragPtrP->m_tablespace_id);
+
+ tsman.restart_undo_page_free_bits(&undo->m_key, bits, undo->m_lsn);
+}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 069eb78702b..8e1c1ee43fd 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -16,6 +16,7 @@
#define DBTUP_C
+#include <Dblqh.hpp>
#include "Dbtup.hpp"
#include <RefConvert.hpp>
#include <ndb_limits.h>
@@ -26,12 +27,14 @@
#include <Interpreter.hpp>
#include <signaldata/TupCommit.hpp>
#include <signaldata/TupKey.hpp>
+#include <signaldata/AttrInfo.hpp>
#include <NdbSqlUtil.hpp>
/* ----------------------------------------------------------------- */
/* ----------- INIT_STORED_OPERATIONREC -------------- */
/* ----------------------------------------------------------------- */
int Dbtup::initStoredOperationrec(Operationrec* const regOperPtr,
+ KeyReqStruct* req_struct,
Uint32 storedId)
{
jam();
@@ -40,29 +43,28 @@ int Dbtup::initStoredOperationrec(Operationrec* const regOperPtr,
if (storedPtr.i != RNIL) {
if (storedPtr.p->storedCode == ZSCAN_PROCEDURE) {
storedPtr.p->storedCounter++;
- regOperPtr->firstAttrinbufrec = storedPtr.p->storedLinkFirst;
- regOperPtr->lastAttrinbufrec = storedPtr.p->storedLinkLast;
- regOperPtr->attrinbufLen = storedPtr.p->storedProcLength;
- regOperPtr->currentAttrinbufLen = storedPtr.p->storedProcLength;
+ regOperPtr->firstAttrinbufrec= storedPtr.p->storedLinkFirst;
+ regOperPtr->lastAttrinbufrec= storedPtr.p->storedLinkLast;
+ regOperPtr->currentAttrinbufLen= storedPtr.p->storedProcLength;
+ req_struct->attrinfo_len= storedPtr.p->storedProcLength;
return ZOK;
- }//if
- }//if
- terrorCode = ZSTORED_PROC_ID_ERROR;
+ }
+ }
+ terrorCode= ZSTORED_PROC_ID_ERROR;
return terrorCode;
-}//Dbtup::initStoredOperationrec()
+}
-void Dbtup::copyAttrinfo(Signal* signal,
- Operationrec * const regOperPtr,
+void Dbtup::copyAttrinfo(Operationrec * const regOperPtr,
Uint32* inBuffer)
{
AttrbufrecPtr copyAttrBufPtr;
- Uint32 RnoOfAttrBufrec = cnoOfAttrbufrec;
+ Uint32 RnoOfAttrBufrec= cnoOfAttrbufrec;
int RbufLen;
- Uint32 RinBufIndex = 0;
+ Uint32 RinBufIndex= 0;
Uint32 Rnext;
Uint32 Rfirst;
- Uint32 TstoredProcedure = (regOperPtr->storedProcedureId != ZNIL);
- Uint32 RnoFree = cnoFreeAttrbufrec;
+ Uint32 TstoredProcedure= (regOperPtr->storedProcedureId != ZNIL);
+ Uint32 RnoFree= cnoFreeAttrbufrec;
//-------------------------------------------------------------------------
// As a prelude to the execution of the TUPKEYREQ we will copy the program
@@ -70,793 +72,974 @@ void Dbtup::copyAttrinfo(Signal* signal,
// between the buffers. In particular this will make the interpreter less
// complex. Hopefully it does also improve performance.
//-------------------------------------------------------------------------
- copyAttrBufPtr.i = regOperPtr->firstAttrinbufrec;
+ 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;
+ RbufLen= copyAttrBufPtr.p->attrbuf[ZBUF_DATA_LEN];
+ Rnext= copyAttrBufPtr.p->attrbuf[ZBUF_NEXT];
+ Rfirst= cfirstfreeAttrbufrec;
MEMCOPY_NO_WORDS(&inBuffer[RinBufIndex],
&copyAttrBufPtr.p->attrbuf[0],
RbufLen);
RinBufIndex += RbufLen;
if (!TstoredProcedure) {
- copyAttrBufPtr.p->attrbuf[ZBUF_NEXT] = Rfirst;
- cfirstfreeAttrbufrec = copyAttrBufPtr.i;
+ copyAttrBufPtr.p->attrbuf[ZBUF_NEXT]= Rfirst;
+ cfirstfreeAttrbufrec= copyAttrBufPtr.i;
RnoFree++;
- }//if
- copyAttrBufPtr.i = Rnext;
- }//while
- cnoFreeAttrbufrec = 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--;
- regOperPtr->storedProcedureId = ZNIL;
- }//if
+ }
// Release the ATTRINFO buffers
- regOperPtr->firstAttrinbufrec = RNIL;
- regOperPtr->lastAttrinbufrec = RNIL;
-}//Dbtup::copyAttrinfo()
+ regOperPtr->storedProcedureId= RNIL;
+ regOperPtr->firstAttrinbufrec= RNIL;
+ regOperPtr->lastAttrinbufrec= RNIL;
+}
void Dbtup::handleATTRINFOforTUPKEYREQ(Signal* signal,
- Uint32 length,
+ const Uint32 *data,
+ Uint32 len,
Operationrec * const regOperPtr)
{
- AttrbufrecPtr TAttrinbufptr;
- TAttrinbufptr.i = cfirstfreeAttrbufrec;
- if ((cfirstfreeAttrbufrec < cnoOfAttrbufrec) &&
- (cnoFreeAttrbufrec > MIN_ATTRBUF)) {
- ptrAss(TAttrinbufptr, attrbufrec);
- MEMCOPY_NO_WORDS(&TAttrinbufptr.p->attrbuf[0],
- &signal->theData[3],
- 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;
- return;
- } else {
+ 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();
- ptrCheckGuard(locAttrinbufptr, cnoOfAttrbufrec, attrbufrec);
- locAttrinbufptr.p->attrbuf[ZBUF_NEXT] = TAttrinbufptr.i;
- }//if
- if (RnewLen < ZATTR_BUFFER_SIZE) {
- return;
+ set_trans_state(regOperPtr, TRANS_ERROR_WAIT_TUPKEYREQ);
} else {
- jam();
- regOperPtr->transstate = TOO_MUCH_AI;
- return;
- }//if
- } else if (cnoFreeAttrbufrec <= MIN_ATTRBUF) {
- jam();
- regOperPtr->transstate = ERROR_WAIT_TUPKEYREQ;
- } else {
- ndbrequire(false);
- }//if
-}//Dbtup::handleATTRINFOforTUPKEYREQ()
+ ndbrequire(false);
+ }
+
+ len -= length;
+ data += length;
+ }
+}
void Dbtup::execATTRINFO(Signal* signal)
{
- OperationrecPtr regOpPtr;
- Uint32 Rsig0 = signal->theData[0];
- Uint32 Rlen = signal->length();
- regOpPtr.i = Rsig0;
-
+ Uint32 Rsig0= signal->theData[0];
+ Uint32 Rlen= signal->length();
jamEntry();
- ptrCheckGuard(regOpPtr, cnoOfOprec, operationrec);
- if (regOpPtr.p->transstate == IDLE) {
- handleATTRINFOforTUPKEYREQ(signal, Rlen - 3, regOpPtr.p);
+ 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 (regOpPtr.p->transstate == WAIT_STORED_PROCEDURE_ATTR_INFO) {
- storedProcedureAttrInfo(signal, regOpPtr.p, Rlen - 3, 3, false);
+ } else if (trans_state == TRANS_WAIT_STORED_PROCEDURE_ATTR_INFO) {
+ storedProcedureAttrInfo(signal, regOpPtr.p, data, Rlen, false);
return;
- }//if
- switch (regOpPtr.p->transstate) {
- case ERROR_WAIT_STORED_PROCREQ:
+ }
+ switch (trans_state) {
+ case TRANS_ERROR_WAIT_STORED_PROCREQ:
jam();
- case TOO_MUCH_AI:
+ case TRANS_TOO_MUCH_AI:
jam();
- case ERROR_WAIT_TUPKEYREQ:
+ case TRANS_ERROR_WAIT_TUPKEYREQ:
jam();
return; /* IGNORE ATTRINFO IN THOSE STATES, WAITING FOR ABORT SIGNAL */
- break;
- case DISCONNECTED:
+ case TRANS_DISCONNECTED:
jam();
- case STARTED:
+ case TRANS_STARTED:
jam();
default:
ndbrequire(false);
- }//switch
-}//Dbtup::execATTRINFO()
+ }
+}
void Dbtup::execTUP_ALLOCREQ(Signal* signal)
{
OperationrecPtr regOperPtr;
- TablerecPtr regTabPtr;
- FragrecordPtr regFragPtr;
jamEntry();
- regOperPtr.i = signal->theData[0];
- regFragPtr.i = signal->theData[1];
- regTabPtr.i = signal->theData[2];
+ regOperPtr.i= signal->theData[0];
+ c_operation_pool.getPtr(regOperPtr);
+
+ regOperPtr.p->op_struct.tuple_state= TUPLE_INITIAL_INSERT;
+ //ndbout_c("execTUP_ALLOCREQ");
- if (!((regOperPtr.i < cnoOfOprec) &&
- (regFragPtr.i < cnoOfFragrec) &&
- (regTabPtr.i < cnoOfTablerec))) {
- ndbrequire(false);
- }//if
- ptrAss(regOperPtr, operationrec);
- ptrAss(regFragPtr, fragrecord);
- ptrAss(regTabPtr, tablerec);
-
-//---------------------------------------------------
-/* --- Allocate a tuple as requested by ACC --- */
-//---------------------------------------------------
- PagePtr pagePtr;
- Uint32 pageOffset;
- if (!allocTh(regFragPtr.p,
- regTabPtr.p,
- NORMAL_PAGE,
- signal,
- pageOffset,
- pagePtr)) {
- signal->theData[0] = terrorCode; // Indicate failure
- return;
- }//if
- Uint32 fragPageId = pagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- Uint32 pageIndex = ((pageOffset - ZPAGE_HEADER_SIZE) /
- regTabPtr.p->tupheadsize) << 1;
- regOperPtr.p->tableRef = regTabPtr.i;
- regOperPtr.p->fragId = regFragPtr.p->fragmentId;
- regOperPtr.p->realPageId = pagePtr.i;
- regOperPtr.p->fragPageId = fragPageId;
- regOperPtr.p->pageOffset = pageOffset;
- regOperPtr.p->pageIndex = pageIndex;
- /* -------------------------------------------------------------- */
- /* AN INSERT IS UNDONE BY FREEING THE DATA OCCUPIED BY THE INSERT */
- /* THE ONLY DATA WE HAVE TO LOG EXCEPT THE TYPE, PAGE AND INDEX */
- /* IS THE AMOUNT OF DATA TO FREE */
- /* -------------------------------------------------------------- */
- if (isUndoLoggingNeeded(regFragPtr.p, fragPageId)) {
- jam();
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_DELETE_TH,
- fragPageId,
- pageIndex,
- regTabPtr.i,
- regFragPtr.p->fragmentId,
- regFragPtr.p->checkpointVersion);
- }//if
-
- //---------------------------------------------------------------
- // Initialise Active operation list by setting the list to empty
- //---------------------------------------------------------------
- ndbrequire(pageOffset < ZWORDS_ON_PAGE);
- pagePtr.p->pageWord[pageOffset] = RNIL;
-
- signal->theData[0] = 0;
- signal->theData[1] = fragPageId;
- signal->theData[2] = pageIndex;
-}//Dbtup::execTUP_ALLOCREQ()
+ signal->theData[0]= 0;
+ signal->theData[1]= ~0 >> MAX_TUPLES_BITS;
+ signal->theData[2]= (1 << MAX_TUPLES_BITS) - 1;
+ return;
+
+mem_error:
+ jam();
+ signal->theData[0]= ZMEM_NOMEM_ERROR;
+ return;
+}
void
-Dbtup::setChecksum(Page* const pagePtr, Uint32 tupHeadOffset, Uint32 tupHeadSize)
+Dbtup::setChecksum(Tuple_header* tuple_ptr,
+ Tablerec* const regTabPtr)
{
- // 2 == regTabPtr.p->tupChecksumIndex
- pagePtr->pageWord[tupHeadOffset + 2] = 0;
- Uint32 checksum = calculateChecksum(pagePtr, tupHeadOffset, tupHeadSize);
- pagePtr->pageWord[tupHeadOffset + 2] = checksum;
-}//Dbtup::setChecksum()
+ tuple_ptr->m_checksum= 0;
+ tuple_ptr->m_checksum= calculateChecksum(tuple_ptr, regTabPtr);
+}
Uint32
-Dbtup::calculateChecksum(Page* pagePtr,
- Uint32 tupHeadOffset,
- Uint32 tupHeadSize)
+Dbtup::calculateChecksum(Tuple_header* tuple_ptr,
+ Tablerec* const regTabPtr)
{
- Uint32 checksum = 0;
- Uint32 loopStop = tupHeadOffset + tupHeadSize;
- ndbrequire(loopStop <= ZWORDS_ON_PAGE);
+ 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
- for (Uint32 i = tupHeadOffset + 1; i < loopStop; i++) {
- checksum ^= pagePtr->pageWord[i];
- }//if
+ //printf("%p - ", tuple_ptr);
+
+ if (regTabPtr->m_attributes[MM].m_no_of_varsize)
+ rec_size += Tuple_header::HeaderSize;
+
+ for (i= 0; i < rec_size-2; 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;
-}//Dbtup::calculateChecksum()
+}
/* ----------------------------------------------------------------- */
/* ----------- INSERT_ACTIVE_OP_LIST -------------- */
/* ----------------------------------------------------------------- */
-void Dbtup::insertActiveOpList(Signal* signal,
- OperationrecPtr regOperPtr,
- Page* const pagePtr,
- Uint32 pageOffset)
+bool
+Dbtup::insertActiveOpList(OperationrecPtr regOperPtr,
+ KeyReqStruct* req_struct)
{
- OperationrecPtr iaoPrevOpPtr;
- ndbrequire(regOperPtr.p->inActiveOpList == ZFALSE);
- regOperPtr.p->inActiveOpList = ZTRUE;
- ndbrequire(pageOffset < ZWORDS_ON_PAGE);
- iaoPrevOpPtr.i = pagePtr->pageWord[pageOffset];
- pagePtr->pageWord[pageOffset] = regOperPtr.i;
- regOperPtr.p->prevActiveOp = RNIL;
- regOperPtr.p->nextActiveOp = iaoPrevOpPtr.i;
- if (iaoPrevOpPtr.i == RNIL) {
- return;
+ 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) {
+ return true;
} else {
- jam();
- ptrCheckGuard(iaoPrevOpPtr, cnoOfOprec, operationrec);
- iaoPrevOpPtr.p->prevActiveOp = regOperPtr.i;
- if (iaoPrevOpPtr.p->optype == ZDELETE &&
- regOperPtr.p->optype == ZINSERT) {
- jam();
- // mark both
- iaoPrevOpPtr.p->deleteInsertFlag = 1;
- regOperPtr.p->deleteInsertFlag = 1;
+ 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;
+ regOperPtr.p->m_mask = prevOpPtr.p->m_mask;
+
+ 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;
}
- return;
- }//if
-}//Dbtup::insertActiveOpList()
+ else
+ {
+ terrorCode= ZMUST_BE_ABORTED_ERROR;
+ return false;
+ }
+ }
+}
-void Dbtup::linkOpIntoFragList(OperationrecPtr regOperPtr,
- Fragrecord* const regFragPtr)
-{
- OperationrecPtr sopTmpOperPtr;
- Uint32 tail = regFragPtr->lastusedOprec;
- ndbrequire(regOperPtr.p->inFragList == ZFALSE);
- regOperPtr.p->inFragList = ZTRUE;
- regOperPtr.p->prevOprecInList = tail;
- regOperPtr.p->nextOprecInList = RNIL;
- sopTmpOperPtr.i = tail;
- if (tail == RNIL) {
- regFragPtr->firstusedOprec = regOperPtr.i;
- } else {
- jam();
- ptrCheckGuard(sopTmpOperPtr, cnoOfOprec, operationrec);
- sopTmpOperPtr.p->nextOprecInList = regOperPtr.i;
- }//if
- regFragPtr->lastusedOprec = regOperPtr.i;
-}//Dbtup::linkOpIntoFragList()
-
-/*
-This routine is optimised for use from TUPKEYREQ.
-This means that a lot of input data is stored in the operation record.
-The routine expects the following data in the operation record to be
-set-up properly.
-Transaction data
-1) transid1
-2) transid2
-3) savePointId
-
-Operation data
-4) optype
-5) dirtyOp
-
-Tuple address
-6) fragPageId
-7) pageIndex
-
-regFragPtr and regTabPtr are references to the table and fragment data and
-is read-only.
-
-The routine will set up the following data in the operation record if
-returned with success.
-
-Tuple address data
-1) realPageId
-2) fragPageId
-3) pageOffset
-4) pageIndex
-
-Also the pagePtr is an output variable if the routine returns with success.
-It's input value can be undefined.
-*/
bool
-Dbtup::getPage(PagePtr& pagePtr,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr)
+Dbtup::setup_read(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr,
+ bool disk)
{
-/* ------------------------------------------------------------------------- */
-// GET THE REFERENCE TO THE TUPLE HEADER BY TRANSLATING THE FRAGMENT PAGE ID
-// INTO A REAL PAGE ID AND BY USING THE PAGE INDEX TO DERIVE THE PROPER INDEX
-// IN THE REAL PAGE.
-/* ------------------------------------------------------------------------- */
- pagePtr.i = getRealpid(regFragPtr, regOperPtr->fragPageId);
- regOperPtr->realPageId = pagePtr.i;
- Uint32 RpageIndex = regOperPtr->pageIndex;
- Uint32 Rtupheadsize = regTabPtr->tupheadsize;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 RpageIndexScaled = RpageIndex >> 1;
- ndbrequire((RpageIndex & 1) == 0);
- regOperPtr->pageOffset = ZPAGE_HEADER_SIZE +
- (Rtupheadsize * RpageIndexScaled);
-
- OperationrecPtr leaderOpPtr;
- ndbrequire(regOperPtr->pageOffset < ZWORDS_ON_PAGE);
- leaderOpPtr.i = pagePtr.p->pageWord[regOperPtr->pageOffset];
- if (leaderOpPtr.i == RNIL) {
+ 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;
- }//if
- ptrCheckGuard(leaderOpPtr, cnoOfOprec, operationrec);
- bool dirtyRead = ((regOperPtr->optype == ZREAD) &&
- (regOperPtr->dirtyOp == 1));
- if (dirtyRead) {
- bool sameTrans = ((regOperPtr->transid1 == leaderOpPtr.p->transid1) &&
- (regOperPtr->transid2 == leaderOpPtr.p->transid2));
- if (!sameTrans) {
- if (!getPageLastCommitted(regOperPtr, leaderOpPtr.p)) {
- return false;
- }//if
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- return true;
- }//if
- }//if
- if (regOperPtr->optype == ZREAD) {
- /*
- Read uses savepoint id's to find the correct tuple version.
- */
- if (getPageThroughSavePoint(regOperPtr, leaderOpPtr.p)) {
- jam();
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- return true;
- }
- return false;
}
-//----------------------------------------------------------------------
-// Check that no other operation is already active on the tuple. Also
-// that abort or commit is not ongoing.
-//----------------------------------------------------------------------
- if (leaderOpPtr.p->tupleState == NO_OTHER_OP) {
- jam();
- if ((leaderOpPtr.p->optype == ZDELETE) &&
- (regOperPtr->optype != ZINSERT)) {
- jam();
- terrorCode = ZTUPLE_DELETED_ERROR;
- return false;
- }//if
- return true;
- } else if (leaderOpPtr.p->tupleState == ALREADY_ABORTED) {
- jam();
- terrorCode = ZMUST_BE_ABORTED_ERROR;
- return false;
- } else {
- ndbrequire(false);
- }//if
- return true;
-}//Dbtup::getPage()
-bool
-Dbtup::getPageThroughSavePoint(Operationrec* regOperPtr,
- Operationrec* leaderOpPtr)
-{
- bool found = false;
- OperationrecPtr loopOpPtr;
- loopOpPtr.p = leaderOpPtr;
- while(true) {
- if (regOperPtr->savePointId > loopOpPtr.p->savePointId) {
- jam();
- found = true;
- break;
+ 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;
}
- if (loopOpPtr.p->nextActiveOp == RNIL) {
+
+ OperationrecPtr prevOpPtr = currOpPtr;
+ bool found= false;
+ while(true)
+ {
+ if (savepointId > currOpPtr.p->savepointId) {
+ found= true;
+ break;
+ }
+ if (currOpPtr.p->is_first_operation()){
+ break;
+ }
+ prevOpPtr= currOpPtr;
+ currOpPtr.i = currOpPtr.p->prevActiveOp;
+ c_operation_pool.getPtr(currOpPtr);
+ }
+
+ Uint32 currOp= currOpPtr.p->op_struct.op_type;
+
+ if((found && currOp == ZDELETE) ||
+ ((dirty || !found) && currOp == ZINSERT))
+ {
+ terrorCode= ZTUPLE_DELETED_ERROR;
break;
}
- loopOpPtr.i = loopOpPtr.p->nextActiveOp;
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
+
+ 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;
+}
+
+ bool
+ Dbtup::getPageThroughSavePoint(Operationrec* regOperPtr,
+ Operationrec* leaderOpPtr)
+ {
+ bool found= false;
+ OperationrecPtr loopOpPtr;
+ loopOpPtr.p= leaderOpPtr;
+ int res= 0;
+ while(true) {
+ ndbout_c("%d regOperPtr->savepointId: %d loopOpPtr.p->savepointId: %d",
+ res++, regOperPtr->savepointId, loopOpPtr.p->savepointId);
+ if (regOperPtr->savepointId > loopOpPtr.p->savepointId) {
+ jam();
+ found= true;
+ break;
+ }
+ if (loopOpPtr.p->nextActiveOp == RNIL) {
+ break;
+ }
+ loopOpPtr.i= loopOpPtr.p->nextActiveOp;
+ c_operation_pool.getPtr(loopOpPtr);
+ jam();
+ }
+ if (!found) {
+ return getPageLastCommitted(regOperPtr, loopOpPtr.p);
+ } else {
+ if (loopOpPtr.p->op_struct.op_type == ZDELETE) {
+ jam();
+ terrorCode= ZTUPLE_DELETED_ERROR;
+ return false;
+ }
+ if (get_tuple_state(loopOpPtr.p) == TUPLE_ALREADY_ABORTED) {
+ /*
+ Requested tuple version has already been aborted
+ */
+ jam();
+ terrorCode= ZMUST_BE_ABORTED_ERROR;
+ return false;
+ }
+ bool use_copy;
+ if (loopOpPtr.p->prevActiveOp == RNIL) {
+ jam();
+ /*
+ Use original tuple since we are reading from the last written tuple.
+ We are the
+ */
+ use_copy= false;
+ } else {
+ /*
+ Go forward in time to find a copy of the tuple which this operation
+ produced
+ */
+ loopOpPtr.i= loopOpPtr.p->prevActiveOp;
+ c_operation_pool.getPtr(loopOpPtr);
+ if (loopOpPtr.p->op_struct.op_type == ZDELETE) {
+ /*
+ This operation was a Delete and thus have no copy tuple attached to
+ it. We will move forward to the next that either doesn't exist in
+ which case we will return the original tuple of any operation and
+ otherwise it must be an insert which contains a copy record.
+ */
+ if (loopOpPtr.p->prevActiveOp == RNIL) {
+ jam();
+ use_copy= false;
+ } else {
+ jam();
+ loopOpPtr.i= loopOpPtr.p->prevActiveOp;
+ c_operation_pool.getPtr(loopOpPtr);
+ ndbrequire(loopOpPtr.p->op_struct.op_type == ZINSERT);
+ use_copy= true;
+ }
+ } else if (loopOpPtr.p->op_struct.op_type == ZUPDATE) {
+ jam();
+ /*
+ This operation which was the next in time have a copy which was the
+ result of the previous operation which we want to use. Thus use
+ the copy tuple of this operation.
+ */
+ use_copy= true;
+ } else {
+ /*
+ This operation was an insert that happened after an insert or update.
+ This is not a possible case.
+ */
+ ndbrequire(false);
+ return false;
+ }
+ }
+ if (use_copy) {
+ ndbrequire(false);
+ regOperPtr->m_tuple_location= loopOpPtr.p->m_copy_tuple_location;
+ } else {
+ regOperPtr->m_tuple_location= loopOpPtr.p->m_tuple_location;
+ }
+ return true;
+ }
+ }
+
+ bool
+ Dbtup::getPageLastCommitted(Operationrec* const regOperPtr,
+ Operationrec* const leaderOpPtr)
+ {
+ //----------------------------------------------------------------------
+ // Dirty reads wants to read the latest committed tuple. The latest
+ // tuple value could be not existing or else we have to find the copy
+ // tuple. Start by finding the end of the list to find the first operation
+ // on the record in the ongoing transaction.
+ //----------------------------------------------------------------------
+ jam();
+ OperationrecPtr loopOpPtr;
+ loopOpPtr.p= leaderOpPtr;
+ while (loopOpPtr.p->nextActiveOp != RNIL) {
+ jam();
+ loopOpPtr.i= loopOpPtr.p->nextActiveOp;
+ c_operation_pool.getPtr(loopOpPtr);
+ }
+ if (loopOpPtr.p->op_struct.op_type == ZINSERT) {
+ jam();
+ //----------------------------------------------------------------------
+ // With an insert in the start of the list we know that the tuple did not
+ // exist before this transaction was started. We don't care if the current
+ // transaction is in the commit phase since the commit is not really
+ // completed until the operation is gone from TUP.
+ //----------------------------------------------------------------------
+ terrorCode= ZTUPLE_DELETED_ERROR;
+ return false;
+ } else {
+ //----------------------------------------------------------------------
+ // A successful update and delete as first in the queue means that a tuple
+ // exist in the committed world. We need to find it.
+ //----------------------------------------------------------------------
+ if (loopOpPtr.p->op_struct.op_type == ZUPDATE) {
+ jam();
+ //----------------------------------------------------------------------
+ // The first operation was a delete we set our tuple reference to the
+ // copy tuple of this operation.
+ //----------------------------------------------------------------------
+ ndbrequire(false);
+ regOperPtr->m_tuple_location= loopOpPtr.p->m_copy_tuple_location;
+ } else if ((loopOpPtr.p->op_struct.op_type == ZDELETE) &&
+ (loopOpPtr.p->prevActiveOp == RNIL)) {
+ jam();
+ //----------------------------------------------------------------------
+ // There was only a delete. The original tuple still is ok.
+ //----------------------------------------------------------------------
+ } else {
+ jam();
+ //----------------------------------------------------------------------
+ // There was another operation after the delete, this must be an insert
+ // and we have found our copy tuple there.
+ //----------------------------------------------------------------------
+ loopOpPtr.i= loopOpPtr.p->prevActiveOp;
+ c_operation_pool.getPtr(loopOpPtr);
+ ndbrequire(loopOpPtr.p->op_struct.op_type == ZINSERT);
+ ndbrequire(false);
+ regOperPtr->m_tuple_location = loopOpPtr.p->m_copy_tuple_location;
+ }
+ }
+ return true;
+ }
+
+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(regOperPtr->op_struct.tuple_state == TUPLE_INITIAL_INSERT)
+ {
jam();
- }
- if (!found) {
- return getPageLastCommitted(regOperPtr, loopOpPtr.p);
- } else {
- if (loopOpPtr.p->optype == ZDELETE) {
- jam();
- terrorCode = ZTUPLE_DELETED_ERROR;
- return false;
+ 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;
+ Uint32 opPtr= ptr->m_operation_ptr_i;
+ 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);
+
+ // Make sure we maintain order
+ flags |= Page_cache_client::STRICT_ORDER;
+ 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
}
- if (loopOpPtr.p->tupleState == ALREADY_ABORTED) {
- /*
- Requested tuple version has already been aborted
- */
- jam();
- terrorCode = ZMUST_BE_ABORTED_ERROR;
- return false;
+ else
+ {
+ // Error
}
- bool use_copy;
- if (loopOpPtr.p->prevActiveOp == RNIL) {
- jam();
- /*
- Use original tuple since we are reading from the last written tuple.
- We are the
- */
- use_copy = false;
- } else {
- /*
- Go forward in time to find a copy of the tuple which this operation
- produced
- */
- loopOpPtr.i = loopOpPtr.p->prevActiveOp;
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- if (loopOpPtr.p->optype == ZDELETE) {
- /*
- This operation was a Delete and thus have no copy tuple attached to
- it. We will move forward to the next that either doesn't exist in
- which case we will return the original tuple of any operation and
- otherwise it must be an insert which contains a copy record.
- */
- if (loopOpPtr.p->prevActiveOp == RNIL) {
- jam();
- use_copy = false;
- } else {
- jam();
- loopOpPtr.i = loopOpPtr.p->prevActiveOp;
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- ndbrequire(loopOpPtr.p->optype == ZINSERT);
- use_copy = true;
- }
- } else if (loopOpPtr.p->optype == ZUPDATE) {
- jam();
- /*
- This operation which was the next in time have a copy which was the
- result of the previous operation which we want to use. Thus use
- the copy tuple of this operation.
- */
- use_copy = true;
- } else {
- /*
- This operation was an insert that happened after an insert or update.
- This is not a possible case.
- */
- ndbrequire(false);
- return false;
- }
+ }
+
+ 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;
+ Uint32 opPtr= ptr->m_operation_ptr_i;
+ 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);
+
+ // Make sure we maintain order
+ flags |= Page_cache_client::STRICT_ORDER;
+ 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
}
- if (use_copy) {
- regOperPtr->realPageId = loopOpPtr.p->realPageIdC;
- regOperPtr->fragPageId = loopOpPtr.p->fragPageIdC;
- regOperPtr->pageIndex = loopOpPtr.p->pageIndexC;
- regOperPtr->pageOffset = loopOpPtr.p->pageOffsetC;
- } else {
- regOperPtr->realPageId = loopOpPtr.p->realPageId;
- regOperPtr->fragPageId = loopOpPtr.p->fragPageId;
- regOperPtr->pageIndex = loopOpPtr.p->pageIndex;
- regOperPtr->pageOffset = loopOpPtr.p->pageOffset;
+ else
+ {
+ // Error
}
- return true;
}
+ return res;
}
-bool
-Dbtup::getPageLastCommitted(Operationrec* const regOperPtr,
- Operationrec* const leaderOpPtr)
+void
+Dbtup::disk_page_load_scan_callback(Signal* signal,
+ Uint32 opRec, Uint32 page_id)
{
-//----------------------------------------------------------------------
-// Dirty reads wants to read the latest committed tuple. The latest
-// tuple value could be not existing or else we have to find the copy
-// tuple. Start by finding the end of the list to find the first operation
-// on the record in the ongoing transaction.
-//----------------------------------------------------------------------
- jam();
- OperationrecPtr loopOpPtr;
- loopOpPtr.p = leaderOpPtr;
- while (loopOpPtr.p->nextActiveOp != RNIL) {
- jam();
- loopOpPtr.i = loopOpPtr.p->nextActiveOp;
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- }//while
- if (loopOpPtr.p->optype == ZINSERT) {
- jam();
-//----------------------------------------------------------------------
-// With an insert in the start of the list we know that the tuple did not
-// exist before this transaction was started. We don't care if the current
-// transaction is in the commit phase since the commit is not really
-// completed until the operation is gone from TUP.
-//----------------------------------------------------------------------
- terrorCode = ZTUPLE_DELETED_ERROR;
- return false;
- } else {
-//----------------------------------------------------------------------
-// A successful update and delete as first in the queue means that a tuple
-// exist in the committed world. We need to find it.
-//----------------------------------------------------------------------
- if (loopOpPtr.p->optype == ZUPDATE) {
- jam();
-//----------------------------------------------------------------------
-// The first operation was a delete we set our tuple reference to the
-// copy tuple of this operation.
-//----------------------------------------------------------------------
- regOperPtr->realPageId = loopOpPtr.p->realPageIdC;
- regOperPtr->fragPageId = loopOpPtr.p->fragPageIdC;
- regOperPtr->pageIndex = loopOpPtr.p->pageIndexC;
- regOperPtr->pageOffset = loopOpPtr.p->pageOffsetC;
- } else if ((loopOpPtr.p->optype == ZDELETE) &&
- (loopOpPtr.p->prevActiveOp == RNIL)) {
- jam();
-//----------------------------------------------------------------------
-// There was only a delete. The original tuple still is ok.
-//----------------------------------------------------------------------
- } else {
- jam();
-//----------------------------------------------------------------------
-// There was another operation after the delete, this must be an insert
-// and we have found our copy tuple there.
-//----------------------------------------------------------------------
- loopOpPtr.i = loopOpPtr.p->prevActiveOp;
- ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec);
- ndbrequire(loopOpPtr.p->optype == ZINSERT);
- regOperPtr->realPageId = loopOpPtr.p->realPageIdC;
- regOperPtr->fragPageId = loopOpPtr.p->fragPageIdC;
- regOperPtr->pageIndex = loopOpPtr.p->pageIndexC;
- regOperPtr->pageOffset = loopOpPtr.p->pageOffsetC;
- }//if
- }//if
- return true;
-}//Dbtup::getPageLastCommitted()
+ 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 * const tupKeyReq = (TupKeyReq *)signal->getDataPtr();
- Uint32 RoperPtr = tupKeyReq->connectPtr;
- Uint32 Rtabptr = tupKeyReq->tableRef;
- Uint32 RfragId = tupKeyReq->fragId;
- Uint32 Rstoredid = tupKeyReq->storedProcedure;
- Uint32 Rfragptr = tupKeyReq->fragPtr;
-
- Uint32 RnoOfOprec = cnoOfOprec;
- Uint32 RnoOfTablerec = cnoOfTablerec;
- Uint32 RnoOfFragrec = cnoOfFragrec;
-
- operPtr.i = RoperPtr;
- fragptr.i = Rfragptr;
- tabptr.i = Rtabptr;
- jamEntry();
-
- ndbrequire(((RoperPtr < RnoOfOprec) &&
- (Rtabptr < RnoOfTablerec) &&
- (Rfragptr < RnoOfFragrec)));
- ptrAss(operPtr, operationrec);
- Operationrec * const regOperPtr = operPtr.p;
- ptrAss(fragptr, fragrecord);
- Fragrecord * const regFragPtr = fragptr.p;
- ptrAss(tabptr, tablerec);
- Tablerec* const regTabPtr = tabptr.p;
-
- Uint32 TrequestInfo = tupKeyReq->request;
+ TupKeyReq * const 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;
+ 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;
+ req_struct.frag_page_id= sig4;
+
+ 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;
+
+ Uint32 Roptype = regOperPtr->op_struct.op_type;
+
+ if (Rstoredid != ZNIL) {
+ ndbrequire(initStoredOperationrec(regOperPtr,
+ &req_struct,
+ Rstoredid) == ZOK);
+ }
+
+ copyAttrinfo(regOperPtr, &cinBuffer[0]);
+
+ if(Roptype == ZINSERT && get_tuple_state(regOperPtr)== TUPLE_INITIAL_INSERT)
+ {
+ // 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();
+ tupkeyErrorLab(signal);
+ return;
+ }
+ }
+ checkImmediateTriggersAfterInsert(&req_struct,
+ regOperPtr,
+ regTabPtr);
+ 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();
+ tupkeyErrorLab(signal);
+ return;
+ }
+ }
+ checkImmediateTriggersAfterUpdate(&req_struct,
+ regOperPtr,
+ regTabPtr);
+ // 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();
+ if (handleDeleteReq(signal, regOperPtr,
+ regFragPtr, regTabPtr, &req_struct) == -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);
+ set_change_mask_state(regOperPtr, DELETE_CHANGES);
+ req_struct.log_size= 0;
+ sendTUPKEYCONF(signal, &req_struct, regOperPtr);
+ return;
+ }
+ else
+ {
+ ndbrequire(false); // Invalid op type
+ }
+ }
+
+ tupkeyErrorLab(signal);
+ }
- if (regOperPtr->transstate != IDLE) {
- TUPKEY_abort(signal, 39);
- return;
- }//if
-/* ----------------------------------------------------------------- */
-// Operation is ZREAD when we arrive here so no need to worry about the
-// abort process.
-/* ----------------------------------------------------------------- */
-/* ----------- INITIATE THE OPERATION RECORD -------------- */
-/* ----------------------------------------------------------------- */
- regOperPtr->fragmentPtr = Rfragptr;
- regOperPtr->dirtyOp = TrequestInfo & 1;
- regOperPtr->opSimple = (TrequestInfo >> 1) & 1;
- regOperPtr->interpretedExec = (TrequestInfo >> 10) & 1;
- regOperPtr->optype = (TrequestInfo >> 6) & 0xf;
-
- // Attributes needed by trigger execution
- regOperPtr->noFiredTriggers = 0;
- regOperPtr->tableRef = Rtabptr;
- regOperPtr->tcOperationPtr = tupKeyReq->opRef;
- regOperPtr->primaryReplica = tupKeyReq->primaryReplica;
- regOperPtr->coordinatorTC = tupKeyReq->coordinatorTC;
- regOperPtr->tcOpIndex = tupKeyReq->tcOpIndex;
- regOperPtr->savePointId = tupKeyReq->savePointId;
-
- regOperPtr->fragId = RfragId;
-
- regOperPtr->fragPageId = tupKeyReq->keyRef1;
- regOperPtr->pageIndex = tupKeyReq->keyRef2;
- regOperPtr->attrinbufLen = regOperPtr->logSize = tupKeyReq->attrBufLen;
- regOperPtr->recBlockref = tupKeyReq->applRef;
-
-// Schema Version in tupKeyReq->schemaVersion not used in this version
- regOperPtr->storedProcedureId = Rstoredid;
- regOperPtr->transid1 = tupKeyReq->transId1;
- regOperPtr->transid2 = tupKeyReq->transId2;
-
- regOperPtr->attroutbufLen = 0;
-/* ----------------------------------------------------------------------- */
-// INITIALISE TO DEFAULT VALUE
-// INIT THE COPY REFERENCE RECORDS TO RNIL TO ENSURE THAT THEIR VALUES
-// ARE VALID IF THEY EXISTS
-// NO PENDING CHECKPOINT WHEN COPY CREATED (DEFAULT)
-// NO TUPLE HAS BEEN ALLOCATED YET
-// NO COPY HAS BEEN CREATED YET
-/* ----------------------------------------------------------------------- */
- regOperPtr->undoLogged = false;
- regOperPtr->realPageId = RNIL;
- regOperPtr->realPageIdC = RNIL;
- regOperPtr->fragPageIdC = RNIL;
-
- regOperPtr->pageOffset = ZNIL;
- regOperPtr->pageOffsetC = ZNIL;
-
- regOperPtr->pageIndexC = ZNIL;
-
- // version not yet known
- regOperPtr->tupVersion = ZNIL;
- regOperPtr->deleteInsertFlag = 0;
-
- regOperPtr->tupleState = TUPLE_BLOCKED;
- regOperPtr->changeMask.clear();
+void
+Dbtup::setup_fixed_part(KeyReqStruct* req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const regTabPtr)
+{
+ PagePtr page_ptr;
+ Uint32* ptr= get_ptr(&page_ptr, &regOperPtr->m_tuple_location, regTabPtr);
+ req_struct->m_page_ptr_p= page_ptr.p;
+ req_struct->m_tuple_ptr= (Tuple_header*)ptr;
- if (Rstoredid != ZNIL) {
- ndbrequire(initStoredOperationrec(regOperPtr, Rstoredid) == ZOK);
- }//if
- copyAttrinfo(signal, regOperPtr, &cinBuffer[0]);
-
- PagePtr pagePtr;
- if (!getPage(pagePtr, regOperPtr, regFragPtr, regTabPtr)) {
- tupkeyErrorLab(signal);
- return;
- }//if
+ ndbassert(! (req_struct->m_tuple_ptr->m_header_bits & Tuple_header::FREE));
- Uint32 Roptype = regOperPtr->optype;
- if (Roptype == ZREAD) {
- jam();
- if (handleReadReq(signal, regOperPtr, regTabPtr, pagePtr.p) != -1) {
- sendTUPKEYCONF(signal, regOperPtr, 0);
-/* ------------------------------------------------------------------------- */
-// 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.
-/* ------------------------------------------------------------------------- */
- regOperPtr->transstate = IDLE;
- regOperPtr->currentAttrinbufLen = 0;
- }//if
- return;
- }//if
- linkOpIntoFragList(operPtr, regFragPtr);
- insertActiveOpList(signal,
- operPtr,
- pagePtr.p,
- regOperPtr->pageOffset);
- if (isUndoLoggingBlocked(regFragPtr)) {
- TUPKEY_abort(signal, 38);
- return;
- }//if
-/* ---------------------------------------------------------------------- */
-// WE SET THE CURRENT ACTIVE OPERATION IN THE TUPLE TO POINT TO OUR
-//OPERATION RECORD. IF SEVERAL OPERATIONS WORK ON THIS TUPLE THEY ARE
-// LINKED TO OUR OPERATION RECORD. DIRTY READS CAN ACCESS THE COPY
-// TUPLE THROUGH OUR OPERATION RECORD.
-/* ---------------------------------------------------------------------- */
- if (Roptype == ZINSERT) {
- jam();
- if (handleInsertReq(signal, regOperPtr,
- regFragPtr, regTabPtr, pagePtr.p) == -1) {
- return;
- }//if
- if (!regTabPtr->tuxCustomTriggers.isEmpty()) {
- jam();
- if (executeTuxInsertTriggers(signal, regOperPtr, regTabPtr) != 0) {
- jam();
- tupkeyErrorLab(signal);
- return;
- }
- }
- checkImmediateTriggersAfterInsert(signal,
- regOperPtr,
- regTabPtr);
- sendTUPKEYCONF(signal, regOperPtr, regOperPtr->logSize);
- return;
- }//if
- if (regTabPtr->checksumIndicator &&
- (calculateChecksum(pagePtr.p,
- regOperPtr->pageOffset,
- regTabPtr->tupheadsize) != 0)) {
- jam();
- terrorCode = ZTUPLE_CORRUPTED_ERROR;
- tupkeyErrorLab(signal);
- return;
- }//if
- if (Roptype == ZUPDATE) {
- jam();
- if (handleUpdateReq(signal, regOperPtr,
- regFragPtr, regTabPtr, pagePtr.p) == -1) {
- return;
- }//if
- // If update operation is done on primary,
- // check any after op triggers
- terrorCode = 0;
- if (!regTabPtr->tuxCustomTriggers.isEmpty()) {
- jam();
- if (executeTuxUpdateTriggers(signal, regOperPtr, regTabPtr) != 0) {
- jam();
- tupkeyErrorLab(signal);
- return;
- }
- }
- checkImmediateTriggersAfterUpdate(signal,
- regOperPtr,
- regTabPtr);
- // XXX use terrorCode for now since all methods are void
- if (terrorCode != 0) {
- tupkeyErrorLab(signal);
- return;
- }
- sendTUPKEYCONF(signal, regOperPtr, regOperPtr->logSize);
- return;
- } else if (Roptype == ZDELETE) {
- jam();
- if (handleDeleteReq(signal, regOperPtr,
- regFragPtr, regTabPtr, pagePtr.p) == -1) {
- return;
- }//if
- // If delete operation is done on primary,
- // check any after op triggers
- if (!regTabPtr->tuxCustomTriggers.isEmpty()) {
- jam();
- if (executeTuxDeleteTriggers(signal, regOperPtr, regTabPtr) != 0) {
- jam();
- tupkeyErrorLab(signal);
- return;
- }
- }
- checkImmediateTriggersAfterDelete(signal,
- regOperPtr,
- regTabPtr);
- sendTUPKEYCONF(signal, regOperPtr, 0);
- return;
- } else {
- ndbrequire(false);
- }//if
-}//Dbtup::execTUPKEYREQ()
+ 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,
- Operationrec * const regOperPtr,
- Uint32 TlogSize)
+ /* ---------------------------------------------------------------- */
+ /* ------------------------ CONFIRM REQUEST ----------------------- */
+ /* ---------------------------------------------------------------- */
+ void Dbtup::sendTUPKEYCONF(Signal* signal,
+ KeyReqStruct *req_struct,
+ Operationrec * const regOperPtr)
{
- TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtrSend();
-
- Uint32 RuserPointer = regOperPtr->userpointer;
- Uint32 RattroutbufLen = regOperPtr->attroutbufLen;
- Uint32 RnoFiredTriggers = regOperPtr->noFiredTriggers;
- BlockReference Ruserblockref = regOperPtr->userblockref;
- Uint32 lastRow = regOperPtr->lastRow;
-
- regOperPtr->transstate = STARTED;
- regOperPtr->tupleState = NO_OTHER_OP;
- tupKeyConf->userPtr = RuserPointer;
- tupKeyConf->readLength = RattroutbufLen;
- tupKeyConf->writeLength = TlogSize;
- tupKeyConf->noFiredTriggers = RnoFiredTriggers;
- tupKeyConf->lastRow = lastRow;
-
- EXECUTE_DIRECT(refToBlock(Ruserblockref), GSN_TUPKEYCONF, signal,
+ TupKeyConf * const tupKeyConf= (TupKeyConf *)signal->getDataPtrSend();
+
+ 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;
+
+ EXECUTE_DIRECT(DBLQH, GSN_TUPKEYCONF, signal,
TupKeyConf::SignalLength);
- return;
-}//Dbtup::sendTUPKEYCONF()
+
+}
+
#define MAX_READ (sizeof(signal->theData) > MAX_MESSAGE_SIZE ? MAX_MESSAGE_SIZE : sizeof(signal->theData))
@@ -866,39 +1049,37 @@ void Dbtup::sendTUPKEYCONF(Signal* signal,
int Dbtup::handleReadReq(Signal* signal,
Operationrec* const regOperPtr,
Tablerec* const regTabPtr,
- Page* pagePtr)
+ KeyReqStruct* req_struct)
{
- Uint32 Ttupheadoffset = regOperPtr->pageOffset;
- const BlockReference sendBref = regOperPtr->recBlockref;
+ Uint32 *dst;
+ Uint32 dstLen, start_index;
+ const BlockReference sendBref= req_struct->rec_blockref;
if (regTabPtr->checksumIndicator &&
- (calculateChecksum(pagePtr, Ttupheadoffset,
- regTabPtr->tupheadsize) != 0)) {
+ (calculateChecksum(req_struct->m_tuple_ptr, regTabPtr) != 0)) {
jam();
- terrorCode = ZTUPLE_CORRUPTED_ERROR;
+ ndbout_c("here2");
+ terrorCode= ZTUPLE_CORRUPTED_ERROR;
tupkeyErrorLab(signal);
return -1;
- }//if
+ }
- Uint32 * dst = &signal->theData[25];
- Uint32 dstLen = (MAX_READ / 4) - 25;
const Uint32 node = refToNode(sendBref);
if(node != 0 && node != getOwnNodeId()) {
- ;
+ start_index= 25;
} else {
jam();
/**
* execute direct
*/
- dst = &signal->theData[3];
- dstLen = (MAX_READ / 4) - 3;
+ start_index= 3;
}
-
- if (regOperPtr->interpretedExec != 1) {
+ dst= &signal->theData[start_index];
+ dstLen= (MAX_READ / 4) - start_index;
+ if (!req_struct->interpreted_exec) {
jam();
- int ret = readAttributes(pagePtr,
- Ttupheadoffset,
+ int ret = readAttributes(req_struct,
&cinBuffer[0],
- regOperPtr->attrinbufLen,
+ req_struct->attrinfo_len,
dst,
dstLen,
false);
@@ -908,155 +1089,400 @@ int Dbtup::handleReadReq(Signal* signal,
/* ------------------------------------------------------------------------- */
jam();
Uint32 TnoOfDataRead= (Uint32) ret;
- regOperPtr->attroutbufLen = TnoOfDataRead;
- sendReadAttrinfo(signal, TnoOfDataRead, regOperPtr);
+ req_struct->read_length= TnoOfDataRead;
+ sendReadAttrinfo(signal, req_struct, TnoOfDataRead, regOperPtr);
return 0;
- }//if
+ }
jam();
tupkeyErrorLab(signal);
return -1;
} else {
jam();
- regOperPtr->lastRow = 0;
- if (interpreterStartLab(signal, pagePtr, Ttupheadoffset) != -1) {
+ if (interpreterStartLab(signal, req_struct) != -1) {
return 0;
- }//if
+ }
return -1;
- }//if
-}//Dbtup::handleReadReq()
+ }
+}
/* ---------------------------------------------------------------- */
/* ---------------------------- UPDATE ---------------------------- */
/* ---------------------------------------------------------------- */
int Dbtup::handleUpdateReq(Signal* signal,
- Operationrec* const regOperPtr,
+ Operationrec* const operPtrP,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
- Page* const pagePtr)
+ KeyReqStruct* req_struct,
+ bool disk)
{
- PagePtr copyPagePtr;
- Uint32 tuple_size = regTabPtr->tupheadsize;
-
-//---------------------------------------------------
-/* --- MAKE A COPY OF THIS TUPLE ON A COPY PAGE --- */
-//---------------------------------------------------
- Uint32 RpageOffsetC;
- if (!allocTh(regFragPtr,
- regTabPtr,
- COPY_PAGE,
- signal,
- RpageOffsetC,
- copyPagePtr)) {
- TUPKEY_abort(signal, 1);
- return -1;
- }//if
- Uint32 RpageIdC = copyPagePtr.i;
- Uint32 RfragPageIdC = copyPagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- Uint32 indexC = ((RpageOffsetC - ZPAGE_HEADER_SIZE) / tuple_size) << 1;
- regOperPtr->pageIndexC = indexC;
- regOperPtr->fragPageIdC = RfragPageIdC;
- regOperPtr->realPageIdC = RpageIdC;
- regOperPtr->pageOffsetC = RpageOffsetC;
- /* -------------------------------------------------------------- */
- /* IF WE HAVE AN ONGING CHECKPOINT WE HAVE TO LOG THE ALLOCATION */
- /* OF THE TUPLE HEADER TO BE ABLE TO DELETE IT UPON RESTART */
- /* THE ONLY DATA EXCEPT THE TYPE, PAGE, INDEX IS THE SIZE TO FREE */
- /* -------------------------------------------------------------- */
- if (isUndoLoggingActive(regFragPtr)) {
- if (isPageUndoLogged(regFragPtr, RfragPageIdC)) {
- jam();
- regOperPtr->undoLogged = true;
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_DELETE_TH,
- RfragPageIdC,
- indexC,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- }//if
- if (isPageUndoLogged(regFragPtr, regOperPtr->fragPageId)) {
- jam();
- cprAddUndoLogRecord(signal,
- ZLCPR_TYPE_UPDATE_TH,
- regOperPtr->fragPageId,
- regOperPtr->pageIndex,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- cprAddData(signal,
- regFragPtr,
- regOperPtr->realPageId,
- tuple_size,
- regOperPtr->pageOffset);
- }//if
- }//if
- Uint32 RwordCount = tuple_size - 1;
- Uint32 end_dest = RpageOffsetC + tuple_size;
- Uint32 offset = regOperPtr->pageOffset;
- Uint32 end_source = offset + tuple_size;
- ndbrequire(end_dest <= ZWORDS_ON_PAGE && end_source <= ZWORDS_ON_PAGE);
- void* Tdestination = (void*)&copyPagePtr.p->pageWord[RpageOffsetC + 1];
- const void* Tsource = (void*)&pagePtr->pageWord[offset + 1];
- MEMCOPY_NO_WORDS(Tdestination, Tsource, RwordCount);
-
- Uint32 prev_tup_version;
- // nextActiveOp is before this op in event order
- if (regOperPtr->nextActiveOp == RNIL) {
+ 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->checksumIndicator &&
+ (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(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;
+
+ int retValue;
+ if (!req_struct->interpreted_exec) {
jam();
- prev_tup_version = ((const Uint32*)Tsource)[0];
+ retValue= updateAttributes(req_struct,
+ &cinBuffer[0],
+ req_struct->attrinfo_len);
} else {
- OperationrecPtr prevOperPtr;
jam();
- prevOperPtr.i = regOperPtr->nextActiveOp;
- ptrCheckGuard(prevOperPtr, cnoOfOprec, operationrec);
- prev_tup_version = prevOperPtr.p->tupVersion;
- }//if
- regOperPtr->tupVersion = (prev_tup_version + 1) &
- ((1 << ZTUP_VERSION_BITS) - 1);
- // global variable alert
- ndbassert(operationrec + operPtr.i == regOperPtr);
- copyPagePtr.p->pageWord[RpageOffsetC] = operPtr.i;
-
- return updateStartLab(signal, regOperPtr, regTabPtr, pagePtr);
-}//Dbtup::handleUpdateReq()
+ retValue= interpreterStartLab(signal, req_struct);
+ }
+
+ if (retValue == -1) {
+ goto error;
+ }
+
+ 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->checksumIndicator) {
+ jam();
+ setChecksum(req_struct->m_tuple_ptr, regTabPtr);
+ }
+ return retValue;
+
+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_var_part_ptr(regTabPtr);
+
+ 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;
+ for(Uint32 i= 0; i<cnt1; i++)
+ {
+ dst->m_offset_array_ptr[i]= pos;
+ pos += AttributeDescriptor::getSizeInBytes(tab_descr[*order++].tabDescr);
+ }
+ }
+ else
+ {
+ ptr -= Tuple_header::HeaderSize;
+ }
+
+ req_struct->m_disk_ptr= (Tuple_header*)ptr;
+
+ if(cnt2)
+ {
+ KeyReqStruct::Var_data *dst= &req_struct->m_var_data[DD];
+ ptr=((Tuple_header*)ptr)->m_data+regTabPtr->m_offsets[DD].m_varpart_offset;
+ dst->m_data_ptr= (char*)(((Uint16*)ptr)+cnt2+1);
+ dst->m_offset_array_ptr= req_struct->var_pos_array + (cnt1 << 1);
+ dst->m_var_len_offset= cnt2;
+ dst->m_max_var_offset= regTabPtr->m_offsets[DD].m_max_var_offset;
+ }
+
+ // 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,
- Operationrec* const regOperPtr,
- Fragrecord* const regFragPtr,
+ Ptr<Operationrec> regOperPtr,
+ Ptr<Fragrecord> fragPtr,
Tablerec* const regTabPtr,
- Page* const pagePtr)
+ KeyReqStruct *req_struct)
{
- Uint32 ret_value;
+ Fragrecord* regFragPtr = fragPtr.p;
+ Uint32 *dst, *ptr= 0;
+ Tuple_header *base= req_struct->m_tuple_ptr, *org= base;
+ Tuple_header *tuple_ptr;
+ if ((dst=
+ c_undo_buffer.alloc_copy_tuple(&regOperPtr.p->m_copy_tuple_location,
+ regTabPtr->total_rec_size)) == 0)
+ {
+ goto mem_error;
+ }
+ tuple_ptr= req_struct->m_tuple_ptr= (Tuple_header*)dst;
- if (regOperPtr->nextActiveOp != RNIL) {
- jam();
- OperationrecPtr prevExecOpPtr;
- prevExecOpPtr.i = regOperPtr->nextActiveOp;
- ptrCheckGuard(prevExecOpPtr, cnoOfOprec, operationrec);
- if (prevExecOpPtr.p->optype != ZDELETE) {
- terrorCode = ZINSERT_ERROR;
- tupkeyErrorLab(signal);
- return -1;
- }//if
- ret_value = handleUpdateReq(signal, regOperPtr,
- regFragPtr, regTabPtr, pagePtr);
- } else {
- jam();
- regOperPtr->tupVersion = 0;
- ret_value = updateStartLab(signal, regOperPtr, regTabPtr, pagePtr);
- }//if
- if (ret_value != (Uint32)-1) {
- if (checkNullAttributes(regOperPtr, regTabPtr)) {
+ if(0)
+ ndbout << "dst: " << hex << UintPtr(dst) << " - "
+ << regOperPtr.p->m_copy_tuple_location << endl;
+
+
+ Uint32 tup_version;
+ union {
+ Uint32 sizes[4];
+ Uint64 cmp[2];
+ };
+ if(regOperPtr.p->is_first_operation())
+ {
+ tup_version= 1;
+ prepare_initial_insert(req_struct, regOperPtr.p, regTabPtr);
+ if(regTabPtr->m_no_of_disk_attributes)
+ {
+ int res;
+ if((res= c_lgman->alloc_log_space(regFragPtr->m_logfile_group_id,
+ regOperPtr.p->m_undo_buffer_space)))
+ {
+ terrorCode= res;
+ regOperPtr.p->m_undo_buffer_space= 0;
+ goto log_space_error;
+ }
+ }
+ }
+ 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, true);
+ else
+ memcpy(dst, org, 4*regTabPtr->m_offsets[MM].m_fix_header_size);
+ }
+
+ regOperPtr.p->tupVersion= tup_version & ZTUP_VERSION_MASK;
+ tuple_ptr->set_tuple_version(tup_version);
+ if(updateAttributes(req_struct, &cinBuffer[0],
+ req_struct->attrinfo_len) == -1)
+ return -1;
+
+ if (checkNullAttributes(req_struct, regTabPtr) == false)
+ {
+
+ goto null_check_error;
+ }
+
+ if (regTabPtr->need_shrink())
+ {
+ shrink_tuple(req_struct, sizes+2, regTabPtr, true);
+ }
+
+ /**
+ * Alloc memory
+ */
+ if(regOperPtr.p->is_first_operation())
+ {
+ Uint32 frag_page_id = req_struct->frag_page_id;
+ Uint32 real_page_id = regOperPtr.p->m_tuple_location.m_page_no;
+ regOperPtr.p->m_tuple_location.m_page_no = frag_page_id;
+ if (likely(get_tuple_state(regOperPtr.p) == TUPLE_INITIAL_INSERT))
+ {
+ if (!regTabPtr->m_attributes[MM].m_no_of_varsize)
+ {
+ jam();
+ if ((ptr= alloc_fix_rec(regFragPtr,
+ regTabPtr,
+ &regOperPtr.p->m_tuple_location,
+ &frag_page_id)) == 0)
+ {
+ goto mem_error;
+ }
+ }
+ else
+ {
+ jam();
+ regOperPtr.p->m_tuple_location.m_file_no= sizes[2+MM];
+ if ((ptr= alloc_var_rec(regFragPtr, regTabPtr,
+ sizes[2+MM],
+ &regOperPtr.p->m_tuple_location,
+ &frag_page_id, 0)) == 0)
+ goto mem_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);
+
+ ((Tuple_header*)ptr)->m_operation_ptr_i= regOperPtr.i;
+ ((Tuple_header*)ptr)->m_header_bits= Tuple_header::ALLOC;
+ }
+
+ if (regTabPtr->m_no_of_disk_attributes)
+ {
+ Local_key tmp;
+ Uint32 size= regTabPtr->m_attributes[DD].m_no_of_varsize == 0 ?
+ 1 : sizes[2+DD];
+
+ int ret= disk_page_prealloc(signal, fragPtr, &tmp, size);
+ ndbassert(ret >= 0);
+
+ 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
+ */
+ Tuple_header* disk_ptr= req_struct->m_disk_ptr;
+ disk_ptr->m_header_bits = 0;
+ disk_ptr->m_base_record_ref= regOperPtr.p->m_tuple_location.ref();
+ }
+
+ regOperPtr.p->m_tuple_location.m_page_no = real_page_id;
+ tuple_ptr->m_header_bits |= Tuple_header::ALLOC;
+
+ if (regTabPtr->checksumIndicator) {
jam();
+ setChecksum(req_struct->m_tuple_ptr, regTabPtr);
+ }
+
+ return 0;
+ }
+ else
+ {
+ if (regTabPtr->checksumIndicator) {
+ jam();
+ setChecksum(req_struct->m_tuple_ptr, regTabPtr);
+ }
+
+ if (!regTabPtr->need_shrink() || cmp[0] == cmp[1])
return 0;
- }//if
- TUPKEY_abort(signal, 17);
- }//if
+
+ return handle_size_change_after_update(req_struct,
+ base,
+ regOperPtr.p,
+ regFragPtr,
+ regTabPtr,
+ sizes);
+ }
+
+
+
+mem_error:
+ terrorCode= ZMEM_NOMEM_ERROR;
+ goto error;
+
+null_check_error:
+ terrorCode= ZNO_ILLEGAL_NULL_ATTR;
+ goto error;
+
+error:
+ tupkeyErrorLab(signal);
+ return -1;
+
+log_space_error:
+ regOperPtr.p->op_struct.in_active_list = false;
+ early_tupkey_error(signal);
return -1;
-}//Dbtup::handleInsertReq()
+}
/* ---------------------------------------------------------------- */
/* ---------------------------- DELETE ---------------------------- */
@@ -1065,84 +1491,60 @@ int Dbtup::handleDeleteReq(Signal* signal,
Operationrec* const regOperPtr,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
- Page* const pagePtr)
+ KeyReqStruct *req_struct)
{
// delete must set but not increment tupVersion
- if (regOperPtr->nextActiveOp != RNIL) {
- OperationrecPtr prevExecOpPtr;
- prevExecOpPtr.i = regOperPtr->nextActiveOp;
- ptrCheckGuard(prevExecOpPtr, cnoOfOprec, operationrec);
- regOperPtr->tupVersion = prevExecOpPtr.p->tupVersion;
- } else {
- jam();
- regOperPtr->tupVersion = pagePtr->pageWord[regOperPtr->pageOffset + 1];
+ if (!regOperPtr->is_first_operation())
+ {
+ Operationrec* prevOp= req_struct->prevOpPtr.p;
+ regOperPtr->tupVersion= prevOp->tupVersion;
+ regOperPtr->m_copy_tuple_location= prevOp->m_copy_tuple_location;
+ }
+ else
+ {
+ regOperPtr->tupVersion= req_struct->m_tuple_ptr->get_tuple_version();
+ if(regTabPtr->m_no_of_disk_attributes)
+ {
+ Uint32 sz;
+ if(regTabPtr->m_attributes[DD].m_no_of_varsize)
+ {
+ /**
+ * Need to have page in memory to read size
+ * to alloc undo space
+ */
+ abort();
+ }
+ else
+ sz= (sizeof(Dbtup::Disk_undo::Free) >> 2) +
+ regTabPtr->m_offsets[DD].m_fix_header_size - 1;
+
+ regOperPtr->m_undo_buffer_space= sz;
+
+ int res;
+ if((res= c_lgman->alloc_log_space(regFragPtr->m_logfile_group_id,
+ sz)))
+ {
+ terrorCode= res;
+ regOperPtr->m_undo_buffer_space= 0;
+ goto error;
+ }
+
+ }
}
- if (isUndoLoggingNeeded(regFragPtr, regOperPtr->fragPageId)) {
- jam();
- cprAddUndoLogRecord(signal,
- ZINDICATE_NO_OP_ACTIVE,
- regOperPtr->fragPageId,
- regOperPtr->pageIndex,
- regOperPtr->tableRef,
- regOperPtr->fragId,
- regFragPtr->checkpointVersion);
- }//if
- if (regOperPtr->attrinbufLen == 0) {
+ if (req_struct->attrinfo_len == 0)
+ {
return 0;
- }//if
-/* ------------------------------------------------------------------------ */
-/* THE APPLICATION WANTS TO READ THE TUPLE BEFORE IT IS DELETED. */
-/* ------------------------------------------------------------------------ */
- return handleReadReq(signal, regOperPtr, regTabPtr, pagePtr);
-}//Dbtup::handleDeleteReq()
-
-int
-Dbtup::updateStartLab(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTabPtr,
- Page* const pagePtr)
-{
- int retValue;
- if (regOperPtr->optype == ZINSERT) {
- jam();
- setNullBits(pagePtr, regTabPtr, regOperPtr->pageOffset);
}
- if (regOperPtr->interpretedExec != 1) {
- jam();
- retValue = updateAttributes(pagePtr,
- regOperPtr->pageOffset,
- &cinBuffer[0],
- regOperPtr->attrinbufLen);
- if (retValue == -1) {
- tupkeyErrorLab(signal);
- return -1;
- }//if
- } else {
- jam();
- retValue = interpreterStartLab(signal, pagePtr, regOperPtr->pageOffset);
- }//if
- ndbrequire(regOperPtr->tupVersion != ZNIL);
- pagePtr->pageWord[regOperPtr->pageOffset + 1] = regOperPtr->tupVersion;
- if (regTabPtr->checksumIndicator) {
- jam();
- setChecksum(pagePtr, regOperPtr->pageOffset, regTabPtr->tupheadsize);
- }//if
- return retValue;
-}//Dbtup::updateStartLab()
+
+ return handleReadReq(signal, regOperPtr, regTabPtr, req_struct);
-void
-Dbtup::setNullBits(Page* const regPage, Tablerec* const regTabPtr, Uint32 pageOffset)
-{
- Uint32 noOfExtraNullWords = regTabPtr->tupNullWords;
- Uint32 nullOffsetStart = regTabPtr->tupNullIndex + pageOffset;
- ndbrequire((noOfExtraNullWords + nullOffsetStart) < ZWORDS_ON_PAGE);
- for (Uint32 i = 0; i < noOfExtraNullWords; i++) {
- regPage->pageWord[nullOffsetStart + i] = 0xFFFFFFFF;
- }//for
-}//Dbtup::setNullBits()
+error:
+ tupkeyErrorLab(signal);
+ return -1;
+}
bool
-Dbtup::checkNullAttributes(Operationrec* const regOperPtr,
+Dbtup::checkNullAttributes(KeyReqStruct * const req_struct,
Tablerec* const regTabPtr)
{
// Implement checking of updating all not null attributes in an insert here.
@@ -1158,14 +1560,14 @@ Dbtup::checkNullAttributes(Operationrec* const regOperPtr,
* XXX remove or fix
*/
attributeMask.clear();
- attributeMask.bitOR(regOperPtr->changeMask);
+ attributeMask.bitOR(req_struct->changeMask);
attributeMask.bitAND(regTabPtr->notNullAttributeMask);
attributeMask.bitXOR(regTabPtr->notNullAttributeMask);
if (!attributeMask.isclear()) {
return false;
- }//if
+ }
return true;
-}//Dbtup::checkNullAttributes()
+}
/* ---------------------------------------------------------------- */
/* THIS IS THE START OF THE INTERPRETED EXECUTION OF UPDATES. WE */
@@ -1213,46 +1615,44 @@ Dbtup::checkNullAttributes(Operationrec* const regOperPtr,
/* ----------------- INTERPRETED EXECUTION ----------------------- */
/* ---------------------------------------------------------------- */
int Dbtup::interpreterStartLab(Signal* signal,
- Page* const pagePtr,
- Uint32 TupHeadOffset)
+ KeyReqStruct *req_struct)
{
- Operationrec * const regOperPtr = operPtr.p;
- Uint32 RtotalLen;
+ 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 RinitReadLen= cinBuffer[0];
+ Uint32 RexecRegionLen= cinBuffer[1];
+ Uint32 RfinalUpdateLen= cinBuffer[2];
+ Uint32 RfinalRLen= cinBuffer[3];
+ Uint32 RsubLen= cinBuffer[4];
- Uint32 RattrinbufLen = regOperPtr->attrinbufLen;
- const BlockReference sendBref = regOperPtr->recBlockref;
+ Uint32 RattrinbufLen= req_struct->attrinfo_len;
+ const BlockReference sendBref= req_struct->rec_blockref;
- Uint32 * dst = &signal->theData[25];
- Uint32 dstLen = (MAX_READ / 4) - 25;
const Uint32 node = refToNode(sendBref);
if(node != 0 && node != getOwnNodeId()) {
- ;
+ start_index= 25;
} else {
jam();
/**
* execute direct
*/
- dst = &signal->theData[3];
- dstLen = (MAX_READ / 4) - 3;
+ start_index= 3;
}
+ dst= &signal->theData[start_index];
+ dstLen= (MAX_READ / 4) - start_index;
- RtotalLen = RinitReadLen;
+ RtotalLen= RinitReadLen;
RtotalLen += RexecRegionLen;
RtotalLen += RfinalUpdateLen;
RtotalLen += RfinalRLen;
RtotalLen += RsubLen;
- Uint32 RattroutCounter = 0;
- Uint32 RinstructionCounter = 5;
- Uint32 RlogSize = 0;
-
+ Uint32 RattroutCounter= 0;
+ Uint32 RinstructionCounter= 5;
+ Uint32 RlogSize= 0;
if (((RtotalLen + 5) == RattrinbufLen) &&
(RattrinbufLen >= 5) &&
(RattrinbufLen < ZATTR_BUFFER_SIZE)) {
@@ -1269,22 +1669,21 @@ int Dbtup::interpreterStartLab(Signal* signal,
// 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(pagePtr,
- TupHeadOffset,
+ TnoDataRW= readAttributes(req_struct,
&cinBuffer[5],
RinitReadLen,
&dst[0],
dstLen,
false);
if (TnoDataRW != -1) {
- RattroutCounter = TnoDataRW;
+ RattroutCounter= TnoDataRW;
RinstructionCounter += RinitReadLen;
} else {
jam();
tupkeyErrorLab(signal);
return -1;
- }//if
- }//if
+ }
+ }
if (RexecRegionLen > 0) {
jam();
/* ---------------------------------------------------------------- */
@@ -1292,10 +1691,9 @@ int Dbtup::interpreterStartLab(Signal* signal,
// a register-based virtual machine which can read and write attributes
// to and from registers.
/* ---------------------------------------------------------------- */
- Uint32 RsubPC = RinstructionCounter + RfinalUpdateLen + RfinalRLen;
- TnoDataRW = interpreterNextLab(signal,
- pagePtr,
- TupHeadOffset,
+ Uint32 RsubPC= RinstructionCounter + RfinalUpdateLen + RfinalRLen;
+ TnoDataRW= interpreterNextLab(signal,
+ req_struct,
&clogMemBuffer[0],
&cinBuffer[RinstructionCounter],
RexecRegionLen,
@@ -1305,21 +1703,20 @@ int Dbtup::interpreterStartLab(Signal* signal,
sizeof(coutBuffer) / 4);
if (TnoDataRW != -1) {
RinstructionCounter += RexecRegionLen;
- RlogSize = TnoDataRW;
+ RlogSize= TnoDataRW;
} else {
jam();
return -1;
- }//if
- }//if
+ }
+ }
if (RfinalUpdateLen > 0) {
jam();
/* ---------------------------------------------------------------- */
// We can also apply a set of updates without any conditions as part
// of the interpreted execution.
/* ---------------------------------------------------------------- */
- if (regOperPtr->optype == ZUPDATE) {
- TnoDataRW = updateAttributes(pagePtr,
- TupHeadOffset,
+ if (regOperPtr->op_struct.op_type == ZUPDATE) {
+ TnoDataRW= updateAttributes(req_struct,
&cinBuffer[RinstructionCounter],
RfinalUpdateLen);
if (TnoDataRW != -1) {
@@ -1332,19 +1729,18 @@ int Dbtup::interpreterStartLab(Signal* signal,
jam();
tupkeyErrorLab(signal);
return -1;
- }//if
+ }
} else {
return TUPKEY_abort(signal, 19);
- }//if
- }//if
+ }
+ }
if (RfinalRLen > 0) {
jam();
/* ---------------------------------------------------------------- */
// The final action is that we can also read the tuple after it has
// been updated.
/* ---------------------------------------------------------------- */
- TnoDataRW = readAttributes(pagePtr,
- TupHeadOffset,
+ TnoDataRW= readAttributes(req_struct,
&cinBuffer[RinstructionCounter],
RfinalRLen,
&dst[RattroutCounter],
@@ -1356,19 +1752,19 @@ int Dbtup::interpreterStartLab(Signal* signal,
jam();
tupkeyErrorLab(signal);
return -1;
- }//if
- }//if
- regOperPtr->logSize = RlogSize;
- regOperPtr->attroutbufLen = RattroutCounter;
- sendReadAttrinfo(signal, RattroutCounter, regOperPtr);
+ }
+ }
+ req_struct->log_size= RlogSize;
+ req_struct->read_length= RattroutCounter;
+ sendReadAttrinfo(signal, req_struct, RattroutCounter, regOperPtr);
if (RlogSize > 0) {
sendLogAttrinfo(signal, RlogSize, regOperPtr);
- }//if
+ }
return 0;
} else {
return TUPKEY_abort(signal, 22);
- }//if
-}//Dbtup::interpreterStartLab()
+ }
+}
/* ---------------------------------------------------------------- */
/* WHEN EXECUTION IS INTERPRETED WE NEED TO SEND SOME ATTRINFO*/
@@ -1383,30 +1779,28 @@ void Dbtup::sendLogAttrinfo(Signal* signal,
Operationrec * const regOperPtr)
{
- Uint32 TbufferIndex = 0;
- signal->theData[0] = regOperPtr->userpointer;
+ Uint32 TbufferIndex= 0;
+ signal->theData[0]= regOperPtr->userpointer;
while (TlogSize > 22) {
MEMCOPY_NO_WORDS(&signal->theData[3],
&clogMemBuffer[TbufferIndex],
22);
- EXECUTE_DIRECT(refToBlock(regOperPtr->userblockref),
- GSN_TUP_ATTRINFO, signal, 25);
+ EXECUTE_DIRECT(DBLQH, GSN_TUP_ATTRINFO, signal, 25);
TbufferIndex += 22;
TlogSize -= 22;
- }//while
+ }
MEMCOPY_NO_WORDS(&signal->theData[3],
&clogMemBuffer[TbufferIndex],
TlogSize);
- EXECUTE_DIRECT(refToBlock(regOperPtr->userblockref),
- GSN_TUP_ATTRINFO, signal, 3 + TlogSize);
-}//Dbtup::sendLogAttrinfo()
+ 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;
+ Uint32 TbranchDirection= TheInstruction >> 31;
+ Uint32 TbranchLength= (TheInstruction >> 16) & 0x7fff;
TprogramCounter--;
if (TbranchDirection == 1) {
jam();
@@ -1420,12 +1814,11 @@ brancher(Uint32 TheInstruction, Uint32 TprogramCounter)
/* WE JUMP FORWARD. */
/* ---------------------------------------------------------------- */
return (TprogramCounter + TbranchLength);
- }//if
-}//brancher()
+ }
+}
int Dbtup::interpreterNextLab(Signal* signal,
- Page* const pagePtr,
- Uint32 TupHeadOffset,
+ KeyReqStruct* req_struct,
Uint32* logMemory,
Uint32* mainProgram,
Uint32 TmainProgLen,
@@ -1434,14 +1827,14 @@ int Dbtup::interpreterNextLab(Signal* signal,
Uint32 * tmpArea,
Uint32 tmpAreaSz)
{
- register Uint32* TcurrentProgram = mainProgram;
- register Uint32 TcurrentSize = TmainProgLen;
- register Uint32 RnoOfInstructions = 0;
- register Uint32 TprogramCounter = 0;
+ 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;
+ Uint32 TdataWritten= 0;
+ Uint32 RstackPtr= 0;
union {
Uint32 TregMemBuffer[32];
Uint64 Tdummy[16];
@@ -1454,23 +1847,23 @@ int Dbtup::interpreterNextLab(Signal* signal,
// 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;
+ 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;
+ theInstruction= TcurrentProgram[TprogramCounter];
+ theRegister= Interpreter::getReg1(theInstruction) << 2;
if (TprogramCounter < TcurrentSize) {
TprogramCounter++;
switch (Interpreter::getOpCode(theInstruction)) {
@@ -1482,37 +1875,37 @@ int Dbtup::interpreterNextLab(Signal* signal,
// as long as it fits in the 64 bits of the register.
/* ---------------------------------------------------------------- */
{
- Uint32 theAttrinfo = theInstruction;
- int TnoDataRW= readAttributes(pagePtr,
- TupHeadOffset,
- &theAttrinfo,
- (Uint32)1,
- &TregMemBuffer[theRegister],
- (Uint32)3,
- false);
+ 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;
- * (Int64*)(TregMemBuffer+theRegister+2) = TregMemBuffer[theRegister+1];
+ TregMemBuffer[theRegister]= 0x50;
+ * (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];
+ 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;
+ TregMemBuffer[theRegister]= 0;
+ TregMemBuffer[theRegister + 2]= 0;
+ TregMemBuffer[theRegister + 3]= 0;
} else if (TnoDataRW == -1) {
jam();
tupkeyErrorLab(signal);
@@ -1523,18 +1916,18 @@ int Dbtup::interpreterNextLab(Signal* signal,
// allowed and will lead to a system crash.
/* ------------------------------------------------------------- */
ndbrequire(false);
- }//if
+ }
break;
}
case Interpreter::WRITE_ATTR_FROM_REG:
jam();
{
- Uint32 TattrId = theInstruction >> 16;
- Uint32 TattrDescrIndex = tabptr.p->tabDescriptor +
+ Uint32 TattrId= theInstruction >> 16;
+ Uint32 TattrDescrIndex= tabptr.p->tabDescriptor +
(TattrId << ZAD_LOG_SIZE);
- Uint32 TattrDesc1 = tableDescriptor[TattrDescrIndex].tabDescr;
- Uint32 TregType = TregMemBuffer[theRegister];
+ Uint32 TattrDesc1= tableDescriptor[TattrDescrIndex].tabDescr;
+ Uint32 TregType= TregMemBuffer[theRegister];
/* --------------------------------------------------------------- */
// Calculate the number of words of this attribute.
@@ -1542,17 +1935,16 @@ int Dbtup::interpreterNextLab(Signal* signal,
// register size.
/* --------------------------------------------------------------- */
Uint32 TattrNoOfWords = AttributeDescriptor::getSizeInWords(TattrDesc1);
- Uint32 Toptype = operPtr.p->optype;
-
+ Uint32 Toptype = operPtr.p->op_struct.op_type;
Uint32 TdataForUpdate[3];
Uint32 Tlen;
- AttributeHeader& ah = AttributeHeader::init(&TdataForUpdate[0],
+ AttributeHeader& ah= AttributeHeader::init(&TdataForUpdate[0],
TattrId,
TattrNoOfWords << 2);
- TdataForUpdate[1] = TregMemBuffer[theRegister + 2];
- TdataForUpdate[2] = TregMemBuffer[theRegister + 3];
- Tlen = TattrNoOfWords + 1;
+ TdataForUpdate[1]= TregMemBuffer[theRegister + 2];
+ TdataForUpdate[2]= TregMemBuffer[theRegister + 3];
+ Tlen= TattrNoOfWords + 1;
if (Toptype == ZUPDATE) {
if (TattrNoOfWords <= 2) {
if (TregType == 0) {
@@ -1560,77 +1952,78 @@ int Dbtup::interpreterNextLab(Signal* signal,
// Write a NULL value into the attribute
/* --------------------------------------------------------- */
ah.setNULL();
- Tlen = 1;
- }//if
- int TnoDataRW= updateAttributes(pagePtr,
- TupHeadOffset,
- &TdataForUpdate[0],
- Tlen);
+ 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];
+ logMemory[TdataWritten + 0]= TdataForUpdate[0];
+ logMemory[TdataWritten + 1]= TdataForUpdate[1];
+ logMemory[TdataWritten + 2]= TdataForUpdate[2];
TdataWritten += Tlen;
} else {
tupkeyErrorLab(signal);
return -1;
- }//if
+ }
} else {
return TUPKEY_abort(signal, 15);
- }//if
+ }
} else {
return TUPKEY_abort(signal, 16);
- }//if
+ }
break;
}
case Interpreter::LOAD_CONST_NULL:
jam();
- TregMemBuffer[theRegister] = 0; /* NULL INDICATOR */
+ TregMemBuffer[theRegister]= 0; /* NULL INDICATOR */
break;
case Interpreter::LOAD_CONST16:
jam();
- TregMemBuffer[theRegister] = 0x50; /* 32 BIT UNSIGNED CONSTANT */
- * (Int64*)(TregMemBuffer+theRegister+2) = theInstruction >> 16;
+ 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) = *
+ 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++);
+ 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 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TdestRegister= Interpreter::getReg3(theInstruction) << 2;
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+ Uint32 TrightType= TregMemBuffer[TrightRegister];
+ Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
- Uint32 TleftType = TregMemBuffer[theRegister];
- Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 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;
+ Uint64 Tdest0= Tleft0 + Tright0;
+ * (Int64*)(TregMemBuffer+TdestRegister+2)= Tdest0;
+ TregMemBuffer[TdestRegister]= 0x60;
} else {
return TUPKEY_abort(signal, 20);
}
@@ -1640,19 +2033,19 @@ int Dbtup::interpreterNextLab(Signal* signal,
case Interpreter::SUB_REG_REG:
jam();
{
- Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
- Uint32 TdestRegister = Interpreter::getReg3(theInstruction) << 2;
+ Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TdestRegister= Interpreter::getReg3(theInstruction) << 2;
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+ Uint32 TrightType= TregMemBuffer[TrightRegister];
+ Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
- Uint32 TleftType = TregMemBuffer[theRegister];
- Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 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;
+ Int64 Tdest0= Tleft0 - Tright0;
+ * (Int64*)(TregMemBuffer+TdestRegister+2)= Tdest0;
+ TregMemBuffer[TdestRegister]= 0x60;
} else {
return TUPKEY_abort(signal, 20);
}
@@ -1660,7 +2053,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
}
case Interpreter::BRANCH:
- TprogramCounter = brancher(theInstruction, TprogramCounter);
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
break;
case Interpreter::BRANCH_REG_EQ_NULL:
@@ -1669,8 +2062,8 @@ int Dbtup::interpreterNextLab(Signal* signal,
continue;
} else {
jam();
- TprogramCounter = brancher(theInstruction, TprogramCounter);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
break;
case Interpreter::BRANCH_REG_NE_NULL:
@@ -1679,140 +2072,140 @@ int Dbtup::interpreterNextLab(Signal* signal,
continue;
} else {
jam();
- TprogramCounter = brancher(theInstruction, TprogramCounter);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
break;
case Interpreter::BRANCH_EQ_REG_REG:
{
- Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 2];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 3];
+ 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];
+ 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);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
} else {
return TUPKEY_abort(signal, 23);
- }//if
+ }
break;
}
case Interpreter::BRANCH_NE_REG_REG:
{
- Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TleftType = TregMemBuffer[theRegister];
- Uint32 Tleft0 = TregMemBuffer[theRegister + 2];
- Uint32 Tleft1 = TregMemBuffer[theRegister + 3];
+ 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];
+ 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);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
} else {
return TUPKEY_abort(signal, 24);
- }//if
+ }
break;
}
case Interpreter::BRANCH_LT_REG_REG:
{
- Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+ Uint32 TrightType= TregMemBuffer[TrightRegister];
+ Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
- Uint32 TleftType = TregMemBuffer[theRegister];
- Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+ Uint32 TleftType= TregMemBuffer[theRegister];
+ Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
if ((TrightType | TleftType) != 0) {
jam();
if (Tleft0 < Tright0) {
- TprogramCounter = brancher(theInstruction, TprogramCounter);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
} else {
return TUPKEY_abort(signal, 24);
- }//if
+ }
break;
}
case Interpreter::BRANCH_LE_REG_REG:
{
- Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+ Uint32 TrightType= TregMemBuffer[TrightRegister];
+ Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
- Uint32 TleftType = TregMemBuffer[theRegister];
- Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+ Uint32 TleftType= TregMemBuffer[theRegister];
+ Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
if ((TrightType | TleftType) != 0) {
jam();
if (Tleft0 <= Tright0) {
- TprogramCounter = brancher(theInstruction, TprogramCounter);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
} else {
return TUPKEY_abort(signal, 26);
- }//if
+ }
break;
}
case Interpreter::BRANCH_GT_REG_REG:
{
- Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+ Uint32 TrightType= TregMemBuffer[TrightRegister];
+ Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
- Uint32 TleftType = TregMemBuffer[theRegister];
- Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+ Uint32 TleftType= TregMemBuffer[theRegister];
+ Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
if ((TrightType | TleftType) != 0) {
jam();
if (Tleft0 > Tright0){
- TprogramCounter = brancher(theInstruction, TprogramCounter);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
} else {
return TUPKEY_abort(signal, 27);
- }//if
+ }
break;
}
case Interpreter::BRANCH_GE_REG_REG:
{
- Uint32 TrightRegister = Interpreter::getReg2(theInstruction) << 2;
+ Uint32 TrightRegister= Interpreter::getReg2(theInstruction) << 2;
- Uint32 TrightType = TregMemBuffer[TrightRegister];
- Int64 Tright0 = * (Int64*)(TregMemBuffer + TrightRegister + 2);
+ Uint32 TrightType= TregMemBuffer[TrightRegister];
+ Int64 Tright0= * (Int64*)(TregMemBuffer + TrightRegister + 2);
- Uint32 TleftType = TregMemBuffer[theRegister];
- Int64 Tleft0 = * (Int64*)(TregMemBuffer + theRegister + 2);
+ Uint32 TleftType= TregMemBuffer[theRegister];
+ Int64 Tleft0= * (Int64*)(TregMemBuffer + theRegister + 2);
if ((TrightType | TleftType) != 0) {
jam();
if (Tleft0 >= Tright0){
- TprogramCounter = brancher(theInstruction, TprogramCounter);
- }//if
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
+ }
} else {
return TUPKEY_abort(signal, 28);
- }//if
+ }
break;
}
@@ -1824,8 +2217,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
Uint32 argLen = Interpreter::getBranchCol_Len(ins2);
if(tmpHabitant != attrId){
- Int32 TnoDataR = readAttributes(pagePtr,
- TupHeadOffset,
+ Int32 TnoDataR = readAttributes(req_struct,
&attrId, 1,
tmpArea, tmpAreaSz,
false);
@@ -1835,7 +2227,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
tupkeyErrorLab(signal);
return -1;
}
- tmpHabitant = attrId;
+ tmpHabitant= attrId;
}
// get type
@@ -1926,12 +2318,11 @@ int Dbtup::interpreterNextLab(Signal* signal,
case Interpreter::BRANCH_ATTR_EQ_NULL:{
jam();
- Uint32 ins2 = TcurrentProgram[TprogramCounter];
- Uint32 attrId = Interpreter::getBranchCol_AttrId(ins2) << 16;
+ Uint32 ins2= TcurrentProgram[TprogramCounter];
+ Uint32 attrId= Interpreter::getBranchCol_AttrId(ins2) << 16;
- if(tmpHabitant != attrId){
- Int32 TnoDataR = readAttributes(pagePtr,
- TupHeadOffset,
+ if (tmpHabitant != attrId){
+ Int32 TnoDataR= readAttributes(req_struct,
&attrId, 1,
tmpArea, tmpAreaSz,
false);
@@ -1941,12 +2332,12 @@ int Dbtup::interpreterNextLab(Signal* signal,
tupkeyErrorLab(signal);
return -1;
}
- tmpHabitant = attrId;
+ tmpHabitant= attrId;
}
AttributeHeader ah(tmpArea[0]);
- if(ah.isNULL()){
- TprogramCounter = brancher(theInstruction, TprogramCounter);
+ if (ah.isNULL()){
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
} else {
TprogramCounter ++;
}
@@ -1955,12 +2346,11 @@ int Dbtup::interpreterNextLab(Signal* signal,
case Interpreter::BRANCH_ATTR_NE_NULL:{
jam();
- Uint32 ins2 = TcurrentProgram[TprogramCounter];
- Uint32 attrId = Interpreter::getBranchCol_AttrId(ins2) << 16;
+ Uint32 ins2= TcurrentProgram[TprogramCounter];
+ Uint32 attrId= Interpreter::getBranchCol_AttrId(ins2) << 16;
- if(tmpHabitant != attrId){
- Int32 TnoDataR = readAttributes(pagePtr,
- TupHeadOffset,
+ if (tmpHabitant != attrId){
+ Int32 TnoDataR= readAttributes(req_struct,
&attrId, 1,
tmpArea, tmpAreaSz,
false);
@@ -1970,14 +2360,14 @@ int Dbtup::interpreterNextLab(Signal* signal,
tupkeyErrorLab(signal);
return -1;
}
- tmpHabitant = attrId;
+ tmpHabitant= attrId;
}
AttributeHeader ah(tmpArea[0]);
- if(ah.isNULL()){
+ if (ah.isNULL()){
TprogramCounter ++;
} else {
- TprogramCounter = brancher(theInstruction, TprogramCounter);
+ TprogramCounter= brancher(theInstruction, TprogramCounter);
}
break;
}
@@ -1994,7 +2384,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
#ifdef TRACE_INTERPRETER
ndbout_c(" - exit_ok_last");
#endif
- operPtr.p->lastRow = 1;
+ req_struct->last_row= true;
return TdataWritten;
case Interpreter::EXIT_REFUSE:
@@ -2002,52 +2392,555 @@ int Dbtup::interpreterNextLab(Signal* signal,
#ifdef TRACE_INTERPRETER
ndbout_c(" - exit_nok");
#endif
- terrorCode = theInstruction >> 16;
+ terrorCode= theInstruction >> 16;
return TUPKEY_abort(signal, 29);
case Interpreter::CALL:
jam();
RstackPtr++;
if (RstackPtr < 32) {
- TstackMemBuffer[RstackPtr] = TprogramCounter + 1;
- TprogramCounter = theInstruction >> 16;
+ TstackMemBuffer[RstackPtr]= TprogramCounter + 1;
+ TprogramCounter= theInstruction >> 16;
if (TprogramCounter < TsubroutineLen) {
- TcurrentProgram = subroutineProg;
- TcurrentSize = TsubroutineLen;
+ TcurrentProgram= subroutineProg;
+ TcurrentSize= TsubroutineLen;
} else {
return TUPKEY_abort(signal, 30);
- }//if
+ }
} else {
return TUPKEY_abort(signal, 31);
- }//if
+ }
break;
case Interpreter::RETURN:
jam();
if (RstackPtr > 0) {
- TprogramCounter = TstackMemBuffer[RstackPtr];
+ TprogramCounter= TstackMemBuffer[RstackPtr];
RstackPtr--;
if (RstackPtr == 0) {
jam();
/* ------------------------------------------------------------- */
// We are back to the main program.
/* ------------------------------------------------------------- */
- TcurrentProgram = mainProgram;
- TcurrentSize = TmainProgLen;
- }//if
+ TcurrentProgram= mainProgram;
+ TcurrentSize= TmainProgLen;
+ }
} else {
return TUPKEY_abort(signal, 32);
- }//if
+ }
break;
default:
return TUPKEY_abort(signal, 33);
- }//switch
+ }
} else {
return TUPKEY_abort(signal, 34);
- }//if
- }//while
+ }
+ }
return TUPKEY_abort(signal, 35);
-}//Dbtup::interpreterNextLab()
+}
+
+/**
+ * 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 * const 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_varpart_offset;
+ Uint32 order_desc= tabPtrP->m_real_order_descriptor;
+
+ Uint32 *dst_ptr= ptr->get_var_part_ptr(tabPtrP);
+ const Uint32 *disk_ref= src->get_disk_ref_ptr(tabPtrP);
+ const Uint32 *src_ptr= src->get_var_part_ptr(tabPtrP);
+ const Uint32 * const 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<Var_page> var_page;
+ src_data= get_ptr(&var_page, * (Var_part_ref*)src_ptr);
+ step= 4;
+ sizes[MM]= (2 + (mm_vars << 1) + ((Uint16*)src_data)[mm_vars] + 3) >> 2;
+ req_struct->m_varpart_page_ptr_p= var_page.p;
+ }
+ else
+ {
+ step= (2 + (mm_vars << 1) + ((Uint16*)src_ptr)[mm_vars]);
+ sizes[MM]= (step + 3) >> 2;
+ req_struct->m_varpart_page_ptr_p= (Var_page*)req_struct->m_page_ptr_p;
+ }
+ 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 + Tuple_header::HeaderSize;
+ memcpy(ptr, src, 4*(fix_size + Tuple_header::HeaderSize));
+ }
+ else
+ {
+ sizes[MM]= 1;
+ dst_ptr -= Tuple_header::HeaderSize;
+ src_ptr -= Tuple_header::HeaderSize;
+ 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_ptr(&req_struct->m_disk_page_ptr, &key, tabPtrP, DD);
+ }
+ 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));
+
+ if(dd_vars)
+ {
+ KeyReqStruct::Var_data* dst= &req_struct->m_var_data[DD];
+ dst_ptr += tabPtrP->m_offsets[DD].m_varpart_offset;
+ src_ptr += tabPtrP->m_offsets[DD].m_varpart_offset;
+ order += tabPtrP->m_attributes[DD].m_no_of_fixsize;
+
+ dst->m_data_ptr= (char*)(char*)(((Uint16*)dst_ptr)+dd_vars+1);
+ dst->m_offset_array_ptr= req_struct->var_pos_array + (mm_vars << 1);
+ dst->m_var_len_offset= dd_vars;
+ dst->m_max_var_offset= tabPtrP->m_offsets[DD].m_max_var_offset;
+
+ expand_var_part(dst, src_ptr, desc, order);
+ }
+ }
+
+ ptr->m_header_bits= (bits & ~(Uint32)(Tuple_header::CHAINED_ROW));
+}
+
+void
+Dbtup::prepare_read(KeyReqStruct* req_struct,
+ Tablerec* const 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_var_part_ptr(tabPtrP);
+ const Uint32 *disk_ref= ptr->get_disk_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_part_ref*)src_ptr);
+ }
+ 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);
+ }
+ else
+ {
+ // disk part if after fixsize part...
+ src_ptr -= Tuple_header::HeaderSize;
+ }
+
+ 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_ptr(&req_struct->m_disk_page_ptr, &key, tabPtrP, DD);
+ }
+ // Fix diskpart
+ req_struct->m_disk_ptr= (Tuple_header*)src_ptr;
+ ndbassert(! (req_struct->m_disk_ptr->m_header_bits & Tuple_header::FREE));
+ if(dd_vars)
+ {
+ KeyReqStruct::Var_data* dst= &req_struct->m_var_data[DD];
+ src_ptr += tabPtrP->m_offsets[DD].m_varpart_offset;
+
+ dst->m_data_ptr= (char*)(char*)(((Uint16*)src_ptr)+dd_vars+1);
+ dst->m_offset_array_ptr= (Uint16*)src_ptr;
+ dst->m_var_len_offset= 1;
+ dst->m_max_var_offset= ((Uint16*)src_ptr)[dd_vars];
+ }
+ }
+}
+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_var_part_ptr(tabPtrP);
+ Uint16* src_off_ptr= req_struct->var_pos_array;
+
+ sizes[MM]= 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);
+ }
+ else
+ {
+ sizes[MM] = 1;
+ dst_ptr -= Tuple_header::HeaderSize;
+ }
+
+ if(disk && dd_tot)
+ {
+ Uint32 * src_ptr = (Uint32*)req_struct->m_disk_ptr;
+ req_struct->m_disk_ptr = (Tuple_header*)dst_ptr;
+ if (unlikely(dd_vars))
+ {
+ abort();
+ }
+ else
+ {
+ 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*)(cpage + real);
+
+ for(Uint32 i=1; i<page->high_index; i++)
+ {
+ Uint32 len= page->get_entry_len(i);
+ if(len && !(len & Var_page::CHAIN))
+ {
+ Tuple_header *ptr= (Tuple_header*)page->get_ptr(i);
+ Uint32 *part= ptr->get_var_part_ptr(regTabPtr);
+ if(ptr->m_header_bits & Tuple_header::CHAINED_ROW)
+ {
+ assert(len == fix_sz + 1);
+ Local_key tmp; tmp= *part;
+ Ptr<Var_page> tmpPage;
+ part= get_ptr(&tmpPage, *(Var_part_ref*)part);
+ len= 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(len)
+ {
+ /**
+ * Chain
+ */
+ Uint32 *part= page->get_ptr(i);
+ Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)part)[mm_vars]);
+ ndbassert((len & ~Var_page::CHAIN) >= ((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 = Tuple_header::HeaderSize +
+ 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 - ");
+ Var_page* pageP= req_struct->m_varpart_page_ptr_p;
+ Uint32 idx, alloc, needed;
+ if(! (bits & Tuple_header::CHAINED_ROW))
+ {
+ idx= regOperPtr->m_tuple_location.m_page_idx;
+ alloc= pageP->get_entry_len(idx) & ~Var_page::CHAIN;
+ ndbassert(!(pageP->get_entry_len(idx) & Var_page::CHAIN));
+ needed= sizes[2+MM];
+ }
+ else
+ {
+ Local_key tmp;
+ tmp= *org->get_var_part_ptr(regTabPtr);
+ idx= tmp.m_page_idx;
+ alloc= pageP->get_entry_len(idx) & ~Var_page::CHAIN;
+ if(!(pageP->get_entry_len(idx) & Var_page::CHAIN))
+ ndbout << *pageP << endl;
+ ndbassert(pageP->get_entry_len(idx) & Var_page::CHAIN);
+ needed= sizes[2+MM] - fix_sz;
+ }
+
+ if(needed <= alloc)
+ {
+ ndbassert(!regOperPtr->is_first_operation());
+ ndbout_c(" no grow");
+ return 0;
+ }
+ Uint32 add= needed - alloc;
+ copy_bits |= Tuple_header::MM_GROWN;
+
+ if(pageP->free_space >= add)
+ {
+ jam();
+ if(!pageP->is_space_behind_entry(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(idx), 4*alloc);
+ pageP->set_entry_len(idx, 0);
+ pageP->free_space += alloc;
+ pageP->reorg((Var_page*)ctemp_page);
+ memcpy(pageP->get_free_space_ptr(), copyBuffer, 4*alloc);
+ pageP->set_entry_offset(idx, pageP->insert_pos);
+ add += alloc;
+ }
+ pageP->grow_entry(idx, add);
+ ndbassert((pageP->get_entry_len(idx) & Var_page::CHAIN) ==
+ (bits & Tuple_header::CHAINED_ROW ? Var_page::CHAIN : 0));
+ update_free_page_list(regFragPtr, pageP);
+ }
+ else
+ {
+ Local_key key;
+
+ if(! (bits & Tuple_header::CHAINED_ROW))
+ {
+ assert(fix_sz < alloc);
+ org->m_header_bits |= Tuple_header::CHAINED_ROW;
+ Uint32 id, *dst= alloc_var_rec(regFragPtr, regTabPtr,
+ needed - fix_sz, &key, &id,
+ Var_page::CHAIN);
+ assert(dst);
+ ndbassert(key.m_page_no != pageP->physical_page_id);
+ ndbassert(pageP->get_ptr(idx) == (Uint32*)org);
+ Uint32 *ptr= org->get_var_part_ptr(regTabPtr);
+
+ Uint32 old= pageP->get_entry_len(idx);
+ memcpy(dst, ptr, 4*(old - fix_sz));
+ * ptr = key.ref(); // store ref
+
+ ndbassert((ptr - (Uint32*)org) + 1 == fix_sz + 1);
+ pageP->shrink_entry(idx, fix_sz + 1); // var part ref
+ //ndbout_c("%p->shrink_entry(%d, %d)", pageP, idx, fix_sz + 1);
+ update_free_page_list(regFragPtr, pageP);
+ }
+ else
+ {
+ assert(sizes[2+MM] >= alloc);
+ Uint32 id, *dst= alloc_var_rec(regFragPtr, regTabPtr,
+ needed, &key, &id,
+ Var_page::CHAIN);
+ assert(dst);
+ ndbassert(key.m_page_no != pageP->physical_page_id);
+
+ // Alloc var_rec can reorg base page, so we need to refetch ptr
+ Uint32 base_idx= regOperPtr->m_tuple_location.m_page_idx;
+ org= (Tuple_header*)
+ ((Var_page*)req_struct->m_page_ptr_p)->get_ptr(base_idx);
+ Uint32 *ref= org->get_var_part_ptr(regTabPtr);
+ Uint32 old_ref= *ref;
+ Uint32 *src= pageP->get_ptr(idx);
+
+ assert(alloc < needed);
+ memcpy(dst, src, 4*alloc);
+ *ref = key.ref();
+
+ free_var_part(regFragPtr, regTabPtr,
+ *(Var_part_ref*)&old_ref, Var_page::CHAIN);
+ }
+ }
+ }
+ req_struct->m_tuple_ptr->m_header_bits = copy_bits;
+ return 0;
+}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp
index cdd54ba2337..e37b493f1e1 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp
@@ -31,12 +31,13 @@
// current implementation.
//
// Public methods
-// bool allocTh(Fragrecord* const regFragPtr, # In
-// Tablerec* const regTabPtr, # In
-// Uint32 pageType, # In
-// Signal* signal, # In
-// Uint32& pageOffset, # Out
-// PagePtr& pagePtr) # In/Out
+// 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.
//
@@ -44,10 +45,6 @@
// This method is used to free a tuple header in normal transaction
// handling.
//
-// freeThSr()
-// This method is used to free a tuple as part of executing the undo
-// log records.
-//
// getThAtPageSr()
// This method is used to allocate a tuple on a set page as part of
// undo log execution.
@@ -60,81 +57,24 @@
// convertThPage()
// Convert an empty page into a page of free tuples in a linked list.
//
-// getEmptyPageThCopy()
-// A page recently taken from set of empty pages on fragment is made
-// part of the copy pages.
-//
// 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.
//
-bool Dbtup::allocTh(Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr,
- Uint32 pageType,
- Signal* signal,
- Uint32& pageOffset,
- PagePtr& pagePtr)
+Uint32*
+Dbtup::alloc_fix_rec(Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr,
+ Local_key* key,
+ Uint32 * out_frag_page_id)
{
- if (pageType == SAME_PAGE) {
- ljam();
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- if (pagePtr.p->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FREE) {
- ljam();
- getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
- return true;
- }//if
- pageType = NORMAL_PAGE;
- }//if
- if (pageType == COPY_PAGE) {
-/* ---------------------------------------------------------------- */
-// Allocate a tuple header for the copy of the tuple header
-/* ---------------------------------------------------------------- */
- if (regFragPtr->thFreeCopyFirst == RNIL) {
-/* ---------------------------------------------------------------- */
-// No page in list with free tuple header exists
-/* ---------------------------------------------------------------- */
- if (regFragPtr->noCopyPagesAlloc < ZMAX_NO_COPY_PAGES) {
- ljam();
-/* ---------------------------------------------------------------- */
-// We have not yet allocated the maximum number of copy pages for
-// this fragment.
-/* ---------------------------------------------------------------- */
- pagePtr.i = getEmptyPage(regFragPtr);
- if (pagePtr.i != RNIL) {
- ljam();
-/* ---------------------------------------------------------------- */
-// We have empty pages already allocated to this fragment. Allocate
-// one of those as copy page.
-/* ---------------------------------------------------------------- */
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- getEmptyPageThCopy(regFragPtr, signal, pagePtr.p);
-/* ---------------------------------------------------------------- */
-// Convert page into a tuple header page.
-/* ---------------------------------------------------------------- */
- convertThPage(regTabPtr->tupheadsize, pagePtr.p);
- getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
- return true;
- }//if
- }//if
- } else {
- ljam();
-/* ---------------------------------------------------------------- */
-/* NORMAL PATH WHEN COPY PAGE REQUESTED, GET PAGE POINTER */
-/* AND THEN GOTO COMMON HANDLING OF GET TUPLE HEADER AT PAGE. */
-/* ---------------------------------------------------------------- */
- pagePtr.i = getRealpid(regFragPtr, regFragPtr->thFreeCopyFirst);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
- return true;
- }//if
- }//if
/* ---------------------------------------------------------------- */
/* EITHER NORMAL PAGE REQUESTED OR ALLOCATION FROM COPY PAGE */
/* FAILED. TRY ALLOCATING FROM NORMAL PAGE. */
/* ---------------------------------------------------------------- */
- Uint32 fragPageId = regFragPtr->thFreeFirst;
- if (fragPageId == RNIL) {
+ PagePtr pagePtr;
+ pagePtr.i= regFragPtr->thFreeFirst;
+ if (pagePtr.i == RNIL) {
/* ---------------------------------------------------------------- */
// No prepared tuple header page with free entries exists.
/* ---------------------------------------------------------------- */
@@ -145,106 +85,76 @@ bool Dbtup::allocTh(Fragrecord* const regFragPtr,
// 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.
/* ---------------------------------------------------------------- */
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- getEmptyPageTh(regFragPtr, signal, pagePtr.p);
- convertThPage(regTabPtr->tupheadsize, pagePtr.p);
- getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
- return true;
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+
+ convertThPage(regTabPtr->m_offsets[MM].m_fix_header_size,
+ (Fix_page*)pagePtr.p);
+
+ pagePtr.p->next_page = regFragPtr->thFreeFirst;
+ pagePtr.p->page_state = ZTH_MM_FREE;
+ regFragPtr->thFreeFirst = pagePtr.i;
} else {
ljam();
/* ---------------------------------------------------------------- */
/* THERE ARE NO EMPTY PAGES. MEMORY CAN NOT BE ALLOCATED. */
/* ---------------------------------------------------------------- */
- terrorCode = ZMEM_NOMEM_ERROR;
- return false;
- }//if
+ return 0;
+ }
} else {
ljam();
/* ---------------------------------------------------------------- */
/* THIS SHOULD BE THE COMMON PATH THROUGH THE CODE, FREE */
/* COPY PAGE EXISTED. */
/* ---------------------------------------------------------------- */
- pagePtr.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
- return true;
- }//if
- ndbrequire(false); // Dead code
- return false;
-}//Dbtup::allocTh()
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ }
+
+ 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(Uint32 Tupheadsize,
- Page* const regPagePtr)
+ Fix_page* const regPagePtr)
{
- Uint32 ctpConstant = Tupheadsize << 16;
- Uint32 nextTuple = ZPAGE_HEADER_SIZE + Tupheadsize;
+ Uint32 nextTuple = Tupheadsize;
Uint32 endOfList;
/*
ASSUMES AT LEAST ONE TUPLE HEADER FITS AND THEREFORE NO HANDLING
OF ZERO AS EXTREME CASE
*/
- do {
- ljam();
- endOfList = nextTuple - Tupheadsize;
- regPagePtr->pageWord[endOfList] = ctpConstant + nextTuple;
- nextTuple += Tupheadsize;
- } while (nextTuple <= ZWORDS_ON_PAGE);
- regPagePtr->pageWord[endOfList] = ctpConstant;
- Uint32 startOfList = ZPAGE_HEADER_SIZE;
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (startOfList << 16) + endOfList;
+ Uint32 cnt= 0;
+ Uint32 pos= 0;
+ Uint32 prev = 0xFFFF;
+#ifdef VM_TRACE
+ memset(regPagePtr->m_data, 0xF1, 4*Fix_page::DATA_WORDS);
+#endif
+ while (pos + nextTuple <= Fix_page::DATA_WORDS)
+ {
+ regPagePtr->m_data[pos] = (prev << 16) | (pos + nextTuple);
+ regPagePtr->m_data[pos + 1] = Tuple_header::FREE;
+ 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()
-void Dbtup::getEmptyPageTh(Fragrecord* const regFragPtr,
- Signal* signal,
- Page* const regPagePtr)
+Uint32
+Dbtup::alloc_tuple_from_page(Fragrecord* const regFragPtr,
+ Fix_page* const regPagePtr)
{
- if (isUndoLoggingNeeded(regFragPtr, regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
- cprAddUndoLogPageHeader(signal,
- regPagePtr,
- regFragPtr);
- }//if
- regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeFirst;
- regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE;
- regFragPtr->thFreeFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
-
-ndbrequire(regFragPtr->thFreeFirst != (RNIL -1));
-}//Dbtup::getEmptyPageTh()
-
-void Dbtup::getEmptyPageThCopy(Fragrecord* const regFragPtr,
- Signal* signal,
- Page* const regPagePtr)
-{
- if (isUndoLoggingNeeded(regFragPtr, regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
- cprAddUndoLogPageHeader(signal,
- regPagePtr,
- regFragPtr);
- }//if
- regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeCopyFirst;
- regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE_COPY;
- regFragPtr->thFreeCopyFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- regFragPtr->noCopyPagesAlloc++;
-}//Dbtup::getEmptyPageThCopy()
-
-void Dbtup::getThAtPage(Fragrecord* const regFragPtr,
- Page* const regPagePtr,
- Signal* signal,
- Uint32& pageOffset)
-{
- Uint32 freeListHeader = regPagePtr->pageWord[ZFREELIST_HEADER_POS];
- Uint32 startTuple = freeListHeader >> 16;
- Uint32 endTuple = freeListHeader & 0xffff;
- pageOffset = startTuple; /* START IS THE ONE ALLOCATED */
- if (startTuple > 0) {
- if (startTuple != endTuple) {
-/* ---------------------------------------------------------------- */
-/* NOT THE LAST, SIMPLY RESHUFFLE POINTERS. */
-/* ---------------------------------------------------------------- */
- ndbrequire(startTuple < ZWORDS_ON_PAGE);
- startTuple = regPagePtr->pageWord[startTuple] & 0xffff;
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = endTuple +
- (startTuple << 16);
- return;
- } else {
+ 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 */
@@ -253,132 +163,30 @@ void Dbtup::getThAtPage(Fragrecord* const regFragPtr,
/* WE ALSO HAVE TO INSERT AN UNDO LOG ENTRY TO ENSURE PAGE */
/* ARE MAINTAINED EVEN AFTER A SYSTEM CRASH. */
/* ---------------------------------------------------------------- */
- if (isUndoLoggingNeeded(regFragPtr,
- regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
- cprAddUndoLogPageHeader(signal,
- regPagePtr,
- regFragPtr);
- }//if
- if (regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FREE) {
- ljam();
- regFragPtr->thFreeFirst = regPagePtr->pageWord[ZPAGE_NEXT_POS];
- regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FULL;
- } else if (regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FREE_COPY) {
- ljam();
- regFragPtr->thFreeCopyFirst = regPagePtr->pageWord[ZPAGE_NEXT_POS];
- regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FULL_COPY;
- } else {
- ndbrequire(false);
- }//if
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = 0;
- regPagePtr->pageWord[ZPAGE_NEXT_POS] = RNIL;
- }//if
- } else {
- ndbrequire(false);
- }//if
- return;
+ ndbrequire(regPagePtr->page_state == ZTH_MM_FREE);
+ regFragPtr->thFreeFirst = regPagePtr->next_page;
+ regPagePtr->next_page = RNIL;
+ regPagePtr->page_state = ZTH_MM_FULL;
+ }
+
+ return idx;
}//Dbtup::getThAtPage()
-void Dbtup::getThAtPageSr(Page* const regPagePtr,
- Uint32& pageOffset)
-{
- Uint32 freeListHeader = regPagePtr->pageWord[ZFREELIST_HEADER_POS];
- Uint32 startTuple = freeListHeader >> 16;
- Uint32 endTuple = freeListHeader & 0xffff;
- ndbrequire(startTuple > 0);
- pageOffset = startTuple; /* START IS THE ONE ALLOCATED */
- if (startTuple == endTuple) {
- ljam();
-/* ---------------------------------------------------------------- */
-/* THIS WAS THE LAST TUPLE HEADER IN THIS PAGE. SINCE WE ARE */
-/* UNDOING PAGE UPDATES WE SHALL NOT DO ANYTHING ABOUT THE */
-/* PAGE HEADER. THIS IS DONE BY SEPARATE LOG RECORDS. */
-/* ---------------------------------------------------------------- */
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = 0;
- } else {
- ljam();
-/* ---------------------------------------------------------------- */
-/* NOT THE LAST, SIMPLY RESHUFFLE POINTERS. */
-/* ---------------------------------------------------------------- */
- ndbrequire(startTuple < ZWORDS_ON_PAGE);
- startTuple = regPagePtr->pageWord[startTuple] & 0xffff; /* GET NEXT POINTER */
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = endTuple + (startTuple << 16);
- }//if
-}//Dbtup::getThAtPageSr()
-void Dbtup::freeTh(Fragrecord* const regFragPtr,
- Tablerec* const regTabPtr,
- Signal* signal,
- Page* const regPagePtr,
- Uint32 freePageOffset)
+void Dbtup::free_fix_rec(Fragrecord* regFragPtr,
+ Tablerec* regTabPtr,
+ Local_key* key,
+ Fix_page* regPagePtr)
{
- Uint32 startOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] >> 16;
- Uint32 endOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] & 0xffff;
-/* LINK THE NOW FREE TUPLE SPACE INTO BEGINNING OF FREE LIST OF OF THE PAGE */
-/* SET THE SIZE OF THE NEW FREE SPACE AND LINK TO THE OLD START OF FREELIST */
- ndbrequire(freePageOffset < ZWORDS_ON_PAGE);
- regPagePtr->pageWord[freePageOffset] = (regTabPtr->tupheadsize << 16) +
- startOfList;
- if (endOfList == 0) {
+ Uint32 free= regPagePtr->free_record(key->m_page_idx);
+
+ if(free == 1)
+ {
ljam();
- ndbrequire(startOfList == 0);
-/* ---------------------------------------------------------------- */
-/* THE PAGE WAS PREVIOUSLY FULL, NO EMPTY SPACE AT ALL. */
-/* THIS ENTRY WILL THEN BE BOTH THE START AND THE END OF THE */
-/* LIST. IT WILL ALSO BE PUT ON THE PROPER FREE LIST. */
-/* */
-/* UPDATE OF NEXT POINTER AND PAGE STATE MUST BE LOGGED TO */
-/* THE UNDO LOG TO ENSURE THAT FREE LISTS ARE OK AFTER A */
-/* SYSTEM RESTART. */
-/* ---------------------------------------------------------------- */
- if (isUndoLoggingNeeded(regFragPtr, regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
- cprAddUndoLogPageHeader(signal,
- regPagePtr,
- regFragPtr);
- }//if
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + freePageOffset;
- if (regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FULL) {
- ljam();
- regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeFirst;
- regFragPtr->thFreeFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE;
- } else {
- ndbrequire(regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FULL_COPY);
- ljam();
- regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeCopyFirst;
- regFragPtr->thFreeCopyFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE_COPY;
- }//if
- } else {
- ljam();
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + endOfList;
- }//if
+ ndbrequire(regPagePtr->page_state == ZTH_MM_FULL);
+ regPagePtr->page_state = ZTH_MM_FREE;
+ regPagePtr->next_page= regFragPtr->thFreeFirst;
+ regFragPtr->thFreeFirst = key->m_page_no;
+ }
}//Dbtup::freeTh()
-void Dbtup::freeThSr(Tablerec* const regTabPtr,
- Page* const regPagePtr,
- Uint32 freePageOffset)
-{
-/* ------------------------------------------------------------------------ */
-/* LINK THE NOW FREE TUPLE SPACE INTO BEGINNING OF FREE LIST OF OF THE PAGE */
-/* SET THE SIZE OF THE NEW FREE SPACE AND LINK TO THE OLD START OF FREELIST */
-/* ------------------------------------------------------------------------ */
- Uint32 startOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] >> 16;
- Uint32 endOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] & 0xffff;
- ndbrequire(freePageOffset < ZWORDS_ON_PAGE);
- regPagePtr->pageWord[freePageOffset] = (regTabPtr->tupheadsize << 16) + startOfList;
- if (endOfList == 0) {
- ljam();
- ndbrequire(startOfList == 0);
-/* ---------------------------------------------------------------- */
-/* THE PAGE WAS PREVIOUSLY FULL, NO EMPTY SPACE AT ALL. */
-/* THIS ENTRY WILL THEN BE BOTH THE START AND THE END OF THE */
-/* LIST. IT WILL ALSO BE PUT ON THE PROPER FREE LIST. */
-/* ---------------------------------------------------------------- */
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + freePageOffset;
- } else {
- ljam();
- regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + endOfList;
- }//if
-}//Dbtup::freeThSr()
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
index 66e98bd2805..694237c85be 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
@@ -25,11 +25,13 @@
#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; }
@@ -39,54 +41,36 @@
void Dbtup::initData()
{
cnoOfAttrbufrec = ZNO_OF_ATTRBUFREC;
- cnoOfLcpRec = ZNO_OF_LCP_REC;
- cnoOfConcurrentOpenOp = ZNO_OF_CONCURRENT_OPEN_OP;
- cnoOfConcurrentWriteOp = ZNO_OF_CONCURRENT_WRITE_OP;
- cnoOfFragoprec = 2 * MAX_FRAG_PER_NODE;
+ cnoOfFragrec = MAX_FRAG_PER_NODE;
+ cnoOfPage = ZNO_OF_PAGE;
+ cnoOfFragoprec = MAX_FRAG_PER_NODE;
cnoOfPageRangeRec = ZNO_OF_PAGE_RANGE_REC;
- cnoOfParallellUndoFiles = ZNO_OF_PARALLELL_UNDO_FILES;
- cnoOfRestartInfoRec = ZNO_OF_RESTART_INFO_REC;
c_maxTriggersPerTable = ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE;
c_noOfBuildIndexRec = 32;
- attrbufrec = 0;
- checkpointInfo = 0;
- diskBufferSegmentInfo = 0;
- fragoperrec = 0;
- fragrecord = 0;
- hostBuffer = 0;
- localLogInfo = 0;
- operationrec = 0;
- page = 0;
- pageRange = 0;
- pendingFileOpenInfo = 0;
- restartInfoRecord = 0;
- tablerec = 0;
- tableDescriptor = 0;
- undoPage = 0;
- totNoOfPagesAllocated = 0;
- cnoOfAllocatedPages = 0;
-
// Records with constant sizes
+ init_list_sizes();
}//Dbtup::initData()
-Dbtup::Dbtup(const class Configuration & conf)
+Dbtup::Dbtup(const class Configuration & conf, Pgman* pgman)
: SimulatedBlock(DBTUP, conf),
- c_storedProcPool(),
- c_buildIndexList(c_buildIndexPool)
+ c_lqh(0),
+ c_storedProcPool(),
+ c_buildIndexList(c_buildIndexPool),
+ c_undo_buffer(this),
+ m_pgman(this, pgman),
+ c_extent_hash(c_extent_pool)
{
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_TUP_LCPREQ, &Dbtup::execTUP_LCPREQ);
- addRecSignal(GSN_END_LCPREQ, &Dbtup::execEND_LCPREQ);
- addRecSignal(GSN_START_RECREQ, &Dbtup::execSTART_RECREQ);
addRecSignal(GSN_MEMCHECKREQ, &Dbtup::execMEMCHECKREQ);
addRecSignal(GSN_TUPKEYREQ, &Dbtup::execTUPKEYREQ);
addRecSignal(GSN_TUPSEIZEREQ, &Dbtup::execTUPSEIZEREQ);
@@ -96,12 +80,6 @@ Dbtup::Dbtup(const class Configuration & conf)
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_TUP_SRREQ, &Dbtup::execTUP_SRREQ);
- addRecSignal(GSN_TUP_PREPLCPREQ, &Dbtup::execTUP_PREPLCPREQ);
- addRecSignal(GSN_FSOPENCONF, &Dbtup::execFSOPENCONF);
- addRecSignal(GSN_FSCLOSECONF, &Dbtup::execFSCLOSECONF);
- addRecSignal(GSN_FSWRITECONF, &Dbtup::execFSWRITECONF);
- addRecSignal(GSN_FSREADCONF, &Dbtup::execFSREADCONF);
addRecSignal(GSN_NDB_STTOR, &Dbtup::execNDB_STTOR);
addRecSignal(GSN_READ_CONFIG_REQ, &Dbtup::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_SET_VAR_REQ, &Dbtup::execSET_VAR_REQ);
@@ -111,7 +89,6 @@ Dbtup::Dbtup(const class Configuration & conf)
addRecSignal(GSN_DROP_TRIG_REQ, &Dbtup::execDROP_TRIG_REQ);
addRecSignal(GSN_DROP_TAB_REQ, &Dbtup::execDROP_TAB_REQ);
- addRecSignal(GSN_FSREMOVECONF, &Dbtup::execFSREMOVECONF);
addRecSignal(GSN_TUP_ALLOCREQ, &Dbtup::execTUP_ALLOCREQ);
addRecSignal(GSN_TUP_DEALLOCREQ, &Dbtup::execTUP_DEALLOCREQ);
@@ -125,23 +102,18 @@ Dbtup::Dbtup(const class Configuration & conf)
addRecSignal(GSN_NEXT_SCANREQ, &Dbtup::execNEXT_SCANREQ);
addRecSignal(GSN_ACC_CHECK_SCAN, &Dbtup::execACC_CHECK_SCAN);
- initData();
-
- attrbufrec = 0;
- checkpointInfo = 0;
- diskBufferSegmentInfo = 0;
+ attrbufrec = 0;
fragoperrec = 0;
- fragrecord = 0;
- hostBuffer = 0;
- localLogInfo = 0;
- operationrec = 0;
- page = 0;
+ fragrecord = 0;
+ hostBuffer = 0;
+ cpage = 0;
pageRange = 0;
- pendingFileOpenInfo = 0;
- restartInfoRecord = 0;
- tablerec = 0;
- tableDescriptor = 0;
- undoPage = 0;
+ tablerec = 0;
+ tableDescriptor = 0;
+ totNoOfPagesAllocated = 0;
+ cnoOfAllocatedPages = 0;
+
+ initData();
}//Dbtup::Dbtup()
Dbtup::~Dbtup()
@@ -151,15 +123,6 @@ Dbtup::~Dbtup()
sizeof(Attrbufrec),
cnoOfAttrbufrec);
- deallocRecord((void **)&checkpointInfo,"CheckpointInfo",
- sizeof(CheckpointInfo),
- cnoOfLcpRec);
-
- deallocRecord((void **)&diskBufferSegmentInfo,
- "DiskBufferSegmentInfo",
- sizeof(DiskBufferSegmentInfo),
- cnoOfConcurrentWriteOp);
-
deallocRecord((void **)&fragoperrec,"Fragoperrec",
sizeof(Fragoperrec),
cnoOfFragoprec);
@@ -172,15 +135,7 @@ Dbtup::~Dbtup()
sizeof(HostBuffer),
MAX_NODES);
- deallocRecord((void **)&localLogInfo,"LocalLogInfo",
- sizeof(LocalLogInfo),
- cnoOfParallellUndoFiles);
-
- deallocRecord((void **)&operationrec,"Operationrec",
- sizeof(Operationrec),
- cnoOfOprec);
-
- deallocRecord((void **)&page,"Page",
+ deallocRecord((void **)&cpage,"Page",
sizeof(Page),
cnoOfPage);
@@ -188,16 +143,6 @@ Dbtup::~Dbtup()
sizeof(PageRange),
cnoOfPageRangeRec);
- deallocRecord((void **)&pendingFileOpenInfo,
- "PendingFileOpenInfo",
- sizeof(PendingFileOpenInfo),
- cnoOfConcurrentOpenOp);
-
- deallocRecord((void **)&restartInfoRecord,
- "RestartInfoRecord",
- sizeof(RestartInfoRecord),
- cnoOfRestartInfoRec);
-
deallocRecord((void **)&tablerec,"Tablerec",
sizeof(Tablerec),
cnoOfTablerec);
@@ -206,314 +151,16 @@ Dbtup::~Dbtup()
sizeof(TableDescriptor),
cnoOfTabDescrRec);
- deallocRecord((void **)&undoPage,"UndoPage",
- sizeof(UndoPage),
- cnoOfUndoPage);
-
}//Dbtup::~Dbtup()
BLOCK_FUNCTIONS(Dbtup)
-/* **************************************************************** */
-/* ---------------------------------------------------------------- */
-/* ----- GENERAL SIGNAL MULTIPLEXER (FS + CONTINUEB) -------------- */
-/* ---------------------------------------------------------------- */
-/* **************************************************************** */
-void Dbtup::execFSCLOSECONF(Signal* signal)
-{
- PendingFileOpenInfoPtr pfoPtr;
- ljamEntry();
- pfoPtr.i = signal->theData[0];
- ptrCheckGuard(pfoPtr, cnoOfConcurrentOpenOp, pendingFileOpenInfo);
- switch (pfoPtr.p->pfoOpenType) {
- case LCP_DATA_FILE_CLOSE:
- {
- CheckpointInfoPtr ciPtr;
- ljam();
- ciPtr.i = pfoPtr.p->pfoCheckpointInfoP;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- ciPtr.p->lcpDataFileHandle = RNIL;
- lcpClosedDataFileLab(signal, ciPtr);
- break;
- }
- case LCP_UNDO_FILE_CLOSE:
- {
- LocalLogInfoPtr lliPtr;
- ljam();
- lliPtr.i = pfoPtr.p->pfoCheckpointInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- lliPtr.p->lliUndoFileHandle = RNIL;
- lcpEndconfLab(signal);
- break;
- }
- case LCP_UNDO_FILE_READ:
- ljam();
- endExecUndoLogLab(signal, pfoPtr.p->pfoCheckpointInfoP);
- break;
- case LCP_DATA_FILE_READ:
- ljam();
- rfrClosedDataFileLab(signal, pfoPtr.p->pfoCheckpointInfoP);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- releasePendingFileOpenInfoRecord(pfoPtr);
-}//Dbtup::execFSCLOSECONF()
-
-void Dbtup::execFSOPENCONF(Signal* signal)
-{
- PendingFileOpenInfoPtr pfoPtr;
-
- ljamEntry();
- pfoPtr.i = signal->theData[0];
- Uint32 fileHandle = signal->theData[1];
- ptrCheckGuard(pfoPtr, cnoOfConcurrentOpenOp, pendingFileOpenInfo);
- switch (pfoPtr.p->pfoOpenType) {
- case LCP_DATA_FILE_READ:
- {
- RestartInfoRecordPtr riPtr;
- ljam();
- riPtr.i = pfoPtr.p->pfoRestartInfoP;
- ptrCheckGuard(riPtr, cnoOfRestartInfoRec, restartInfoRecord);
- riPtr.p->sriDataFileHandle = fileHandle;
- rfrReadRestartInfoLab(signal, riPtr);
- break;
- }
- case LCP_UNDO_FILE_READ:
- {
- RestartInfoRecordPtr riPtr;
- LocalLogInfoPtr lliPtr;
- DiskBufferSegmentInfoPtr dbsiPtr;
-
- ljam();
- riPtr.i = pfoPtr.p->pfoRestartInfoP;
- ptrCheckGuard(riPtr, cnoOfRestartInfoRec, restartInfoRecord);
- lliPtr.i = riPtr.p->sriLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- lliPtr.p->lliUndoFileHandle = fileHandle;
- dbsiPtr.i = riPtr.p->sriDataBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- rfrLoadDataPagesLab(signal, riPtr, dbsiPtr);
- break;
- }
- case LCP_DATA_FILE_WRITE_WITH_UNDO:
- {
- CheckpointInfoPtr ciPtr;
- LocalLogInfoPtr lliPtr;
-
- ljam();
- ciPtr.i = pfoPtr.p->pfoCheckpointInfoP;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- lliPtr.i = ciPtr.p->lcpLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- ciPtr.p->lcpDataFileHandle = fileHandle;
- if (lliPtr.p->lliUndoFileHandle != RNIL) {
- ljam();
- signal->theData[0] = ciPtr.p->lcpUserptr;
- signal->theData[1] = ciPtr.i;
- sendSignal(ciPtr.p->lcpBlockref, GSN_TUP_PREPLCPCONF, signal, 2, JBB);
- }//if
- break;
- }
- case LCP_DATA_FILE_WRITE:
- {
- CheckpointInfoPtr ciPtr;
-
- ljam();
- ciPtr.i = pfoPtr.p->pfoCheckpointInfoP;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- ciPtr.p->lcpDataFileHandle = fileHandle;
- signal->theData[0] = ciPtr.p->lcpUserptr;
- signal->theData[1] = ciPtr.i;
- sendSignal(ciPtr.p->lcpBlockref, GSN_TUP_PREPLCPCONF, signal, 2, JBB);
- break;
- }
- case LCP_UNDO_FILE_WRITE:
- {
- CheckpointInfoPtr ciPtr;
- LocalLogInfoPtr lliPtr;
-
- ljam();
- ciPtr.i = pfoPtr.p->pfoCheckpointInfoP;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- lliPtr.i = ciPtr.p->lcpLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- lliPtr.p->lliUndoFileHandle = fileHandle;
- if (ciPtr.p->lcpDataFileHandle != RNIL) {
- ljam();
- signal->theData[0] = ciPtr.p->lcpUserptr;
- signal->theData[1] = ciPtr.i;
- sendSignal(ciPtr.p->lcpBlockref, GSN_TUP_PREPLCPCONF, signal, 2, JBB);
- }//if
- break;
- }
- default:
- ndbrequire(false);
- break;
- }//switch
- releasePendingFileOpenInfoRecord(pfoPtr);
-}//Dbtup::execFSOPENCONF()
-
-void Dbtup::execFSREADCONF(Signal* signal)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
- ljamEntry();
- dbsiPtr.i = signal->theData[0];
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- switch (dbsiPtr.p->pdxOperation) {
- case CHECKPOINT_DATA_READ:
- {
- RestartInfoRecordPtr riPtr;
- ljam();
- riPtr.i = dbsiPtr.p->pdxRestartInfoP;
- ptrCheckGuard(riPtr, cnoOfRestartInfoRec, restartInfoRecord);
-/************************************************************/
-/* VERIFY THAT THE PAGES ARE CORRECT, HAVE A CORRECT */
-/* STATE AND A CORRECT PAGE ID. */
-/************************************************************/
- ndbrequire(dbsiPtr.p->pdxNumDataPages <= 16);
- for (Uint32 i = 0; i < dbsiPtr.p->pdxNumDataPages; i++) {
- PagePtr pagePtr;
- ljam();
- pagePtr.i = dbsiPtr.p->pdxDataPage[i];
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- ndbrequire(pagePtr.p->pageWord[ZPAGE_STATE_POS] != 0);
- ndbrequire(pagePtr.p->pageWord[ZPAGE_STATE_POS] <= ZAC_MM_FREE_COPY);
- ndbrequire(pagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS] == ((dbsiPtr.p->pdxFilePage - 1) + i));
- }//for
- rfrLoadDataPagesLab(signal, riPtr, dbsiPtr);
- break;
- }
- case CHECKPOINT_DATA_READ_PAGE_ZERO:
- {
- ljam();
- rfrInitRestartInfoLab(signal, dbsiPtr);
- break;
- }
- case CHECKPOINT_UNDO_READ:
- {
- LocalLogInfoPtr lliPtr;
- ljam();
- lliPtr.i = dbsiPtr.p->pdxCheckpointInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- xlcGetNextRecordLab(signal, dbsiPtr, lliPtr);
- break;
- }
- case CHECKPOINT_UNDO_READ_FIRST:
- ljam();
- rfrReadSecondUndoLogLab(signal, dbsiPtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
-}//Dbtup::execFSREADCONF()
-
-void Dbtup::execFSWRITECONF(Signal* signal)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
-
- ljamEntry();
- dbsiPtr.i = signal->theData[0];
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- switch (dbsiPtr.p->pdxOperation) {
- case CHECKPOINT_DATA_WRITE:
- ljam();
- lcpSaveDataPageLab(signal, dbsiPtr.p->pdxCheckpointInfoP);
- break;
- case CHECKPOINT_DATA_WRITE_LAST:
- {
- CheckpointInfoPtr ciPtr;
- ljam();
- ciPtr.i = dbsiPtr.p->pdxCheckpointInfoP;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- lcpFlushLogLab(signal, ciPtr);
- break;
- }
- case CHECKPOINT_DATA_WRITE_FLUSH:
- {
- ljam();
- Uint32 ciIndex = dbsiPtr.p->pdxCheckpointInfoP;
- freeDiskBufferSegmentRecord(signal, dbsiPtr);
- lcpCompletedLab(signal, ciIndex);
- break;
- }
- case CHECKPOINT_UNDO_WRITE_FLUSH:
- {
- ljam();
- Uint32 ciIndex = dbsiPtr.p->pdxCheckpointInfoP;
- freeDiskBufferSegmentRecord(signal, dbsiPtr);
- lcpFlushRestartInfoLab(signal, ciIndex);
- break;
- }
- case CHECKPOINT_UNDO_WRITE:
- ljam();
- freeDiskBufferSegmentRecord(signal, dbsiPtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- return;
-}//Dbtup::execFSWRITECONF()
-
void Dbtup::execCONTINUEB(Signal* signal)
{
ljamEntry();
Uint32 actionType = signal->theData[0];
Uint32 dataPtr = signal->theData[1];
switch (actionType) {
- case ZSTART_EXEC_UNDO_LOG:
- ljam();
- startExecUndoLogLab(signal, dataPtr);
- break;
- case ZCONT_SAVE_DP:
- ljam();
- lcpSaveDataPageLab(signal, dataPtr);
- break;
- case ZCONT_START_SAVE_CL:
- {
- CheckpointInfoPtr ciPtr;
-
- ljam();
- ciPtr.i = dataPtr;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- lcpSaveCopyListLab(signal, ciPtr);
- break;
- }
- case ZCONT_EXECUTE_LC:
- {
- LocalLogInfoPtr lliPtr;
- DiskBufferSegmentInfoPtr dbsiPtr;
-
- ljam();
- lliPtr.i = dataPtr;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- dbsiPtr.i = lliPtr.p->lliUndoBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- xlcGetNextRecordLab(signal, dbsiPtr, lliPtr);
- break;
- }
- case ZCONT_LOAD_DP:
- {
- DiskBufferSegmentInfoPtr dbsiPtr;
- RestartInfoRecordPtr riPtr;
-
- ljam();
- riPtr.i = dataPtr;
- ptrCheckGuard(riPtr, cnoOfRestartInfoRec, restartInfoRecord);
- dbsiPtr.i = riPtr.p->sriDataBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- rfrLoadDataPagesLab(signal, riPtr, dbsiPtr);
- break;
- }
- case ZLOAD_BAL_LCP_TIMER:
- ljam();
- clblPageCounter = clblPagesPerTick;
- signal->theData[0] = ZLOAD_BAL_LCP_TIMER;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 400, 1);
- break;
case ZINITIALISE_RECORDS:
ljam();
initialiseRecordsLab(signal, dataPtr,
@@ -550,6 +197,32 @@ void Dbtup::execCONTINUEB(Signal* signal)
ljam();
buildIndex(signal, dataPtr);
break;
+ case ZFREE_EXTENT:
+ {
+ ljam();
+
+ TablerecPtr tabPtr;
+ tabPtr.i= dataPtr;
+ FragrecordPtr fragPtr;
+ fragPtr.i= signal->theData[2];
+ ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ drop_fragment_free_exent(signal, tabPtr, fragPtr, signal->theData[3]);
+ return;
+ }
+ case ZUNMAP_PAGES:
+ {
+ ljam();
+
+ 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;
+ }
default:
ndbrequire(false);
break;
@@ -570,6 +243,9 @@ void Dbtup::execSTTOR(Signal* signal)
case ZSTARTPHASE1:
ljam();
CLEAR_ERROR_INSERT_VALUE;
+ 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:
@@ -602,25 +278,9 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
- Uint32 log_page_size= 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_UNDO_DATA_BUFFER,
- &log_page_size);
-
- /**
- * Always set page size in half MBytes
- */
- cnoOfUndoPage= (log_page_size / sizeof(UndoPage));
- Uint32 mega_byte_part= cnoOfUndoPage & 15;
- if (mega_byte_part != 0) {
- jam();
- cnoOfUndoPage+= (16 - mega_byte_part);
- }
-
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_FRAG, &cnoOfFragrec));
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &cnoOfOprec));
-
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE, &cnoOfPage));
+
Uint32 noOfTriggers= 0;
Uint32 tmp= 0;
@@ -635,10 +295,6 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
&noOfTriggers));
- Uint32 nScanOp; // use TUX config for now
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
-
-
cnoOfTabDescrRec = (cnoOfTabDescrRec & 0xFFFFFFF0) + 16;
initRecords();
@@ -646,25 +302,25 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
c_storedProcPool.setSize(noOfStoredProc);
c_buildIndexPool.setSize(c_noOfBuildIndexRec);
c_triggerPool.setSize(noOfTriggers);
- c_scanOpPool.setSize(nScanOp);
+
+ c_extent_pool.setSize(256);
+ c_extent_hash.setSize(1024); // 4k
+ c_page_request_pool.setSize(100);
+
+ Uint32 nScanOp; // use TUX config for now
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
+ c_scanOpPool.setSize(nScanOp + 1);
+
+ ScanOpPtr lcp;
+ ndbrequire(c_scanOpPool.seize(lcp));
+ c_lcp_scan_op= lcp.i;
czero = 0;
cminusOne = czero - 1;
clastBitMask = 1;
clastBitMask = clastBitMask << 31;
- cnoOfLocalLogInfo = 0;
- cnoFreeUndoSeg = 0;
initialiseRecordsLab(signal, 0, ref, senderData);
-
- clblPagesPerTick = 50;
- ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_TUP_SR,
- &clblPagesPerTick);
-
- clblPagesPerTickAfterSr = 50;
- ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_TUP,
- &clblPagesPerTickAfterSr);
-
}//Dbtup::execSIZEALT_REP()
void Dbtup::initRecords()
@@ -672,32 +328,15 @@ void Dbtup::initRecords()
unsigned i;
// Records with dynamic sizes
- page = (Page*)allocRecord("Page",
+ cpage = (Page*)allocRecord("Page",
sizeof(Page),
cnoOfPage,
false);
- undoPage = (UndoPage*)allocRecord("UndoPage",
- sizeof(UndoPage),
- cnoOfUndoPage);
-
- operationrec = (Operationrec*)allocRecord("Operationrec",
- sizeof(Operationrec),
- cnoOfOprec);
-
attrbufrec = (Attrbufrec*)allocRecord("Attrbufrec",
sizeof(Attrbufrec),
cnoOfAttrbufrec);
- checkpointInfo = (CheckpointInfo*)allocRecord("CheckpointInfo",
- sizeof(CheckpointInfo),
- cnoOfLcpRec);
-
- diskBufferSegmentInfo = (DiskBufferSegmentInfo*)
- allocRecord("DiskBufferSegmentInfo",
- sizeof(DiskBufferSegmentInfo),
- cnoOfConcurrentWriteOp);
-
fragoperrec = (Fragoperrec*)allocRecord("Fragoperrec",
sizeof(Fragoperrec),
cnoOfFragoprec);
@@ -706,60 +345,33 @@ void Dbtup::initRecords()
sizeof(Fragrecord),
cnoOfFragrec);
- for (i = 0; i<cnoOfFragrec; i++) {
- void * p = &fragrecord[i];
- new (p) Fragrecord(c_scanOpPool);
- }
-
hostBuffer = (HostBuffer*)allocRecord("HostBuffer",
sizeof(HostBuffer),
MAX_NODES);
- localLogInfo = (LocalLogInfo*)allocRecord("LocalLogInfo",
- sizeof(LocalLogInfo),
- cnoOfParallellUndoFiles);
+ tableDescriptor = (TableDescriptor*)allocRecord("TableDescriptor",
+ sizeof(TableDescriptor),
+ cnoOfTabDescrRec);
+ Uint32 tmp;
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &tmp));
+ c_operation_pool.setSize(tmp);
+
pageRange = (PageRange*)allocRecord("PageRange",
sizeof(PageRange),
cnoOfPageRangeRec);
- pendingFileOpenInfo = (PendingFileOpenInfo*)
- allocRecord("PendingFileOpenInfo",
- sizeof(PendingFileOpenInfo),
- cnoOfConcurrentOpenOp);
-
- restartInfoRecord = (RestartInfoRecord*)
- allocRecord("RestartInfoRecord",
- sizeof(RestartInfoRecord),
- cnoOfRestartInfoRec);
-
-
tablerec = (Tablerec*)allocRecord("Tablerec",
sizeof(Tablerec),
cnoOfTablerec);
-
+
for (i = 0; i<cnoOfTablerec; i++) {
void * p = &tablerec[i];
new (p) Tablerec(c_triggerPool);
}
-
- tableDescriptor = (TableDescriptor*)
- allocRecord("TableDescriptor",
- sizeof(TableDescriptor),
- cnoOfTabDescrRec);
-
- // Initialize BAT for interface to file system
- NewVARIABLE* bat = allocateBat(3);
- bat[1].WA = &page->pageWord[0];
- bat[1].nrr = cnoOfPage;
- bat[1].ClusterSize = sizeof(Page);
- bat[1].bits.q = 13; /* 8192 words/page */
- bat[1].bits.v = 5;
- bat[2].WA = &undoPage->undoPageWord[0];
- bat[2].nrr = cnoOfUndoPage;
- bat[2].ClusterSize = sizeof(UndoPage);
- bat[2].bits.q = 13; /* 8192 words/page */
- bat[2].bits.v = 5;
}//Dbtup::initRecords()
void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
@@ -780,7 +392,6 @@ void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
break;
case 3:
ljam();
- initializeUndoPage();
break;
case 4:
ljam();
@@ -788,7 +399,6 @@ void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
break;
case 5:
ljam();
- initializeCheckpointInfoRec();
break;
case 6:
ljam();
@@ -808,11 +418,9 @@ void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
break;
case 10:
ljam();
- initializeDiskBufferSegmentRecord();
break;
case 11:
ljam();
- initializeLocalLogInfo();
break;
case 12:
ljam();
@@ -820,11 +428,9 @@ void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
break;
case 13:
ljam();
- initializePendingFileOpenInfoRecord();
break;
case 14:
ljam();
- initializeRestartInfoRec();
{
ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
@@ -875,8 +481,6 @@ void Dbtup::execNDB_STTOR(Signal* signal)
/* PAGES PER TICK AFTER SYSTEM */
/* RESTART. */
/*****************************************/
- clblPagesPerTick = clblPagesPerTickAfterSr;
-
signal->theData[0] = ZREPORT_MEMORY_USAGE;
sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 2000, 1);
break;
@@ -890,9 +494,6 @@ void Dbtup::execNDB_STTOR(Signal* signal)
void Dbtup::startphase3Lab(Signal* signal, Uint32 config1, Uint32 config2)
{
- clblPageCounter = clblPagesPerTick;
- signal->theData[0] = ZLOAD_BAL_LCP_TIMER;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 1);
}//Dbtup::startphase3Lab()
void Dbtup::initializeAttrbufrec()
@@ -911,35 +512,6 @@ void Dbtup::initializeAttrbufrec()
cnoFreeAttrbufrec = cnoOfAttrbufrec;
}//Dbtup::initializeAttrbufrec()
-void Dbtup::initializeCheckpointInfoRec()
-{
- CheckpointInfoPtr checkpointInfoPtr;
- for (checkpointInfoPtr.i = 0;
- checkpointInfoPtr.i < cnoOfLcpRec; checkpointInfoPtr.i++) {
- ptrAss(checkpointInfoPtr, checkpointInfo);
- checkpointInfoPtr.p->lcpNextRec = checkpointInfoPtr.i + 1;
- }//for
- checkpointInfoPtr.i = cnoOfLcpRec - 1;
- ptrAss(checkpointInfoPtr, checkpointInfo);
- checkpointInfoPtr.p->lcpNextRec = RNIL;
- cfirstfreeLcp = 0;
-}//Dbtup::initializeCheckpointInfoRec()
-
-void Dbtup::initializeDiskBufferSegmentRecord()
-{
- DiskBufferSegmentInfoPtr diskBufferSegmentPtr;
- for (diskBufferSegmentPtr.i = 0;
- diskBufferSegmentPtr.i < cnoOfConcurrentWriteOp; diskBufferSegmentPtr.i++) {
- ptrAss(diskBufferSegmentPtr, diskBufferSegmentInfo);
- diskBufferSegmentPtr.p->pdxNextRec = diskBufferSegmentPtr.i + 1;
- diskBufferSegmentPtr.p->pdxBuffertype = NOT_INITIALIZED;
- }//for
- diskBufferSegmentPtr.i = cnoOfConcurrentWriteOp - 1;
- ptrAss(diskBufferSegmentPtr, diskBufferSegmentInfo);
- diskBufferSegmentPtr.p->pdxNextRec = RNIL;
- cfirstfreePdx = 0;
-}//Dbtup::initializeDiskBufferSegmentRecord()
-
void Dbtup::initializeFragoperrec()
{
FragoperrecPtr fragoperPtr;
@@ -960,9 +532,6 @@ void Dbtup::initializeFragrecord()
refresh_watch_dog();
ptrAss(regFragPtr, fragrecord);
regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
- regFragPtr.p->checkpointVersion = RNIL;
- regFragPtr.p->firstusedOprec = RNIL;
- regFragPtr.p->lastusedOprec = RNIL;
regFragPtr.p->fragStatus = IDLE;
}//for
regFragPtr.i = cnoOfFragrec - 1;
@@ -982,71 +551,12 @@ void Dbtup::initializeHostBuffer()
}//for
}//Dbtup::initializeHostBuffer()
-void Dbtup::initializeLocalLogInfo()
-{
- LocalLogInfoPtr localLogInfoPtr;
- for (localLogInfoPtr.i = 0;
- localLogInfoPtr.i < cnoOfParallellUndoFiles; localLogInfoPtr.i++) {
- ptrAss(localLogInfoPtr, localLogInfo);
- localLogInfoPtr.p->lliActiveLcp = 0;
- localLogInfoPtr.p->lliUndoFileHandle = RNIL;
- }//for
-}//Dbtup::initializeLocalLogInfo()
void Dbtup::initializeOperationrec()
{
- OperationrecPtr regOpPtr;
- for (regOpPtr.i = 0; regOpPtr.i < cnoOfOprec; regOpPtr.i++) {
- refresh_watch_dog();
- ptrAss(regOpPtr, operationrec);
- regOpPtr.p->firstAttrinbufrec = RNIL;
- regOpPtr.p->lastAttrinbufrec = RNIL;
- regOpPtr.p->prevOprecInList = RNIL;
- regOpPtr.p->nextOprecInList = regOpPtr.i + 1;
- regOpPtr.p->optype = ZREAD;
- regOpPtr.p->inFragList = ZFALSE;
- regOpPtr.p->inActiveOpList = ZFALSE;
-/* FOR ABORT HANDLING BEFORE ANY SUCCESSFUL OPERATION */
- regOpPtr.p->transstate = DISCONNECTED;
- regOpPtr.p->storedProcedureId = ZNIL;
- regOpPtr.p->prevActiveOp = RNIL;
- regOpPtr.p->nextActiveOp = RNIL;
- regOpPtr.p->tupVersion = ZNIL;
- regOpPtr.p->deleteInsertFlag = 0;
- }//for
- regOpPtr.i = cnoOfOprec - 1;
- ptrAss(regOpPtr, operationrec);
- regOpPtr.p->nextOprecInList = RNIL;
- cfirstfreeOprec = 0;
+ refresh_watch_dog();
}//Dbtup::initializeOperationrec()
-void Dbtup::initializePendingFileOpenInfoRecord()
-{
- PendingFileOpenInfoPtr pendingFileOpenInfoPtr;
- for (pendingFileOpenInfoPtr.i = 0;
- pendingFileOpenInfoPtr.i < cnoOfConcurrentOpenOp; pendingFileOpenInfoPtr.i++) {
- ptrAss(pendingFileOpenInfoPtr, pendingFileOpenInfo);
- pendingFileOpenInfoPtr.p->pfoNextRec = pendingFileOpenInfoPtr.i + 1;
- }//for
- pendingFileOpenInfoPtr.i = cnoOfConcurrentOpenOp - 1;
- ptrAss(pendingFileOpenInfoPtr, pendingFileOpenInfo);
- pendingFileOpenInfoPtr.p->pfoNextRec = RNIL;
- cfirstfreePfo = 0;
-}//Dbtup::initializePendingFileOpenInfoRecord()
-
-void Dbtup::initializeRestartInfoRec()
-{
- RestartInfoRecordPtr restartInfoPtr;
- for (restartInfoPtr.i = 0; restartInfoPtr.i < cnoOfRestartInfoRec; restartInfoPtr.i++) {
- ptrAss(restartInfoPtr, restartInfoRecord);
- restartInfoPtr.p->sriNextRec = restartInfoPtr.i + 1;
- }//for
- restartInfoPtr.i = cnoOfRestartInfoRec - 1;
- ptrAss(restartInfoPtr, restartInfoRecord);
- restartInfoPtr.p->sriNextRec = RNIL;
- cfirstfreeSri = 0;
-}//Dbtup::initializeRestartInfoRec()
-
void Dbtup::initializeTablerec()
{
TablerecPtr regTabPtr;
@@ -1061,7 +571,7 @@ void Dbtup::initializeTablerec()
void
Dbtup::initTab(Tablerec* const regTabPtr)
{
- for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
regTabPtr->fragid[i] = RNIL;
regTabPtr->fragrec[i] = RNIL;
}//for
@@ -1070,22 +580,12 @@ Dbtup::initTab(Tablerec* const regTabPtr)
regTabPtr->charsetArray = NULL;
regTabPtr->tabDescriptor = RNIL;
- regTabPtr->attributeGroupDescriptor = RNIL;
regTabPtr->readKeyArray = RNIL;
regTabPtr->checksumIndicator = false;
- regTabPtr->GCPIndicator = false;
- regTabPtr->noOfAttr = 0;
+ regTabPtr->m_no_of_attributes = 0;
regTabPtr->noOfKeyAttr = 0;
- regTabPtr->noOfNewAttr = 0;
- regTabPtr->noOfAttributeGroups = 0;
-
- regTabPtr->tupheadsize = 0;
- regTabPtr->tupNullIndex = 0;
- regTabPtr->tupNullWords = 0;
- regTabPtr->tupChecksumIndex = 0;
- regTabPtr->tupGCPIndex = 0;
regTabPtr->m_dropTable.tabUserPtr = RNIL;
regTabPtr->m_dropTable.tabUserRef = 0;
@@ -1124,24 +624,6 @@ void Dbtup::initializeTabDescr()
freeTabDescr(0, cnoOfTabDescrRec);
}//Dbtup::initializeTabDescr()
-void Dbtup::initializeUndoPage()
-{
- UndoPagePtr undoPagep;
- for (undoPagep.i = 0;
- undoPagep.i < cnoOfUndoPage;
- undoPagep.i = undoPagep.i + ZUB_SEGMENT_SIZE) {
- refresh_watch_dog();
- ptrAss(undoPagep, undoPage);
- undoPagep.p->undoPageWord[ZPAGE_NEXT_POS] = undoPagep.i +
- ZUB_SEGMENT_SIZE;
- cnoFreeUndoSeg++;
- }//for
- undoPagep.i = cnoOfUndoPage - ZUB_SEGMENT_SIZE;
- ptrAss(undoPagep, undoPage);
- undoPagep.p->undoPageWord[ZPAGE_NEXT_POS] = RNIL;
- cfirstfreeUndoSeg = 0;
-}//Dbtup::initializeUndoPage()
-
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */
/* --------------- CONNECT/DISCONNECT MODULE ---------------------- */
@@ -1153,27 +635,36 @@ void Dbtup::execTUPSEIZEREQ(Signal* signal)
ljamEntry();
Uint32 userPtr = signal->theData[0];
BlockReference userRef = signal->theData[1];
- if (cfirstfreeOprec != RNIL) {
- ljam();
- seizeOpRec(regOperPtr);
- } else {
+ if (!c_operation_pool.seize(regOperPtr))
+ {
ljam();
signal->theData[0] = userPtr;
signal->theData[1] = ZGET_OPREC_ERROR;
sendSignal(userRef, GSN_TUPSEIZEREF, signal, 2, JBB);
return;
}//if
- regOperPtr.p->optype = ZREAD;
- initOpConnection(regOperPtr.p, 0);
+
+ new (regOperPtr.p) Operationrec();
+ regOperPtr.p->firstAttrinbufrec = RNIL;
+ regOperPtr.p->lastAttrinbufrec = RNIL;
+ 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;
- regOperPtr.p->userblockref = userRef;
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 < (2 * MAX_FRAG_PER_NODE);i++){\
+#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]); }}
@@ -1182,139 +673,21 @@ void Dbtup::execTUPRELEASEREQ(Signal* signal)
OperationrecPtr regOperPtr;
ljamEntry();
regOperPtr.i = signal->theData[0];
- ptrCheckGuard(regOperPtr, cnoOfOprec, operationrec);
- regOperPtr.p->transstate = DISCONNECTED;
- regOperPtr.p->nextOprecInList = cfirstfreeOprec;
- cfirstfreeOprec = regOperPtr.i;
+ c_operation_pool.getPtr(regOperPtr);
+ set_trans_state(regOperPtr.p, TRANS_DISCONNECTED);
+ c_operation_pool.release(regOperPtr);
+
signal->theData[0] = regOperPtr.p->userpointer;
- sendSignal(regOperPtr.p->userblockref, GSN_TUPRELEASECONF, signal, 1, JBB);
+ sendSignal(DBLQH_REF, GSN_TUPRELEASECONF, signal, 1, JBB);
return;
}//Dbtup::execTUPRELEASEREQ()
-/* ---------------------------------------------------------------- */
-/* ---------------- FREE_DISK_BUFFER_SEGMENT_RECORD --------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* THIS ROUTINE DEALLOCATES A DISK SEGMENT AND ITS DATA PAGES */
-/* */
-/* INPUT: DISK_BUFFER_SEGMENT_PTR THE DISK SEGMENT */
-/* */
-/* -----------------------------------------------------------------*/
-void Dbtup::freeDiskBufferSegmentRecord(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr)
-{
- switch (dbsiPtr.p->pdxBuffertype) {
- case UNDO_PAGES:
- case COMMON_AREA_PAGES:
- ljam();
- freeUndoBufferPages(signal, dbsiPtr);
- break;
- case UNDO_RESTART_PAGES:
- ljam();
- dbsiPtr.p->pdxDataPage[0] = dbsiPtr.p->pdxUndoBufferSet[0];
- freeUndoBufferPages(signal, dbsiPtr);
- dbsiPtr.p->pdxDataPage[0] = dbsiPtr.p->pdxUndoBufferSet[1];
- freeUndoBufferPages(signal, dbsiPtr);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- releaseDiskBufferSegmentRecord(dbsiPtr);
-}//Dbtup::freeDiskBufferSegmentRecord()
-
-/* ---------------------------------------------------------------- */
-/* -------------------- FREE_UNDO_BUFFER_PAGES -------------------- */
-/* ---------------------------------------------------------------- */
-/* */
-/* THIS ROUTINE DEALLOCATES A SEGMENT OF UNDO PAGES */
-/* */
-/* INPUT: UNDO_PAGEP POINTER TO FIRST PAGE IN SEGMENT */
-/* */
-/* -----------------------------------------------------------------*/
-void Dbtup::freeUndoBufferPages(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr)
-{
- UndoPagePtr undoPagePtr;
-
- undoPagePtr.i = dbsiPtr.p->pdxDataPage[0];
- ptrCheckGuard(undoPagePtr, cnoOfUndoPage, undoPage);
- undoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS] = cfirstfreeUndoSeg;
- cfirstfreeUndoSeg = undoPagePtr.i;
- cnoFreeUndoSeg++;
- if (cnoFreeUndoSeg == ZMIN_PAGE_LIMIT_TUP_COMMITREQ) {
- EXECUTE_DIRECT(DBLQH, GSN_TUP_COM_UNBLOCK, signal, 1);
- ljamEntry();
- }//if
-}//Dbtup::freeUndoBufferPages()
-
-void Dbtup::releaseCheckpointInfoRecord(CheckpointInfoPtr ciPtr)
-{
- ciPtr.p->lcpNextRec = cfirstfreeLcp;
- cfirstfreeLcp = ciPtr.i;
-}//Dbtup::releaseCheckpointInfoRecord()
-
-void Dbtup::releaseDiskBufferSegmentRecord(DiskBufferSegmentInfoPtr dbsiPtr)
-{
- dbsiPtr.p->pdxNextRec = cfirstfreePdx;
- cfirstfreePdx = dbsiPtr.i;
-}//Dbtup::releaseDiskBufferSegmentRecord()
-
void Dbtup::releaseFragrec(FragrecordPtr regFragPtr)
{
regFragPtr.p->nextfreefrag = cfirstfreefrag;
cfirstfreefrag = regFragPtr.i;
}//Dbtup::releaseFragrec()
-void Dbtup::releasePendingFileOpenInfoRecord(PendingFileOpenInfoPtr pfoPtr)
-{
- pfoPtr.p->pfoNextRec = cfirstfreePfo;
- cfirstfreePfo = pfoPtr.i;
-}//Dbtup::releasePendingFileOpenInfoRecord()
-
-void Dbtup::releaseRestartInfoRecord(RestartInfoRecordPtr riPtr)
-{
- riPtr.p->sriNextRec = cfirstfreeSri;
- cfirstfreeSri = riPtr.i;
-}//Dbtup::releaseRestartInfoRecord()
-
-void Dbtup::seizeCheckpointInfoRecord(CheckpointInfoPtr& ciPtr)
-{
- ciPtr.i = cfirstfreeLcp;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- cfirstfreeLcp = ciPtr.p->lcpNextRec;
- ciPtr.p->lcpNextRec = RNIL;
-}//Dbtup::seizeCheckpointInfoRecord()
-
-void Dbtup::seizeDiskBufferSegmentRecord(DiskBufferSegmentInfoPtr& dbsiPtr)
-{
- dbsiPtr.i = cfirstfreePdx;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- cfirstfreePdx = dbsiPtr.p->pdxNextRec;
- dbsiPtr.p->pdxNextRec = RNIL;
- for (Uint32 i = 0; i < 16; i++) {
- dbsiPtr.p->pdxDataPage[i] = RNIL;
- }//for
- dbsiPtr.p->pdxCheckpointInfoP = RNIL;
- dbsiPtr.p->pdxRestartInfoP = RNIL;
- dbsiPtr.p->pdxLocalLogInfoP = RNIL;
- dbsiPtr.p->pdxFilePage = 0;
- dbsiPtr.p->pdxNumDataPages = 0;
-}//Dbtup::seizeDiskBufferSegmentRecord()
-
-void Dbtup::seizeOpRec(OperationrecPtr& regOperPtr)
-{
- regOperPtr.i = cfirstfreeOprec;
- ptrCheckGuard(regOperPtr, cnoOfOprec, operationrec);
- cfirstfreeOprec = regOperPtr.p->nextOprecInList;
-}//Dbtup::seizeOpRec()
-
-void Dbtup::seizePendingFileOpenInfoRecord(PendingFileOpenInfoPtr& pfoiPtr)
-{
- pfoiPtr.i = cfirstfreePfo;
- ptrCheckGuard(pfoiPtr, cnoOfConcurrentOpenOp, pendingFileOpenInfo);
- cfirstfreePfo = pfoiPtr.p->pfoNextRec;
- pfoiPtr.p->pfoNextRec = RNIL;
-}//Dbtup::seizePendingFileOpenInfoRecord()
-
void Dbtup::execSET_VAR_REQ(Signal* signal)
{
#if 0
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
index ab6e0642e11..a70b3739270 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
@@ -30,200 +30,251 @@
// methods used by ordered index
void
-Dbtup::tuxGetTupAddr(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32& tupAddr)
+Dbtup::tuxGetTupAddr(Uint32 fragPtrI,
+ Uint32 pageId,
+ Uint32 pageIndex,
+ Uint32& tupAddr)
{
ljamEntry();
- 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, page);
- Uint32 fragPageId = pagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- Uint32 tupheadsize = tablePtr.p->tupheadsize;
- ndbrequire(pageOffset >= ZPAGE_HEADER_SIZE);
- Uint32 offset = pageOffset - ZPAGE_HEADER_SIZE;
- ndbrequire(offset % tupheadsize == 0);
- Uint32 pageIndex = (offset / tupheadsize) << 1;
- tupAddr = (fragPageId << MAX_TUPLES_BITS) | pageIndex;
+ pagePtr.i= pageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ 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)
+Dbtup::tuxAllocNode(Signal* signal,
+ Uint32 fragPtrI,
+ Uint32& pageId,
+ Uint32& pageOffset,
+ Uint32*& node)
{
ljamEntry();
FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
+ fragPtr.i= fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
+ tablePtr.i= fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- terrorCode = 0;
- if (! allocTh(fragPtr.p, tablePtr.p, NORMAL_PAGE, signal, pageOffset, pagePtr)) {
+ terrorCode= 0;
+
+ Local_key key;
+ Uint32* ptr, frag_page_id;
+ if ((ptr= alloc_fix_rec(fragPtr.p, tablePtr.p, &key, &frag_page_id)) == 0)
+ {
ljam();
ndbrequire(terrorCode != 0);
return terrorCode;
}
- pageId = pagePtr.i;
- Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
- node = &pagePtr.p->pageWord[pageOffset] + attrDataOffset;
+ 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)
+Dbtup::tuxFreeNode(Signal* signal,
+ Uint32 fragPtrI,
+ Uint32 pageId,
+ Uint32 pageOffset,
+ Uint32* node)
{
ljamEntry();
FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
+ fragPtr.i= fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
+ tablePtr.i= fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
+ 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)
+Dbtup::tuxGetNode(Uint32 fragPtrI,
+ Uint32 pageId,
+ Uint32 pageOffset,
+ Uint32*& node)
{
ljamEntry();
FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
+ fragPtr.i= fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
+ tablePtr.i= fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 attrDescIndex = tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
- Uint32 attrDataOffset = AttributeOffset::getOffset(tableDescriptor[attrDescIndex + 1].tabDescr);
- node = &pagePtr.p->pageWord[pageOffset] + attrDataOffset;
+ pagePtr.i= pageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ 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 pageOffset, Uint32 tupVersion, const Uint32* attrIds, Uint32 numAttrs, Uint32* dataOut)
+Dbtup::tuxReadAttrs(Uint32 fragPtrI,
+ Uint32 pageId,
+ Uint32 pageIndex,
+ Uint32 tupVersion,
+ const Uint32* attrIds,
+ Uint32 numAttrs,
+ Uint32* dataOut)
{
ljamEntry();
// use own variables instead of globals
FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
+ fragPtr.i= fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
+ tablePtr.i= fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
+
// search for tuple version if not original
- if (pagePtr.p->pageWord[pageOffset + 1] != tupVersion) {
+
+ 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)
+ {
ljam();
OperationrecPtr opPtr;
- opPtr.i = pagePtr.p->pageWord[pageOffset];
- Uint32 loopGuard = 0;
- while (true) {
- ptrCheckGuard(opPtr, cnoOfOprec, operationrec);
- if (opPtr.p->realPageIdC != RNIL) {
- // update page and offset
- pagePtr.i = opPtr.p->realPageIdC;
- pageOffset = opPtr.p->pageOffsetC;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- if (pagePtr.p->pageWord[pageOffset + 1] == tupVersion) {
- ljam();
- break;
+ 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) {
+ ljam();
+ 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;
}
ljam();
- opPtr.i = opPtr.p->nextActiveOp;
+ 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;
+ TablerecPtr tabptr_old= tabptr;
+ FragrecordPtr fragptr_old= fragptr;
+ OperationrecPtr operPtr_old= operPtr;
// new globals
- tabptr = tablePtr;
- fragptr = fragPtr;
- operPtr.i = RNIL;
- operPtr.p = NULL;
+ tabptr= tablePtr;
+ fragptr= fragPtr;
+ operPtr.i= RNIL;
+ operPtr.p= NULL;
+ prepare_read(&req_struct, tablePtr.p, false);
+
// do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds, numAttrs, dataOut, ZNIL, true);
+ int ret = readAttributes(&req_struct,
+ attrIds,
+ numAttrs,
+ dataOut,
+ ZNIL,
+ true);
+
// restore globals
- tabptr = tabptr_old;
- fragptr = fragptr_old;
- operPtr = operPtr_old;
+ 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 pageOffset, Uint32* dataOut, bool xfrmFlag)
+Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag)
{
ljamEntry();
// use own variables instead of globals
FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
+ fragPtr.i= fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
+ tablePtr.i= fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- PagePtr pagePtr;
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- const Uint32 tabDescriptor = tablePtr.p->tabDescriptor;
- const Uint32* attrIds = &tableDescriptor[tablePtr.p->readKeyArray].tabDescr;
- const Uint32 numAttrs = tablePtr.p->noOfKeyAttr;
+
+ Operationrec tmpOp;
+ tmpOp.m_tuple_location.m_page_no= pageId;
+ tmpOp.m_tuple_location.m_page_idx= pageIndex;
+
+ KeyReqStruct req_struct;
+ setup_fixed_part(&req_struct, &tmpOp, tablePtr.p);
+ 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;
+ TablerecPtr tabptr_old= tabptr;
+ FragrecordPtr fragptr_old= fragptr;
+ OperationrecPtr operPtr_old= operPtr;
+
// new globals
- tabptr = tablePtr;
- fragptr = fragPtr;
- operPtr.i = RNIL;
- operPtr.p = NULL;
+ tabptr= tablePtr;
+ fragptr= fragPtr;
+ operPtr.i= RNIL;
+ operPtr.p= NULL;
+
// do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds, numAttrs, dataOut, ZNIL, xfrmFlag);
+ int ret = readAttributes(&req_struct,
+ attrIds,
+ numAttrs,
+ dataOut,
+ ZNIL,
+ xfrmFlag);
// restore globals
- tabptr = tabptr_old;
- fragptr = fragptr_old;
- operPtr = operPtr_old;
+ tabptr= tabptr_old;
+ fragptr= fragptr_old;
+ operPtr= operPtr_old;
// done
if (ret != -1) {
// remove headers
- Uint32 n = 0;
- Uint32 i = 0;
+ Uint32 n= 0;
+ Uint32 i= 0;
while (n < numAttrs) {
const AttributeHeader ah(dataOut[i]);
- Uint32 size = ah.getDataSize();
+ Uint32 size= ah.getDataSize();
ndbrequire(size != 0);
- for (Uint32 j = 0; j < size; j++) {
- dataOut[i + j - n] = dataOut[i + j + 1];
+ for (Uint32 j= 0; j < size; j++) {
+ dataOut[i + j - n]= dataOut[i + j + 1];
}
- n += 1;
- i += 1 + size;
+ n+= 1;
+ i+= 1 + size;
}
ndbrequire((int)i == ret);
ret -= numAttrs;
} else {
- ret = terrorCode ? (-(int)terrorCode) : -1;
+ ret= terrorCode ? (-(int)terrorCode) : -1;
}
return ret;
}
@@ -240,47 +291,52 @@ Dbtup::accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIn
FragrecordPtr fragPtr;
getFragmentrec(fragPtr, fragId, tablePtr.p);
// get real page id and tuple offset
- PagePtr pagePtr;
+
Uint32 pageId = getRealpid(fragPtr.p, fragPageId);
- ndbrequire((pageIndex & 0x1) == 0);
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
// use TUX routine - optimize later
- int ret = tuxReadPk(fragPtr.i, pageId, pageOffset, dataOut, xfrmFlag);
+ int ret = tuxReadPk(fragPtr.i, pageId, pageIndex, dataOut, xfrmFlag);
return ret;
}
bool
-Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId)
+Dbtup::tuxQueryTh(Uint32 fragPtrI,
+ Uint32 tupAddr,
+ Uint32 tupVersion,
+ Uint32 transId1,
+ Uint32 transId2,
+ Uint32 savePointId)
{
ljamEntry();
FragrecordPtr fragPtr;
- fragPtr.i = fragPtrI;
+ fragPtr.i= fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
TablerecPtr tablePtr;
- tablePtr.i = fragPtr.p->fragTableId;
+ tablePtr.i= fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
// get page
- PagePtr pagePtr;
- Uint32 fragPageId = tupAddr >> MAX_TUPLES_BITS;
- Uint32 pageIndex = tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
+ Uint32 fragPageId= tupAddr >> MAX_TUPLES_BITS;
+ Uint32 pageIndex= tupAddr & ((1 << MAX_TUPLES_BITS ) - 1);
// use temp op rec
Operationrec tempOp;
- tempOp.fragPageId = fragPageId;
- tempOp.pageIndex = pageIndex;
- tempOp.transid1 = transId1;
- tempOp.transid2 = transId2;
- tempOp.savePointId = savePointId;
- tempOp.optype = ZREAD;
- tempOp.dirtyOp = 1;
- if (getPage(pagePtr, &tempOp, fragPtr.p, tablePtr.p)) {
+ KeyReqStruct req_struct;
+ tempOp.m_tuple_location.m_page_no= getRealpid(fragPtr.p, fragPageId);
+ tempOp.m_tuple_location.m_page_idx= pageIndex;
+ tempOp.savepointId= savePointId;
+ tempOp.op_struct.op_type= ZREAD;
+ req_struct.frag_page_id= fragPageId;
+ req_struct.trans_id1= transId1;
+ req_struct.trans_id2= transId2;
+ req_struct.dirty_op= 1;
+
+ setup_fixed_part(&req_struct, &tempOp, tablePtr.p);
+ if (setup_read(&req_struct, &tempOp, fragPtr.p, tablePtr.p, false)) {
/*
- * We use the normal getPage which will return the tuple to be used
- * for this transaction and savepoint id. If its tuple version
- * equals the requested then we have a visible tuple otherwise not.
- */
+ * We use the normal getPage which will return the tuple to be used
+ * for this transaction and savepoint id. If its tuple version
+ * equals the requested then we have a visible tuple otherwise not.
+ */
ljam();
- Uint32 read_tupVersion = pagePtr.p->pageWord[tempOp.pageOffset + 1];
- if (read_tupVersion == tupVersion) {
+ if (req_struct.m_tuple_ptr->get_tuple_version() == tupVersion) {
ljam();
return true;
}
@@ -301,9 +357,9 @@ Dbtup::execBUILDINDXREQ(Signal* signal)
{
ljamEntry();
#ifdef TIME_MEASUREMENT
- time_events = 0;
- tot_time_passed = 0;
- number_events = 1;
+ time_events= 0;
+ tot_time_passed= 0;
+ number_events= 1;
#endif
// get new operation
BuildIndexPtr buildPtr;
@@ -311,54 +367,71 @@ Dbtup::execBUILDINDXREQ(Signal* signal)
ljam();
BuildIndexRec buildRec;
memcpy(buildRec.m_request, signal->theData, sizeof(buildRec.m_request));
- buildRec.m_errorCode = BuildIndxRef::Busy;
+ buildRec.m_errorCode= BuildIndxRef::Busy;
buildIndexReply(signal, &buildRec);
return;
}
- memcpy(buildPtr.p->m_request, signal->theData, sizeof(buildPtr.p->m_request));
+ memcpy(buildPtr.p->m_request,
+ signal->theData,
+ sizeof(buildPtr.p->m_request));
// check
- buildPtr.p->m_errorCode = BuildIndxRef::NoError;
+ buildPtr.p->m_errorCode= BuildIndxRef::NoError;
do {
- const BuildIndxReq* buildReq = (const BuildIndxReq*)buildPtr.p->m_request;
+ const BuildIndxReq* buildReq= (const BuildIndxReq*)buildPtr.p->m_request;
if (buildReq->getTableId() >= cnoOfTablerec) {
ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::InvalidPrimaryTable;
+ buildPtr.p->m_errorCode= BuildIndxRef::InvalidPrimaryTable;
break;
}
TablerecPtr tablePtr;
- tablePtr.i = buildReq->getTableId();
+ tablePtr.i= buildReq->getTableId();
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
if (tablePtr.p->tableStatus != DEFINED) {
ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::InvalidPrimaryTable;
+ buildPtr.p->m_errorCode= BuildIndxRef::InvalidPrimaryTable;
break;
}
- if (! DictTabInfo::isOrderedIndex(buildReq->getIndexType())) {
+ // memory page format
+ buildPtr.p->m_build_vs =
+ tablePtr.p->m_attributes[MM].m_no_of_varsize > 0;
+ if (DictTabInfo::isOrderedIndex(buildReq->getIndexType())) {
ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::InvalidIndexType;
- break;
- }
- const ArrayList<TupTriggerData>& triggerList = tablePtr.p->tuxCustomTriggers;
- TriggerPtr triggerPtr;
- triggerList.first(triggerPtr);
- while (triggerPtr.i != RNIL) {
- if (triggerPtr.p->indexId == buildReq->getIndexId()) {
- ljam();
- break;
+ const ArrayList<TupTriggerData>& triggerList =
+ tablePtr.p->tuxCustomTriggers;
+
+ TriggerPtr triggerPtr;
+ triggerList.first(triggerPtr);
+ while (triggerPtr.i != RNIL) {
+ if (triggerPtr.p->indexId == buildReq->getIndexId()) {
+ ljam();
+ break;
+ }
+ triggerList.next(triggerPtr);
}
- triggerList.next(triggerPtr);
- }
- if (triggerPtr.i == RNIL) {
+ if (triggerPtr.i == RNIL) {
+ ljam();
+ // 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) {
ljam();
- // trigger was not created
- buildPtr.p->m_errorCode = BuildIndxRef::InternalError;
+ // REBUILD of acc
+ buildPtr.p->m_indexId = RNIL;
+ buildPtr.p->m_buildRef = DBACC;
+ } else {
+ ljam();
+ buildPtr.p->m_errorCode = BuildIndxRef::InvalidIndexType;
break;
}
- buildPtr.p->m_triggerPtrI = triggerPtr.i;
+
// set to first tuple position
- buildPtr.p->m_fragNo = 0;
- buildPtr.p->m_pageId = 0;
- buildPtr.p->m_tupleNo = 0;
+ const Uint32 firstTupleNo = ! buildPtr.p->m_build_vs ? 0 : 1;
+ buildPtr.p->m_fragNo= 0;
+ buildPtr.p->m_pageId= 0;
+ buildPtr.p->m_tupleNo= firstTupleNo;
// start build
buildIndex(signal, buildPtr.i);
return;
@@ -373,18 +446,16 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
{
// get build record
BuildIndexPtr buildPtr;
- buildPtr.i = buildPtrI;
+ buildPtr.i= buildPtrI;
c_buildIndexList.getPtr(buildPtr);
- const BuildIndxReq* buildReq = (const BuildIndxReq*)buildPtr.p->m_request;
+ const BuildIndxReq* buildReq= (const BuildIndxReq*)buildPtr.p->m_request;
// get table
TablerecPtr tablePtr;
- tablePtr.i = buildReq->getTableId();
+ tablePtr.i= buildReq->getTableId();
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- // get trigger
- TriggerPtr triggerPtr;
- triggerPtr.i = buildPtr.p->m_triggerPtrI;
- c_triggerPool.getPtr(triggerPtr);
- ndbrequire(triggerPtr.p->indexId == buildReq->getIndexId());
+
+ const Uint32 firstTupleNo = ! buildPtr.p->m_build_vs ? 0 : 1;
+
#ifdef TIME_MEASUREMENT
MicroSecondTimer start;
MicroSecondTimer stop;
@@ -393,20 +464,20 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
do {
// get fragment
FragrecordPtr fragPtr;
- if (buildPtr.p->m_fragNo == 2 * MAX_FRAG_PER_NODE) {
+ if (buildPtr.p->m_fragNo == MAX_FRAG_PER_NODE) {
ljam();
// build ready
buildIndexReply(signal, buildPtr.p);
c_buildIndexList.release(buildPtr);
return;
}
- ndbrequire(buildPtr.p->m_fragNo < 2 * MAX_FRAG_PER_NODE);
- fragPtr.i = tablePtr.p->fragrec[buildPtr.p->m_fragNo];
+ ndbrequire(buildPtr.p->m_fragNo < MAX_FRAG_PER_NODE);
+ fragPtr.i= tablePtr.p->fragrec[buildPtr.p->m_fragNo];
if (fragPtr.i == RNIL) {
ljam();
buildPtr.p->m_fragNo++;
- buildPtr.p->m_pageId = 0;
- buildPtr.p->m_tupleNo = 0;
+ buildPtr.p->m_pageId= 0;
+ buildPtr.p->m_tupleNo= firstTupleNo;
break;
}
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
@@ -415,61 +486,88 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
if (buildPtr.p->m_pageId >= fragPtr.p->noOfPages) {
ljam();
buildPtr.p->m_fragNo++;
- buildPtr.p->m_pageId = 0;
- buildPtr.p->m_tupleNo = 0;
+ buildPtr.p->m_pageId= 0;
+ buildPtr.p->m_tupleNo= firstTupleNo;
break;
}
- Uint32 realPageId = getRealpid(fragPtr.p, buildPtr.p->m_pageId);
- pagePtr.i = realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- const Uint32 pageState = pagePtr.p->pageWord[ZPAGE_STATE_POS];
- if (pageState != ZTH_MM_FREE &&
- pageState != ZTH_MM_FREE_COPY &&
- pageState != ZTH_MM_FULL &&
- pageState != ZTH_MM_FULL_COPY) {
+ Uint32 realPageId= getRealpid(fragPtr.p, buildPtr.p->m_pageId);
+ pagePtr.i= realPageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ Uint32 pageState= pagePtr.p->page_state;
+ // skip empty page
+ if (pageState == ZEMPTY_MM) {
ljam();
buildPtr.p->m_pageId++;
- buildPtr.p->m_tupleNo = 0;
+ buildPtr.p->m_tupleNo= firstTupleNo;
break;
}
// get tuple
- const Uint32 tupheadsize = tablePtr.p->tupheadsize;
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + buildPtr.p->m_tupleNo * tupheadsize;
- if (pageOffset + tupheadsize > ZWORDS_ON_PAGE) {
- ljam();
- buildPtr.p->m_pageId++;
- buildPtr.p->m_tupleNo = 0;
- break;
- }
- // skip over free tuple
- bool isFree = false;
- if (pageState == ZTH_MM_FREE ||
- pageState == ZTH_MM_FREE_COPY) {
- ljam();
- if ((pagePtr.p->pageWord[pageOffset] >> 16) == tupheadsize) {
- // verify it really is free XXX far too expensive
- Uint32 nextTuple = pagePtr.p->pageWord[ZFREELIST_HEADER_POS] >> 16;
- ndbrequire(nextTuple != 0);
- while (nextTuple != 0) {
- ljam();
- if (nextTuple == pageOffset) {
- ljam();
- isFree = true;
- break;
- }
- nextTuple = pagePtr.p->pageWord[nextTuple] & 0xffff;
- }
+ Uint32 pageIndex = ~0;
+ const Tuple_header* tuple_ptr = 0;
+ if (! buildPtr.p->m_build_vs) {
+ Uint32 tupheadsize= tablePtr.p->m_offsets[MM].m_fix_header_size;
+ pageIndex = buildPtr.p->m_tupleNo * tupheadsize;
+ if (pageIndex + tupheadsize > Fix_page::DATA_WORDS) {
+ ljam();
+ 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) {
+ ljam();
+ buildPtr.p->m_tupleNo++;
+ break;
+ }
+ } else {
+ pageIndex = buildPtr.p->m_tupleNo;
+ Var_page* page_ptr = (Var_page*)pagePtr.p;
+ if (pageIndex >= page_ptr->high_index) {
+ ljam();
+ buildPtr.p->m_pageId++;
+ buildPtr.p->m_tupleNo= firstTupleNo;
+ break;
+ }
+ Uint32 len= page_ptr->get_entry_len(pageIndex);
+ if (len == 0) {
+ ljam();
+ buildPtr.p->m_tupleNo++;
+ break;
+ }
+ if (len & Var_page::CHAIN) {
+ ljam();
+ buildPtr.p->m_tupleNo++;
+ break;
+ }
+ tuple_ptr = (Tuple_header*)page_ptr->get_ptr(pageIndex);
}
- if (isFree) {
- ljam();
- buildPtr.p->m_tupleNo++;
- break;
- }
- Uint32 tupVersion = pagePtr.p->pageWord[pageOffset + 1];
+ Uint32 tupVersion= tuple_ptr->get_tuple_version();
OperationrecPtr pageOperPtr;
- pageOperPtr.i = pagePtr.p->pageWord[pageOffset];
- if (pageOperPtr.i != RNIL) {
+ 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
@@ -484,31 +582,40 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
preferrable to store in TUX.
*/
ljam();
- ptrCheckGuard(pageOperPtr, cnoOfOprec, operationrec);
- realPageId = pageOperPtr.p->realPageId;
- pageOffset = pageOperPtr.p->pageOffset;
- }//if
-#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 = triggerPtr.p->indexId;
- req->fragId = tablePtr.p->fragid[buildPtr.p->m_fragNo];
- req->pageId = realPageId;
- req->pageOffset = pageOffset;
- req->tupVersion = tupVersion;
- req->opInfo = TuxMaintReq::OpAdd;
- EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ,
- signal, TuxMaintReq::SignalLength);
+
+ /**
+ * 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);
+ }
+
ljamEntry();
if (req->errorCode != 0) {
switch (req->errorCode) {
case TuxMaintReq::NoMemError:
ljam();
- buildPtr.p->m_errorCode = BuildIndxRef::AllocationFailure;
+ buildPtr.p->m_errorCode= BuildIndxRef::AllocationFailure;
break;
default:
ndbrequire(false);
@@ -520,35 +627,37 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
}
#ifdef TIME_MEASUREMENT
NdbTick_getMicroTimer(&stop);
- time_passed = NdbTick_getMicrosPassed(start, 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;
+ 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;
- }//if
+ 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;
+ 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;
+ const BuildIndxReq* const buildReq=
+ (const BuildIndxReq*)buildPtrP->m_request;
// conf is subset of ref
- BuildIndxRef* rep = (BuildIndxRef*)signal->getDataPtr();
+ BuildIndxRef* rep= (BuildIndxRef*)signal->getDataPtr();
rep->setUserRef(buildReq->getUserRef());
rep->setConnectionPtr(buildReq->getConnectionPtr());
rep->setRequestType(buildReq->getRequestType());
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
deleted file mode 100644
index 370ef4c4ba5..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#define DBTUP_C
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRef.hpp>
-
-#define ljam() { jamLine(10000 + __LINE__); }
-#define ljamEntry() { jamEntryLine(10000 + __LINE__); }
-
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-/* -------------------- LOCAL CHECKPOINT MODULE ------------------- */
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::execTUP_PREPLCPREQ(Signal* signal)
-{
- CheckpointInfoPtr ciPtr;
- DiskBufferSegmentInfoPtr dbsiPtr;
- FragrecordPtr regFragPtr;
- LocalLogInfoPtr lliPtr;
- TablerecPtr regTabPtr;
-
- ljamEntry();
- Uint32 userptr = signal->theData[0];
- BlockReference userblockref = signal->theData[1];
- regTabPtr.i = signal->theData[2];
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
- Uint32 fragId = signal->theData[3];
- Uint32 checkpointNumber = signal->theData[4];
- cundoFileVersion = signal->theData[5];
-
- getFragmentrec(regFragPtr, fragId, regTabPtr.p);
- ndbrequire(regTabPtr.i != RNIL);
- seizeCheckpointInfoRecord(ciPtr);
-
- lliPtr.i = (cundoFileVersion << 2) + (regTabPtr.i & 0x3);
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- cnoOfDataPagesToDiskWithoutSynch = 0;
-
- ciPtr.p->lcpDataFileHandle = RNIL;
- ciPtr.p->lcpCheckpointVersion = checkpointNumber;
- ciPtr.p->lcpLocalLogInfoP = lliPtr.i;
- ciPtr.p->lcpFragmentP = regFragPtr.i; /* SET THE FRAGMENT */
- ciPtr.p->lcpFragmentId = fragId; /* SAVE THE FRAGMENT IDENTITY */
- ciPtr.p->lcpTabPtr = regTabPtr.i; /* SET THE TABLE POINTER */
- ciPtr.p->lcpBlockref = userblockref; /* SET THE BLOCK REFERENCE */
- ciPtr.p->lcpUserptr = userptr; /* SET THE USERPOINTER */
-
- /***************************************************************/
- /* OPEN THE UNDO FILE FOR WRITE */
- /* UPON FSOPENCONF */
- /***************************************************************/
- if (lliPtr.p->lliActiveLcp == 0) { /* IS THE UNDO LOG FILE OPEN? */
- PendingFileOpenInfoPtr undoPfoiPtr;
- UndoPagePtr regUndoPagePtr;
-
- ljam();
- lliPtr.p->lliPrevRecordId = 0;
- lliPtr.p->lliLogFilePage = 0;
- lliPtr.p->lliUndoPagesToDiskWithoutSynch = 0;
- lliPtr.p->lliUndoWord = ZUNDO_PAGE_HEADER_SIZE;
-
- seizeUndoBufferSegment(signal, regUndoPagePtr);
- seizeDiskBufferSegmentRecord(dbsiPtr);
- dbsiPtr.p->pdxBuffertype = UNDO_PAGES;
- for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) {
- dbsiPtr.p->pdxDataPage[i] = regUndoPagePtr.i + i;
- }//for
- dbsiPtr.p->pdxFilePage = lliPtr.p->lliLogFilePage;
- lliPtr.p->lliUndoPage = regUndoPagePtr.i;
- lliPtr.p->lliUndoBufferSegmentP = dbsiPtr.i;
- /* F LEVEL NOT USED */
- Uint32 fileType = 1; /* VERSION */
- fileType = (fileType << 8) | 2; /* .LOCLOG */
- fileType = (fileType << 8) | 6; /* D6 */
- fileType = (fileType << 8) | 0xff; /* DON'T USE P DIRECTORY LEVEL */
- Uint32 fileFlag = 0x301; /* CREATE, WRITE ONLY, TRUNCATE */
-
- seizePendingFileOpenInfoRecord(undoPfoiPtr);
- undoPfoiPtr.p->pfoOpenType = LCP_UNDO_FILE_WRITE;
- undoPfoiPtr.p->pfoCheckpointInfoP = ciPtr.i;
-
- signal->theData[0] = cownref;
- signal->theData[1] = undoPfoiPtr.i;
- signal->theData[2] = lliPtr.i;
- signal->theData[3] = 0xFFFFFFFF;
- signal->theData[4] = cundoFileVersion;
- signal->theData[5] = fileType;
- signal->theData[6] = fileFlag;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- }//if
- /***************************************************************/
- /* OPEN THE DATA FILE FOR WRITE */
- /* THE FILE HANDLE WILL BE SET IN THE CHECKPOINT_INFO_RECORD */
- /* UPON FSOPENCONF */
- /***************************************************************/
- /* OPEN THE DATA FILE IN THE FOLLOWING FORM */
- /* D5/DBTUP/T<TABID>/F<FRAGID>/S<CHECKPOINT_NUMBER>.DATA */
-
- PendingFileOpenInfoPtr dataPfoiPtr;
-
- Uint32 fileType = 1; /* VERSION */
- fileType = (fileType << 8) | 0; /* .DATA */
- fileType = (fileType << 8) | 5; /* D5 */
- fileType = (fileType << 8) | 0xff; /* DON'T USE P DIRECTORY LEVEL */
- Uint32 fileFlag = 0x301; /* CREATE, WRITE ONLY, TRUNCATE */
-
- seizePendingFileOpenInfoRecord(dataPfoiPtr); /* SEIZE A NEW FILE OPEN INFO */
- if (lliPtr.p->lliActiveLcp == 0) {
- ljam();
- dataPfoiPtr.p->pfoOpenType = LCP_DATA_FILE_WRITE_WITH_UNDO;
- } else {
- ljam();
- dataPfoiPtr.p->pfoOpenType = LCP_DATA_FILE_WRITE;
- }//if
- dataPfoiPtr.p->pfoCheckpointInfoP = ciPtr.i;
-
- /* LET'S OPEN THE DATA FILE FOR WRITE */
- /* INCREASE NUMBER OF ACTIVE CHECKPOINTS */
- lliPtr.p->lliActiveLcp = 1;
- signal->theData[0] = cownref;
- signal->theData[1] = dataPfoiPtr.i;
- signal->theData[2] = ciPtr.p->lcpTabPtr;
- signal->theData[3] = ciPtr.p->lcpFragmentId;
- signal->theData[4] = ciPtr.p->lcpCheckpointVersion;
- signal->theData[5] = fileType;
- signal->theData[6] = fileFlag;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- return;
-}//Dbtup::execTUP_PREPLCPREQ()
-
-/* ---------------------------------------------------------------- */
-/* ------------------------ START CHECKPOINT --------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::execTUP_LCPREQ(Signal* signal)
-{
- CheckpointInfoPtr ciPtr;
- DiskBufferSegmentInfoPtr dbsiPtr;
- FragrecordPtr regFragPtr;
- LocalLogInfoPtr lliPtr;
-
- ljamEntry();
-// Uint32 userptr = signal->theData[0];
-// BlockReference userblockref = signal->theData[1];
- ciPtr.i = signal->theData[2];
-
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- regFragPtr.i = ciPtr.p->lcpFragmentP;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
-
-/* ---------------------------------------------------------------- */
-/* ASSIGNING A VALUE DIFFERENT FROM RNIL TO CHECKPOINT VERSION*/
-/* TRIGGERS THAT UNDO LOGGING WILL START FOR THIS FRAGMENT. */
-/* WE ASSIGN IT THE POINTER TO THE CHECKPOINT RECORD FOR */
-/* OPTIMISATION OF THE WRITING OF THE UNDO LOG. */
-/* ---------------------------------------------------------------- */
- regFragPtr.p->checkpointVersion = ciPtr.p->lcpLocalLogInfoP; /* MARK START OF UNDO LOGGING */
-
- regFragPtr.p->maxPageWrittenInCheckpoint = getNoOfPages(regFragPtr.p);
- regFragPtr.p->minPageNotWrittenInCheckpoint = 0;
- ndbrequire(getNoOfPages(regFragPtr.p) > 0);
- allocDataBufferSegment(signal, dbsiPtr);
-
- dbsiPtr.p->pdxNumDataPages = 0;
- dbsiPtr.p->pdxFilePage = 1;
- ciPtr.p->lcpDataBufferSegmentP = dbsiPtr.i;
- dbsiPtr.p->pdxCheckpointInfoP = ciPtr.i;
- ciPtr.p->lcpNoOfPages = getNoOfPages(regFragPtr.p);
- ciPtr.p->lcpNoCopyPagesAlloc = regFragPtr.p->noCopyPagesAlloc;
- ciPtr.p->lcpEmptyPrimPage = regFragPtr.p->emptyPrimPage;
- ciPtr.p->lcpThFreeFirst = regFragPtr.p->thFreeFirst;
- ciPtr.p->lcpThFreeCopyFirst = regFragPtr.p->thFreeCopyFirst;
- lliPtr.i = ciPtr.p->lcpLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
-/* ---------------------------------------------------------------- */
-/* --- PERFORM A COPY OF THE TABLE DESCRIPTOR FOR THIS FRAGMENT --- */
-/* ---------------------------------------------------------------- */
- cprAddLogHeader(signal,
- lliPtr.p,
- ZTABLE_DESCRIPTOR,
- ciPtr.p->lcpTabPtr,
- ciPtr.p->lcpFragmentId);
-
-/* ---------------------------------------------------------------- */
-/* CONTINUE WITH SAVING ACTIVE OPERATIONS AFTER A REAL-TIME */
-/* BREAK. */
-/* ---------------------------------------------------------------- */
- ciPtr.p->lcpTmpOperPtr = regFragPtr.p->firstusedOprec;
- lcpSaveCopyListLab(signal, ciPtr);
- return;
-}//Dbtup::execTUP_LCPREQ()
-
-void Dbtup::allocDataBufferSegment(Signal* signal, DiskBufferSegmentInfoPtr& dbsiPtr)
-{
- UndoPagePtr regUndoPagePtr;
-
- seizeDiskBufferSegmentRecord(dbsiPtr);
- dbsiPtr.p->pdxBuffertype = COMMON_AREA_PAGES;
- ndbrequire(cfirstfreeUndoSeg != RNIL);
- if (cnoFreeUndoSeg == ZMIN_PAGE_LIMIT_TUP_COMMITREQ) {
- EXECUTE_DIRECT(DBLQH, GSN_TUP_COM_BLOCK, signal, 1);
- ljamEntry();
- }//if
- cnoFreeUndoSeg--;
- ndbrequire(cnoFreeUndoSeg >= 0);
-
- regUndoPagePtr.i = cfirstfreeUndoSeg;
- ptrCheckGuard(regUndoPagePtr, cnoOfUndoPage, undoPage);
- cfirstfreeUndoSeg = regUndoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS];
- regUndoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS] = RNIL;
- for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) {
- dbsiPtr.p->pdxDataPage[i] = regUndoPagePtr.i + i;
- }//for
-}//Dbtup::allocDataBufferSegment()
-
-/* ---------------------------------------------------------------- */
-/* --- PERFORM A COPY OF THE ACTIVE OPERATIONS FOR THIS FRAGMENT -- */
-/* ---------------------------------------------------------------- */
-void Dbtup::lcpSaveCopyListLab(Signal* signal, CheckpointInfoPtr ciPtr)
-{
- FragrecordPtr regFragPtr;
- LocalLogInfoPtr lliPtr;
- OperationrecPtr regOpPtr;
-
- regFragPtr.i = ciPtr.p->lcpFragmentP;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- lliPtr.i = ciPtr.p->lcpLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- regOpPtr.i = ciPtr.p->lcpTmpOperPtr;
-
-/* -------------------------------------------------------------------------------- */
-/* TRAVERSE THE ENTIRE BLOCK OF OPERATIONS. CHECK IF THERE ARE EXISTING COPYS OF */
-/* TUPLES IN THE CHECKPOINTED FRAGMENT. SAVE THOSE IN A LIST IN THE FOLLOWING FORM: */
-/* */
-/* SOURCE PAGE */
-/* SOURCE INDEX */
-/* COPY PAGE */
-/* COPY INDEX */
-/* -------------------------------------------------------------------------------- */
- Uint32 loopCount = 0;
- while ((regOpPtr.i != RNIL) && (loopCount < 50)) {
- ljam();
- ptrCheckGuard(regOpPtr, cnoOfOprec, operationrec);
- if (regOpPtr.p->realPageId != RNIL) {
-/* ---------------------------------------------------------------- */
-// We ensure that we have actually allocated the tuple header and
-// also found it. Otherwise we will fill the undo log with garbage.
-/* ---------------------------------------------------------------- */
- if (regOpPtr.p->optype == ZUPDATE ||
- (regOpPtr.p->optype == ZINSERT && regOpPtr.p->deleteInsertFlag)) {
- ljam();
- if (regOpPtr.p->realPageIdC != RNIL) {
-/* ---------------------------------------------------------------- */
-// We ensure that we have actually allocated the tuple header copy.
-// Otherwise we will fill the undo log with garbage.
-/* ---------------------------------------------------------------- */
- cprAddLogHeader(signal,
- lliPtr.p,
- ZLCPR_ABORT_UPDATE,
- ciPtr.p->lcpTabPtr,
- ciPtr.p->lcpFragmentId);
- cprAddAbortUpdate(signal, lliPtr.p, regOpPtr.p);
- }//if
- } else if (regOpPtr.p->optype == ZINSERT) {
- ljam();
- cprAddUndoLogRecord(signal,
- ZLCPR_ABORT_INSERT,
- regOpPtr.p->fragPageId,
- regOpPtr.p->pageIndex,
- regOpPtr.p->tableRef,
- regOpPtr.p->fragId,
- regFragPtr.p->checkpointVersion);
- } else {
- ndbrequire(regOpPtr.p->optype == ZDELETE);
- ljam();
- cprAddUndoLogRecord(signal,
- ZINDICATE_NO_OP_ACTIVE,
- regOpPtr.p->fragPageId,
- regOpPtr.p->pageIndex,
- regOpPtr.p->tableRef,
- regOpPtr.p->fragId,
- regFragPtr.p->checkpointVersion);
- }//if
- }//if
- loopCount++;;
- regOpPtr.i = regOpPtr.p->nextOprecInList;
- }//while
- if (regOpPtr.i == RNIL) {
- ljam();
-
- signal->theData[0] = ciPtr.p->lcpUserptr;
- sendSignal(ciPtr.p->lcpBlockref, GSN_TUP_LCPSTARTED, signal, 1, JBA);
-
- signal->theData[0] = ZCONT_SAVE_DP;
- signal->theData[1] = ciPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- } else {
- ljam();
- ciPtr.p->lcpTmpOperPtr = regOpPtr.i;
- signal->theData[0] = ZCONT_START_SAVE_CL;
- signal->theData[1] = ciPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
-}//Dbtup::lcpSaveCopyListLab()
-
-/* ---------------------------------------------------------------- */
-/* ------- PERFORM A COPY OF ONE DATAPAGE DURING CHECKPOINT ------- */
-/* ---------------------------------------------------------------- */
-/* THE RANGE OF DATA PAGES IS INCLUDED IN THE CHECKPOINT_INFO_PTR */
-/* LAST_PAGE_TO_BUFFER ELEMENT IS INCREASED UNTIL ALL PAGES ARE */
-/* COPIED TO THE DISK BUFFER. WHEN A DISK BUFFER SEGMENT IS FULL */
-/* IT WILL BE WRITTEN TO DISK (TYPICALLY EACH 8:TH PAGE) */
-/* ---------------------------------------------------------------- */
-void Dbtup::lcpSaveDataPageLab(Signal* signal, Uint32 ciIndex)
-{
- CheckpointInfoPtr ciPtr;
- DiskBufferSegmentInfoPtr dbsiPtr;
- FragrecordPtr regFragPtr;
- LocalLogInfoPtr lliPtr;
- UndoPagePtr undoCopyPagePtr;
- PagePtr pagePtr;
-
- ciPtr.i = ciIndex;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
- if (ERROR_INSERTED(4000)){
- if (ciPtr.p->lcpTabPtr == c_errorInsert4000TableId) {
- // Delay writing of data pages during LCP
- ndbout << "Delay writing of data pages during LCP" << endl;
- signal->theData[0] = ZCONT_SAVE_DP;
- signal->theData[1] = ciIndex;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 1000, 2);
- return;
- }//if
- }//if
- if (clblPageCounter == 0) {
- ljam();
- signal->theData[0] = ZCONT_SAVE_DP;
- signal->theData[1] = ciPtr.i;
- sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 2);
- return;
- } else {
- ljam();
- clblPageCounter--;
- }//if
-
- regFragPtr.i = ciPtr.p->lcpFragmentP;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- dbsiPtr.i = ciPtr.p->lcpDataBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
-
- pagePtr.i = getRealpid(regFragPtr.p, regFragPtr.p->minPageNotWrittenInCheckpoint);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- ndbrequire(dbsiPtr.p->pdxNumDataPages < 16);
- undoCopyPagePtr.i = dbsiPtr.p->pdxDataPage[dbsiPtr.p->pdxNumDataPages];
- ptrCheckGuard(undoCopyPagePtr, cnoOfUndoPage, undoPage);
- MEMCOPY_NO_WORDS(&undoCopyPagePtr.p->undoPageWord[0],
- &pagePtr.p->pageWord[0],
- ZWORDS_ON_PAGE);
- regFragPtr.p->minPageNotWrittenInCheckpoint++;
- dbsiPtr.p->pdxNumDataPages++;
- if (regFragPtr.p->minPageNotWrittenInCheckpoint == regFragPtr.p->maxPageWrittenInCheckpoint) {
- /* ---------------------------------------------------------- */
- /* ALL PAGES ARE COPIED, TIME TO FINISH THE CHECKPOINT */
- /* SAVE THE END POSITIONS OF THE LOG RECORDS SINCE ALL DATA */
- /* PAGES ARE NOW SAFE ON DISK AND NO MORE LOGGING WILL APPEAR */
- /* ---------------------------------------------------------- */
- ljam();
- lliPtr.i = ciPtr.p->lcpLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- regFragPtr.p->checkpointVersion = RNIL; /* UNDO LOGGING IS SHUT OFF */
- lcpWriteListDataPageSegment(signal, dbsiPtr, ciPtr, false);
- dbsiPtr.p->pdxOperation = CHECKPOINT_DATA_WRITE_LAST;
- } else if (dbsiPtr.p->pdxNumDataPages == ZDB_SEGMENT_SIZE) {
- ljam();
- lcpWriteListDataPageSegment(signal, dbsiPtr, ciPtr, false);
- dbsiPtr.p->pdxOperation = CHECKPOINT_DATA_WRITE;
- } else {
- ljam();
- signal->theData[0] = ZCONT_SAVE_DP;
- signal->theData[1] = ciPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
-}//Dbtup::lcpSaveDataPageLab()
-
-void Dbtup::lcpWriteListDataPageSegment(Signal* signal,
- DiskBufferSegmentInfoPtr dbsiPtr,
- CheckpointInfoPtr ciPtr,
- bool flushFlag)
-{
- Uint32 flags = 1;
- cnoOfDataPagesToDiskWithoutSynch += dbsiPtr.p->pdxNumDataPages;
- if ((cnoOfDataPagesToDiskWithoutSynch > MAX_PAGES_WITHOUT_SYNCH) ||
- (flushFlag)) {
- ljam();
-/* ---------------------------------------------------------------- */
-// To avoid synching too big chunks at a time we synch after writing
-// a certain number of data pages. (e.g. 2 MBytes).
-/* ---------------------------------------------------------------- */
- cnoOfDataPagesToDiskWithoutSynch = 0;
- flags |= 0x10; //Set synch flag unconditionally
- }//if
- signal->theData[0] = ciPtr.p->lcpDataFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = dbsiPtr.i;
- signal->theData[3] = flags;
- signal->theData[4] = ZBASE_ADDR_UNDO_WORD;
- signal->theData[5] = dbsiPtr.p->pdxNumDataPages;
- signal->theData[6] = dbsiPtr.p->pdxDataPage[0];
- signal->theData[7] = dbsiPtr.p->pdxFilePage;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
-
- dbsiPtr.p->pdxFilePage += dbsiPtr.p->pdxNumDataPages;
- dbsiPtr.p->pdxNumDataPages = 0;
-}//Dbtup::lcpWriteListDataPageSegment()
-
-void Dbtup::lcpFlushLogLab(Signal* signal, CheckpointInfoPtr ciPtr)
-{
- DiskBufferSegmentInfoPtr oldDbsiPtr;
- LocalLogInfoPtr lliPtr;
- UndoPagePtr oldUndoPagePtr;
- UndoPagePtr newUndoPagePtr;
-
- lliPtr.i = ciPtr.p->lcpLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- oldDbsiPtr.i = lliPtr.p->lliUndoBufferSegmentP;
- ptrCheckGuard(oldDbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- oldDbsiPtr.p->pdxNumDataPages++;
- if (clblPageCounter > 0) {
- ljam();
- clblPageCounter--;
- }//if
- oldUndoPagePtr.i = lliPtr.p->lliUndoPage;
- ptrCheckGuard(oldUndoPagePtr, cnoOfUndoPage, undoPage);
- lcpWriteUndoSegment(signal, lliPtr.p, true);
- oldDbsiPtr.p->pdxOperation = CHECKPOINT_UNDO_WRITE_FLUSH;
- oldDbsiPtr.p->pdxCheckpointInfoP = ciPtr.i;
-
-/* ---------------------------------------------------------------- */
-/* SINCE LAST PAGE SENT TO DISK WAS NOT FULL YET WE COPY IT */
-/* TO THE NEW LAST PAGE. */
-/* ---------------------------------------------------------------- */
- newUndoPagePtr.i = lliPtr.p->lliUndoPage;
- ptrCheckGuard(newUndoPagePtr, cnoOfUndoPage, undoPage);
- ndbrequire(lliPtr.p->lliUndoWord < ZWORDS_ON_PAGE);
- MEMCOPY_NO_WORDS(&newUndoPagePtr.p->undoPageWord[0],
- &oldUndoPagePtr.p->undoPageWord[0],
- lliPtr.p->lliUndoWord);
-}//Dbtup::lcpFlushLogLab()
-
-void Dbtup::lcpFlushRestartInfoLab(Signal* signal, Uint32 ciIndex)
-{
- CheckpointInfoPtr ciPtr;
- DiskBufferSegmentInfoPtr dbsiPtr;
- LocalLogInfoPtr lliPtr;
- UndoPagePtr undoCopyPagePtr;
-
- ciPtr.i = ciIndex;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
-
- lliPtr.i = ciPtr.p->lcpLocalLogInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- dbsiPtr.i = ciPtr.p->lcpDataBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- undoCopyPagePtr.i = dbsiPtr.p->pdxDataPage[0]; /* UNDO INFO STORED AT PAGE 0 */
- ptrCheckGuard(undoCopyPagePtr, cnoOfUndoPage, undoPage);
- ndbrequire(ciPtr.p->lcpNoOfPages > 0);
- undoCopyPagePtr.p->undoPageWord[ZSRI_NO_OF_FRAG_PAGES_POS] = ciPtr.p->lcpNoOfPages;
- undoCopyPagePtr.p->undoPageWord[ZSRI_NO_COPY_PAGES_ALLOC] = ciPtr.p->lcpNoCopyPagesAlloc;
- undoCopyPagePtr.p->undoPageWord[ZSRI_EMPTY_PRIM_PAGE] = ciPtr.p->lcpEmptyPrimPage;
- undoCopyPagePtr.p->undoPageWord[ZSRI_TH_FREE_FIRST] = ciPtr.p->lcpThFreeFirst;
- undoCopyPagePtr.p->undoPageWord[ZSRI_TH_FREE_COPY_FIRST] = ciPtr.p->lcpThFreeCopyFirst;
- undoCopyPagePtr.p->undoPageWord[ZSRI_UNDO_LOG_END_REC_ID] = lliPtr.p->lliPrevRecordId;
- undoCopyPagePtr.p->undoPageWord[ZSRI_UNDO_FILE_VER] = cundoFileVersion;
- if (lliPtr.p->lliUndoWord == ZUNDO_PAGE_HEADER_SIZE) {
- ljam();
- undoCopyPagePtr.p->undoPageWord[ZSRI_UNDO_LOG_END_PAGE_ID] = lliPtr.p->lliLogFilePage - 1;
- } else {
- ljam();
- undoCopyPagePtr.p->undoPageWord[ZSRI_UNDO_LOG_END_PAGE_ID] = lliPtr.p->lliLogFilePage;
- }//if
- dbsiPtr.p->pdxNumDataPages = 1;
- dbsiPtr.p->pdxFilePage = 0;
- if (clblPageCounter > 0) {
- ljam();
- clblPageCounter--;
- }//if
- lcpWriteListDataPageSegment(signal, dbsiPtr, ciPtr, true);
- dbsiPtr.p->pdxOperation = CHECKPOINT_DATA_WRITE_FLUSH;
- return;
-}//Dbtup::lcpFlushRestartInfoLab()
-
-void Dbtup::lcpCompletedLab(Signal* signal, Uint32 ciIndex)
-{
- CheckpointInfoPtr ciPtr;
- PendingFileOpenInfoPtr pfoiPtr;
-/* ---------------------------------------------------------------------- */
-/* INSERT CODE TO CLOSE DATA FILE HERE. DO THIS BEFORE SEND CONF */
-/* ---------------------------------------------------------------------- */
- ciPtr.i = ciIndex;
- ptrCheckGuard(ciPtr, cnoOfLcpRec, checkpointInfo);
-
- seizePendingFileOpenInfoRecord(pfoiPtr);
- pfoiPtr.p->pfoOpenType = LCP_DATA_FILE_CLOSE;
- pfoiPtr.p->pfoCheckpointInfoP = ciPtr.i;
-
- signal->theData[0] = ciPtr.p->lcpDataFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = pfoiPtr.i;
- signal->theData[3] = 0;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- return;
-}//Dbtup::lcpCompletedLab()
-
-void Dbtup::lcpClosedDataFileLab(Signal* signal, CheckpointInfoPtr ciPtr)
-{
- signal->theData[0] = ciPtr.p->lcpUserptr;
- sendSignal(ciPtr.p->lcpBlockref, GSN_TUP_LCPCONF, signal, 1, JBB);
- releaseCheckpointInfoRecord(ciPtr);
- return;
-}//Dbtup::lcpClosedDataFileLab()
-
-/* ---------------------------------------------------------------------- */
-/* LCP END IS THE LAST STEP IN THE LCP PROCESS IT WILL CLOSE THE LOGFILES */
-/* AND RELEASE THE ALLOCATED CHECKPOINT_INFO_RECORDS */
-/* ---------------------------------------------------------------------- */
-void Dbtup::execEND_LCPREQ(Signal* signal)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
- LocalLogInfoPtr lliPtr;
- PendingFileOpenInfoPtr pfoiPtr;
-
- ljamEntry();
- clqhUserpointer = signal->theData[0];
- clqhBlockref = signal->theData[1];
- for (lliPtr.i = 0; lliPtr.i < 16; lliPtr.i++) {
- ljam();
- ptrAss(lliPtr, localLogInfo);
- if (lliPtr.p->lliActiveLcp > 0) {
- ljam();
- dbsiPtr.i = lliPtr.p->lliUndoBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- freeDiskBufferSegmentRecord(signal, dbsiPtr);
-
- seizePendingFileOpenInfoRecord(pfoiPtr); /* SEIZE A NEW FILE OPEN INFO */
- pfoiPtr.p->pfoOpenType = LCP_UNDO_FILE_CLOSE;
- pfoiPtr.p->pfoCheckpointInfoP = lliPtr.i;
-
- signal->theData[0] = lliPtr.p->lliUndoFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = pfoiPtr.i;
- signal->theData[3] = 0;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- lliPtr.p->lliActiveLcp = 0;
- }//if
- }//for
- return;
-}//Dbtup::execEND_LCPREQ()
-
-void Dbtup::lcpEndconfLab(Signal* signal)
-{
- LocalLogInfoPtr lliPtr;
- for (lliPtr.i = 0; lliPtr.i < 16; lliPtr.i++) {
- ljam();
- ptrAss(lliPtr, localLogInfo);
- if (lliPtr.p->lliUndoFileHandle != RNIL) {
- ljam();
-/* ---------------------------------------------------------------------- */
-/* WAIT UNTIL ALL LOG FILES HAVE BEEN CLOSED. */
-/* ---------------------------------------------------------------------- */
- return;
- }//if
- }//for
- signal->theData[0] = clqhUserpointer;
- sendSignal(clqhBlockref, GSN_END_LCPCONF, signal, 1, JBB);
- return;
-}//Dbtup::lcpEndconfLab()
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
index 91bdd58e406..037ac101af7 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
@@ -25,6 +25,7 @@
#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>
@@ -32,11 +33,6 @@
#define ljam() { jamLine(20000 + __LINE__); }
#define ljamEntry() { jamEntryLine(20000 + __LINE__); }
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
-/* --------------- ADD/DROP FRAGMENT TABLE MODULE ----------------- */
-/* ---------------------------------------------------------------- */
-/* ---------------------------------------------------------------- */
void Dbtup::execTUPFRAGREQ(Signal* signal)
{
ljamEntry();
@@ -51,23 +47,23 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
FragrecordPtr regFragPtr;
TablerecPtr regTabPtr;
- Uint32 userptr = signal->theData[0];
- Uint32 userblockref = signal->theData[1];
- Uint32 reqinfo = signal->theData[2];
- regTabPtr.i = signal->theData[3];
- Uint32 noOfAttributes = signal->theData[4];
- Uint32 fragId = signal->theData[5];
- Uint32 noOfNullAttr = signal->theData[7];
- /* Uint32 schemaVersion = signal->theData[8];*/
- Uint32 noOfKeyAttr = signal->theData[9];
-
- Uint32 noOfNewAttr = (signal->theData[10] & 0xFFFF);
+ Uint32 userptr= signal->theData[0];
+ Uint32 userblockref= signal->theData[1];
+ Uint32 reqinfo= signal->theData[2];
+ regTabPtr.i= signal->theData[3];
+ Uint32 noOfAttributes= signal->theData[4];
+ Uint32 fragId= signal->theData[5];
+ Uint32 pages= signal->theData[6];
+ Uint32 noOfNullAttr= signal->theData[7];
+ /* Uint32 schemaVersion= signal->theData[8];*/
+ Uint32 noOfKeyAttr= signal->theData[9];
+
+ //Uint32 noOfNewAttr= (signal->theData[10] & 0xFFFF);
/* DICT sends number of character sets in upper half */
- Uint32 noOfCharsets = (signal->theData[10] >> 16);
+ Uint32 noOfCharsets= (signal->theData[10] >> 16);
+ Uint32 tablespace= signal->theData[14];
- Uint32 checksumIndicator = signal->theData[11];
- Uint32 noOfAttributeGroups = signal->theData[12];
- Uint32 globalCheckpointIdIndicator = signal->theData[13];
+ Uint32 checksumIndicator= signal->theData[11];
#ifndef VM_TRACE
// config mismatch - do not crash if release compiled
@@ -83,11 +79,11 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
if (cfirstfreeFragopr == RNIL) {
ljam();
- signal->theData[0] = userptr;
- signal->theData[1] = ZNOFREE_FRAGOP_ERROR;
+ signal->theData[0]= userptr;
+ signal->theData[1]= ZNOFREE_FRAGOP_ERROR;
sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
return;
- }//if
+ }
seizeFragoperrec(fragOperPtr);
fragOperPtr.p->nextFragoprec = RNIL;
@@ -96,60 +92,67 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
fragOperPtr.p->fragidFrag = fragId;
fragOperPtr.p->tableidFrag = regTabPtr.i;
fragOperPtr.p->attributeCount = noOfAttributes;
- fragOperPtr.p->noOfNullBits = noOfNullAttr;
- fragOperPtr.p->noOfNewAttrCount = noOfNewAttr;
+
+ 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->currNullBit = 0;
ndbrequire(reqinfo == ZADDFRAG);
getFragmentrec(regFragPtr, fragId, regTabPtr.p);
if (regFragPtr.i != RNIL) {
ljam();
- terrorCode = ZEXIST_FRAG_ERROR; /* THE FRAGMENT ALREADY EXIST */
+ terrorCode= ZEXIST_FRAG_ERROR;
fragrefuse1Lab(signal, fragOperPtr);
return;
- }//if
+ }
if (cfirstfreefrag != RNIL) {
ljam();
seizeFragrecord(regFragPtr);
} else {
ljam();
- terrorCode = ZFULL_FRAGRECORD_ERROR;
+ terrorCode= ZFULL_FRAGRECORD_ERROR;
fragrefuse1Lab(signal, fragOperPtr);
return;
- }//if
+ }
initFragRange(regFragPtr.p);
if (!addfragtotab(regTabPtr.p, fragId, regFragPtr.i)) {
ljam();
- terrorCode = ZNO_FREE_TAB_ENTRY_ERROR;
+ terrorCode= ZNO_FREE_TAB_ENTRY_ERROR;
fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
return;
- }//if
+ }
if (cfirstfreerange == RNIL) {
ljam();
- terrorCode = ZNO_FREE_PAGE_RANGE_ERROR;
+ terrorCode= ZNO_FREE_PAGE_RANGE_ERROR;
fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
return;
- }//if
-
- regFragPtr.p->emptyPrimPage = RNIL;
- regFragPtr.p->thFreeFirst = RNIL;
- regFragPtr.p->thFreeCopyFirst = RNIL;
- regFragPtr.p->noCopyPagesAlloc = 0;
- regFragPtr.p->fragTableId = regTabPtr.i;
- regFragPtr.p->fragmentId = fragId;
- regFragPtr.p->checkpointVersion = RNIL;
-
- Uint32 noAllocatedPages = 2;
- noAllocatedPages = allocFragPages(regFragPtr.p, noAllocatedPages);
+ }
+ regFragPtr.p->emptyPrimPage= RNIL;
+ regFragPtr.p->thFreeFirst= RNIL;
+ regFragPtr.p->free_var_page_array[0]= RNIL;
+ regFragPtr.p->free_var_page_array[1]= RNIL;
+ regFragPtr.p->free_var_page_array[2]= RNIL;
+ regFragPtr.p->free_var_page_array[3]= RNIL;
+ regFragPtr.p->fragTableId= regTabPtr.i;
+ regFragPtr.p->fragmentId= fragId;
+ regFragPtr.p->m_tablespace_id= tablespace;
+ regFragPtr.p->m_undo_complete= false;
+ regFragPtr.p->m_lcp_scan_op= RNIL;
+
+ Uint32 noAllocatedPages= allocFragPages(regFragPtr.p, pages);
+
if (noAllocatedPages == 0) {
ljam();
- terrorCode = ZNO_PAGES_ALLOCATED_ERROR;
+ terrorCode= ZNO_PAGES_ALLOCATED_ERROR;
fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
return;
- }//if
+ }
if (ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId ||
ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) {
@@ -162,112 +165,109 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
if (regTabPtr.p->tableStatus == NOT_DEFINED) {
ljam();
-//-------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// 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.
+// 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
-// Global Checkpoint id
-// This word is optional. When used it is stored as a 32-bit unsigned
-// attribute with attribute identity 0. Thus the kernel assumes that
-// this is the first word after the header.
-//-------------------------------------------------------------------------------------
- fragOperPtr.p->definingFragment = true;
- regTabPtr.p->tableStatus = DEFINING;
- regTabPtr.p->checksumIndicator = (checksumIndicator != 0 ? true : false);
- regTabPtr.p->GCPIndicator = (globalCheckpointIdIndicator != 0 ? true : false);
-
- regTabPtr.p->tupChecksumIndex = 2;
- regTabPtr.p->tupNullIndex = 2 + (checksumIndicator != 0 ? 1 : 0);
- regTabPtr.p->tupNullWords = (noOfNullAttr + 31) >> 5;
- regTabPtr.p->tupGCPIndex = regTabPtr.p->tupNullIndex + regTabPtr.p->tupNullWords;
- regTabPtr.p->tupheadsize = regTabPtr.p->tupGCPIndex;
-
- regTabPtr.p->noOfKeyAttr = noOfKeyAttr;
- regTabPtr.p->noOfCharsets = noOfCharsets;
- regTabPtr.p->noOfAttr = noOfAttributes;
- regTabPtr.p->noOfNewAttr = noOfNewAttr;
- regTabPtr.p->noOfNullAttr = noOfNullAttr;
- regTabPtr.p->noOfAttributeGroups = noOfAttributeGroups;
-
+// 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->checksumIndicator= (checksumIndicator != 0 ? true : false);
+
+ 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_varpart_offset= 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_varpart_offset= 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();
-
+
Uint32 offset[10];
- Uint32 tableDescriptorRef = allocTabDescr(regTabPtr.p, offset);
+ Uint32 tableDescriptorRef= allocTabDescr(regTabPtr.p, offset);
if (tableDescriptorRef == RNIL) {
ljam();
fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
return;
- }//if
+ }
setUpDescriptorReferences(tableDescriptorRef, regTabPtr.p, offset);
} else {
ljam();
- fragOperPtr.p->definingFragment = false;
- }//if
- signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- signal->theData[1] = fragOperPtr.i;
- signal->theData[2] = regFragPtr.i;
- signal->theData[3] = fragId;
+ 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;
-}//Dbtup::execTUPFRAGREQ()
+}
-/* -------------------------------------------------------------------- */
-/* ------------------------- ADDFRAGTOTAB ----------------------------- */
-/* PUTS A FRAGMENT POINTER AND FID IN THE TABLE ARRAY OF THE TID RECORD */
-/* -------------------------------------------------------------------- */
-bool Dbtup::addfragtotab(Tablerec* const regTabPtr, Uint32 fragId, Uint32 fragIndex)
+bool Dbtup::addfragtotab(Tablerec* const regTabPtr,
+ Uint32 fragId,
+ Uint32 fragIndex)
{
- for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
ljam();
if (regTabPtr->fragid[i] == RNIL) {
ljam();
- regTabPtr->fragid[i] = fragId;
- regTabPtr->fragrec[i] = fragIndex;
+ regTabPtr->fragid[i]= fragId;
+ regTabPtr->fragrec[i]= fragIndex;
return true;
- }//if
- }//for
+ }
+ }
return false;
-}//Dbtup::addfragtotab()
+}
-void Dbtup::getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr)
+void Dbtup::getFragmentrec(FragrecordPtr& regFragPtr,
+ Uint32 fragId,
+ Tablerec* const regTabPtr)
{
- for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
ljam();
if (regTabPtr->fragid[i] == fragId) {
ljam();
-/* ---------------------------------------------------------------- */
-/* A FRAGMENT RECORD HAVE BEEN FOUND FOR THIS OPERATION. */
-/* ---------------------------------------------------------------- */
- regFragPtr.i = regTabPtr->fragrec[i];
+ regFragPtr.i= regTabPtr->fragrec[i];
ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
return;
- }//if
- }//for
- regFragPtr.i = RNIL;
+ }
+ }
+ regFragPtr.i= RNIL;
ptrNull(regFragPtr);
-}//Dbtup::getFragmentrec()
+}
void Dbtup::seizeFragrecord(FragrecordPtr& regFragPtr)
{
- regFragPtr.i = cfirstfreefrag;
+ regFragPtr.i= cfirstfreefrag;
ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- cfirstfreefrag = regFragPtr.p->nextfreefrag;
- regFragPtr.p->nextfreefrag = RNIL;
-}//Dbtup::seizeFragrecord()
+ cfirstfreefrag= regFragPtr.p->nextfreefrag;
+ regFragPtr.p->nextfreefrag= RNIL;
+}
-/* ---------------------------------------------------------------- */
-/* SEIZE A FRAGMENT OPERATION RECORD */
-/* ---------------------------------------------------------------- */
void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr)
{
- fragOperPtr.i = cfirstfreeFragopr;
+ fragOperPtr.i= cfirstfreeFragopr;
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
fragOperPtr.p->nextFragoprec = RNIL;
@@ -284,17 +284,17 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
TablerecPtr regTabPtr;
ljamEntry();
- fragOperPtr.i = signal->theData[0];
+ fragOperPtr.i= signal->theData[0];
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
Uint32 attrId = signal->theData[2];
Uint32 attrDescriptor = signal->theData[3];
// DICT sends charset number in upper half
Uint32 csNumber = (signal->theData[4] >> 16);
- regTabPtr.i = fragOperPtr.p->tableidFrag;
+ regTabPtr.i= fragOperPtr.p->tableidFrag;
ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
- Uint32 fragId = fragOperPtr.p->fragidFrag;
+ Uint32 fragId= fragOperPtr.p->fragidFrag;
getFragmentrec(regFragPtr, fragId, regTabPtr.p);
ndbrequire(regFragPtr.i != RNIL);
@@ -303,103 +303,114 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
fragOperPtr.p->attributeCount--;
const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
- if ((regTabPtr.p->tableStatus == DEFINING) &&
- (fragOperPtr.p->definingFragment)) {
+ 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)
+ {
+ /**
+ * 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;
+ }
+ 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)) {
ljam();
- Uint32 firstTabDesIndex = regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
- setTabDescrWord(firstTabDesIndex, attrDescriptor);
- Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
- Uint32 nullBitPos = fragOperPtr.p->currNullBit;
- Uint32 bitCount = 0;
-
- if (AttributeDescriptor::getNullable(attrDescriptor)) {
- if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
- ljam(); /* NULL ATTR */
- fragOperPtr.p->currNullBit++;
- }//if
- } else {
+ 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))
+ {
ljam();
+ fragOperPtr.p->m_null_bits[ind]++;
+ }
+ else
+ {
regTabPtr.p->notNullAttributeMask.set(attrId);
- }//if
+ }
- Uint32 attrDes2 = 0;
- if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
+ switch (AttributeDescriptor::getArrayType(attrDescriptor)) {
+ case NDB_ARRAYTYPE_FIXED:
+ {
ljam();
- Uint32 attributePos = regTabPtr.p->tupheadsize;
- switch (AttributeDescriptor::getArrayType(attrDescriptor)) {
- case 1:
- case 2:
+ regTabPtr.p->m_attributes[ind].m_no_of_fixsize++;
+ if(attrLen != 0)
{
- ljam();
- if(attrLen != 0)
- {
- ljam();
- Uint32 bitsUsed =
- AttributeDescriptor::getArraySize(attrDescriptor) * (1 << attrLen);
- regTabPtr.p->tupheadsize += ((bitsUsed + 31) >> 5);
- break;
- }
- else
- {
- ljam();
- bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
- fragOperPtr.p->currNullBit += bitCount;
- break;
- }
+ ljam();
+ pos= fragOperPtr.p->m_fix_attributes_size[ind];
+ fragOperPtr.p->m_fix_attributes_size[ind] += words;
}
- default:
- ndbrequire(false);
- break;
- }//switch
- if(nullBitPos + bitCount + 1 >= MAX_NULL_BITS)
+ else
{
- terrorCode = TupAddAttrRef::TooManyBitsUsed;
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- return;
- }
- AttributeOffset::setOffset(attrDes2, attributePos);
- AttributeOffset::setNullFlagPos(attrDes2, nullBitPos);
- } else {
- ndbrequire(false);
- }//if
- if (csNumber != 0) {
- CHARSET_INFO* cs = all_charsets[csNumber];
- ndbrequire(cs != NULL);
- Uint32 i = 0;
- while (i < fragOperPtr.p->charsetIndex) {
- ljam();
- if (regTabPtr.p->charsetArray[i] == cs)
- break;
- i++;
+ ljam();
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ fragOperPtr.p->m_null_bits[ind] += bitCount;
}
- if (i == fragOperPtr.p->charsetIndex) {
- ljam();
- fragOperPtr.p->charsetIndex++;
- }
- ndbrequire(i < regTabPtr.p->noOfCharsets);
- regTabPtr.p->charsetArray[i] = cs;
- AttributeOffset::setCharsetPos(attrDes2, i);
+ break;
}
- setTabDescrWord(firstTabDesIndex + 1, attrDes2);
-
- if (regTabPtr.p->tupheadsize > MAX_TUPLE_SIZE_IN_WORDS) {
- ljam();
- terrorCode = ZTOO_LARGE_TUPLE_ERROR;
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- return;
- }//if
- if (lastAttr &&
- (fragOperPtr.p->currNullBit != fragOperPtr.p->noOfNullBits))
+ default:
{
ljam();
- terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT;
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- return;
- }//if
- }//if
- if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId && attrId == 0 ||
+ 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) {
+ ljam();
+ if (regTabPtr.p->charsetArray[i] == cs)
+ break;
+ i++;
+ }
+ if (i == fragOperPtr.p->charsetIndex) {
+ ljam();
+ 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(4011) && regTabPtr.p->fragid[1] == fragId && attrId == 0||
ERROR_INSERTED(4012) && regTabPtr.p->fragid[1] == fragId && lastAttr) {
ljam();
terrorCode = 1;
@@ -407,26 +418,201 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
CLEAR_ERROR_INSERT_VALUE;
return;
}
+
/* **************************************************************** */
/* ************** TUP_ADD_ATTCONF ****************** */
/* **************************************************************** */
- signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- signal->theData[1] = lastAttr;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 2, JBB);
if (! lastAttr) {
ljam();
- return; /* EXIT AND WAIT FOR MORE */
- }//if
- regFragPtr.p->fragStatus = ACTIVE;
- if (regTabPtr.p->tableStatus == DEFINING) {
- ljam();
- setUpQueryRoutines(regTabPtr.p);
- setUpKeyArray(regTabPtr.p);
- regTabPtr.p->tableStatus = DEFINED;
- }//if
+ 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->checksumIndicator)
+ {
+ pos[0]= 1;
+ }
+
+ 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] += 2; // 8 bytes
+ }
+
+ 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=
+ 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[MM].m_no_of_varsize == 0)
+ regTabPtr.p->m_offsets[MM].m_fix_header_size += Tuple_header::HeaderSize;
+
+ 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
+
+ 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;
+ }
+
+ new (&regFragPtr.p->m_disk_alloc_info)
+ Disk_alloc_info(regTabPtr.p, rep.tablespace.extent_size);
+
+ if (regTabPtr.p->m_no_of_disk_attributes)
+ {
+ if(!(getNodeState().getSystemRestartInProgress() &&
+ getNodeState().startLevel == NodeState::SL_STARTING &&
+ getNodeState().starting.startPhase <= 4))
+ {
+ Callback cb;
+ 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);
+ int r0 = c_lgman->alloc_log_space(regFragPtr.p->m_logfile_group_id,
+ sz);
+
+ int res= lgman.get_log_buffer(signal, sz, &cb);
+ switch(res){
+ case 0:
+ signal->theData[0] = 1;
+ return;
+ case -1:
+ ndbrequire("NOT YET IMPLEMENTED" == 0);
+ break;
+ }
+ execute(signal, cb, 0);
+ 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;
-}//Dbtup::execTUP_ADD_ATTRREQ()
+}
+
+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 lsman(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= lsman.add_entry<1>(c);
+
+ 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:
@@ -435,49 +621,84 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
* 1 updateFunctionArray ( ditto )
* 2 charsetArray ( pointers to distinct CHARSET_INFO )
* 3 readKeyArray ( attribute ids of keys )
- * 4 attributeGroupDescriptor ( currently size 1 but unused )
* 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->attributeGroupDescriptor = descriptorReference + offset[4];
- regTabPtr->tabDescriptor = descriptorReference + offset[5];
-}//Dbtup::setUpDescriptorReferences()
+ 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);
+ ReadFunction* tmp= (ReadFunction*)&tableDescriptor[0];
+ TableDescriptor* start= &tableDescriptor[0];
+ TableDescriptor * end= (TableDescriptor*)(tmp + 1);
return (Uint32)(end - start);
-}//Dbtup::sizeOfReadFunction()
+}
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->noOfAttr; i++) {
+ 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++) {
ljam();
- Uint32 refAttr = regTabPtr->tabDescriptor + (i * ZAD_SIZE);
- Uint32 attrDescriptor = getTabDescrWord(refAttr);
+ Uint32 refAttr= regTabPtr->tabDescriptor + (i * ZAD_SIZE);
+ Uint32 attrDescriptor= getTabDescrWord(refAttr);
if (AttributeDescriptor::getPrimaryKey(attrDescriptor)) {
ljam();
AttributeHeader::init(&keyArray[countKeyAttr], i, 0);
countKeyAttr++;
- }//if
- }//for
+ }
+ }
ndbrequire(countKeyAttr == regTabPtr->noOfKeyAttr);
-}//Dbtup::setUpKeyArray()
+
+ /**
+ * 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++)
+ {
+ ljam();
+ 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,
@@ -491,12 +712,12 @@ void Dbtup::addattrrefuseLab(Signal* signal,
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);
+ signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
+ signal->theData[1]= terrorCode;
+ sendSignal(fragOperPtr.p->lqhBlockrefFrag,
+ GSN_TUP_ADD_ATTRREF, signal, 2, JBB);
releaseFragoperrec(fragOperPtr);
- return;
-}//Dbtup::addattrrefuseLab()
+}
void Dbtup::fragrefuse4Lab(Signal* signal,
FragoperrecPtr fragOperPtr,
@@ -507,8 +728,7 @@ void Dbtup::fragrefuse4Lab(Signal* signal,
releaseFragPages(regFragPtr.p);
fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr, fragId);
initTab(regTabPtr);
- return;
-}//Dbtup::fragrefuse4Lab()
+}
void Dbtup::fragrefuse3Lab(Signal* signal,
FragoperrecPtr fragOperPtr,
@@ -518,30 +738,28 @@ void Dbtup::fragrefuse3Lab(Signal* signal,
{
fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
deleteFragTab(regTabPtr, fragId);
- return;
-}//Dbtup::fragrefuse3Lab()
+}
-void Dbtup::fragrefuse2Lab(Signal* signal, FragoperrecPtr fragOperPtr, FragrecordPtr regFragPtr)
+void Dbtup::fragrefuse2Lab(Signal* signal,
+ FragoperrecPtr fragOperPtr,
+ FragrecordPtr regFragPtr)
{
fragrefuse1Lab(signal, fragOperPtr);
releaseFragrec(regFragPtr);
- return;
-}//Dbtup::fragrefuse2Lab()
+}
void Dbtup::fragrefuse1Lab(Signal* signal, FragoperrecPtr fragOperPtr)
{
fragrefuseLab(signal, fragOperPtr);
releaseFragoperrec(fragOperPtr);
- return;
-}//Dbtup::fragrefuse1Lab()
+}
void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr)
{
- signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- signal->theData[1] = terrorCode;
+ signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
+ signal->theData[1]= terrorCode;
sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUPFRAGREF, signal, 2, JBB);
- return;
-}//Dbtup::fragrefuseLab()
+}
void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr)
{
@@ -552,17 +770,17 @@ void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr)
void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
{
- for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
+ for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
ljam();
if (regTabPtr->fragid[i] == fragId) {
ljam();
- regTabPtr->fragid[i] = RNIL;
- regTabPtr->fragrec[i] = RNIL;
+ regTabPtr->fragid[i]= RNIL;
+ regTabPtr->fragrec[i]= RNIL;
return;
- }//if
- }//for
+ }
+ }
ndbrequire(false);
-}//Dbtup::deleteFragTab()
+}
/*
* LQH aborts on-going create table operation. The table is later
@@ -582,124 +800,283 @@ void
Dbtup::execDROP_TAB_REQ(Signal* signal)
{
ljamEntry();
- DropTabReq* req = (DropTabReq*)signal->getDataPtr();
+ DropTabReq* req= (DropTabReq*)signal->getDataPtr();
TablerecPtr tabPtr;
- tabPtr.i = req->tableId;
+ 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[0]= ZREL_FRAG;
+ signal->theData[1]= tabPtr.i;
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
-}//Dbtup::execDROP_TAB_REQ()
+}
void Dbtup::releaseTabDescr(Tablerec* const regTabPtr)
{
- Uint32 descriptor = regTabPtr->readKeyArray;
+ Uint32 descriptor= regTabPtr->readKeyArray;
if (descriptor != RNIL) {
ljam();
Uint32 offset[10];
getTabDescrOffsets(regTabPtr, offset);
- regTabPtr->tabDescriptor = RNIL;
- regTabPtr->readKeyArray = RNIL;
- regTabPtr->readFunctionArray = NULL;
- regTabPtr->updateFunctionArray = NULL;
- regTabPtr->charsetArray = NULL;
- regTabPtr->attributeGroupDescriptor= RNIL;
+ 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);
+ 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));
+ ndbrequire(ZTD_TYPE_NORMAL ==
+ getTabDescrWord((descriptor + retNo) - ZTD_TR_TYPE));
freeTabDescr(descriptor, retNo);
- }//if
-}//Dbtup::releaseTabDescr()
+ }
+}
void Dbtup::releaseFragment(Signal* signal, Uint32 tableId)
{
TablerecPtr tabPtr;
- tabPtr.i = tableId;
+ tabPtr.i= tableId;
ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
Uint32 fragIndex = RNIL;
Uint32 fragId = RNIL;
Uint32 i = 0;
- for (i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
+ for (i = 0; i < MAX_FRAG_PER_NODE; i++) {
ljam();
if (tabPtr.p->fragid[i] != RNIL) {
ljam();
- fragIndex = tabPtr.p->fragrec[i];
- fragId = tabPtr.p->fragid[i];
+ fragIndex= tabPtr.p->fragrec[i];
+ fragId= tabPtr.p->fragid[i];
break;
- }//if
- }//for
+ }
+ }
if (fragIndex != RNIL) {
ljam();
- FragrecordPtr regFragPtr;
- regFragPtr.i = fragIndex;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- releaseFragPages(regFragPtr.p);
-
- tabPtr.p->fragid[i] = RNIL;
- tabPtr.p->fragrec[i] = RNIL;
- releaseFragrec(regFragPtr);
-
- signal->theData[0] = ZREL_FRAG;
- signal->theData[1] = tableId;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
+ 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
+ }
- /**
- * Finished...
- */
- sendFSREMOVEREQ(signal, tabPtr);
-}//Dbtup::releaseFragment()
+ 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::sendFSREMOVEREQ(Signal* signal, TablerecPtr tabPtr)
+void
+Dbtup::drop_fragment_unmap_pages(Signal *signal,
+ TablerecPtr tabPtr,
+ FragrecordPtr fragPtr,
+ Uint32 pos)
{
- FsRemoveReq * const fsReq = (FsRemoveReq *)signal->getDataPtrSend();
- fsReq->userReference = cownref;
- fsReq->userPointer = tabPtr.i;
- fsReq->fileNumber[0] = tabPtr.i;
- fsReq->fileNumber[1] = (Uint32)-1; // Remove all fragments
- fsReq->fileNumber[2] = (Uint32)-1; // Remove all data files within fragment
- fsReq->fileNumber[3] = 255 | // No P-value used here
- (5 << 8) | // Data-files in D5
- (0 << 16) | // Data-files
- (1 << 24); // Version 1 of fileNumber
-
- fsReq->directory = 1;
- fsReq->ownDirectory = 1;
- sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
- FsRemoveReq::SignalLength, JBA);
-}//Dbtup::sendFSREMOVEREQ()
-
-void Dbtup::execFSREMOVECONF(Signal* signal)
+ if (tabPtr.p->m_no_of_disk_attributes)
+ {
+ Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
+ 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)
+ {
+ LocalDLList<Extent_info>
+ 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_exent(signal, tabPtr, fragPtr, 0);
+ return;
+ }
+
+ Uint32 page_id = alloc_info.m_dirty_pages[pos].firstItem;
+ Ptr<GlobalPage> page;
+ m_global_page_pool.getPtr(page, page_id);
+
+ Page_cache_client::Request req;
+ req.m_page.m_page_no = ((Page*)page.p)->m_page_no;
+ req.m_page.m_file_no = ((Page*)page.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(res == page_id);
+ drop_fragment_unmap_page_callback(signal, pos, res);
+ }
+ return;
+ }
+ drop_fragment_free_exent(signal, tabPtr, fragPtr, 0);
+}
+
+void
+Dbtup::drop_fragment_unmap_page_callback(Signal* signal,
+ Uint32 pos, Uint32 page_id)
{
- ljamEntry();
+ Ptr<GlobalPage> page;
+ m_global_page_pool.getPtr(page, page_id);
- FsConf * const fsConf = (FsConf *)signal->getDataPtrSend();
+ 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 = fsConf->userPointer;
+ 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_exent(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();
+ LocalDLList<Extent_info>
+ list(c_extent_pool, alloc_info.m_free_extents[pos]);
+ Ptr<Extent_info> ext_ptr;
+ list.first(ext_ptr);
+
+ Tablespace_client tsman(signal, c_tsman, tabPtr.i,
+ fragPtr.p->fragmentId,
+ fragPtr.p->m_tablespace_id);
+
+ tsman.free_extent(&ext_ptr.p->m_key);
+ 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;
+ }
+ }
+
+ 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();
+ }
+ }
- 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);
+ releaseFragPages(fragPtr.p);
- releaseTabDescr(tabPtr.p);
- initTab(tabPtr.p);
-}//Dbtup::execFSREMOVECONF()
+ 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;
+ sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
+ return;
+}
+
+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;
+ }
+}
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
index 9722aa437c0..d95dd7b9eb0 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp
@@ -124,26 +124,27 @@ void Dbtup::initializePage()
for (pagePtr.i = 0; pagePtr.i < cnoOfPage; pagePtr.i++) {
ljam();
refresh_watch_dog();
- ptrAss(pagePtr, page);
- pagePtr.p->pageWord[ZPAGE_PHYSICAL_INDEX] = pagePtr.i;
- pagePtr.p->pageWord[ZPAGE_NEXT_POS] = pagePtr.i + 1;
- pagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = RNIL;
- pagePtr.p->pageWord[ZPAGE_LAST_CLUST_POS] = RNIL;
- pagePtr.p->pageWord[ZPAGE_PREV_POS] = RNIL;
- pagePtr.p->pageWord[ZPAGE_STATE_POS] = ZFREE_COMMON;
+ ptrAss(pagePtr, cpage);
+ 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.i = cnoOfPage - 1;
- ptrAss(pagePtr, page);
- pagePtr.p->pageWord[ZPAGE_NEXT_POS] = RNIL;
+ ptrAss(pagePtr, cpage);
+ pagePtr.p->next_page = RNIL;
pagePtr.i = 0;
- ptrAss(pagePtr, page);
- pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
+ ptrAss(pagePtr, cpage);
+ pagePtr.p->page_state = ~ZFREE_COMMON;
for(size_t j = 0; j<MAX_PARALLELL_TUP_SRREQ; j++){
pagePtr.i = 1+j;
- ptrAss(pagePtr, page);
- pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
+ ptrAss(pagePtr, cpage);
+ pagePtr.p->page_state = ~ZFREE_COMMON;
}
Uint32 tmp = 1 + MAX_PARALLELL_TUP_SRREQ;
@@ -233,13 +234,13 @@ void Dbtup::findFreeLeftNeighbours(Uint32& allocPageRef,
while (allocPageRef > 0) {
ljam();
pageLastPtr.i = allocPageRef - 1;
- ptrCheckGuard(pageLastPtr, cnoOfPage, page);
- if (pageLastPtr.p->pageWord[ZPAGE_STATE_POS] != ZFREE_COMMON) {
+ ptrCheckGuard(pageLastPtr, cnoOfPage, cpage);
+ if (pageLastPtr.p->page_state != ZFREE_COMMON) {
ljam();
return;
} else {
ljam();
- pageFirstPtr.i = pageLastPtr.p->pageWord[ZPAGE_FIRST_CLUST_POS];
+ pageFirstPtr.i = pageLastPtr.p->first_cluster_page;
ndbrequire(pageFirstPtr.i != RNIL);
Uint32 list = nextHigherTwoLog(pageLastPtr.i - pageFirstPtr.i);
removeCommonArea(pageFirstPtr.i, list);
@@ -274,13 +275,13 @@ void Dbtup::findFreeRightNeighbours(Uint32& allocPageRef,
while ((allocPageRef + noPagesAllocated) < cnoOfPage) {
ljam();
pageFirstPtr.i = allocPageRef + noPagesAllocated;
- ptrCheckGuard(pageFirstPtr, cnoOfPage, page);
- if (pageFirstPtr.p->pageWord[ZPAGE_STATE_POS] != ZFREE_COMMON) {
+ ptrCheckGuard(pageFirstPtr, cnoOfPage, cpage);
+ if (pageFirstPtr.p->page_state != ZFREE_COMMON) {
ljam();
return;
} else {
ljam();
- pageLastPtr.i = pageFirstPtr.p->pageWord[ZPAGE_LAST_CLUST_POS];
+ pageLastPtr.i = pageFirstPtr.p->last_cluster_page;
ndbrequire(pageLastPtr.i != RNIL);
Uint32 list = nextHigherTwoLog(pageLastPtr.i - pageFirstPtr.i);
removeCommonArea(pageFirstPtr.i, list);
@@ -307,18 +308,18 @@ void Dbtup::insertCommonArea(Uint32 insPageRef, Uint32 insList)
PagePtr pageLastPtr, pageInsPtr;
pageInsPtr.i = insPageRef;
- ptrCheckGuard(pageInsPtr, cnoOfPage, page);
+ ptrCheckGuard(pageInsPtr, cnoOfPage, cpage);
ndbrequire(insList < 16);
pageLastPtr.i = (pageInsPtr.i + (1 << insList)) - 1;
- pageInsPtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = cfreepageList[insList];
- pageInsPtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = RNIL;
- pageInsPtr.p->pageWord[ZPAGE_LAST_CLUST_POS] = pageLastPtr.i;
+ pageInsPtr.p->next_cluster_page = cfreepageList[insList];
+ pageInsPtr.p->prev_cluster_page = RNIL;
+ pageInsPtr.p->last_cluster_page = pageLastPtr.i;
cfreepageList[insList] = pageInsPtr.i;
-
- ptrCheckGuard(pageLastPtr, cnoOfPage, page);
- pageLastPtr.p->pageWord[ZPAGE_FIRST_CLUST_POS] = pageInsPtr.i;
- pageLastPtr.p->pageWord[ZPAGE_NEXT_POS] = RNIL;
+
+ ptrCheckGuard(pageLastPtr, cnoOfPage, cpage);
+ pageLastPtr.p->first_cluster_page = pageInsPtr.i;
+ pageLastPtr.p->next_page = RNIL;
}//Dbtup::insertCommonArea()
void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list)
@@ -327,44 +328,42 @@ void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list)
PagePtr pagePrevPtr, pageNextPtr, pageLastPtr, pageSearchPtr, remPagePtr;
remPagePtr.i = remPageRef;
- ptrCheckGuard(remPagePtr, cnoOfPage, page);
+ ptrCheckGuard(remPagePtr, cnoOfPage, cpage);
ndbrequire(list < 16);
if (cfreepageList[list] == remPagePtr.i) {
ljam();
- cfreepageList[list] = remPagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS];
+ cfreepageList[list] = remPagePtr.p->next_cluster_page;
pageNextPtr.i = cfreepageList[list];
if (pageNextPtr.i != RNIL) {
ljam();
- ptrCheckGuard(pageNextPtr, cnoOfPage, page);
- pageNextPtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = RNIL;
+ ptrCheckGuard(pageNextPtr, cnoOfPage, cpage);
+ pageNextPtr.p->prev_cluster_page = RNIL;
}//if
} else {
pageSearchPtr.i = cfreepageList[list];
while (true) {
ljam();
- ptrCheckGuard(pageSearchPtr, cnoOfPage, page);
+ ptrCheckGuard(pageSearchPtr, cnoOfPage, cpage);
pagePrevPtr = pageSearchPtr;
- pageSearchPtr.i = pageSearchPtr.p->pageWord[ZPAGE_NEXT_CLUST_POS];
+ pageSearchPtr.i = pageSearchPtr.p->next_cluster_page;
if (pageSearchPtr.i == remPagePtr.i) {
ljam();
break;
}//if
}//while
- pageNextPtr.i = remPagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS];
- pagePrevPtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = pageNextPtr.i;
+ pageNextPtr.i = remPagePtr.p->next_cluster_page;
+ pagePrevPtr.p->next_cluster_page = pageNextPtr.i;
if (pageNextPtr.i != RNIL) {
ljam();
- ptrCheckGuard(pageNextPtr, cnoOfPage, page);
- pageNextPtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = pagePrevPtr.i;
+ ptrCheckGuard(pageNextPtr, cnoOfPage, cpage);
+ pageNextPtr.p->prev_cluster_page = pagePrevPtr.i;
}//if
}//if
- remPagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = RNIL;
- remPagePtr.p->pageWord[ZPAGE_LAST_CLUST_POS] = RNIL;
- remPagePtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = RNIL;
+ remPagePtr.p->next_cluster_page= RNIL;
+ remPagePtr.p->last_cluster_page= RNIL;
+ remPagePtr.p->prev_cluster_page= RNIL;
pageLastPtr.i = (remPagePtr.i + (1 << list)) - 1;
- ptrCheckGuard(pageLastPtr, cnoOfPage, page);
- pageLastPtr.p->pageWord[ZPAGE_FIRST_CLUST_POS] = RNIL;
+ ptrCheckGuard(pageLastPtr, cnoOfPage, cpage);
+ pageLastPtr.p->first_cluster_page= RNIL;
}//Dbtup::removeCommonArea()
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
index 1f674876642..5b3e3eb273d 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
@@ -91,22 +91,21 @@
Uint32 Dbtup::getEmptyPage(Fragrecord* const regFragPtr)
{
- Uint32 logicalPageId = regFragPtr->emptyPrimPage;
- if (logicalPageId == RNIL) {
+ Uint32 pageId = regFragPtr->emptyPrimPage;
+ if (pageId == RNIL) {
ljam();
allocMoreFragPages(regFragPtr);
- logicalPageId = regFragPtr->emptyPrimPage;
- if (logicalPageId == RNIL) {
+ pageId = regFragPtr->emptyPrimPage;
+ if (pageId == RNIL) {
ljam();
return RNIL;
}//if
}//if
- Uint32 physicalPageId = getRealpid(regFragPtr, logicalPageId);
PagePtr pagePtr;
- pagePtr.i = physicalPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- regFragPtr->emptyPrimPage = pagePtr.p->pageWord[ZPAGE_NEXT_POS];
- return physicalPageId;
+ pagePtr.i = pageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ regFragPtr->emptyPrimPage = pagePtr.p->next_page;
+ return pageId;
}//Dbtup::getEmptyPage()
Uint32 Dbtup::getRealpid(Fragrecord* const regFragPtr, Uint32 logicalPageId)
@@ -115,10 +114,10 @@ Uint32 Dbtup::getRealpid(Fragrecord* const regFragPtr, Uint32 logicalPageId)
Uint32 loopLimit;
Uint32 loopCount = 0;
Uint32 pageRangeLimit = cnoOfPageRangeRec;
-
+ ndbassert(logicalPageId < getNoOfPages(regFragPtr));
grpPageRangePtr.i = regFragPtr->rootPageRange;
while (true) {
- ndbrequire(loopCount++ < 100);
+ ndbassert(loopCount++ < 100);
ndbrequire(grpPageRangePtr.i < pageRangeLimit);
ptrAss(grpPageRangePtr, pageRange);
loopLimit = grpPageRangePtr.p->currentIndexPos;
@@ -368,16 +367,17 @@ Uint32 Dbtup::allocFragPages(Fragrecord* const regFragPtr, Uint32 tafpNoAllocReq
/* ---------------------------------------------------------------- */
for (loopPagePtr.i = retPageRef; loopPagePtr.i < loopLimit; loopPagePtr.i++) {
ljam();
- ptrCheckGuard(loopPagePtr, cnoOfPage, page);
- loopPagePtr.p->pageWord[ZPAGE_STATE_POS] = ZEMPTY_MM;
- loopPagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS] = startRange +
- (loopPagePtr.i - retPageRef);
- loopPagePtr.p->pageWord[ZPAGE_NEXT_POS] = loopPagePtr.p->pageWord[ZPAGE_FRAG_PAGE_ID_POS] + 1;
+ ptrCheckGuard(loopPagePtr, cnoOfPage, cpage);
+ loopPagePtr.p->page_state = ZEMPTY_MM;
+ loopPagePtr.p->frag_page_id = startRange +
+ (loopPagePtr.i - retPageRef);
+ loopPagePtr.p->physical_page_id = loopPagePtr.i;
+ loopPagePtr.p->next_page = loopPagePtr.i + 1;
}//for
loopPagePtr.i = (retPageRef + noOfPagesAllocated) - 1;
- ptrCheckGuard(loopPagePtr, cnoOfPage, page);
- loopPagePtr.p->pageWord[ZPAGE_NEXT_POS] = regFragPtr->emptyPrimPage;
- regFragPtr->emptyPrimPage = startRange;
+ ptrCheckGuard(loopPagePtr, cnoOfPage, cpage);
+ loopPagePtr.p->next_page = regFragPtr->emptyPrimPage;
+ regFragPtr->emptyPrimPage = retPageRef;
/* ---------------------------------------------------------------- */
/* WAS ENOUGH PAGES ALLOCATED OR ARE MORE NEEDED. */
/* ---------------------------------------------------------------- */
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
index 65a61174596..d44400222fb 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
@@ -30,35 +30,39 @@
void
Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
{
- Uint32 startDescriptor = regTabPtr->tabDescriptor;
- ndbrequire((startDescriptor + (regTabPtr->noOfAttr << ZAD_LOG_SIZE)) <= cnoOfTabDescrRec);
- for (Uint32 i = 0; i < regTabPtr->noOfAttr; i++) {
- Uint32 attrDescriptorStart = startDescriptor + (i << ZAD_LOG_SIZE);
- Uint32 attrDescriptor = tableDescriptor[attrDescriptorStart].tabDescr;
- Uint32 attrOffset = tableDescriptor[attrDescriptorStart + 1].tabDescr;
- if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
- if ((AttributeDescriptor::getArrayType(attrDescriptor) == ZNON_ARRAY) ||
- (AttributeDescriptor::getArrayType(attrDescriptor) == ZFIXED_ARRAY)) {
- if (!AttributeDescriptor::getNullable(attrDescriptor)) {
- if (AttributeDescriptor::getSize(attrDescriptor) == 0){
- ljam();
+ 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){
+ ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNotNULL;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNotNULL;
- } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1){
+ } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 4) {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHOneWordNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHOneWordNotNULL;
- } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 2) {
+ regTabPtr->readFunctionArray[i]=
+ &Dbtup::readFixedSizeTHOneWordNotNULL;
+ regTabPtr->updateFunctionArray[i]=
+ &Dbtup::updateFixedSizeTHOneWordNotNULL;
+ } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 8) {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHTwoWordNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHTwoWordNotNULL;
- } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) > 2) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNotNULL;
+ regTabPtr->readFunctionArray[i]=
+ &Dbtup::readFixedSizeTHTwoWordNotNULL;
+ regTabPtr->updateFunctionArray[i]=
+ &Dbtup::updateFixedSizeTHTwoWordNotNULL;
} else {
- ndbrequire(false);
- }//if
+ ljam();
+ regTabPtr->readFunctionArray[i]=
+ &Dbtup::readFixedSizeTHManyWordNotNULL;
+ regTabPtr->updateFunctionArray[i]=
+ &Dbtup::updateFixedSizeTHManyWordNotNULL;
+ }
// replace functions for char attribute
if (AttributeOffset::getCharsetFlag(attrOffset)) {
ljam();
@@ -66,93 +70,88 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNotNULL;
}
} else {
- if (AttributeDescriptor::getSize(attrDescriptor) == 0){
+ if (AttributeDescriptor::getSize(attrDescr) == 0){
ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNULLable;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNULLable;
- } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1){
+ } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 4){
ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHOneWordNULLable;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
- } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 2) {
+ } else if (AttributeDescriptor::getSizeInBytes(attrDescr) == 8) {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHTwoWordNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
- } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) > 2) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
+ regTabPtr->readFunctionArray[i]=
+ &Dbtup::readFixedSizeTHTwoWordNULLable;
+ regTabPtr->updateFunctionArray[i]=
+ &Dbtup::updateFixedSizeTHManyWordNULLable;
} else {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHZeroWordNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
- }//if
+ regTabPtr->readFunctionArray[i]=
+ &Dbtup::readFixedSizeTHManyWordNULLable;
+ regTabPtr->updateFunctionArray[i]=
+ &Dbtup::updateFixedSizeTHManyWordNULLable;
+ }
// replace functions for char attribute
if (AttributeOffset::getCharsetFlag(attrOffset)) {
ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNULLable;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
}
- }//if
- } else if (AttributeDescriptor::getArrayType(attrDescriptor) == ZVAR_ARRAY) {
- if (!AttributeDescriptor::getNullable(attrDescriptor)) {
- if (AttributeDescriptor::getArraySize(attrDescriptor) == 0) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readVarSizeUnlimitedNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateVarSizeUnlimitedNotNULL;
- } else if (AttributeDescriptor::getArraySize(attrDescriptor) > ZMAX_SMALL_VAR_ARRAY) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readBigVarSizeNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateBigVarSizeNotNULL;
- } else {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readSmallVarSizeNotNULL;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateSmallVarSizeNotNULL;
- }//if
+ }
+ } else {
+ if (!AttributeDescriptor::getNullable(attrDescr)) {
+ regTabPtr->readFunctionArray[i]=
+ &Dbtup::readVarSizeNotNULL;
+ regTabPtr->updateFunctionArray[i]=
+ &Dbtup::updateVarSizeNotNULL;
} else {
- if (AttributeDescriptor::getArraySize(attrDescriptor) == 0) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readVarSizeUnlimitedNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateVarSizeUnlimitedNULLable;
- } else if (AttributeDescriptor::getArraySize(attrDescriptor) > ZMAX_SMALL_VAR_ARRAY) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readBigVarSizeNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateBigVarSizeNULLable;
- } else {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readSmallVarSizeNULLable;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateSmallVarSizeNULLable;
- }//if
- }//if
+ regTabPtr->readFunctionArray[i]=
+ &Dbtup::readVarSizeNULLable;
+ regTabPtr->updateFunctionArray[i]=
+ &Dbtup::updateVarSizeNULLable;
+ }
+ }
+ if(AttributeDescriptor::getDiskBased(attrDescr))
+ {
+ ReadFunction r[] = {
+ &Dbtup::readDiskBitsNotNULL,
+ &Dbtup::readDiskBitsNULLable,
+ &Dbtup::readDiskFixedSizeNotNULL,
+ &Dbtup::readDiskFixedSizeNULLable,
+ &Dbtup::readDiskVarSizeNULLable,
+ &Dbtup::readDiskVarSizeNotNULL
+ };
+ UpdateFunction u[] = {
+ &Dbtup::updateDiskBitsNotNULL,
+ &Dbtup::updateDiskBitsNULLable,
+ &Dbtup::updateDiskFixedSizeNotNULL,
+ &Dbtup::updateDiskFixedSizeNULLable,
+ &Dbtup::updateDiskVarSizeNULLable,
+ &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 {
- ndbrequire(false);
- }//if
- } else {
- if ((AttributeDescriptor::getArrayType(attrDescriptor) == ZNON_ARRAY) ||
- (AttributeDescriptor::getArrayType(attrDescriptor) == ZFIXED_ARRAY)) {
+ if (AttributeDescriptor::getArrayType(attrDescr) == NDB_ARRAYTYPE_FIXED){
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readDynFixedSize;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateDynFixedSize;
- } else if (AttributeDescriptor::getType(attrDescriptor) == ZVAR_ARRAY) {
- if (AttributeDescriptor::getArraySize(attrDescriptor) == 0) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readDynVarSizeUnlimited;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateDynVarSizeUnlimited;
- } else if (AttributeDescriptor::getArraySize(attrDescriptor) > ZMAX_SMALL_VAR_ARRAY) {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readDynBigVarSize;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateDynBigVarSize;
- } else {
- ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readDynSmallVarSize;
- regTabPtr->updateFunctionArray[i] = &Dbtup::updateDynSmallVarSize;
- }//if
+ regTabPtr->readFunctionArray[i]= &Dbtup::readDynFixedSize;
+ regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynFixedSize;
} else {
- ndbrequire(false);
- }//if
- }//if
- }//for
-}//Dbtup::setUpQueryRoutines()
+ regTabPtr->readFunctionArray[i]= &Dbtup::readDynVarSize;
+ regTabPtr->updateFunctionArray[i]= &Dbtup::updateDynVarSize;
+ }
+ }
+ }
+}
/* ---------------------------------------------------------------- */
/* THIS ROUTINE IS USED TO READ A NUMBER OF ATTRIBUTES IN THE */
@@ -164,196 +163,158 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
// 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(Page* const pagePtr,
- Uint32 tupHeadOffset,
- const Uint32* inBuffer,
- Uint32 inBufLen,
- Uint32* outBuffer,
- Uint32 maxRead,
- bool xfrmFlag)
+int Dbtup::readAttributes(KeyReqStruct *req_struct,
+ const Uint32* inBuffer,
+ Uint32 inBufLen,
+ Uint32* outBuffer,
+ Uint32 maxRead,
+ bool xfrm_flag)
{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 numAttributes = regTabPtr->noOfAttr;
- Uint32 attrDescriptorStart = regTabPtr->tabDescriptor;
- Uint32 inBufIndex = 0;
-
- ndbrequire(attrDescriptorStart + (numAttributes << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
-
- tOutBufIndex = 0;
- tCheckOffset = regTabPtr->tupheadsize;
- tMaxRead = maxRead;
- tTupleHeader = &pagePtr->pageWord[tupHeadOffset];
- tXfrmFlag = xfrmFlag;
-
- ndbrequire(tupHeadOffset + tCheckOffset <= ZWORDS_ON_PAGE);
+ 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) {
- Uint32 tmpAttrBufIndex = tOutBufIndex;
+ tmpAttrBufIndex= req_struct->out_buf_index;
AttributeHeader ahIn(inBuffer[inBufIndex]);
inBufIndex++;
- Uint32 attributeId = ahIn.getAttributeId();
- Uint32 attrDescriptorIndex = attrDescriptorStart + (attributeId << ZAD_LOG_SIZE);
+ attributeId= ahIn.getAttributeId();
+ descr_index= attributeId << ZAD_LOG_SIZE;
ljam();
AttributeHeader::init(&outBuffer[tmpAttrBufIndex], attributeId, 0);
- AttributeHeader* ahOut = (AttributeHeader*)&outBuffer[tmpAttrBufIndex];
- tOutBufIndex = tmpAttrBufIndex + 1;
+ ahOut= (AttributeHeader*)&outBuffer[tmpAttrBufIndex];
+ req_struct->out_buf_index= tmpAttrBufIndex + 1;
+ attr_descr= req_struct->attr_descr;
if (attributeId < numAttributes) {
- Uint32 attributeDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr;
- Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr;
- ReadFunction f = regTabPtr->readFunctionArray[attributeId];
+ 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,
- attributeDescriptor,
attributeOffset)) {
continue;
} else {
return -1;
- }//if
- } else if(attributeId & AttributeHeader::PSEUDO){
- Uint32 sz = read_pseudo(attributeId,
- outBuffer+tmpAttrBufIndex+1);
+ }
+ } else if(attributeId & AttributeHeader::PSEUDO) {
+ ljam();
+ Uint32 sz= read_pseudo(attributeId,
+ req_struct,
+ outBuffer+tmpAttrBufIndex+1);
AttributeHeader::init(&outBuffer[tmpAttrBufIndex], attributeId, sz << 2);
- tOutBufIndex = tmpAttrBufIndex + 1 + sz;
- } else {
- terrorCode = ZATTRIBUTE_ID_ERROR;
- return -1;
- }//if
- }//while
- return tOutBufIndex;
-}//Dbtup::readAttributes()
-
-#if 0
-int Dbtup::readAttributesWithoutHeader(Page* const pagePtr,
- Uint32 tupHeadOffset,
- Uint32* inBuffer,
- Uint32 inBufLen,
- Uint32* outBuffer,
- Uint32* attrBuffer,
- Uint32 maxRead)
-{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 numAttributes = regTabPtr->noOfAttr;
- Uint32 attrDescriptorStart = regTabPtr->tabDescriptor;
- Uint32 inBufIndex = 0;
- Uint32 attrBufIndex = 0;
-
- ndbrequire(attrDescriptorStart + (numAttributes << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
-
- tOutBufIndex = 0;
- tCheckOffset = regTabPtr->tupheadsize;
- tMaxRead = maxRead;
- tTupleHeader = &pagePtr->pageWord[tupHeadOffset];
-
- ndbrequire(tupHeadOffset + tCheckOffset <= ZWORDS_ON_PAGE);
- while (inBufIndex < inBufLen) {
- AttributeHeader ahIn(inBuffer[inBufIndex]);
- inBufIndex++;
- Uint32 attributeId = ahIn.getAttributeId();
- Uint32 attrDescriptorIndex = attrDescriptorStart + (attributeId << ZAD_LOG_SIZE);
- ljam();
-
- AttributeHeader::init(&attrBuffer[attrBufIndex], attributeId, 0);
- AttributeHeader* ahOut = (AttributeHeader*)&attrBuffer[attrBufIndex];
- attrBufIndex++;
- if (attributeId < numAttributes) {
- Uint32 attributeDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr;
- Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr;
- ReadFunction f = regTabPtr->readFunctionArray[attributeId];
- if ((this->*f)(outBuffer,
- ahOut,
- attributeDescriptor,
- attributeOffset)) {
- continue;
- } else {
- return -1;
- }//if
+ req_struct->out_buf_index= tmpAttrBufIndex + 1 + sz;
} else {
terrorCode = ZATTRIBUTE_ID_ERROR;
return -1;
}//if
}//while
- ndbrequire(attrBufIndex == inBufLen);
- return tOutBufIndex;
-}//Dbtup::readAttributes()
-#endif
+ return req_struct->out_buf_index;
+}
bool
Dbtup::readFixedSizeTHOneWordNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
- Uint32 indexBuf = tOutBufIndex;
- Uint32 readOffset = AttributeOffset::getOffset(attrDes2);
- Uint32 const wordRead = tTupleHeader[readOffset];
- Uint32 newIndexBuf = indexBuf + 1;
- Uint32 maxRead = tMaxRead;
-
- ndbrequire(readOffset < tCheckOffset);
+ 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) {
ljam();
- outBuffer[indexBuf] = wordRead;
+ outBuffer[indexBuf]= wordRead;
ahOut->setDataSize(1);
- tOutBufIndex = newIndexBuf;
+ req_struct->out_buf_index= newIndexBuf;
return true;
} else {
ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
return false;
- }//if
-}//Dbtup::readFixedSizeTHOneWordNotNULL()
+ }
+}
bool
Dbtup::readFixedSizeTHTwoWordNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
- Uint32 indexBuf = tOutBufIndex;
- Uint32 readOffset = AttributeOffset::getOffset(attrDes2);
- Uint32 const wordReadFirst = tTupleHeader[readOffset];
- Uint32 const wordReadSecond = tTupleHeader[readOffset + 1];
- Uint32 newIndexBuf = indexBuf + 2;
- Uint32 maxRead = tMaxRead;
-
- ndbrequire(readOffset + 1 < tCheckOffset);
+ 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) {
ljam();
ahOut->setDataSize(2);
- outBuffer[indexBuf] = wordReadFirst;
- outBuffer[indexBuf + 1] = wordReadSecond;
- tOutBufIndex = newIndexBuf;
+ outBuffer[indexBuf]= wordReadFirst;
+ outBuffer[indexBuf + 1]= wordReadSecond;
+ req_struct->out_buf_index= newIndexBuf;
return true;
} else {
ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
return false;
- }//if
-}//Dbtup::readFixedSizeTHTwoWordNotNULL()
+ }
+}
bool
Dbtup::readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
- Uint32 indexBuf = tOutBufIndex;
+ 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);
- Uint32 readOffset = AttributeOffset::getOffset(attrDes2);
- Uint32 attrNoOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 maxRead = tMaxRead;
- ndbrequire((readOffset + attrNoOfWords - 1) < tCheckOffset);
- if (! charsetFlag || ! tXfrmFlag) {
+ ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[MM]);
+ if (! charsetFlag || ! req_struct->xfrm_flag) {
Uint32 newIndexBuf = indexBuf + attrNoOfWords;
if (newIndexBuf <= maxRead) {
ljam();
- ahOut->setDataSize(attrNoOfWords);
+ ahOut->setByteSize(AttributeDescriptor::getSizeInBytes(attrDescriptor));
MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
- &tTupleHeader[readOffset],
+ &tuple_header[readOffset],
attrNoOfWords);
- tOutBufIndex = newIndexBuf;
+ req_struct->out_buf_index = newIndexBuf;
return true;
} else {
ljam();
@@ -364,248 +325,392 @@ Dbtup::readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
Tablerec* regTabPtr = tabptr.p;
Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
uchar* dstPtr = (uchar*)&outBuffer[indexBuf];
- const uchar* srcPtr = (uchar*)&tTupleHeader[readOffset];
+ 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);
- if (ok) {
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- // see comment in DbtcMain.cpp
- Uint32 dstLen = xmul * (srcBytes - lb);
- Uint32 maxIndexBuf = indexBuf + (dstLen >> 2);
- if (maxIndexBuf <= maxRead) {
- ljam();
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- while ((n & 3) != 0) {
- dstPtr[n++] = 0;
- }
- Uint32 dstWords = (n >> 2);
- ahOut->setDataSize(dstWords);
- Uint32 newIndexBuf = indexBuf + dstWords;
- ndbrequire(newIndexBuf <= maxRead);
- tOutBufIndex = newIndexBuf;
- return true;
- } else {
- ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ Uint32 maxIndexBuf = indexBuf + (dstLen >> 2);
+ if (maxIndexBuf <= maxRead && ok) {
+ ljam();
+ const char* ssrcPtr = (const char*)srcPtr;
+ 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 {
ljam();
- terrorCode = ZTUPLE_CORRUPTED_ERROR;
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
}
- }
+ }
return false;
}//Dbtup::readFixedSizeTHManyWordNotNULL()
bool
Dbtup::readFixedSizeTHOneWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
- if (!nullFlagCheck(attrDes2)) {
+ if (!nullFlagCheck(req_struct, attrDes2)) {
ljam();
return readFixedSizeTHOneWordNotNULL(outBuffer,
+ req_struct,
ahOut,
- attrDescriptor,
attrDes2);
} else {
ljam();
ahOut->setNULL();
return true;
- }//if
-}//Dbtup::readFixedSizeTHOneWordNULLable()
+ }
+}
bool
Dbtup::readFixedSizeTHTwoWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
- if (!nullFlagCheck(attrDes2)) {
+ if (!nullFlagCheck(req_struct, attrDes2)) {
ljam();
return readFixedSizeTHTwoWordNotNULL(outBuffer,
+ req_struct,
ahOut,
- attrDescriptor,
attrDes2);
} else {
ljam();
ahOut->setNULL();
return true;
- }//if
-}//Dbtup::readFixedSizeTHTwoWordNULLable()
+ }
+}
bool
Dbtup::readFixedSizeTHManyWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
- if (!nullFlagCheck(attrDes2)) {
+ if (!nullFlagCheck(req_struct, attrDes2)) {
ljam();
return readFixedSizeTHManyWordNotNULL(outBuffer,
+ req_struct,
ahOut,
- attrDescriptor,
attrDes2);
} else {
ljam();
ahOut->setNULL();
return true;
- }//if
-}//Dbtup::readFixedSizeTHManyWordNULLable()
+ }
+}
bool
Dbtup::readFixedSizeTHZeroWordNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
ljam();
- if (nullFlagCheck(attrDes2)) {
+ if (nullFlagCheck(req_struct, attrDes2)) {
ljam();
ahOut->setNULL();
- }//if
+ }
return true;
-}//Dbtup::readFixedSizeTHZeroWordNULLable()
+}
bool
-Dbtup::nullFlagCheck(Uint32 attrDes2)
+Dbtup::nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2)
{
- Tablerec* const regTabPtr = tabptr.p;
- Uint32 nullFlagOffsetInTuple = AttributeOffset::getNullFlagOffset(attrDes2);
- ndbrequire(nullFlagOffsetInTuple < regTabPtr->tupNullWords);
- nullFlagOffsetInTuple += regTabPtr->tupNullIndex;
- ndbrequire(nullFlagOffsetInTuple < tCheckOffset);
-
- return (AttributeOffset::isNULL(tTupleHeader[nullFlagOffsetInTuple], attrDes2));
-}//Dbtup::nullFlagCheck()
+ 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::readVariableSizedAttr(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::disk_nullFlagCheck(KeyReqStruct *req_struct, Uint32 attrDes2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readVariableSizedAttr()
+ 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::readVarSizeUnlimitedNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+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) {
+ ljam();
+ 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
+ {
+ ljam();
+ 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) {
+ ljam();
+ const char* ssrcPtr = (const char*)srcPtr;
+ 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;
+ }
+ }
ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
+ terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
return false;
-}//Dbtup::readVarSizeUnlimitedNotNULL()
+}
bool
-Dbtup::readVarSizeUnlimitedNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::readVarSizeNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readVarSizeUnlimitedNULLable()
+ if (!nullFlagCheck(req_struct, attrDes2)) {
+ ljam();
+ return readVarSizeNotNULL(outBuffer,
+ req_struct,
+ ahOut,
+ attrDes2);
+ } else {
+ ljam();
+ ahOut->setNULL();
+ return true;
+ }
+}
bool
-Dbtup::readBigVarSizeNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::readDynFixedSize(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2)
{
ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
+ terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
return false;
-}//Dbtup::readBigVarSizeNotNULL()
+}
bool
-Dbtup::readBigVarSizeNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::readDynVarSize(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2)
{
ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
+ terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
return false;
-}//Dbtup::readBigVarSizeNULLable()
+}//Dbtup::readDynBigVarSize()
bool
-Dbtup::readSmallVarSizeNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::readDiskFixedSizeNotNULL(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readSmallVarSizeNotNULL()
+ 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);
-bool
-Dbtup::readSmallVarSizeNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
+ ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[DD]);
+ if (! charsetFlag || ! req_struct->xfrm_flag) {
+ Uint32 newIndexBuf = indexBuf + attrNoOfWords;
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ ahOut->setByteSize(AttributeDescriptor::getSizeInBytes(attrDescriptor));
+ MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
+ &tuple_header[readOffset],
+ attrNoOfWords);
+ req_struct->out_buf_index = newIndexBuf;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ }//if
+ } else {
+ ljam();
+ 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) {
+ ljam();
+ const char* ssrcPtr = (const char*)srcPtr;
+ 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 {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ }
+ }
return false;
-}//Dbtup::readSmallVarSizeNULLable()
+}
bool
-Dbtup::readDynFixedSize(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::readDiskFixedSizeNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readDynFixedSize()
+ if (!disk_nullFlagCheck(req_struct, attrDes2)) {
+ ljam();
+ return readDiskFixedSizeNotNULL(outBuffer,
+ req_struct,
+ ahOut,
+ attrDes2);
+ } else {
+ ljam();
+ ahOut->setNULL();
+ return true;
+ }
+}
bool
-Dbtup::readDynVarSizeUnlimited(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::readDiskVarSizeNotNULL(Uint32* out_buffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ah_out,
+ Uint32 attr_des2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readDynVarSizeUnlimited()
+ 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) {
+ ljam();
+ 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 {
+ ljam();
+ terrorCode= ZTRY_TO_READ_TOO_MUCH_ERROR;
+ return false;
+ }
+}
bool
-Dbtup::readDynBigVarSize(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::readDiskVarSizeNULLable(Uint32* outBuffer,
+ KeyReqStruct *req_struct,
+ AttributeHeader* ahOut,
+ Uint32 attrDes2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readDynBigVarSize()
+ if (!disk_nullFlagCheck(req_struct, attrDes2)) {
+ ljam();
+ return readDiskVarSizeNotNULL(outBuffer,
+ req_struct,
+ ahOut,
+ attrDes2);
+ } else {
+ ljam();
+ ahOut->setNULL();
+ return true;
+ }
+}
-bool
-Dbtup::readDynSmallVarSize(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::readDynSmallVarSize()
/* ---------------------------------------------------------------------- */
/* THIS ROUTINE IS USED TO UPDATE A NUMBER OF ATTRIBUTES. IT IS */
@@ -614,192 +719,209 @@ Dbtup::readDynSmallVarSize(Uint32* outBuffer,
// In addition to the parameters used in the call it also relies on the
// following variables set-up properly.
//
-// pagep.p Page record pointer
-// fragptr.p Fragment record pointer
// operPtr.p Operation record pointer
// tabptr.p Table record pointer
/* ---------------------------------------------------------------------- */
-int Dbtup::updateAttributes(Page* const pagePtr,
- Uint32 tupHeadOffset,
+int Dbtup::updateAttributes(KeyReqStruct *req_struct,
Uint32* inBuffer,
Uint32 inBufLen)
{
- Tablerec* const regTabPtr = tabptr.p;
- Operationrec* const regOperPtr = operPtr.p;
- Uint32 numAttributes = regTabPtr->noOfAttr;
- Uint32 attrDescriptorStart = regTabPtr->tabDescriptor;
- ndbrequire(attrDescriptorStart + (numAttributes << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
-
- tCheckOffset = regTabPtr->tupheadsize;
- tTupleHeader = &pagePtr->pageWord[tupHeadOffset];
- Uint32 inBufIndex = 0;
- tInBufIndex = 0;
- tInBufLen = inBufLen;
-
- ndbrequire(tupHeadOffset + tCheckOffset <= ZWORDS_ON_PAGE);
+ 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 = attrDescriptorStart + (attributeId << ZAD_LOG_SIZE);
- if (attributeId < numAttributes) {
- Uint32 attrDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr;
- Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr;
+ 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->optype != ZINSERT)) {
- if (checkUpdateOfPrimaryKey(&inBuffer[inBufIndex], regTabPtr)) {
+ (regOperPtr->op_struct.op_type != ZINSERT)) {
+ if (checkUpdateOfPrimaryKey(req_struct,
+ &inBuffer[inBufIndex],
+ regTabPtr)) {
ljam();
- terrorCode = ZTRY_UPDATE_PRIMARY_KEY;
+ terrorCode= ZTRY_UPDATE_PRIMARY_KEY;
return -1;
- }//if
- }//if
- UpdateFunction f = regTabPtr->updateFunctionArray[attributeId];
+ }
+ }
+ UpdateFunction f= regTabPtr->updateFunctionArray[attributeId];
ljam();
- regOperPtr->changeMask.set(attributeId);
+ 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,
- attrDescriptor,
+ req_struct,
attributeOffset)) {
- inBufIndex = tInBufIndex;
+ inBufIndex= req_struct->in_buf_index;
continue;
} else {
ljam();
return -1;
- }//if
- } else {
+ }
+ }
+ else if(attributeId == AttributeHeader::DISK_REF)
+ {
ljam();
- terrorCode = ZATTRIBUTE_ID_ERROR;
+ 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;
+ }
+ else
+ {
+ ljam();
+ terrorCode= ZATTRIBUTE_ID_ERROR;
return -1;
- }//if
- }//while
+ }
+ }
return 0;
-}//Dbtup::updateAttributes()
+}
bool
-Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr)
+Dbtup::checkUpdateOfPrimaryKey(KeyReqStruct* req_struct,
+ Uint32* updateBuffer,
+ Tablerec* const regTabPtr)
{
Uint32 keyReadBuffer[MAX_KEY_SIZE_IN_WORDS];
Uint32 attributeHeader;
- AttributeHeader* ahOut = (AttributeHeader*)&attributeHeader;
+ TableDescriptor* attr_descr= req_struct->attr_descr;
+ AttributeHeader* ahOut= (AttributeHeader*)&attributeHeader;
AttributeHeader ahIn(*updateBuffer);
- Uint32 attributeId = ahIn.getAttributeId();
- Uint32 attrDescriptorIndex = regTabPtr->tabDescriptor + (attributeId << ZAD_LOG_SIZE);
- Uint32 attrDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr;
- Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr;
- ReadFunction f = regTabPtr->readFunctionArray[attributeId];
+ Uint32 attributeId= ahIn.getAttributeId();
+ Uint32 attrDescriptorIndex= attributeId << ZAD_LOG_SIZE;
+ Uint32 attrDescriptor= attr_descr[attrDescriptorIndex].tabDescr;
+ Uint32 attributeOffset= attr_descr[attrDescriptorIndex + 1].tabDescr;
+ ReadFunction f= regTabPtr->readFunctionArray[attributeId];
AttributeHeader::init(&attributeHeader, attributeId, 0);
- tOutBufIndex = 0;
- tMaxRead = MAX_KEY_SIZE_IN_WORDS;
-
- bool tmp = tXfrmFlag;
- tXfrmFlag = false;
- ndbrequire((this->*f)(&keyReadBuffer[0], ahOut, attrDescriptor, attributeOffset));
- tXfrmFlag = tmp;
- ndbrequire(tOutBufIndex == ahOut->getDataSize());
+ 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 = false;
+ ndbrequire((this->*f)(&keyReadBuffer[0],
+ req_struct,
+ ahOut,
+ attributeOffset));
+ req_struct->xfrm_flag = tmp;
+
+ ndbrequire(req_struct->out_buf_index == ahOut->getDataSize());
if (ahIn.getDataSize() != ahOut->getDataSize()) {
ljam();
return true;
- }//if
- if (memcmp(&keyReadBuffer[0], &updateBuffer[1], tOutBufIndex << 2) != 0) {
+ }
+ if (memcmp(&keyReadBuffer[0],
+ &updateBuffer[1],
+ req_struct->out_buf_index << 2) != 0) {
ljam();
return true;
- }//if
- return false;
-}//Dbtup::checkUpdateOfPrimaryKey()
-
-#if 0
-void Dbtup::checkPages(Fragrecord* const regFragPtr)
-{
- Uint32 noPages = getNoOfPages(regFragPtr);
- for (Uint32 i = 0; i < noPages ; i++) {
- PagePtr pagePtr;
- pagePtr.i = getRealpid(regFragPtr, i);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- ndbrequire(pagePtr.p->pageWord[1] != (RNIL - 1));
}
+ return false;
}
-#endif
bool
Dbtup::updateFixedSizeTHOneWordNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2)
{
- Uint32 indexBuf = tInBufIndex;
- Uint32 inBufLen = tInBufLen;
- Uint32 updateOffset = AttributeOffset::getOffset(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;
- ndbrequire(updateOffset < tCheckOffset);
+ 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];
+ Uint32 updateWord= inBuffer[indexBuf + 1];
if (!nullIndicator) {
ljam();
- tInBufIndex = newIndex;
- tTupleHeader[updateOffset] = updateWord;
+ req_struct->in_buf_index= newIndex;
+ tuple_header[updateOffset]= updateWord;
return true;
} else {
ljam();
- terrorCode = ZNOT_NULL_ATTR;
+ terrorCode= ZNOT_NULL_ATTR;
return false;
- }//if
+ }
} else {
ljam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
+ terrorCode= ZAI_INCONSISTENCY_ERROR;
return false;
- }//if
+ }
return true;
-}//Dbtup::updateFixedSizeTHOneWordNotNULL()
+}
bool
Dbtup::updateFixedSizeTHTwoWordNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2)
{
- Uint32 indexBuf = tInBufIndex;
- Uint32 inBufLen = tInBufLen;
- Uint32 updateOffset = AttributeOffset::getOffset(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;
- ndbrequire((updateOffset + 1) < tCheckOffset);
+ 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];
+ Uint32 updateWord1= inBuffer[indexBuf + 1];
+ Uint32 updateWord2= inBuffer[indexBuf + 2];
if (!nullIndicator) {
ljam();
- tInBufIndex = newIndex;
- tTupleHeader[updateOffset] = updateWord1;
- tTupleHeader[updateOffset + 1] = updateWord2;
+ req_struct->in_buf_index= newIndex;
+ tuple_header[updateOffset]= updateWord1;
+ tuple_header[updateOffset + 1]= updateWord2;
return true;
} else {
ljam();
- terrorCode = ZNOT_NULL_ATTR;
+ terrorCode= ZNOT_NULL_ATTR;
return false;
- }//if
+ }
} else {
ljam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
+ terrorCode= ZAI_INCONSISTENCY_ERROR;
return false;
- }//if
-}//Dbtup::updateFixedSizeTHTwoWordNotNULL()
+ }
+}
bool
Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2)
{
- Uint32 indexBuf = tInBufIndex;
- Uint32 inBufLen = tInBufLen;
- Uint32 updateOffset = AttributeOffset::getOffset(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 nullIndicator = ahIn.isNULL();
- Uint32 noOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 newIndex = indexBuf + noOfWords + 1;
- ndbrequire((updateOffset + noOfWords - 1) < tCheckOffset);
+ 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) {
@@ -814,7 +936,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
// not const in MySQL
CHARSET_INFO* cs = regTabPtr->charsetArray[i];
int not_used;
- const char* ssrc = (const char*)&inBuffer[tInBufIndex + 1];
+ const char* ssrc = (const char*)&inBuffer[indexBuf + 1];
Uint32 lb, len;
if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
ljam();
@@ -829,199 +951,181 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
return false;
}
}
- tInBufIndex = newIndex;
- MEMCOPY_NO_WORDS(&tTupleHeader[updateOffset],
+ req_struct->in_buf_index= newIndex;
+ MEMCOPY_NO_WORDS(&tuple_header[updateOffset],
&inBuffer[indexBuf + 1],
noOfWords);
+
return true;
} else {
ljam();
- terrorCode = ZNOT_NULL_ATTR;
+ terrorCode= ZNOT_NULL_ATTR;
return false;
- }//if
+ }
} else {
ljam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
+ terrorCode= ZAI_INCONSISTENCY_ERROR;
return false;
- }//if
-}//Dbtup::updateFixedSizeTHManyWordNotNULL()
+ }
+}
bool
Dbtup::updateFixedSizeTHManyWordNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2)
{
- Tablerec* const regTabPtr = tabptr.p;
- AttributeHeader ahIn(inBuffer[tInBufIndex]);
- Uint32 nullIndicator = ahIn.isNULL();
- Uint32 nullFlagOffset = AttributeOffset::getNullFlagOffset(attrDes2);
- Uint32 nullFlagBitOffset = AttributeOffset::getNullFlagBitOffset(attrDes2);
- Uint32 nullWordOffset = nullFlagOffset + regTabPtr->tupNullIndex;
- ndbrequire((nullFlagOffset < regTabPtr->tupNullWords) &&
- (nullWordOffset < tCheckOffset));
- Uint32 nullBits = tTupleHeader[nullWordOffset];
-
+ 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) {
- nullBits &= (~(1 << nullFlagBitOffset));
ljam();
- tTupleHeader[nullWordOffset] = nullBits;
+ BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
return updateFixedSizeTHManyWordNotNULL(inBuffer,
- attrDescriptor,
+ req_struct,
attrDes2);
} else {
- Uint32 newIndex = tInBufIndex + 1;
- if (newIndex <= tInBufLen) {
- nullBits |= (1 << nullFlagBitOffset);
+ 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);
ljam();
- tTupleHeader[nullWordOffset] = nullBits;
- tInBufIndex = newIndex;
+ req_struct->in_buf_index= newIndex;
return true;
} else {
ljam();
- terrorCode = ZAI_INCONSISTENCY_ERROR;
+ terrorCode= ZAI_INCONSISTENCY_ERROR;
return false;
- }//if
- }//if
-}//Dbtup::updateFixedSizeTHManyWordNULLable()
-
-bool
-Dbtup::updateVariableSizedAttr(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateVariableSizedAttr()
-
-bool
-Dbtup::updateVarSizeUnlimitedNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateVarSizeUnlimitedNotNULL()
-
-bool
-Dbtup::updateVarSizeUnlimitedNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateVarSizeUnlimitedNULLable()
-
-bool
-Dbtup::updateBigVarSizeNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateBigVarSizeNotNULL()
-
-bool
-Dbtup::updateBigVarSizeNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateBigVarSizeNULLable()
+ }
+ }
+}
bool
-Dbtup::updateSmallVarSizeNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::updateVarSizeNotNULL(Uint32* in_buffer,
+ KeyReqStruct *req_struct,
+ Uint32 attr_des2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateSmallVarSizeNotNULL()
+ Uint32 attr_descriptor, index_buf, in_buf_len, var_index, null_ind;
+ Uint32 vsize_in_bytes, 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) {
+ ljam();
+ 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 {
+ ljam();
+ terrorCode= ZNOT_NULL_ATTR;
+ return false;
+ }
+ } else {
+ ljam();
+ terrorCode= ZAI_INCONSISTENCY_ERROR;
+ return false;
+ }
+}
bool
-Dbtup::updateSmallVarSizeNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::updateVarSizeNULLable(Uint32* inBuffer,
+ KeyReqStruct *req_struct,
+ Uint32 attrDes2)
{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateSmallVarSizeNULLable()
+ 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) {
+ ljam();
+ 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) {
+ ljam();
+ 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 {
+ ljam();
+ terrorCode= ZAI_INCONSISTENCY_ERROR;
+ return false;
+ }
+ }
+}
bool
Dbtup::updateDynFixedSize(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct *req_struct,
Uint32 attrDes2)
{
ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateDynFixedSize()
-
-bool
-Dbtup::updateDynVarSizeUnlimited(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
- return false;
-}//Dbtup::updateDynVarSizeUnlimited()
-
-bool
-Dbtup::updateDynBigVarSize(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
+ terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
return false;
-}//Dbtup::updateDynBigVarSize()
+}
bool
-Dbtup::updateDynSmallVarSize(Uint32* inBuffer,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
+Dbtup::updateDynVarSize(Uint32* inBuffer,
+ KeyReqStruct *req_struct,
+ Uint32 attrDes2)
{
ljam();
- terrorCode = ZVAR_SIZED_NOT_SUPPORTED;
+ terrorCode= ZVAR_SIZED_NOT_SUPPORTED;
return false;
-}//Dbtup::updateDynSmallVarSize()
+}
Uint32
-Dbtup::read_pseudo(Uint32 attrId, Uint32* outBuffer){
+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 = operPtr.p->fragId >> 1; // remove "hash" bit
+ * outBuffer = fragptr.p->fragmentId;
return 1;
case AttributeHeader::FRAGMENT_MEMORY:
{
- Uint64 tmp = 0;
- tmp += fragptr.p->noOfPages;
- {
- /**
- * Each fragment is split into 2...get #pages from other as well
- */
- Uint32 twin = fragptr.p->fragmentId ^ 1;
- FragrecordPtr twinPtr;
- getFragmentrec(twinPtr, twin, tabptr.p);
- ndbrequire(twinPtr.p != 0);
- tmp += twinPtr.p->noOfPages;
- }
- tmp *= 32768;
+ Uint64 tmp= fragptr.p->noOfPages;
+ tmp*= 32768;
memcpy(outBuffer,&tmp,8);
}
return 2;
case AttributeHeader::ROW_SIZE:
- * outBuffer = tabptr.p->tupheadsize << 2;
+ * outBuffer = tabptr.p->m_offsets[MM].m_fix_header_size << 2;
return 1;
case AttributeHeader::ROW_COUNT:
case AttributeHeader::COMMIT_COUNT:
@@ -1039,7 +1143,13 @@ Dbtup::read_pseudo(Uint32 attrId, Uint32* outBuffer){
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;
@@ -1050,7 +1160,6 @@ Dbtup::read_pseudo(Uint32 attrId, Uint32* outBuffer){
outBuffer[2] = signal->theData[2];
outBuffer[3] = signal->theData[3];
return 4;
-
default:
return 0;
}
@@ -1058,27 +1167,25 @@ Dbtup::read_pseudo(Uint32 attrId, Uint32* outBuffer){
bool
Dbtup::readBitsNotNULL(Uint32* outBuffer,
+ KeyReqStruct* req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
Tablerec* const regTabPtr = tabptr.p;
Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
- Uint32 indexBuf = tOutBufIndex;
+ Uint32 bitCount =
+ AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
+ Uint32 indexBuf = req_struct->out_buf_index;
Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
- Uint32 maxRead = tMaxRead;
-
+ Uint32 maxRead = req_struct->max_read;
+ Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
if (newIndexBuf <= maxRead) {
ljam();
ahOut->setDataSize((bitCount + 31) >> 5);
- tOutBufIndex = newIndexBuf;
+ req_struct->out_buf_index = newIndexBuf;
- BitmaskImpl::getField(regTabPtr->tupNullWords,
- tTupleHeader+regTabPtr->tupNullIndex,
- pos,
- bitCount,
- outBuffer+indexBuf);
+ BitmaskImpl::getField(regTabPtr->m_offsets[MM].m_null_words, bits, pos,
+ bitCount, outBuffer+indexBuf);
return true;
} else {
@@ -1090,37 +1197,33 @@ Dbtup::readBitsNotNULL(Uint32* outBuffer,
bool
Dbtup::readBitsNULLable(Uint32* outBuffer,
+ KeyReqStruct* req_struct,
AttributeHeader* ahOut,
- Uint32 attrDescriptor,
Uint32 attrDes2)
{
Tablerec* const regTabPtr = tabptr.p;
Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ Uint32 bitCount =
+ AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
- Uint32 indexBuf = tOutBufIndex;
+ Uint32 indexBuf = req_struct->out_buf_index;
Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
- Uint32 maxRead = tMaxRead;
+ Uint32 maxRead = req_struct->max_read;
+ Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
- if(BitmaskImpl::get(regTabPtr->tupNullWords,
- tTupleHeader+regTabPtr->tupNullIndex,
- pos))
+ if(BitmaskImpl::get(regTabPtr->m_offsets[MM].m_null_words, bits, pos))
{
ljam();
ahOut->setNULL();
return true;
}
-
if (newIndexBuf <= maxRead) {
ljam();
ahOut->setDataSize((bitCount + 31) >> 5);
- tOutBufIndex = newIndexBuf;
- BitmaskImpl::getField(regTabPtr->tupNullWords,
- tTupleHeader+regTabPtr->tupNullIndex,
- pos+1,
- bitCount,
- outBuffer+indexBuf);
+ req_struct->out_buf_index = newIndexBuf;
+ BitmaskImpl::getField(regTabPtr->m_offsets[MM].m_null_words, bits, pos+1,
+ bitCount, outBuffer+indexBuf);
return true;
} else {
ljam();
@@ -1131,26 +1234,25 @@ Dbtup::readBitsNULLable(Uint32* outBuffer,
bool
Dbtup::updateBitsNotNULL(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct* req_struct,
Uint32 attrDes2)
{
Tablerec* const regTabPtr = tabptr.p;
- Uint32 indexBuf = tInBufIndex;
- Uint32 inBufLen = tInBufLen;
+ 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(attrDescriptor);
+ 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->tupNullWords,
- tTupleHeader+regTabPtr->tupNullIndex,
- pos,
- bitCount,
- inBuffer+indexBuf+1);
- tInBufIndex = newIndex;
+ BitmaskImpl::setField(regTabPtr->m_offsets[MM].m_null_words, bits, pos,
+ bitCount, inBuffer+indexBuf+1);
+ req_struct->in_buf_index = newIndex;
return true;
} else {
ljam();
@@ -1167,38 +1269,34 @@ Dbtup::updateBitsNotNULL(Uint32* inBuffer,
bool
Dbtup::updateBitsNULLable(Uint32* inBuffer,
- Uint32 attrDescriptor,
+ KeyReqStruct* req_struct,
Uint32 attrDes2)
{
Tablerec* const regTabPtr = tabptr.p;
- AttributeHeader ahIn(inBuffer[tInBufIndex]);
- Uint32 indexBuf = tInBufIndex;
+ Uint32 indexBuf = req_struct->in_buf_index;
+ AttributeHeader ahIn(inBuffer[indexBuf]);
Uint32 nullIndicator = ahIn.isNULL();
Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
- Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ Uint32 bitCount =
+ AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
+ Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
if (!nullIndicator) {
- BitmaskImpl::clear(regTabPtr->tupNullWords,
- tTupleHeader+regTabPtr->tupNullIndex,
- pos);
- BitmaskImpl::setField(regTabPtr->tupNullWords,
- tTupleHeader+regTabPtr->tupNullIndex,
- pos+1,
- bitCount,
- inBuffer+indexBuf+1);
+ 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);
- tInBufIndex = newIndex;
+ req_struct->in_buf_index = newIndex;
return true;
} else {
- Uint32 newIndex = tInBufIndex + 1;
- if (newIndex <= tInBufLen) {
+ Uint32 newIndex = indexBuf + 1;
+ if (newIndex <= req_struct->in_buf_len)
+ {
ljam();
- BitmaskImpl::set(regTabPtr->tupNullWords,
- tTupleHeader+regTabPtr->tupNullIndex,
- pos);
+ BitmaskImpl::set(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
- tInBufIndex = newIndex;
+ req_struct->in_buf_index = newIndex;
return true;
} else {
ljam();
@@ -1207,3 +1305,325 @@ Dbtup::updateBitsNULLable(Uint32* inBuffer,
}//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) {
+ ljam();
+ if (charsetFlag) {
+ ljam();
+ Tablerec* regTabPtr = tabptr.p;
+ Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
+ Uint32 bytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
+ ndbrequire(i < regTabPtr->noOfCharsets);
+ // not const in MySQL
+ CHARSET_INFO* cs = regTabPtr->charsetArray[i];
+ int not_used;
+ const char* ssrc = (const char*)&inBuffer[indexBuf + 1];
+ Uint32 lb, len;
+ if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
+ ljam();
+ terrorCode = ZINVALID_CHAR_FORMAT;
+ return false;
+ }
+ // fast fix bug#7340
+ if (typeId != NDB_TYPE_TEXT &&
+ (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, &not_used) != len) {
+ ljam();
+ terrorCode = ZINVALID_CHAR_FORMAT;
+ return false;
+ }
+ }
+ req_struct->in_buf_index= newIndex;
+ MEMCOPY_NO_WORDS(&tuple_header[updateOffset],
+ &inBuffer[indexBuf + 1],
+ noOfWords);
+ return true;
+ } else {
+ ljam();
+ terrorCode= ZNOT_NULL_ATTR;
+ return false;
+ }
+ } else {
+ ljam();
+ 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) {
+ ljam();
+ 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);
+ ljam();
+ req_struct->in_buf_index= newIndex;
+ return true;
+ } else {
+ ljam();
+ 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_bytes, 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) {
+ ljam();
+ 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 {
+ ljam();
+ terrorCode= ZNOT_NULL_ATTR;
+ return false;
+ }
+ } else {
+ ljam();
+ terrorCode= ZAI_INCONSISTENCY_ERROR;
+ 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) {
+ ljam();
+ 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) {
+ ljam();
+ 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 {
+ ljam();
+ 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) {
+ ljam();
+ 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 {
+ ljam();
+ 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))
+ {
+ ljam();
+ ahOut->setNULL();
+ return true;
+ }
+
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ 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 {
+ ljam();
+ 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 {
+ ljam();
+ terrorCode = ZNOT_NULL_ATTR;
+ return false;
+ }//if
+ } else {
+ ljam();
+ 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)
+ {
+ ljam();
+ BitmaskImpl::set(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
+
+ req_struct->in_buf_index = newIndex;
+ return true;
+ } else {
+ ljam();
+ 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
index 396404faa8c..b5819ce268c 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
@@ -37,27 +37,61 @@ Dbtup::execACC_SCANREQ(Signal* signal)
TablerecPtr tablePtr;
tablePtr.i = req->tableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
- FragrecordPtr fragPtr[2];
- Uint32 fragId = req->fragmentNo << 1;
- fragPtr[0].i = fragPtr[1].i = RNIL;
- getFragmentrec(fragPtr[0], fragId | 0, tablePtr.p);
- getFragmentrec(fragPtr[1], fragId | 1, tablePtr.p);
- ndbrequire(fragPtr[0].i != RNIL && fragPtr[1].i != RNIL);
- Fragrecord& frag = *fragPtr[0].p;
+ FragrecordPtr fragPtr;
+ Uint32 fragId = req->fragmentNo;
+ fragPtr.i = RNIL;
+ getFragmentrec(fragPtr, fragId, tablePtr.p);
+ ndbrequire(fragPtr.i != RNIL);
+ Fragrecord& frag = *fragPtr.p;
// seize from pool and link to per-fragment list
- if (! frag.m_scanList.seize(scanPtr)) {
- jam();
- break;
+
+ Uint32 bits= 0;
+ if(frag.m_lcp_scan_op != RNIL)
+ {
+ bits |= ScanOp::SCAN_LCP;
+ ndbrequire(frag.m_lcp_scan_op == c_lcp_scan_op);
+ c_scanOpPool.getPtr(scanPtr, frag.m_lcp_scan_op);
+ }
+ else
+ {
+ LocalDLList<ScanOp> list(c_scanOpPool, frag.m_scanList);
+ if (! list.seize(scanPtr))
+ {
+ jam();
+ break;
+ }
}
new (scanPtr.p) ScanOp();
ScanOp& scan = *scanPtr.p;
scan.m_state = ScanOp::First;
+ // TODO scan disk only if any scanned attribute on disk
+
+ if(! (bits & ScanOp::SCAN_LCP))
+ {
+ /**
+ * Remove this until disk scan has been implemented
+ */
+ if(tablePtr.p->m_attributes[DD].m_no_of_fixsize > 0 ||
+ tablePtr.p->m_attributes[DD].m_no_of_varsize > 0)
+ {
+ bits |= ScanOp::SCAN_DD;
+
+ if (tablePtr.p->m_attributes[DD].m_no_of_varsize > 0)
+ bits |= ScanOp::SCAN_DD_VS;
+ }
+ }
+
+ if(tablePtr.p->m_attributes[MM].m_no_of_varsize)
+ {
+ bits |= ScanOp::SCAN_VS;
+ }
+
+ 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[0] = fragPtr[0].i;
- scan.m_fragPtrI[1] = fragPtr[1].i;
+ scan.m_fragPtrI = fragPtr.i;
scan.m_transId1 = req->transId1;
scan.m_transId2 = req->transId2;
// conf
@@ -67,9 +101,11 @@ Dbtup::execACC_SCANREQ(Signal* signal)
conf->flag = AccScanConf::ZNOT_EMPTY_FRAGMENT;
sendSignal(req->senderRef, GSN_ACC_SCANCONF, signal,
AccScanConf::SignalLength, JBB);
+
return;
} while (0);
- if (scanPtr.i != RNIL) {
+ if (scanPtr.i != RNIL)
+ {
jam();
releaseScanOp(scanPtr);
}
@@ -87,10 +123,6 @@ Dbtup::execNEXT_SCANREQ(Signal* signal)
ScanOpPtr scanPtr;
c_scanOpPool.getPtr(scanPtr, req->accPtr);
ScanOp& scan = *scanPtr.p;
- FragrecordPtr fragPtr;
- fragPtr.i = scan.m_fragPtrI[0];
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- Fragrecord& frag = *fragPtr.p;
switch (req->scanFlag) {
case NextScanReq::ZSCAN_NEXT:
jam();
@@ -138,7 +170,7 @@ Dbtup::execACC_CHECK_SCAN(Signal* signal)
c_scanOpPool.getPtr(scanPtr, req->accPtr);
ScanOp& scan = *scanPtr.p;
FragrecordPtr fragPtr;
- fragPtr.i = scan.m_fragPtrI[0];
+ fragPtr.i = scan.m_fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
Fragrecord& frag = *fragPtr.p;
if (req->checkLcpStop == AccCheckScan::ZCHECK_LCP_STOP) {
@@ -151,11 +183,11 @@ Dbtup::execACC_CHECK_SCAN(Signal* signal)
}
if (scan.m_state == ScanOp::First) {
jam();
- scanFirst(signal, scanPtr);
+ scanFirst(signal, fragPtr.p, scanPtr);
}
if (scan.m_state == ScanOp::Next) {
jam();
- scanNext(signal, scanPtr);
+ scanNext(signal, fragPtr.p, scanPtr);
}
if (scan.m_state == ScanOp::Locked) {
jam();
@@ -163,9 +195,8 @@ Dbtup::execACC_CHECK_SCAN(Signal* signal)
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = (Uint32)-1; // no lock returned
- conf->fragId = frag.fragmentId | pos.m_fragBit;
- conf->localKey[0] = (pos.m_pageId << MAX_TUPLES_BITS) |
- (pos.m_tupleNo << 1);
+ conf->fragId = frag.fragmentId;
+ conf->localKey[0] = pos.m_key.ref();
conf->localKey[1] = 0;
conf->localKeyLength = 1;
unsigned signalLength = 6;
@@ -192,101 +223,118 @@ Dbtup::execACC_CHECK_SCAN(Signal* signal)
}
void
-Dbtup::scanFirst(Signal* signal, ScanOpPtr scanPtr)
+Dbtup::scanFirst(Signal*, Fragrecord* fragPtrP, ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
// set to first fragment, first page, first tuple
+ const Uint32 first_page_idx = scan.m_bits & ScanOp::SCAN_VS ? 1 : 0;
PagePos& pos = scan.m_scanPos;
- pos.m_fragId = scan.m_fragId;
- pos.m_fragBit = 0;
- pos.m_pageId = 0;
- pos.m_tupleNo = 0;
+ pos.m_key.m_page_no = 0;
+ pos.m_key.m_page_idx = first_page_idx;
// just before
pos.m_match = false;
// let scanNext() do the work
scan.m_state = ScanOp::Next;
+
+ if (scan.m_bits & ScanOp::SCAN_DD)
+ {
+ pos.m_extent_info_ptr_i =
+ fragPtrP->m_disk_alloc_info.m_extent_list.firstItem;
+ }
}
-// TODO optimize this + index build
void
-Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr)
+Dbtup::scanNext(Signal* signal, Fragrecord* fragPtrP, ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
PagePos& pos = scan.m_scanPos;
+ Uint32 bits = scan.m_bits;
+ Local_key& key = pos.m_key;
TablerecPtr tablePtr;
tablePtr.i = scan.m_tableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ Fragrecord& frag = *fragPtrP;
+ const Uint32 first_page_idx = bits & ScanOp::SCAN_VS ? 1 : 0;
while (true) {
// TODO time-slice here after X loops
jam();
- // get fragment
- if (pos.m_fragBit == 2) {
- jam();
- scan.m_state = ScanOp::Last;
- break;
- }
- ndbrequire(pos.m_fragBit <= 1);
- FragrecordPtr fragPtr;
- fragPtr.i = scan.m_fragPtrI[pos.m_fragBit];
- ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- Fragrecord& frag = *fragPtr.p;
// get page
PagePtr pagePtr;
- if (pos.m_pageId >= frag.noOfPages) {
+ if (key.m_page_no >= frag.noOfPages) {
jam();
- pos.m_fragBit++;
- pos.m_pageId = 0;
- pos.m_tupleNo = 0;
- pos.m_match = false;
- continue;
+ scan.m_state = ScanOp::Last;
+ break;
}
- Uint32 realPageId = getRealpid(fragPtr.p, pos.m_pageId);
+ Uint32 realPageId = getRealpid(fragPtrP, key.m_page_no);
pagePtr.i = realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- const Uint32 pageState = pagePtr.p->pageWord[ZPAGE_STATE_POS];
- if (pageState != ZTH_MM_FREE &&
- pageState != ZTH_MM_FULL) {
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ Uint32 pageState = pagePtr.p->page_state;
+ // skip empty page
+ if (pageState == ZEMPTY_MM) {
jam();
- pos.m_pageId++;
- pos.m_tupleNo = 0;
+ key.m_page_no++;
+ key.m_page_idx = first_page_idx;
pos.m_match = false;
continue;
}
// get next tuple
- if (pos.m_match)
- pos.m_tupleNo++;
- pos.m_match = true;
- const Uint32 tupheadsize = tablePtr.p->tupheadsize;
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + pos.m_tupleNo * tupheadsize;
- if (pageOffset + tupheadsize > ZWORDS_ON_PAGE) {
- jam();
- pos.m_pageId++;
- pos.m_tupleNo = 0;
- pos.m_match = false;
- continue;
- }
- // skip over free tuple
- bool isFree = false;
- if (pageState == ZTH_MM_FREE) {
- jam();
- if ((pagePtr.p->pageWord[pageOffset] >> 16) == tupheadsize) {
- Uint32 nextTuple = pagePtr.p->pageWord[ZFREELIST_HEADER_POS] >> 16;
- while (nextTuple != 0) {
+ const Tuple_header* th = 0;
+ if (! (bits & ScanOp::SCAN_VS)) {
+ Uint32 tupheadsize = tablePtr.p->m_offsets[MM].m_fix_header_size;
+ if (pos.m_match)
+ key.m_page_idx += tupheadsize;
+ pos.m_match = true;
+ if (key.m_page_idx + tupheadsize > Fix_page::DATA_WORDS) {
+ jam();
+ key.m_page_no++;
+ key.m_page_idx = first_page_idx;
+ pos.m_match = false;
+ continue;
+ }
+ th = (Tuple_header*)&pagePtr.p->m_data[key.m_page_idx];
+ // skip over free tuple
+ if (th->m_header_bits & Tuple_header::FREE) {
jam();
- if (nextTuple == pageOffset) {
- jam();
- isFree = true;
- break;
- }
- nextTuple = pagePtr.p->pageWord[nextTuple] & 0xffff;
- }
+ continue;
}
+ } else {
+ Var_page* page_ptr = (Var_page*)pagePtr.p;
+ if (pos.m_match)
+ key.m_page_idx += 1;
+ pos.m_match = true;
+ if (key.m_page_idx >= page_ptr->high_index) {
+ jam();
+ key.m_page_no++;
+ key.m_page_idx = first_page_idx;
+ pos.m_match = false;
+ continue;
+ }
+
+ Uint32 len= page_ptr->get_entry_len(key.m_page_idx);
+ if (len == 0)
+ {
+ // skip empty slot or
+ jam();
+ continue;
+ }
+ if(len & Var_page::CHAIN)
+ {
+ // skip varpart chain
+ jam();
+ continue;
+ }
+ th = (Tuple_header*)page_ptr->get_ptr(key.m_page_idx);
}
- if (isFree) {
- jam();
+
+ if(bits & ScanOp::SCAN_LCP &&
+ th->m_header_bits & Tuple_header::LCP_SKIP)
+ {
+ /**
+ * Clear it so that it will show up in next LCP
+ */
+ ((Tuple_header*)th)->m_header_bits &= ~(Uint32)Tuple_header::LCP_SKIP;
continue;
}
- // TODO check for operation and return latest in own tx
scan.m_state = ScanOp::Locked;
break;
}
@@ -302,6 +350,7 @@ Dbtup::scanClose(Signal* signal, ScanOpPtr scanPtr)
unsigned signalLength = 3;
sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
+
releaseScanOp(scanPtr);
}
@@ -309,7 +358,46 @@ void
Dbtup::releaseScanOp(ScanOpPtr& scanPtr)
{
FragrecordPtr fragPtr;
- fragPtr.i = scanPtr.p->m_fragPtrI[0];
+ fragPtr.i = scanPtr.p->m_fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
- fragPtr.p->m_scanList.release(scanPtr);
+
+ if(! (scanPtr.p->m_bits & ScanOp::SCAN_LCP))
+ {
+ LocalDLList<ScanOp> list(c_scanOpPool, fragPtr.p->m_scanList);
+ list.release(scanPtr);
+ }
+ else
+ {
+ ndbrequire(fragPtr.p->m_lcp_scan_op == scanPtr.i);
+ fragPtr.p->m_lcp_scan_op = RNIL;
+ }
+}
+
+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);
+
+ scanFirst(signal, fragPtr.p, 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
index 3b957688a1c..d48a83c8794 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp
@@ -35,14 +35,14 @@ void Dbtup::execSTORED_PROCREQ(Signal* signal)
TablerecPtr regTabPtr;
ljamEntry();
regOperPtr.i = signal->theData[0];
- ptrCheckGuard(regOperPtr, cnoOfOprec, operationrec);
+ c_operation_pool.getPtr(regOperPtr);
regTabPtr.i = signal->theData[1];
ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
Uint32 requestInfo = signal->theData[3];
-
- ndbrequire(regOperPtr.p->transstate == IDLE ||
- ((regOperPtr.p->transstate == ERROR_WAIT_STORED_PROCREQ) &&
+ 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) {
@@ -81,10 +81,10 @@ void Dbtup::deleteScanProcedure(Signal* signal,
c_storedProcPool.release(storedPtr);
freeAttrinbufrec(firstAttrinbuf);
regOperPtr->currentAttrinbufLen = 0;
- regOperPtr->transstate = IDLE;
+ set_trans_state(regOperPtr, TRANS_IDLE);
signal->theData[0] = regOperPtr->userpointer;
signal->theData[1] = storedProcId;
- sendSignal(regOperPtr->userblockref, GSN_STORED_PROCCONF, signal, 2, JBB);
+ sendSignal(DBLQH_REF, GSN_STORED_PROCCONF, signal, 2, JBB);
}//Dbtup::deleteScanProcedure()
void Dbtup::scanProcedure(Signal* signal,
@@ -105,17 +105,17 @@ void Dbtup::scanProcedure(Signal* signal,
storedPtr.p->storedProcLength = lenAttrInfo;
storedPtr.p->storedLinkFirst = RNIL;
storedPtr.p->storedLinkLast = RNIL;
- regOperPtr->transstate = WAIT_STORED_PROCEDURE_ATTR_INFO;
+ set_trans_state(regOperPtr, TRANS_WAIT_STORED_PROCEDURE_ATTR_INFO);
regOperPtr->attrinbufLen = lenAttrInfo;
regOperPtr->currentAttrinbufLen = 0;
- regOperPtr->pageOffset = storedPtr.i;
+ regOperPtr->storedProcPtr = storedPtr.i;
}//Dbtup::scanProcedure()
void Dbtup::copyProcedure(Signal* signal,
TablerecPtr regTabPtr,
Operationrec* regOperPtr)
{
- Uint32 TnoOfAttributes = regTabPtr.p->noOfAttr;
+ Uint32 TnoOfAttributes = regTabPtr.p->m_no_of_attributes;
scanProcedure(signal,
regOperPtr,
TnoOfAttributes);
@@ -126,21 +126,23 @@ void Dbtup::copyProcedure(Signal* signal,
length++;
if (length == 24) {
ljam();
- ndbrequire(storedProcedureAttrInfo(signal, regOperPtr, length, 1, true));
+ ndbrequire(storedProcedureAttrInfo(signal, regOperPtr,
+ signal->theData+1, length, true));
length = 0;
}//if
}//for
if (length != 0) {
ljam();
- ndbrequire(storedProcedureAttrInfo(signal, regOperPtr, length, 1, true));
+ 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,
- Uint32 firstWord,
bool copyProcedure)
{
AttrbufrecPtr regAttrPtr;
@@ -182,7 +184,7 @@ bool Dbtup::storedProcedureAttrInfo(Signal* signal,
regAttrPtr.p->attrbuf[ZBUF_DATA_LEN] = length;
MEMCOPY_NO_WORDS(&regAttrPtr.p->attrbuf[0],
- &signal->theData[firstWord],
+ data,
length);
if (regOperPtr->currentAttrinbufLen < regOperPtr->attrinbufLen) {
@@ -196,7 +198,7 @@ bool Dbtup::storedProcedureAttrInfo(Signal* signal,
}//if
StoredProcPtr storedPtr;
- c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->pageOffset);
+ c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->storedProcPtr);
ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
regOperPtr->currentAttrinbufLen = 0;
@@ -204,10 +206,10 @@ bool Dbtup::storedProcedureAttrInfo(Signal* signal,
storedPtr.p->storedLinkLast = regOperPtr->lastAttrinbufrec;
regOperPtr->firstAttrinbufrec = RNIL;
regOperPtr->lastAttrinbufrec = RNIL;
- regOperPtr->transstate = IDLE;
+ set_trans_state(regOperPtr, TRANS_IDLE);
signal->theData[0] = regOperPtr->userpointer;
signal->theData[1] = storedPtr.i;
- sendSignal(regOperPtr->userblockref, GSN_STORED_PROCCONF, signal, 2, JBB);
+ sendSignal(DBLQH_REF, GSN_STORED_PROCCONF, signal, 2, JBB);
return true;
}//Dbtup::storedProcedureAttrInfo()
@@ -215,16 +217,16 @@ void Dbtup::storedSeizeAttrinbufrecErrorLab(Signal* signal,
Operationrec* regOperPtr)
{
StoredProcPtr storedPtr;
- c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->pageOffset);
+ c_storedProcPool.getPtr(storedPtr, regOperPtr->storedProcPtr);
ndbrequire(storedPtr.p->storedCode == ZSCAN_PROCEDURE);
storedPtr.p->storedLinkFirst = regOperPtr->firstAttrinbufrec;
regOperPtr->firstAttrinbufrec = RNIL;
regOperPtr->lastAttrinbufrec = RNIL;
- regOperPtr->transstate = ERROR_WAIT_STORED_PROCREQ;
+ set_trans_state(regOperPtr, TRANS_ERROR_WAIT_STORED_PROCREQ);
signal->theData[0] = regOperPtr->userpointer;
signal->theData[1] = ZSTORED_SEIZE_ATTRINBUFREC_ERROR;
- signal->theData[2] = regOperPtr->pageOffset;
- sendSignal(regOperPtr->userblockref, GSN_STORED_PROCREF, signal, 3, JBB);
+ 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/DbtupSystemRestart.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
deleted file mode 100644
index 35d1b75e573..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
+++ /dev/null
@@ -1,1021 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#define DBTUP_C
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-#include <signaldata/EventReport.hpp>
-#include <signaldata/FsConf.hpp>
-#include <signaldata/FsRef.hpp>
-
-#define ljam() { jamLine(26000 + __LINE__); }
-#define ljamEntry() { jamEntryLine(26000 + __LINE__); }
-
-/* **************************************************************** */
-/* ********************* SYSTEM RESTART MANAGER ******************* */
-/* **************************************************************** */
-/***************************************************************/
-/* CHECK RESTART STATE AND SET NEW STATE CALLED IN OPEN, */
-/* READ AND COPY STATES */
-/***************************************************************/
-void Dbtup::execTUP_SRREQ(Signal* signal)
-{
- RestartInfoRecordPtr riPtr;
- PendingFileOpenInfoPtr pfoiPtr;
-
- ljamEntry();
- Uint32 userPtr = signal->theData[0];
- Uint32 userBlockref = signal->theData[1];
- Uint32 tableId = signal->theData[2];
- Uint32 fragId = signal->theData[3];
- Uint32 checkpointNumber = signal->theData[4];
-
- seizeRestartInfoRecord(riPtr);
-
- riPtr.p->sriUserptr = userPtr;
- riPtr.p->sriBlockref = userBlockref;
- riPtr.p->sriState = OPENING_DATA_FILE;
- riPtr.p->sriCheckpointVersion = checkpointNumber;
- riPtr.p->sriFragid = fragId;
- riPtr.p->sriTableId = tableId;
-
- /* OPEN THE DATA FILE IN THE FOLLOWING FORM */
- /* D5/DBTUP/T<TABID>/F<FRAGID>/S<CHECKPOINT_NUMBER>.DATA */
- Uint32 fileType = 1; /* VERSION */
- fileType = (fileType << 8) | 0; /* .DATA */
- fileType = (fileType << 8) | 5; /* D5 */
- fileType = (fileType << 8) | 0xff; /* DON'T USE P DIRECTORY LEVEL */
- Uint32 fileFlag = 0; /* READ ONLY */
-
- seizePendingFileOpenInfoRecord(pfoiPtr);
- pfoiPtr.p->pfoOpenType = LCP_DATA_FILE_READ;
- pfoiPtr.p->pfoRestartInfoP = riPtr.i;
-
- signal->theData[0] = cownref;
- signal->theData[1] = pfoiPtr.i;
- signal->theData[2] = tableId;
- signal->theData[3] = fragId;
- signal->theData[4] = checkpointNumber;
- signal->theData[5] = fileType;
- signal->theData[6] = fileFlag;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
- return;
-}//Dbtup::execTUP_SRREQ()
-
-void Dbtup::seizeRestartInfoRecord(RestartInfoRecordPtr& riPtr)
-{
- riPtr.i = cfirstfreeSri;
- ptrCheckGuard(riPtr, cnoOfRestartInfoRec, restartInfoRecord);
- cfirstfreeSri = riPtr.p->sriNextRec;
- riPtr.p->sriNextRec = RNIL;
-}//Dbtup::seizeRestartInfoRecord()
-
-void Dbtup::rfrReadRestartInfoLab(Signal* signal, RestartInfoRecordPtr riPtr)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
-
- seizeDiskBufferSegmentRecord(dbsiPtr);
- riPtr.p->sriDataBufferSegmentP = dbsiPtr.i;
- Uint32 retPageRef = RNIL;
- Uint32 noAllocPages = 1;
- Uint32 noOfPagesAllocated;
- {
- /**
- * Use low pages for 0-pages during SR
- * bitmask of free pages is kept in c_sr_free_page_0
- */
- Uint32 tmp = c_sr_free_page_0;
- for(Uint32 i = 1; i<(1+MAX_PARALLELL_TUP_SRREQ); i++){
- if(tmp & (1 << i)){
- retPageRef = i;
- c_sr_free_page_0 = tmp & (~(1 << i));
- break;
- }
- }
- ndbrequire(retPageRef != RNIL);
- }
-
- dbsiPtr.p->pdxDataPage[0] = retPageRef;
- dbsiPtr.p->pdxNumDataPages = 1;
- dbsiPtr.p->pdxFilePage = 0;
- rfrReadNextDataSegment(signal, riPtr, dbsiPtr);
- dbsiPtr.p->pdxOperation = CHECKPOINT_DATA_READ_PAGE_ZERO;
-}//Dbtup::rfrReadRestartInfoLab()
-
-/***************************************************************/
-/* THE RESTART INFORMATION IS NOW READ INTO THE DATA BUFFER */
-/* USE THE RESTART INFORMATION TO INITIATE THE RESTART RECORD */
-/***************************************************************/
-void
-Dbtup::rfrInitRestartInfoLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr)
-{
- Uint32 TzeroDataPage[64];
- Uint32 Ti;
- FragrecordPtr regFragPtr;
- LocalLogInfoPtr lliPtr;
- PagePtr pagePtr;
- RestartInfoRecordPtr riPtr;
- TablerecPtr regTabPtr;
-
- riPtr.i = dbsiPtr.p->pdxRestartInfoP;
- ptrCheckGuard(riPtr, cnoOfRestartInfoRec, restartInfoRecord);
-
- regTabPtr.i = riPtr.p->sriTableId;
- ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
-
- Uint32 fragId = riPtr.p->sriFragid;
- getFragmentrec(regFragPtr, fragId, regTabPtr.p);
- riPtr.p->sriFragP = regFragPtr.i;
-
- /* ----- PAGE ALLOCATION --- */
- /* ALLOCATE PAGES TO FRAGMENT, INSERT THEM INTO PAGE RANGE TABLE AND */
- /* ALSO CONVERT THEM INTO EMPTY PAGES AND INSERT THEM INTO THE EMPTY LIST */
- /* OF THE FRAGMENT. SET ALL LISTS OF FREE PAGES TO RNIL */
-
- ndbrequire(cfirstfreerange != RNIL);
- pagePtr.i = dbsiPtr.p->pdxDataPage[0];
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- for (Ti = 0; Ti < 63; Ti++) {
- /***************************************************************/
- // Save Important content from Page zero in stack variable so
- // that we can immediately release page zero.
- /***************************************************************/
- TzeroDataPage[Ti] = pagePtr.p->pageWord[Ti];
- }//for
- /************************************************************************/
- /* NOW WE DON'T NEED THE RESTART INFO BUFFER PAGE ANYMORE */
- /* LETS REMOVE IT AND REUSE THE SEGMENT FOR REAL DATA PAGES */
- /* REMOVE ONE PAGE ONLY, PAGEP IS ALREADY SET TO THE RESTART INFO PAGE */
- /************************************************************************/
- {
- ndbrequire(pagePtr.i > 0 && pagePtr.i <= MAX_PARALLELL_TUP_SRREQ);
- c_sr_free_page_0 |= (1 << pagePtr.i);
- }
-
- Uint32 undoFileVersion = TzeroDataPage[ZSRI_UNDO_FILE_VER];
- lliPtr.i = (undoFileVersion << 2) + (regTabPtr.i & 0x3);
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- riPtr.p->sriLocalLogInfoP = lliPtr.i;
-
- ndbrequire(regFragPtr.p->fragTableId == regTabPtr.i);
- ndbrequire(regFragPtr.p->fragmentId == fragId);
-
- regFragPtr.p->fragStatus = SYSTEM_RESTART;
-
- regFragPtr.p->noCopyPagesAlloc = TzeroDataPage[ZSRI_NO_COPY_PAGES_ALLOC];
-
- riPtr.p->sriCurDataPageFromBuffer = 0;
- riPtr.p->sriNumDataPages = TzeroDataPage[ZSRI_NO_OF_FRAG_PAGES_POS];
-
- ndbrequire(riPtr.p->sriNumDataPages >= regFragPtr.p->noOfPages);
- const Uint32 pageCount = riPtr.p->sriNumDataPages - regFragPtr.p->noOfPages;
- if(pageCount > 0){
- Uint32 noAllocPages = allocFragPages(regFragPtr.p, pageCount);
- ndbrequireErr(noAllocPages == pageCount, NDBD_EXIT_SR_OUT_OF_DATAMEMORY);
- }//if
- ndbrequire(getNoOfPages(regFragPtr.p) == riPtr.p->sriNumDataPages);
-
-/***************************************************************/
-// Set the variables on fragment record which might have been
-// affected by allocFragPages.
-/***************************************************************/
-
- regFragPtr.p->emptyPrimPage = TzeroDataPage[ZSRI_EMPTY_PRIM_PAGE];
- regFragPtr.p->thFreeFirst = TzeroDataPage[ZSRI_TH_FREE_FIRST];
- regFragPtr.p->thFreeCopyFirst = TzeroDataPage[ZSRI_TH_FREE_COPY_FIRST];
-
-/***************************************************************/
-/* THE RESTART INFORMATION IS NOW READ INTO THE DATA BUFFER */
-/* USE THE RESTART INFORMATION TO INITIATE THE FRAGMENT */
-/***************************************************************/
- /**
- * IF THIS UNDO FILE IS NOT OPEN, IT WILL BE OPENED HERE AND THE EXECUTION
- * WILL CONTINUE WHEN THE FSOPENCONF IS ENTERED.
- * IF IT'S ALREADY IN USE THE EXECUTION WILL CONTINUE BY A
- * CONTINUE B SIGNAL
- */
- if (lliPtr.p->lliActiveLcp == 0) {
- PendingFileOpenInfoPtr pfoiPtr;
- ljam();
-/***************************************************************/
-/* OPEN THE UNDO FILE FOR READ */
-/* THE FILE HANDLE WILL BE SET IN THE LOCAL_LOG_INFO_REC */
-/* UPON FSOPENCONF */
-/***************************************************************/
- cnoOfLocalLogInfo++;
- /* F_LEVEL NOT USED */
- Uint32 fileType = 1; /* VERSION */
- fileType = (fileType << 8) | 2; /* .LOCLOG */
- fileType = (fileType << 8) | 6; /* D6 */
- fileType = (fileType << 8) | 0xff; /* DON'T USE P DIRECTORY LEVEL */
- Uint32 fileFlag = 0; /* READ ONLY */
-
- seizePendingFileOpenInfoRecord(pfoiPtr);
- pfoiPtr.p->pfoOpenType = LCP_UNDO_FILE_READ;
- pfoiPtr.p->pfoRestartInfoP = riPtr.i;
-
- signal->theData[0] = cownref;
- signal->theData[1] = pfoiPtr.i;
- signal->theData[2] = lliPtr.i;
- signal->theData[3] = 0xFFFFFFFF;
- signal->theData[4] = undoFileVersion;
- signal->theData[5] = fileType;
- signal->theData[6] = fileFlag;
- sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, 7, JBA);
-
- lliPtr.p->lliPrevRecordId = 0;
- lliPtr.p->lliActiveLcp = 1;
- lliPtr.p->lliNumFragments = 1;
- } else {
- ljam();
- signal->theData[0] = ZCONT_LOAD_DP;
- signal->theData[1] = riPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- lliPtr.p->lliNumFragments++;
- }//if
- /* RETAIN THE HIGH- AND LOWSCORE ID:S OF THE LOGRECORD POSITIONS. WE HAVE TO EXECUTE THE */
- /* UNDO LOG BETWEEN THE END AND START RECORDS FOR ALL RECORDS THAT INCLUDE FRAGMENTS OF */
- /* THE RIGHT CHECKPOINT VERSION TO COMPLETE THE OPERATION WE HAVE TO RUN ALL LOGS THAT */
- /* HAS THE NUMBER OF LCP ELEMENT GREATER THAN 0, I.E. IS INCLUDED. */
- if (TzeroDataPage[ZSRI_UNDO_LOG_END_REC_ID] > lliPtr.p->lliPrevRecordId) {
- ljam();
- lliPtr.p->lliPrevRecordId = TzeroDataPage[ZSRI_UNDO_LOG_END_REC_ID];
- lliPtr.p->lliEndPageId = TzeroDataPage[ZSRI_UNDO_LOG_END_PAGE_ID];
- }//if
- return;
-}//Dbtup::rfrInitRestartInfoLab()
-
-/***************************************************************/
-/* LOAD THE NEXT DATA PAGE SEGMENT INTO MEMORY */
-/***************************************************************/
-void Dbtup::rfrLoadDataPagesLab(Signal* signal, RestartInfoRecordPtr riPtr, DiskBufferSegmentInfoPtr dbsiPtr)
-{
- FragrecordPtr regFragPtr;
-
- if (riPtr.p->sriCurDataPageFromBuffer >= riPtr.p->sriNumDataPages) {
- ljam();
- rfrCompletedLab(signal, riPtr);
- return;
- }//if
- Uint32 startPage = riPtr.p->sriCurDataPageFromBuffer;
- Uint32 endPage;
- if ((startPage + ZDB_SEGMENT_SIZE) < riPtr.p->sriNumDataPages) {
- ljam();
- endPage = startPage + ZDB_SEGMENT_SIZE;
- } else {
- ljam();
- endPage = riPtr.p->sriNumDataPages;
- }//if
- regFragPtr.i = riPtr.p->sriFragP;
- ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
- ndbrequire((endPage - startPage) <= 16);
- Uint32 i = 0;
- for (Uint32 pageId = startPage; pageId < endPage; pageId++) {
- ljam();
- dbsiPtr.p->pdxDataPage[i] = getRealpid(regFragPtr.p, pageId);
- i++;
- }//for
- dbsiPtr.p->pdxNumDataPages = endPage - startPage; /* SET THE NUMBER OF DATA PAGES */
- riPtr.p->sriCurDataPageFromBuffer = endPage;
- dbsiPtr.p->pdxFilePage = startPage + 1;
- rfrReadNextDataSegment(signal, riPtr, dbsiPtr);
- return;
-}//Dbtup::rfrLoadDataPagesLab()
-
-void Dbtup::rfrCompletedLab(Signal* signal, RestartInfoRecordPtr riPtr)
-{
- PendingFileOpenInfoPtr pfoPtr;
-/* ---------------------------------------------------------------------- */
-/* CLOSE THE DATA FILE BEFORE SENDING TUP_SRCONF */
-/* ---------------------------------------------------------------------- */
- seizePendingFileOpenInfoRecord(pfoPtr);
- pfoPtr.p->pfoOpenType = LCP_DATA_FILE_READ;
- pfoPtr.p->pfoCheckpointInfoP = riPtr.i;
-
- signal->theData[0] = riPtr.p->sriDataFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = pfoPtr.i;
- signal->theData[3] = 0;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
-}//Dbtup::rfrCompletedLab()
-
-void Dbtup::rfrClosedDataFileLab(Signal* signal, Uint32 restartIndex)
-{
- RestartInfoRecordPtr riPtr;
- DiskBufferSegmentInfoPtr dbsiPtr;
-
- riPtr.i = restartIndex;
- ptrCheckGuard(riPtr, cnoOfRestartInfoRec, restartInfoRecord);
- riPtr.p->sriDataFileHandle = RNIL;
- dbsiPtr.i = riPtr.p->sriDataBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- releaseDiskBufferSegmentRecord(dbsiPtr);
- signal->theData[0] = riPtr.p->sriUserptr;
- signal->theData[1] = riPtr.p->sriFragP;
- sendSignal(riPtr.p->sriBlockref, GSN_TUP_SRCONF, signal, 2, JBB);
- releaseRestartInfoRecord(riPtr);
-}//Dbtup::rfrClosedDataFileLab()
-
-/* ---------------------------------------------------------------- */
-/* ---------------------- EXECUTE LOCAL LOG ---------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::execSTART_RECREQ(Signal* signal)
-{
- ljamEntry();
- clqhUserpointer = signal->theData[0];
- clqhBlockref = signal->theData[1];
-
- for (int i = 0; i < ZNO_CHECKPOINT_RECORDS; i++){
- cSrUndoRecords[i] = 0;
- }//for
-
- if (cnoOfLocalLogInfo == 0) {
- ljam();
-/* ---------------------------------------------------------------- */
-/* THERE WERE NO LOCAL LOGS TO EXECUTE IN THIS SYSTEM RESTART */
-/* ---------------------------------------------------------------- */
- xlcRestartCompletedLab(signal);
- return;
- }//if
- LocalLogInfoPtr lliPtr;
- for (lliPtr.i = 0; lliPtr.i < 16; lliPtr.i++) {
- ljam();
- ptrAss(lliPtr, localLogInfo);
- if (lliPtr.p->lliActiveLcp == 1) {
- ljam();
- signal->theData[0] = ZSTART_EXEC_UNDO_LOG;
- signal->theData[1] = lliPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- }//if
- }//for
- return;
-}//Dbtup::execSTART_RECREQ()
-
-void Dbtup::closeExecUndoLogLab(Signal* signal, LocalLogInfoPtr lliPtr)
-{
- PendingFileOpenInfoPtr pfoPtr;
-/* ---------------------------------------------------------------------- */
-/* CLOSE THE UNDO LOG BEFORE COMPLETION OF THE SYSTEM RESTART */
-/* ---------------------------------------------------------------------- */
- seizePendingFileOpenInfoRecord(pfoPtr);
- pfoPtr.p->pfoOpenType = LCP_UNDO_FILE_READ;
- pfoPtr.p->pfoCheckpointInfoP = lliPtr.i;
-
- signal->theData[0] = lliPtr.p->lliUndoFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = pfoPtr.i;
- signal->theData[3] = 0;
- sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, 4, JBA);
- return;
-}//Dbtup::closeExecUndoLogLab()
-
-void Dbtup::endExecUndoLogLab(Signal* signal, Uint32 lliIndex)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
- LocalLogInfoPtr lliPtr;
-
- lliPtr.i = lliIndex;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
- lliPtr.p->lliUndoFileHandle = RNIL;
- lliPtr.p->lliActiveLcp = 0;
-/* ---------------------------------------------------------------------- */
-/* WE HAVE NOW CLOSED THE LOG. WE WAIT FOR ALL LOCAL LOGS TO */
-/* COMPLETE LOG EXECUTION BEFORE SENDING THE RESPONSE TO LQH. */
-/* ---------------------------------------------------------------------- */
- dbsiPtr.i = lliPtr.p->lliUndoBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- freeDiskBufferSegmentRecord(signal, dbsiPtr);
- lliPtr.p->lliUndoBufferSegmentP = RNIL;
- for (lliPtr.i = 0; lliPtr.i < 16; lliPtr.i++) {
- ljam();
- ptrAss(lliPtr, localLogInfo);
- if (lliPtr.p->lliActiveLcp == 1) {
- ljam();
- return;
- }//if
- }//for
- xlcRestartCompletedLab(signal);
- return;
-}//Dbtup::endExecUndoLogLab()
-
-void Dbtup::xlcRestartCompletedLab(Signal* signal)
-{
- cnoOfLocalLogInfo = 0;
-
- signal->theData[0] = NDB_LE_UNDORecordsExecuted;
- signal->theData[1] = DBTUP; // From block
- signal->theData[2] = 0; // Total records executed
- for (int i = 0; i < 10; i++) {
- if (i < ZNO_CHECKPOINT_RECORDS){
- signal->theData[i+3] = cSrUndoRecords[i];
- signal->theData[2] += cSrUndoRecords[i];
- } else {
- signal->theData[i+3] = 0; // Unsused data
- }//if
- }//for
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 12, JBB);
-
-/* ---------------------------------------------------------------------- */
-/* ALL LOCAL LOGS HAVE COMPLETED. WE HAVE COMPLETED OUR PART OF THE */
-/* SYSTEM RESTART. */
-/* ---------------------------------------------------------------------- */
- signal->theData[0] = clqhUserpointer;
- sendSignal(clqhBlockref, GSN_START_RECCONF, signal, 1, JBB);
- return;
-}//Dbtup::xlcRestartCompletedLab()
-
-void Dbtup::startExecUndoLogLab(Signal* signal, Uint32 lliIndex)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
- LocalLogInfoPtr lliPtr;
-
-/* ---------------------------------------------------------------------- */
-/* START EXECUTING THE LOG FOR THIS PART. WE BEGIN BY READING THE */
-/* LAST 16 PAGES. */
-/* ---------------------------------------------------------------------- */
- /* SET THE PREVIOS RECORD TO THE LAST ONE BECAUSE THAT'S WHERE TO START */
- lliPtr.i = lliIndex;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
-
- allocRestartUndoBufferSegment(signal, dbsiPtr, lliPtr);
- lliPtr.p->lliUndoBufferSegmentP = dbsiPtr.i;
- dbsiPtr.p->pdxCheckpointInfoP = lliPtr.i;
- if (lliPtr.p->lliEndPageId > ((2 * ZUB_SEGMENT_SIZE) - 1)) {
- ljam();
- dbsiPtr.p->pdxNumDataPages = ZUB_SEGMENT_SIZE;
- dbsiPtr.p->pdxFilePage = lliPtr.p->lliEndPageId - (ZUB_SEGMENT_SIZE - 1);
- } else if (lliPtr.p->lliEndPageId > (ZUB_SEGMENT_SIZE - 1)) {
- ljam();
- dbsiPtr.p->pdxNumDataPages = lliPtr.p->lliEndPageId - (ZUB_SEGMENT_SIZE - 1);
- dbsiPtr.p->pdxFilePage = ZUB_SEGMENT_SIZE;
- } else {
- ljam();
- dbsiPtr.p->pdxNumDataPages = lliPtr.p->lliEndPageId + 1;
- dbsiPtr.p->pdxFilePage = 0;
- rfrReadNextUndoSegment(signal, dbsiPtr, lliPtr);
- return;
- }//if
- rfrReadFirstUndoSegment(signal, dbsiPtr, lliPtr);
- return;
-}//Dbtup::startExecUndoLogLab()
-
-void Dbtup::rfrReadSecondUndoLogLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr)
-{
- LocalLogInfoPtr lliPtr;
- lliPtr.i = dbsiPtr.p->pdxCheckpointInfoP;
- ptrCheckGuard(lliPtr, cnoOfParallellUndoFiles, localLogInfo);
-
- dbsiPtr.p->pdxNumDataPages = ZUB_SEGMENT_SIZE;
- dbsiPtr.p->pdxFilePage -= ZUB_SEGMENT_SIZE;
- rfrReadNextUndoSegment(signal, dbsiPtr, lliPtr);
- return;
-}//Dbtup::rfrReadSecondUndoLogLab()
-
-void Dbtup::readExecUndoLogLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr)
-{
-/* ---------------------------------------------------------------------- */
-/* THE NEXT UNDO LOG RECORD HAS NOT BEEN READ FROM DISK YET. WE WILL*/
-/* READ UPTO 8 PAGES BACKWARDS OF THE UNDO LOG FILE. WE WILL KEEP */
-/* THE LAST 8 PAGES TO ENSURE THAT WE WILL BE ABLE TO READ THE NEXT */
-/* LOG RECORD EVEN IF IT SPANS UPTO 8 PAGES. */
-/* ---------------------------------------------------------------------- */
- if (dbsiPtr.p->pdxFilePage >= ZUB_SEGMENT_SIZE) {
- ljam();
- for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) {
- ljam();
- Uint32 savePageId = dbsiPtr.p->pdxDataPage[i + ZUB_SEGMENT_SIZE];
- dbsiPtr.p->pdxDataPage[i + ZUB_SEGMENT_SIZE] = dbsiPtr.p->pdxDataPage[i];
- dbsiPtr.p->pdxDataPage[i] = savePageId;
- }//for
- dbsiPtr.p->pdxNumDataPages = ZUB_SEGMENT_SIZE;
- dbsiPtr.p->pdxFilePage = dbsiPtr.p->pdxFilePage - ZUB_SEGMENT_SIZE;
- } else {
- ljam();
- Uint32 dataPages[16];
- ndbrequire(dbsiPtr.p->pdxFilePage > 0);
- ndbrequire(dbsiPtr.p->pdxFilePage <= ZUB_SEGMENT_SIZE);
- Uint32 i;
- for (i = 0; i < dbsiPtr.p->pdxFilePage; i++) {
- ljam();
- dataPages[i] = dbsiPtr.p->pdxDataPage[i + ZUB_SEGMENT_SIZE];
- }//for
- for (i = 0; i < ZUB_SEGMENT_SIZE; i++) {
- ljam();
- dataPages[i + dbsiPtr.p->pdxFilePage] = dbsiPtr.p->pdxDataPage[i];
- }//for
- Uint32 limitLoop = ZUB_SEGMENT_SIZE + dbsiPtr.p->pdxFilePage;
- for (i = 0; i < limitLoop; i++) {
- ljam();
- dbsiPtr.p->pdxDataPage[i] = dataPages[i];
- }//for
- dbsiPtr.p->pdxNumDataPages = dbsiPtr.p->pdxFilePage;
- dbsiPtr.p->pdxFilePage = 0;
- }//if
- rfrReadNextUndoSegment(signal, dbsiPtr, lliPtr);
- return;
-}//Dbtup::readExecUndoLogLab()
-
-void Dbtup::rfrReadNextDataSegment(Signal* signal, RestartInfoRecordPtr riPtr, DiskBufferSegmentInfoPtr dbsiPtr)
-{
- dbsiPtr.p->pdxRestartInfoP = riPtr.i;
- dbsiPtr.p->pdxOperation = CHECKPOINT_DATA_READ;
- ndbrequire(dbsiPtr.p->pdxNumDataPages <= 8);
-
- signal->theData[0] = riPtr.p->sriDataFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = dbsiPtr.i;
- signal->theData[3] = 2;
- signal->theData[4] = ZBASE_ADDR_PAGE_WORD;
- signal->theData[5] = dbsiPtr.p->pdxNumDataPages;
- for (Uint32 i = 0; i < dbsiPtr.p->pdxNumDataPages; i++) {
- ljam();
- signal->theData[6 + i] = dbsiPtr.p->pdxDataPage[i];
- }//for
- signal->theData[6 + dbsiPtr.p->pdxNumDataPages] = dbsiPtr.p->pdxFilePage;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA);
-}//Dbtup::rfrReadNextDataSegment()
-
-/* ---------------------------------------------------------------- */
-/* ------------------- RFR_READ_FIRST_UNDO_SEGMENT ---------------- */
-/* ---------------------------------------------------------------- */
-/* THIS ROUTINE READS IN THE FIRST UNDO SEGMENT INTO THE CURRENTLY */
-/* ACTIVE UNDO BUFFER SEGMENT */
-/* -----------------------------------------------------------------*/
-void Dbtup::rfrReadFirstUndoSegment(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr)
-{
- dbsiPtr.p->pdxOperation = CHECKPOINT_UNDO_READ_FIRST;
-
- signal->theData[0] = lliPtr.p->lliUndoFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = dbsiPtr.i;
- signal->theData[3] = 1;
- signal->theData[4] = ZBASE_ADDR_UNDO_WORD;
- signal->theData[5] = dbsiPtr.p->pdxNumDataPages;
- signal->theData[6] = dbsiPtr.p->pdxDataPage[ZUB_SEGMENT_SIZE];
- signal->theData[7] = dbsiPtr.p->pdxFilePage;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
-}//Dbtup::rfrReadFirstUndoSegment()
-
-/* ---------------------------------------------------------------- */
-/* ------------------- RFR_READ_NEXT_UNDO_SEGMENT ----------------- */
-/* ---------------------------------------------------------------- */
-/* THIS ROUTINE READS IN THE NEXT UNDO SEGMENT INTO THE CURRENTLY */
-/* ACTIVE UNDO BUFFER SEGMENT AND SWITCH TO THE UNACTIVE, READY ONE */
-/* -----------------------------------------------------------------*/
-void Dbtup::rfrReadNextUndoSegment(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr)
-{
- dbsiPtr.p->pdxOperation = CHECKPOINT_UNDO_READ;
-
- signal->theData[0] = lliPtr.p->lliUndoFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = dbsiPtr.i;
- signal->theData[3] = 1;
- signal->theData[4] = ZBASE_ADDR_UNDO_WORD;
- signal->theData[5] = dbsiPtr.p->pdxNumDataPages;
- signal->theData[6] = dbsiPtr.p->pdxDataPage[0];
- signal->theData[7] = dbsiPtr.p->pdxFilePage;
- sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
-}//Dbtup::rfrReadNextUndoSegment()
-
-void Dbtup::xlcGetNextRecordLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr, LocalLogInfoPtr lliPtr)
-{
- Uint32 loopCount = 0;
-/* ---------------------------------------------------------------------- */
-/* EXECUTE A NEW SET OF UNDO LOG RECORDS. */
-/* ---------------------------------------------------------------------- */
- XlcStruct xlcStruct;
-
- xlcStruct.LliPtr = lliPtr;
- xlcStruct.DbsiPtr = dbsiPtr;
-
- do {
- ljam();
- loopCount++;
- if (loopCount == 20) {
- ljam();
- signal->theData[0] = ZCONT_EXECUTE_LC;
- signal->theData[1] = xlcStruct.LliPtr.i;
- sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
- return;
- }//if
- if (xlcStruct.LliPtr.p->lliPrevRecordId == 0) {
- ljam();
- closeExecUndoLogLab(signal, xlcStruct.LliPtr);
- return;
- }//if
- xlcStruct.PageId = xlcStruct.LliPtr.p->lliPrevRecordId >> ZUNDO_RECORD_ID_PAGE_INDEX;
- xlcStruct.PageIndex = xlcStruct.LliPtr.p->lliPrevRecordId & ZUNDO_RECORD_ID_PAGE_INDEX_MASK;
- if (xlcStruct.PageId < xlcStruct.DbsiPtr.p->pdxFilePage) {
- ljam();
- readExecUndoLogLab(signal, xlcStruct.DbsiPtr, xlcStruct.LliPtr);
- return;
- }//if
- ndbrequire((xlcStruct.PageId - xlcStruct.DbsiPtr.p->pdxFilePage) < 16);
- xlcStruct.UPPtr.i = xlcStruct.DbsiPtr.p->pdxDataPage[xlcStruct.PageId - xlcStruct.DbsiPtr.p->pdxFilePage];
- ptrCheckGuard(xlcStruct.UPPtr, cnoOfUndoPage, undoPage);
- xlcGetLogHeader(xlcStruct);
- getFragmentrec(xlcStruct.FragPtr, xlcStruct.FragId, xlcStruct.TabPtr.p);
- if (xlcStruct.FragPtr.i == RNIL) {
- ljam();
- continue;
- }//if
- if (xlcStruct.FragPtr.p->fragStatus != SYSTEM_RESTART) {
- ljam();
- continue;
- }//if
- ndbrequire(xlcStruct.LogRecordType < ZNO_CHECKPOINT_RECORDS);
- cSrUndoRecords[xlcStruct.LogRecordType]++;
- switch (xlcStruct.LogRecordType) {
- case ZLCPR_TYPE_INSERT_TH:
- ljam();
- xlcInsertTh(xlcStruct);
- break;
- case ZLCPR_TYPE_DELETE_TH:
- ljam();
- xlcDeleteTh(xlcStruct);
- break;
- case ZLCPR_TYPE_UPDATE_TH:
- ljam();
- xlcUpdateTh(xlcStruct);
- break;
- case ZLCPR_TYPE_INSERT_TH_NO_DATA:
- ljam();
- xlcInsertTh(xlcStruct);
- break;
- case ZLCPR_ABORT_UPDATE:
- ljam();
- xlcAbortUpdate(signal, xlcStruct);
- break;
- case ZLCPR_ABORT_INSERT:
- ljam();
- xlcAbortInsert(signal, xlcStruct);
- break;
- case ZTABLE_DESCRIPTOR:
- ljam();
- xlcTableDescriptor(xlcStruct);
- if (xlcStruct.LliPtr.p->lliNumFragments == 0) {
- ljam();
- closeExecUndoLogLab(signal, xlcStruct.LliPtr);
- return;
- }//if
- break;
- case ZLCPR_UNDO_LOG_PAGE_HEADER:
- ljam();
- xlcUndoLogPageHeader(xlcStruct);
- break;
- case ZINDICATE_NO_OP_ACTIVE:
- ljam();
- xlcIndicateNoOpActive(xlcStruct);
- break;
- case ZLCPR_TYPE_UPDATE_GCI:
- ljam();
- xlcUpdateGCI(xlcStruct);
- break;
- default:
- ndbrequire(false);
- break;
- }//switch
- } while (1);
-}//Dbtup::xlcGetNextRecordLab()
-
-/* ---------------------------------------------------------------- */
-/* ----------------- XLC_GET_LOG_HEADER ---------------------- */
-/* ---------------------------------------------------------------- */
-void Dbtup::xlcGetLogHeader(XlcStruct& xlcStruct)
-{
- Uint32 pIndex = xlcStruct.PageIndex;
- Uint32 fragId;
- Uint32 tableId;
- Uint32 prevId;
- if ((pIndex + 4) < ZWORDS_ON_PAGE) {
- UndoPage* const regUndoPagePtr = xlcStruct.UPPtr.p;
- ljam();
- xlcStruct.LogRecordType = regUndoPagePtr->undoPageWord[pIndex];
- prevId = regUndoPagePtr->undoPageWord[pIndex + 1];
- tableId = regUndoPagePtr->undoPageWord[pIndex + 2];
- fragId = regUndoPagePtr->undoPageWord[pIndex + 3];
- xlcStruct.PageIndex = pIndex + 4;
- } else {
- ljam();
- xlcStruct.LogRecordType = xlcGetLogWord(xlcStruct);
- prevId = xlcGetLogWord(xlcStruct);
- tableId = xlcGetLogWord(xlcStruct);
- fragId = xlcGetLogWord(xlcStruct);
- }//if
- xlcStruct.LliPtr.p->lliPrevRecordId = prevId;
- xlcStruct.FragId = fragId;
- xlcStruct.TabPtr.i = tableId;
- ptrCheckGuard(xlcStruct.TabPtr, cnoOfTablerec, tablerec);
-}//Dbtup::xlcGetLogHeader()
-
-/* ------------------------------------------------------------------- */
-/* ---------------------- XLC_GET_LOG_WORD --------------------------- */
-/* ------------------------------------------------------------------- */
-Uint32 Dbtup::xlcGetLogWord(XlcStruct& xlcStruct)
-{
- Uint32 pIndex = xlcStruct.PageIndex;
- ndbrequire(xlcStruct.UPPtr.p != NULL);
- ndbrequire(pIndex < ZWORDS_ON_PAGE);
- Uint32 logWord = xlcStruct.UPPtr.p->undoPageWord[pIndex];
- pIndex++;
- xlcStruct.PageIndex = pIndex;
- if (pIndex == ZWORDS_ON_PAGE) {
- ljam();
- xlcStruct.PageIndex = ZUNDO_PAGE_HEADER_SIZE;
- xlcStruct.PageId++;
- if ((xlcStruct.PageId - xlcStruct.DbsiPtr.p->pdxFilePage) >= (2 * ZUB_SEGMENT_SIZE)) {
- ljam();
- xlcStruct.UPPtr.i = RNIL;
- ptrNull(xlcStruct.UPPtr);
- } else {
- ljam();
- Uint32 index = xlcStruct.PageId - xlcStruct.DbsiPtr.p->pdxFilePage;
- ndbrequire(index < 16);
- xlcStruct.UPPtr.i = xlcStruct.DbsiPtr.p->pdxDataPage[index];
- ptrCheckGuard(xlcStruct.UPPtr, cnoOfUndoPage, undoPage);
- }//if
- }//if
- return logWord;
-}//Dbtup::xlcGetLogWord()
-
- /****************************************************/
- /* INSERT A TUPLE HEADER THE DATA IS THE TUPLE DATA */
- /****************************************************/
-void Dbtup::xlcInsertTh(XlcStruct& xlcStruct)
-{
- PagePtr pagePtr;
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- Tablerec* const regTabPtr = xlcStruct.TabPtr.p;
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- Uint32 pageIndex = xlcGetLogWord(xlcStruct);
- ndbrequire((pageIndex & 1) == 0);
- pagePtr.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageOffset;
- getThAtPageSr(pagePtr.p, pageOffset);
- ndbrequire(pageOffset == (ZPAGE_HEADER_SIZE + (regTabPtr->tupheadsize * (pageIndex >> 1))));
- if (xlcStruct.LogRecordType == ZLCPR_TYPE_INSERT_TH) {
- ljam();
- xlcCopyData(xlcStruct, pageOffset, regTabPtr->tupheadsize, pagePtr);
- } else {
- ndbrequire(xlcStruct.LogRecordType == ZLCPR_TYPE_INSERT_TH_NO_DATA);
- ljam();
- }//if
-/* ----------------------------------------*/
-/* INDICATE THAT NO OPERATIONS ACTIVE */
-/* ----------------------------------------*/
- ndbrequire(pageOffset < ZWORDS_ON_PAGE);
- pagePtr.p->pageWord[pageOffset] = RNIL;
-}//Dbtup::xlcInsertTh()
-
- /**********************************************/
- /* DELETE A TUPLE HEADER - NO ADDITIONAL DATA */
- /**********************************************/
-void Dbtup::xlcDeleteTh(XlcStruct& xlcStruct)
-{
- PagePtr pagePtr;
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- Tablerec* const regTabPtr = xlcStruct.TabPtr.p;
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- Uint32 pageIndex = xlcGetLogWord(xlcStruct);
- ndbrequire((pageIndex & 1) == 0);
- pagePtr.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + (regTabPtr->tupheadsize * (pageIndex >> 1));
- freeThSr(regTabPtr, pagePtr.p, pageOffset);
-}//Dbtup::xlcDeleteTh()
-
- /*****************************************************/
- /* UPDATE A TUPLE HEADER, THE DATA IS THE TUPLE DATA */
- /*****************************************************/
-void Dbtup::xlcUpdateTh(XlcStruct& xlcStruct)
-{
- PagePtr pagePtr;
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- Tablerec* const regTabPtr = xlcStruct.TabPtr.p;
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- Uint32 pageIndex = xlcGetLogWord(xlcStruct);
- ndbrequire((pageIndex & 1) == 0);
- pagePtr.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + (regTabPtr->tupheadsize * (pageIndex >> 1));
- xlcCopyData(xlcStruct, pageOffset, regTabPtr->tupheadsize, pagePtr);
-/* ----------------------------------------*/
-/* INDICATE THAT NO OPERATIONS ACTIVE */
-/* ----------------------------------------*/
- ndbrequire(pageOffset < ZWORDS_ON_PAGE);
- pagePtr.p->pageWord[pageOffset] = RNIL;
-}//Dbtup::xlcUpdateTh()
-
- /**************************************************/
- /* ABORT AN INSERT OPERATION - NO ADDITIONAL DATA */
- /**************************************************/
-void Dbtup::xlcAbortInsert(Signal* signal, XlcStruct& xlcStruct)
-{
- PagePtr pagePtr;
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- Tablerec* const regTabPtr = xlcStruct.TabPtr.p;
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- Uint32 pageIndex = xlcGetLogWord(xlcStruct);
- ndbrequire((pageIndex & 1) == 0);
- pagePtr.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + (regTabPtr->tupheadsize * (pageIndex >> 1));
- freeTh(regFragPtr, regTabPtr, signal, pagePtr.p, pageOffset);
-}//Dbtup::xlcAbortInsert()
-
- /*****************************************************/
- /* COPY DATA FROM COPY TUPLE TO ORIGINAL TUPLE */
- /*****************************************************/
-void Dbtup::xlcAbortUpdate(Signal* signal, XlcStruct& xlcStruct)
-{
- PagePtr pagePtr;
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- Tablerec* const regTabPtr = xlcStruct.TabPtr.p;
- Uint32 tuple_size = regTabPtr->tupheadsize;
-
- Uint32 fragPageIdC = xlcGetLogWord(xlcStruct);
- Uint32 pageIndexC = xlcGetLogWord(xlcStruct);
- ndbrequire((pageIndexC & 1) == 0);
- Uint32 TdestPageId = getRealpid(regFragPtr, fragPageIdC);
- Uint32 TcmDestIndex = ZPAGE_HEADER_SIZE +
- (tuple_size * (pageIndexC >> 1));
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- Uint32 pageIndex = xlcGetLogWord(xlcStruct);
- ndbrequire((pageIndex & 1) == 0);
- Uint32 TsourcePageId = getRealpid(regFragPtr, fragPageId);
- Uint32 TcmSourceIndex = ZPAGE_HEADER_SIZE +
- (tuple_size * (pageIndex >> 1));
- Uint32 end_source = tuple_size + TcmSourceIndex;
- Uint32 end_dest = tuple_size + TcmDestIndex;
-
- void* Tdestination = (void*)&page[TdestPageId].pageWord[TcmDestIndex + 1];
- const void* Tsource =
- (void*)&page[TsourcePageId].pageWord[TcmSourceIndex + 1];
-
- ndbrequire(TsourcePageId < cnoOfPage &&
- TdestPageId < cnoOfPage &&
- end_source <= ZWORDS_ON_PAGE &&
- end_dest <= ZWORDS_ON_PAGE);
- MEMCOPY_NO_WORDS(Tdestination, Tsource, (tuple_size - 1));
-
- pagePtr.i = TsourcePageId;
- ptrAss(pagePtr, page);
- freeTh(regFragPtr, regTabPtr, signal, pagePtr.p, TcmSourceIndex);
-
- pagePtr.i = TdestPageId;
- ptrAss(pagePtr, page);
- pagePtr.p->pageWord[TcmDestIndex] = RNIL;
-}//Dbtup::xlcAbortUpdate()
-
- /*****************************/
- /* RESTORE UPDATED GCI VALUE */
- /*****************************/
-void Dbtup::xlcUpdateGCI(XlcStruct& xlcStruct)
-{
- PagePtr pagePtr;
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- Tablerec* const regTabPtr = xlcStruct.TabPtr.p;
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- Uint32 pageIndex = xlcGetLogWord(xlcStruct);
- Uint32 restoredGCI = xlcGetLogWord(xlcStruct);
-
- ndbrequire((pageIndex & 1) == 0);
- pagePtr.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + (regTabPtr->tupheadsize * (pageIndex >> 1));
- Uint32 gciOffset = pageOffset + regTabPtr->tupGCPIndex;
- ndbrequire((gciOffset < ZWORDS_ON_PAGE) &&
- (regTabPtr->tupGCPIndex < regTabPtr->tupheadsize));
- pagePtr.p->pageWord[gciOffset] = restoredGCI;
-}//Dbtup::xlcUpdateGCI()
-
- /*****************************************************/
- /* READ TABLE DESCRIPTOR FROM UNDO LOG */
- /*****************************************************/
-void Dbtup::xlcTableDescriptor(XlcStruct& xlcStruct)
-{
- xlcStruct.LliPtr.p->lliNumFragments--;
- xlcStruct.FragPtr.p->fragStatus = ACTIVE;
-}//Dbtup::xlcTableDescriptor()
-
- /********************************************************/
- /* UPDATE PAGE STATE AND NEXT POINTER IN PAGE */
- /********************************************************/
-void Dbtup::xlcUndoLogPageHeader(XlcStruct& xlcStruct)
-{
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- PagePtr xlcPagep;
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- xlcPagep.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(xlcPagep, cnoOfPage, page);
- Uint32 logWord = xlcGetLogWord(xlcStruct);
- ndbrequire(logWord != 0);
- ndbrequire(logWord <= ZAC_MM_FREE_COPY);
-
- xlcPagep.p->pageWord[ZPAGE_STATE_POS] = logWord;
- xlcPagep.p->pageWord[ZPAGE_NEXT_POS] = xlcGetLogWord(xlcStruct);
-}//Dbtup::xlcUndoLogPageHeader()
-
- /********************************************************/
- /* INDICATE THAT NO OPERATIONS ACTIVE */
- /********************************************************/
-void Dbtup::xlcIndicateNoOpActive(XlcStruct& xlcStruct)
-{
- PagePtr pagePtr;
- Fragrecord* const regFragPtr = xlcStruct.FragPtr.p;
- Tablerec* const regTabPtr = xlcStruct.TabPtr.p;
-
- Uint32 fragPageId = xlcGetLogWord(xlcStruct);
- Uint32 pageIndex = xlcGetLogWord(xlcStruct);
- ndbrequire((pageIndex & 1) == 0);
- pagePtr.i = getRealpid(regFragPtr, fragPageId);
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 pageOffset = ZPAGE_HEADER_SIZE + (regTabPtr->tupheadsize * (pageIndex >> 1));
-/* ----------------------------------------*/
-/* INDICATE THAT NO OPERATIONS ACTIVE */
-/* ----------------------------------------*/
- ndbrequire(pageOffset < ZWORDS_ON_PAGE);
- pagePtr.p->pageWord[pageOffset] = RNIL;
-}//Dbtup::xlcIndicateNoOpActive()
-
- /********************************************************/
- /* THIS IS THE COMMON ROUTINE TO COPY DATA FROM THE */
- /* UNDO BUFFER TO THE DATA PAGES. IT USES THE */
- /* XLC_REQUEST_SEGMENT SUB TO GET MORE DATA WHEN NEEDED */
- /********************************************************/
-void Dbtup::xlcCopyData(XlcStruct& xlcStruct, Uint32 pageOffset, Uint32 noOfWords, PagePtr pagePtr)
-{
- ndbrequire((pageOffset + noOfWords - 1) < ZWORDS_ON_PAGE);
- for (Uint32 i = 1; i < noOfWords; i++) {
- ljam();
- pagePtr.p->pageWord[pageOffset + i] = xlcGetLogWord(xlcStruct);
- }//for
-}//Dbtup::xlcCopyData()
-
-void Dbtup::allocRestartUndoBufferSegment(Signal* signal, DiskBufferSegmentInfoPtr& dbsiPtr, LocalLogInfoPtr lliPtr)
-{
- UndoPagePtr undoPagePtr;
-
- ndbrequire(cfirstfreeUndoSeg != RNIL);
- if (cnoFreeUndoSeg == ZMIN_PAGE_LIMIT_TUP_COMMITREQ) {
- EXECUTE_DIRECT(DBLQH, GSN_TUP_COM_BLOCK, signal, 1);
- ljamEntry();
- }//if
- cnoFreeUndoSeg--;
- ndbrequire(cnoFreeUndoSeg >= 0);
- undoPagePtr.i = cfirstfreeUndoSeg;
- ptrCheckGuard(undoPagePtr, cnoOfUndoPage, undoPage);
- cfirstfreeUndoSeg = undoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS];
- undoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS] = RNIL;
- seizeDiskBufferSegmentRecord(dbsiPtr);
- dbsiPtr.p->pdxBuffertype = UNDO_RESTART_PAGES;
- dbsiPtr.p->pdxUndoBufferSet[0] = undoPagePtr.i;
- Uint32 i;
- for (i = 0; i < ZUB_SEGMENT_SIZE; i++) {
- dbsiPtr.p->pdxDataPage[i] = undoPagePtr.i + i;
- }//for
-
- ndbrequire(cfirstfreeUndoSeg != RNIL);
- if (cnoFreeUndoSeg == ZMIN_PAGE_LIMIT_TUP_COMMITREQ) {
- EXECUTE_DIRECT(DBLQH, GSN_TUP_COM_BLOCK, signal, 1);
- ljamEntry();
- }//if
- cnoFreeUndoSeg--;
- ndbrequire(cnoFreeUndoSeg >= 0);
- undoPagePtr.i = cfirstfreeUndoSeg;
- ptrCheckGuard(undoPagePtr, cnoOfUndoPage, undoPage);
- cfirstfreeUndoSeg = undoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS];
- undoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS] = RNIL;
- dbsiPtr.p->pdxUndoBufferSet[1] = undoPagePtr.i;
-// lliPtr.p->lliUndoPage = undoPagePtr.i;
- for (i = ZUB_SEGMENT_SIZE; i < (2 * ZUB_SEGMENT_SIZE); i++) {
- dbsiPtr.p->pdxDataPage[i] = undoPagePtr.i + (i - ZUB_SEGMENT_SIZE);
- }//for
- return;
-}//Dbtup::allocRestartUndoBufferSegment()
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
index 642ba270760..3754942bb99 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
@@ -43,12 +43,12 @@ Dbtup::getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset)
Uint32 allocSize = 0;
// magically aligned to 8 bytes
offset[0] = allocSize += ZTD_SIZE;
- offset[1] = allocSize += regTabPtr->noOfAttr * sizeOfReadFunction();
- offset[2] = allocSize += regTabPtr->noOfAttr * sizeOfReadFunction();
+ 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->noOfAttributeGroups;
- allocSize += regTabPtr->noOfAttr * ZAD_SIZE;
+ 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;
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
index 0cdfe97ecb5..e105fe1f2bd 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
@@ -282,7 +282,7 @@ Dbtup::createTrigger(Tablerec* table, const CreateTrigReq* req)
tptr.p->attributeMask.clear();
if (tptr.p->monitorAllAttributes) {
ljam();
- for(Uint32 i = 0; i < table->noOfAttr; i++) {
+ for(Uint32 i = 0; i < table->m_no_of_attributes; i++) {
if (!primaryKey(table, i)) {
ljam();
tptr.p->attributeMask.set(i);
@@ -300,7 +300,8 @@ bool
Dbtup::primaryKey(Tablerec* const regTabPtr, Uint32 attrId)
{
Uint32 attrDescriptorStart = regTabPtr->tabDescriptor;
- Uint32 attrDescriptor = getTabDescrWord(attrDescriptorStart + (attrId * ZAD_SIZE));
+ Uint32 attrDescriptor = getTabDescrWord(attrDescriptorStart +
+ (attrId * ZAD_SIZE));
return (bool)AttributeDescriptor::getPrimaryKey(attrDescriptor);
}//Dbtup::primaryKey()
@@ -353,63 +354,66 @@ Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req)
/* Executes immediate triggers by sending FIRETRIGORD */
/* */
/* ---------------------------------------------------------------- */
-void Dbtup::checkImmediateTriggersAfterInsert(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTablePtr)
+void
+Dbtup::checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const regTablePtr)
{
- if(refToBlock(regOperPtr->coordinatorTC) == DBLQH) {
+ if(refToBlock(req_struct->TC_ref) != DBTC) {
return;
}
- if ((regOperPtr->primaryReplica) &&
+ if ((regOperPtr->op_struct.primary_replica) &&
(!(regTablePtr->afterInsertTriggers.isEmpty()))) {
ljam();
- fireImmediateTriggers(signal,
+ fireImmediateTriggers(req_struct,
regTablePtr->afterInsertTriggers,
regOperPtr);
- }//if
-}//Dbtup::checkImmediateTriggersAfterInsert()
+ }
+}
-void Dbtup::checkImmediateTriggersAfterUpdate(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTablePtr)
+void
+Dbtup::checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const regTablePtr)
{
- if(refToBlock(regOperPtr->coordinatorTC) == DBLQH) {
+ if(refToBlock(req_struct->TC_ref) != DBTC) {
return;
}
- if ((regOperPtr->primaryReplica) &&
+ if ((regOperPtr->op_struct.primary_replica) &&
(!(regTablePtr->afterUpdateTriggers.isEmpty()))) {
ljam();
- fireImmediateTriggers(signal,
+ fireImmediateTriggers(req_struct,
regTablePtr->afterUpdateTriggers,
regOperPtr);
- }//if
- if ((regOperPtr->primaryReplica) &&
+ }
+ if ((regOperPtr->op_struct.primary_replica) &&
(!(regTablePtr->constraintUpdateTriggers.isEmpty()))) {
ljam();
- fireImmediateTriggers(signal,
+ fireImmediateTriggers(req_struct,
regTablePtr->constraintUpdateTriggers,
regOperPtr);
- }//if
-}//Dbtup::checkImmediateTriggersAfterUpdate()
+ }
+}
-void Dbtup::checkImmediateTriggersAfterDelete(Signal* signal,
- Operationrec* const regOperPtr,
- Tablerec* const regTablePtr)
+void
+Dbtup::checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const regTablePtr)
{
- if(refToBlock(regOperPtr->coordinatorTC) == DBLQH) {
+ if(refToBlock(req_struct->TC_ref) != DBTC) {
return;
}
- if ((regOperPtr->primaryReplica) &&
+ if ((regOperPtr->op_struct.primary_replica) &&
(!(regTablePtr->afterDeleteTriggers.isEmpty()))) {
ljam();
- executeTriggers(signal,
+ executeTriggers(req_struct,
regTablePtr->afterDeleteTriggers,
regOperPtr);
- }//if
-}//Dbtup::checkImmediateTriggersAfterDelete()
+ }
+}
#if 0
/* ---------------------------------------------------------------- */
@@ -439,21 +443,22 @@ void Dbtup::checkDeferredTriggers(Signal* signal,
/* Executes detached triggers by sending FIRETRIGORD */
/* */
/* ---------------------------------------------------------------- */
-void Dbtup::checkDetachedTriggers(Signal* signal,
+void Dbtup::checkDetachedTriggers(KeyReqStruct *req_struct,
Operationrec* const regOperPtr,
Tablerec* const regTablePtr)
{
- switch(regOperPtr->optype) {
+
+ switch(regOperPtr->op_struct.op_type) {
case(ZINSERT):
ljam();
if (regTablePtr->subscriptionInsertTriggers.isEmpty()) {
// Table has no active triggers monitoring inserts at commit
ljam();
return;
- }//if
+ }
// If any fired immediate insert trigger then fetch after tuple
- fireDetachedTriggers(signal,
+ fireDetachedTriggers(req_struct,
regTablePtr->subscriptionInsertTriggers,
regOperPtr);
break;
@@ -463,13 +468,13 @@ void Dbtup::checkDetachedTriggers(Signal* signal,
// Table has no active triggers monitoring deletes at commit
ljam();
return;
- }//if
+ }
// Execute any after delete triggers by sending
// FIRETRIGORD with the before tuple
- executeTriggers(signal,
- regTablePtr->subscriptionDeleteTriggers,
- regOperPtr);
+ fireDetachedTriggers(req_struct,
+ regTablePtr->subscriptionDeleteTriggers,
+ regOperPtr);
break;
case(ZUPDATE):
ljam();
@@ -477,22 +482,22 @@ void Dbtup::checkDetachedTriggers(Signal* signal,
// Table has no active triggers monitoring updates at commit
ljam();
return;
- }//if
+ }
// If any fired immediate update trigger then fetch after tuple
// and send two FIRETRIGORD one with before tuple and one with after tuple
- fireDetachedTriggers(signal,
+ fireDetachedTriggers(req_struct,
regTablePtr->subscriptionUpdateTriggers,
regOperPtr);
break;
default:
ndbrequire(false);
break;
- }//switch
-}//Dbtup::CheckDetachedTriggers()
+ }
+}
void
-Dbtup::fireImmediateTriggers(Signal* signal,
+Dbtup::fireImmediateTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr)
{
@@ -501,9 +506,9 @@ Dbtup::fireImmediateTriggers(Signal* signal,
while (trigPtr.i != RNIL) {
ljam();
if (trigPtr.p->monitorAllAttributes ||
- trigPtr.p->attributeMask.overlaps(regOperPtr->changeMask)) {
+ trigPtr.p->attributeMask.overlaps(req_struct->changeMask)) {
ljam();
- executeTrigger(signal,
+ executeTrigger(req_struct,
trigPtr.p,
regOperPtr);
}//if
@@ -513,7 +518,8 @@ Dbtup::fireImmediateTriggers(Signal* signal,
#if 0
void
-Dbtup::fireDeferredTriggers(Signal* signal,
+Dbtup::fireDeferredTriggers(Signal* signal,
+ KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr)
{
@@ -522,9 +528,9 @@ Dbtup::fireDeferredTriggers(Signal* signal,
while (trigPtr.i != RNIL) {
ljam();
if (trigPtr.p->monitorAllAttributes ||
- trigPtr.p->attributeMask.overlaps(regOperPtr->changeMask)) {
+ trigPtr.p->attributeMask.overlaps(req_struct->changeMask)) {
ljam();
- executeTrigger(signal,
+ executeTrigger(req_struct,
trigPtr,
regOperPtr);
}//if
@@ -534,27 +540,60 @@ Dbtup::fireDeferredTriggers(Signal* signal,
#endif
void
-Dbtup::fireDetachedTriggers(Signal* signal,
+Dbtup::fireDetachedTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr)
{
+
TriggerPtr trigPtr;
+ Uint32 save= regOperPtr->op_struct.op_type;
+ Tuple_header *save_ptr = req_struct->m_tuple_ptr;
+
+ switch(save){
+ 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
+ */
+ if(req_struct->m_tuple_ptr->m_header_bits & Tuple_header::ALLOC)
+ {
+ if(save == ZDELETE)
+ {
+ // insert + delete = nothing
+ ljam();
+ return;
+ goto end;
+ }
+ regOperPtr->op_struct.op_type = ZINSERT;
+ }
+
+ ndbrequire(regOperPtr->is_first_operation());
triggerList.first(trigPtr);
while (trigPtr.i != RNIL) {
ljam();
- if ((trigPtr.p->monitorReplicas || regOperPtr->primaryReplica) &&
+ if ((trigPtr.p->monitorReplicas ||
+ regOperPtr->op_struct.primary_replica) &&
(trigPtr.p->monitorAllAttributes ||
- trigPtr.p->attributeMask.overlaps(regOperPtr->changeMask))) {
+ trigPtr.p->attributeMask.overlaps(req_struct->changeMask))) {
ljam();
- executeTrigger(signal,
+ executeTrigger(req_struct,
trigPtr.p,
regOperPtr);
- }//if
+ }
triggerList.next(trigPtr);
- }//while
-}//Dbtup::fireDetachedTriggers()
+ }
-void Dbtup::executeTriggers(Signal* signal,
+end:
+ regOperPtr->op_struct.op_type = save;
+ req_struct->m_tuple_ptr = save_ptr;
+}
+
+void Dbtup::executeTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList,
Operationrec* regOperPtr)
{
@@ -562,15 +601,15 @@ void Dbtup::executeTriggers(Signal* signal,
triggerList.first(trigPtr);
while (trigPtr.i != RNIL) {
ljam();
- executeTrigger(signal,
+ executeTrigger(req_struct,
trigPtr.p,
regOperPtr);
triggerList.next(trigPtr);
- }//while
-}//Dbtup::executeTriggers()
+ }
+}
-void Dbtup::executeTrigger(Signal* signal,
+void Dbtup::executeTrigger(KeyReqStruct *req_struct,
TupTriggerData* const trigPtr,
Operationrec* const regOperPtr)
{
@@ -595,17 +634,21 @@ void Dbtup::executeTrigger(Signal* signal,
*/
// XXX quick fix to NR, should fix in LQHKEYREQ instead
/*
- if (refToBlock(regOperPtr->coordinatorTC) == DBLQH) {
+ 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 mainBuffer = &coutBuffer[0];
- Uint32* const copyBuffer = &clogMemBuffer[0];
-
- Uint32 noPrimKey, noMainWords, noCopyWords;
+ 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) {
ljam();
@@ -619,25 +662,27 @@ void Dbtup::executeTrigger(Signal* signal,
for everybody else.
*/
signal->theData[0] = trigPtr->triggerId;
- signal->theData[1] = regOperPtr->fragId >> 1; // send "real" frag id
+ signal->theData[1] = regFragPtr.p->fragmentId;
EXECUTE_DIRECT(BACKUP, GSN_BACKUP_TRIG_REQ, signal, 2);
ljamEntry();
if (signal->theData[0] == 0) {
ljam();
return;
- }//if
- }//if
+ }
+ }
if (!readTriggerInfo(trigPtr,
regOperPtr,
+ req_struct,
+ regFragPtr.p,
keyBuffer,
noPrimKey,
- mainBuffer,
- noMainWords,
- copyBuffer,
- noCopyWords)) {
+ afterBuffer,
+ noAfterWords,
+ beforeBuffer,
+ noBeforeWords)) {
ljam();
return;
- }//if
+ }
//--------------------------------------------------------------------
// 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_
@@ -646,13 +691,13 @@ void Dbtup::executeTrigger(Signal* signal,
//--------------------------------------------------------------------
bool executeDirect;
TrigAttrInfo* const trigAttrInfo = (TrigAttrInfo *)signal->getDataPtrSend();
- trigAttrInfo->setConnectionPtr(regOperPtr->tcOpIndex);
+ trigAttrInfo->setConnectionPtr(req_struct->TC_index);
trigAttrInfo->setTriggerId(trigPtr->triggerId);
switch(trigPtr->triggerType) {
case (TriggerType::SECONDARY_INDEX):
ljam();
- ref = regOperPtr->coordinatorTC;
+ ref = req_struct->TC_ref;
executeDirect = false;
break;
case (TriggerType::SUBSCRIPTION):
@@ -671,110 +716,112 @@ void Dbtup::executeTrigger(Signal* signal,
executeDirect= false; // remove warning
}//switch
- regOperPtr->noFiredTriggers++;
+ req_struct->no_fired_triggers++;
trigAttrInfo->setAttrInfoType(TrigAttrInfo::PRIMARY_KEY);
sendTrigAttrInfo(signal, keyBuffer, noPrimKey, executeDirect, ref);
- Uint32 noAfter = 0;
- Uint32 noBefore = 0;
- switch(regOperPtr->optype) {
+ switch(regOperPtr->op_struct.op_type) {
case(ZINSERT):
ljam();
// Send AttrInfo signals with new attribute values
trigAttrInfo->setAttrInfoType(TrigAttrInfo::AFTER_VALUES);
- sendTrigAttrInfo(signal, mainBuffer, noMainWords, executeDirect, ref);
- noAfter = noMainWords;
+ sendTrigAttrInfo(signal, afterBuffer, noAfterWords, executeDirect, ref);
break;
case(ZDELETE):
if (trigPtr->sendBeforeValues) {
ljam();
trigAttrInfo->setAttrInfoType(TrigAttrInfo::BEFORE_VALUES);
- sendTrigAttrInfo(signal, mainBuffer, noMainWords, executeDirect, ref);
- noBefore = noMainWords;
- }//if
+ sendTrigAttrInfo(signal, beforeBuffer, noBeforeWords, executeDirect,ref);
+ }
break;
case(ZUPDATE):
ljam();
if (trigPtr->sendBeforeValues) {
ljam();
trigAttrInfo->setAttrInfoType(TrigAttrInfo::BEFORE_VALUES);
- sendTrigAttrInfo(signal, copyBuffer, noCopyWords, executeDirect, ref);
- noBefore = noCopyWords;
- }//if
+ sendTrigAttrInfo(signal, beforeBuffer, noBeforeWords, executeDirect,ref);
+ }
trigAttrInfo->setAttrInfoType(TrigAttrInfo::AFTER_VALUES);
- sendTrigAttrInfo(signal, mainBuffer, noMainWords, executeDirect, ref);
- noAfter = noMainWords;
+ sendTrigAttrInfo(signal, afterBuffer, noAfterWords, executeDirect, ref);
break;
default:
ndbrequire(false);
- }//switch
+ }
sendFireTrigOrd(signal,
+ req_struct,
regOperPtr,
trigPtr,
+ regFragPtr.p->fragmentId,
noPrimKey,
- noBefore,
- noAfter);
-}//Dbtup::executeTrigger()
+ noBeforeWords,
+ noAfterWords);
+}
Uint32 Dbtup::setAttrIds(Bitmask<MAXNROFATTRIBUTESINWORDS>& attributeMask,
- Uint32 noOfAttributes,
+ Uint32 m_no_of_attributesibutes,
Uint32* inBuffer)
{
Uint32 bufIndx = 0;
- for (Uint32 i = 0; i < noOfAttributes; i++) {
+ for (Uint32 i = 0; i < m_no_of_attributesibutes; i++) {
ljam();
if (attributeMask.get(i)) {
ljam();
AttributeHeader::init(&inBuffer[bufIndx++], i, 0);
- }//if
- }//for
+ }
+ }
return bufIndx;
-}//Dbtup::setAttrIds()
+}
bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
- Operationrec* const regOperPtr,
+ Operationrec* const regOperPtr,
+ KeyReqStruct *req_struct,
+ Fragrecord* const regFragPtr,
Uint32* const keyBuffer,
Uint32& noPrimKey,
- Uint32* const mainBuffer,
- Uint32& noMainWords,
- Uint32* const copyBuffer,
- Uint32& noCopyWords)
+ Uint32* const afterBuffer,
+ Uint32& noAfterWords,
+ Uint32* const beforeBuffer,
+ Uint32& noBeforeWords)
{
- noCopyWords = 0;
- noMainWords = 0;
+ //XXX this will not work with varsize attributes...
+ noAfterWords = 0;
+ noBeforeWords = 0;
Uint32 readBuffer[MAX_ATTRIBUTES_IN_TABLE];
- PagePtr pagep;
//---------------------------------------------------------------------------
// Set-up variables needed by readAttributes operPtr.p, tabptr.p
//---------------------------------------------------------------------------
operPtr.p = regOperPtr;
- tabptr.i = regOperPtr->tableRef;
+ tabptr.i = regFragPtr->fragTableId;
ptrCheckGuard(tabptr, cnoOfTablerec, tablerec);
+
Tablerec* const regTabPtr = tabptr.p;
-//--------------------------------------------------------------------
-// Initialise pagep and tuple offset for read of main tuple
-//--------------------------------------------------------------------
- Uint32 tupheadoffset = regOperPtr->pageOffset;
- pagep.i = regOperPtr->realPageId;
- ptrCheckGuard(pagep, cnoOfPage, page);
+ 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
//--------------------------------------------------------------------
- int ret= readAttributes(pagep.p,
- tupheadoffset,
- &tableDescriptor[regTabPtr->readKeyArray].tabDescr,
- regTabPtr->noOfKeyAttr,
- keyBuffer,
- ZATTR_BUFFER_SIZE,
- false);
+ if (regTabPtr->need_expand(false)) // no disk
+ prepare_read(req_struct, regTabPtr, false); // setup varsize
+
+ int ret = readAttributes(req_struct,
+ &tableDescriptor[regTabPtr->readKeyArray].tabDescr,
+ regTabPtr->noOfKeyAttr,
+ keyBuffer,
+ ZATTR_BUFFER_SIZE,
+ false);
ndbrequire(ret != -1);
noPrimKey= ret;
Uint32 numAttrsToRead;
- if ((regOperPtr->optype == ZUPDATE) &&
+ if ((regOperPtr->op_struct.op_type == ZUPDATE) &&
(trigPtr->sendOnlyChangedAttributes)) {
ljam();
//--------------------------------------------------------------------
@@ -782,10 +829,11 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
//--------------------------------------------------------------------
Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
attributeMask = trigPtr->attributeMask;
- attributeMask.bitAND(regOperPtr->changeMask);
- numAttrsToRead = setAttrIds(attributeMask, regTabPtr->noOfAttr, &readBuffer[0]);
-
- } else if ((regOperPtr->optype == ZDELETE) &&
+ 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)) {
ljam();
//--------------------------------------------------------------------
@@ -797,63 +845,79 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
//--------------------------------------------------------------------
// All others send all attributes that are monitored
//--------------------------------------------------------------------
- numAttrsToRead = setAttrIds(trigPtr->attributeMask, regTabPtr->noOfAttr, &readBuffer[0]);
- }//if
+ numAttrsToRead = setAttrIds(trigPtr->attributeMask,
+ regTabPtr->m_no_of_attributes, &readBuffer[0]);
+ }
ndbrequire(numAttrsToRead < MAX_ATTRIBUTES_IN_TABLE);
//--------------------------------------------------------------------
// Read Main tuple values
//--------------------------------------------------------------------
- if ((regOperPtr->optype != ZDELETE) ||
- (trigPtr->sendBeforeValues)) {
+ if (regOperPtr->op_struct.op_type != ZDELETE)
+ {
ljam();
- int ret= readAttributes(pagep.p,
- tupheadoffset,
- &readBuffer[0],
- numAttrsToRead,
- mainBuffer,
- ZATTR_BUFFER_SIZE,
- false);
+ int ret = readAttributes(req_struct,
+ &readBuffer[0],
+ numAttrsToRead,
+ afterBuffer,
+ ZATTR_BUFFER_SIZE,
+ false);
ndbrequire(ret != -1);
- noMainWords= ret;
+ noAfterWords= ret;
} else {
ljam();
- noMainWords = 0;
- }//if
+ noAfterWords = 0;
+ }
+
//--------------------------------------------------------------------
// Read Copy tuple values for UPDATE's
//--------------------------------------------------------------------
// Initialise pagep and tuple offset for read of copy tuple
//--------------------------------------------------------------------
- if ((regOperPtr->optype == ZUPDATE) &&
+ if ((regOperPtr->op_struct.op_type == ZUPDATE ||
+ regOperPtr->op_struct.op_type == ZDELETE) &&
(trigPtr->sendBeforeValues)) {
ljam();
+
+ 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);
- tupheadoffset = regOperPtr->pageOffsetC;
- pagep.i = regOperPtr->realPageIdC;
- ptrCheckGuard(pagep, cnoOfPage, page);
-
- int ret= readAttributes(pagep.p,
- tupheadoffset,
- &readBuffer[0],
- numAttrsToRead,
- copyBuffer,
- ZATTR_BUFFER_SIZE,
- false);
+ req_struct->m_tuple_ptr= (Tuple_header*)ptr;
+ }
+ if (regTabPtr->need_expand(false)) // no disk
+ prepare_read(req_struct, regTabPtr, false); // setup varsize
+
+ int ret = readAttributes(req_struct,
+ &readBuffer[0],
+ numAttrsToRead,
+ beforeBuffer,
+ ZATTR_BUFFER_SIZE,
+ false);
+ req_struct->m_tuple_ptr= save;
ndbrequire(ret != -1);
- noCopyWords = ret;
- if ((noMainWords == noCopyWords) &&
- (memcmp(mainBuffer, copyBuffer, noMainWords << 2) == 0)) {
+ noBeforeWords = ret;
+ if ((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
//--------------------------------------------------------------------
ljam();
+ //XXX does this work with collations?
return false;
- }//if
- }//if
+ }
+ }
return true;
-}//Dbtup::readTriggerInfo()
+}
void Dbtup::sendTrigAttrInfo(Signal* signal,
Uint32* data,
@@ -869,7 +933,7 @@ void Dbtup::sendTrigAttrInfo(Signal* signal,
if (sigLen > TrigAttrInfo::DataLength) {
ljam();
sigLen = TrigAttrInfo::DataLength;
- }//if
+ }
MEMCOPY_NO_WORDS(trigAttrInfo->getData(),
data + dataIndex,
sigLen);
@@ -887,25 +951,27 @@ void Dbtup::sendTrigAttrInfo(Signal* signal,
signal,
TrigAttrInfo::StaticLength + sigLen,
JBB);
- }//if
+ }
dataIndex += sigLen;
} while (dataLen != dataIndex);
-}//Dbtup::sendTrigAttrInfo()
+}
-void Dbtup::sendFireTrigOrd(Signal* signal,
+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(regOperPtr->tcOpIndex);
+ fireTrigOrd->setConnectionPtr(req_struct->TC_index);
fireTrigOrd->setTriggerId(trigPtr->triggerId);
- fireTrigOrd->fragId= regOperPtr->fragId >> 1; //Handle two local frags
+ fireTrigOrd->fragId= fragmentId;
- switch(regOperPtr->optype) {
+ switch(regOperPtr->op_struct.op_type) {
case(ZINSERT):
ljam();
fireTrigOrd->setTriggerEvent(TriggerEvent::TE_INSERT);
@@ -921,7 +987,7 @@ void Dbtup::sendFireTrigOrd(Signal* signal,
default:
ndbrequire(false);
break;
- }//switch
+ }
fireTrigOrd->setNoOfPrimaryKeyWords(noPrimKeyWords);
fireTrigOrd->setNoOfBeforeValueWords(noBeforeValueWords);
@@ -930,15 +996,15 @@ void Dbtup::sendFireTrigOrd(Signal* signal,
switch(trigPtr->triggerType) {
case (TriggerType::SECONDARY_INDEX):
ljam();
- sendSignal(regOperPtr->coordinatorTC, GSN_FIRE_TRIG_ORD,
+ sendSignal(req_struct->TC_ref, GSN_FIRE_TRIG_ORD,
signal, FireTrigOrd::SignalLength, JBB);
break;
case (TriggerType::SUBSCRIPTION_BEFORE): // Only Suma
ljam();
// Since only backup uses subscription triggers we
// send to backup directly for now
- fireTrigOrd->setGCI(regOperPtr->gci);
- fireTrigOrd->setHashValue(regOperPtr->hashValue);
+ fireTrigOrd->setGCI(req_struct->gci);
+ fireTrigOrd->setHashValue(req_struct->hash_value);
EXECUTE_DIRECT(trigPtr->m_receiverBlock,
GSN_FIRE_TRIG_ORD,
signal,
@@ -948,7 +1014,7 @@ void Dbtup::sendFireTrigOrd(Signal* signal,
ljam();
// Since only backup uses subscription triggers we
// send to backup directly for now
- fireTrigOrd->setGCI(regOperPtr->gci);
+ fireTrigOrd->setGCI(req_struct->gci);
EXECUTE_DIRECT(trigPtr->m_receiverBlock,
GSN_FIRE_TRIG_ORD,
signal,
@@ -957,8 +1023,8 @@ void Dbtup::sendFireTrigOrd(Signal* signal,
default:
ndbrequire(false);
break;
- }//switch
-}//Dbtup::sendFireTrigOrd()
+ }
+}
/*
* Ordered index triggers.
@@ -975,20 +1041,16 @@ void Dbtup::sendFireTrigOrd(Signal* signal,
int
Dbtup::executeTuxInsertTriggers(Signal* signal,
Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr)
{
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- PagePtr pagePtr;
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 tupVersion = pagePtr.p->pageWord[regOperPtr->pageOffset + 1];
- ndbrequire(tupVersion == regOperPtr->tupVersion);
// fill in constant part
- req->tableId = regOperPtr->tableRef;
- req->fragId = regOperPtr->fragId;
- req->pageId = regOperPtr->realPageId;
- req->pageOffset = regOperPtr->pageOffset;
- req->tupVersion = tupVersion;
+ 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);
}
@@ -996,20 +1058,16 @@ Dbtup::executeTuxInsertTriggers(Signal* signal,
int
Dbtup::executeTuxUpdateTriggers(Signal* signal,
Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr)
{
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- PagePtr pagePtr;
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- Uint32 tupVersion = pagePtr.p->pageWord[regOperPtr->pageOffset + 1];
- ndbrequire(tupVersion == regOperPtr->tupVersion);
// fill in constant part
- req->tableId = regOperPtr->tableRef;
- req->fragId = regOperPtr->fragId;
- req->pageId = regOperPtr->realPageId;
- req->pageOffset = regOperPtr->pageOffset;
- req->tupVersion = tupVersion;
+ 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);
}
@@ -1062,6 +1120,7 @@ fail:
int
Dbtup::executeTuxDeleteTriggers(Signal* signal,
Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr)
{
// do nothing
@@ -1071,45 +1130,33 @@ Dbtup::executeTuxDeleteTriggers(Signal* signal,
void
Dbtup::executeTuxCommitTriggers(Signal* signal,
Operationrec* regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr)
{
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
- // get version
Uint32 tupVersion;
- if (regOperPtr->optype == ZINSERT) {
- if (! regOperPtr->deleteInsertFlag)
+ if (regOperPtr->op_struct.op_type == ZINSERT) {
+ if (! regOperPtr->op_struct.delete_insert_flag)
return;
ljam();
- PagePtr pagePtr;
- pagePtr.i = regOperPtr->realPageIdC;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- tupVersion = pagePtr.p->pageWord[regOperPtr->pageOffsetC + 1];
- ndbrequire(tupVersion != regOperPtr->tupVersion);
- } else if (regOperPtr->optype == ZUPDATE) {
+ tupVersion= decr_tup_version(regOperPtr->tupVersion);
+ } else if (regOperPtr->op_struct.op_type == ZUPDATE) {
ljam();
- PagePtr pagePtr;
- pagePtr.i = regOperPtr->realPageIdC;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- tupVersion = pagePtr.p->pageWord[regOperPtr->pageOffsetC + 1];
- ndbrequire(tupVersion != regOperPtr->tupVersion);
- } else if (regOperPtr->optype == ZDELETE) {
- if (regOperPtr->deleteInsertFlag)
+ tupVersion= decr_tup_version(regOperPtr->tupVersion);
+ } else if (regOperPtr->op_struct.op_type == ZDELETE) {
+ if (regOperPtr->op_struct.delete_insert_flag)
return;
ljam();
- PagePtr pagePtr;
- pagePtr.i = regOperPtr->realPageId;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- tupVersion = pagePtr.p->pageWord[regOperPtr->pageOffset + 1];
- ndbrequire(tupVersion == regOperPtr->tupVersion);
+ tupVersion= regOperPtr->tupVersion;
} else {
ndbrequire(false);
tupVersion= 0; // remove warning
}
// fill in constant part
- req->tableId = regOperPtr->tableRef;
- req->fragId = regOperPtr->fragId;
- req->pageId = regOperPtr->realPageId;
- req->pageOffset = regOperPtr->pageOffset;
+ 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, regOperPtr, regTabPtr);
@@ -1118,18 +1165,19 @@ Dbtup::executeTuxCommitTriggers(Signal* signal,
void
Dbtup::executeTuxAbortTriggers(Signal* signal,
Operationrec* regOperPtr,
+ Fragrecord* const regFragPtr,
Tablerec* const regTabPtr)
{
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
// get version
Uint32 tupVersion;
- if (regOperPtr->optype == ZINSERT) {
+ if (regOperPtr->op_struct.op_type == ZINSERT) {
ljam();
tupVersion = regOperPtr->tupVersion;
- } else if (regOperPtr->optype == ZUPDATE) {
+ } else if (regOperPtr->op_struct.op_type == ZUPDATE) {
ljam();
tupVersion = regOperPtr->tupVersion;
- } else if (regOperPtr->optype == ZDELETE) {
+ } else if (regOperPtr->op_struct.op_type == ZDELETE) {
ljam();
return;
} else {
@@ -1137,10 +1185,10 @@ Dbtup::executeTuxAbortTriggers(Signal* signal,
tupVersion= 0; // remove warning
}
// fill in constant part
- req->tableId = regOperPtr->tableRef;
- req->fragId = regOperPtr->fragId;
- req->pageId = regOperPtr->realPageId;
- req->pageOffset = regOperPtr->pageOffset;
+ 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, regOperPtr, regTabPtr);
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupUndoLog.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupUndoLog.cpp
deleted file mode 100644
index 869f399583f..00000000000
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupUndoLog.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#define DBTUP_C
-#include "Dbtup.hpp"
-#include <RefConvert.hpp>
-#include <ndb_limits.h>
-#include <pc.hpp>
-
-#define ljam() { jamLine(12000 + __LINE__); }
-#define ljamEntry() { jamEntryLine(12000 + __LINE__); }
-
-void Dbtup::cprAddData(Signal* signal,
- Fragrecord* const regFragPtr,
- Uint32 pageIndex,
- Uint32 noOfWords,
- Uint32 startOffset)
-{
- UndoPagePtr undoPagePtr;
- PagePtr pagePtr;
- LocalLogInfoPtr regLliPtr;
-
- regLliPtr.i = regFragPtr->checkpointVersion;
- ptrCheckGuard(regLliPtr, cnoOfParallellUndoFiles, localLogInfo);
-
- pagePtr.i = pageIndex;
- ptrCheckGuard(pagePtr, cnoOfPage, page);
- undoPagePtr.i = regLliPtr.p->lliUndoPage;
- ptrCheckGuard(undoPagePtr, cnoOfUndoPage, undoPage);
-
- startOffset++;
- noOfWords--;
- if ((regLliPtr.p->lliUndoWord + noOfWords) < ZWORDS_ON_PAGE) {
- ljam();
- MEMCOPY_NO_WORDS(&undoPagePtr.p->undoPageWord[regLliPtr.p->lliUndoWord],
- &pagePtr.p->pageWord[startOffset],
- noOfWords);
- regLliPtr.p->lliUndoWord += noOfWords;
- } else {
- for (Uint32 i = 0; i < noOfWords; i++) {
- ljam();
- Uint32 undoWord = pagePtr.p->pageWord[startOffset + i];
- cprAddUndoLogWord(signal, regLliPtr.p, undoWord);
- }//for
- }//if
-}//Dbtup::cprAddData()
-
-void Dbtup::cprAddLogHeader(Signal* signal,
- LocalLogInfo* const lliPtr,
- Uint32 recordType,
- Uint32 tableId,
- Uint32 fragId)
-{
- Uint32 prevRecId = lliPtr->lliPrevRecordId;
- lliPtr->lliPrevRecordId = lliPtr->lliUndoWord + (lliPtr->lliLogFilePage << ZUNDO_RECORD_ID_PAGE_INDEX);
- cprAddUndoLogWord(signal, lliPtr, recordType);
- cprAddUndoLogWord(signal, lliPtr, prevRecId);
- cprAddUndoLogWord(signal, lliPtr, tableId);
- cprAddUndoLogWord(signal, lliPtr, fragId);
-}//Dbtup::cprAddLogHeader()
-
-void Dbtup::cprAddGCIUpdate(Signal* signal,
- Uint32 prevGCI,
- Fragrecord* const regFragPtr)
-{
- LocalLogInfoPtr regLliPtr;
- regLliPtr.i = regFragPtr->checkpointVersion;
- ptrCheckGuard(regLliPtr, cnoOfParallellUndoFiles, localLogInfo);
-
- cprAddUndoLogWord(signal, regLliPtr.p, prevGCI);
-}//Dbtup::cprAddLogHeader()
-
-void Dbtup::cprAddUndoLogPageHeader(Signal* signal,
- Page* const regPagePtr,
- Fragrecord* const regFragPtr)
-{
- UndoPagePtr regUndoPagePtr;
- LocalLogInfoPtr regLliPtr;
-
- regLliPtr.i = regFragPtr->checkpointVersion;
- ptrCheckGuard(regLliPtr, cnoOfParallellUndoFiles, localLogInfo);
-
- Uint32 prevRecId = regLliPtr.p->lliPrevRecordId;
- Uint32 lliWord = regLliPtr.p->lliUndoWord;
- regLliPtr.p->lliPrevRecordId = lliWord +
- (regLliPtr.p->lliLogFilePage << ZUNDO_RECORD_ID_PAGE_INDEX);
- if ((lliWord + 7) < ZWORDS_ON_PAGE) {
- ljam();
- regUndoPagePtr.i = regLliPtr.p->lliUndoPage;
- ptrCheckGuard(regUndoPagePtr, cnoOfUndoPage, undoPage);
-
- regUndoPagePtr.p->undoPageWord[lliWord] = ZLCPR_UNDO_LOG_PAGE_HEADER;
- regUndoPagePtr.p->undoPageWord[lliWord + 1] = prevRecId;
- regUndoPagePtr.p->undoPageWord[lliWord + 2] = regFragPtr->fragTableId;
- regUndoPagePtr.p->undoPageWord[lliWord + 3] = regFragPtr->fragmentId;
- regUndoPagePtr.p->undoPageWord[lliWord + 4] = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
- regUndoPagePtr.p->undoPageWord[lliWord + 5] = regPagePtr->pageWord[ZPAGE_STATE_POS];
- regUndoPagePtr.p->undoPageWord[lliWord + 6] = regPagePtr->pageWord[ZPAGE_NEXT_POS];
- regLliPtr.p->lliUndoWord = lliWord + 7;
- } else {
- ljam();
- cprAddUndoLogWord(signal, regLliPtr.p, ZLCPR_UNDO_LOG_PAGE_HEADER);
- cprAddUndoLogWord(signal, regLliPtr.p, prevRecId);
- cprAddUndoLogWord(signal, regLliPtr.p, regFragPtr->fragTableId);
- cprAddUndoLogWord(signal, regLliPtr.p, regFragPtr->fragmentId);
- cprAddUndoLogWord(signal, regLliPtr.p, regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS]);
- cprAddUndoLogWord(signal, regLliPtr.p, regPagePtr->pageWord[ZPAGE_STATE_POS]);
- cprAddUndoLogWord(signal, regLliPtr.p, regPagePtr->pageWord[ZPAGE_NEXT_POS]);
- }//if
-}//Dbtup::cprAddUndoLogPageHeader()
-
-void Dbtup::cprAddUndoLogRecord(Signal* signal,
- Uint32 recordType,
- Uint32 pageId,
- Uint32 pageIndex,
- Uint32 tableId,
- Uint32 fragId,
- Uint32 localLogIndex)
-{
- LocalLogInfoPtr regLliPtr;
- UndoPagePtr regUndoPagePtr;
-
- regLliPtr.i = localLogIndex;
- ptrCheckGuard(regLliPtr, cnoOfParallellUndoFiles, localLogInfo);
-
- Uint32 prevRecId = regLliPtr.p->lliPrevRecordId;
- Uint32 lliWord = regLliPtr.p->lliUndoWord;
-
- regLliPtr.p->lliPrevRecordId = lliWord +
- (regLliPtr.p->lliLogFilePage << ZUNDO_RECORD_ID_PAGE_INDEX);
- if ((lliWord + 6) < ZWORDS_ON_PAGE) {
- ljam();
- regUndoPagePtr.i = regLliPtr.p->lliUndoPage;
- ptrCheckGuard(regUndoPagePtr, cnoOfUndoPage, undoPage);
- regUndoPagePtr.p->undoPageWord[lliWord] = recordType;
- regUndoPagePtr.p->undoPageWord[lliWord + 1] = prevRecId;
- regUndoPagePtr.p->undoPageWord[lliWord + 2] = tableId;
- regUndoPagePtr.p->undoPageWord[lliWord + 3] = fragId;
- regUndoPagePtr.p->undoPageWord[lliWord + 4] = pageId;
- regUndoPagePtr.p->undoPageWord[lliWord + 5] = pageIndex;
-
- regLliPtr.p->lliUndoWord = lliWord + 6;
- } else {
- ljam();
- cprAddUndoLogWord(signal, regLliPtr.p, recordType);
- cprAddUndoLogWord(signal, regLliPtr.p, prevRecId);
- cprAddUndoLogWord(signal, regLliPtr.p, tableId);
- cprAddUndoLogWord(signal, regLliPtr.p, fragId);
- cprAddUndoLogWord(signal, regLliPtr.p, pageId);
- cprAddUndoLogWord(signal, regLliPtr.p, pageIndex);
- }//if
-}//Dbtup::cprAddUndoLogRecord()
-
-void Dbtup::cprAddAbortUpdate(Signal* signal,
- LocalLogInfo* const lliPtr,
- Operationrec* const regOperPtr)
-{
- Uint32 lliWord = lliPtr->lliUndoWord;
- if ((lliWord + 4) < ZWORDS_ON_PAGE) {
- ljam();
- UndoPagePtr regUndoPagePtr;
- regUndoPagePtr.i = lliPtr->lliUndoPage;
- ptrCheckGuard(regUndoPagePtr, cnoOfUndoPage, undoPage);
-
- regUndoPagePtr.p->undoPageWord[lliWord] = regOperPtr->fragPageId;
- regUndoPagePtr.p->undoPageWord[lliWord + 1] = regOperPtr->pageIndex;
- regUndoPagePtr.p->undoPageWord[lliWord + 2] = regOperPtr->fragPageIdC;
- regUndoPagePtr.p->undoPageWord[lliWord + 3] = regOperPtr->pageIndexC;
- lliPtr->lliUndoWord = lliWord + 4;
- } else {
- ljam();
- cprAddUndoLogWord(signal, lliPtr, regOperPtr->fragPageId);
- cprAddUndoLogWord(signal, lliPtr, regOperPtr->pageIndex);
- cprAddUndoLogWord(signal, lliPtr, regOperPtr->fragPageIdC);
- cprAddUndoLogWord(signal, lliPtr, regOperPtr->pageIndexC);
- }//if
-}//Dbtup::cprAddAbortUpdate()
-
-void Dbtup::cprAddUndoLogWord(Signal* signal, LocalLogInfo* const lliPtr, Uint32 undoWord)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
- UndoPagePtr regUndoPagePtr;
-
- ljam();
- regUndoPagePtr.i = lliPtr->lliUndoPage;
- ptrCheckGuard(regUndoPagePtr, cnoOfUndoPage, undoPage);
- ndbrequire(lliPtr->lliUndoWord < ZWORDS_ON_PAGE);
- regUndoPagePtr.p->undoPageWord[lliPtr->lliUndoWord] = undoWord;
-
- lliPtr->lliUndoWord++;
- if (lliPtr->lliUndoWord == ZWORDS_ON_PAGE) {
- ljam();
- lliPtr->lliUndoWord = ZUNDO_PAGE_HEADER_SIZE;
- lliPtr->lliUndoPage++;
- if (clblPageCounter > 0) {
- ljam();
- clblPageCounter--;
- }//if
- dbsiPtr.i = lliPtr->lliUndoBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- dbsiPtr.p->pdxNumDataPages++;
- ndbrequire(dbsiPtr.p->pdxNumDataPages < 16);
- lliPtr->lliLogFilePage++;
- if (dbsiPtr.p->pdxNumDataPages == ZUB_SEGMENT_SIZE) {
- ljam();
- lcpWriteUndoSegment(signal, lliPtr, false);
- }//if
- }//if
-}//Dbtup::cprAddUndoLogWord()
-
-void Dbtup::lcpWriteUndoSegment(Signal* signal, LocalLogInfo* const lliPtr, bool flushFlag)
-{
- DiskBufferSegmentInfoPtr dbsiPtr;
-
- dbsiPtr.i = lliPtr->lliUndoBufferSegmentP;
- ptrCheckGuard(dbsiPtr, cnoOfConcurrentWriteOp, diskBufferSegmentInfo);
- Uint32 flags = 1;
- lliPtr->lliUndoPagesToDiskWithoutSynch += dbsiPtr.p->pdxNumDataPages;
- if ((lliPtr->lliUndoPagesToDiskWithoutSynch > MAX_PAGES_WITHOUT_SYNCH) ||
- (flushFlag)) {
- ljam();
-/* ---------------------------------------------------------------- */
-// To avoid synching too big chunks at a time we synch after writing
-// a certain number of data pages. (e.g. 2 MBytes).
-/* ---------------------------------------------------------------- */
- lliPtr->lliUndoPagesToDiskWithoutSynch = 0;
- flags |= 0x10; //Set synch flag unconditionally
- }//if
- dbsiPtr.p->pdxOperation = CHECKPOINT_UNDO_WRITE;
- signal->theData[0] = lliPtr->lliUndoFileHandle;
- signal->theData[1] = cownref;
- signal->theData[2] = dbsiPtr.i;
- signal->theData[3] = flags;
- signal->theData[4] = ZBASE_ADDR_UNDO_WORD;
- signal->theData[5] = dbsiPtr.p->pdxNumDataPages;
- signal->theData[6] = dbsiPtr.p->pdxDataPage[0];
- signal->theData[7] = dbsiPtr.p->pdxFilePage;
- sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
-
- DiskBufferSegmentInfoPtr newDbsiPtr;
- UndoPagePtr newUndoPagePtr;
-
- seizeUndoBufferSegment(signal, newUndoPagePtr);
- seizeDiskBufferSegmentRecord(newDbsiPtr);
- newDbsiPtr.p->pdxBuffertype = UNDO_PAGES;
- for (Uint32 i = 0; i < ZUB_SEGMENT_SIZE; i++) {
- newDbsiPtr.p->pdxDataPage[i] = newUndoPagePtr.i + i;
- }//for
- newDbsiPtr.p->pdxFilePage = lliPtr->lliLogFilePage;
- lliPtr->lliUndoPage = newUndoPagePtr.i;
- lliPtr->lliUndoBufferSegmentP = newDbsiPtr.i;
-}//Dbtup::lcpWriteUndoSegment()
-
-void Dbtup::seizeUndoBufferSegment(Signal* signal, UndoPagePtr& regUndoPagePtr)
-{
- if (cnoFreeUndoSeg == ZMIN_PAGE_LIMIT_TUP_COMMITREQ) {
- EXECUTE_DIRECT(DBLQH, GSN_TUP_COM_BLOCK, signal, 1);
- ljamEntry();
- }//if
- cnoFreeUndoSeg--;
- ndbrequire(cnoFreeUndoSeg >= 0);
- ndbrequire(cfirstfreeUndoSeg != RNIL);
- regUndoPagePtr.i = cfirstfreeUndoSeg;
- ptrCheckGuard(regUndoPagePtr, cnoOfUndoPage, undoPage);
- cfirstfreeUndoSeg = regUndoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS];
- regUndoPagePtr.p->undoPageWord[ZPAGE_NEXT_POS] = RNIL;
-}//Dbtup::seizeUndoBufferSegment()
-
-
-
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp
new file mode 100644
index 00000000000..8436c72993d
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp
@@ -0,0 +1,846 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#define DBTUP_C
+#include "Dbtup.hpp"
+
+#define ljam() { jamLine(32000 + __LINE__); }
+#define ljamEntry() { jamEntryLine(32000 + __LINE__); }
+
+
+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;
+}
+
+#if 0
+void
+Dbtup::free_separate_var_part(Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr,
+ Tuple_header* tuple_header)
+{
+ Uint32 page_ref, page_index;
+ PagePtr page_ptr;
+ page_ref= tuple_header->m_data[regTabPtr->var_offset];
+ page_index= page_ref & MAX_TUPLES_PER_PAGE;
+ page_ptr.i= page_ref >> MAX_TUPLES_BITS;
+ ptrCheckGuard(page_ptr, cnoOfPage, cpage);
+ free_var_rec(regFragPtr,
+ regTabPtr,
+ (Var_page*)page_ptr.p,
+ page_index);
+}
+
+
+void
+Dbtup::abort_separate_var_part(Uint32 var_page_ref,
+ const Uint32* copy_var_part,
+ Uint32 copy_var_size)
+{
+ Uint32 page_index;
+ PagePtr var_page_ptr;
+ page_index= var_page_ref & MAX_TUPLES_PER_PAGE;
+ var_page_ptr.i= var_page_ref >> MAX_TUPLES_BITS;
+ ptrCheckGuard(var_page_ptr, cnoOfPage, cpage);
+ Uint32 *ptr= ((Var_page*)var_page_ptr.p)->get_ptr(page_index);
+ MEMCOPY_NO_WORDS(ptr, copy_var_part, copy_var_size);
+}
+
+void
+Dbtup::shrink_entry(Fragrecord* const regFragPtr,
+ Var_page* const page_ptr,
+ Uint32 page_index,
+ Uint32 new_size)
+{
+
+ page_ptr->shrink_entry(page_index, new_size);
+ update_free_page_list(regFragPtr, page_ptr);
+}
+
+void
+Dbtup::check_entry_size(KeyReqStruct* req_struct,
+ Operationrec* regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr)
+{
+#if 0
+ Uint32 vp_index, no_var_attr, total_var_size, add_size, new_size, entry_len;
+ Uint32 vp_offset, tuple_size, var_part_local;
+ Uint32 *var_data_part, *var_link;
+ PagePtr var_page_ptr;
+ Uint32* tuple_ptr= req_struct->m_tuple_ptr;
+ Uint32 page_index= regOperPtr->m_tuple_location.m_page_idx;
+ tuple_size= regTabPtr->tupheadsize;
+ no_var_attr= regTabPtr->no_var_attr;
+ var_part_local= get_var_part_local(* (tuple_ptr+1));
+ add_size= regTabPtr->var_array_wsize;
+ var_link= tuple_ptr+tuple_size;
+ if (var_part_local == 1) {
+ ljam();
+ var_data_part= var_link;
+ var_page_ptr.p= req_struct->fix_page_ptr.p;
+ add_size+= tuple_size;
+ vp_index= regOperPtr->m_tuple_location.m_page_idx;
+ } else {
+ ljam();
+ entry_len= get_entry_len(req_struct->var_page_ptr, page_index);
+ if (entry_len > (tuple_size + 1)) {
+ ljam();
+ shrink_entry(regFragPtr,
+ req_struct->fix_page_ptr,
+ page_index,
+ tuple_size + 1);
+ } else {
+ ndbassert(entry_len == (tuple_size + 1));
+ }
+ set_up_var_page(*var_link,
+ regFragPtr,
+ var_page_ptr,
+ vp_index,
+ vp_offset);
+ var_data_part= &var_page_ptr.p->pageWord[vp_offset];
+ }
+ total_var_size= calculate_total_var_size((uint16*)var_data_part,
+ no_var_attr);
+ new_size= total_var_size + add_size;
+ entry_len= get_entry_len(var_page_ptr.p, vp_index);
+ if (new_size < entry_len) {
+ ljam();
+ shrink_entry(regFragPtr,
+ var_page_ptr.p,
+ vp_index,
+ new_size);
+ } else {
+ ndbassert(entry_len == new_size);
+ }
+#endif
+}
+
+inline
+void
+Dbtup::grow_entry(Fragrecord* const regFragPtr,
+ Var_page* page_header,
+ Uint32 page_index,
+ Uint32 growth_len)
+{
+ page_header->grow_entry(page_index, growth_len);
+ update_free_page_list(regFragPtr, page_header);
+}
+
+
+void
+Dbtup::setup_varsize_part(KeyReqStruct* req_struct,
+ Operationrec* const regOperPtr,
+ Tablerec* const regTabPtr)
+{
+ Uint32 num_var_attr;
+ Uint32 var_data_wsize;
+ Uint32* var_data_ptr;
+ Uint32* var_data_start;
+
+ Uint32 page_index= regOperPtr->m_tuple_location.m_page_idx;
+ if (regTabPtr->var_sized_record) {
+ ljam();
+ num_var_attr= regTabPtr->no_var_attr;
+ if (!(req_struct->m_tuple_ptr->m_header_bits & Tuple_header::CHAINED_ROW))
+ {
+ ljam();
+ var_data_ptr= req_struct->m_tuple_ptr->m_data+regTabPtr->var_offset;
+ req_struct->var_page_ptr.i = req_struct->fix_page_ptr.i;
+ req_struct->var_page_ptr.p = (Var_page*)req_struct->fix_page_ptr.p;
+ req_struct->vp_index= page_index;
+ } else {
+ Uint32 var_link= req_struct->m_tuple_ptr->m_data[regTabPtr->var_offset];
+ ljam();
+
+ Uint32 vp_index= var_link & MAX_TUPLES_PER_PAGE;
+ PagePtr var_page_ptr;
+ var_page_ptr.i= var_link >> MAX_TUPLES_BITS;
+ ptrCheckGuard(var_page_ptr, cnoOfPage, cpage);
+
+ req_struct->vp_index= vp_index;
+ req_struct->var_page_ptr.i= var_page_ptr.i;
+ req_struct->var_page_ptr.p= (Var_page*)var_page_ptr.p;
+
+ var_data_ptr= ((Var_page*)var_page_ptr.p)->get_ptr(vp_index);
+ req_struct->fix_var_together= false;
+ }
+ var_data_start= &var_data_ptr[regTabPtr->var_array_wsize];
+ req_struct->var_len_array= (Uint16*)var_data_ptr;
+ req_struct->var_data_start= var_data_start;
+ var_data_wsize= init_var_pos_array(req_struct->var_len_array,
+ &req_struct->var_pos_array[0],
+ num_var_attr);
+ req_struct->var_data_end= &var_data_start[var_data_wsize];
+ }
+}
+
+
+bool
+Dbtup::compress_var_sized_part_after_update(KeyReqStruct *req_struct,
+ Operationrec* const regOperPtr,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr)
+{
+ Uint32 entry_len, old_var_len, new_size, total_size;
+ Uint32* used_var_data_start= req_struct->var_data_start;
+ total_size= calculate_total_var_size(req_struct->var_len_array,
+ regTabPtr->no_var_attr);
+ entry_len= req_struct->var_page_ptr.p->get_entry_len(req_struct->vp_index);
+ if (req_struct->fix_var_together) {
+ ljam();
+ old_var_len= entry_len -
+ (regTabPtr->tupheadsize + regTabPtr->var_array_wsize);
+ } else {
+ ljam();
+ old_var_len= entry_len - regTabPtr->var_array_wsize;
+ }
+ if (total_size > old_var_len) {
+ ljam();
+ /**
+ * The new total size of the variable part is greater than it was before
+ * the update. We will need to increase the size of the record or split
+ * it into a fixed part and a variable part.
+ */
+ if (! handle_growth_after_update(req_struct,
+ regFragPtr,
+ regTabPtr,
+ (total_size - old_var_len))) {
+ ljam();
+ return false;
+ }
+ } else if (total_size < old_var_len) {
+ ljam();
+ /**
+ * The new total size is smaller than what it was before we started.
+ * In one case we can shrink immediately and this is after an initial
+ * insert since we allocate in this case a full sized tuple and there
+ * is no problem in shrinking this already before committing.
+ *
+ * For all other cases we need to keep the space to ensure that we
+ * can safely abort (which means in this case to grow back to
+ * original size). Thus shrink cannot be done before commit occurs
+ * in those cases.
+ */
+ if (regOperPtr->op_struct.op_type == ZINSERT &&
+ regOperPtr->prevActiveOp == RNIL &&
+ regOperPtr->nextActiveOp == RNIL) {
+ ljam();
+ new_size= entry_len - (old_var_len - total_size);
+ shrink_entry(regFragPtr,
+ req_struct->var_page_ptr.p,
+ req_struct->vp_index,
+ new_size);
+ }
+ }
+ reset_req_struct_data(regTabPtr,
+ req_struct,
+ regOperPtr->m_tuple_location.m_page_idx);
+ copy_back_var_attr(req_struct, regTabPtr, used_var_data_start);
+ return true;
+}
+
+void
+Dbtup::reset_req_struct_data(Tablerec* const regTabPtr,
+ KeyReqStruct* req_struct,
+ Uint32 fix_index)
+{
+ Var_page *var_page_ptr, *fix_page_ptr;
+ Uint32 vp_index;
+
+ fix_page_ptr= (Var_page*)req_struct->fix_page_ptr.p;
+ var_page_ptr= req_struct->var_page_ptr.p;
+ vp_index= req_struct->vp_index;
+
+ req_struct->m_tuple_ptr= (Tuple_header*)fix_page_ptr->get_ptr(fix_index);
+
+ Uint32 vp_len= var_page_ptr->get_entry_len(vp_index);
+
+ Uint32 *var_ptr;
+ if (req_struct->fix_var_together)
+ {
+ ljam();
+ var_ptr= req_struct->m_tuple_ptr->m_data+regTabPtr->var_offset;
+ }
+ else
+ {
+ var_ptr= var_page_ptr->get_ptr(vp_index);
+ }
+
+ req_struct->var_len_array= (Uint16*)(var_ptr);
+ req_struct->var_data_start= var_ptr+regTabPtr->var_array_wsize;
+ req_struct->var_data_end= var_ptr+regTabPtr->var_array_wsize+vp_len;
+}
+
+void
+Dbtup::copy_back_var_attr(KeyReqStruct *req_struct,
+ Tablerec* const regTabPtr,
+ Uint32 *source_rec)
+{
+ Uint32 i, dest_index, vpos_index, byte_size, word_size, num_var_attr;
+ Uint32 *dest_rec, max_var_size, entry_len;
+ Uint32 total_word_size= 0;
+
+#ifdef VM_TRACE
+ entry_len= req_struct->var_page_ptr.p->get_entry_len(req_struct->vp_index);
+ if (req_struct->fix_var_together) {
+ ljam();
+ max_var_size= entry_len - (regTabPtr->tupheadsize +
+ regTabPtr->var_array_wsize);
+ } else {
+ ljam();
+ max_var_size= entry_len - regTabPtr->var_array_wsize;
+ }
+#endif
+ dest_rec= req_struct->var_data_start;
+ num_var_attr= regTabPtr->no_var_attr;
+ ljam();
+ for (i= 0; i < num_var_attr; i++) {
+ dest_index= total_word_size;
+ byte_size= req_struct->var_len_array[i];
+ vpos_index= req_struct->var_pos_array[i];
+ word_size= convert_byte_to_word_size(byte_size);
+ total_word_size+= word_size;
+ req_struct->var_pos_array[i]= total_word_size;
+ MEMCOPY_NO_WORDS(&dest_rec[vpos_index],
+ &source_rec[dest_index],
+ word_size);
+ ndbassert((vpos_index + word_size) <= max_var_size);
+ }
+ ndbassert(total_word_size <= max_var_size);
+ req_struct->var_pos_array[num_var_attr]= total_word_size;
+ req_struct->var_data_end= &req_struct->var_data_start[total_word_size];
+}
+
+
+void
+Dbtup::copy_out_var_attr(KeyReqStruct *req_struct,
+ Tablerec* const regTabPtr)
+{
+ Uint32 i, source_index, byte_size, vpos_index, word_size, last_pos_array;
+ Uint32 num_var_attr= regTabPtr->no_var_attr;
+ Uint16 copy_pos_array[MAX_ATTRIBUTES_IN_TABLE + 1];
+ init_var_len_array(&copy_pos_array[0], regTabPtr);
+ init_var_pos_array(&copy_pos_array[0],
+ &copy_pos_array[0],
+ regTabPtr->no_var_attr);
+
+ Uint32 *source_rec= req_struct->var_data_start;
+ Uint32 *dest_rec= &ctemp_var_record[0];
+ Uint32 total_word_size= 0;
+ ljam();
+ for (i= 0; i < num_var_attr; i++) {
+ source_index= total_word_size;
+ byte_size= req_struct->var_len_array[i];
+ vpos_index= copy_pos_array[i];
+ word_size= convert_byte_to_word_size(byte_size);
+ total_word_size+= word_size;
+ req_struct->var_pos_array[i]= copy_pos_array[i];
+ MEMCOPY_NO_WORDS(&dest_rec[source_index],
+ &source_rec[vpos_index],
+ word_size);
+ }
+ last_pos_array= copy_pos_array[num_var_attr];
+ req_struct->var_data_start= dest_rec;
+ req_struct->var_data_end= &dest_rec[last_pos_array];
+ req_struct->var_part_updated= true;
+ req_struct->var_pos_array[num_var_attr]= last_pos_array;
+}
+
+
+Uint32
+Dbtup::calculate_total_var_size(Uint16* var_len_array,
+ Uint32 num_var_attr)
+{
+ Uint32 i, byte_size, word_size, total_size;
+ total_size= 0;
+ for (i= 0; i < num_var_attr; i++) {
+ byte_size= var_len_array[i];
+ word_size= convert_byte_to_word_size(byte_size);
+ total_size+= word_size;
+ }
+ return total_size;
+}
+
+Uint32
+Dbtup::init_var_pos_array(Uint16* var_len_array,
+ Uint16* var_pos_array,
+ Uint32 num_var_attr)
+{
+ Uint32 i, real_len, word_len;
+ Uint32 curr_pos= 0;
+ for (i= 0, curr_pos= 0; i < num_var_attr; i++) {
+ real_len= var_len_array[i];
+ var_pos_array[i]= curr_pos;
+ word_len= convert_byte_to_word_size(real_len);
+ curr_pos+= word_len;
+ }
+ var_pos_array[num_var_attr]= curr_pos;
+ return curr_pos;
+}
+
+void
+Dbtup::init_var_len_array(Uint16 *var_len_array, Tablerec *tab_ptr)
+{
+ Uint32 array_ind= 0;
+ Uint32 attr_descr, i;
+ Uint32 no_of_attr= tab_ptr->noOfAttr;
+ Uint32 descr_start= tab_ptr->tabDescriptor;
+ TableDescriptor *tab_descr= &tableDescriptor[descr_start];
+ ndbrequire(descr_start + (no_of_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
+ for (i= 0; i < no_of_attr; i++) {
+ attr_descr= tab_descr[i * ZAD_SIZE].tabDescr;
+ if (AttributeDescriptor::getArrayType(attr_descr) == 0) {
+ Uint32 bits_used= AttributeDescriptor::getArraySize(attr_descr) *
+ (1 << AttributeDescriptor::getSize(attr_descr));
+ Uint32 no_attr_bytes= ((bits_used + 7) >> 3);
+ var_len_array[array_ind++]= no_attr_bytes;
+ }
+ }
+}
+
+#endif
+
+/*
+ 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
+ frag_ptr A pointer to the fragment description
+ tab_ptr 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* const frag_ptr,
+ Tablerec* const tab_ptr,
+ Uint32 alloc_size,
+ Local_key* key,
+ Uint32 * out_frag_page_id,
+ Uint32 base)
+{
+ Var_page* page_header;
+ PagePtr page_ptr;
+ page_ptr.i= get_alloc_page(frag_ptr, (alloc_size + 1));
+ if (page_ptr.i == RNIL) {
+ ljam();
+ if ((page_ptr.i= getEmptyPage(frag_ptr)) == RNIL) {
+ ljam();
+ return 0;
+ }
+ ptrCheckGuard(page_ptr, cnoOfPage, cpage);
+ page_header= (Var_page*)page_ptr.p;
+ page_header->init();
+ insert_free_page(frag_ptr, page_header, MAX_FREE_LIST - 1);
+ /*
+ * Tup scan and index build check ZEMPTY_MM to skip un-init()ed
+ * page. Change state here. For varsize it means "page in use".
+ */
+ page_ptr.p->page_state = ZTH_MM_FREE;
+ } else {
+ ptrCheckGuard(page_ptr, cnoOfPage, cpage);
+ ljam();
+ page_header= (Var_page*)page_ptr.p;
+ }
+ Uint32 idx= page_header->alloc_record(alloc_size,
+ (Var_page*)ctemp_page, base);
+
+ key->m_page_no= page_ptr.i;
+ key->m_page_idx= idx;
+ *out_frag_page_id= page_header->frag_page_id;
+ update_free_page_list(frag_ptr, page_header);
+ return page_header->get_ptr(idx);
+}
+
+/*
+ Deallocator for variable sized segments
+ Part of the external interface for variable sized segments
+
+ SYNOPSIS
+ frag_ptr A pointer to the fragment description
+ tab_ptr 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_part(Fragrecord* frag_ptr, Tablerec* tab_ptr,
+ Var_part_ref ref, Uint32 chain)
+{
+ Local_key tmp;
+ PagePtr pagePtr;
+ tmp.m_page_idx= ref.m_ref & MAX_TUPLES_PER_PAGE;
+ pagePtr.i= tmp.m_page_no= ref.m_ref >> MAX_TUPLES_BITS;
+
+ ptrCheckGuard(pagePtr, cnoOfPage, cpage);
+ free_var_part(frag_ptr, tab_ptr, &tmp, (Var_page*)pagePtr.p, chain);
+}
+
+void Dbtup::free_var_part(Fragrecord* const frag_ptr,
+ Tablerec* const tab_ptr,
+ Local_key* key,
+ Var_page* const page_header,
+ Uint32 chain)
+{
+
+ Uint32 page_idx= key->m_page_idx;
+ page_header->free_record(page_idx, chain);
+
+ ndbassert(page_header->free_space <= Var_page::DATA_WORDS);
+ if (page_header->free_space == Var_page::DATA_WORDS - 1)
+ {
+ ljam();
+ /*
+ This code could be used when we release pages.
+ remove_free_page(signal,frag_ptr,page_header,page_header->list_index);
+ return_empty_page(frag_ptr, page_header);
+ */
+ update_free_page_list(frag_ptr, page_header);
+ } else {
+ ljam();
+ update_free_page_list(frag_ptr, page_header);
+ }
+ return;
+}
+
+
+#if 0
+/*
+ This method is called whenever the variable part has been updated and
+ has grown beyond its original size. This means that more space needs to
+ be allocated to the record. If possible this space should be in the
+ same page but we might have to allocate more space in a new page.
+ In the case of a new page we must still keep the old page and the
+ page index since this is the entrance to the record. In this case the
+ record might have to be split into a fixed part and a variable part.
+
+ This routine uses cinBuffer as temporary copy buffer. This is no longer
+ used since it contains the interpreted program to use in the update
+ and this has completed when this function is called.
+
+ SYNOPSIS
+ req_struct The structure for temporary content
+ signal The signal object
+ regOperPtr The operation record
+ regFragPtr The fragment record
+ regTabPtr The table record
+
+ RETURN VALUES
+ bool false if failed due to lack of memory
+ */
+bool
+Dbtup::handle_growth_after_update(KeyReqStruct* req_struct,
+ Fragrecord* const regFragPtr,
+ Tablerec* const regTabPtr,
+ Uint32 growth_len)
+{
+ Uint32 vp_index, alloc_size, entry_len, curr_var_len;
+ Uint32 new_vp_index, new_vp_offset, new_page_ref;
+ Uint32 *copy_record= &cinBuffer[0];
+ Ptr<Var_page> var_page= req_struct->var_page_ptr;
+ Var_page* page_header= var_page.p;
+ vp_index= req_struct->vp_index;
+ entry_len= var_page.p->get_entry_len(vp_index);
+ if (page_header->free_space >= growth_len) {
+ /**
+ * We will be able to handle the growth without changing the page
+ * and page index.
+ */
+ if (page_header->largest_frag_size() >= entry_len + growth_len) {
+ ljam();
+ /**
+ * In this case we need to copy the entry to the free space area of
+ * the page, it is not necessary to reorganise the page.
+ */
+ MEMCOPY_NO_WORDS(page_header->get_free_space_ptr(),
+ page_header->get_ptr(vp_index),
+ entry_len);
+ page_header->set_entry_offset(vp_index, page_header->insert_pos);
+ page_header->insert_pos+= entry_len;
+ } else {
+ ljam();
+ /**
+ * 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.
+ */
+ MEMCOPY_NO_WORDS(copy_record,
+ page_header->get_ptr(vp_index),
+ entry_len);
+ page_header->set_entry_len(vp_index, 0);
+ page_header->free_space+= entry_len;
+ reorg_page(page_header);
+ MEMCOPY_NO_WORDS(page_header->get_free_space_ptr(),
+ copy_record,
+ entry_len);
+ page_header->set_entry_offset(vp_index, page_header->insert_pos);
+ growth_len+= entry_len;
+ }
+ grow_entry(regFragPtr,
+ page_header,
+ vp_index,
+ growth_len);
+ return true;
+ } else {
+ /**
+ * It is necessary to allocate a segment from a new page.
+ */
+ if (req_struct->fix_var_together) {
+ ljam();
+ alloc_size= (entry_len + growth_len) - regTabPtr->tupheadsize;
+ curr_var_len= alloc_size - regTabPtr->var_array_wsize;
+ } else {
+ ljam();
+ curr_var_len= entry_len - regTabPtr->var_array_wsize;
+ alloc_size= entry_len + growth_len;
+ }
+ Uint32* ptr, frag_page_id;
+ Local_key key;
+ if ((ptr= alloc_var_rec(regFragPtr,
+ regTabPtr,
+ alloc_size,
+ &key, &frag_page_id)) == 0)
+ {
+ /**
+ * No space existed for this growth. We need to abort the update.
+ */
+ ljam();
+ terrorCode= ZMEM_NOMEM_ERROR;
+ return false;
+ }
+
+ /*
+ * I need to be careful to copy the var_len_array before freeing it.
+ * The data part will be copied by copy_back_var_attr immediately
+ * after returning from this method.
+ * The updated var part is always in ctemp_var_record since I can
+ * never arrive here after a first insert. Thus no danger of the
+ * var part written being released.
+ */
+ MEMCOPY_NO_WORDS(ptr,
+ req_struct->var_len_array,
+ regTabPtr->var_array_wsize);
+ req_struct->var_len_array= (Uint16*)ptr;
+ if (! req_struct->fix_var_together) {
+ ljam();
+ /*
+ * We need to deallocate the old variable part. This new one will
+ * remain the variable part even if we abort the transaction.
+ * We don't keep multiple references to the variable parts.
+ * The copy data for abort is still kept in the copy record.
+ */
+ free_separate_var_part(regFragPtr, regTabPtr, req_struct->m_tuple_ptr);
+ } else {
+ ljam();
+ req_struct->fix_var_together= false;
+ }
+ page_header= (Var_page*)var_page.p;
+ new_page_ref= (key.m_page_no << MAX_TUPLES_BITS) + key.m_page_idx;
+ req_struct->m_tuple_ptr->m_data[regTabPtr->var_offset] = new_page_ref;
+ Uint32 bits= req_struct->m_tuple_ptr->m_header_bits;
+ req_struct->m_tuple_ptr->m_header_bits |= Tuple_header::CHAINED_ROW;
+ req_struct->var_page_ptr= var_page;
+ req_struct->vp_index= key.m_page_idx;
+ }
+ return true;
+}
+#endif
+
+
+/* ------------------------------------------------------------------------ */
+// 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* const frag_ptr, Uint32 alloc_size)
+{
+ Uint32 i, start_index, loop_count= 0;
+ PagePtr page_ptr;
+
+ start_index= calculate_free_list_impl(alloc_size);
+ if (start_index == (MAX_FREE_LIST - 1)) {
+ ljam();
+ } else {
+ ljam();
+ ndbrequire(start_index < (MAX_FREE_LIST - 1));
+ start_index++;
+ }
+ for (i= start_index; i < MAX_FREE_LIST; i++) {
+ ljam();
+ if (frag_ptr->free_var_page_array[i] != RNIL) {
+ ljam();
+ return frag_ptr->free_var_page_array[i];
+ }
+ }
+ ndbrequire(start_index > 0);
+ i= start_index - 1;
+ page_ptr.i= frag_ptr->free_var_page_array[i];
+ while ((page_ptr.i != RNIL) && (loop_count++ < 16)) {
+ ljam();
+ ptrCheckGuard(page_ptr, cnoOfPage, cpage);
+ Var_page* page_header= (Var_page*)page_ptr.p;
+ if (page_header->free_space >= alloc_size) {
+ ljam();
+ return page_ptr.i;
+ }
+ page_ptr.i= page_header->next_page;
+ }
+ return RNIL;
+}
+
+
+/* ------------------------------------------------------------------------ */
+// Check if the page needs to go to a new free page list.
+/* ------------------------------------------------------------------------ */
+void Dbtup::update_free_page_list(Fragrecord* const frag_ptr,
+ Var_page* page_header)
+{
+ Uint32 free_space, list_index;
+ free_space= page_header->free_space;
+ list_index= page_header->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) {
+ ljam();
+ /*
+ * Only remove it from its list if it is in a list
+ */
+ remove_free_page(frag_ptr, page_header, list_index);
+ }
+ 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.
+ */
+ ljam();
+ ndbrequire(new_list_index == 0);
+ page_header->list_index= MAX_FREE_LIST;
+ } else {
+ ljam();
+ insert_free_page(frag_ptr, page_header, 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++) {
+ ljam();
+ if (free_space_size <= c_max_list_size[i]) {
+ ljam();
+ return i;
+ }
+ }
+ ndbrequire(false);
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+// Remove a page from its current free list
+/* ------------------------------------------------------------------------ */
+void Dbtup::remove_free_page(Fragrecord* frag_ptr,
+ Var_page* page_header,
+ Uint32 index)
+{
+ Var_page* tmp_page_header;
+ if (page_header->prev_page == RNIL) {
+ ljam();
+ ndbassert(index < MAX_FREE_LIST);
+ frag_ptr->free_var_page_array[index]= page_header->next_page;
+ } else {
+ ljam();
+ PagePtr prev_page_ptr;
+ prev_page_ptr.i= page_header->prev_page;
+ ptrCheckGuard(prev_page_ptr, cnoOfPage, cpage);
+ tmp_page_header= (Var_page*)prev_page_ptr.p;
+ tmp_page_header->next_page= page_header->next_page;
+ }
+ if (page_header->next_page != RNIL) {
+ ljam();
+ PagePtr next_page_ptr;
+ next_page_ptr.i= page_header->next_page;
+ ptrCheckGuard(next_page_ptr, cnoOfPage, cpage);
+ tmp_page_header= (Var_page*) next_page_ptr.p;
+ tmp_page_header->prev_page= page_header->prev_page;
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+// Insert a page into a free list on the fragment
+/* ------------------------------------------------------------------------ */
+void Dbtup::insert_free_page(Fragrecord* frag_ptr,
+ Var_page* page_header,
+ Uint32 index)
+{
+ Var_page* tmp_page_header;
+ Uint32 current_head= frag_ptr->free_var_page_array[index];
+ Uint32 pagePtrI = page_header->physical_page_id;
+ page_header->next_page= current_head;
+ ndbassert(index < MAX_FREE_LIST);
+ frag_ptr->free_var_page_array[index]= pagePtrI;
+ page_header->prev_page= RNIL;
+ page_header->list_index= index;
+ if (current_head != RNIL) {
+ ljam();
+ PagePtr head_page_ptr;
+ head_page_ptr.i= current_head;
+ ptrCheckGuard(head_page_ptr, cnoOfPage, cpage);
+ tmp_page_header= (Var_page*)head_page_ptr.p;
+ tmp_page_header->prev_page= pagePtrI;
+ }
+}
+
diff --git a/storage/ndb/src/kernel/blocks/dbtup/Makefile.am b/storage/ndb/src/kernel/blocks/dbtup/Makefile.am
index 3aee511d039..bc6b975a980 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/Makefile.am
+++ b/storage/ndb/src/kernel/blocks/dbtup/Makefile.am
@@ -8,18 +8,19 @@ libdbtup_a_SOURCES = \
DbtupFixAlloc.cpp \
DbtupTrigger.cpp \
DbtupAbort.cpp \
- DbtupLCP.cpp \
- DbtupUndoLog.cpp \
DbtupPageMap.cpp \
DbtupPagMan.cpp \
DbtupStoredProcDef.cpp \
DbtupMeta.cpp \
DbtupTabDesMan.cpp \
DbtupGen.cpp \
- DbtupSystemRestart.cpp \
DbtupIndex.cpp \
+ DbtupDebug.cpp \
DbtupScan.cpp \
- DbtupDebug.cpp
+ DbtupDiskAlloc.cpp DbtupVarAlloc.cpp \
+ tuppage.cpp Undo_buffer.cpp
+
+INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/kernel/blocks/dblqh
include $(top_srcdir)/storage/ndb/config/common.mk.am
include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am
@@ -40,3 +41,12 @@ libdbtup.dsp: Makefile \
@$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES)
@$(top_srcdir)/storage/ndb/config/win-sources $@ $(libdbtup_a_SOURCES)
@$(top_srcdir)/storage/ndb/config/win-libraries $@ LIB $(LDADD)
+
+ndbtest_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/Undo_buffer.cpp b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp
new file mode 100644
index 00000000000..350d6ce8759
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp
@@ -0,0 +1,120 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "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 m_state; // Used by buddy alg
+ Uint32 m_words_used;
+ Uint32 m_ref_count;
+ Uint32 m_data[GLOBAL_PAGE_SIZE_WORDS-3-(sizeof(File_formats::Page_header)>>2)];
+
+ STATIC_CONST( DATA_WORDS = GLOBAL_PAGE_SIZE_WORDS-3-(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->cpage+m_first_free);
+ page->m_state= ~ZFREE_COMMON;
+ page->m_words_used= 0;
+ page->m_ref_count= 0;
+ }
+
+ if(m_first_free < m_tup->cnoOfPage)
+ {
+ page= (UndoPage*)(m_tup->cpage+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;
+ }
+ assert(false);
+ return 0;
+}
+
+void
+Undo_buffer::shrink_copy_tuple(Local_key* key, Uint32 words)
+{
+ assert(key->m_page_no == m_first_free);
+ UndoPage* page= (UndoPage*)(m_tup->cpage+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->cpage+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->cpage+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
new file mode 100644
index 00000000000..db624c9672d
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp
@@ -0,0 +1,57 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef __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
new file mode 100644
index 00000000000..6f3586ddfd2
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbtup/test_varpage.cpp
@@ -0,0 +1,125 @@
+#include <ndb_global.h>
+#include "tuppage.hpp"
+#include <Vector.hpp>
+
+struct Record
+{
+ Uint32 idx;
+ Uint32 size;
+ Uint32* data;
+};
+
+#define TRACE(x) x
+
+static
+void
+cmp(const Uint32 *p1, const Uint32 *p2, Uint32 words)
+{
+ if(memcmp(p1, p2, 4*words) == 0)
+ return;
+
+ 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");
+
+ abort();
+}
+
+static
+void
+do_test(int loops, int dist[3])
+{
+ int allocated= 0;
+ Record records[8192];
+
+ Tup_varsize_page page, tmp;
+ page.init();
+
+ for(int i = 0; i<loops; i++)
+ {
+ for(int j = 0; j<allocated; j++)
+ {
+ Record rec= records[j];
+ Uint32* ptr= page.get_ptr(rec.idx);
+ cmp(ptr, rec.data, rec.size);
+ }
+
+loop:
+ int op;
+ int rnd= rand() % 100;
+ for(op= 0; op<3; 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 " << rec.size << flush;
+ rec.idx= page.alloc_record(rec.size, &tmp, 0);
+ ndbout << " -> " << rec.idx << 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];
+ ndbout << "Free no: " << no << " idx: " << rec.idx << endl;
+ Uint32* ptr= page.get_ptr(rec.idx);
+ 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:
+ ndbout << "Expand" << endl;
+
+ }
+
+ }
+ ndbout << page << endl;
+}
+
+int
+main(void)
+{
+ ndb_init();
+
+ int t1[] = { 30, 90, 100 };
+ int t2[] = { 45, 90, 100 };
+ int t3[] = { 60, 90, 100 };
+ int t4[] = { 75, 90, 100 };
+
+ do_test(10000, t1);
+ do_test(10000, t2);
+ do_test(10000, t3);
+ do_test(10000, t4);
+}
+
+template class Vector<Record>;
diff --git a/storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp b/storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp
new file mode 100644
index 00000000000..aaa0f1314c7
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp
@@ -0,0 +1,330 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+#include "tuppage.hpp"
+#include "Dbtup.hpp"
+
+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] == Dbtup::Tuple_header::FREE);
+
+ 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] == Dbtup::Tuple_header::FREE))
+ {
+ 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] != Dbtup::Tuple_header::FREE);
+
+ 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] == Dbtup::Tuple_header::FREE);
+ }
+
+ next_free_index = page_idx;
+ m_data[page_idx] = 0xFFFF0000 | next;
+ m_data[page_idx + 1] = Dbtup::Tuple_header::FREE;
+
+ return ++free_space;
+}
+
+void
+Tup_varsize_page::init()
+{
+ free_space= DATA_WORDS - 1;
+ high_index= 1;
+ insert_pos= 0;
+ next_free_index= 0xFFFF;
+ m_page_header.m_page_type = File_formats::PT_Tup_varsize_page;
+}
+
+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 == 0xFFFF) {
+ /*
+ 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) & 0xFFFF0000) == 0);
+ next_free_index= get_index_word(page_idx);
+ }
+
+ assert(chain == 0 || chain == CHAIN);
+ * get_index_ptr(page_idx) = insert_pos + ((chain + alloc_size) << 16);
+
+ 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 & 0xFFFF;
+ Uint32 entry_len= (index_word >> 16) & ~CHAIN;
+ assert(chain == 0 || chain == CHAIN);
+ assert(!(((index_word >> 16) ^ chain) & 0x8000));
+#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 {
+ * index_ptr= next_free_index;
+ next_free_index= page_idx;
+ }
+
+ 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 >> 16) == 0)
+ empty++;
+ else
+ break;
+
+ if(index_ptr == end)
+ {
+ // Totally free page
+ high_index = 1;
+ free_space += empty;
+ next_free_index= 0xFFFF;
+ return;
+ }
+
+ Uint32 next= 0xFFFF;
+ high_index -= empty;
+ for(index_ptr++; index_ptr < end; index_ptr++)
+ {
+ if((* index_ptr >> 16) == 0)
+ {
+ * index_ptr= next;
+ next= (end - index_ptr);
+ }
+ }
+
+ free_space += empty;
+ next_free_index= next;
+}
+
+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 >> 16) & ~CHAIN;
+ if (entry_len != 0) {
+ /*
+ 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 & 0xffff;
+ assert(entry_pos + entry_len <= old_insert_pos);
+ assert(new_insert_pos + entry_len <= old_insert_pos);
+ * index_ptr= new_insert_pos + (index_word & 0xFFFF0000);
+ 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 >> 16)
+ out << " pos: " << ((*index_ptr) & 0xFFFF)
+ << " len: " << ((*index_ptr >> 16) & ~page.CHAIN)
+ << (((* index_ptr >> 16) & page.CHAIN) ? " CHAIN " : " ")
+ << "]" << flush;
+ else
+ out << " FREE ]" << flush;
+ }
+
+ out << " free list: " << flush;
+ Uint32 next= page.next_free_index;
+ while(next != 0xFFFF)
+ {
+ out << next << " " << flush;
+ next= * (page.m_data+page.DATA_WORDS-next);
+ }
+ 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;
+ Uint32 startTuple = page.next_free_index >> 16;
+
+#if 0
+ 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
new file mode 100644
index 00000000000..beeb85d063b
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp
@@ -0,0 +1,231 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef __NDB_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( 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
+ **/
+ 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;
+ 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 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 = 0x8000 );
+
+ Uint32 m_data[DATA_WORDS];
+
+ 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);
+
+ /**
+ * 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 & 0xFFFF;
+ Uint32 len= (idx >> 16) & ~CHAIN;
+ 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;
+ Uint32 size= (idx >> 16) + growth_len;
+ *pos= (idx & 0xFFFF) + (size << 16);
+ assert((idx & 0xFFFF) + ((idx >> 16) & ~CHAIN) == insert_pos);
+ 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;
+ *pos= (idx & (CHAIN << 16 | 0xFFFF)) + (new_size << 16);
+ Uint32 old_size= (idx >> 16) & ~CHAIN;
+
+ assert(old_size >= new_size);
+ Uint32 shrink = old_size - new_size;
+#ifdef VM_TRACE
+ memset(m_data + (idx & 0xFFFF) + new_size, 0xF1, 4 * shrink);
+#endif
+ free_space+= shrink;
+ if(insert_pos == ((idx & 0xFFFF) + old_size))
+ insert_pos -= shrink;
+ }
+
+ Uint32* get_ptr(Uint32 page_idx) {
+ return m_data + (get_index_word(page_idx) & 0xFFFF);
+ }
+
+ void set_entry_offset(Uint32 page_idx, Uint32 offset){
+ Uint32 *pos= get_index_ptr(page_idx);
+ *pos = (* pos & 0xFFFF0000) + offset;
+ }
+
+ Uint32 get_entry_len(Uint32 page_idx) const {
+ return get_index_word(page_idx) >> 16;
+ }
+
+ void set_entry_len(Uint32 page_idx, Uint32 len) {
+ Uint32 *pos= get_index_ptr(page_idx);
+ *pos = (len << 16) + (*pos & (CHAIN << 16 | 0xFFFF));
+ }
+};
+
+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
index b34fd5151c2..76ace6b2c56 100644
--- a/storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -110,7 +110,7 @@ public:
private:
// sizes are in words (Uint32)
- STATIC_CONST( MaxIndexFragments = 2 * MAX_FRAG_PER_NODE );
+ STATIC_CONST( MaxIndexFragments = MAX_FRAG_PER_NODE );
STATIC_CONST( MaxIndexAttributes = MAX_ATTRIBUTES_IN_INDEX );
STATIC_CONST( MaxAttrDataSize = 2048 );
public:
@@ -214,7 +214,6 @@ private:
struct TreeEnt {
TupLoc m_tupLoc; // address of original tuple
unsigned m_tupVersion : 15; // version
- unsigned m_fragBit : 1; // which duplicated table fragment
TreeEnt();
// methods
bool eq(const TreeEnt ent) const;
@@ -489,8 +488,8 @@ private:
TupLoc m_freeLoc; // list of free index nodes
DLList<ScanOp> m_scanList; // current scans on this fragment
Uint32 m_tupIndexFragPtrI;
- Uint32 m_tupTableFragPtrI[2];
- Uint32 m_accTableFragPtrI[2];
+ Uint32 m_tupTableFragPtrI;
+ Uint32 m_accTableFragPtrI;
union {
Uint32 nextPool;
};
@@ -907,8 +906,7 @@ Dbtux::TupLoc::operator!=(const TupLoc& loc) const
inline
Dbtux::TreeEnt::TreeEnt() :
m_tupLoc(),
- m_tupVersion(0),
- m_fragBit(0)
+ m_tupVersion(0)
{
}
@@ -917,8 +915,7 @@ Dbtux::TreeEnt::eq(const TreeEnt ent) const
{
return
m_tupLoc == ent.m_tupLoc &&
- m_tupVersion == ent.m_tupVersion &&
- m_fragBit == ent.m_fragBit;
+ m_tupVersion == ent.m_tupVersion;
}
inline int
@@ -936,10 +933,6 @@ Dbtux::TreeEnt::cmp(const TreeEnt ent) const
return -1;
if (m_tupVersion > ent.m_tupVersion)
return +1;
- if (m_fragBit < ent.m_fragBit)
- return -1;
- if (m_fragBit > ent.m_fragBit)
- return +1;
return 0;
}
@@ -1099,10 +1092,8 @@ Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_scanList(scanOpPool),
m_tupIndexFragPtrI(RNIL)
{
- m_tupTableFragPtrI[0] = RNIL;
- m_tupTableFragPtrI[1] = RNIL;
- m_accTableFragPtrI[0] = RNIL;
- m_accTableFragPtrI[1] = RNIL;
+ m_tupTableFragPtrI = RNIL;
+ m_accTableFragPtrI = RNIL;
}
// Dbtux::FragOp
@@ -1282,7 +1273,7 @@ Dbtux::getDescEnt(Uint32 descPage, Uint32 descOff)
inline Uint32
Dbtux::getTupAddr(const Frag& frag, TreeEnt ent)
{
- const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
const TupLoc tupLoc = ent.m_tupLoc;
Uint32 tupAddr = NullTupAddr;
c_tup->tuxGetTupAddr(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), tupAddr);
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index ed29dc57915..a9eae510ce6 100644
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -53,37 +53,7 @@ Dbtux::execDUMP_STATE_ORD(Signal* signal)
return;
}
if (signal->theData[0] == DumpStateOrd::TuxMetaDataJunk) {
- // read table definition
- Uint32 tableId = signal->theData[1];
- Uint32 tableVersion = signal->theData[2];
- int ret;
- MetaData md(this);
- MetaData::Table table;
- MetaData::Attribute attribute;
- infoEvent("md: read table %u %u", tableId, tableVersion);
- if ((ret = md.lock(false)) < 0) {
- infoEvent("md.lock error %d", ret);
- return;
- }
- if ((ret = md.getTable(table, tableId, tableVersion)) < 0) {
- infoEvent("md.getTable error %d", ret);
- // lock is released by destructor
- return;
- }
- infoEvent("md: %s type=%d attrs=%u", table.tableName, table.tableType, table.noOfAttributes);
- for (Uint32 i = 0; i < table.noOfAttributes; i++) {
- if ((ret = md.getAttribute(attribute, table, i)) < 0) {
- infoEvent("mg.getAttribute %u error %d", i, ret);
- // lock is released by destructor
- return;
- }
- infoEvent("md: %d %s", attribute.attributeId, attribute.attributeName);
- }
- if ((ret = md.unlock(false)) < 0) {
- infoEvent("md.unlock error %d", ret);
- return;
- }
- return;
+ abort();
}
#endif
}
@@ -268,8 +238,7 @@ operator<<(NdbOut& out, const Dbtux::TupLoc& loc)
NdbOut&
operator<<(NdbOut& out, const Dbtux::TreeEnt& ent)
{
- out << dec << ent.m_fragBit;
- out << "-" << ent.m_tupLoc;
+ out << ent.m_tupLoc;
out << "-" << dec << ent.m_tupVersion;
return out;
}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index 7c7d762d1e9..9b6085439c3 100644
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -238,7 +238,7 @@ void
Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData)
{
ConstData keyAttrs = c_keyAttrs; // global
- const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
const TupLoc tupLoc = ent.m_tupLoc;
const Uint32 tupVersion = ent.m_tupVersion;
ndbrequire(start < frag.m_numAttrs);
@@ -274,7 +274,7 @@ Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData)
void
Dbtux::readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize)
{
- const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
+ 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();
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index 4b568badc67..b329d694f0b 100644
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -33,7 +33,7 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
jam();
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
- TupLoc tupLoc(sig->pageId, sig->pageOffset);
+ TupLoc tupLoc(sig->pageId, sig->pageIndex);
debugOut << "opInfo=" << hex << sig->opInfo;
debugOut << " tableId=" << dec << sig->tableId;
debugOut << " indexId=" << dec << sig->indexId;
@@ -57,8 +57,7 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
c_indexPool.getPtr(indexPtr, req->indexId);
ndbrequire(indexPtr.p->m_tableId == req->tableId);
// get base fragment id and extra bits
- const Uint32 fragId = req->fragId & ~1;
- const Uint32 fragBit = req->fragId & 1;
+ const Uint32 fragId = req->fragId;
// get the fragment
FragPtr fragPtr;
fragPtr.i = RNIL;
@@ -76,9 +75,8 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
setKeyAttrs(frag);
// set up search entry
TreeEnt ent;
- ent.m_tupLoc = TupLoc(req->pageId, req->pageOffset);
+ ent.m_tupLoc = TupLoc(req->pageId, req->pageIndex);
ent.m_tupVersion = req->tupVersion;
- ent.m_fragBit = fragBit;
// read search key
readKeyAttrs(frag, ent, 0, c_searchKey);
if (! frag.m_storeNullKey) {
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index 93c4a583624..7703b3e6ab8 100644
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -89,10 +89,8 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
fragPtr.p->m_numAttrs = req->noOfAttr;
fragPtr.p->m_storeNullKey = true; // not yet configurable
fragPtr.p->m_tupIndexFragPtrI = req->tupIndexFragPtrI;
- fragPtr.p->m_tupTableFragPtrI[0] = req->tupTableFragPtrI[0];
- fragPtr.p->m_tupTableFragPtrI[1] = req->tupTableFragPtrI[1];
- fragPtr.p->m_accTableFragPtrI[0] = req->accTableFragPtrI[0];
- fragPtr.p->m_accTableFragPtrI[1] = req->accTableFragPtrI[1];
+ 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;
diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index a61b7c1f5ca..3c0b2c4ed3f 100644
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -35,7 +35,7 @@ Dbtux::execACC_SCANREQ(Signal* signal)
fragPtr.i = RNIL;
for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) {
jam();
- if (indexPtr.p->m_fragId[i] == req->fragmentNo << 1) {
+ if (indexPtr.p->m_fragId[i] == req->fragmentNo) {
jam();
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
break;
@@ -161,8 +161,19 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
Uint32 dstWords = 0;
if (! ah->isNULL()) {
jam();
+ const uchar* srcPtr = (const uchar*)&data[offset + 2];
const DescAttr& descAttr = descEnt.m_descAttr[attrId];
- Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(descAttr.m_attrDesc);
+ 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();
@@ -171,27 +182,17 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
return;
}
uchar* dstPtr = (uchar*)&xfrmData[dstPos + 2];
- const uchar* srcPtr = (const uchar*)&data[offset + 2];
if (descAttr.m_charset == 0) {
memcpy(dstPtr, srcPtr, srcWords << 2);
dstWords = srcWords;
} else {
jam();
- Uint32 typeId = descAttr.m_typeId;
- Uint32 lb, len;
- bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
- if (! ok) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidCharFormat;
- return;
- }
CHARSET_INFO* cs = all_charsets[descAttr.m_charset];
Uint32 xmul = cs->strxfrm_multiply;
if (xmul == 0)
xmul = 1;
// see comment in DbtcMain.cpp
- Uint32 dstLen = xmul * (srcBytes - lb);
+ Uint32 dstLen = xmul * (maxBytes - lb);
if (dstLen > ((dstSize - dstPos) << 2)) {
jam();
scan.m_state = ScanOp::Invalid;
@@ -410,7 +411,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = RNIL; // no tuple returned
- conf->fragId = frag.m_fragId | ent.m_fragBit;
+ 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,
@@ -453,8 +454,8 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
lockReq->userPtr = scanPtr.i;
lockReq->userRef = reference();
lockReq->tableId = scan.m_tableId;
- lockReq->fragId = frag.m_fragId | ent.m_fragBit;
- lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit];
+ 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);
@@ -545,7 +546,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
accLockOp = (Uint32)-1;
}
conf->accOperationPtr = accLockOp;
- conf->fragId = frag.m_fragId | ent.m_fragBit;
+ conf->fragId = frag.m_fragId;
conf->localKey[0] = getTupAddr(frag, ent);
conf->localKey[1] = 0;
conf->localKeyLength = 1;
@@ -928,14 +929,13 @@ Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent)
{
const ScanOp& scan = *scanPtr.p;
const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
- Uint32 fragBit = ent.m_fragBit;
- Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit];
- Uint32 fragId = frag.m_fragId | fragBit;
+ Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
+ Uint32 fragId = frag.m_fragId;
Uint32 tupAddr = getTupAddr(frag, ent);
Uint32 tupVersion = ent.m_tupVersion;
// check for same tuple twice in row
- if (scan.m_scanEnt.m_tupLoc == ent.m_tupLoc &&
- scan.m_scanEnt.m_fragBit == fragBit) {
+ if (scan.m_scanEnt.m_tupLoc == ent.m_tupLoc)
+ {
jam();
return false;
}
diff --git a/storage/ndb/src/kernel/blocks/dbtux/Makefile.am b/storage/ndb/src/kernel/blocks/dbtux/Makefile.am
index 41eefaf0c3e..857cdf3f861 100644
--- a/storage/ndb/src/kernel/blocks/dbtux/Makefile.am
+++ b/storage/ndb/src/kernel/blocks/dbtux/Makefile.am
@@ -12,7 +12,8 @@ libdbtux_a_SOURCES = \
DbtuxStat.cpp \
DbtuxDebug.cpp
-INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/kernel/blocks/dbtup
+INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/kernel/blocks/dbtup \
+ -I$(top_srcdir)/storage/ndb/src/kernel/blocks/dblqh
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/dbutil/DbUtil.cpp b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
index 093735b9567..6401ac35820 100644
--- a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
+++ b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
@@ -1863,6 +1863,14 @@ DbUtil::execUTIL_EXECUTE_REQ(Signal* signal)
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();
@@ -1870,10 +1878,9 @@ DbUtil::execUTIL_EXECUTE_REQ(Signal* signal)
if (TcKeyReq::getOperationType(prepOpPtr.p->tckey.requestInfo) != ZREAD){
ndbrequire(l1 == l2);
} else {
-#if 0
ndbout_c("TcKeyReq::Read");
-#endif
}
+#endif
releaseSections(signal);
transPtr.p->noOfRetries = 3;
diff --git a/storage/ndb/src/kernel/blocks/diskpage.cpp b/storage/ndb/src/kernel/blocks/diskpage.cpp
new file mode 100644
index 00000000000..57e2194ea93
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/diskpage.cpp
@@ -0,0 +1,75 @@
+
+#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 << ", " <<
+ getVersionString(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
new file mode 100644
index 00000000000..108352f8fb7
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/diskpage.hpp
@@ -0,0 +1,236 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef __NDB_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)
+ 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;
+ };
+ 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_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_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 & 0x7777)
+ 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
new file mode 100644
index 00000000000..32a588caf35
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/lgman.cpp
@@ -0,0 +1,2952 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "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 "ndbfs/Ndbfs.hpp"
+#include "dbtup/Dbtup.hpp"
+
+#include <EventLogger.hpp>
+extern EventLogger g_eventLogger;
+
+/**
+ * ---<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(const Configuration & conf) :
+ SimulatedBlock(LGMAN, conf),
+ 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);
+
+ m_last_lsn = 0;
+ m_logfile_group_pool.setSize(10);
+ m_logfile_group_hash.setSize(10);
+ m_file_pool.setSize(10);
+ m_data_buffer_pool.setSize(10);
+ m_log_waiter_pool.setSize(10000);
+}
+
+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 =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
+void
+Lgman::execSTTOR(Signal* signal)
+{
+ jamEntry();
+
+ const Uint32 startphase = signal->theData[1];
+ const Uint32 typeOfStart = signal->theData[7];
+
+ 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);
+ 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",
+ 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_sync_waiters.isEmpty());
+ 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_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);
+
+ 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();
+
+ 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();
+ ndbassert(! (ptr.p->m_state & Logfile_group::LG_THREAD_MASK));
+ ndbrequire(ptr.p->m_meta_files.isEmpty());
+ ndbrequire(ptr.p->m_outstanding_fs == 0);
+
+ LocalDLFifoList<Undofile> 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;
+ }
+
+ 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:
+ {
+ 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))
+ {
+ 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();
+ conf->senderData = senderData;
+ conf->senderRef = reference();
+ sendSignal(senderRef, GSN_CREATE_FILE_CONF, signal,
+ CreateFileImplConf::SignalLength, JBB);
+ return;
+ }
+ return;
+ }
+ default: // prepare
+ break;
+ }
+
+ if (!m_file_pool.seize(file_ptr))
+ {
+ jam();
+ err = CreateFileImplRef::OutOfFileRecords;
+ break;
+ }
+
+ new (file_ptr.p) Undofile(req, ptr.i);
+ LocalDLFifoList<Undofile> 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);
+ }
+
+ LocalDLFifoList<Undofile> 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,
+ DLFifoList<Undofile>::Head& head, Uint32 id)
+{
+ LocalDLFifoList<Undofile> 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)
+ {
+ jam();
+ LocalDLFifoList<Undofile> free(m_file_pool, lg_ptr.p->m_files);
+ LocalDLFifoList<Undofile> 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;
+ sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
+ }
+ }
+ else
+ {
+ ptr.p->m_state = Undofile::FS_SORTING;
+ }
+
+ 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();
+ {
+ LocalDLFifoList<Undofile> list(m_file_pool, lg_ptr.p->m_files);
+ list.release(ptr);
+ }
+ drop_filegroup_drop_files(signal, lg_ptr, senderRef, senderData);
+ }
+ else
+ {
+ jam();
+ LocalDLFifoList<Undofile> 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_last_lsn = 0;
+ m_last_synced_lsn = 0;
+ m_last_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)
+{
+ /**
+ * TODO use buddy allocator
+ */
+ 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)
+ {
+ Ptr<GlobalPage> page;
+ if(m_global_page_pool.seize(page))
+ {
+ Buffer_idx range;
+ range.m_ptr_i= page.i;
+ range.m_idx = 1;
+ while(pages >range.m_idx && m_global_page_pool.seizeId(page, page.i+1))
+ range.m_idx++;
+
+ 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);
+ LocalDLFifoList<Undofile> 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;
+ while(range.m_idx)
+ {
+ m_global_page_pool.release(range.m_ptr_i);
+ 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;
+ {
+ LocalDLFifoList<Lgman::Log_waiter>
+ 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));
+ }
+
+ 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)
+{
+ LocalDLFifoList<Lgman::Log_waiter>
+ 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_global_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
+ */
+ ndbassert(ptr.p->m_free_file_words >= free);
+ ndbassert(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;
+ }
+ }
+
+
+ Ptr<Lgman::Log_waiter> last;
+ if(list.last(last) &&
+ last.p->m_sync_lsn > force_lsn &&
+ ptr.p->m_last_sync_req_lsn < last.p->m_sync_lsn)
+ {
+ ndbassert(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] = last.p->m_sync_lsn >> 32;
+ signal->theData[3] = last.p->m_sync_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)
+{
+ LocalDLFifoList<Log_waiter>
+ 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);
+
+ 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, 0);
+
+ list.release(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_global_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
+ ndbassert(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
+ */
+ ndbassert(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_global_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;
+ LocalDLFifoList<Lgman::Log_waiter>
+ 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));
+ }
+
+ if(empty)
+ { // Start ContinueB
+ m_lgman->process_log_buffer_waiters(signal, ptr);
+ }
+ 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)
+{
+ 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
+ ndbout_c("ptr.p->m_file_pos[HEAD].m_ptr_i= %x",
+ 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();
+ signal->theData[0] = LgmanContinueB::FLUSH_LOG;
+ signal->theData[1] = ptr.i;
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
+ }
+ 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
+ ndbassert(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;
+ sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
+ }
+ else
+ {
+ ptr.p->m_state &= ~(Uint32)Logfile_group::LG_FLUSH_THREAD;
+ }
+
+ if(tot > 0 && !ptr.p->m_log_buffer_waiters.isEmpty() &&
+ !(ptr.p->m_state & Logfile_group::LG_WAITERS_THREAD))
+ {
+ jam();
+ process_log_buffer_waiters(signal, ptr);
+ }
+}
+
+void
+Lgman::process_log_buffer_waiters(Signal* signal, Ptr<Logfile_group> ptr)
+{
+ Uint32 free_buffer= ptr.p->m_free_buffer_words;
+ LocalDLFifoList<Log_waiter>
+ 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);
+ 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, 0);
+
+ list.release(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;
+ }
+}
+
+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::fsFormatGlobalPage);
+
+ if(max > pages)
+ {
+ jam();
+ max= pages;
+ head.m_idx += max;
+ ptr.p->m_file_pos[HEAD] = head;
+
+ 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_global_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);
+
+ 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_global_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;
+ LocalDLFifoList<Undofile> 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);
+ ndbassert(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);
+
+ ndbassert(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;
+ ndbassert(cnt);
+
+ if(lg_ptr.p->m_next_reply_ptr_i == ptr.i)
+ {
+ Uint32 tot= 0;
+ Uint64 lsn = 0;
+ LocalDLFifoList<Undofile> 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;
+ ndbassert(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);
+ }
+
+ 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);
+ }
+ }
+
+ 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())
+ {
+ 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));
+ ndbassert(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));
+ ndbassert(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())
+ {
+ /**
+ * 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: %d",
+ 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,
+ (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)
+{
+ 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);
+
+ bool done= true;
+ 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;
+ LocalDLFifoList<Undofile> files(m_file_pool, ptr.p->m_files);
+ while(files.next(next) && (next.p->m_state & Undofile::FS_EMPTY))
+ ndbassert(next.i != filePtr.i);
+ if(next.isNull())
+ {
+ jam();
+ files.first(next);
+ while((next.p->m_state & Undofile::FS_EMPTY) && files.next(next))
+ ndbassert(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();
+ Uint32 gci= ((SubGcpCompleteRep*)signal->getDataPtr())->gci;
+
+ 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)
+{
+ ndbassert(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)
+{
+ ndbassert(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;
+ }
+ ndbassert(false);
+ return -1;
+}
+
+template<Uint32 cnt>
+Uint64
+Logfile_client::add_entry(const Change* src)
+{
+ 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;
+ }
+}
+
+template Uint64 Logfile_client::add_entry<1>(const Change*);
+template Uint64 Logfile_client::add_entry<3>(const Change*);
+
+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);
+ 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)
+{
+ if(ptr.p->m_meta_files.isEmpty() && ptr.p->m_files.isEmpty())
+ {
+ jam();
+ /**
+ * Logfile_group wo/ any files
+ */
+
+ 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...)
+ */
+ LocalDLFifoList<Undofile> 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::fsFormatGlobalPage);
+
+ 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
+ */
+ ndbassert(!ptr.p->m_files.isEmpty());
+ LocalDLFifoList<Undofile> 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::fsFormatGlobalPage);
+
+ 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);
+
+ ndbassert(ptr.p->m_state & Undofile::FS_OUTSTANDING);
+ ptr.p->m_state &= ~(Uint32)Undofile::FS_OUTSTANDING;
+
+ Uint32 cnt= lg_ptr.p->m_outstanding_fs;
+ ndbassert(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;
+ LocalDLFifoList<Undofile> 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;
+ ndbassert(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_global_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
+ */
+ {
+ LocalDLFifoList<Undofile> meta(m_file_pool, lg_ptr.p->m_meta_files);
+ LocalDLFifoList<Undofile> 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;
+
+ ndbassert(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::fsFormatGlobalPage);
+
+ 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;
+
+ {
+ LocalDLFifoList<Undofile> 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;
+ DLFifoList<Logfile_group>& list= m_logfile_group_list;
+ DLFifoList<Logfile_group> 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_global_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 postion 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;
+ ndbassert(free >= max * File_formats::UNDO_PAGE_WORDS);
+ cnt= read_undo_pages(signal, ptr, producer.m_current_pos.m_ptr_i, max);
+ ndbassert(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;
+ ndbassert(free >= max * File_formats::UNDO_PAGE_WORDS);
+ cnt= read_undo_pages(signal, ptr, producer.m_current_pos.m_ptr_i, max);
+ ndbassert(cnt <= max);
+ producer.m_current_pos.m_ptr_i -= cnt;
+ producer.m_current_page.m_idx -= cnt;
+ }
+
+ ndbassert(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)
+{
+ ndbassert(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::fsFormatGlobalPage);
+
+
+ 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();
+
+ ndbassert(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;
+ LocalDLFifoList<Undofile> 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(lcp > m_latest_lcp)
+ {
+ // Just ignore
+ break;
+ }
+
+ if(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:
+ 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_global_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;
+ ndbassert(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
+ {
+ ndbassert(pos >= 3);
+ lsn += * (prev - 1); lsn <<= 32;
+ lsn += * (prev - 0);
+ len += 2;
+ ndbrequire((Int64)lsn >= 0);
+ }
+
+
+ ndbassert(pos >= len);
+
+ if(pos == len)
+ {
+ /**
+ * Switching page
+ */
+ ndbassert(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_global_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)
+ ndbassert(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
+ */
+ ndbassert(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;
+ ndbassert(size >= page);
+ Uint32 diff= size - page;
+
+ if(pages >= diff)
+ {
+ pages -= diff;
+ LocalDLFifoList<Undofile> 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);
+ 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;
+
+ signal->theData[0] = LgmanContinueB::FLUSH_LOG;
+ signal->theData[1] = ptr.i;
+ sendSignal(reference(), GSN_CONTINUEB, signal, 2, 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)
+{
+ /**
+ * 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));
+ ndbassert(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));
+ ndbassert(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)
+{
+ if (ptr.p->m_file_pos[HEAD].m_ptr_i == RNIL)
+ return;
+
+ 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);
+ }
+}
+#endif
diff --git a/storage/ndb/src/kernel/blocks/lgman.hpp b/storage/ndb/src/kernel/blocks/lgman.hpp
new file mode 100644
index 00000000000..e89babf1d06
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/lgman.hpp
@@ -0,0 +1,342 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef 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"
+
+class Lgman : public SimulatedBlock
+{
+public:
+ Lgman(const Configuration & conf);
+ 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*);
+public:
+ struct Log_waiter
+ {
+ union {
+ Uint32 m_size;
+ Uint64 m_sync_lsn;
+ };
+ Uint32 m_block;
+ Callback m_callback;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+
+ struct Undofile
+ {
+ Undofile(){}
+ Undofile(const struct CreateFileImplReq*, Uint32 lg_ptr_i);
+
+ 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 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*);
+
+ 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
+ };
+
+ 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;
+ Uint64 m_last_synced_lsn;
+ union {
+ Uint64 m_last_read_lsn;
+ Uint64 m_last_lcp_lsn;
+ };
+ DLFifoList<Log_waiter>::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
+
+ DLFifoList<Undofile>::Head m_files; // Files in log
+ DLFifoList<Undofile>::Head m_meta_files;// Files being created or dropped
+
+ Uint32 m_free_buffer_words; // Free buffer page words
+ DLFifoList<Log_waiter>::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;
+ }
+ };
+
+ /**
+ * 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;
+ ArrayPool<Undofile> m_file_pool;
+ ArrayPool<Logfile_group> m_logfile_group_pool;
+ ArrayPool<Log_waiter> m_log_waiter_pool;
+
+ Page_map::DataBufferPool m_data_buffer_pool;
+
+ Uint64 m_last_lsn;
+ Uint32 m_latest_lcp;
+ DLFifoList<Logfile_group> m_logfile_group_list;
+ KeyTable<Logfile_group> 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 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>&, DLFifoList<Undofile>::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);
+ template<Uint32 cnt> Uint64 add_entry(const Change*);
+
+ 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/ndbcntr/NdbcntrMain.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 88c0da8b9ae..89fe83f6bf4 100644
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -81,6 +81,10 @@ static BlockInfo ALL_BLOCKS[] = {
{ 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);
@@ -100,7 +104,11 @@ static BlockReference readConfigOrder[ALL_BLOCKS_SZ] = {
TRIX_REF,
BACKUP_REF,
DBUTIL_REF,
- SUMA_REF
+ SUMA_REF,
+ TSMAN_REF,
+ LGMAN_REF,
+ PGMAN_REF,
+ RESTORE_REF
};
/*******************************/
@@ -1594,7 +1602,6 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
//w.add(DictTabInfo::MinLoadFactor, 70);
//w.add(DictTabInfo::MaxLoadFactor, 80);
w.add(DictTabInfo::FragmentTypeVal, (Uint32)table.fragmentType);
- //w.add(DictTabInfo::TableStorageVal, (Uint32)DictTabInfo::MainMemory);
//w.add(DictTabInfo::NoOfKeyAttr, 1);
w.add(DictTabInfo::NoOfAttributes, (Uint32)table.columnCount);
//w.add(DictTabInfo::NoOfNullable, (Uint32)0);
@@ -1606,9 +1613,12 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
const SysColumn& column = table.columnList[i];
ndbassert(column.pos == i);
w.add(DictTabInfo::AttributeName, column.name);
- w.add(DictTabInfo::AttributeId, (Uint32)column.pos);
+ w.add(DictTabInfo::AttributeId, (Uint32)i);
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)column.keyFlag);
- //w.add(DictTabInfo::AttributeStorage, (Uint32)DictTabInfo::MainMemory);
+ 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);
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index 5e815cb0511..a9cbd558921 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -24,7 +24,9 @@
#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
@@ -85,7 +87,7 @@ extern "C" void * runAsyncFile(void* arg)
return (NULL);
}
-AsyncFile::AsyncFile() :
+AsyncFile::AsyncFile(SimulatedBlock& fs) :
theFileName(),
#ifdef NDB_WIN32
hFile(INVALID_HANDLE_VALUE),
@@ -93,17 +95,16 @@ AsyncFile::AsyncFile() :
theFd(-1),
#endif
theReportTo(0),
- theMemoryChannelPtr(NULL)
+ theMemoryChannelPtr(NULL),
+ m_fs(fs)
{
+ m_page_ptr.setNull();
m_current_request= m_last_request= 0;
}
void
-AsyncFile::doStart(Uint32 nodeId,
- const char * filesystemPath,
- const char * backup_path) {
- theFileName.init(nodeId, filesystemPath, backup_path);
-
+AsyncFile::doStart()
+{
// Stacksize for filesystem threads
// An 8k stack should be enough
const NDB_THREAD_STACKSIZE stackSize = 8192;
@@ -189,6 +190,7 @@ AsyncFile::run()
closeReq(request);
removeReq(request);
break;
+ case Request:: readPartial:
case Request:: read:
readReq(request);
break;
@@ -236,7 +238,6 @@ AsyncFile::run()
}//AsyncFile::run()
extern bool Global_useO_SYNC;
-extern bool Global_useO_DIRECT;
extern bool Global_unlinkO_CREAT;
extern Uint32 Global_syncFreq;
@@ -322,35 +323,29 @@ void AsyncFile::openReq(Request* request)
new_flags |= O_TRUNC;
}
+ if (flags & FsOpenReq::OM_AUTOSYNC)
+ {
+ m_syncFrequency = 1024*1024; // Hard coded to 1M
+ }
+
if(flags & FsOpenReq::OM_APPEND){
new_flags |= O_APPEND;
}
- if(flags & FsOpenReq::OM_SYNC){
-#if 0
- if(Global_useO_SYNC){
- new_flags |= O_SYNC;
- m_openedWithSync = true;
- m_syncFrequency = 0;
- } else {
-#endif
- m_openedWithSync = false;
- m_syncFrequency = Global_syncFreq;
-#if 0
- }
+ if((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT))
+ {
+#ifdef O_SYNC
+ new_flags |= O_SYNC;
#endif
- } else {
- m_openedWithSync = false;
- m_syncFrequency = 0;
}
-
-#if 0
- //#if NDB_LINUX
- if(Global_useO_DIRECT){
+
+#ifdef O_DIRECT
+ if (flags & FsOpenReq::OM_DIRECT)
+ {
new_flags |= O_DIRECT;
}
#endif
-
+
switch(flags & 0x3){
case FsOpenReq::OM_READONLY:
new_flags |= O_RDONLY;
@@ -366,11 +361,20 @@ void AsyncFile::openReq(Request* request)
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;
+ const int mode = S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH;
+retry:
+ if(flags & FsOpenReq::OM_CREATE_IF_NONE){
+ if((theFd = ::open(theFileName.c_str(), new_flags, mode)) != -1) {
+ close(theFd);
+ request->error = FsRef::fsErrFileExists;
+ return;
+ }
+ new_flags |= O_CREAT;
+ }
if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) {
PRINT_ERRORANDFLAGS(new_flags);
@@ -379,18 +383,98 @@ void AsyncFile::openReq(Request* request)
if (-1 == (theFd = ::open(theFileName.c_str(), new_flags, mode))) {
PRINT_ERRORANDFLAGS(new_flags);
request->error = errno;
+ return;
}
} else {
request->error = errno;
+ return;
+ }
+ }
+
+ if(flags & FsOpenReq::OM_CHECK_SIZE)
+ {
+ struct stat buf;
+ if((fstat(theFd, &buf) == -1))
+ {
+ request->error = errno;
+ } else if(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_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);
+ 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)
+ {
+ close(theFd);
+ unlink(theFileName.c_str());
+ request->error = errno;
+ return;
+ }
+ off += request->par.open.page_size;
}
+ if(lseek(theFd, 0, SEEK_SET) != 0)
+ request->error = errno;
+ }
+
+ if ((flags & FsOpenReq::OM_SYNC) && (flags & FsOpenReq::OM_INIT))
+ {
+ /**
+ * reopen file with O_SYNC
+ */
+ close(theFd);
+ new_flags &= ~(O_CREAT | O_TRUNC);
+#ifdef O_SYNC
+ new_flags |= O_SYNC;
+#endif
+ theFd = ::open(theFileName.c_str(), new_flags, mode);
}
#endif
}
int
-AsyncFile::readBuffer(char * buf, size_t size, off_t offset){
+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) {
@@ -436,17 +520,22 @@ AsyncFile::readBuffer(char * buf, size_t size, off_t offset){
}
#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));
+ 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));
+ bytes_read, size));
}
-
+
buf += bytes_read;
size -= bytes_read;
offset += bytes_read;
@@ -462,7 +551,7 @@ AsyncFile::readReq( Request * request)
size_t size = request->par.readWrite.pages[i].size;
char * buf = request->par.readWrite.pages[i].buf;
- int err = readBuffer(buf, size, offset);
+ int err = readBuffer(request, buf, size, offset);
if(err != 0){
request->error = err;
return;
@@ -891,13 +980,20 @@ void AsyncFile::endReq()
void AsyncFile::createDirectories()
{
- for (int i = 0; i < theFileName.levels(); i++) {
+ char* tmp;
+ const char * name = theFileName.c_str();
+ const char * base = theFileName.get_base_name();
+ while((tmp = strstr(base, DIR_SEPARATOR)))
+ {
+ char t = tmp[0];
+ tmp[0] = 0;
#ifdef NDB_WIN32
- CreateDirectory(theFileName.directory(i), 0);
+ CreateDirectory(name, 0);
#else
- //printf("AsyncFile::createDirectories : \"%s\"\n", theFileName.directory(i));
- mkdir(theFileName.directory(i), S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
+ mkdir(name, S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
#endif
+ tmp[0] = t;
+ base = tmp + sizeof(DIR_SEPARATOR);
}
}
@@ -1035,8 +1131,10 @@ void printErrorAndFlags(Uint32 used_flags) {
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
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
index 997bf40fe2a..22364ae32d7 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
@@ -123,12 +123,15 @@ public:
sync,
end,
append,
- rmrf
+ rmrf,
+ readPartial
};
Action action;
union {
struct {
Uint32 flags;
+ Uint32 page_size;
+ Uint64 file_size;
} open;
struct {
int numberOfPages;
@@ -176,14 +179,14 @@ class AsyncFile
{
friend class Ndbfs;
public:
- AsyncFile();
+ AsyncFile(SimulatedBlock& fs);
~AsyncFile();
void reportTo( MemoryChannel<Request> *reportTo );
void execute( Request* request );
- void doStart(Uint32 nodeId, const char * fspath, const char * backup_path);
+ void doStart();
// its a thread so its always running
void run();
@@ -206,7 +209,7 @@ private:
void rmrfReq(Request *request, char * path, bool removePath);
void endReq();
- int readBuffer(char * buf, size_t size, off_t offset);
+ 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);
@@ -232,6 +235,9 @@ private:
bool m_openedWithSync;
Uint32 m_syncCount;
Uint32 m_syncFrequency;
+public:
+ SimulatedBlock& m_fs;
+ Ptr<GlobalPage> m_page_ptr;
};
#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp b/storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp
index 238390f262c..91038175e3c 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/Filename.cpp
@@ -39,58 +39,37 @@ static const char* fileExtension[] = {
static const Uint32 noOfExtensions = sizeof(fileExtension)/sizeof(char*);
-Filename::Filename() :
- theLevelDepth(0)
+Filename::Filename()
{
}
-void
-Filename::init(Uint32 nodeid,
- const char * pFileSystemPath,
- const char * pBackupDirPath){
- DBUG_ENTER("Filename::init");
-
- if (pFileSystemPath == NULL) {
- ERROR_SET(fatal, NDBD_EXIT_AFS_NOPATH, "","Missing FileSystemPath");
- return;
- }
-
- BaseString::snprintf(theFileSystemDirectory, sizeof(theFileSystemDirectory),
- "%sndb_%u_fs%s", pFileSystemPath, nodeid, DIR_SEPARATOR);
- strncpy(theBackupDirectory, pBackupDirPath, sizeof(theBackupDirectory));
-
- DBUG_PRINT("info", ("theFileSystemDirectory=%s", theFileSystemDirectory));
- DBUG_PRINT("info", ("theBackupDirectory=%s", theBackupDirectory));
-
-#ifdef NDB_WIN32
- CreateDirectory(theFileSystemDirectory, 0);
-#else
- mkdir(theFileSystemDirectory, S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
-#endif
- theBaseDirectory= 0;
-
- DBUG_VOID_RETURN;
-}
-
Filename::~Filename(){
}
void
-Filename::set(BlockReference blockReference,
+Filename::set(Filename::NameSpec& spec,
+ BlockReference blockReference,
const Uint32 filenumber[4], bool dir)
{
char buf[PATH_MAX];
- theLevelDepth = 0;
const Uint32 type = FsOpenReq::getSuffix(filenumber);
const Uint32 version = FsOpenReq::getVersion(filenumber);
+ size_t sz;
if (version == 2)
- theBaseDirectory= theBackupDirectory;
+ {
+ sz = BaseString::snprintf(theName, sizeof(theName), "%s",
+ spec.backup_path.c_str());
+ m_base_name = theName + spec.backup_path.length();
+ }
else
- theBaseDirectory= theFileSystemDirectory;
- strncpy(theName, theBaseDirectory, PATH_MAX);
-
+ {
+ 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);
@@ -102,7 +81,6 @@ Filename::set(BlockReference blockReference,
if (diskNo < 0xff){
BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
strcat(theName, buf);
- theLevelDepth++;
}
{
@@ -113,19 +91,16 @@ Filename::set(BlockReference blockReference,
}
BaseString::snprintf(buf, sizeof(buf), "%s%s", blockName, DIR_SEPARATOR);
strcat(theName, buf);
- theLevelDepth++;
}
if (table < 0xffffffff){
BaseString::snprintf(buf, sizeof(buf), "T%d%s", table, DIR_SEPARATOR);
strcat(theName, buf);
- theLevelDepth++;
}
if (frag < 0xffffffff){
BaseString::snprintf(buf, sizeof(buf), "F%d%s", frag, DIR_SEPARATOR);
strcat(theName, buf);
- theLevelDepth++;
}
@@ -156,7 +131,6 @@ Filename::set(BlockReference blockReference,
BaseString::snprintf(buf, sizeof(buf), "BACKUP-%d-%d.%d",
seq, count, nodeId); strcat(theName, buf);
}
- theLevelDepth = 2;
break;
}
break;
@@ -169,9 +143,16 @@ Filename::set(BlockReference blockReference,
BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
strcat(theName, buf);
- theLevelDepth++;
}
- break;
+ break;
+ case 5:
+ {
+ Uint32 tableId = FsOpenReq::v5_getTableId(filenumber);
+ Uint32 lcpNo = FsOpenReq::v5_getLcpNo(filenumber);
+ BaseString::snprintf(buf, sizeof(buf), "LCP/%d/T%d", lcpNo, tableId);
+ strcat(theName, buf);
+ break;
+ }
default:
ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Wrong version");
}
@@ -191,28 +172,20 @@ Filename::set(BlockReference blockReference,
}
}
-/**
- * Find out directory name on level
- * Ex:
- * theName = "/tmp/fs/T0/NDBFS/D0/P0/S27.data"
- * level = 1
- * would return "/tmp/fs/T0/NDBFS/
- */
-const char* Filename::directory(int level)
+void
+Filename::set(Filename::NameSpec& spec,
+ SegmentedSectionPtr ptr, class SectionSegmentPool& pool)
{
- const char* p;
-
- p = theName;
- p += strlen(theBaseDirectory);
-
- for (int i = 0; i <= level; i++){
- p = strstr(p, DIR_SEPARATOR);
- p++;
- }
-
- strncpy(theDirectory, theName, p - theName - 1);
- theDirectory[p-theName-1] = 0;
- return theDirectory;
+ 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
index 249c1b1ca10..861f8995753 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/Filename.hpp
@@ -54,43 +54,41 @@
#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();
~Filename();
- void set(BlockReference blockReference,
- const Uint32 filenumber[4], bool dir = false);
- const char* baseDirectory() const;
- const char* directory(int level);
- int levels() const;
- const char* c_str() const;
-
- void init(Uint32 nodeid, const char * fileSystemPath,
- const char * backupDirPath);
+ 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:
- int theLevelDepth;
char theName[PATH_MAX];
- char theFileSystemDirectory[PATH_MAX];
- char theBackupDirectory[PATH_MAX];
- char *theBaseDirectory;
- char theDirectory[PATH_MAX];
+ char * m_base_name;
};
// inline methods
-inline const char* Filename::c_str() const{
+inline const char* Filename::c_str() const {
return theName;
}
-inline const char* Filename::baseDirectory() const{
- return theBaseDirectory;
-}
-
-inline int Filename::levels() const{
- return theLevelDepth;
+inline const char* Filename::get_base_name() const {
+ return m_base_name;
}
#endif
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
index 5049c726315..ab50974ad64 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
@@ -54,6 +54,7 @@ Ndbfs::Ndbfs(const Configuration & conf) :
SimulatedBlock(NDBFS, conf),
scanningInProgress(false),
theLastId(0),
+ theRequestPool(0),
m_maxOpenedFiles(0)
{
BLOCK_CONSTRUCTOR(Ndbfs);
@@ -71,8 +72,6 @@ Ndbfs::Ndbfs(const Configuration & conf) :
addRecSignal(GSN_FSAPPENDREQ, &Ndbfs::execFSAPPENDREQ);
addRecSignal(GSN_FSREMOVEREQ, &Ndbfs::execFSREMOVEREQ);
// Set send signals
-
- theRequestPool = 0;
}
Ndbfs::~Ndbfs()
@@ -86,7 +85,6 @@ Ndbfs::~Ndbfs()
theFiles[i] = NULL;
}//for
theFiles.clear();
-
if (theRequestPool)
delete theRequestPool;
}
@@ -102,15 +100,15 @@ Ndbfs::execREAD_CONFIG_REQ(Signal* signal)
const ndb_mgm_configuration_iterator * p =
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
-
- theFileSystemPath = theConfiguration.fileSystemPath();
- theBackupFilePath = theConfiguration.backupFilePath();
+ theFileSystemPath.assfmt("%sndb_%u_fs%s", theConfiguration.fileSystemPath(),
+ getOwnNodeId(), DIR_SEPARATOR);
+ theBackupFilePath.assign(theConfiguration.backupFilePath());
theRequestPool = new Pool<Request>;
m_maxFiles = 40;
ndb_mgm_get_int_parameter(p, CFG_DB_MAX_OPEN_FILES, &m_maxFiles);
-
+
// Create idle AsyncFiles
Uint32 noIdleFiles = m_maxFiles > 27 ? 27 : m_maxFiles ;
for (Uint32 i = 0; i < noIdleFiles; i++){
@@ -141,6 +139,16 @@ Ndbfs::execSTTOR(Signal* signal)
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);
@@ -173,17 +181,53 @@ Ndbfs::execFSOPENREQ(Signal* signal)
const BlockReference userRef = fsOpenReq->userReference;
AsyncFile* file = getIdleFile();
ndbrequire(file != NULL);
- ndbrequire(signal->getLength() == FsOpenReq::SignalLength)
- file->theFileName.set( userRef, fsOpenReq->fileNumber);
+ 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);
Request* request = theRequestPool->get();
request->action = Request::open;
request->error = 0;
- request->par.open.flags = fsOpenReq->fileFlags;
- request->set(userRef, fsOpenReq->userPointer, newId() );
+ 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;
ndbrequire(forward(file, request));
}
@@ -197,7 +241,8 @@ Ndbfs::execFSREMOVEREQ(Signal* signal)
AsyncFile* file = getIdleFile();
ndbrequire(file != NULL);
- file->theFileName.set( userRef, req->fileNumber, req->directory);
+ Filename::NameSpec spec(theFileSystemPath, theBackupFilePath);
+ file->theFileName.set(spec, userRef, req->fileNumber, req->directory);
file->reportTo(&theFromThreads);
Request* request = theRequestPool->get();
@@ -286,96 +331,105 @@ Ndbfs::readWriteRequest(int action, Signal * signal)
goto error;
}
- 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 (fsRWReq->getFormatFlag(fsRWReq->operationFlag)) {
-
- // List of memory and file pages pairs
- case FsReadWriteReq::fsFormatListOfPairs: {
- jam();
- for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) {
+ if(fsRWReq->getFormatFlag(fsRWReq->operationFlag) !=
+ FsReadWriteReq::fsFormatGlobalPage){
+ 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 (fsRWReq->getFormatFlag(fsRWReq->operationFlag)) {
+
+ // List of memory and file pages pairs
+ case FsReadWriteReq::fsFormatListOfPairs: {
jam();
- const UintPtr varIndex = fsRWReq->data.listOfPair[i].varIndex;
- const UintPtr fileOffset = fsRWReq->data.listOfPair[i].fileOffset;
- if (varIndex >= tNRR) {
+ 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
- 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) {
+ 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;
- }//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;
+ }//default
+ }//switch
+ } else {
+ 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;
- 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
+ }
ndbrequire(forward(openFile, request));
return;
@@ -393,6 +447,7 @@ error:
sendSignal(userRef, GSN_FSWRITEREF, signal, 3, JBB);
break;
}//case
+ case Request:: readPartial:
case Request:: read: {
jam();
sendSignal(userRef, GSN_FSREADREF, signal, 3, JBB);
@@ -437,8 +492,12 @@ Ndbfs::execFSWRITEREQ(Signal* signal)
void
Ndbfs::execFSREADREQ(Signal* signal)
{
- jamEntry();
- readWriteRequest( Request::read, signal );
+ jamEntry();
+ FsReadWriteReq * req = (FsReadWriteReq *)signal->getDataPtr();
+ if (FsReadWriteReq::getPartialReadFlag(req->operationFlag))
+ readWriteRequest( Request::readPartial, signal );
+ else
+ readWriteRequest( Request::read, signal );
}
/*
@@ -579,8 +638,8 @@ Ndbfs::createAsyncFile(){
ERROR_SET(fatal, NDBD_EXIT_AFS_MAXOPEN,""," Ndbfs::createAsyncFile");
}
- AsyncFile* file = new AsyncFile;
- file->doStart(getOwnNodeId(), theFileSystemPath, theBackupFilePath);
+ AsyncFile* file = new AsyncFile(* this);
+ file->doStart();
// Put the file in list of all files
theFiles.push_back(file);
@@ -612,14 +671,28 @@ 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;
- fsRef->setErrorCode(fsRef->errorCode, translateErrno(request->error));
- fsRef->osErrorCode = request->error;
-
+ 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();
@@ -642,7 +715,8 @@ Ndbfs::report(Request * request, Signal* signal)
sendSignal(ref, GSN_FSWRITEREF, signal, FsRef::SignalLength, JBB);
break;
}
- case Request:: read:
+ case Request:: read:
+ case Request:: readPartial:
case Request:: readv: {
jam();
sendSignal(ref, GSN_FSREADREF, signal, FsRef::SignalLength, JBB);
@@ -712,6 +786,12 @@ Ndbfs::report(Request * request, Signal* signal)
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);
@@ -755,7 +835,7 @@ Ndbfs::scanIPC(Signal* signal)
}
#if defined NDB_WIN32
-int Ndbfs::translateErrno(int aErrno)
+Uint32 Ndbfs::translateErrno(int aErrno)
{
switch (aErrno)
{
@@ -809,7 +889,7 @@ int Ndbfs::translateErrno(int aErrno)
}
}
#elif defined NDB_OSE || defined NDB_SOFTOSE
-int Ndbfs::translateErrno(int aErrno)
+Uint32 Ndbfs::translateErrno(int aErrno)
{
switch (aErrno)
{
@@ -857,7 +937,7 @@ int Ndbfs::translateErrno(int aErrno)
}
}
#else
-int Ndbfs::translateErrno(int aErrno)
+Uint32 Ndbfs::translateErrno(int aErrno)
{
switch (aErrno)
{
@@ -956,8 +1036,7 @@ Ndbfs::execCONTINUEB(Signal* signal)
return;
}
-bool Global_useO_SYNC = false;
-bool Global_useO_DIRECT = false;
+bool Global_useO_SYNC = true;
bool Global_unlinkO_CREAT = false;
Uint32 Global_syncFreq = 1024 * 1024;
@@ -974,14 +1053,10 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal)
if(signal->length() > 3){
Global_unlinkO_CREAT = signal->theData[3];
}
- if(signal->length() > 4){
- Global_useO_DIRECT = signal->theData[4];
- }
- ndbout_c("useO_SYNC = %d syncFreq = %d unlinkO_CREATE = %d O_DIRECT = %d",
+ ndbout_c("useO_SYNC = %d syncFreq = %d unlinkO_CREATE = %d",
Global_useO_SYNC,
Global_syncFreq,
- Global_unlinkO_CREAT,
- Global_useO_DIRECT);
+ Global_unlinkO_CREAT);
return;
}
if(signal->theData[0] == DumpStateOrd::NdbfsDumpFileStat){
@@ -1031,7 +1106,7 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal)
ndbrequire(signal->getLength() == 2);
Uint32 file= signal->theData[1];
AsyncFile* openFile = theOpenFiles.find(file);
- ndbrequire(openFile);
+ 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;
@@ -1051,6 +1126,15 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal)
}
}//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)
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
index 17ce8fbd8aa..d80bde7d13e 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
@@ -37,6 +37,7 @@ public:
Ndbfs(const class Configuration & conf);
virtual ~Ndbfs();
+ virtual const char* get_filename(Uint32 fd) const;
protected:
BLOCK_DEFINES(Ndbfs);
@@ -80,9 +81,10 @@ private:
Vector<AsyncFile*> theFiles; // List all created AsyncFiles
Vector<AsyncFile*> theIdleFiles; // List of idle AsyncFiles
OpenFiles theOpenFiles; // List of open AsyncFiles
- const char * theFileSystemPath;
- const char * theBackupFilePath;
+ BaseString theFileSystemPath;
+ BaseString theBackupFilePath;
+
// Statistics variables
Uint32 m_maxOpenedFiles;
@@ -91,7 +93,7 @@ private:
void readWriteRequest( int action, Signal * signal );
- static int translateErrno(int aErrno);
+ static Uint32 translateErrno(int aErrno);
};
class VoidFs : public SimulatedBlock
diff --git a/storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp b/storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
index eacda6ec77d..fa113fff151 100644
--- a/storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
+++ b/storage/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
@@ -25,7 +25,7 @@ public:
OpenFiles(){ }
/* Get a pointer to the file with id */
- AsyncFile* find(Uint16 id);
+ AsyncFile* find(Uint16 id) const;
/* Insert file with id */
bool insert(AsyncFile* file, Uint16 id);
/* Erase file with id */
@@ -52,7 +52,7 @@ private:
//*****************************************************************************
-inline AsyncFile* OpenFiles::find(Uint16 id){
+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;
diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp
new file mode 100644
index 00000000000..7ff3ab7eff4
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/pgman.cpp
@@ -0,0 +1,2214 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "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
+
+Pgman::Pgman(const Configuration & conf) :
+ SimulatedBlock(PGMAN, conf),
+ 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;
+ m_lcp_copy_page = RNIL;
+ m_lcp_copy_page_free = false;
+
+ // clean-up variables
+ m_cleanup_ptr.i = RNIL;
+
+ // should be a factor larger than number of pool pages
+ m_page_entry_pool.setSize(2000);
+ m_page_request_pool.setSize(10000);
+ m_data_buffer_pool.setSize(1);
+ 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 =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
+Pgman::Param::Param() :
+ m_max_pages(64), // smallish for testing
+ m_max_hot_pages(56),
+ m_max_loop_count(256),
+ m_max_io_waits(64),
+ m_stats_loop_delay(1000),
+ m_cleanup_loop_delay(200),
+ m_lcp_loop_delay(200)
+{
+}
+
+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:
+ {
+ Ptr<GlobalPage> page_ptr;
+ ndbrequire(m_global_page_pool.seize(page_ptr));
+ m_lcp_copy_page = page_ptr.i;
+ m_lcp_copy_page_free = true;
+ // 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;
+ default:
+ ndbrequire(false);
+ break;
+ }
+}
+
+// page entry
+
+Pgman::Page_entry::Page_entry(Uint32 file_no, Uint32 page_no) :
+ m_state(0),
+ m_file_no(file_no),
+ m_page_no(page_no),
+ m_real_page_i(RNIL),
+ m_lsn(0),
+ m_last_lcp(0),
+ m_busy_count(0),
+ m_requests()
+{
+}
+
+// page lists
+
+Uint32
+Pgman::get_sublist_no(Uint16 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;
+ }
+ return Page_entry::SL_OTHER;
+}
+
+void
+Pgman::set_page_state(Ptr<Page_entry> ptr, Uint16 new_state)
+{
+#ifdef VM_TRACE
+ debugOut << "PGMAN: >set_page_state: state=" << hex << new_state << endl;
+ debugOut << "PGMAN: " << ptr << ": before" << endl;
+#endif
+
+ Uint16 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))
+ {
+ ndbrequire(ptr.p->m_state != 0);
+ m_stats.m_page_hits++;
+ return true;
+ }
+
+ if (seize_page_entry(ptr, file_no, page_no))
+ {
+ ndbrequire(ptr.p->m_state == 0);
+ m_stats.m_page_faults++;
+ return true;
+ }
+
+ 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
+ Uint16 state = ptr.p->m_state;
+
+ ndbrequire(! (state & Page_entry::REQUEST));
+ ndbrequire(ptr.p->m_requests.isEmpty());
+
+ ndbrequire(! (state & Page_entry::ONSTACK));
+ ndbrequire(! (state & Page_entry::ONQUEUE));
+ ndbrequire(ptr.p->m_real_page_i == RNIL);
+
+ 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;
+ Page_queue& pl_queue = m_page_queue;
+ Ptr<Page_entry> ptr;
+
+ while (pl_stack.first(ptr)) // first is stack bottom
+ {
+ Uint16 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);
+ Uint16 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;
+
+ Uint16 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);
+ }
+ 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();
+ pl_stack.remove(ptr);
+ }
+ pl_stack.add(ptr);
+ state |= Page_entry::ONSTACK;
+ state |= Page_entry::HOT;
+ }
+
+ 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;
+ sendSignalWithDelay(PGMAN_REF, GSN_CONTINUEB, signal, delay, 1);
+ }
+#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_sublist& pl_bind = *m_page_sublist[Page_entry::SL_BIND];
+ 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;
+ }
+ Uint16 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
+
+ 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;
+
+ c_tup->disk_page_unmap_callback(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);
+ }
+
+ Uint16 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 = m_param.m_max_io_waits - m_stats.m_current_io_waits;
+ if (max_count > 0)
+ 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];
+
+ while (! pl_callback.isEmpty() && --max_count >= 0)
+ {
+ jam();
+ Ptr<Page_entry> ptr;
+ pl_callback.first(ptr);
+ if (! process_callback(signal, ptr))
+ {
+ 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;
+ Uint16 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).
+ */
+ LocalDLFifoList<Page_request>
+ 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
+ b = globalData.getBlock(req_ptr.p->m_block);
+ callback = req_ptr.p->m_callback;
+
+ req_list.release(req_ptr);
+
+ if (req_ptr.p->m_flags & DIRTY_FLAGS)
+ {
+ jam();
+ state |= Page_entry::DIRTY;
+ }
+ }
+ 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;
+
+ state &= ~ Page_entry::NO_HOOK;
+ }
+
+ 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 = m_param.m_max_io_waits - m_stats.m_current_io_waits;
+
+ if (max_count > 0)
+ {
+ max_count = max_count / 2 + 1;
+ /*
+ * Possibly add code here to avoid writing too rapidly. May be
+ * unnecessary since only cold pages are cleaned.
+ */
+ }
+
+ Ptr<Page_entry> ptr = m_cleanup_ptr;
+ while (max_loop_count != 0 && max_count != 0)
+ {
+ Uint16 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
+ 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)
+{
+ LcpFragOrd* ord = (LcpFragOrd*)signal->getDataPtr();
+ ndbrequire(ord->lcpId >= m_last_lcp_complete + 1 || m_last_lcp_complete == 0);
+ m_last_lcp = ord->lcpId;
+
+ ndbrequire(!m_lcp_outstanding);
+ ndbrequire(m_lcp_copy_page_free);
+ m_lcp_curr_bucket = 0;
+
+#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
+
+ do_lcp_loop(signal, true);
+}
+
+void
+Pgman::execEND_LCP_REQ(Signal* signal)
+{
+ EndLcpReq* req = (EndLcpReq*)signal->getDataPtr();
+ m_end_lcp_req = *req;
+
+#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
+
+ if (m_last_lcp == m_last_lcp_complete)
+ {
+ ndbrequire(! m_lcp_loop_on);
+ signal->theData[0] = m_end_lcp_req.senderData;
+ sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF, signal, 1, JBB);
+ }
+
+ m_last_lcp_complete = m_last_lcp;
+}
+
+bool
+Pgman::process_lcp(Signal* signal)
+{
+ Page_hashlist& pl_hash = m_page_hashlist;
+ int max_count = m_param.m_max_io_waits - m_stats.m_current_io_waits;
+ if (max_count > 0)
+ 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);
+
+ while (iter.curr.i != RNIL && --max_count > 0)
+ {
+ Ptr<Page_entry>& ptr = iter.curr;
+ Uint16 state = ptr.p->m_state;
+
+ if (ptr.p->m_last_lcp < m_last_lcp &&
+ (state & Page_entry::DIRTY))
+ {
+ if(! (state & Page_entry::BOUND))
+ {
+ ndbout << ptr << endl;
+ ndbrequire(false);
+ }
+ if (state & Page_entry::BUSY)
+ {
+ break; // wait for it
+ }
+ if (state & Page_entry::LOCKED)
+ {
+ /**
+ * Special handling of LOCKED pages...only write 1 at a time...
+ * using copy page (m_lcp_copy_page)
+ */
+ if (!m_lcp_copy_page_free)
+ {
+ break;
+ }
+ m_lcp_copy_page_free = false;
+ Ptr<GlobalPage> src, copy;
+ m_global_page_pool.getPtr(copy, m_lcp_copy_page);
+ m_global_page_pool.getPtr(src, ptr.p->m_real_page_i);
+ memcpy(copy.p, src.p, sizeof(GlobalPage));
+ ptr.p->m_real_page_i = copy.i;
+ ptr.p->m_copy_real_page_i = src.i;
+ ptr.p->m_state |= Page_entry::LCP;
+ pageout(signal, ptr);
+ }
+ else if (state & Page_entry::PAGEOUT)
+ {
+ set_page_state(ptr, state | Page_entry::LCP);
+ }
+ else
+ {
+ ptr.p->m_state |= Page_entry::LCP;
+ pageout(signal, ptr);
+ }
+ ptr.p->m_last_lcp = m_last_lcp;
+ m_lcp_outstanding++;
+ }
+ 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)
+ {
+ if (m_last_lcp == m_last_lcp_complete)
+ {
+ signal->theData[0] = m_end_lcp_req.senderData;
+ sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF, signal, 1, JBB);
+ }
+ m_last_lcp_complete = m_last_lcp;
+ m_lcp_curr_bucket = ~(Uint32)0;
+ return false;
+ }
+ return true;
+}
+
+// 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);
+ Uint16 state = ptr.p->m_state;
+
+ if (!(state & Page_entry::NO_HOOK) &&
+ c_tup->disk_page_load_hook(ptr.p->m_real_page_i))
+ {
+ state |= Page_entry::DIRTY;
+ }
+
+ state &= ~ Page_entry::PAGEIN;
+ state &= ~ Page_entry::EMPTY;
+ state &= ~ Page_entry::NO_HOOK;
+ state |= Page_entry::MAPPED;
+ set_page_state(ptr, state);
+
+ ndbrequire(m_stats.m_current_io_waits > 0);
+ m_stats.m_current_io_waits--;
+
+ ptr.p->m_last_lcp = m_last_lcp;
+ 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
+
+ Uint16 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::NO_HOOK;
+ state |= Page_entry::PAGEOUT;
+ c_tup->disk_page_unmap_callback(ptr.p->m_real_page_i);
+
+ // 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)
+ Uint16 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
+
+ Uint16 state = ptr.p->m_state;
+ ndbrequire(state & Page_entry::PAGEOUT);
+
+ 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::LOCKED)
+ {
+ jam();
+ ndbrequire(!m_lcp_copy_page_free);
+ m_lcp_copy_page_free = true;
+ ptr.p->m_real_page_i = ptr.p->m_copy_real_page_i;
+ ptr.p->m_copy_real_page_i = RNIL;
+ }
+
+ if (state & Page_entry::LCP)
+ {
+ ndbrequire(m_lcp_outstanding);
+ m_lcp_outstanding--;
+ }
+ state &= ~ Page_entry::LCP;
+
+ 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;
+ 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;
+ sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
+ FsReadWriteReq::FixedLength + 1, JBB);
+}
+
+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;
+ sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal,
+ FsReadWriteReq::FixedLength + 1, JBB);
+}
+
+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)
+{
+#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());
+ }
+
+ Uint16 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;
+ /*
+ * Consider commit to be correlated. Otherwise pk op + commit makes
+ * the page hot. XXX move to TUP which knows better.
+ */
+ req_flags |= Page_request::CORR_REQ;
+ }
+ 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;
+ }
+
+ bool only_request = ptr.p->m_requests.isEmpty();
+
+ 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 (state & Page_entry::LOCKED &&
+ ! (req_flags & Page_request::UNLOCK_PAGE))
+ {
+ ndbrequire(ptr.p->m_copy_real_page_i != m_lcp_copy_page);
+ ndbrequire(ptr.p->m_copy_real_page_i != RNIL);
+ return ptr.p->m_copy_real_page_i;
+ }
+ }
+
+ if (! (req_flags & Page_request::LOCK_PAGE))
+ {
+ ndbrequire(! (state & Page_entry::LOCKED));
+ }
+
+ // queue the request
+ Ptr<Pgman::Page_request> req_ptr;
+ {
+ LocalDLFifoList<Page_request>
+ req_list(m_page_request_pool, ptr.p->m_requests);
+ req_list.seize(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;
+
+ state |= Page_entry::REQUEST;
+ if (only_request && req_flags & Page_request::EMPTY_PAGE)
+ {
+ state |= Page_entry::EMPTY;
+ }
+
+ if (req_flags & Page_request::NO_HOOK)
+ {
+ state |= Page_entry::NO_HOOK;
+ }
+
+ if (req_flags & Page_request::UNLOCK_PAGE)
+ {
+ state &= ~ Page_entry::LOCKED;
+ }
+
+ ptr.p->m_busy_count += busy_count;
+ 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)
+{
+#ifdef VM_TRACE
+ const char* bname = getBlockName(block, "?");
+ debugOut << "PGMAN: >update_lsn: block=" << bname << " lsn=" << lsn << endl;
+ debugOut << "PGMAN: " << ptr << endl;
+#endif
+
+ Uint16 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)
+{
+ Page_stack& pl_stack = m_page_stack;
+ Page_queue& pl_queue = m_page_queue;
+
+ Uint16 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();
+ pl_stack.remove(ptr);
+ state &= ~ Page_entry::ONSTACK;
+ }
+
+ if (state & Page_entry::ONQUEUE)
+ {
+ jam();
+ pl_queue.remove(ptr);
+ state &= ~ Page_entry::ONQUEUE;
+ }
+
+ if (ptr.p->m_real_page_i != RNIL)
+ {
+ jam();
+ c_tup->disk_page_unmap_callback(ptr.p->m_real_page_i);
+ 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;
+ Uint16 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_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);
+
+ Uint16 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_bound_count = 0;
+ Uint32 cold_bound_count = 0;
+
+ Uint32 i1 = RNIL;
+ for (pl_stack.first(ptr); ptr.i != RNIL; pl_stack.next(ptr))
+ {
+ ndbrequire(i1 != ptr.i);
+ i1 = ptr.i;
+ Uint16 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 &&
+ state & Page_entry::BOUND)
+ hot_bound_count++;
+ }
+
+ Uint32 i2 = RNIL;
+ for (pl_queue.first(ptr); ptr.i != RNIL; pl_queue.next(ptr))
+ {
+ ndbrequire(i2 != ptr.i);
+ i2 = ptr.i;
+ Uint16 state = ptr.p->m_state;
+ ndbrequire(state & Page_entry::ONQUEUE || dump_page_lists());
+ ndbrequire(state & Page_entry::BOUND || dump_page_lists());
+ cold_bound_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()
+ << " queue:" << pl_queue.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_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::STRICT_ORDER)
+ out << ",strict_order";
+ 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::NO_HOOK)
+ out << ",no_hook";
+ 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::NO_HOOK)
+ out << ",no_hook";
+ 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
+ {
+ LocalDLFifoList<Pgman::Page_request>
+ 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;
+ pageout(signal, ptr);
+ }
+ }
+
+ if (signal->theData[0] == 11003)
+ {
+#ifdef VM_TRACE
+ verify_page_lists();
+ dump_page_lists();
+#endif
+ }
+}
+
+// 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
new file mode 100644
index 00000000000..276cc60ee4c
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/pgman.hpp
@@ -0,0 +1,659 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef 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(const Configuration & conf);
+ virtual ~Pgman();
+ BLOCK_DEFINES(Pgman);
+
+private:
+ friend class Page_cache_client;
+
+ struct Page_request {
+ enum Flags {
+ OP_MASK = 0x000F // 4 bits for TUP operation
+ ,STRICT_ORDER = 0x0010 // maintain request order
+ ,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
+ ,NO_HOOK = 0x0400 // dont run load hook
+ ,UNLOCK_PAGE = 0x0800
+ ,CORR_REQ = 0x1000 // correlated request (no LIRS update)
+ };
+
+ Uint16 m_block;
+ Uint16 m_flags;
+ SimulatedBlock::Callback m_callback;
+
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+
+ 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;
+ };
+
+ 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
+ ,NO_HOOK = 0x0800 // don't run load hook
+ ,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_OTHER = 7
+ ,SUBLIST_COUNT = 8
+ };
+
+ Uint16 m_state; // flags (0 for new entry)
+
+ Uint16 m_file_no; // disk page address set at seize
+ Uint32 m_page_no;
+ Uint32 m_real_page_i;
+ Uint32 m_copy_real_page_i; // used for flushing LOCKED pages
+
+ Uint64 m_lsn;
+ Uint32 m_last_lcp;
+
+ union {
+ Uint32 m_busy_count; // non-zero means BUSY
+ Uint32 nextPool;
+ };
+
+ DLFifoList<Page_request>::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
+ Uint32 m_lcp_copy_page;
+ bool m_lcp_copy_page_free;
+ 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
+ ArrayPool<Page_request> 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_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(Uint16 state);
+ void set_page_state(Ptr<Page_entry> ptr, Uint16 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 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 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;
+ };
+
+ Ptr<GlobalPage> m_ptr; // TODO remove
+
+ enum RequestFlags {
+ STRICT_ORDER = Pgman::Page_request::STRICT_ORDER
+ ,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
+ ,NO_HOOK = Pgman::Page_request::NO_HOOK
+ ,UNLOCK_PAGE = Pgman::Page_request::UNLOCK_PAGE
+ };
+
+ /**
+ * 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;
+
+ 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
new file mode 100644
index 00000000000..2cbf0824831
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/print_file.cpp
@@ -0,0 +1,370 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <ndb_global.h>
+
+#include <NdbOut.hpp>
+#include <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 i = 0;
+ do {
+ buffer.grow(g_page_size);
+ sz = fread(buffer.get_data(), 1, g_page_size, f);
+ if((* g_print_page)(i++, 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);
+ 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;
+ 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;
+}
diff --git a/storage/ndb/src/kernel/blocks/restore.cpp b/storage/ndb/src/kernel/blocks/restore.cpp
new file mode 100644
index 00000000000..31dea0dfcdf
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/restore.cpp
@@ -0,0 +1,1211 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "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 (4*32)
+
+Restore::Restore(const Configuration & conf) :
+ SimulatedBlock(RESTORE, conf),
+ 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);
+}
+
+Restore::~Restore()
+{
+}
+
+BLOCK_FUNCTIONS(Restore)
+
+void
+Restore::execSTTOR(Signal* signal)
+{
+ jamEntry();
+
+ const Uint32 startphase = signal->theData[1];
+ const Uint32 typeOfStart = signal->theData[7];
+ 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 =
+ theConfiguration.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);
+ m_databuffer_pool.setSize((1*128+PAGES+List::getSegmentSize()-1)/List::getSegmentSize());
+
+ 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, req->lcpNo);
+ 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_table_id = req->tableId;
+ file_ptr.p->m_fragment_id = RNIL;
+ 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, Uint32 lcpNo)
+{
+ 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, lcpNo);
+ FsOpenReq::v5_setTableId(req->fileNumber, file_ptr.p->m_table_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);
+ 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 0x4e444242: // 'NDBB'
+ if(ntohl(* (data+2)) != NDB_VERSION)
+ parse_error(signal, file_ptr, __LINE__, ntohl(* (data+2)));
+ 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(ntohl(fh->NdbVersion) != NDB_VERSION)
+ {
+ 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;
+ }
+
+ DataBuffer<15> variable(m_databuffer_pool);
+
+ Uint32 null_offset = 0;
+ union { Column c; Uint32 _align[1];};
+ 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;
+
+ union {
+ Column c;
+ Uint32 _align[1];
+ };
+ 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)
+ {
+ c.m_nulloffset = 0;
+ if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
+ {
+ parse_error(signal, file_ptr, __LINE__, i);
+ return;
+ }
+ }
+ else if (true) // null mask dropped in 5.1
+ {
+ c.m_nulloffset = (tmp.AttributeNullableFlag != 0);
+ if (varsize)
+ c.m_flags |= Column::COL_VAR;
+ if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
+ {
+ parse_error(signal, file_ptr, __LINE__, i);
+ return;
+ }
+ }
+ else
+ {
+ c.m_nulloffset = 1 + null_offset++;
+ c.m_flags |= Column::COL_VAR;
+ if(!variable.append(_align, sizeof(Column)/sizeof(Uint32)))
+ {
+ parse_error(signal, file_ptr, __LINE__, i);
+ return;
+ }
+ }
+ }
+
+ if(lcp && disk)
+ {
+ c.m_id = AttributeHeader::DISK_REF;
+ c.m_size = 2;
+ c.m_nulloffset = 0;
+ c.m_flags = 0;
+ if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
+ {
+ parse_error(signal, file_ptr, __LINE__, 0);
+ return;
+ }
+ }
+
+ file_ptr.p->m_table_version = tmpTab.TableVersion;
+ file_ptr.p->m_null_bitmask_size = (null_offset + 31)/32;
+#if 0
+ List::Iterator cols;
+ for(variable.first(cols); !cols.isNull(); variable.next(cols))
+ {
+ if(!columns.append(cols.data, 1))
+ {
+ parse_error(signal, file_ptr, __LINE__, 0);
+ }
+ }
+ return ;
+#endif
+}
+
+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;
+
+ Uint32 nulls= file_ptr.p->m_null_bitmask_size;
+ const Uint32 *null_mask= data+1;
+ data += (1+nulls);
+ const Uint32* const dataStart = data;
+ //if (file_ptr.p->m_table_id >= 2) { for (uint ii = 0; ii+1<len; ii++) ndbout << hex << dataStart[ii]; ndbout << endl; }
+
+ Uint32 *keyData = key_start;
+ Uint32 *attrData = attr_start;
+ union {
+ Column c;
+ Uint32 _align[1];
+ };
+ bool disk= false;
+
+ //if (file_ptr.p->m_table_id >= 2) { ndbout << "*** "; columns.first(it); while (!it.isNull()) { _align[0] = *it.data; columns.next(it); _align[1] = *it.data; columns.next(it); ndbout << c << " "; } ndbout << endl; }
+
+ Uint32 column_no = 0;
+ columns.first(it);
+ while(!it.isNull())
+ {
+ _align[0] = *it.data; ndbrequire(columns.next(it));
+ _align[1] = *it.data; columns.next(it);
+
+ if (! (c.m_flags & Column::COL_VAR) &&
+ ! c.m_nulloffset)
+ {
+ 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 (file_ptr.p->m_table_id >= 2) ndbout << "1: " << c.m_id << " " << c.m_size << " col=" << column_no << endl;
+ }
+
+ column_no++;
+
+ 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;
+
+ if(c.m_flags & Column::COL_KEY)
+ {
+ assert(! c.m_nulloffset && c.m_flags & Column::COL_VAR);
+ memcpy(keyData, data, 4 * sz32);
+ keyData += sz32;
+ }
+
+ AttributeHeader::init(attrData++, c.m_id, sz);
+ memcpy(attrData, data, sz);
+
+ attrData += sz32;
+ data += sz32;
+ //if (file_ptr.p->m_table_id >= 2) ndbout << "2: " << c.m_id << " " << sz << endl;
+ }
+
+ ndbrequire(data == dataStart + len - 1);
+
+ ndbrequire(disk == false); // Not supported...
+
+ Uint32 keyLen = keyData - key_start;
+ Uint32 attrLen = attrData - attr_start;
+ LqhKeyReq * req = (LqhKeyReq *)signal->getDataPtrSend();
+
+ Uint32 tableId = file_ptr.p->m_table_id;
+ 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);
+ LqhKeyReq::setLockType(tmp, ZINSERT);
+ /* ---------------------------------------------------------------------- */
+ // 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::setExecuteDirectFlag(tmp, 1);
+ 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);
+
+ file_ptr.p->m_outstanding_operations++;
+ EXECUTE_DIRECT(DBLQH, GSN_LQHKEYREQ, signal, 11+(keyLen > 4 ? 4 : keyLen));
+
+ 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;
+ }
+ dst += sz;
+ }
+ assert((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*)
+{
+ 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)
+{
+ ndbrequire(false);
+}
+
+NdbOut&
+operator << (NdbOut& ndbout, const Restore::Column& col)
+{
+ ndbout << "[ Col: id: " << col.m_id
+ << " size: " << col.m_size
+ << " nulloffset: " << col.m_nulloffset
+ << " key: " << (Uint32)(col.m_flags & Restore::Column::COL_KEY)
+ << " variable: " << (Uint32)(col.m_flags & Restore::Column::COL_VAR)
+ << " disk: " << (Uint32)(col.m_flags & Restore::Column::COL_DISK)
+ << "]";
+
+ return ndbout;
+}
diff --git a/storage/ndb/src/kernel/blocks/restore.hpp b/storage/ndb/src/kernel/blocks/restore.hpp
new file mode 100644
index 00000000000..5654bcebd0e
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/restore.hpp
@@ -0,0 +1,154 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef 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(const Configuration & conf);
+ 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_nulloffset; // 0 = not nullable
+ Uint16 m_flags;
+
+ enum Flags
+ {
+ COL_KEY = 0x1,
+ COL_VAR = 0x2,
+ COL_DISK = 0x4
+ };
+ };
+private:
+
+ 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_null_bitmask_size;
+
+ 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;
+
+ 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, Uint32 lcpNo);
+ 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);
+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
index bc5fc650320..b2f2cbe2a09 100644
--- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -1694,7 +1694,7 @@ Suma::execDI_FCOUNTCONF(Signal* signal)
TablePtr tabPtr;
tabPtr.i= signal->theData[3];
- ndbrequire(tabPtr.p= c_tablePool.getPtr(tabPtr.i));
+ ndbrequire((tabPtr.p= c_tablePool.getPtr(tabPtr.i)) != 0);
ndbrequire(tabPtr.p->m_tableId == tableId);
LocalDataBuffer<15> fragBuf(c_dataBufferPool, tabPtr.p->m_fragments);
@@ -1727,7 +1727,7 @@ Suma::execDIGETPRIMCONF(Signal* signal){
TablePtr tabPtr;
tabPtr.i= signal->theData[1];
- ndbrequire(tabPtr.p= c_tablePool.getPtr(tabPtr.i));
+ ndbrequire((tabPtr.p= c_tablePool.getPtr(tabPtr.i)) != 0);
ndbrequire(tabPtr.p->m_tableId == tableId);
{
@@ -2519,7 +2519,7 @@ Suma::Table::setupTrigger(Signal* signal,
req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE);
req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
req->setMonitorReplicas(true);
- req->setMonitorAllAttributes(false);
+ req->setMonitorAllAttributes(j == TriggerEvent::TE_DELETE);
req->setReceiverRef(SUMA_REF);
req->setTriggerId(triggerId);
req->setTriggerEvent((TriggerEvent::Value)j);
@@ -3067,7 +3067,7 @@ Suma::execFIRE_TRIG_ORD(Signal* signal)
/**
* Signal to subscriber(s)
*/
- ndbrequire(tabPtr.p = c_tablePool.getPtr(tabPtr.i));
+ ndbrequire((tabPtr.p = c_tablePool.getPtr(tabPtr.i)) != 0);
SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg;
data->gci = gci;
@@ -3149,7 +3149,7 @@ Suma::execSUB_GCP_COMPLETE_REP(Signal* signal)
Page_pos pos= bucket->m_buffer_head;
ndbrequire(pos.m_max_gci < gci);
- Buffer_page* page= (Buffer_page*)(m_tup->page+pos.m_page_id);
+ Buffer_page* page= (Buffer_page*)(m_tup->cpage+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;
@@ -4091,7 +4091,7 @@ Suma::get_buffer_ptr(Signal* signal, Uint32 buck, Uint32 gci, Uint32 sz)
Bucket* bucket= c_buckets+buck;
Page_pos pos= bucket->m_buffer_head;
- Buffer_page* page= (Buffer_page*)(m_tup->page+pos.m_page_id);
+ Buffer_page* page= (Buffer_page*)(m_tup->cpage+pos.m_page_id);
Uint32* ptr= page->m_data + pos.m_page_pos;
const bool same_gci = (gci == pos.m_last_gci) && (!ERROR_INSERTED(13022));
@@ -4150,7 +4150,7 @@ loop:
pos.m_page_pos = sz;
pos.m_last_gci = gci;
- page= (Buffer_page*)(m_tup->page+pos.m_page_id);
+ page= (Buffer_page*)(m_tup->cpage+pos.m_page_id);
page->m_next_page= RNIL;
ptr= page->m_data;
goto loop; //
@@ -4181,7 +4181,7 @@ Suma::out_of_buffer_release(Signal* signal, Uint32 buck)
if(tail != RNIL)
{
- Buffer_page* page= (Buffer_page*)(m_tup->page+tail);
+ Buffer_page* page= (Buffer_page*)(m_tup->cpage+tail);
bucket->m_buffer_tail = page->m_next_page;
free_page(tail, page);
signal->theData[0] = SumaContinueB::OUT_OF_BUFFER_RELEASE;
@@ -4225,8 +4225,8 @@ loop:
Uint32 ref= m_first_free_page;
if(likely(ref != RNIL))
{
- m_first_free_page = ((Buffer_page*)m_tup->page+ref)->m_next_page;
- Uint32 chunk = ((Buffer_page*)m_tup->page+ref)->m_page_chunk_ptr_i;
+ m_first_free_page = ((Buffer_page*)m_tup->cpage+ref)->m_next_page;
+ Uint32 chunk = ((Buffer_page*)m_tup->cpage+ref)->m_page_chunk_ptr_i;
c_page_chunk_pool.getPtr(ptr, chunk);
ndbassert(ptr.p->m_free);
ptr.p->m_free--;
@@ -4249,7 +4249,7 @@ loop:
Buffer_page* page;
for(Uint32 i = 0; i<count; i++)
{
- page = (Buffer_page*)(m_tup->page+ref);
+ page = (Buffer_page*)(m_tup->cpage+ref);
page->m_page_state= SUMA_SEQUENCE;
page->m_page_chunk_ptr_i = ptr.i;
page->m_next_page = ++ref;
@@ -4313,7 +4313,7 @@ Suma::release_gci(Signal* signal, Uint32 buck, Uint32 gci)
else
{
jam();
- Buffer_page* page= (Buffer_page*)(m_tup->page+tail);
+ Buffer_page* page= (Buffer_page*)(m_tup->cpage+tail);
Uint32 max_gci = page->m_max_gci;
Uint32 next_page = page->m_next_page;
@@ -4406,7 +4406,7 @@ Suma::resend_bucket(Signal* signal, Uint32 buck, Uint32 min_gci,
Bucket* bucket= c_buckets+buck;
Uint32 tail= bucket->m_buffer_tail;
- Buffer_page* page= (Buffer_page*)(m_tup->page+tail);
+ Buffer_page* page= (Buffer_page*)(m_tup->cpage+tail);
Uint32 max_gci = page->m_max_gci;
Uint32 next_page = page->m_next_page;
Uint32 *ptr = page->m_data + pos;
@@ -4502,7 +4502,7 @@ Suma::resend_bucket(Signal* signal, Uint32 buck, Uint32 min_gci,
* Signal to subscriber(s)
*/
Ptr<Table> tabPtr;
- ndbrequire(tabPtr.p = c_tablePool.getPtr(table));
+ ndbrequire((tabPtr.p = c_tablePool.getPtr(table)) != 0);
SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg;
data->gci = last_gci;
diff --git a/storage/ndb/src/kernel/blocks/tsman.cpp b/storage/ndb/src/kernel/blocks/tsman.cpp
new file mode 100644
index 00000000000..324f909d78b
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/tsman.cpp
@@ -0,0 +1,2101 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "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>
+
+
+Tsman::Tsman(const Configuration & conf, class Pgman* pg, class Lgman* lg) :
+ SimulatedBlock(TSMAN, conf),
+ 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);
+
+ // 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_END_LCP_REQ, &Tsman::execEND_LCP_REQ);
+
+ addRecSignal(GSN_GET_TABINFOREQ, &Tsman::execGET_TABINFOREQ);
+
+ m_tablespace_pool.setSize(10);
+ m_tablespace_hash.setSize(10);
+ m_file_pool.setSize(10);
+ m_file_hash.setSize(10);
+}
+
+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 =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
+void
+Tsman::execSTTOR(Signal* signal)
+{
+ jamEntry();
+
+ const Uint32 startphase = signal->theData[1];
+ const Uint32 typeOfStart = signal->theData[7];
+
+ 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;
+ }
+ }
+}
+
+#ifdef VM_TRACE
+struct TsmanChunk
+{
+ Uint32 page_count;
+ Local_key start_page;
+ Vector<Uint32> bitmask;
+};
+template class Vector<TsmanChunk>;
+template class Vector<Uint32>;
+#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) == 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);
+}
+
+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)
+ {
+ ndbassert(false);
+ 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,
+ DLList<Datafile>::Head& head, Uint32 id)
+{
+ LocalDLList<Datafile> 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;
+ }
+
+ new (file_ptr.p) Datafile(req);
+ LocalDLList<Datafile> 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 | Page_cache_client::NO_HOOK;
+ 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);
+ LocalDLList<Datafile> 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;
+
+ // Extent size in #pages
+ Uint32 extent_size = ts_ptr.p->m_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 tmp = Uint64(extents_per_page) * Uint64(extent_size);
+ Uint64 extent_pages = pages / (1+tmp);
+ extent_pages = extent_pages ? extent_pages : 1;
+
+ Uint64 data_pages = pages - extent_pages -1;
+ Uint64 extents = data_pages / extent_size;
+ data_pages = extents * extent_size;
+
+ 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;
+ hi = (pages * File_formats::NDB_PAGE_SIZE) >> 32;
+ lo = (pages * File_formats::NDB_PAGE_SIZE) & 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);
+
+ LocalDLList<Datafile> 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 | Page_cache_client::NO_HOOK;
+ 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<Tablespace> ts_ptr;
+ m_tablespace_pool.getPtr(ts_ptr, ptr.p->m_tablespace_ptr_i);
+ if (!getNodeState().getSystemRestartInProgress())
+ {
+ LocalDLList<Datafile> free(m_file_pool, ts_ptr.p->m_free_files);
+ LocalDLList<Datafile> 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;
+ {
+ LocalDLList<Datafile> 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 = lg_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 SZ= File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_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;
+ }
+ 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) & ~(1 << (SZ - 1));
+ header->update_free_bits(i, bits);
+ tup->disk_restart_page_bits(tableId, fragmentId, &key, 0, 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;
+
+ LocalDLList<Datafile> meta(m_file_pool, lg_ptr.p->m_meta_files);
+ Ptr<Datafile> next = ptr;
+ meta.next(next);
+ if(firstFree != RNIL)
+ {
+ LocalDLList<Datafile> free(m_file_pool, lg_ptr.p->m_free_files);
+ meta.remove(ptr);
+ free.add(ptr);
+ }
+ else
+ {
+ LocalDLList<Datafile> 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();
+ LocalDLList<Datafile> 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();
+ LocalDLList<Datafile> free(m_file_pool, fg_ptr.p->m_free_files);
+ free.remove(file_ptr);
+ }
+ else
+ {
+ errorCode = DropFileImplRef::NoSuchFile;
+ break;
+ }
+
+ LocalDLList<Datafile> 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;
+ LocalDLList<Datafile> 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)
+ {
+ LocalDLList<Datafile> free(m_file_pool, fg_ptr.p->m_free_files);
+ free.add(file_ptr);
+ }
+ else
+ {
+ LocalDLList<Datafile> 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));
+ Uint32 size = ts_ptr.p->m_extent_size;
+ LocalDLList<Datafile> tmp(m_file_pool, ts_ptr.p->m_free_files);
+
+ if (tmp.first(file_ptr))
+ {
+ Uint32 eh_words = File_formats::Datafile::extent_header_words(size);
+ Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS/eh_words;
+
+ Uint32 extent = file_ptr.p->m_online.m_first_free_extent;
+ Uint32 data_off = file_ptr.p->m_online.m_offset_data_pages;
+ 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;
+ preq.m_page.m_page_idx = extent;
+
+ /**
+ * 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();
+ LocalDLList<Datafile> 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);
+
+ 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;
+ }
+
+ /**
+ * Pack return values
+ */
+ AllocExtentReq* rep = (AllocExtentReq*)signal->getDataPtr();
+ rep->reply.errorCode = err;
+ return;
+}
+
+void
+Tsman::execFREE_EXTENT_REQ(Signal* signal)
+{
+ jamEntry();
+ Ptr<Tablespace> ts_ptr;
+ Ptr<Datafile> file_ptr;
+ FreeExtentReq req = *(FreeExtentReq*)signal->getDataPtr();
+ FreeExtentReq::ErrorCode err = (FreeExtentReq::ErrorCode)0;
+
+ ndbrequire(m_tablespace_hash.find(ts_ptr, req.request.tablespace_id));
+ Datafile file_key;
+ file_key.m_file_no = req.request.key.m_file_no;
+ ndbrequire(m_file_hash.find(file_ptr, file_key));
+ Uint32 size = ts_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 data_off = file_ptr.p->m_online.m_offset_data_pages;
+ Uint32 extent = (req.request.key.m_page_no - data_off) / size + per_page;
+
+
+ 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 = 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(extent_no, size);
+
+ ndbrequire(header->m_table == req.request.table_id);
+ header->m_table = RNIL;
+ 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;
+ file_ptr.p->m_online.m_used_extent_cnt--;
+ }
+ 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 bit, Uint64 lsn)
+{
+ 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));
+
+ Uint32 size = file_ptr.p->m_extent_size;
+ 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 SZ= File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE;
+
+ Uint32 extent = (key->m_page_no - data_off) / size + per_page;
+ 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 = 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(extent_no, size);
+
+ ndbrequire(header->m_table != RNIL);
+
+ Uint32 page_no_in_extent = (key->m_page_no - data_off) % size;
+
+ /**
+ * Toggle word
+ */
+ bit |= header->get_free_bits(page_no_in_extent) & (1 << (SZ - 1));
+ header->update_free_bits(page_no_in_extent, bit);
+
+#ifdef VM_TRACE
+ if(! (bit & ((1 << (SZ - 1)) - 1)) && header->check_free(eh_words))
+ {
+ ndbout_c("Extent is now free!!");
+ }
+#endif
+
+ /**
+ * Update lsn
+ */
+ m_page_cache_client.update_lsn(preq.m_page, lsn);
+ return 0;
+ }
+
+ return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
+}
+
+int
+Tsman::unmap_page(Signal* signal, Local_key *key)
+{
+ 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));
+
+ Uint32 size = file_ptr.p->m_extent_size;
+ 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 SZ= File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE;
+
+ Uint32 extent = (key->m_page_no - data_off) / size + per_page;
+ 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 = 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(extent_no, size);
+
+ ndbrequire(header->m_table != RNIL);
+
+ Uint32 page_no_in_extent = (key->m_page_no - data_off) % size;
+
+ /**
+ * Toggle word
+ */
+ unsigned bit =
+ (header->get_free_bits(page_no_in_extent) & ((1 << (SZ - 1)) - 1));
+ header->update_free_bits(page_no_in_extent, bit);
+ 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));
+
+ Uint32 size = file_ptr.p->m_extent_size;
+ 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 extent = (req.key.m_page_no - data_off) / size;
+ Uint32 extent_no = extent % per_page;
+
+ Page_cache_client::Request preq;
+ preq.m_page.m_page_no = 1 /* zero */ + extent / per_page;
+ 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(extent_no, size);
+
+ ndbrequire(header->m_table == req.request.table_id);
+
+ Uint32 page_no_in_extent = (req.key.m_page_no - data_off) % size;
+ 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%
+ */
+
+ /**
+ * Search
+ */
+ Uint32 *src= header->m_page_bitmask + word;
+ for(page_no= page_no_in_extent; page_no<size; page_no++)
+ {
+ src_bits= (* src >> shift) & ((1 << SZ) - 1);
+ if(src_bits <= req.bits)
+ {
+ 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 <= req.bits)
+ {
+ goto found;
+ }
+ shift += SZ;
+ src = src + (shift >> 5);
+ shift &= 31;
+ }
+
+ err= AllocPageReq::NoPageFree;
+ }
+
+ rep->reply.errorCode = err;
+ return;
+
+found:
+ src_bits |= (1 << (SZ - 1)); // high unlogged, allocated bit
+ header->update_free_bits(page_no, src_bits);
+ rep->bits= src_bits & ((1 << (SZ - 1)) - 1);
+ rep->key.m_page_no= data_off + extent * size + page_no;
+ rep->reply.errorCode= 0;
+ return;
+}
+
+int
+Tsman::restart_undo_page_free_bits(Signal* signal,
+ Local_key *key, unsigned bit,
+ Uint64 undo_lsn)
+{
+ 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));
+
+ Uint32 size = file_ptr.p->m_extent_size;
+ 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 SZ= File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE;
+
+ Uint32 extent = (key->m_page_no - data_off) / size + per_page;
+ 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 = 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;
+
+ Uint64 lsn = 0;
+ lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32;
+ lsn += page->m_page_header.m_page_lsn_lo;
+
+ if (undo_lsn <= lsn)
+ {
+ File_formats::Datafile::Extent_header* header =
+ page->get_header(extent_no, size);
+
+ Uint32 tableId = header->m_table;
+ Uint32 fragmentId = header->m_fragment_id;
+ ndbrequire(tableId != RNIL);
+ ndbrequire(fragmentId != RNIL);
+
+ Uint32 page_no_in_extent = (key->m_page_no - data_off) % size;
+
+ Uint32 old_bits = header->get_free_bits(page_no_in_extent);
+ if (old_bits != bit)
+ {
+ ndbout << "tsman toggle " << *key << " from " << old_bits << " to "
+ << bit << endl;
+ Dbtup* tup= (Dbtup*)globalData.getBlock(DBTUP);
+ header->update_free_bits(page_no_in_extent, bit);
+ tup->disk_restart_page_bits(tableId, fragmentId, key, old_bits, bit);
+ }
+ lsn--; // prevent UNDO from being run again...
+ }
+ else
+ {
+ ndbout_c("tsman skipping undo %lld %lld", undo_lsn, lsn);
+ }
+
+ m_page_cache_client.update_lsn(preq.m_page, lsn);
+ return 0;
+ }
+ return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
+}
+
+void
+Tsman::execEND_LCP_REQ(Signal* signal)
+{
+ jamEntry();
+
+ /**
+ * 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:
+ {
+ LocalDLList<Datafile> 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:
+ {
+ LocalDLList<Datafile> 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;
+
+ LocalDLList<Datafile> free(m_file_pool, ptr.p->m_free_files);
+ LocalDLList<Datafile> 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::TableNameTooLong);
+ return;
+ }
+
+ DLHashTable<Datafile>::Iterator iter;
+ ndbrequire(m_file_hash.first(iter));
+ while(iter.curr.p->m_file_id != tableId && m_file_hash.next(iter))
+ ;
+ ndbrequire(iter.curr.p->m_file_id == tableId);
+
+ 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
new file mode 100644
index 00000000000..cbe5e356440
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/tsman.hpp
@@ -0,0 +1,372 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef 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(const Configuration & conf, class Pgman*, class 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 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_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;
+ } 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;
+ }
+ };
+
+ struct Tablespace
+ {
+ Tablespace(){}
+ Tablespace(Tsman*, Lgman*, const struct CreateFilegroupImplReq*);
+
+ 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
+ DLList<Datafile>::Head m_free_files; // Files w/ free space
+ Logfile_client m_logfile_client;
+
+ DLList<Datafile>::Head m_full_files; // Files wo/ free space
+ DLList<Datafile>::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;
+ }
+ };
+
+private:
+ friend class Tablespace_client;
+ ArrayPool<Datafile> m_file_pool;
+ ArrayPool<Tablespace> m_tablespace_pool;
+
+ DLHashTable<Datafile> m_file_hash;
+ DLList<Tablespace> m_tablespace_list;
+ KeyTable<Tablespace> 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 bits, Uint64 lsn);
+ int unmap_page(Signal*, Local_key*);
+ int restart_undo_page_free_bits(Signal*, Local_key*, unsigned, Uint64);
+
+ 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>&, DLList<Datafile>::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);
+};
+
+class Tablespace_client
+{
+ 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;
+ }
+
+ /**
+ * 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);
+
+ /**
+ * Update page free bits
+ */
+ int update_page_free_bits(Local_key*, unsigned bits, Uint64 lsn);
+
+ /**
+ * Update unlogged page free bit
+ */
+ int unmap_page(Local_key*);
+
+ /**
+ * Undo handling of page bits
+ */
+ int restart_undo_page_free_bits(Local_key*, unsigned bits, Uint64 lsn);
+
+ /**
+ * Get tablespace info
+ *
+ * Store result in <em>rep</em>
+ *
+ * Return 0 - on sucess
+ * <0 - on error
+ */
+ int get_tablespace_info(CreateFilegroupImplReq* rep);
+};
+
+#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)
+{
+ FreeExtentReq* req = (FreeExtentReq*)m_signal->theData;
+ req->request.key = *key;
+ req->request.table_id = m_table_id;
+ req->request.tablespace_id = m_tablespace_id;
+ 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 bits, Uint64 lsn)
+{
+ return m_tsman->update_page_free_bits(m_signal, key, bits, lsn);
+}
+
+inline
+int
+Tablespace_client::unmap_page(Local_key *key)
+{
+ return m_tsman->unmap_page(m_signal, key);
+}
+
+inline
+int
+Tablespace_client::restart_undo_page_free_bits(Local_key* key,
+ unsigned bits, Uint64 lsn)
+{
+ return m_tsman->restart_undo_page_free_bits(m_signal,
+ key, bits, lsn);
+}
+
+
+#endif
diff --git a/storage/ndb/src/kernel/vm/ArrayPool.hpp b/storage/ndb/src/kernel/vm/ArrayPool.hpp
index 3b1264af8be..9133bbf6d36 100644
--- a/storage/ndb/src/kernel/vm/ArrayPool.hpp
+++ b/storage/ndb/src/kernel/vm/ArrayPool.hpp
@@ -26,9 +26,6 @@
#include <Bitmask.hpp>
template <class T> class Array;
-template <class T> class SLList;
-template <class T> class DLList;
-template <class T> class DLHashTable;
/**
* Template class used for implementing an
@@ -45,7 +42,7 @@ public:
*
* Note, can currently only be called once
*/
- bool setSize(Uint32 noOfElements, bool exit_on_error = true);
+ bool setSize(Uint32 noOfElements, bool align = false, bool exit_on_error = true);
inline Uint32 getNoOfFree() const {
return noOfFree;
@@ -123,9 +120,6 @@ public:
protected:
friend class Array<T>;
- friend class SLList<T>;
- friend class DLList<T>;
- friend class DLHashTable<T>;
/**
* Allocate <b>n</b> consecutive object from pool
@@ -182,6 +176,7 @@ protected:
Uint32 size;
Uint32 noOfFree;
T * theArray;
+ void * alloc_ptr;
Uint32 bitmaskSz;
Uint32 *theAllocatedBitmask;
};
@@ -193,6 +188,7 @@ ArrayPool<T>::ArrayPool(){
size = 0;
noOfFree = 0;
theArray = 0;
+ alloc_ptr = 0;
#ifdef ARRAY_GUARD
theAllocatedBitmask = 0;
#endif
@@ -202,8 +198,9 @@ template <class T>
inline
ArrayPool<T>::~ArrayPool(){
if(theArray != 0){
- ndbd_free(theArray, size * sizeof(T));
+ ndbd_free(alloc_ptr, size * sizeof(T));
theArray = 0;
+ alloc_ptr = 0;
#ifdef ARRAY_GUARD
delete []theAllocatedBitmask;
theAllocatedBitmask = 0;
@@ -219,11 +216,24 @@ ArrayPool<T>::~ArrayPool(){
template <class T>
inline
bool
-ArrayPool<T>::setSize(Uint32 noOfElements, bool exit_on_error){
+ArrayPool<T>::setSize(Uint32 noOfElements, bool align, bool exit_on_error){
if(size == 0){
if(noOfElements == 0)
return true;
- theArray = (T *)ndbd_malloc(noOfElements * sizeof(T));
+ if(align)
+ {
+ alloc_ptr = ndbd_malloc((noOfElements+1) * sizeof(T));
+ UintPtr p = (UintPtr)alloc_ptr;
+ UintPtr mod = p % sizeof(T);
+ if (mod)
+ {
+ p += sizeof(T) - mod;
+ }
+ theArray = (T *)p;
+ }
+ else
+ theArray = (T *)(alloc_ptr = ndbd_malloc(noOfElements * sizeof(T)));
+
if(theArray == 0)
{
if (!exit_on_error)
diff --git a/storage/ndb/src/kernel/vm/Configuration.cpp b/storage/ndb/src/kernel/vm/Configuration.cpp
index 484bca68772..fe7d474b578 100644
--- a/storage/ndb/src/kernel/vm/Configuration.cpp
+++ b/storage/ndb/src/kernel/vm/Configuration.cpp
@@ -658,14 +658,14 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
*/
// Can keep 65536 pages (= 0.5 GByte)
cfg.put(CFG_ACC_DIR_RANGE,
- 4 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
+ 2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
cfg.put(CFG_ACC_DIR_ARRAY,
(noOfIndexPages >> 8) +
- 4 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
+ 2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
cfg.put(CFG_ACC_FRAGMENT,
- 2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
+ NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
/*-----------------------------------------------------------------------*/
// The extra operation records added are used by the scan and node
@@ -681,14 +681,11 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
cfg.put(CFG_ACC_OVERFLOW_RECS,
noOfIndexPages +
- 2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
+ NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
cfg.put(CFG_ACC_PAGE8,
noOfIndexPages + 32);
- cfg.put(CFG_ACC_ROOT_FRAG,
- NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
-
cfg.put(CFG_ACC_TABLE, noOfAccTables);
cfg.put(CFG_ACC_SCAN, noOfLocalScanRecords);
@@ -771,7 +768,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
* Tup Size Alt values
*/
cfg.put(CFG_TUP_FRAG,
- 2 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
+ NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
cfg.put(CFG_TUP_OP_RECS,
noOfLocalOperations + 50);
@@ -780,14 +777,14 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
noOfDataPages);
cfg.put(CFG_TUP_PAGE_RANGE,
- 4 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
+ 2 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
cfg.put(CFG_TUP_TABLE,
noOfMetaTables);
cfg.put(CFG_TUP_TABLE_DESC,
- 2 * 6 * NO_OF_FRAG_PER_NODE * noOfAttributes * noOfReplicas +
- 2 * 10 * NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas );
+ 6 * NO_OF_FRAG_PER_NODE * noOfAttributes * noOfReplicas +
+ 10 * NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas );
cfg.put(CFG_TUP_STORED_PROC,
noOfLocalScanRecords);
@@ -801,7 +798,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
noOfMetaTables /*noOfOrderedIndexes*/);
cfg.put(CFG_TUX_FRAGMENT,
- 2 * NO_OF_FRAG_PER_NODE * noOfOrderedIndexes * noOfReplicas);
+ NO_OF_FRAG_PER_NODE * noOfOrderedIndexes * noOfReplicas);
cfg.put(CFG_TUX_ATTRIBUTE,
noOfOrderedIndexes * 4);
diff --git a/storage/ndb/src/kernel/vm/DLCFifoList.hpp b/storage/ndb/src/kernel/vm/DLCFifoList.hpp
new file mode 100644
index 00000000000..c02c2765659
--- /dev/null
+++ b/storage/ndb/src/kernel/vm/DLCFifoList.hpp
@@ -0,0 +1,119 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef 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
new file mode 100644
index 00000000000..c3a2fc8029f
--- /dev/null
+++ b/storage/ndb/src/kernel/vm/DLCHashTable.hpp
@@ -0,0 +1,82 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef 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
index b139ade831d..6543be3c812 100644
--- a/storage/ndb/src/kernel/vm/DLFifoList.hpp
+++ b/storage/ndb/src/kernel/vm/DLFifoList.hpp
@@ -24,7 +24,7 @@
* Template class used for implementing an
* list of object retreived from a pool
*/
-template <class T>
+template <class T, class U = T>
class DLFifoList {
public:
/**
@@ -34,6 +34,12 @@ public:
Head();
Uint32 firstItem;
Uint32 lastItem;
+
+#ifdef VM_TRACE
+ bool in_use;
+#endif
+
+ inline bool isEmpty() const { return firstItem == RNIL;}
};
DLFifoList(ArrayPool<T> & thePool);
@@ -60,6 +66,11 @@ public:
void add(Ptr<T> &);
/**
+ * Insert object <em>ptr</ptr> _before_ <em>loc</em>
+ */
+ void insert(Ptr<T> & ptr, Ptr<T>& loc);
+
+ /**
* Remove from list
*/
void remove(Ptr<T> &);
@@ -101,6 +112,14 @@ public:
*/
bool first(Ptr<T> &) const ;
+
+ /**
+ * Update ptr to first element in list
+ *
+ * Return i
+ */
+ bool last(Ptr<T> &) const ;
+
/**
* Get next element
*
@@ -108,12 +127,27 @@ public:
*/
bool next(Ptr<T> &) const ;
+
/**
- * Check if next exists
+ * 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 prev exists i.e. this is not first
+ *
+ * NOTE ptr must be both p & i
+ */
+ bool hasPrev(const Ptr<T> &) const;
Uint32 noOfElements() const {
Uint32 c = 0;
@@ -121,7 +155,7 @@ public:
while(i != RNIL){
c++;
const T * t = thePool.getPtr(i);
- i = t->nextList;
+ i = t->U::nextList;
}
return c;
}
@@ -136,44 +170,64 @@ public:
T * t = thePool.getPtr(i);
out << (unsigned int) t << "[" << i << "]:";
t->print(out); out << " ";
- i = t->nextList;
+ i = t->U::nextList;
}
}
inline bool isEmpty() const { return head.firstItem == RNIL;}
+ /**
+ * Copy list (head)
+ * Will construct to identical lists
+ */
+ DLFifoList<T>& operator=(const DLFifoList<T>& src){
+ assert(&thePool == &src.thePool);
+ this->head = src.head;
+ return * this;
+ }
+
protected:
Head head;
ArrayPool<T> & thePool;
};
-template<class T>
-class LocalDLFifoList : public DLFifoList<T> {
+template <class T, class U = T>
+class LocalDLFifoList : public DLFifoList<T,U> {
public:
- LocalDLFifoList(ArrayPool<T> & thePool, typename DLFifoList<T>::Head & _src)
- : DLFifoList<T>(thePool), src(_src)
+ LocalDLFifoList(ArrayPool<T> & thePool, typename DLFifoList<T,U>::Head &_src)
+ : DLFifoList<T,U>(thePool), src(_src)
{
this->head = src;
+#ifdef VM_TRACE
+ assert(src.in_use == false);
+ src.in_use = true;
+#endif
}
~LocalDLFifoList(){
+#ifdef VM_TRACE
+ assert(src.in_use == true);
+#endif
src = this->head;
}
private:
- typename DLFifoList<T>::Head & src;
+ typename DLFifoList<T,U>::Head & src;
};
-template <class T>
+template <class T, class U>
inline
-DLFifoList<T>::DLFifoList(ArrayPool<T> & _pool):
+DLFifoList<T,U>::DLFifoList(ArrayPool<T> & _pool):
thePool(_pool){
}
-template<class T>
+template <class T, class U>
inline
-DLFifoList<T>::Head::Head(){
+DLFifoList<T,U>::Head::Head(){
firstItem = RNIL;
lastItem = RNIL;
+#ifdef VM_TRACE
+ in_use = false;
+#endif
}
/**
@@ -181,10 +235,10 @@ DLFifoList<T>::Head::Head(){
*
* Return i
*/
-template <class T>
+template <class T, class U>
inline
bool
-DLFifoList<T>::seize(Ptr<T> & p){
+DLFifoList<T,U>::seize(Ptr<T> & p){
thePool.seize(p);
if (p.i != RNIL) {
add(p);
@@ -199,10 +253,10 @@ DLFifoList<T>::seize(Ptr<T> & p){
*
* Return i
*/
-template <class T>
+template <class T, class U>
inline
bool
-DLFifoList<T>::seizeId(Ptr<T> & p, Uint32 ir){
+DLFifoList<T,U>::seizeId(Ptr<T> & p, Uint32 ir){
thePool.seizeId(p, ir);
if(p.i != RNIL){
add(p);
@@ -212,52 +266,73 @@ DLFifoList<T>::seizeId(Ptr<T> & p, Uint32 ir){
return false;
}
-template <class T>
+template <class T, class U>
inline
void
-DLFifoList<T>::add(Ptr<T> & p){
+DLFifoList<T,U>::add(Ptr<T> & p){
T * t = p.p;
Uint32 last = head.lastItem;
if(p.i == RNIL)
- ErrorReporter::handleAssert("DLFifoList<T>::add", __FILE__, __LINE__);
+ ErrorReporter::handleAssert("DLFifoList<T,U>::add", __FILE__, __LINE__);
- t->nextList = RNIL;
- t->prevList = last;
+ t->U::nextList = RNIL;
+ t->U::prevList = last;
if (head.firstItem == RNIL)
head.firstItem = p.i;
head.lastItem = p.i;
if(last != RNIL){
T * t2 = thePool.getPtr(last);
- t2->nextList = p.i;
+ t2->U::nextList = p.i;
}
}
+template <class T, class U>
+inline
+void
+DLFifoList<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;
+}
+
/**
* Return an object to pool
*/
-template <class T>
+template <class T, class U>
inline
void
-DLFifoList<T>::release(Uint32 i){
+DLFifoList<T,U>::release(Uint32 i){
Ptr<T> p;
p.i = i;
p.p = thePool.getPtr(i);
release(p);
}
-template <class T>
+template <class T, class U>
inline
void
-DLFifoList<T>::remove(Ptr<T> & p){
+DLFifoList<T,U>::remove(Ptr<T> & p){
T * t = p.p;
- Uint32 ni = t->nextList;
- Uint32 pi = t->prevList;
+ Uint32 ni = t->U::nextList;
+ Uint32 pi = t->U::prevList;
if(ni != RNIL){
T * t = thePool.getPtr(ni);
- t->prevList = pi;
+ t->U::prevList = pi;
} else {
// We are releasing last
head.lastItem = pi;
@@ -265,7 +340,7 @@ DLFifoList<T>::remove(Ptr<T> & p){
if(pi != RNIL){
T * t = thePool.getPtr(pi);
- t->nextList = ni;
+ t->U::nextList = ni;
} else {
// We are releasing first
head.firstItem = ni;
@@ -275,47 +350,47 @@ DLFifoList<T>::remove(Ptr<T> & p){
/**
* Return an object to pool
*/
-template <class T>
+template <class T, class U>
inline
void
-DLFifoList<T>::release(Ptr<T> & p){
+DLFifoList<T,U>::release(Ptr<T> & p){
remove(p);
thePool.release(p.i);
}
-template <class T>
+template <class T, class U>
inline
void
-DLFifoList<T>::release(){
+DLFifoList<T,U>::release(){
Ptr<T> p;
while(head.firstItem != RNIL){
p.i = head.firstItem;
p.p = thePool.getPtr(head.firstItem);
T * t = p.p;
- head.firstItem = t->nextList;
+ head.firstItem = t->U::nextList;
release(p);
}
}
-template <class T>
+template <class T, class U>
inline
void
-DLFifoList<T>::getPtr(Ptr<T> & p, Uint32 i) const {
+DLFifoList<T,U>::getPtr(Ptr<T> & p, Uint32 i) const {
p.i = i;
p.p = thePool.getPtr(i);
}
-template <class T>
+template <class T, class U>
inline
void
-DLFifoList<T>::getPtr(Ptr<T> & p) const {
+DLFifoList<T,U>::getPtr(Ptr<T> & p) const {
thePool.getPtr(p);
}
-template <class T>
+template <class T, class U>
inline
T *
-DLFifoList<T>::getPtr(Uint32 i) const {
+DLFifoList<T,U>::getPtr(Uint32 i) const {
return thePool.getPtr(i);
}
@@ -324,10 +399,10 @@ DLFifoList<T>::getPtr(Uint32 i) const {
*
* Return i
*/
-template <class T>
+template <class T, class U>
inline
bool
-DLFifoList<T>::first(Ptr<T> & p) const {
+DLFifoList<T,U>::first(Ptr<T> & p) const {
p.i = head.firstItem;
if(p.i != RNIL){
p.p = thePool.getPtr(p.i);
@@ -337,11 +412,37 @@ DLFifoList<T>::first(Ptr<T> & p) const {
return false;
}
-template <class T>
+template <class T, class U>
+inline
+bool
+DLFifoList<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 <class T, class U>
+inline
+bool
+DLFifoList<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 <class T, class U>
inline
bool
-DLFifoList<T>::next(Ptr<T> & p) const {
- p.i = p.p->nextList;
+DLFifoList<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;
@@ -350,11 +451,18 @@ DLFifoList<T>::next(Ptr<T> & p) const {
return false;
}
-template <class T>
+template <class T, class U>
+inline
+bool
+DLFifoList<T,U>::hasNext(const Ptr<T> & p) const {
+ return p.p->U::nextList != RNIL;
+}
+
+template <class T, class U>
inline
bool
-DLFifoList<T>::hasNext(const Ptr<T> & p) const {
- return p.p->nextList != RNIL;
+DLFifoList<T,U>::hasPrev(const Ptr<T> & p) const {
+ return p.p->U::prevList != RNIL;
}
#endif
diff --git a/storage/ndb/src/kernel/vm/DLHashTable.hpp b/storage/ndb/src/kernel/vm/DLHashTable.hpp
index 13a9632f8da..319d12ea4fc 100644
--- a/storage/ndb/src/kernel/vm/DLHashTable.hpp
+++ b/storage/ndb/src/kernel/vm/DLHashTable.hpp
@@ -30,7 +30,7 @@
* -# Uint32 hashValue() const;
* Which should return a 32 bit hashvalue
*/
-template <class T>
+template <class T, class U = T>
class DLHashTable {
public:
DLHashTable(ArrayPool<T> & thePool);
@@ -156,26 +156,26 @@ private:
ArrayPool<T> & thePool;
};
-template<class T>
+template <class T, class U>
inline
-DLHashTable<T>::DLHashTable(ArrayPool<T> & _pool)
+DLHashTable<T,U>::DLHashTable(ArrayPool<T> & _pool)
: thePool(_pool)
{
mask = 0;
hashValues = 0;
}
-template<class T>
+template <class T, class U>
inline
-DLHashTable<T>::~DLHashTable(){
+DLHashTable<T,U>::~DLHashTable(){
if(hashValues != 0)
delete [] hashValues;
}
-template<class T>
+template <class T, class U>
inline
bool
-DLHashTable<T>::setSize(Uint32 size){
+DLHashTable<T,U>::setSize(Uint32 size){
Uint32 i = 1;
while(i < size) i *= 2;
@@ -201,23 +201,23 @@ DLHashTable<T>::setSize(Uint32 size){
return true;
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::add(Ptr<T> & obj){
+DLHashTable<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;
+ obj.p->U::nextHash = RNIL;
+ obj.p->U::prevHash = RNIL;
} else {
T * tmp = thePool.getPtr(i);
- tmp->prevHash = obj.i;
- obj.p->nextHash = i;
- obj.p->prevHash = RNIL;
+ tmp->U::prevHash = obj.i;
+ obj.p->U::nextHash = i;
+ obj.p->U::prevHash = RNIL;
hashValues[hv] = obj.i;
}
@@ -226,10 +226,10 @@ DLHashTable<T>::add(Ptr<T> & obj){
/**
* First element
*/
-template<class T>
+template <class T, class U>
inline
bool
-DLHashTable<T>::first(Iterator & iter) const {
+DLHashTable<T,U>::first(Iterator & iter) const {
Uint32 i = 0;
while(i <= mask && hashValues[i] == RNIL) i++;
if(i <= mask){
@@ -243,11 +243,11 @@ DLHashTable<T>::first(Iterator & iter) const {
return false;
}
-template<class T>
+template <class T, class U>
inline
bool
-DLHashTable<T>::next(Iterator & iter) const {
- if(iter.curr.p->nextHash == RNIL){
+DLHashTable<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){
@@ -261,15 +261,15 @@ DLHashTable<T>::next(Iterator & iter) const {
}
}
- iter.curr.i = iter.curr.p->nextHash;
+ iter.curr.i = iter.curr.p->U::nextHash;
iter.curr.p = thePool.getPtr(iter.curr.i);
return true;
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::remove(Ptr<T> & ptr, const T & key){
+DLHashTable<T,U>::remove(Ptr<T> & ptr, const T & key){
const Uint32 hv = key.hashValue() & mask;
Uint32 i;
@@ -281,16 +281,16 @@ DLHashTable<T>::remove(Ptr<T> & ptr, const T & key){
while(i != RNIL){
p = thePool.getPtr(i);
if(key.equal(* p)){
- const Uint32 next = p->nextHash;
+ const Uint32 next = p->U::nextHash;
if(prev.i == RNIL){
hashValues[hv] = next;
} else {
- prev.p->nextHash = next;
+ prev.p->U::nextHash = next;
}
if(next != RNIL){
T * nextP = thePool.getPtr(next);
- nextP->prevHash = prev.i;
+ nextP->U::prevHash = prev.i;
}
ptr.i = i;
@@ -299,15 +299,15 @@ DLHashTable<T>::remove(Ptr<T> & ptr, const T & key){
}
prev.p = p;
prev.i = i;
- i = p->nextHash;
+ i = p->U::nextHash;
}
ptr.i = RNIL;
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::release(Ptr<T> & ptr, const T & key){
+DLHashTable<T,U>::release(Ptr<T> & ptr, const T & key){
const Uint32 hv = key.hashValue() & mask;
Uint32 i;
@@ -319,16 +319,16 @@ DLHashTable<T>::release(Ptr<T> & ptr, const T & key){
while(i != RNIL){
p = thePool.getPtr(i);
if(key.equal(* p)){
- const Uint32 next = p->nextHash;
+ const Uint32 next = p->U::nextHash;
if(prev.i == RNIL){
hashValues[hv] = next;
} else {
- prev.p->nextHash = next;
+ prev.p->U::nextHash = next;
}
if(next != RNIL){
T * nextP = thePool.getPtr(next);
- nextP->prevHash = prev.i;
+ nextP->U::prevHash = prev.i;
}
thePool.release(i);
@@ -338,41 +338,41 @@ DLHashTable<T>::release(Ptr<T> & ptr, const T & key){
}
prev.p = p;
prev.i = i;
- i = p->nextHash;
+ i = p->U::nextHash;
}
ptr.i = RNIL;
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::remove(Uint32 i){
+DLHashTable<T,U>::remove(Uint32 i){
Ptr<T> tmp;
tmp.i = i;
tmp.p = thePool.getPtr(i);
remove(tmp);
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::release(Uint32 i){
+DLHashTable<T,U>::release(Uint32 i){
Ptr<T> tmp;
tmp.i = i;
tmp.p = thePool.getPtr(i);
release(tmp);
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::remove(Ptr<T> & ptr){
- const Uint32 next = ptr.p->nextHash;
- const Uint32 prev = ptr.p->prevHash;
+DLHashTable<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->nextHash = next;
+ prevP->U::nextHash = next;
} else {
const Uint32 hv = ptr.p->hashValue() & mask;
hashValues[hv] = next;
@@ -380,20 +380,20 @@ DLHashTable<T>::remove(Ptr<T> & ptr){
if(next != RNIL){
T * nextP = thePool.getPtr(next);
- nextP->prevHash = prev;
+ nextP->U::prevHash = prev;
}
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::release(Ptr<T> & ptr){
- const Uint32 next = ptr.p->nextHash;
- const Uint32 prev = ptr.p->prevHash;
+DLHashTable<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->nextHash = next;
+ prevP->U::nextHash = next;
} else {
const Uint32 hv = ptr.p->hashValue() & mask;
hashValues[hv] = next;
@@ -401,24 +401,24 @@ DLHashTable<T>::release(Ptr<T> & ptr){
if(next != RNIL){
T * nextP = thePool.getPtr(next);
- nextP->prevHash = prev;
+ nextP->U::prevHash = prev;
}
thePool.release(ptr.i);
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::removeAll(){
+DLHashTable<T,U>::removeAll(){
for(Uint32 i = 0; i<=mask; i++)
hashValues[i] = RNIL;
}
-template<class T>
+template <class T, class U>
inline
bool
-DLHashTable<T>::next(Uint32 bucket, Iterator & iter) const {
+DLHashTable<T,U>::next(Uint32 bucket, Iterator & iter) const {
while (bucket <= mask && hashValues[bucket] == RNIL)
bucket++;
@@ -434,43 +434,43 @@ DLHashTable<T>::next(Uint32 bucket, Iterator & iter) const {
return true;
}
-template<class T>
+template <class T, class U>
inline
bool
-DLHashTable<T>::seize(Ptr<T> & ptr){
+DLHashTable<T,U>::seize(Ptr<T> & ptr){
if(thePool.seize(ptr)){
- ptr.p->nextHash = ptr.p->prevHash = RNIL;
+ ptr.p->U::nextHash = ptr.p->U::prevHash = RNIL;
return true;
}
return false;
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::getPtr(Ptr<T> & ptr, Uint32 i) const {
+DLHashTable<T,U>::getPtr(Ptr<T> & ptr, Uint32 i) const {
ptr.i = i;
ptr.p = thePool.getPtr(i);
}
-template<class T>
+template <class T, class U>
inline
void
-DLHashTable<T>::getPtr(Ptr<T> & ptr) const {
+DLHashTable<T,U>::getPtr(Ptr<T> & ptr) const {
thePool.getPtr(ptr);
}
-template<class T>
+template <class T, class U>
inline
T *
-DLHashTable<T>::getPtr(Uint32 i) const {
+DLHashTable<T,U>::getPtr(Uint32 i) const {
return thePool.getPtr(i);
}
-template<class T>
+template <class T, class U>
inline
bool
-DLHashTable<T>::find(Ptr<T> & ptr, const T & key) const {
+DLHashTable<T,U>::find(Ptr<T> & ptr, const T & key) const {
const Uint32 hv = key.hashValue() & mask;
Uint32 i;
@@ -484,7 +484,7 @@ DLHashTable<T>::find(Ptr<T> & ptr, const T & key) const {
ptr.p = p;
return true;
}
- i = p->nextHash;
+ i = p->U::nextHash;
}
ptr.i = RNIL;
ptr.p = NULL;
diff --git a/storage/ndb/src/kernel/vm/DLList.hpp b/storage/ndb/src/kernel/vm/DLList.hpp
index b7820eb9229..337f9388f74 100644
--- a/storage/ndb/src/kernel/vm/DLList.hpp
+++ b/storage/ndb/src/kernel/vm/DLList.hpp
@@ -24,16 +24,24 @@
* Template class used for implementing an
* list of object retreived from a pool
*/
-template <class T>
+template <class T, class U = T>
class DLList {
public:
/**
* List head
*/
- struct Head {
- 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;
+ }
};
DLList(ArrayPool<T> & thePool);
@@ -58,13 +66,6 @@ public:
bool findId(Uint32 i) const;
/**
- * 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 an object to pool
*/
void release(Uint32 i);
@@ -80,6 +81,11 @@ public:
void release();
/**
+ * Remove all objects from list
+ */
+ void remove();
+
+ /**
* Add object to list
*
* @NOTE MUST be seized from correct pool
@@ -138,7 +144,7 @@ public:
while(i != RNIL){
c++;
const T * t = thePool.getPtr(i);
- i = t->nextList;
+ i = t->U::nextList;
}
return c;
}
@@ -152,7 +158,7 @@ public:
while(i != RNIL){
T * t = thePool.getPtr(i);
t->print(out); out << " ";
- i = t->nextList;
+ i = t->U::nextList;
}
}
@@ -163,11 +169,11 @@ protected:
ArrayPool<T> & thePool;
};
-template<class T>
-class LocalDLList : public DLList<T> {
+template <class T, class U = T>
+class LocalDLList : public DLList<T,U> {
public:
- LocalDLList(ArrayPool<T> & thePool, typename DLList<T>::Head & _src)
- : DLList<T>(thePool), src(_src)
+ LocalDLList(ArrayPool<T> & thePool, typename DLList<T,U>::HeadPOD & _src)
+ : DLList<T,U>(thePool), src(_src)
{
this->head = src;
}
@@ -176,19 +182,19 @@ public:
src = this->head;
}
private:
- typename DLList<T>::Head & src;
+ typename DLList<T,U>::HeadPOD & src;
};
-template <class T>
+template <class T, class U>
inline
-DLList<T>::DLList(ArrayPool<T> & _pool):
+DLList<T,U>::DLList(ArrayPool<T> & _pool):
thePool(_pool){
}
-template<class T>
+template <class T, class U>
inline
-DLList<T>::Head::Head(){
- firstItem = RNIL;
+DLList<T,U>::Head::Head(){
+ this->init();
}
/**
@@ -196,10 +202,10 @@ DLList<T>::Head::Head(){
*
* Return i
*/
-template <class T>
+template <class T, class U>
inline
bool
-DLList<T>::seize(Ptr<T> & p){
+DLList<T,U>::seize(Ptr<T> & p){
if(thePool.seize(p)){
add(p);
return true;
@@ -212,10 +218,10 @@ DLList<T>::seize(Ptr<T> & p){
*
* Return i
*/
-template <class T>
+template <class T, class U>
inline
bool
-DLList<T>::seizeId(Ptr<T> & p, Uint32 ir){
+DLList<T,U>::seizeId(Ptr<T> & p, Uint32 ir){
if(thePool.seizeId(p, ir)){
add(p);
return true;
@@ -223,46 +229,46 @@ DLList<T>::seizeId(Ptr<T> & p, Uint32 ir){
return false;
}
-template <class T>
+template <class T, class U>
inline
bool
-DLList<T>::findId(Uint32 i) const {
+DLList<T,U>::findId(Uint32 i) const {
return thePool.findId(i);
}
-template <class T>
+template <class T, class U>
inline
void
-DLList<T>::add(Ptr<T> & p){
+DLList<T,U>::add(Ptr<T> & p){
T * t = p.p;
Uint32 ff = head.firstItem;
- t->nextList = ff;
- t->prevList = RNIL;
+ t->U::nextList = ff;
+ t->U::prevList = RNIL;
head.firstItem = p.i;
if(ff != RNIL){
T * t2 = thePool.getPtr(ff);
- t2->prevList = p.i;
+ t2->U::prevList = p.i;
}
}
-template <class T>
+template <class T, class U>
inline
void
-DLList<T>::remove(Ptr<T> & p){
+DLList<T,U>::remove(Ptr<T> & p){
T * t = p.p;
- Uint32 ni = t->nextList;
- Uint32 pi = t->prevList;
+ Uint32 ni = t->U::nextList;
+ Uint32 pi = t->U::prevList;
if(ni != RNIL){
T * t = thePool.getPtr(ni);
- t->prevList = pi;
+ t->U::prevList = pi;
}
if(pi != RNIL){
T * t = thePool.getPtr(pi);
- t->nextList = ni;
+ t->U::nextList = ni;
} else {
head.firstItem = ni;
}
@@ -271,10 +277,10 @@ DLList<T>::remove(Ptr<T> & p){
/**
* Return an object to pool
*/
-template <class T>
+template <class T, class U>
inline
void
-DLList<T>::release(Uint32 i){
+DLList<T,U>::release(Uint32 i){
Ptr<T> p;
p.i = i;
p.p = thePool.getPtr(i);
@@ -284,45 +290,52 @@ DLList<T>::release(Uint32 i){
/**
* Return an object to pool
*/
-template <class T>
+template <class T, class U>
inline
void
-DLList<T>::release(Ptr<T> & p){
+DLList<T,U>::release(Ptr<T> & p){
remove(p);
thePool.release(p.i);
}
-template <class T>
+template <class T, class U>
inline
void
-DLList<T>::release(){
+DLList<T,U>::release(){
while(head.firstItem != RNIL){
const T * t = thePool.getPtr(head.firstItem);
const Uint32 i = head.firstItem;
- head.firstItem = t->nextList;
+ head.firstItem = t->U::nextList;
thePool.release(i);
}
}
-template <class T>
+template <class T, class U>
+inline
+void
+DLList<T,U>::remove(){
+ head.firstItem = RNIL;
+}
+
+template <class T, class U>
inline
void
-DLList<T>::getPtr(Ptr<T> & p, Uint32 i) const {
+DLList<T,U>::getPtr(Ptr<T> & p, Uint32 i) const {
p.i = i;
p.p = thePool.getPtr(i);
}
-template <class T>
+template <class T, class U>
inline
void
-DLList<T>::getPtr(Ptr<T> & p) const {
+DLList<T,U>::getPtr(Ptr<T> & p) const {
thePool.getPtr(p);
}
-template <class T>
+template <class T, class U>
inline
T *
-DLList<T>::getPtr(Uint32 i) const {
+DLList<T,U>::getPtr(Uint32 i) const {
return thePool.getPtr(i);
}
@@ -331,10 +344,10 @@ DLList<T>::getPtr(Uint32 i) const {
*
* Return i
*/
-template <class T>
+template <class T, class U>
inline
bool
-DLList<T>::first(Ptr<T> & p) const {
+DLList<T,U>::first(Ptr<T> & p) const {
Uint32 i = head.firstItem;
p.i = i;
if(i != RNIL){
@@ -345,11 +358,11 @@ DLList<T>::first(Ptr<T> & p) const {
return false;
}
-template <class T>
+template <class T, class U>
inline
bool
-DLList<T>::next(Ptr<T> & p) const {
- Uint32 i = p.p->nextList;
+DLList<T,U>::next(Ptr<T> & p) const {
+ Uint32 i = p.p->U::nextList;
p.i = i;
if(i != RNIL){
p.p = thePool.getPtr(i);
@@ -359,11 +372,11 @@ DLList<T>::next(Ptr<T> & p) const {
return false;
}
-template <class T>
+template <class T, class U>
inline
bool
-DLList<T>::hasNext(const Ptr<T> & p) const {
- return p.p->nextList != RNIL;
+DLList<T,U>::hasNext(const Ptr<T> & p) const {
+ return p.p->U::nextList != RNIL;
}
#endif
diff --git a/storage/ndb/src/kernel/vm/DataBuffer.hpp b/storage/ndb/src/kernel/vm/DataBuffer.hpp
index 7f553898eb5..ee870d3cd6a 100644
--- a/storage/ndb/src/kernel/vm/DataBuffer.hpp
+++ b/storage/ndb/src/kernel/vm/DataBuffer.hpp
@@ -102,7 +102,8 @@ public:
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;
diff --git a/storage/ndb/src/kernel/vm/GlobalData.hpp b/storage/ndb/src/kernel/vm/GlobalData.hpp
index 99b65727374..6d48d96711f 100644
--- a/storage/ndb/src/kernel/vm/GlobalData.hpp
+++ b/storage/ndb/src/kernel/vm/GlobalData.hpp
@@ -25,6 +25,7 @@
#include <BlockNumbers.h>
#include <NodeState.hpp>
#include <NodeInfo.hpp>
+#include "ArrayPool.hpp"
class SimulatedBlock;
@@ -34,8 +35,9 @@ enum restartStates {initial_state,
perform_stop};
struct GlobalData {
+ Uint32 m_restart_seq; //
NodeInfo m_nodeInfo[MAX_NODES];
- Signal VMSignals[1]; // Owned by FastScheduler::
+ Signal VMSignals[1]; // Owned by FastScheduler::
Uint64 internalMillisecCounter; // Owned by ThreadConfig::
Uint32 highestAvailablePrio; // Owned by FastScheduler::
@@ -77,6 +79,8 @@ struct GlobalData {
private:
Uint32 watchDog;
SimulatedBlock* blockTable[NO_OF_BLOCKS]; // Owned by Dispatcher::
+public:
+ ArrayPool<GlobalPage> m_global_page_pool;
};
extern GlobalData globalData;
diff --git a/storage/ndb/src/kernel/vm/KeyDescriptor.hpp b/storage/ndb/src/kernel/vm/KeyDescriptor.hpp
index 456d64ce1d8..b4d39a11190 100644
--- a/storage/ndb/src/kernel/vm/KeyDescriptor.hpp
+++ b/storage/ndb/src/kernel/vm/KeyDescriptor.hpp
@@ -23,12 +23,14 @@
struct KeyDescriptor
{
- KeyDescriptor () { noOfKeyAttr = hasCharAttr = noOfDistrKeys = 0; }
+ KeyDescriptor () {
+ noOfKeyAttr = hasCharAttr = noOfDistrKeys = noOfVarKeys = 0;
+ }
Uint8 noOfKeyAttr;
Uint8 hasCharAttr;
Uint8 noOfDistrKeys;
- Uint8 unused;
+ Uint8 noOfVarKeys;
struct KeyAttr
{
Uint32 attributeDescriptor;
diff --git a/storage/ndb/src/kernel/vm/KeyTable2Ref.hpp b/storage/ndb/src/kernel/vm/KeyTable2Ref.hpp
new file mode 100644
index 00000000000..8ede144a53e
--- /dev/null
+++ b/storage/ndb/src/kernel/vm/KeyTable2Ref.hpp
@@ -0,0 +1,51 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef 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;
+ return m_ref.find(*(Ptr<U>*)&ptr, rec);
+ }
+
+ bool seize(Ptr<T> & ptr) {
+ return m_ref.seize(*(Ptr<U>*)&ptr);
+ }
+
+ void add(Ptr<T> & ptr) {
+ m_ref.add(*(Ptr<U>*)&ptr);
+ }
+
+ void release(Ptr<T> & ptr) {
+ m_ref.release(*(Ptr<U>*)&ptr);
+ }
+};
+
+#endif
diff --git a/storage/ndb/src/kernel/vm/LongSignal.hpp b/storage/ndb/src/kernel/vm/LongSignal.hpp
index 9818358011f..4174a4cecf0 100644
--- a/storage/ndb/src/kernel/vm/LongSignal.hpp
+++ b/storage/ndb/src/kernel/vm/LongSignal.hpp
@@ -53,6 +53,7 @@ extern SectionSegmentPool g_sectionSegmentPool;
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);
diff --git a/storage/ndb/src/kernel/vm/Makefile.am b/storage/ndb/src/kernel/vm/Makefile.am
index 0be546237ea..3f3230b0694 100644
--- a/storage/ndb/src/kernel/vm/Makefile.am
+++ b/storage/ndb/src/kernel/vm/Makefile.am
@@ -17,8 +17,10 @@ libkernel_a_SOURCES = \
WatchDog.cpp \
SimplePropertiesSection.cpp \
SectionReader.cpp \
- MetaData.cpp \
- Mutex.cpp SafeCounter.cpp ndbd_malloc.cpp
+ Mutex.cpp SafeCounter.cpp \
+ Rope.cpp \
+ SuperPool.cpp \
+ ndbd_malloc.cpp
INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/mgmapi
diff --git a/storage/ndb/src/kernel/vm/MetaData.cpp b/storage/ndb/src/kernel/vm/MetaData.cpp
deleted file mode 100644
index 51afbf21503..00000000000
--- a/storage/ndb/src/kernel/vm/MetaData.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "MetaData.hpp"
-#include "SimulatedBlock.hpp"
-#include <blocks/dbdict/Dbdict.hpp>
-#include <blocks/dbdih/Dbdih.hpp>
-
-// MetaData::Common
-
-MetaData::Common::Common(Dbdict& dbdict, Dbdih& dbdih) :
- m_dbdict(dbdict),
- m_dbdih(dbdih)
-{
- m_lock[false] = m_lock[true] = 0;
-}
-
-// MetaData::Table
-
-// MetaData
-
-MetaData::MetaData(Common& common) :
- m_common(common)
-{
- m_lock[false] = m_lock[true] = 0;
-}
-
-MetaData::MetaData(SimulatedBlock* block) :
- m_common(*block->getMetaDataCommon())
-{
- m_lock[false] = m_lock[true] = 0;
-}
-
-MetaData::~MetaData()
-{
- for (int i = false; i <= true; i++) {
- assert(m_common.m_lock[i] >= m_lock[i]);
- m_common.m_lock[i] -= m_lock[i];
- m_lock[i] = 0;
- }
-}
-
-int
-MetaData::lock(bool exclusive)
-{
- if (m_common.m_lock[true] > m_lock[true]) {
- // locked exclusively by another instance
- return MetaData::Locked;
- }
- m_lock[exclusive]++;
- m_common.m_lock[exclusive]++;
- return 0;
-}
-
-int
-MetaData::unlock(bool exclusive)
-{
- if (m_lock[exclusive] == 0) {
- return MetaData::NotLocked;
- }
- m_lock[exclusive]--;
- m_common.m_lock[exclusive]--;
- return 0;
-}
-
-int
-MetaData::getTable(MetaData::Table& table, Uint32 tableId, Uint32 tableVersion)
-{
- if (m_lock[false] + m_lock[true] == 0) {
- return MetaData::NotLocked;
- }
- return m_common.m_dbdict.getMetaTable(table, tableId, tableVersion);
-}
-
-int
-MetaData::getTable(MetaData::Table& table, const char* tableName)
-{
- if (m_lock[false] + m_lock[true] == 0) {
- return MetaData::NotLocked;
- }
- return m_common.m_dbdict.getMetaTable(table, tableName);
-}
-
-int
-MetaData::getAttribute(MetaData::Attribute& attribute, const MetaData::Table& table, Uint32 attributeId)
-{
- if (m_lock[false] + m_lock[true] == 0) {
- return MetaData::NotLocked;
- }
- return m_common.m_dbdict.getMetaAttribute(attribute, table, attributeId);
-}
-
-int
-MetaData::getAttribute(MetaData::Attribute& attribute, const MetaData::Table& table, const char* attributeName)
-{
- if (m_lock[false] + m_lock[true] == 0) {
- return MetaData::NotLocked;
- }
- return m_common.m_dbdict.getMetaAttribute(attribute, table, attributeName);
-}
diff --git a/storage/ndb/src/kernel/vm/MetaData.hpp b/storage/ndb/src/kernel/vm/MetaData.hpp
deleted file mode 100644
index 1000114a421..00000000000
--- a/storage/ndb/src/kernel/vm/MetaData.hpp
+++ /dev/null
@@ -1,243 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef KERNEL_VM_METADATA_HPP
-#define KERNEL_VM_METADATA_HPP
-
-#include <ndb_types.h>
-#include <ndb_limits.h>
-#include <ErrorReporter.hpp>
-#include <signaldata/DictTabInfo.hpp>
-
-class SimulatedBlock;
-class Dbdict;
-class Dbdih;
-
-/*
- * Common metadata for all blocks on the node.
- *
- * A database node has unique DICT and DIH instances. Parts of their
- * metadata are described by subclasses of MetaData. Any block can
- * access the metadata via a MetaData instance.
- */
-class MetaData {
-public:
- /*
- * Methods return < 0 on error.
- */
- enum Error {
- Locked = -1,
- NotLocked = -2,
- InvalidArgument = -3,
- TableNotFound = -4,
- InvalidTableVersion = -5,
- AttributeNotFound = -6
- };
-
- /*
- * Common data shared by all metadata instances. Contains DICT and
- * DIH pointers and counts of shared and exclusive locks.
- */
- class Common {
- public:
- Common(Dbdict& dbdict, Dbdih& dbdih);
- private:
- friend class MetaData;
- Dbdict& m_dbdict;
- Dbdih& m_dbdih;
- unsigned m_lock[2]; // shared: 0 (false), exclusive: 1 (true)
- };
-
- /*
- * Table metadata. A base class of Dbdict::TableRecord. This is
- * actually fragment metadata but until "alter table" there is no
- * difference.
- */
- class Table {
- public:
- /* Table id (array index in DICT and other blocks) */
- Uint32 tableId;
-
- /* Table version (incremented when tableId is re-used) */
- Uint32 tableVersion;
-
- /* Table name (may not be unique under "alter table") */
- char tableName[MAX_TAB_NAME_SIZE];
-
- /* 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;
-
- /* 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;
-
- /* Number of distinct character sets (computed) */
- Uint16 noOfCharsets;
-
- /* Length of primary key in words (should be computed) */
- /* For ordered index this is tree node size in words */
- Uint16 tupKeyLength;
-
- /* 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;
-
- /*
- * Used when shrinking to decide when to merge buckets. Hysteresis
- * is thus possible. Should be smaller but not much smaller than
- * maxLoadFactor
- */
- Uint8 minLoadFactor;
-
- /* Is the table logged (i.e. data survives system restart) */
- bool storedTable;
-
- /* Convenience routines */
- bool isTable() const;
- bool isIndex() const;
- bool isUniqueIndex() const;
- bool isNonUniqueIndex() const;
- bool isHashIndex() const;
- bool isOrderedIndex() const;
- };
-
- /*
- * Attribute metadata. A base class of Dbdict::AttributeRecord.
- */
- class Attribute {
- public:
- /* Attribute id within table (counted from 0) */
- Uint16 attributeId;
-
- /* Attribute number within tuple key (counted from 1) */
- Uint16 tupleKey;
-
- /* Attribute name (unique within table) */
- char attributeName[MAX_ATTR_NAME_SIZE];
-
- /* Attribute description (old-style packed descriptor) */
- Uint32 attributeDescriptor;
-
- /* Extended attributes */
- Uint32 extPrecision;
- Uint32 extScale;
- Uint32 extLength;
-
- /* Autoincrement flag, only for ODBC/SQL */
- bool autoIncrement;
-
- /* Default value as null-terminated string, only for ODBC/SQL */
- char defaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
- };
-
- /*
- * Metadata is accessed via a MetaData instance. The constructor
- * needs a reference to MetaData::Common which can be obtained via
- * the block. The destructor releases any leftover locks.
- */
- MetaData(Common& common);
- MetaData(SimulatedBlock* block);
- ~MetaData();
-
- /*
- * Access methods. Locking can be shared (read) or exclusive (write).
- * Locking can be recursive (a count is kept). Example (in a block):
- *
- * MetaData md(this);
- * MetaData::Table table;
- * ret = md.lock(false);
- * ret = md.getTable(table, "SYSTAB_0");
- * ret = md.unlock();
- */
- int lock(bool exclusive);
- int unlock(bool exclusive);
- int getTable(MetaData::Table& table, Uint32 tableId, Uint32 tableVersion);
- int getTable(MetaData::Table& table, const char* tableName);
- int getAttribute(MetaData::Attribute& attribute, const MetaData::Table& table, Uint32 attributeId);
- int getAttribute(MetaData::Attribute& attribute, const MetaData::Table& table, const char* attributeName);
-
-private:
- Common& m_common;
- unsigned m_lock[2];
-};
-
-// MetaData::Table
-
-inline bool
-MetaData::Table::isTable() const
-{
- return DictTabInfo::isTable(tableType);
-}
-
-inline bool
-MetaData::Table::isIndex() const
-{
- return DictTabInfo::isIndex(tableType);
-}
-
-inline bool
-MetaData::Table::isUniqueIndex() const
-{
- return DictTabInfo::isUniqueIndex(tableType);
-}
-
-inline bool
-MetaData::Table::isNonUniqueIndex() const
-{
- return DictTabInfo::isNonUniqueIndex(tableType);
-}
-
-inline bool
-MetaData::Table::isHashIndex() const
-{
- return DictTabInfo::isHashIndex(tableType);
-}
-
-inline bool
-MetaData::Table::isOrderedIndex() const
-{
- return DictTabInfo::isOrderedIndex(tableType);
-}
-
-#endif
diff --git a/storage/ndb/src/kernel/vm/Rope.cpp b/storage/ndb/src/kernel/vm/Rope.cpp
new file mode 100644
index 00000000000..0c90d8f65d5
--- /dev/null
+++ b/storage/ndb/src/kernel/vm/Rope.cpp
@@ -0,0 +1,173 @@
+#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, 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, 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, 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, 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, len, res);
+ return res;
+ }
+ }
+ if(DEBUG_ROPE)
+ ndbout_c("Rope::compare(%s, %d) -> %d", str, 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, 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
new file mode 100644
index 00000000000..8e0f1323e69
--- /dev/null
+++ b/storage/ndb/src/kernel/vm/Rope.hpp
@@ -0,0 +1,117 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef NDB_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/SLList.hpp b/storage/ndb/src/kernel/vm/SLList.hpp
index 5fde41aa3e0..9758f9a66c4 100644
--- a/storage/ndb/src/kernel/vm/SLList.hpp
+++ b/storage/ndb/src/kernel/vm/SLList.hpp
@@ -24,15 +24,23 @@
* Template class used for implementing an
* list of object retreived from a pool
*/
-template <class T>
+template <class T, class U = T>
class SLList {
public:
/**
* List head
*/
- struct Head {
- 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;
+ }
};
SLList(ArrayPool<T> & thePool);
@@ -64,6 +72,11 @@ public:
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;
@@ -99,13 +112,21 @@ public:
*/
bool hasNext(const Ptr<T> &) const;
+ /**
+ * Add
+ */
+ void add(Ptr<T> & p){
+ p.p->U::nextList = head.firstItem;
+ head.firstItem = p.i;
+ }
+
Uint32 noOfElements() const {
Uint32 c = 0;
Uint32 i = head.firstItem;
while(i != RNIL){
c++;
const T * t = thePool.getPtr(i);
- i = t->nextList;
+ i = t->U::nextList;
}
return c;
}
@@ -131,11 +152,11 @@ protected:
ArrayPool<T> & thePool;
};
-template<class T>
-class LocalSLList : public SLList<T> {
+template <class T, class U = T>
+class LocalSLList : public SLList<T,U> {
public:
- LocalSLList(ArrayPool<T> & thePool, typename SLList<T>::Head & _src)
- : SLList<T>(thePool), src(_src)
+ LocalSLList(ArrayPool<T> & thePool, typename SLList<T,U>::HeadPOD & _src)
+ : SLList<T,U>(thePool), src(_src)
{
this->head = src;
}
@@ -144,55 +165,55 @@ public:
src = this->head;
}
private:
- typename SLList<T>::Head & src;
+ typename SLList<T,U>::HeadPOD & src;
};
-template <class T>
+template <class T, class U>
inline
-SLList<T>::SLList(ArrayPool<T> & _pool):
+SLList<T,U>::SLList(ArrayPool<T> & _pool):
thePool(_pool){
}
-template<class T>
+template <class T, class U>
inline
-SLList<T>::Head::Head(){
- firstItem = RNIL;
+SLList<T,U>::Head::Head(){
+ this->init();
}
-template <class T>
+template <class T, class U>
inline
bool
-SLList<T>::seize(Ptr<T> & p){
+SLList<T,U>::seize(Ptr<T> & p){
thePool.seize(p);
T * t = p.p;
Uint32 ff = head.firstItem;
if(p.i != RNIL){
- t->nextList = ff;
+ t->U::nextList = ff;
head.firstItem = p.i;
return true;
}
return false;
}
-template <class T>
+template <class T, class U>
inline
bool
-SLList<T>::seizeId(Ptr<T> & p, Uint32 ir){
+SLList<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->nextList = ff;
+ t->U::nextList = ff;
head.firstItem = p.i;
return true;
}
return false;
}
-template <class T>
+template <class T, class U>
inline
bool
-SLList<T>::seizeN(Ptr<T> & p, Uint32 n){
+SLList<T,U>::seizeN(Ptr<T> & p, Uint32 n){
for(Uint32 i = 0; i < n; i++){
if(seize(p) == RNIL){
/**
@@ -201,7 +222,7 @@ SLList<T>::seizeN(Ptr<T> & p, Uint32 n){
for(; i > 0; i--){
const Uint32 tmp = head.firstItem;
const T * t = thePool.getPtr(tmp);
- head.firstItem = t->nextList;
+ head.firstItem = t->U::nextList;
thePool.release(tmp);
}
return false;
@@ -218,37 +239,44 @@ SLList<T>::seizeN(Ptr<T> & p, Uint32 n){
}
-template <class T>
+template <class T, class U>
+inline
+void
+SLList<T,U>::remove(){
+ head.firstItem = RNIL;
+}
+
+template <class T, class U>
inline
void
-SLList<T>::release(){
+SLList<T,U>::release(){
while(head.firstItem != RNIL){
const T * t = thePool.getPtr(head.firstItem);
const Uint32 i = head.firstItem;
- head.firstItem = t->nextList;
+ head.firstItem = t->U::nextList;
thePool.release(i);
}
}
-template <class T>
+template <class T, class U>
inline
void
-SLList<T>::getPtr(Ptr<T> & p, Uint32 i) const {
+SLList<T,U>::getPtr(Ptr<T> & p, Uint32 i) const {
p.i = i;
p.p = thePool.getPtr(i);
}
-template <class T>
+template <class T, class U>
inline
void
-SLList<T>::getPtr(Ptr<T> & p) const {
+SLList<T,U>::getPtr(Ptr<T> & p) const {
thePool.getPtr(p);
}
-template <class T>
+template <class T, class U>
inline
T *
-SLList<T>::getPtr(Uint32 i) const {
+SLList<T,U>::getPtr(Uint32 i) const {
return thePool.getPtr(i);
}
@@ -257,10 +285,10 @@ SLList<T>::getPtr(Uint32 i) const {
*
* Return i
*/
-template <class T>
+template <class T, class U>
inline
bool
-SLList<T>::first(Ptr<T> & p) const {
+SLList<T,U>::first(Ptr<T> & p) const {
Uint32 i = head.firstItem;
p.i = i;
if(i != RNIL){
@@ -271,11 +299,11 @@ SLList<T>::first(Ptr<T> & p) const {
return false;
}
-template <class T>
+template <class T, class U>
inline
bool
-SLList<T>::next(Ptr<T> & p) const {
- Uint32 i = p.p->nextList;
+SLList<T,U>::next(Ptr<T> & p) const {
+ Uint32 i = p.p->U::nextList;
p.i = i;
if(i != RNIL){
p.p = thePool.getPtr(i);
@@ -285,11 +313,11 @@ SLList<T>::next(Ptr<T> & p) const {
return false;
}
-template <class T>
+template <class T, class U>
inline
bool
-SLList<T>::hasNext(const Ptr<T> & p) const {
- return p.p->nextList != RNIL;
+SLList<T,U>::hasNext(const Ptr<T> & p) const {
+ return p.p->U::nextList != RNIL;
}
#endif
diff --git a/storage/ndb/src/kernel/vm/SafeCounter.cpp b/storage/ndb/src/kernel/vm/SafeCounter.cpp
index 542e43f9172..a176c714549 100644
--- a/storage/ndb/src/kernel/vm/SafeCounter.cpp
+++ b/storage/ndb/src/kernel/vm/SafeCounter.cpp
@@ -26,7 +26,7 @@ SafeCounterManager::SafeCounterManager(class SimulatedBlock & block)
bool
SafeCounterManager::setSize(Uint32 maxNoOfActiveMutexes, bool exit_on_error) {
- return m_counterPool.setSize(maxNoOfActiveMutexes, exit_on_error);
+ return m_counterPool.setSize(maxNoOfActiveMutexes, false, exit_on_error);
}
Uint32
diff --git a/storage/ndb/src/kernel/vm/SimBlockList.hpp b/storage/ndb/src/kernel/vm/SimBlockList.hpp
index 40485a37425..cfe09701cc4 100644
--- a/storage/ndb/src/kernel/vm/SimBlockList.hpp
+++ b/storage/ndb/src/kernel/vm/SimBlockList.hpp
@@ -17,7 +17,6 @@
#ifndef SimBlockList_H
#define SimBlockList_H
-#include <MetaData.hpp>
#include <SimulatedBlock.hpp>
class Configuration;
@@ -33,14 +32,12 @@ public:
private:
int noOfBlocks;
SimulatedBlock** theList;
- MetaData::Common* ptrMetaDataCommon;
};
inline
SimBlockList::SimBlockList(){
noOfBlocks = 0;
theList = 0;
- ptrMetaDataCommon = 0;
}
inline
diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp
index a7ab5630d25..de310a533db 100644
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -36,6 +36,8 @@
#include <Properties.hpp>
#include "Configuration.hpp"
+#include <AttributeDescriptor.hpp>
+#include <NdbSqlUtil.hpp>
#define ljamEntry() jamEntryLine(30000 + __LINE__)
#define ljam() jamLine(30000 + __LINE__)
@@ -49,12 +51,12 @@ SimulatedBlock::SimulatedBlock(BlockNumber blockNumber,
theNumber(blockNumber),
theReference(numberToRef(blockNumber, globalData.ownId)),
theConfiguration(conf),
+ m_global_page_pool(globalData.m_global_page_pool),
c_fragmentInfoHash(c_fragmentInfoPool),
c_linearFragmentSendList(c_fragmentSendPool),
c_segmentedFragmentSendList(c_fragmentSendPool),
c_mutexMgr(* this),
- c_counterMgr(* this),
- c_ptrMetaDataCommon(0)
+ c_counterMgr(* this)
{
NewVarRef = 0;
@@ -1881,21 +1883,49 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
{
const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
+ Uint32 array =
+ AttributeDescriptor::getArrayType(keyAttr.attributeDescriptor);
Uint32 srcBytes =
AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
- Uint32 srcWords = (srcBytes + 3) / 4;
+
+ Uint32 srcWords = ~0;
Uint32 dstWords = ~0;
uchar* dstPtr = (uchar*)&dst[dstPos];
const uchar* srcPtr = (const uchar*)&src[srcPos];
CHARSET_INFO* cs = keyAttr.charsetInfo;
- if (cs == NULL)
+ if (cs == NULL)
{
jam();
- memcpy(dstPtr, srcPtr, srcWords << 2);
+ Uint32 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
+ else
{
jam();
Uint32 typeId =
@@ -1920,12 +1950,22 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
dstPtr[n++] = 0;
}
dstWords = (n >> 2);
+ srcWords = (lb + len + 3) >> 2;
}
+
dstPos += dstWords;
srcPos += srcWords;
keyPartLen[i++] = dstWords;
}
+ if (0)
+ {
+ for(Uint32 i = 0; i<dstPos; i++)
+ {
+ printf("%.8x ", dst[i]);
+ }
+ printf("\n");
+ }
return dstPos;
}
@@ -1966,6 +2006,7 @@ SimulatedBlock::create_distr_key(Uint32 tableId,
{
Uint32 attr = desc->keyAttr[i].attributeDescriptor;
Uint32 len = AttributeDescriptor::getSizeInWords(attr);
+ ndbrequire(AttributeDescriptor::getArrayType(attr) == NDB_ARRAYTYPE_FIXED);
if(AttributeDescriptor::getDKey(attr))
{
noOfDistrKeys--;
diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp
index 810267d6c09..bd4af5fa1ee 100644
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -42,7 +42,6 @@
#include "DLHashTable.hpp"
#include "Callback.hpp"
#include "SafeCounter.hpp"
-#include "MetaData.hpp"
#include <mgmapi.h>
#include <mgmapi_config_parameters.h>
@@ -76,9 +75,15 @@ typedef struct NewVar
} NewVARIABLE; /* 128 bits */
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;
public:
friend class BlockComponent;
virtual ~SimulatedBlock();
@@ -110,6 +115,8 @@ public:
CallbackFunction m_callbackFunction;
Uint32 m_callbackData;
};
+
+ virtual const char* get_filename(Uint32 fd) const { return "";}
protected:
static Callback TheEmptyCallback;
void execute(Signal* signal, Callback & c, Uint32 returnCode);
@@ -409,6 +416,10 @@ private:
NewVARIABLE* NewVarRef; /* New Base Address Table for block */
Uint16 theBATSize; /* # entries in BAT */
+protected:
+ ArrayPool<GlobalPage>& m_global_page_pool;
+
+private:
/**
* Node state
*/
@@ -519,13 +530,6 @@ protected:
// Variable for storing inserted errors, see pc.H
ERROR_INSERT_VARIABLE;
-private:
- // Metadata common part shared by block instances
- MetaData::Common* c_ptrMetaDataCommon;
-public:
- void setMetaDataCommon(MetaData::Common* ptr) { c_ptrMetaDataCommon = ptr; }
- MetaData::Common* getMetaDataCommon() { return c_ptrMetaDataCommon; }
-
#ifdef VM_TRACE_TIME
public:
void clearTimes();
diff --git a/storage/ndb/src/kernel/vm/pc.hpp b/storage/ndb/src/kernel/vm/pc.hpp
index 6aeda59224f..b80224b1735 100644
--- a/storage/ndb/src/kernel/vm/pc.hpp
+++ b/storage/ndb/src/kernel/vm/pc.hpp
@@ -161,6 +161,12 @@
#define NO_OF_FRAGS_PER_CHUNK 4
#define LOG_NO_OF_FRAGS_PER_CHUNK 2
+/**
+* Page Header Size for pages
+*/
+#define ZPAGE_HEADER_SIZE 32
+#define ZPAGE_FRAG_PAGE_ID_POS 4 /* POSITION OF FRAG PAGE ID WHEN USED*/
+
/* ---------------------------------------------------------------- */
// To avoid synching too big chunks at a time we synch after writing
// a certain number of data/UNDO pages. (e.g. 2 MBytes).
@@ -199,7 +205,7 @@
*/
#if defined VM_TRACE
#define ndbassert(check) \
- if((check)){ \
+ if(likely(check)){ \
} else { \
progError(__LINE__, NDBD_EXIT_NDBASSERT, __FILE__); \
}
@@ -208,7 +214,7 @@
#endif
#define ndbrequireErr(check, error) \
- if((check)){ \
+ if(likely(check)){ \
} else { \
progError(__LINE__, error, __FILE__); \
}
diff --git a/storage/ndb/src/ndbapi/DictCache.cpp b/storage/ndb/src/ndbapi/DictCache.cpp
index 57d9b361522..d7a6e4c8586 100644
--- a/storage/ndb/src/ndbapi/DictCache.cpp
+++ b/storage/ndb/src/ndbapi/DictCache.cpp
@@ -67,8 +67,7 @@ LocalDictCache::get(const char * name){
void
LocalDictCache::put(const char * name, Ndb_local_table_info * tab_info){
- const Uint32 id = tab_info->m_table_impl->m_tableId;
-
+ const Uint32 id = tab_info->m_table_impl->m_id;
m_tableHash.insertKey(name, strlen(name), id, tab_info);
}
@@ -292,9 +291,9 @@ GlobalDictCache::drop(NdbTableImpl * tab)
for(i = 0; i<sz; i++){
TableVersion & ver = (* vers)[i];
- DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
- i, ver.m_version, ver.m_refCount,
- ver.m_status, ver.m_impl));
+ ndbout_c("%d: version: %d refCount: %d status: %d impl: %p",
+ i, ver.m_version, ver.m_refCount,
+ ver.m_status, ver.m_impl);
}
abort();
@@ -340,9 +339,9 @@ GlobalDictCache::release(NdbTableImpl * tab)
for(i = 0; i<sz; i++){
TableVersion & ver = (* vers)[i];
- DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
- i, ver.m_version, ver.m_refCount,
- ver.m_status, ver.m_impl));
+ ndbout_c("%d: version: %d refCount: %d status: %d impl: %p",
+ i, ver.m_version, ver.m_refCount,
+ ver.m_status, ver.m_impl);
}
abort();
@@ -373,7 +372,7 @@ GlobalDictCache::alter_table_rep(const char * name,
{
TableVersion & ver = (* vers)[i];
if(ver.m_version == tableVersion && ver.m_impl &&
- ver.m_impl->m_tableId == tableId)
+ ver.m_impl->m_id == tableId)
{
ver.m_status = DROPPED;
ver.m_impl->m_status = altered ?
diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp
index 02b66af9a6e..50f2123a811 100644
--- a/storage/ndb/src/ndbapi/Ndb.cpp
+++ b/storage/ndb/src/ndbapi/Ndb.cpp
@@ -758,7 +758,7 @@ Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize)
if (info == 0)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl *table= info->m_table_impl;
- Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize);
+ Uint64 tupleId = getTupleIdFromNdb(table->m_id, cacheSize);
DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
@@ -770,7 +770,7 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize
if (aTable == 0)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize);
+ Uint64 tupleId = getTupleIdFromNdb(table->m_id, cacheSize);
DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
@@ -781,7 +781,7 @@ Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize)
const NdbTableImpl* table = theDictionary->getTable(aTableName);
if (table == 0)
return ~(Uint64)0;
- return getTupleIdFromNdb(table->m_tableId, cacheSize);
+ return getTupleIdFromNdb(table->m_id, cacheSize);
}
Uint64
@@ -812,7 +812,7 @@ Ndb::readAutoIncrementValue(const char* aTableName)
theError= theDictionary->getNdbError();
DBUG_RETURN(~(Uint64)0);
}
- Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
+ Uint64 tupleId = readTupleIdFromNdb(table->m_id);
DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
@@ -824,7 +824,7 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable)
if (aTable == 0)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
+ Uint64 tupleId = readTupleIdFromNdb(table->m_id);
DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
DBUG_RETURN(tupleId);
}
@@ -852,7 +852,7 @@ Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase)
DBUG_RETURN(false);
}
const NdbTableImpl* table= info->m_table_impl;
- DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase));
+ DBUG_RETURN(setTupleIdInNdb(table->m_id, val, increase));
}
bool
@@ -862,7 +862,7 @@ Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool
if (aTable == 0)
DBUG_RETURN(~(Uint64)0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase));
+ DBUG_RETURN(setTupleIdInNdb(table->m_id, val, increase));
}
bool
@@ -874,7 +874,7 @@ Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val, bool increase )
theError= theDictionary->getNdbError();
DBUG_RETURN(false);
}
- DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase));
+ DBUG_RETURN(setTupleIdInNdb(table->m_id, val, increase));
}
bool
@@ -1171,7 +1171,7 @@ Ndb::internalize_index_name(const NdbTableImpl * table,
BaseString ret;
DBUG_ENTER("internalize_index_name");
DBUG_PRINT("enter", ("external_name: %s, table_id: %d",
- external_name, table ? table->m_tableId : ~0));
+ external_name, table ? table->m_id : ~0));
if (!table)
{
DBUG_PRINT("error", ("!table"));
@@ -1183,7 +1183,7 @@ Ndb::internalize_index_name(const NdbTableImpl * table,
/* Internal index name format <db>/<schema>/<tabid>/<table> */
ret.assfmt("%s%d%c%s",
theImpl->m_prefix.c_str(),
- table->m_tableId,
+ table->m_id,
table_name_separator,
external_name);
}
diff --git a/storage/ndb/src/ndbapi/NdbBlob.cpp b/storage/ndb/src/ndbapi/NdbBlob.cpp
index 28d657f3fe9..edfdd9ec836 100644
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp
@@ -61,7 +61,7 @@ NdbBlob::getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnIm
{
assert(t != 0 && c != 0 && c->getBlobType());
memset(btname, 0, NdbBlobImpl::BlobTableNameSize);
- sprintf(btname, "NDB$BLOB_%d_%d", (int)t->m_tableId, (int)c->m_attrId);
+ sprintf(btname, "NDB$BLOB_%d_%d", (int)t->m_id, (int)c->m_column_no);
}
void
@@ -77,7 +77,7 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
but may change the fragment type if it is UserDefined since it
must be hash based so that the kernel can handle it on its own.
*/
- bt.m_primaryTableId = t->m_tableId;
+ bt.m_primaryTableId = t->m_id;
bt.m_ng.clear();
switch (t->getFragmentType())
{
@@ -134,6 +134,7 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
break;
}
bc.setLength(c->getPartSize());
+ bc.setStorageType(c->getStorageType());
bt.addColumn(bc);
}
DBUG_VOID_RETURN;
@@ -360,7 +361,7 @@ NdbBlob::setTableKeyValue(NdbOperation* anOp)
assert(c != NULL);
if (c->m_pk) {
unsigned len = c->m_attrSize * c->m_arraySize;
- if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
+ if (anOp->equal_impl(c, (const char*)&data[pos]) == -1) {
setErrorCode(anOp);
DBUG_RETURN(-1);
}
@@ -384,7 +385,7 @@ NdbBlob::setAccessKeyValue(NdbOperation* anOp)
assert(c != NULL);
if (c->m_pk) {
unsigned len = c->m_attrSize * c->m_arraySize;
- if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
+ if (anOp->equal_impl(c, (const char*)&data[pos]) == -1) {
setErrorCode(anOp);
DBUG_RETURN(-1);
}
@@ -445,7 +446,7 @@ NdbBlob::setHeadInlineValue(NdbOperation* anOp)
memset(theInlineData + theLength, 0, theInlineSize - theLength);
assert(theNullFlag != -1);
const char* aValue = theNullFlag ? 0 : theHeadInlineBuf.data;
- if (anOp->setValue(theColumn, aValue, theHeadInlineBuf.size) == -1) {
+ if (anOp->setValue(theColumn, aValue) == -1) {
setErrorCode(anOp);
DBUG_RETURN(-1);
}
diff --git a/storage/ndb/src/ndbapi/NdbDictionary.cpp b/storage/ndb/src/ndbapi/NdbDictionary.cpp
index 520a5711100..b56bd778855 100644
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp
@@ -178,12 +178,12 @@ NdbDictionary::Column::getPrimaryKey() const {
void
NdbDictionary::Column::setPartitionKey(bool val){
- m_impl.m_distributionKey = val;
+ m_impl.m_distributionKey = (val ? 2 : 0);
}
bool
NdbDictionary::Column::getPartitionKey() const{
- return m_impl.m_distributionKey;
+ return (bool)m_impl.m_distributionKey;
}
const NdbDictionary::Table *
@@ -223,7 +223,12 @@ NdbDictionary::Column::getDefaultValue() const
int
NdbDictionary::Column::getColumnNo() const {
- return m_impl.m_attrId;
+ return m_impl.m_column_no;
+}
+
+int
+NdbDictionary::Column::getAttrId() const {
+ return m_impl.m_attrId;;
}
bool
@@ -237,6 +242,30 @@ NdbDictionary::Column::getSizeInBytes() const
return m_impl.m_attrSize * m_impl.m_arraySize;
}
+void
+NdbDictionary::Column::setArrayType(ArrayType type)
+{
+ m_impl.m_arrayType = type;
+}
+
+NdbDictionary::Column::ArrayType
+NdbDictionary::Column::getArrayType() const
+{
+ return (ArrayType)m_impl.m_arrayType;
+}
+
+void
+NdbDictionary::Column::setStorageType(StorageType type)
+{
+ m_impl.m_storageType = type;
+}
+
+NdbDictionary::Column::StorageType
+NdbDictionary::Column::getStorageType() const
+{
+ return (StorageType)m_impl.m_storageType;
+}
+
/*****************************************************************
* Table facade
*/
@@ -247,8 +276,7 @@ NdbDictionary::Table::Table(const char * name)
}
NdbDictionary::Table::Table(const NdbDictionary::Table & org)
- : NdbDictionary::Object(),
- m_impl(* new NdbTableImpl(* this))
+ : Object(org), m_impl(* new NdbTableImpl(* this))
{
m_impl.assign(org.m_impl);
}
@@ -291,7 +319,7 @@ NdbDictionary::Table::getMysqlName() const {
int
NdbDictionary::Table::getTableId() const {
- return m_impl.m_tableId;
+ return m_impl.m_id;
}
void
@@ -299,12 +327,7 @@ NdbDictionary::Table::addColumn(const Column & c){
NdbColumnImpl* col = new NdbColumnImpl;
(* col) = NdbColumnImpl::getImpl(c);
m_impl.m_columns.push_back(col);
- if(c.getPrimaryKey()){
- m_impl.m_noOfKeys++;
- }
- if (col->getBlobType()) {
- m_impl.m_noOfBlobs++;
- }
+ m_impl.computeAggregates();
m_impl.buildColumnHash();
}
@@ -404,17 +427,17 @@ NdbDictionary::Table::getPrimaryKey(int no) const {
const void*
NdbDictionary::Table::getFrmData() const {
- return m_impl.m_frm.get_data();
+ return m_impl.getFrmData();
}
Uint32
NdbDictionary::Table::getFrmLength() const {
- return m_impl.m_frm.length();
+ return m_impl.getFrmLength();
}
void
NdbDictionary::Table::setFrm(const void* data, Uint32 len){
- m_impl.m_frm.assign(data, len);
+ m_impl.setFrm(data, len);
}
const void*
@@ -474,6 +497,20 @@ NdbDictionary::Table::createTableInDb(Ndb* pNdb, bool equalOk) const {
return pNdb->getDictionary()->createTable(* this);
}
+void
+NdbDictionary::Table::setTablespace(const char * name){
+ m_impl.m_tablespace_id = ~0;
+ m_impl.m_tablespace_version = ~0;
+ m_impl.m_tablespace_name.assign(name);
+}
+
+void
+NdbDictionary::Table::setTablespace(const NdbDictionary::Tablespace & ts){
+ m_impl.m_tablespace_id = NdbTablespaceImpl::getImpl(ts).m_id;
+ m_impl.m_tablespace_version = ts.getObjectVersion();
+ m_impl.m_tablespace_name.assign(ts.getName());
+}
+
/*****************************************************************
* Index facade
*/
@@ -579,12 +616,12 @@ NdbDictionary::Index::addIndexColumns(int noOfNames, const char ** names){
void
NdbDictionary::Index::setType(NdbDictionary::Index::Type t){
- m_impl.m_type = t;
+ m_impl.m_type = (NdbDictionary::Object::Type)t;
}
NdbDictionary::Index::Type
NdbDictionary::Index::getType() const {
- return m_impl.m_type;
+ return (NdbDictionary::Index::Type)m_impl.m_type;
}
void
@@ -734,6 +771,295 @@ void NdbDictionary::Event::print()
}
/*****************************************************************
+ * Tablespace facade
+ */
+NdbDictionary::Tablespace::Tablespace()
+ : m_impl(* new NdbTablespaceImpl(* this))
+{
+}
+
+NdbDictionary::Tablespace::Tablespace(NdbTablespaceImpl & impl)
+ : m_impl(impl)
+{
+}
+
+NdbDictionary::Tablespace::~Tablespace(){
+ NdbTablespaceImpl * tmp = &m_impl;
+ if(this != tmp){
+ delete tmp;
+ }
+}
+
+void
+NdbDictionary::Tablespace::setName(const char * name){
+ m_impl.m_name.assign(name);
+}
+
+const char *
+NdbDictionary::Tablespace::getName() const {
+ return m_impl.m_name.c_str();
+}
+
+void
+NdbDictionary::Tablespace::setAutoGrowSpecification
+(const NdbDictionary::AutoGrowSpecification& spec){
+ m_impl.m_grow_spec = spec;
+}
+const NdbDictionary::AutoGrowSpecification&
+NdbDictionary::Tablespace::getAutoGrowSpecification() const {
+ return m_impl.m_grow_spec;
+}
+
+void
+NdbDictionary::Tablespace::setExtentSize(Uint32 sz){
+ m_impl.m_extent_size = sz;
+}
+
+Uint32
+NdbDictionary::Tablespace::getExtentSize() const {
+ return m_impl.m_extent_size;
+}
+
+void
+NdbDictionary::Tablespace::setDefaultLogfileGroup(const char * name){
+ m_impl.m_logfile_group_id = ~0;
+ m_impl.m_logfile_group_version = ~0;
+ m_impl.m_logfile_group_name.assign(name);
+}
+
+void
+NdbDictionary::Tablespace::setDefaultLogfileGroup
+(const NdbDictionary::LogfileGroup & lg){
+ m_impl.m_logfile_group_id = NdbLogfileGroupImpl::getImpl(lg).m_id;
+ m_impl.m_logfile_group_version = lg.getObjectVersion();
+ m_impl.m_logfile_group_name.assign(lg.getName());
+}
+
+const char *
+NdbDictionary::Tablespace::getDefaultLogfileGroup() const {
+ return m_impl.m_logfile_group_name.c_str();
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::Tablespace::getObjectStatus() const {
+ return m_impl.m_status;
+}
+
+int
+NdbDictionary::Tablespace::getObjectVersion() const {
+ return m_impl.m_version;
+}
+
+/*****************************************************************
+ * LogfileGroup facade
+ */
+NdbDictionary::LogfileGroup::LogfileGroup()
+ : m_impl(* new NdbLogfileGroupImpl(* this))
+{
+}
+
+NdbDictionary::LogfileGroup::LogfileGroup(NdbLogfileGroupImpl & impl)
+ : m_impl(impl)
+{
+}
+
+NdbDictionary::LogfileGroup::~LogfileGroup(){
+ NdbLogfileGroupImpl * tmp = &m_impl;
+ if(this != tmp){
+ delete tmp;
+ }
+}
+
+void
+NdbDictionary::LogfileGroup::setName(const char * name){
+ m_impl.m_name.assign(name);
+}
+
+const char *
+NdbDictionary::LogfileGroup::getName() const {
+ return m_impl.m_name.c_str();
+}
+
+void
+NdbDictionary::LogfileGroup::setUndoBufferSize(Uint32 sz){
+ m_impl.m_undo_buffer_size = sz;
+}
+
+Uint32
+NdbDictionary::LogfileGroup::getUndoBufferSize() const {
+ return m_impl.m_undo_buffer_size;
+}
+
+void
+NdbDictionary::LogfileGroup::setAutoGrowSpecification
+(const NdbDictionary::AutoGrowSpecification& spec){
+ m_impl.m_grow_spec = spec;
+}
+const NdbDictionary::AutoGrowSpecification&
+NdbDictionary::LogfileGroup::getAutoGrowSpecification() const {
+ return m_impl.m_grow_spec;
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::LogfileGroup::getObjectStatus() const {
+ return m_impl.m_status;
+}
+
+int
+NdbDictionary::LogfileGroup::getObjectVersion() const {
+ return m_impl.m_version;
+}
+
+/*****************************************************************
+ * Datafile facade
+ */
+NdbDictionary::Datafile::Datafile()
+ : m_impl(* new NdbDatafileImpl(* this))
+{
+}
+
+NdbDictionary::Datafile::Datafile(NdbDatafileImpl & impl)
+ : m_impl(impl)
+{
+}
+
+NdbDictionary::Datafile::~Datafile(){
+ NdbDatafileImpl * tmp = &m_impl;
+ if(this != tmp){
+ delete tmp;
+ }
+}
+
+void
+NdbDictionary::Datafile::setPath(const char * path){
+ m_impl.m_path.assign(path);
+}
+
+const char *
+NdbDictionary::Datafile::getPath() const {
+ return m_impl.m_path.c_str();
+}
+
+void
+NdbDictionary::Datafile::setSize(Uint64 sz){
+ m_impl.m_size = sz;
+}
+
+Uint64
+NdbDictionary::Datafile::getSize() const {
+ return m_impl.m_size;
+}
+
+Uint64
+NdbDictionary::Datafile::getFree() const {
+ return m_impl.m_free;
+}
+
+void
+NdbDictionary::Datafile::setTablespace(const char * tablespace){
+ m_impl.m_filegroup_id = ~0;
+ m_impl.m_filegroup_version = ~0;
+ m_impl.m_filegroup_name.assign(tablespace);
+}
+
+void
+NdbDictionary::Datafile::setTablespace(const NdbDictionary::Tablespace & ts){
+ m_impl.m_filegroup_id = NdbTablespaceImpl::getImpl(ts).m_id;
+ m_impl.m_filegroup_version = ts.getObjectVersion();
+ m_impl.m_filegroup_name.assign(ts.getName());
+}
+
+const char *
+NdbDictionary::Datafile::getTablespace() const {
+ return m_impl.m_filegroup_name.c_str();
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::Datafile::getObjectStatus() const {
+ return m_impl.m_status;
+}
+
+int
+NdbDictionary::Datafile::getObjectVersion() const {
+ return m_impl.m_version;
+}
+
+/*****************************************************************
+ * Undofile facade
+ */
+NdbDictionary::Undofile::Undofile()
+ : m_impl(* new NdbUndofileImpl(* this))
+{
+}
+
+NdbDictionary::Undofile::Undofile(NdbUndofileImpl & impl)
+ : m_impl(impl)
+{
+}
+
+NdbDictionary::Undofile::~Undofile(){
+ NdbUndofileImpl * tmp = &m_impl;
+ if(this != tmp){
+ delete tmp;
+ }
+}
+
+void
+NdbDictionary::Undofile::setPath(const char * path){
+ m_impl.m_path.assign(path);
+}
+
+const char *
+NdbDictionary::Undofile::getPath() const {
+ return m_impl.m_path.c_str();
+}
+
+void
+NdbDictionary::Undofile::setSize(Uint64 sz){
+ m_impl.m_size = sz;
+}
+
+Uint64
+NdbDictionary::Undofile::getSize() const {
+ return m_impl.m_size;
+}
+
+Uint64
+NdbDictionary::Undofile::getFree() const {
+ return m_impl.m_free;
+}
+
+void
+NdbDictionary::Undofile::setLogfileGroup(const char * logfileGroup){
+ m_impl.m_filegroup_id = ~0;
+ m_impl.m_filegroup_version = ~0;
+ m_impl.m_filegroup_name.assign(logfileGroup);
+}
+
+void
+NdbDictionary::Undofile::setLogfileGroup
+(const NdbDictionary::LogfileGroup & ts){
+ m_impl.m_filegroup_id = NdbLogfileGroupImpl::getImpl(ts).m_id;
+ m_impl.m_filegroup_version = ts.getObjectVersion();
+ m_impl.m_filegroup_name.assign(ts.getName());
+}
+
+const char *
+NdbDictionary::Undofile::getLogfileGroup() const {
+ return m_impl.m_filegroup_name.c_str();
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::Undofile::getObjectStatus() const {
+ return m_impl.m_status;
+}
+
+int
+NdbDictionary::Undofile::getObjectVersion() const {
+ return m_impl.m_version;
+}
+
+/*****************************************************************
* Dictionary facade
*/
NdbDictionary::Dictionary::Dictionary(Ndb & ndb)
@@ -1062,6 +1388,7 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
break;
}
}
+
if (col.getPrimaryKey())
out << " PRIMARY KEY";
else if (! col.getNullable())
@@ -1072,13 +1399,115 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
if(col.getDistributionKey())
out << " DISTRIBUTION KEY";
+ switch (col.getArrayType()) {
+ case NDB_ARRAYTYPE_FIXED:
+ out << " AT=FIXED";
+ break;
+ case NDB_ARRAYTYPE_SHORT_VAR:
+ out << " AT=SHORT_VAR";
+ break;
+ case NDB_ARRAYTYPE_MEDIUM_VAR:
+ out << " AT=MEDIUM_VAR";
+ break;
+ default:
+ out << " AT=" << col.getArrayType() << "?";
+ break;
+ }
+
+ switch (col.getStorageType()) {
+ case NDB_STORAGETYPE_MEMORY:
+ out << " ST=MEMORY";
+ break;
+ case NDB_STORAGETYPE_DISK:
+ out << " ST=DISK";
+ break;
+ default:
+ out << " ST=" << col.getStorageType() << "?";
+ break;
+ }
+
return out;
}
+int
+NdbDictionary::Dictionary::createLogfileGroup(const LogfileGroup & lg){
+ return m_impl.createLogfileGroup(NdbLogfileGroupImpl::getImpl(lg));
+}
+
+int
+NdbDictionary::Dictionary::dropLogfileGroup(const LogfileGroup & lg){
+ return m_impl.dropLogfileGroup(NdbLogfileGroupImpl::getImpl(lg));
+}
+
+NdbDictionary::LogfileGroup
+NdbDictionary::Dictionary::getLogfileGroup(const char * name){
+ NdbDictionary::LogfileGroup tmp;
+ m_impl.m_receiver.get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
+ NdbDictionary::Object::LogfileGroup, name);
+ return tmp;
+}
+
+int
+NdbDictionary::Dictionary::createTablespace(const Tablespace & lg){
+ return m_impl.createTablespace(NdbTablespaceImpl::getImpl(lg));
+}
+
+int
+NdbDictionary::Dictionary::dropTablespace(const Tablespace & lg){
+ return m_impl.dropTablespace(NdbTablespaceImpl::getImpl(lg));
+}
+
+NdbDictionary::Tablespace
+NdbDictionary::Dictionary::getTablespace(const char * name){
+ NdbDictionary::Tablespace tmp;
+ m_impl.m_receiver.get_filegroup(NdbTablespaceImpl::getImpl(tmp),
+ NdbDictionary::Object::Tablespace, name);
+ return tmp;
+}
+
+int
+NdbDictionary::Dictionary::createDatafile(const Datafile & df, bool force){
+ return m_impl.createDatafile(NdbDatafileImpl::getImpl(df), force);
+}
+
+int
+NdbDictionary::Dictionary::dropDatafile(const Datafile& df){
+ return m_impl.dropDatafile(NdbDatafileImpl::getImpl(df));
+}
+
+NdbDictionary::Datafile
+NdbDictionary::Dictionary::getDatafile(Uint32 node, const char * path){
+ NdbDictionary::Datafile tmp;
+ m_impl.m_receiver.get_file(NdbDatafileImpl::getImpl(tmp),
+ NdbDictionary::Object::Datafile,
+ node ? (int)node : -1, path);
+ return tmp;
+}
+
+int
+NdbDictionary::Dictionary::createUndofile(const Undofile & df, bool force){
+ return m_impl.createUndofile(NdbUndofileImpl::getImpl(df), force);
+}
+
+int
+NdbDictionary::Dictionary::dropUndofile(const Undofile& df){
+ return m_impl.dropUndofile(NdbUndofileImpl::getImpl(df));
+}
+
+NdbDictionary::Undofile
+NdbDictionary::Dictionary::getUndofile(Uint32 node, const char * path){
+ NdbDictionary::Undofile tmp;
+ m_impl.m_receiver.get_file(NdbUndofileImpl::getImpl(tmp),
+ NdbDictionary::Object::Undofile,
+ node ? (int)node : -1, path);
+ return tmp;
+}
+
const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0;
const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_MEMORY = 0;
const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0;
const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0;
const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0;
const NdbDictionary::Column * NdbDictionary::Column::RANGE_NO = 0;
+const NdbDictionary::Column * NdbDictionary::Column::DISK_REF = 0;
const NdbDictionary::Column * NdbDictionary::Column::RECORDS_IN_RANGE = 0;
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 3236916b035..79780c62643 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -29,6 +29,8 @@
#include <signaldata/AlterTable.hpp>
#include <signaldata/DropIndx.hpp>
#include <signaldata/ListTables.hpp>
+#include <signaldata/DropFilegroup.hpp>
+#include <signaldata/CreateFilegroup.hpp>
#include <signaldata/WaitGCP.hpp>
#include <SimpleProperties.hpp>
#include <Bitmask.hpp>
@@ -39,6 +41,7 @@
#include "NdbBlobImpl.hpp"
#include <AttributeHeader.hpp>
#include <my_sys.h>
+#include <NdbEnv.h>
#define DEBUG_PRINT 0
#define INCOMPATIBLE_VERSION -2
@@ -80,8 +83,11 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
m_defaultValue = col.m_defaultValue;
m_attrSize = col.m_attrSize;
m_arraySize = col.m_arraySize;
+ m_arrayType = col.m_arrayType;
+ m_storageType = col.m_storageType;
m_keyInfoPos = col.m_keyInfoPos;
m_blobTable = col.m_blobTable;
+ m_column_no = col.m_column_no;
// Do not copy m_facade !!
return *this;
@@ -111,6 +117,7 @@ NdbColumnImpl::init(Type t)
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Olddecimal:
case Olddecimalunsigned:
@@ -120,34 +127,57 @@ NdbColumnImpl::init(Type t)
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Char:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
+ break;
case Varchar:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
break;
case Binary:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
+ break;
case Varbinary:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
+ break;
case Datetime:
case Date:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Blob:
m_precision = 256;
m_scale = 8000;
m_length = 4;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Text:
m_precision = 256;
m_scale = 8000;
m_length = 4;
m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Time:
case Year:
@@ -156,24 +186,28 @@ NdbColumnImpl::init(Type t)
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Bit:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Longvarchar:
m_precision = 0;
m_scale = 0;
m_length = 1; // legal
m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
break;
case Longvarbinary:
m_precision = 0;
m_scale = 0;
m_length = 1; // legal
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
break;
default:
case Undefined:
@@ -190,6 +224,11 @@ NdbColumnImpl::init(Type t)
m_autoIncrement = false;
m_autoIncrementInitialValue = 1;
m_blobTable = NULL;
+ m_storageType = NDB_STORAGETYPE_MEMORY;
+#ifdef VM_TRACE
+ if(NdbEnv_GetEnv("NDB_DEFAULT_DISK", (char *)0, 0))
+ m_storageType = NDB_STORAGETYPE_DISK;
+#endif
}
NdbColumnImpl::~NdbColumnImpl()
@@ -212,13 +251,11 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const
if(m_nullable != col.m_nullable){
DBUG_RETURN(false);
}
-#ifdef ndb_dictionary_dkey_fixed
- if(m_pk){
- if(m_distributionKey != col.m_distributionKey){
+ if (m_pk) {
+ if ((bool)m_distributionKey != (bool)col.m_distributionKey) {
DBUG_RETURN(false);
}
}
-#endif
if (m_precision != col.m_precision ||
m_scale != col.m_scale ||
m_length != col.m_length ||
@@ -232,6 +269,10 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const
DBUG_RETURN(false);
}
+ if (m_arrayType != col.m_arrayType || m_storageType != col.m_storageType){
+ DBUG_RETURN(false);
+ }
+
DBUG_RETURN(true);
}
@@ -269,6 +310,11 @@ NdbColumnImpl::create_pseudo(const char * name){
col->m_impl.m_attrId = AttributeHeader::RANGE_NO;
col->m_impl.m_attrSize = 4;
col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$DISK_REF")){
+ col->setType(NdbDictionary::Column::Bigunsigned);
+ col->m_impl.m_attrId = AttributeHeader::DISK_REF;
+ col->m_impl.m_attrSize = 8;
+ col->m_impl.m_arraySize = 1;
} else if(!strcmp(name, "NDB$RECORDS_IN_RANGE")){
col->setType(NdbDictionary::Column::Unsigned);
col->m_impl.m_attrId = AttributeHeader::RECORDS_IN_RANGE;
@@ -285,13 +331,15 @@ NdbColumnImpl::create_pseudo(const char * name){
*/
NdbTableImpl::NdbTableImpl()
- : NdbDictionary::Table(* this), m_facade(this)
+ : NdbDictionary::Table(* this),
+ NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(this)
{
init();
}
NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
- : NdbDictionary::Table(* this), m_facade(&f)
+ : NdbDictionary::Table(* this),
+ NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(&f)
{
init();
}
@@ -309,9 +357,10 @@ NdbTableImpl::~NdbTableImpl()
void
NdbTableImpl::init(){
m_changeMask= 0;
- m_tableId= RNIL;
+ m_id= RNIL;
m_primaryTableId= RNIL;
m_frm.clear();
+ m_newFrm.clear();
m_fragmentType= NdbDictionary::Object::DistrKeyHash;
m_hashValueMask= 0;
m_hashpointerValue= 0;
@@ -323,11 +372,12 @@ NdbTableImpl::init(){
m_fragmentCount= 0;
m_dictionary= NULL;
m_index= NULL;
- m_indexType= NdbDictionary::Index::Undefined;
+ m_indexType= NdbDictionary::Object::TypeUndefined;
m_noOfKeys= 0;
m_noOfDistributionKeys= 0;
m_noOfBlobs= 0;
m_replicaCount= 0;
+ m_tablespace_id = ~0;
}
bool
@@ -387,19 +437,19 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const
DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,obj.m_maxLoadFactor));
DBUG_RETURN(false);
}
-
- DBUG_RETURN(true);
+
+ DBUG_RETURN(true);
}
void
NdbTableImpl::assign(const NdbTableImpl& org)
{
- m_tableId = org.m_tableId;
m_internalName.assign(org.m_internalName);
updateMysqlName();
m_externalName.assign(org.m_externalName);
m_newExternalName.assign(org.m_newExternalName);
m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
+ m_newFrm.assign(org.m_newFrm.get_data(), org.m_newFrm.length());
m_ng.assign(org.m_ng.get_data(), org.m_ng.length());
m_fragmentType = org.m_fragmentType;
m_fragmentCount = org.m_fragmentCount;
@@ -425,8 +475,13 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_keyLenInWords = org.m_keyLenInWords;
m_noOfBlobs = org.m_noOfBlobs;
+ m_id = org.m_id;
m_version = org.m_version;
m_status = org.m_status;
+
+ m_tablespace_name = org.m_tablespace_name;
+ m_tablespace_id= org.m_tablespace_id;
+ m_tablespace_version = org.m_tablespace_version;
}
void NdbTableImpl::setName(const char * name)
@@ -444,6 +499,89 @@ NdbTableImpl::getName() const
}
void
+NdbTableImpl::computeAggregates()
+{
+ m_noOfKeys = 0;
+ m_keyLenInWords = 0;
+ m_noOfDistributionKeys = 0;
+ m_noOfBlobs = 0;
+ Uint32 i, n;
+ for (i = 0; i < m_columns.size(); i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk) {
+ m_noOfKeys++;
+ m_keyLenInWords += (col->m_attrSize * col->m_arraySize + 3) / 4;
+ }
+ if (col->m_distributionKey == 2) // set by user
+ m_noOfDistributionKeys++;
+
+ if (col->getBlobType())
+ m_noOfBlobs++;
+ col->m_keyInfoPos = ~0;
+ }
+ if (m_noOfDistributionKeys == m_noOfKeys) {
+ // all is none!
+ m_noOfDistributionKeys = 0;
+ }
+
+ if (m_noOfDistributionKeys == 0)
+ {
+ // none is all!
+ for (i = 0, n = m_noOfKeys; n != 0; i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk) {
+ col->m_distributionKey = true; // set by us
+ n--;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0, n = m_noOfKeys; n != 0; i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk)
+ {
+ if(col->m_distributionKey == 1)
+ col->m_distributionKey = 0;
+ n--;
+ }
+ }
+ }
+
+ Uint32 keyInfoPos = 0;
+ for (i = 0, n = m_noOfKeys; n != 0; i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk) {
+ col->m_keyInfoPos = keyInfoPos++;
+ n--;
+ }
+ }
+}
+
+void NdbTableImpl::setFrm(const void* data, Uint32 len)
+{
+ m_newFrm.assign(data, len);
+}
+
+const void *
+NdbTableImpl::getFrmData() const
+{
+ if (m_newFrm.empty())
+ return m_frm.get_data();
+ else
+ return m_newFrm.get_data();
+}
+
+Uint32
+NdbTableImpl::getFrmLength() const
+{
+ if (m_newFrm.empty())
+ return m_frm.length();
+ else
+ return m_newFrm.length();
+}
+
+void
NdbTableImpl::updateMysqlName()
{
Vector<BaseString> v;
@@ -458,7 +596,6 @@ NdbTableImpl::updateMysqlName()
void
NdbTableImpl::buildColumnHash(){
const Uint32 size = m_columns.size();
-
int i;
for(i = 31; i >= 0; i--){
if(((1 << i) & size) != 0){
@@ -564,22 +701,22 @@ NdbTableImpl::get_nodes(Uint32 hashValue, const Uint16 ** nodes) const
NdbIndexImpl::NdbIndexImpl() :
NdbDictionary::Index(* this),
- m_facade(this)
+ NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(this)
{
init();
}
NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
NdbDictionary::Index(* this),
- m_facade(&f)
+ NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(&f)
{
init();
}
void NdbIndexImpl::init()
{
- m_indexId= RNIL;
- m_type= NdbDictionary::Index::Undefined;
+ m_id= RNIL;
+ m_type= NdbDictionary::Object::TypeUndefined;
m_logging= true;
m_table= NULL;
}
@@ -624,14 +761,14 @@ NdbIndexImpl::getIndexTable() const
NdbEventImpl::NdbEventImpl() :
NdbDictionary::Event(* this),
- m_facade(this)
+ NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(this)
{
init();
}
NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
NdbDictionary::Event(* this),
- m_facade(&f)
+ NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(&f)
{
init();
}
@@ -752,6 +889,7 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
delete NdbDictionary::Column::COMMIT_COUNT;
delete NdbDictionary::Column::ROW_SIZE;
delete NdbDictionary::Column::RANGE_NO;
+ delete NdbDictionary::Column::DISK_REF;
delete NdbDictionary::Column::RECORDS_IN_RANGE;
NdbDictionary::Column::FRAGMENT= 0;
NdbDictionary::Column::FRAGMENT_MEMORY= 0;
@@ -759,6 +897,7 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
NdbDictionary::Column::COMMIT_COUNT= 0;
NdbDictionary::Column::ROW_SIZE= 0;
NdbDictionary::Column::RANGE_NO= 0;
+ NdbDictionary::Column::DISK_REF= 0;
NdbDictionary::Column::RECORDS_IN_RANGE= 0;
}
m_globalHash->unlock();
@@ -832,6 +971,8 @@ NdbDictionaryImpl::setTransporter(class Ndb* ndb,
NdbColumnImpl::create_pseudo("NDB$ROW_SIZE");
NdbDictionary::Column::RANGE_NO=
NdbColumnImpl::create_pseudo("NDB$RANGE_NO");
+ NdbDictionary::Column::DISK_REF=
+ NdbColumnImpl::create_pseudo("NDB$DISK_REF");
NdbDictionary::Column::RECORDS_IN_RANGE=
NdbColumnImpl::create_pseudo("NDB$RECORDS_IN_RANGE");
}
@@ -962,6 +1103,30 @@ NdbDictInterface::execSignal(void* dictImpl,
case GSN_LIST_TABLES_CONF:
tmp->execLIST_TABLES_CONF(signal, ptr);
break;
+ case GSN_CREATE_FILEGROUP_REF:
+ tmp->execCREATE_FILEGROUP_REF(signal, ptr);
+ break;
+ case GSN_CREATE_FILEGROUP_CONF:
+ tmp->execCREATE_FILEGROUP_CONF(signal, ptr);
+ break;
+ case GSN_CREATE_FILE_REF:
+ tmp->execCREATE_FILE_REF(signal, ptr);
+ break;
+ case GSN_CREATE_FILE_CONF:
+ tmp->execCREATE_FILE_CONF(signal, ptr);
+ break;
+ case GSN_DROP_FILEGROUP_REF:
+ tmp->execDROP_FILEGROUP_REF(signal, ptr);
+ break;
+ case GSN_DROP_FILEGROUP_CONF:
+ tmp->execDROP_FILEGROUP_CONF(signal, ptr);
+ break;
+ case GSN_DROP_FILE_REF:
+ tmp->execDROP_FILE_REF(signal, ptr);
+ break;
+ case GSN_DROP_FILE_CONF:
+ tmp->execDROP_FILE_CONF(signal, ptr);
+ break;
case GSN_WAIT_GCP_CONF:
tmp->execWAIT_GCP_CONF(signal, ptr);
break;
@@ -989,20 +1154,16 @@ NdbDictInterface::execNodeStatus(void* dictImpl, Uint32 aNode,
}
int
-NdbDictInterface::dictSignal(NdbApiSignal* signal,
- LinearSectionPtr ptr[3],int noLSP,
- const int useMasterNodeId,
- const Uint32 RETRIES,
- const WaitSignalType wst,
- const int theWait,
- const int *errcodes,
- const int noerrcodes,
- const int temporaryMask)
+NdbDictInterface::dictSignal(NdbApiSignal* sig,
+ LinearSectionPtr ptr[3], int secs,
+ int node_specification,
+ WaitSignalType wst,
+ int timeout, Uint32 RETRIES,
+ const int *errcodes, int temporaryMask)
{
DBUG_ENTER("NdbDictInterface::dictSignal");
- DBUG_PRINT("enter", ("useMasterNodeId: %d", useMasterNodeId));
+ DBUG_PRINT("enter", ("useMasterNodeId: %d", node_specification));
for(Uint32 i = 0; i<RETRIES; i++){
- //if (useMasterNodeId == 0)
m_buffer.clear();
// Protected area
@@ -1013,44 +1174,33 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
break, continue or simply end of statement block
*/
PollGuard poll_guard(m_transporter, &m_waiter, refToBlock(m_reference));
- Uint32 aNodeId;
- if (useMasterNodeId) {
- if ((m_masterNodeId == 0) ||
- (!m_transporter->get_node_alive(m_masterNodeId))) {
- m_masterNodeId = m_transporter->get_an_alive_node();
- }//if
- aNodeId = m_masterNodeId;
- } else {
- aNodeId = m_transporter->get_an_alive_node();
+ Uint32 node;
+ switch(node_specification){
+ case 0:
+ node = (m_transporter->get_node_alive(m_masterNodeId) ? m_masterNodeId :
+ (m_masterNodeId = m_transporter->get_an_alive_node()));
+ break;
+ case -1:
+ node = m_transporter->get_an_alive_node();
+ break;
+ default:
+ node = node_specification;
}
- if(aNodeId == 0){
+ DBUG_PRINT("info", ("node %d", node));
+ if(node == 0){
m_error.code= 4009;
DBUG_RETURN(-1);
}
- {
- int r;
- if (ptr) {
-#ifdef EVENT_DEBUG
- printf("Long signal %d ptr", noLSP);
- for (int q=0;q<noLSP;q++) {
- printf(" sz %d", ptr[q].sz);
- }
- printf("\n");
-#endif
- r = m_transporter->sendFragmentedSignal(signal, aNodeId, ptr, noLSP);
- } else {
-#ifdef EVENT_DEBUG
- printf("Short signal\n");
-#endif
- r = m_transporter->sendSignal(signal, aNodeId);
- }
- if(r != 0){
- continue;
- }
- }
+ int res = (ptr ?
+ m_transporter->sendFragmentedSignal(sig, node, ptr, secs):
+ m_transporter->sendSignal(sig, node));
+ if(res != 0){
+ DBUG_PRINT("info", ("dictSignal failed to send signal"));
+ continue;
+ }
m_error.code= 0;
- int ret_val= poll_guard.wait_n_unlock(theWait, aNodeId, wst);
+ int ret_val= poll_guard.wait_n_unlock(timeout, node, wst);
// End of Protected area
if(ret_val == 0 && m_error.code == 0){
@@ -1062,10 +1212,12 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
* Handle error codes
*/
if(ret_val == -2) //WAIT_NODE_FAILURE
+ {
continue;
-
+ }
if(m_waiter.m_state == WST_WAIT_TIMEOUT)
{
+ DBUG_PRINT("info", ("dictSignal caught time-out"));
m_error.code = 4008;
DBUG_RETURN(-1);
}
@@ -1079,18 +1231,20 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
else if ( (temporaryMask & m_error.code) != 0 ) {
continue;
}
- if (errcodes) {
- int doContinue = 0;
- for (int j=0; j < noerrcodes; j++)
- if(m_error.code == errcodes[j]) {
- doContinue = 1;
+ DBUG_PRINT("info", ("dictSignal caught error= %d", m_error.code));
+
+ if(m_error.code && errcodes)
+ {
+ for(int j = 0; errcodes[j] ; j++){
+ if(m_error.code == errcodes[j]){
+ m_error.code = 0;
break;
}
- if (doContinue)
+ }
+ if(!m_error.code) // Accepted error code
continue;
}
-
- DBUG_RETURN(-1);
+ break;
}
DBUG_RETURN(-1);
}
@@ -1105,8 +1259,8 @@ NdbTableImpl *
NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
- GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
-
+ GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
req->senderRef = m_reference;
req->senderData = 0;
req->requestType =
@@ -1165,21 +1319,23 @@ NdbDictInterface::getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames)
{
- int errCodes[] = {GetTabInfoRef::Busy };
-
- int r = dictSignal(signal,ptr,noOfSections,
- 0/*do not use masternode id*/,
- 100,
+ int errCodes[] = {GetTabInfoRef::Busy, 0 };
+ int r = dictSignal(signal, ptr, noOfSections,
+ -1, // any node
WAIT_GET_TAB_INFO_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes, 1);
- if (r) return 0;
+ WAITFOR_RESPONSE_TIMEOUT, 100, errCodes);
+ if (r)
+ return 0;
+
NdbTableImpl * rt = 0;
- m_error.code= parseTableInfo(&rt,
- (Uint32*)m_buffer.get_data(),
- m_buffer.length() / 4, fullyQualifiedNames);
- rt->buildColumnHash();
+ m_error.code = parseTableInfo(&rt,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4,
+ fullyQualifiedNames);
+ if(rt)
+ rt->buildColumnHash();
+
return rt;
}
@@ -1211,8 +1367,9 @@ void
NdbDictInterface::execGET_TABINFO_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef, signal->getDataPtr());
-
+ const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef,
+ signal->getDataPtr());
+
m_error.code= ref->errorCode;
m_waiter.signal(NO_WAIT);
}
@@ -1277,6 +1434,10 @@ objectTypeMapping[] = {
{ DictTabInfo::IndexTrigger, NdbDictionary::Object::IndexTrigger },
{ DictTabInfo::SubscriptionTrigger,NdbDictionary::Object::SubscriptionTrigger },
{ DictTabInfo::ReadOnlyConstraint ,NdbDictionary::Object::ReadOnlyConstraint },
+ { DictTabInfo::Tablespace, NdbDictionary::Object::Tablespace },
+ { DictTabInfo::LogfileGroup, NdbDictionary::Object::LogfileGroup },
+ { DictTabInfo::Datafile, NdbDictionary::Object::Datafile },
+ { DictTabInfo::Undofile, NdbDictionary::Object::Undofile },
{ -1, -1 }
};
@@ -1330,7 +1491,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
const char * externalName = Ndb::externalizeTableName(internalName, fullyQualifiedNames);
NdbTableImpl * impl = new NdbTableImpl();
- impl->m_tableId = tableDesc.TableId;
+ impl->m_id = tableDesc.TableId;
impl->m_version = tableDesc.TableVersion;
impl->m_status = NdbDictionary::Object::Retrieved;
impl->m_internalName.assign(internalName);
@@ -1350,23 +1511,18 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_minLoadFactor = tableDesc.MinLoadFactor;
impl->m_maxLoadFactor = tableDesc.MaxLoadFactor;
- impl->m_indexType = (NdbDictionary::Index::Type)
+ impl->m_indexType = (NdbDictionary::Object::Type)
getApiConstant(tableDesc.TableType,
indexTypeMapping,
- NdbDictionary::Index::Undefined);
+ NdbDictionary::Object::TypeUndefined);
- if(impl->m_indexType == NdbDictionary::Index::Undefined){
+ if(impl->m_indexType == NdbDictionary::Object::TypeUndefined){
} else {
const char * externalPrimary =
Ndb::externalizeTableName(tableDesc.PrimaryTable, fullyQualifiedNames);
impl->m_primaryTable.assign(externalPrimary);
}
- Uint32 keyInfoPos = 0;
- Uint32 keyCount = 0;
- Uint32 blobCount = 0;
- Uint32 distKeys = 0;
-
Uint32 i;
for(i = 0; i < tableDesc.NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
@@ -1409,46 +1565,27 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
}
col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
col->m_arraySize = attrDesc.AttributeArraySize;
+ col->m_arrayType = attrDesc.AttributeArrayType;
if(attrDesc.AttributeSize == 0)
{
col->m_attrSize = 4;
col->m_arraySize = (attrDesc.AttributeArraySize + 31) >> 5;
}
+ col->m_storageType = attrDesc.AttributeStorageType;
col->m_pk = attrDesc.AttributeKeyFlag;
- col->m_distributionKey = attrDesc.AttributeDKey;
+ col->m_distributionKey = attrDesc.AttributeDKey ? 2 : 0;
col->m_nullable = attrDesc.AttributeNullableFlag;
col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
col->m_autoIncrementInitialValue = ~0;
col->m_defaultValue.assign(attrDesc.AttributeDefaultValue);
- if(attrDesc.AttributeKeyFlag){
- col->m_keyInfoPos = keyInfoPos + 1;
- keyInfoPos += ((col->m_attrSize * col->m_arraySize + 3) / 4);
- keyCount++;
-
- if(attrDesc.AttributeDKey)
- distKeys++;
- } else {
- col->m_keyInfoPos = 0;
- }
- if (col->getBlobType())
- blobCount++;
- NdbColumnImpl * null = 0;
- impl->m_columns.fill(attrDesc.AttributeId, null);
- if(impl->m_columns[attrDesc.AttributeId] != 0){
- delete col;
- delete impl;
- DBUG_RETURN(703);
- }
- impl->m_columns[attrDesc.AttributeId] = col;
+ col->m_column_no = impl->m_columns.size();
+ impl->m_columns.push_back(col);
it.next();
}
- impl->m_noOfKeys = keyCount;
- impl->m_keyLenInWords = keyInfoPos;
- impl->m_noOfBlobs = blobCount;
- impl->m_noOfDistributionKeys = distKeys;
+ impl->computeAggregates();
if(tableDesc.FragmentDataLen > 0)
{
@@ -1458,7 +1595,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_replicaCount = replicaCount;
impl->m_fragmentCount = fragCount;
DBUG_PRINT("info", ("replicaCount=%x , fragCount=%x",replicaCount,fragCount));
- for(i = 0; i<(fragCount*replicaCount); i++)
+ for(i = 0; i < (Uint32) (fragCount*replicaCount); i++)
{
impl->m_fragments.push_back(tableDesc.FragmentData[i+2]);
}
@@ -1478,14 +1615,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_hashpointerValue = 0;
}
- if(distKeys == 0)
- {
- for(i = 0; i < tableDesc.NoOfAttributes; i++)
- {
- if(impl->m_columns[i]->getPrimaryKey())
- impl->m_columns[i]->m_distributionKey = true;
- }
- }
+ impl->m_tablespace_id = tableDesc.TablespaceId;
+ impl->m_tablespace_version = tableDesc.TablespaceVersion;
* ret = impl;
@@ -1514,7 +1645,7 @@ NdbDictionaryImpl::createTable(NdbTableImpl &t)
m_error.code= 709;
DBUG_RETURN(-1);
}
- if (createBlobTables(*(info->m_table_impl)) != 0) {
+ if (createBlobTables(t, *(info->m_table_impl)) != 0) {
int save_code = m_error.code;
(void)dropTable(t);
m_error.code= save_code;
@@ -1524,15 +1655,19 @@ NdbDictionaryImpl::createTable(NdbTableImpl &t)
}
int
-NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
+NdbDictionaryImpl::createBlobTables(NdbTableImpl& org, NdbTableImpl &t)
{
DBUG_ENTER("NdbDictionaryImpl::createBlobTables");
for (unsigned i = 0; i < t.m_columns.size(); i++) {
NdbColumnImpl & c = *t.m_columns[i];
+ NdbColumnImpl & oc = *org.m_columns[i];
if (! c.getBlobType() || c.getPartSize() == 0)
continue;
NdbTableImpl bt;
+ NdbDictionary::Column::StorageType save = c.getStorageType();
+ c.setStorageType(oc.getStorageType());
NdbBlob::getBlobTable(bt, &t, &c);
+ c.setStorageType(save);
if (createTable(bt) != 0)
{
DBUG_RETURN(-1);
@@ -1623,6 +1758,9 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
{
DBUG_ENTER("NdbDictInterface::createOrAlterTable");
unsigned i;
+
+ impl.computeAggregates();
+
if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
m_error.code= 4317;
DBUG_RETURN(-1);
@@ -1632,12 +1770,28 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
m_error.code= 4318;
DBUG_RETURN(-1);
}
-
+
+ // Check if any changes for alter table
+
+ // Name change
if (!impl.m_newExternalName.empty()) {
+ if (alter)
+ {
+ AlterTableReq::setNameFlag(impl.m_changeMask, true);
+ }
impl.m_externalName.assign(impl.m_newExternalName);
- AlterTableReq::setNameFlag(impl.m_changeMask, true);
+ impl.m_newExternalName.clear();
}
-
+ // Definition change (frm)
+ if (!impl.m_newFrm.empty()) {
+ if (alter)
+ {
+ AlterTableReq::setFrmFlag(impl.m_changeMask, true);
+ }
+ impl.m_frm.assign(impl.m_newFrm.get_data(), impl.m_newFrm.length());
+ impl.m_newFrm.clear();
+ }
+
//validate();
//aggregate();
@@ -1645,7 +1799,6 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
ndb.internalize_table_name(impl.m_externalName.c_str()));
impl.m_internalName.assign(internalName);
impl.updateMysqlName();
- UtilBufferWriter w(m_buffer);
DictTabInfo::Table tmpTab;
tmpTab.init();
BaseString::snprintf(tmpTab.TableName,
@@ -1668,7 +1821,9 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
autoIncrementValue = col->m_autoIncrementInitialValue;
}
if (col->m_distributionKey)
+ {
distKeys++;
+ }
}
if (distKeys == impl.m_noOfKeys)
distKeys= 0;
@@ -1698,6 +1853,41 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
DictTabInfo::AllNodesSmallTable);
tmpTab.TableVersion = rand();
+ const char* tablespace_name= impl.m_tablespace_name.c_str();
+loop:
+ if(impl.m_tablespace_id != ~(Uint32)0)
+ {
+ tmpTab.TablespaceId = impl.m_tablespace_id;
+ tmpTab.TablespaceVersion = impl.m_tablespace_version;
+ }
+ else if(strlen(tablespace_name))
+ {
+ NdbTablespaceImpl tmp;
+ if(get_filegroup(tmp, NdbDictionary::Object::Tablespace,
+ tablespace_name) == 0)
+ {
+ tmpTab.TablespaceId = tmp.m_id;
+ tmpTab.TablespaceVersion = tmp.m_version;
+ }
+ else
+ {
+ // error set by get filegroup
+ return -1;
+ }
+ }
+ else
+ {
+ for(i = 0; i<sz; i++)
+ {
+ if(impl.m_columns[i]->m_storageType == NDB_STORAGETYPE_DISK)
+ {
+ tablespace_name = "DEFAULT-TS";
+ goto loop;
+ }
+ }
+ }
+
+ UtilBufferWriter w(m_buffer);
SimpleProperties::UnpackStatus s;
s = SimpleProperties::pack(w,
&tmpTab,
@@ -1724,16 +1914,28 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
DictTabInfo::Attribute tmpAttr; tmpAttr.init();
BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
- tmpAttr.AttributeId = i;
+ tmpAttr.AttributeId = col->m_attrId;
tmpAttr.AttributeKeyFlag = col->m_pk;
tmpAttr.AttributeNullableFlag = col->m_nullable;
- tmpAttr.AttributeDKey = distKeys ? col->m_distributionKey : 0;
+ tmpAttr.AttributeDKey = distKeys ? (bool)col->m_distributionKey : 0;
tmpAttr.AttributeExtType = (Uint32)col->m_type;
tmpAttr.AttributeExtPrecision = ((unsigned)col->m_precision & 0xFFFF);
tmpAttr.AttributeExtScale = col->m_scale;
tmpAttr.AttributeExtLength = col->m_length;
-
+ if(col->m_storageType == NDB_STORAGETYPE_DISK)
+ tmpAttr.AttributeArrayType = NDB_ARRAYTYPE_FIXED;
+ else
+ tmpAttr.AttributeArrayType = col->m_arrayType;
+
+ if(col->m_pk)
+ tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
+ else
+ tmpAttr.AttributeStorageType = col->m_storageType;
+
+ if(col->getBlobType())
+ tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
+
// check type and compute attribute size and array size
if (! tmpAttr.translateExtType()) {
m_error.code= 703;
@@ -1776,77 +1978,65 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
w.add(DictTabInfo::AttributeEnd, 1);
}
- NdbApiSignal tSignal(m_reference);
- tSignal.theReceiversBlockNumber = DBDICT;
+ int ret;
LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = m_buffer.length() / 4;
- int ret;
- if (alter)
- {
- AlterTableReq * const req =
- CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ if (alter) {
+ tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
+ tSignal.theLength = AlterTableReq::SignalLength;
+
+ AlterTableReq * req = CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
req->changeMask = impl.m_changeMask;
- req->tableId = impl.m_tableId;
+ req->tableId = impl.m_id;
req->tableVersion = impl.m_version;;
- tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
- tSignal.theLength = AlterTableReq::SignalLength;
- ret= alterTable(&tSignal, ptr);
- }
- else
- {
- CreateTableReq * const req =
- CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
+
+ int errCodes[] = { AlterTableRef::NotMaster, AlterTableRef::Busy, 0 };
+ ret = dictSignal(&tSignal, ptr, 1,
+ 0, // master
+ WAIT_ALTER_TAB_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ errCodes);
- req->senderRef = m_reference;
- req->senderData = 0;
+ if(m_error.code == AlterTableRef::InvalidTableVersion) {
+ // Clear caches and try again
+ return INCOMPATIBLE_VERSION;
+ }
+ } else {
tSignal.theVerId_signalNumber = GSN_CREATE_TABLE_REQ;
tSignal.theLength = CreateTableReq::SignalLength;
- ret= createTable(&tSignal, ptr);
-
- if (ret)
- DBUG_RETURN(ret);
-
- if (haveAutoIncrement) {
- if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
- autoIncrementValue)) {
- if (ndb.theError.code == 0) {
- m_error.code= 4336;
- ndb.theError = m_error;
- } else
- m_error= ndb.theError;
- ret = -1; // errorcode set in initialize_autoincrement
- }
+
+ CreateTableReq * req = CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ int errCodes[] = { CreateTableRef::Busy, CreateTableRef::NotMaster, 0 };
+ ret = dictSignal(&tSignal, ptr, 1,
+ 0, // master node
+ WAIT_CREATE_INDX_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ errCodes);
+ }
+
+ if (!ret && !alter && haveAutoIncrement) {
+ if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
+ autoIncrementValue)) {
+ if (ndb.theError.code == 0) {
+ m_error.code = 4336;
+ ndb.theError = m_error;
+ } else
+ m_error= ndb.theError;
+ ret = -1; // errorcode set in initialize_autoincrement
}
}
DBUG_RETURN(ret);
}
-int
-NdbDictInterface::createTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
-#if DEBUG_PRINT
- ndbout_c("BufferLen = %d", ptr[0].sz);
- SimplePropertiesLinearReader r(ptr[0].p, ptr[0].sz);
- r.printAll(ndbout);
-#endif
- const int noErrCodes = 2;
- int errCodes[noErrCodes] =
- {CreateTableRef::Busy,
- CreateTableRef::NotMaster};
- return dictSignal(signal,ptr,1,
- 1/*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes,noErrCodes);
-}
-
-
void
NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
@@ -1861,55 +2051,27 @@ NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal,
}
void
-NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * signal,
+NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * sig,
LinearSectionPtr ptr[3])
{
- const CreateTableRef* const ref=
- CAST_CONSTPTR(CreateTableRef, signal->getDataPtr());
+ const CreateTableRef* ref = CAST_CONSTPTR(CreateTableRef, sig->getDataPtr());
m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
-int
-NdbDictInterface::alterTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
-#if DEBUG_PRINT
- ndbout_c("BufferLen = %d", ptr[0].sz);
- SimplePropertiesLinearReader r(ptr[0].p, ptr[0].sz);
- r.printAll(ndbout);
-#endif
- const int noErrCodes = 2;
- int errCodes[noErrCodes] =
- {AlterTableRef::NotMaster,
- AlterTableRef::Busy};
- int r = dictSignal(signal,ptr,1,
- 1/*use masternode id*/,
- 100,WAIT_ALTER_TAB_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes, noErrCodes);
- if(m_error.code == AlterTableRef::InvalidTableVersion) {
- // Clear caches and try again
- return INCOMPATIBLE_VERSION;
- }
-
- return r;
-}
-
void
NdbDictInterface::execALTER_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- //AlterTableConf* const conf = CAST_CONSTPTR(AlterTableConf, signal->getDataPtr());
m_waiter.signal(NO_WAIT);
}
void
-NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * signal,
+NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * sig,
LinearSectionPtr ptr[3])
{
- const AlterTableRef * const ref =
- CAST_CONSTPTR(AlterTableRef, signal->getDataPtr());
+ const AlterTableRef * ref = CAST_CONSTPTR(AlterTableRef, sig->getDataPtr());
m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
@@ -1932,7 +2094,6 @@ NdbDictionaryImpl::dropTable(const char * name)
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
const BaseString internalTableName(m_ndb.internalize_table_name(name));
-
DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName.c_str()));
m_localHash.drop(internalTableName.c_str());
m_globalHash->lock();
@@ -1941,7 +2102,7 @@ NdbDictionaryImpl::dropTable(const char * name)
m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
}
-
+
DBUG_RETURN(ret);
}
@@ -1954,13 +2115,14 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
return dropTable(name);
}
- if (impl.m_indexType != NdbDictionary::Index::Undefined) {
+ if (impl.m_indexType != NdbDictionary::Object::TypeUndefined)
+ {
m_receiver.m_error.code= 1228;
return -1;
}
List list;
- if ((res = listIndexes(list, impl.m_tableId)) == -1){
+ if ((res = listIndexes(list, impl.m_id)) == -1){
return -1;
}
for (unsigned i = 0; i < list.count; i++) {
@@ -1978,7 +2140,7 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
}
int ret = m_receiver.dropTable(impl);
- if(ret == 0 || m_error.code == 709){
+ if(ret == 0 || m_error.code == 709 || m_error.code == 723){
const char * internalTableName = impl.m_internalName.c_str();
@@ -2005,7 +2167,7 @@ NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
char btname[NdbBlobImpl::BlobTableNameSize];
NdbBlob::getBlobTableName(btname, &t, &c);
if (dropTable(btname) != 0) {
- if (m_error.code != 709){
+ if (m_error.code != 709 && m_error.code != 723){
DBUG_PRINT("exit",("error %u - exiting",m_error.code));
DBUG_RETURN(-1);
}
@@ -2023,28 +2185,21 @@ NdbDictInterface::dropTable(const NdbTableImpl & impl)
tSignal.theVerId_signalNumber = GSN_DROP_TABLE_REQ;
tSignal.theLength = DropTableReq::SignalLength;
- DropTableReq * const req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
+ DropTableReq * req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
- req->tableId = impl.m_tableId;
+ req->tableId = impl.m_id;
req->tableVersion = impl.m_version;
- return dropTable(&tSignal, 0);
-}
-
-int
-NdbDictInterface::dropTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
- const int noErrCodes = 3;
- int errCodes[noErrCodes] =
- {DropTableRef::NoDropTableRecordAvailable,
- DropTableRef::NotMaster,
- DropTableRef::Busy};
- int r = dictSignal(signal,NULL,0,
- 1/*use masternode id*/,
- 100,WAIT_DROP_TAB_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes, noErrCodes);
+ int errCodes[] =
+ { DropTableRef::NoDropTableRecordAvailable,
+ DropTableRef::NotMaster,
+ DropTableRef::Busy, 0 };
+ int r = dictSignal(&tSignal, 0, 0,
+ 0, // master
+ WAIT_DROP_TAB_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ errCodes);
if(m_error.code == DropTableRef::InvalidTableVersion) {
// Clear caches and try again
return INCOMPATIBLE_VERSION;
@@ -2068,7 +2223,7 @@ NdbDictInterface::execDROP_TABLE_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
DBUG_ENTER("NdbDictInterface::execDROP_TABLE_REF");
- const DropTableRef* const ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
+ const DropTableRef* ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
@@ -2116,7 +2271,8 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
}
NdbTableImpl * tab = info->m_table_impl;
- if(tab->m_indexType == NdbDictionary::Index::Undefined){
+ if(tab->m_indexType == NdbDictionary::Object::TypeUndefined)
+ {
// Not an index
m_error.code = 4243;
return 0;
@@ -2151,10 +2307,10 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
NdbIndexImpl *idx = new NdbIndexImpl();
idx->m_version = tab->m_version;
idx->m_status = tab->m_status;
- idx->m_indexId = tab->m_tableId;
+ idx->m_id = tab->m_id;
idx->m_externalName.assign(tab->getName());
idx->m_tableName.assign(prim->m_externalName);
- NdbDictionary::Index::Type type = idx->m_type = tab->m_indexType;
+ NdbDictionary::Object::Type type = idx->m_type = tab->m_indexType;
idx->m_logging = tab->m_logging;
// skip last attribute (NDB$PK or NDB$TNODE)
@@ -2180,7 +2336,7 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
idx->m_key_ids[key_id] = i;
col->m_keyInfoPos = key_id;
- if(type == NdbDictionary::Index::OrderedIndex &&
+ if(type == NdbDictionary::Object::OrderedIndex &&
(primCol->m_distributionKey ||
(distKeys == 0 && primCol->getPrimaryKey())))
{
@@ -2221,7 +2377,7 @@ NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
int
NdbDictInterface::createIndex(Ndb & ndb,
- NdbIndexImpl & impl,
+ const NdbIndexImpl & impl,
const NdbTableImpl & table)
{
//validate();
@@ -2235,8 +2391,6 @@ NdbDictInterface::createIndex(Ndb & ndb,
}
const BaseString internalName(
ndb.internalize_index_name(&table, impl.getName()));
- impl.m_internalName.assign(internalName);
-
w.add(DictTabInfo::TableName, internalName.c_str());
w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
@@ -2261,7 +2415,7 @@ NdbDictInterface::createIndex(Ndb & ndb,
}
req->setIndexType((DictTabInfo::TableType) it);
- req->setTableId(table.m_tableId);
+ req->setTableId(table.m_id);
req->setOnline(true);
AttributeList attributeList;
attributeList.sz = impl.m_columns.size();
@@ -2272,7 +2426,7 @@ NdbDictInterface::createIndex(Ndb & ndb,
m_error.code = 4247;
return -1;
}
- // Copy column definition
+ // Copy column definition XXX must be wrong, overwrites
*impl.m_columns[i] = *col;
// index key type check
@@ -2283,44 +2437,35 @@ NdbDictInterface::createIndex(Ndb & ndb,
m_error.code = 743;
return -1;
}
- attributeList.id[i] = col->m_attrId;
+ // API uses external column number to talk to DICT
+ attributeList.id[i] = col->m_column_no;
}
LinearSectionPtr ptr[2];
ptr[0].p = (Uint32*)&attributeList;
ptr[0].sz = 1 + attributeList.sz;
ptr[1].p = (Uint32*)m_buffer.get_data();
ptr[1].sz = m_buffer.length() >> 2; //BUG?
- return createIndex(&tSignal, ptr);
-}
-int
-NdbDictInterface::createIndex(NdbApiSignal* signal,
- LinearSectionPtr ptr[3])
-{
- const int noErrCodes = 2;
- int errCodes[noErrCodes] = {CreateIndxRef::Busy, CreateIndxRef::NotMaster};
- return dictSignal(signal,ptr,2,
- 1 /*use masternode id*/,
- 100,
+ int errCodes[] = { CreateIndxRef::Busy, CreateIndxRef::NotMaster, 0 };
+ return dictSignal(&tSignal, ptr, 2,
+ 0, // master
WAIT_CREATE_INDX_REQ,
- -1,
- errCodes,noErrCodes);
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ errCodes);
}
void
NdbDictInterface::execCREATE_INDX_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- //CreateTableConf* const conf = CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
-
m_waiter.signal(NO_WAIT);
}
void
-NdbDictInterface::execCREATE_INDX_REF(NdbApiSignal * signal,
+NdbDictInterface::execCREATE_INDX_REF(NdbApiSignal * sig,
LinearSectionPtr ptr[3])
{
- const CreateIndxRef* const ref = CAST_CONSTPTR(CreateIndxRef, signal->getDataPtr());
+ const CreateIndxRef* ref = CAST_CONSTPTR(CreateIndxRef, sig->getDataPtr());
m_error.code = ref->getErrorCode();
if(m_error.code == ref->NotMaster)
m_masterNodeId= ref->masterNodeId;
@@ -2411,23 +2556,15 @@ NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
req->setConnectionPtr(0);
req->setRequestType(DropIndxReq::RT_USER);
req->setTableId(~0); // DICT overwrites
- req->setIndexId(timpl.m_tableId);
+ req->setIndexId(timpl.m_id);
req->setIndexVersion(timpl.m_version);
- return dropIndex(&tSignal, 0);
-}
-
-int
-NdbDictInterface::dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
- const int noErrCodes = 2;
- int errCodes[noErrCodes] = {DropIndxRef::Busy, DropIndxRef::NotMaster};
- int r = dictSignal(signal,NULL,0,
- 1/*Use masternode id*/,
- 100,
+ int errCodes[] = { DropIndxRef::Busy, DropIndxRef::NotMaster, 0 };
+ int r = dictSignal(&tSignal, 0, 0,
+ 0, // master
WAIT_DROP_INDX_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes,noErrCodes);
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ errCodes);
if(m_error.code == DropIndxRef::InvalidIndexVersion) {
// Clear caches and try again
return INCOMPATIBLE_VERSION;
@@ -2446,7 +2583,7 @@ void
NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- const DropIndxRef* const ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
+ const DropIndxRef* ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
m_error.code = ref->getErrorCode();
if(m_error.code == ref->NotMaster)
m_masterNodeId= ref->masterNodeId;
@@ -2473,9 +2610,9 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
}
}
- DBUG_PRINT("info",("Table: id: %d version: %d", tab->m_tableId, tab->m_version));
+ DBUG_PRINT("info",("Table: id: %d version: %d", tab->m_id, tab->m_version));
- evnt.m_tableId = tab->m_tableId;
+ evnt.m_tableId = tab->m_id;
evnt.m_tableVersion = tab->m_version;
evnt.m_tableImpl = tab;
NdbTableImpl &table = *evnt.m_tableImpl;
@@ -2608,12 +2745,17 @@ NdbDictInterface::createEvent(class Ndb & ndb,
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = (m_buffer.length()+3) >> 2;
- int ret = createEvent(&tSignal, ptr, 1);
+ int errCodes[] = { CreateEvntRef::Busy, 0 };
+ int ret = dictSignal(&tSignal,ptr, 1,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ errCodes, 0);
if (ret) {
DBUG_RETURN(ret);
}
-
+
char *dataPtr = (char *)m_buffer.get_data();
unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr);
dataPtr += sizeof(lenCreateEvntConf);
@@ -2645,18 +2787,6 @@ NdbDictInterface::createEvent(class Ndb & ndb,
}
int
-NdbDictInterface::createEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLSP)
-{
- return dictSignal(signal,ptr,noLSP,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- NULL,0, -1);
-}
-
-int
NdbDictionaryImpl::executeSubscribeEvent(NdbEventOperationImpl & ev_op)
{
// NdbDictInterface m_receiver;
@@ -2685,13 +2815,12 @@ NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
"subscriberData=%d",req->subscriptionId,
req->subscriptionKey,req->subscriberData));
- int errCodes[] = { SubStartRef::Busy };
+ int errCodes[] = { SubStartRef::Busy, 0 };
DBUG_RETURN(dictSignal(&tSignal,NULL,0,
- 1 /*use masternode id*/,
- 100,
+ 0 /*use masternode id*/,
WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- errCodes, sizeof(errCodes)/sizeof(errCodes[0])));
+ -1, 100,
+ errCodes, 0));
}
int
@@ -2725,13 +2854,12 @@ NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
"subscriberData=%d",req->subscriptionId,
req->subscriptionKey,req->subscriberData));
- int errCodes[] = { SubStopRef::Busy };
+ int errCodes[] = { SubStopRef::Busy, 0 };
DBUG_RETURN(dictSignal(&tSignal,NULL,0,
- 1 /*use masternode id*/,
- 100,
+ 0 /*use masternode id*/,
WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
- -1,
- errCodes, sizeof(errCodes)/sizeof(errCodes[0])));
+ -1, 100,
+ errCodes, 0));
}
NdbEventImpl *
@@ -2768,7 +2896,7 @@ NdbDictionaryImpl::getEvent(const char * eventName)
DBUG_RETURN(NULL);
}
- if (ev->m_tableId == info->m_table_impl->m_tableId &&
+ if (ev->m_tableId == info->m_table_impl->m_id &&
ev->m_tableVersion == info->m_table_impl->m_version)
break;
if (retry)
@@ -2776,7 +2904,7 @@ NdbDictionaryImpl::getEvent(const char * eventName)
m_error.code= 241;
DBUG_PRINT("error",("%s: table version mismatch, event: [%u,%u] table: [%u,%u]",
ev->getTableName(), ev->m_tableId, ev->m_tableVersion,
- info->m_table_impl->m_tableId, info->m_table_impl->m_version));
+ info->m_table_impl->m_id, info->m_table_impl->m_version));
delete ev;
DBUG_RETURN(NULL);
}
@@ -2793,7 +2921,7 @@ NdbDictionaryImpl::getEvent(const char * eventName)
AttributeMask & mask = ev->m_attrListBitmask;
unsigned attributeList_sz = mask.count();
- DBUG_PRINT("info",("Table: id: %d version: %d", table.m_tableId, table.m_version));
+ DBUG_PRINT("info",("Table: id: %d version: %d", table.m_id, table.m_version));
#ifndef DBUG_OFF
char buf[128] = {0};
@@ -2994,21 +3122,14 @@ NdbDictInterface::dropEvent(const NdbEventImpl &evnt)
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = (m_buffer.length()+3) >> 2;
- return dropEvent(&tSignal, ptr, 1);
-}
-
-int
-NdbDictInterface::dropEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLSP)
-{
//TODO
- return dictSignal(signal,ptr,noLSP,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- NULL,0, -1);
+ return dictSignal(&tSignal,ptr, 1,
+ 0 /*use masternode id*/,
+ WAIT_CREATE_INDX_REQ,
+ -1, 100,
+ 0, 0);
}
+
void
NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
@@ -3259,9 +3380,568 @@ NdbDictInterface::execWAIT_GCP_REF(NdbApiSignal* signal,
m_waiter.signal(NO_WAIT);
}
+NdbFilegroupImpl::NdbFilegroupImpl(NdbDictionary::Object::Type t)
+ : NdbDictObjectImpl(t)
+{
+ m_extent_size = 0;
+ m_undo_buffer_size = 0;
+ m_logfile_group_id = ~0;
+ m_logfile_group_version = ~0;
+}
+
+NdbTablespaceImpl::NdbTablespaceImpl() :
+ NdbDictionary::Tablespace(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(this)
+{
+}
+
+NdbTablespaceImpl::NdbTablespaceImpl(NdbDictionary::Tablespace & f) :
+ NdbDictionary::Tablespace(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(&f)
+{
+}
+
+NdbTablespaceImpl::~NdbTablespaceImpl(){
+}
+
+NdbLogfileGroupImpl::NdbLogfileGroupImpl() :
+ NdbDictionary::LogfileGroup(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(this)
+{
+}
+
+NdbLogfileGroupImpl::NdbLogfileGroupImpl(NdbDictionary::LogfileGroup & f) :
+ NdbDictionary::LogfileGroup(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(&f)
+{
+}
+
+NdbLogfileGroupImpl::~NdbLogfileGroupImpl(){
+}
+
+NdbFileImpl::NdbFileImpl(NdbDictionary::Object::Type t)
+ : NdbDictObjectImpl(t)
+{
+ m_size = 0;
+ m_free = 0;
+ m_filegroup_id = ~0;
+ m_filegroup_version = ~0;
+}
+
+NdbDatafileImpl::NdbDatafileImpl() :
+ NdbDictionary::Datafile(* this),
+ NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(this)
+{
+}
+
+NdbDatafileImpl::NdbDatafileImpl(NdbDictionary::Datafile & f) :
+ NdbDictionary::Datafile(* this),
+ NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(&f)
+{
+}
+
+NdbDatafileImpl::~NdbDatafileImpl(){
+}
+
+NdbUndofileImpl::NdbUndofileImpl() :
+ NdbDictionary::Undofile(* this),
+ NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(this)
+{
+}
+
+NdbUndofileImpl::NdbUndofileImpl(NdbDictionary::Undofile & f) :
+ NdbDictionary::Undofile(* this),
+ NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(&f)
+{
+}
+
+NdbUndofileImpl::~NdbUndofileImpl(){
+}
+
+int
+NdbDictionaryImpl::createDatafile(const NdbDatafileImpl & file, bool force){
+ DBUG_ENTER("NdbDictionaryImpl::createDatafile");
+ NdbFilegroupImpl tmp(NdbDictionary::Object::Tablespace);
+ if(file.m_filegroup_version != ~(Uint32)0){
+ tmp.m_id = file.m_filegroup_id;
+ tmp.m_version = file.m_filegroup_version;
+ DBUG_RETURN(m_receiver.create_file(file, tmp));
+ }
+
+
+ if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::Tablespace,
+ file.m_filegroup_name.c_str()) == 0){
+ DBUG_RETURN(m_receiver.create_file(file, tmp, force));
+ }
+ DBUG_RETURN(-1);
+}
+
+int
+NdbDictionaryImpl::dropDatafile(const NdbDatafileImpl & file){
+ return m_receiver.drop_file(file);
+}
+
+int
+NdbDictionaryImpl::createUndofile(const NdbUndofileImpl & file, bool force){
+ DBUG_ENTER("NdbDictionaryImpl::createUndofile");
+ NdbFilegroupImpl tmp(NdbDictionary::Object::LogfileGroup);
+ if(file.m_filegroup_version != ~(Uint32)0){
+ tmp.m_id = file.m_filegroup_id;
+ tmp.m_version = file.m_filegroup_version;
+ DBUG_RETURN(m_receiver.create_file(file, tmp));
+ }
+
+
+ if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
+ file.m_filegroup_name.c_str()) == 0){
+ DBUG_RETURN(m_receiver.create_file(file, tmp, force));
+ }
+ DBUG_PRINT("info", ("Failed to find filegroup"));
+ DBUG_RETURN(-1);
+}
+
+int
+NdbDictionaryImpl::dropUndofile(const NdbUndofileImpl & file){
+ return m_receiver.drop_file(file);
+}
+
+int
+NdbDictionaryImpl::createTablespace(const NdbTablespaceImpl & fg){
+ return m_receiver.create_filegroup(fg);
+}
+
+int
+NdbDictionaryImpl::dropTablespace(const NdbTablespaceImpl & fg){
+ return m_receiver.drop_filegroup(fg);
+}
+
+int
+NdbDictionaryImpl::createLogfileGroup(const NdbLogfileGroupImpl & fg){
+ return m_receiver.create_filegroup(fg);
+}
+
+int
+NdbDictionaryImpl::dropLogfileGroup(const NdbLogfileGroupImpl & fg){
+ return m_receiver.drop_filegroup(fg);
+}
+
+int
+NdbDictInterface::create_file(const NdbFileImpl & file,
+ const NdbFilegroupImpl & group,
+ bool overwrite){
+ DBUG_ENTER("NdbDictInterface::create_file");
+ UtilBufferWriter w(m_buffer);
+ DictFilegroupInfo::File f; f.init();
+ snprintf(f.FileName, sizeof(f.FileName), file.m_path.c_str());
+ f.FileType = file.m_type;
+ f.FilegroupId = group.m_id;
+ f.FilegroupVersion = group.m_version;
+ f.FileSizeHi = (file.m_size >> 32);
+ f.FileSizeLo = (file.m_size & 0xFFFFFFFF);
+
+ SimpleProperties::UnpackStatus s;
+ s = SimpleProperties::pack(w,
+ &f,
+ DictFilegroupInfo::FileMapping,
+ DictFilegroupInfo::FileMappingSize, true);
+
+ if(s != SimpleProperties::Eof){
+ abort();
+ }
+
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_CREATE_FILE_REQ;
+ tSignal.theLength = CreateFileReq::SignalLength;
+
+ CreateFileReq* req = CAST_PTR(CreateFileReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->objType = file.m_type;
+ req->requestInfo = 0;
+ if (overwrite)
+ req->requestInfo |= CreateFileReq::ForceCreateFile;
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ ptr[0].sz = m_buffer.length() / 4;
+
+ int err[] = { CreateFileRef::Busy, 0};
+ /*
+ Send signal without time-out since creating files can take a very long
+ time if the file is very big.
+ */
+ DBUG_RETURN(dictSignal(&tSignal, ptr, 1,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ -1, 100,
+ err));
+}
+
+void
+NdbDictInterface::execCREATE_FILE_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execCREATE_FILE_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const CreateFileRef* ref =
+ CAST_CONSTPTR(CreateFileRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+int
+NdbDictInterface::drop_file(const NdbFileImpl & file){
+ DBUG_ENTER("NdbDictInterface::drop_file");
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_DROP_FILE_REQ;
+ tSignal.theLength = DropFileReq::SignalLength;
+
+ DropFileReq* req = CAST_PTR(DropFileReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->file_id = file.m_id;
+ req->file_version = file.m_version;
+
+ int err[] = { DropFileRef::Busy, 0};
+ DBUG_RETURN(dictSignal(&tSignal, 0, 0,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ err));
+}
+
+void
+NdbDictInterface::execDROP_FILE_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execDROP_FILE_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const DropFileRef* ref =
+ CAST_CONSTPTR(DropFileRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+int
+NdbDictInterface::create_filegroup(const NdbFilegroupImpl & group){
+ DBUG_ENTER("NdbDictInterface::create_filegroup");
+ UtilBufferWriter w(m_buffer);
+ DictFilegroupInfo::Filegroup fg; fg.init();
+ snprintf(fg.FilegroupName, sizeof(fg.FilegroupName), group.m_name.c_str());
+ switch(group.m_type){
+ case NdbDictionary::Object::Tablespace:
+ {
+ fg.FilegroupType = DictTabInfo::Tablespace;
+ //fg.TS_DataGrow = group.m_grow_spec;
+ fg.TS_ExtentSize = group.m_extent_size;
+
+ if(group.m_logfile_group_version != ~(Uint32)0)
+ {
+ fg.TS_LogfileGroupId = group.m_logfile_group_id;
+ fg.TS_LogfileGroupVersion = group.m_logfile_group_version;
+ }
+ else
+ {
+ NdbLogfileGroupImpl tmp;
+ if(get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
+ group.m_logfile_group_name.c_str()) == 0)
+ {
+ fg.TS_LogfileGroupId = tmp.m_id;
+ fg.TS_LogfileGroupVersion = tmp.m_version;
+ }
+ else // error set by get filegroup
+ {
+ DBUG_RETURN(-1);
+ }
+ }
+ }
+ break;
+ case NdbDictionary::Object::LogfileGroup:
+ fg.LF_UndoBufferSize = group.m_undo_buffer_size;
+ fg.FilegroupType = DictTabInfo::LogfileGroup;
+ //fg.LF_UndoGrow = group.m_grow_spec;
+ break;
+ default:
+ abort();
+ DBUG_RETURN(-1);
+ };
+
+ SimpleProperties::UnpackStatus s;
+ s = SimpleProperties::pack(w,
+ &fg,
+ DictFilegroupInfo::Mapping,
+ DictFilegroupInfo::MappingSize, true);
+
+ if(s != SimpleProperties::Eof){
+ abort();
+ }
+
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_CREATE_FILEGROUP_REQ;
+ tSignal.theLength = CreateFilegroupReq::SignalLength;
+
+ CreateFilegroupReq* req =
+ CAST_PTR(CreateFilegroupReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->objType = fg.FilegroupType;
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ ptr[0].sz = m_buffer.length() / 4;
+
+ int err[] = { CreateFilegroupRef::Busy, CreateFilegroupRef::NotMaster, 0};
+ DBUG_RETURN(dictSignal(&tSignal, ptr, 1,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ err));
+}
+
+void
+NdbDictInterface::execCREATE_FILEGROUP_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execCREATE_FILEGROUP_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const CreateFilegroupRef* ref =
+ CAST_CONSTPTR(CreateFilegroupRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+int
+NdbDictInterface::drop_filegroup(const NdbFilegroupImpl & group){
+ DBUG_ENTER("NdbDictInterface::drop_filegroup");
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_DROP_FILEGROUP_REQ;
+ tSignal.theLength = DropFilegroupReq::SignalLength;
+
+ DropFilegroupReq* req = CAST_PTR(DropFilegroupReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->filegroup_id = group.m_id;
+ req->filegroup_version = group.m_version;
+
+ int err[] = { DropFilegroupRef::Busy, DropFilegroupRef::NotMaster, 0};
+ DBUG_RETURN(dictSignal(&tSignal, 0, 0,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100,
+ err));
+}
+
+void
+NdbDictInterface::execDROP_FILEGROUP_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execDROP_FILEGROUP_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const DropFilegroupRef* ref =
+ CAST_CONSTPTR(DropFilegroupRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+
+int
+NdbDictInterface::get_filegroup(NdbFilegroupImpl & dst,
+ NdbDictionary::Object::Type type,
+ const char * name){
+ DBUG_ENTER("NdbDictInterface::get_filegroup");
+ NdbApiSignal tSignal(m_reference);
+ GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
+ size_t strLen = strlen(name) + 1;
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestType =
+ GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
+ req->tableNameLen = strLen;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
+ tSignal.theLength = GetTabInfoReq::SignalLength;
+
+ LinearSectionPtr ptr[1];
+ ptr[0].p = (Uint32*)name;
+ ptr[0].sz = (strLen + 3)/4;
+
+ int r = dictSignal(&tSignal, ptr, 1,
+ -1, // any node
+ WAIT_GET_TAB_INFO_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100);
+ if (r)
+ {
+ DBUG_PRINT("info", ("get_filegroup failed dictSignal"));
+ DBUG_RETURN(-1);
+ }
+
+ m_error.code = parseFilegroupInfo(dst,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4);
+
+ if(m_error.code)
+ {
+ DBUG_PRINT("info", ("get_filegroup failed parseFilegroupInfo %d",
+ m_error.code));
+ DBUG_RETURN(m_error.code);
+ }
+
+ if(dst.m_type == type)
+ {
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("info", ("get_filegroup failed no such filegroup"));
+ DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
+}
+
+int
+NdbDictInterface::parseFilegroupInfo(NdbFilegroupImpl &dst,
+ const Uint32 * data, Uint32 len)
+
+{
+ SimplePropertiesLinearReader it(data, len);
+
+ SimpleProperties::UnpackStatus status;
+ DictFilegroupInfo::Filegroup fg; fg.init();
+ status = SimpleProperties::unpack(it, &fg,
+ DictFilegroupInfo::Mapping,
+ DictFilegroupInfo::MappingSize,
+ true, true);
+
+ if(status != SimpleProperties::Eof){
+ return CreateFilegroupRef::InvalidFormat;
+ }
+
+ dst.m_id = fg.FilegroupId;
+ dst.m_version = fg.FilegroupVersion;
+ dst.m_type = (NdbDictionary::Object::Type)fg.FilegroupType;
+ dst.m_status = NdbDictionary::Object::Retrieved;
+
+ dst.m_name.assign(fg.FilegroupName);
+ dst.m_extent_size = fg.TS_ExtentSize;
+ dst.m_undo_buffer_size = fg.LF_UndoBufferSize;
+ dst.m_logfile_group_id = fg.TS_LogfileGroupId;
+ dst.m_logfile_group_version = fg.TS_LogfileGroupVersion;
+ return 0;
+}
+
+int
+NdbDictInterface::get_file(NdbFileImpl & dst,
+ NdbDictionary::Object::Type type,
+ int node,
+ const char * name){
+ DBUG_ENTER("NdbDictInterface::get_file");
+ NdbApiSignal tSignal(m_reference);
+ GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
+ size_t strLen = strlen(name) + 1;
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestType =
+ GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
+ req->tableNameLen = strLen;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
+ tSignal.theLength = GetTabInfoReq::SignalLength;
+
+ LinearSectionPtr ptr[1];
+ ptr[0].p = (Uint32*)name;
+ ptr[0].sz = (strLen + 3)/4;
+
+ int r = dictSignal(&tSignal, ptr, 1,
+ node,
+ WAIT_GET_TAB_INFO_REQ,
+ WAITFOR_RESPONSE_TIMEOUT, 100);
+ if (r)
+ {
+ DBUG_PRINT("info", ("get_file failed dictSignal"));
+ DBUG_RETURN(-1);
+ }
+
+ m_error.code = parseFileInfo(dst,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4);
+
+ if(m_error.code)
+ {
+ DBUG_PRINT("info", ("get_file failed parseFileInfo %d",
+ m_error.code));
+ DBUG_RETURN(m_error.code);
+ }
+
+ if(dst.m_type == type)
+ {
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("info", ("get_file failed no such file"));
+ DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
+}
+
+int
+NdbDictInterface::parseFileInfo(NdbFileImpl &dst,
+ const Uint32 * data, Uint32 len)
+{
+ SimplePropertiesLinearReader it(data, len);
+
+ SimpleProperties::UnpackStatus status;
+ DictFilegroupInfo::File f; f.init();
+ status = SimpleProperties::unpack(it, &f,
+ DictFilegroupInfo::FileMapping,
+ DictFilegroupInfo::FileMappingSize,
+ true, true);
+
+ if(status != SimpleProperties::Eof){
+ return CreateFilegroupRef::InvalidFormat;
+ }
+
+ dst.m_type= (NdbDictionary::Object::Type)f.FileType;
+ dst.m_id= f.FileNo;
+
+ dst.m_size= ((Uint64)f.FileSizeHi << 32) | (f.FileSizeLo);
+ dst.m_free= f.FileFreeExtents;
+ dst.m_path.assign(f.FileName);
+ //dst.m_filegroup_name
+ dst.m_filegroup_id= f.FilegroupId;
+ dst.m_filegroup_version= f.FilegroupVersion;
+
+ return 0;
+}
+
template class Vector<int>;
template class Vector<Uint16>;
template class Vector<Uint32>;
template class Vector<Vector<Uint32> >;
template class Vector<NdbTableImpl*>;
template class Vector<NdbColumnImpl*>;
+
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 575de7fb425..0e03fe80ecd 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -32,13 +32,17 @@
class NdbDictObjectImpl {
public:
+ int m_id;
Uint32 m_version;
+ NdbDictionary::Object::Type m_type;
NdbDictionary::Object::Status m_status;
bool change();
protected:
- NdbDictObjectImpl() :
+ NdbDictObjectImpl(NdbDictionary::Object::Type type) :
+ m_type(type),
m_status(NdbDictionary::Object::New) {
+ m_id = -1;
}
};
@@ -59,10 +63,15 @@ public:
int m_precision;
int m_scale;
int m_length;
+ int m_column_no;
CHARSET_INFO * m_cs; // not const in MySQL
bool m_pk;
- bool m_distributionKey;
+ /*
+ * Since "none" is "all" we distinguish between
+ * 1-set by us, 2-set by user
+ */
+ Uint32 m_distributionKey;
bool m_nullable;
bool m_autoIncrement;
Uint64 m_autoIncrementInitialValue;
@@ -73,7 +82,13 @@ public:
* Internal types and sizes, and aggregates
*/
Uint32 m_attrSize; // element size (size when arraySize==1)
- Uint32 m_arraySize; // length or length+2 for Var* types
+ Uint32 m_arraySize; // length or maxlength+1/2 for Var* types
+ Uint32 m_arrayType; // NDB_ARRAYTYPE_FIXED or _VAR
+ Uint32 m_storageType; // NDB_STORAGETYPE_MEMORY or _DISK
+ /*
+ * NdbTableImpl: if m_pk, 0-based index of key in m_attrId order
+ * NdbIndexImpl: m_column_no of primary table column
+ */
Uint32 m_keyInfoPos;
// TODO: use bits in attr desc 2
bool getInterpretableType() const ;
@@ -91,6 +106,9 @@ public:
NdbDictionary::Column * m_facade;
static NdbDictionary::Column * create_pseudo(const char *);
+
+ // Get total length in bytes, used by NdbOperation
+ bool get_var_length(const void* value, Uint32& len) const;
};
class NdbTableImpl : public NdbDictionary::Table, public NdbDictObjectImpl {
@@ -102,17 +120,20 @@ public:
void init();
void setName(const char * name);
const char * getName() const;
+ void setFrm(const void* data, Uint32 len);
+ const void * getFrmData() const;
+ Uint32 getFrmLength() const;
const char * getMysqlName() const;
void updateMysqlName();
Uint32 m_changeMask;
- Uint32 m_tableId;
Uint32 m_primaryTableId;
BaseString m_internalName;
BaseString m_externalName;
BaseString m_mysqlName;
BaseString m_newExternalName; // Used for alter table
UtilBuffer m_frm;
+ UtilBuffer m_newFrm; // Used for alter table
UtilBuffer m_ng;
NdbDictionary::Object::FragmentType m_fragmentType;
@@ -122,6 +143,7 @@ public:
Uint32 m_columnHashMask;
Vector<Uint32> m_columnHash;
Vector<NdbColumnImpl *> m_columns;
+ void computeAggregates();
void buildColumnHash();
/**
@@ -149,12 +171,13 @@ public:
* Index only stuff
*/
BaseString m_primaryTable;
- NdbDictionary::Index::Type m_indexType;
+ NdbDictionary::Object::Type m_indexType;
/**
* Aggregates
*/
Uint8 m_noOfKeys;
+ // if all pk = dk then this is zero!
Uint8 m_noOfDistributionKeys;
Uint8 m_noOfBlobs;
@@ -174,6 +197,13 @@ public:
* Return count
*/
Uint32 get_nodes(Uint32 hashValue, const Uint16** nodes) const ;
+
+ /**
+ * Disk stuff
+ */
+ BaseString m_tablespace_name;
+ Uint32 m_tablespace_id;
+ Uint32 m_tablespace_version;
};
class NdbIndexImpl : public NdbDictionary::Index, public NdbDictObjectImpl {
@@ -189,13 +219,11 @@ public:
const char * getTable() const;
const NdbTableImpl * getIndexTable() const;
- Uint32 m_indexId;
BaseString m_internalName;
BaseString m_externalName;
BaseString m_tableName;
Vector<NdbColumnImpl *> m_columns;
Vector<int> m_key_ids;
- NdbDictionary::Index::Type m_type;
bool m_logging;
@@ -250,6 +278,79 @@ public:
NdbDictionary::Event * m_facade;
};
+struct NdbFilegroupImpl : public NdbDictObjectImpl {
+ NdbFilegroupImpl(NdbDictionary::Object::Type t);
+
+ BaseString m_name;
+ NdbDictionary::AutoGrowSpecification m_grow_spec;
+
+ union {
+ Uint32 m_extent_size;
+ Uint32 m_undo_buffer_size;
+ };
+
+ BaseString m_logfile_group_name;
+ Uint32 m_logfile_group_id;
+ Uint32 m_logfile_group_version;
+};
+
+class NdbTablespaceImpl : public NdbDictionary::Tablespace,
+ public NdbFilegroupImpl {
+public:
+ NdbTablespaceImpl();
+ NdbTablespaceImpl(NdbDictionary::Tablespace &);
+ ~NdbTablespaceImpl();
+
+ static NdbTablespaceImpl & getImpl(NdbDictionary::Tablespace & t);
+ static const NdbTablespaceImpl & getImpl(const NdbDictionary::Tablespace &);
+ NdbDictionary::Tablespace * m_facade;
+};
+
+class NdbLogfileGroupImpl : public NdbDictionary::LogfileGroup,
+ public NdbFilegroupImpl {
+public:
+ NdbLogfileGroupImpl();
+ NdbLogfileGroupImpl(NdbDictionary::LogfileGroup &);
+ ~NdbLogfileGroupImpl();
+
+ static NdbLogfileGroupImpl & getImpl(NdbDictionary::LogfileGroup & t);
+ static const NdbLogfileGroupImpl& getImpl(const
+ NdbDictionary::LogfileGroup&);
+ NdbDictionary::LogfileGroup * m_facade;
+};
+
+struct NdbFileImpl : public NdbDictObjectImpl {
+ NdbFileImpl(NdbDictionary::Object::Type t);
+
+ Uint64 m_size;
+ Uint32 m_free;
+ BaseString m_path;
+ BaseString m_filegroup_name;
+ Uint32 m_filegroup_id;
+ Uint32 m_filegroup_version;
+};
+
+class NdbDatafileImpl : public NdbDictionary::Datafile, public NdbFileImpl {
+public:
+ NdbDatafileImpl();
+ NdbDatafileImpl(NdbDictionary::Datafile &);
+ ~NdbDatafileImpl();
+
+ static NdbDatafileImpl & getImpl(NdbDictionary::Datafile & t);
+ static const NdbDatafileImpl & getImpl(const NdbDictionary::Datafile & t);
+ NdbDictionary::Datafile * m_facade;
+};
+
+class NdbUndofileImpl : public NdbDictionary::Undofile, public NdbFileImpl {
+public:
+ NdbUndofileImpl();
+ NdbUndofileImpl(NdbDictionary::Undofile &);
+ ~NdbUndofileImpl();
+
+ static NdbUndofileImpl & getImpl(NdbDictionary::Undofile & t);
+ static const NdbUndofileImpl & getImpl(const NdbDictionary::Undofile & t);
+ NdbDictionary::Undofile * m_facade;
+};
class NdbDictInterface {
public:
@@ -264,39 +365,22 @@ public:
bool setTransporter(class TransporterFacade * tf);
// To abstract the stuff thats made in all create/drop/lists below
- int
- dictSignal(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLPTR,
- const int useMasterNodeId,
- const Uint32 RETRIES,
- const WaitSignalType wst,
- const int theWait,
- const int *errcodes,
- const int noerrcodes,
- const int temporaryMask = 0);
+ int dictSignal(NdbApiSignal* signal, LinearSectionPtr ptr[3], int secs,
+ int nodeId, // -1 any, 0 = master, >1 = specified
+ WaitSignalType wst,
+ int timeout, Uint32 RETRIES,
+ const int *errcodes = 0, int temporaryMask = 0);
int createOrAlterTable(class Ndb & ndb, NdbTableImpl &, bool alter);
int createTable(class Ndb & ndb, NdbTableImpl &);
- int createTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
int alterTable(class Ndb & ndb, NdbTableImpl &);
- int alterTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
- int createIndex(class Ndb & ndb,
- NdbIndexImpl &,
- const NdbTableImpl &);
- int createIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
- int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag);
- int createEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
-
int dropTable(const NdbTableImpl &);
- int dropTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
+ int createIndex(class Ndb & ndb, const NdbIndexImpl &, const NdbTableImpl &);
int dropIndex(const NdbIndexImpl &, const NdbTableImpl &);
- int dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
+
+ int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag);
int dropEvent(const NdbEventImpl &);
int dropEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
@@ -317,10 +401,27 @@ public:
static int parseTableInfo(NdbTableImpl ** dst,
const Uint32 * data, Uint32 len,
bool fullyQualifiedNames);
+
+ static int parseFileInfo(NdbFileImpl &dst,
+ const Uint32 * data, Uint32 len);
+
+ static int parseFilegroupInfo(NdbFilegroupImpl &dst,
+ const Uint32 * data, Uint32 len);
+
+ int create_file(const NdbFileImpl &, const NdbFilegroupImpl&, bool overwrite = false);
+ int drop_file(const NdbFileImpl &);
+ int create_filegroup(const NdbFilegroupImpl &);
+ int drop_filegroup(const NdbFilegroupImpl &);
+
+ int get_filegroup(NdbFilegroupImpl&, NdbDictionary::Object::Type, int);
+ int get_filegroup(NdbFilegroupImpl&,NdbDictionary::Object::Type,const char*);
+ int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, int);
+ int get_file(NdbFileImpl&, NdbDictionary::Object::Type, int, const char *);
static int create_index_obj_from_table(NdbIndexImpl ** dst,
NdbTableImpl* index_table,
const NdbTableImpl* primary_table);
+
const NdbError &getNdbError() const;
NdbError & m_error;
private:
@@ -363,6 +464,18 @@ private:
void execDROP_TABLE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execLIST_TABLES_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execCREATE_FILE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execCREATE_FILE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
+ void execCREATE_FILEGROUP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execCREATE_FILEGROUP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
+ void execDROP_FILE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execDROP_FILE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
+ void execDROP_FILEGROUP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+ void execDROP_FILEGROUP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
+
void execWAIT_GCP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execWAIT_GCP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
@@ -380,7 +493,7 @@ public:
bool setTransporter(class TransporterFacade * tf);
int createTable(NdbTableImpl &t);
- int createBlobTables(NdbTableImpl &);
+ int createBlobTables(NdbTableImpl& org, NdbTableImpl & created);
int addBlobTables(NdbTableImpl &);
int alterTable(NdbTableImpl &t);
int dropTable(const char * name);
@@ -414,7 +527,18 @@ public:
const char * tableName);
NdbEventImpl * getEvent(const char * eventName);
NdbEventImpl * getEventImpl(const char * internalName);
-
+
+ int createDatafile(const NdbDatafileImpl &, bool force = false);
+ int dropDatafile(const NdbDatafileImpl &);
+ int createUndofile(const NdbUndofileImpl &, bool force = false);
+ int dropUndofile(const NdbUndofileImpl &);
+
+ int createTablespace(const NdbTablespaceImpl &);
+ int dropTablespace(const NdbTablespaceImpl &);
+
+ int createLogfileGroup(const NdbLogfileGroupImpl &);
+ int dropLogfileGroup(const NdbLogfileGroupImpl &);
+
const NdbError & getNdbError() const;
NdbError m_error;
Uint32 m_local_table_data_size;
@@ -493,6 +617,25 @@ NdbColumnImpl::getBlobType() const {
}
inline
+bool
+NdbColumnImpl::get_var_length(const void* value, Uint32& len) const
+{
+ Uint32 max_len = m_attrSize * m_arraySize;
+ switch (m_arrayType) {
+ case NDB_ARRAYTYPE_SHORT_VAR:
+ len = 1 + *((Uint8*)value);
+ break;
+ case NDB_ARRAYTYPE_MEDIUM_VAR:
+ len = 2 + uint2korr((char*)value);
+ break;
+ default:
+ len = max_len;
+ return true;
+ }
+ return (len <= max_len);
+}
+
+inline
NdbTableImpl &
NdbTableImpl::getImpl(NdbDictionary::Table & t){
return t.m_impl;
@@ -711,4 +854,54 @@ NdbDictionaryImpl::getIndex(const char * index_name,
return 0;
}
+inline
+NdbTablespaceImpl &
+NdbTablespaceImpl::getImpl(NdbDictionary::Tablespace & t){
+ return t.m_impl;
+}
+
+inline
+const NdbTablespaceImpl &
+NdbTablespaceImpl::getImpl(const NdbDictionary::Tablespace & t){
+ return t.m_impl;
+}
+
+inline
+NdbLogfileGroupImpl &
+NdbLogfileGroupImpl::getImpl(NdbDictionary::LogfileGroup & t){
+ return t.m_impl;
+}
+
+inline
+const NdbLogfileGroupImpl &
+NdbLogfileGroupImpl::getImpl(const NdbDictionary::LogfileGroup & t){
+ return t.m_impl;
+}
+
+inline
+NdbDatafileImpl &
+NdbDatafileImpl::getImpl(NdbDictionary::Datafile & t){
+ return t.m_impl;
+}
+
+inline
+const NdbDatafileImpl &
+NdbDatafileImpl::getImpl(const NdbDictionary::Datafile & t){
+ return t.m_impl;
+}
+
+inline
+NdbUndofileImpl &
+NdbUndofileImpl::getImpl(NdbDictionary::Undofile & t){
+ return t.m_impl;
+}
+
+inline
+const NdbUndofileImpl &
+NdbUndofileImpl::getImpl(const NdbDictionary::Undofile & t){
+ return t.m_impl;
+}
+
+
+
#endif
diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index 429e3b558d3..76352a9000c 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -371,7 +371,7 @@ NdbEventOperationImpl::receive_event()
while(tAttr)
{
assert(aAttrPtr < aAttrEndPtr);
- unsigned tDataSz= AttributeHeader(*aAttrPtr).getDataSize();
+ unsigned tDataSz= AttributeHeader(*aAttrPtr).getByteSize();
assert(tAttr->attrId() ==
AttributeHeader(*aAttrPtr).getAttributeId());
receive_data(tAttr, aDataPtr, tDataSz);
@@ -382,7 +382,7 @@ NdbEventOperationImpl::receive_event()
}
// next
aAttrPtr++;
- aDataPtr+= tDataSz;
+ aDataPtr+= (tDataSz + 3) >> 2;
tAttr= tAttr->next();
}
}
@@ -396,7 +396,7 @@ NdbEventOperationImpl::receive_event()
while ((aAttrPtr < aAttrEndPtr) && (tWorkingRecAttr != NULL)) {
tRecAttrId = tWorkingRecAttr->attrId();
tAttrId = AttributeHeader(*aAttrPtr).getAttributeId();
- tDataSz = AttributeHeader(*aAttrPtr).getDataSize();
+ tDataSz = AttributeHeader(*aAttrPtr).getByteSize();
while (tAttrId > tRecAttrId) {
DBUG_PRINT("info",("undef [%u] %u 0x%x [%u] 0x%x",
@@ -420,7 +420,7 @@ NdbEventOperationImpl::receive_event()
tWorkingRecAttr = tWorkingRecAttr->next();
}
aAttrPtr++;
- aDataPtr += tDataSz;
+ aDataPtr += (tDataSz + 3) >> 2;
}
while (tWorkingRecAttr != NULL) {
@@ -437,7 +437,7 @@ NdbEventOperationImpl::receive_event()
while ((aDataPtr < aDataEndPtr) && (tWorkingRecAttr != NULL)) {
tRecAttrId = tWorkingRecAttr->attrId();
tAttrId = AttributeHeader(*aDataPtr).getAttributeId();
- tDataSz = AttributeHeader(*aDataPtr).getDataSize();
+ tDataSz = AttributeHeader(*aDataPtr).getByteSize();
aDataPtr++;
while (tAttrId > tRecAttrId) {
tWorkingRecAttr->setUNDEFINED();
@@ -455,7 +455,7 @@ NdbEventOperationImpl::receive_event()
receive_data(tWorkingRecAttr, aDataPtr, tDataSz);
tWorkingRecAttr = tWorkingRecAttr->next();
}
- aDataPtr += tDataSz;
+ aDataPtr += (tDataSz + 3) >> 2;
}
while (tWorkingRecAttr != NULL) {
tWorkingRecAttr->setUNDEFINED();
diff --git a/storage/ndb/src/ndbapi/NdbIndexOperation.cpp b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp
index 4cedffed4a2..250af162262 100644
--- a/storage/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -208,7 +208,7 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
- Uint32 tIndexId = m_theIndex->m_indexId;
+ Uint32 tIndexId = m_theIndex->m_id;
Uint32 tSchemaVersion = m_theIndex->m_version;
tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
diff --git a/storage/ndb/src/ndbapi/NdbOperation.cpp b/storage/ndb/src/ndbapi/NdbOperation.cpp
index c9143444908..c88b3a5e6ac 100644
--- a/storage/ndb/src/ndbapi/NdbOperation.cpp
+++ b/storage/ndb/src/ndbapi/NdbOperation.cpp
@@ -161,6 +161,7 @@ NdbOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection){
theMagicNumber = 0xABCDEF01;
theBlobList = NULL;
m_abortOption = -1;
+ m_no_disk_flag = 1;
tSignal = theNdb->getSignal();
if (tSignal == NULL)
@@ -283,36 +284,28 @@ NdbOperation::getValue(const NdbDictionary::Column* col, char* aValue)
}
int
-NdbOperation::equal(const char* anAttrName,
- const char* aValuePassed,
- Uint32 aVariableKeyLen)
+NdbOperation::equal(const char* anAttrName, const char* aValuePassed)
{
- return equal_impl(m_accessTable->getColumn(anAttrName), aValuePassed, aVariableKeyLen);
+ return equal_impl(m_accessTable->getColumn(anAttrName), aValuePassed);
}
int
-NdbOperation::equal(Uint32 anAttrId,
- const char* aValuePassed,
- Uint32 aVariableKeyLen)
+NdbOperation::equal(Uint32 anAttrId, const char* aValuePassed)
{
- return equal_impl(m_accessTable->getColumn(anAttrId), aValuePassed, aVariableKeyLen);
+ return equal_impl(m_accessTable->getColumn(anAttrId), aValuePassed);
}
int
-NdbOperation::setValue( const char* anAttrName,
- const char* aValuePassed,
- Uint32 len)
+NdbOperation::setValue(const char* anAttrName, const char* aValuePassed)
{
- return setValue(m_currentTable->getColumn(anAttrName), aValuePassed, len);
+ return setValue(m_currentTable->getColumn(anAttrName), aValuePassed);
}
int
-NdbOperation::setValue( Uint32 anAttrId,
- const char* aValuePassed,
- Uint32 len)
+NdbOperation::setValue(Uint32 anAttrId, const char* aValuePassed)
{
- return setValue(m_currentTable->getColumn(anAttrId), aValuePassed, len);
+ return setValue(m_currentTable->getColumn(anAttrId), aValuePassed);
}
NdbBlob*
diff --git a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp
index 6c417860464..6915a91dd12 100644
--- a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -340,6 +340,7 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
NdbRecAttr* tRecAttr;
if ((tAttrInfo != NULL) &&
(theStatus != Init)){
+ m_no_disk_flag &= (tAttrInfo->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
if (theStatus != GetValue) {
if (theInterpretIndicator == 1) {
if (theStatus == FinalGetValue) {
@@ -404,15 +405,12 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
******************************************************************************/
int
NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
- const char* aValuePassed, Uint32 len)
+ const char* aValuePassed)
{
DBUG_ENTER("NdbOperation::setValue");
- DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
- tAttrInfo->m_name.c_str(),
- theOperationType,
- aValuePassed, len));
- if (aValuePassed != NULL)
- DBUG_DUMP("value", (char*)aValuePassed, len);
+ DBUG_PRINT("enter", ("col=%s op=%d val=%p",
+ tAttrInfo->m_name.c_str(), theOperationType,
+ aValuePassed));
int tReturnCode;
Uint32 tAttrId;
@@ -483,18 +481,16 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
}//if
if (tAttrInfo->m_pk) {
if (theOperationType == InsertRequest) {
- DBUG_RETURN(equal_impl(tAttrInfo, aValuePassed, len));
+ DBUG_RETURN(equal_impl(tAttrInfo, aValuePassed));
} else {
setErrorCodeAbort(4202);
DBUG_RETURN(-1);
}//if
}//if
- if (len > 8000) {
- setErrorCodeAbort(4216);
- DBUG_RETURN(-1);
- }//if
+ // Insert Attribute Id into ATTRINFO part.
tAttrId = tAttrInfo->m_attrId;
+ m_no_disk_flag &= (tAttrInfo->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
const char *aValue = aValuePassed;
Uint32 ahValue;
if (aValue == NULL) {
@@ -514,36 +510,15 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
}//if
}//if
- // Insert Attribute Id into ATTRINFO part.
- const Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
-
-#if 0
- tAttrSize = tAttrInfo->theAttrSize;
- tArraySize = tAttrInfo->theArraySize;
- if (tArraySize == 0) {
- setErrorCodeAbort(4201);
- return -1;
- }//if
- tAttrSizeInBits = tAttrSize*tArraySize;
- tAttrSizeInWords = tAttrSizeInBits >> 5;
-#endif
- const Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
- if (len != sizeInBytes && (len != 0)) {
+ Uint32 len;
+ if (! tAttrInfo->get_var_length(aValue, len)) {
setErrorCodeAbort(4209);
DBUG_RETURN(-1);
- }//if
- const Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Including bits in last word
- const Uint32 sizeInWords = sizeInBytes / 4; // Excluding bits in last word
- AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId,
- totalSizeInWords << 2);
- insertATTRINFO( ahValue );
+ }
- /***********************************************************************
- * Check if the pointer of the value passed is aligned on a 4 byte boundary.
- * If so only assign the pointer to the internal variable aValue.
- * If it is not aligned then we start by copying the value to tempData and
- * use this as aValue instead.
- *************************************************************************/
+ const Uint32 sizeInBytes = len;
+ const Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
+
const int attributeSize = sizeInBytes;
const int slack = sizeInBytes & 3;
@@ -556,6 +531,20 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
}//if
}//if
+ // Including bits in last word
+ const Uint32 totalSizeInWords = (sizeInBytes + 3)/4;
+ // Excluding bits in last word
+ const Uint32 sizeInWords = sizeInBytes / 4;
+ AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, sizeInBytes);
+ insertATTRINFO( ahValue );
+
+ /***********************************************************************
+ * Check if the pointer of the value passed is aligned on a 4 byte boundary.
+ * If so only assign the pointer to the internal variable aValue.
+ * If it is not aligned then we start by copying the value to tempData and
+ * use this as aValue instead.
+ *************************************************************************/
+
tReturnCode = insertATTRINFOloop((Uint32*)aValue, sizeInWords);
if (tReturnCode == -1) {
DBUG_RETURN(tReturnCode);
@@ -572,6 +561,10 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
}//if
theErrorLine++;
DBUG_RETURN(0);
+
+error:
+ setErrorCodeAbort(tReturnCode);
+ DBUG_RETURN(-1);
}//NdbOperation::setValue()
NdbBlob*
diff --git a/storage/ndb/src/ndbapi/NdbOperationExec.cpp b/storage/ndb/src/ndbapi/NdbOperationExec.cpp
index 58a816e3c1a..5e6945c4ae0 100644
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -148,7 +148,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
//-------------------------------------------------------------
TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
- Uint32 tTableId = m_currentTable->m_tableId;
+ Uint32 tTableId = m_currentTable->m_id;
Uint32 tSchemaVersion = m_currentTable->m_version;
tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
@@ -172,6 +172,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
Uint8 tCommitIndicator = theCommitIndicator;
Uint8 tStartIndicator = theStartIndicator;
Uint8 tInterpretIndicator = theInterpretIndicator;
+ Uint8 tNoDisk = m_no_disk_flag;
//-------------------------------------------------------------
// Simple state is set if start and commit is set and it is
@@ -194,6 +195,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
+ tcKeyReq->setNoDiskFlag(tReqInfo, tNoDisk);
OperationType tOperationType = theOperationType;
Uint32 tTupKeyLen = theTupKeyLen;
diff --git a/storage/ndb/src/ndbapi/NdbOperationInt.cpp b/storage/ndb/src/ndbapi/NdbOperationInt.cpp
index 41e0cb1d140..e33e8b09dca 100644
--- a/storage/ndb/src/ndbapi/NdbOperationInt.cpp
+++ b/storage/ndb/src/ndbapi/NdbOperationInt.cpp
@@ -81,6 +81,8 @@ NdbOperation::incCheck(const NdbColumnImpl* tNdbColumnImpl)
setErrorCodeAbort(4231);
return -1;
}
+ m_no_disk_flag &=
+ (tNdbColumnImpl->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
return tNdbColumnImpl->m_attrId;
} else {
if (theNdbCon->theCommitStatus == NdbTransaction::Started)
@@ -133,6 +135,8 @@ NdbOperation::write_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
setErrorCodeAbort(4231);
return -1;
}
+ m_no_disk_flag &=
+ (tNdbColumnImpl->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
return tNdbColumnImpl->m_attrId;
} else {
if (theNdbCon->theCommitStatus == NdbTransaction::Started)
@@ -181,6 +185,8 @@ NdbOperation::read_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
setErrorCodeAbort(4231);
return -1;
}
+ m_no_disk_flag &=
+ (tNdbColumnImpl->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
return tNdbColumnImpl->m_attrId;
} else {
if (theNdbCon->theCommitStatus == NdbTransaction::Started)
@@ -1047,6 +1053,8 @@ NdbOperation::branch_col(Uint32 type,
}
}
+ m_no_disk_flag &= (col->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
+
Uint32 tempData[2000];
if (((UintPtr)val & 3) != 0) {
memcpy(tempData, val, len);
@@ -1059,7 +1067,7 @@ NdbOperation::branch_col(Uint32 type,
if (insertBranch(Label) == -1)
DBUG_RETURN(-1);
- if (insertATTRINFO(Interpreter::BranchCol_2(ColId, len)))
+ if (insertATTRINFO(Interpreter::BranchCol_2(col->m_attrId, len)))
DBUG_RETURN(-1);
Uint32 len2 = Interpreter::mod4(len);
@@ -1144,8 +1152,11 @@ NdbOperation::branch_col_null(Uint32 type, Uint32 ColId, Uint32 Label){
if (insertBranch(Label) == -1)
return -1;
+
+ Uint32 attrId=
+ NdbColumnImpl::getImpl(* m_currentTable->getColumn(ColId)).m_attrId;
- if (insertATTRINFO(Interpreter::BranchCol_2(ColId)))
+ if (insertATTRINFO(Interpreter::BranchCol_2(attrId)))
return -1;
theErrorLine++;
diff --git a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp
index 058198e9887..f2d0d1079a0 100644
--- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -54,21 +54,14 @@ Remark: Defines search condition with equality anAttrName.
******************************************************************************/
int
NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
- const char* aValuePassed,
- Uint32 aVariableKeyLen)
+ const char* aValuePassed)
{
DBUG_ENTER("NdbOperation::equal_impl");
- DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
- tAttrInfo->m_name.c_str(),
- theOperationType,
- aValuePassed, aVariableKeyLen));
- if (aValuePassed != NULL)
- DBUG_DUMP("value", (char*)aValuePassed, aVariableKeyLen);
+ DBUG_PRINT("enter", ("col=%s op=%d val=%p",
+ tAttrInfo->m_name.c_str(), theOperationType,
+ aValuePassed));
- register Uint32 tAttrId;
-
Uint32 tData;
- Uint32 tKeyInfoPosition;
const char* aValue = aValuePassed;
Uint64 tempData[512];
@@ -83,10 +76,21 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
* Finally check if all tuple key attributes have been defined. If
* this is true then set Operation state to tuple key defined.
*****************************************************************************/
- tAttrId = tAttrInfo->m_attrId;
- tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
- bool tDistrKey = tAttrInfo->m_distributionKey;
+ /*
+ * For each call theTupleKeyDefined stores 3 items:
+ *
+ * [0] = m_column_no (external column id)
+ * [1] = 1-based index of first word of accumulating keyinfo
+ * [2] = number of words of keyinfo
+ *
+ * This is used to re-order keyinfo if not in m_attrId order.
+ *
+ * Note: No point to "clean up" this code. The upcoming
+ * record-based ndb api makes it obsolete.
+ */
+
+ Uint32 tAttrId = tAttrInfo->m_column_no; // not m_attrId;
Uint32 i = 0;
if (tAttrInfo->m_pk) {
Uint32 tKeyDefined = theTupleKeyDefined[0][2];
@@ -124,12 +128,17 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
* We have to retrieve the size of the attribute in words and bits.
*************************************************************************/
keyEntryFound:
+ Uint32 sizeInBytes;
+ if (! tAttrInfo->get_var_length(aValue, sizeInBytes)) {
+ setErrorCodeAbort(4209);
+ DBUG_RETURN(-1);
+ }
+
+ Uint32 tKeyInfoPosition =
+ i == 0 ? 1 : theTupleKeyDefined[i-1][1] + theTupleKeyDefined[i-1][2];
theTupleKeyDefined[i][0] = tAttrId;
theTupleKeyDefined[i][1] = tKeyInfoPosition;
- theTupleKeyDefined[i][2] = true;
-
- OperationType tOpType = theOperationType;
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ theTupleKeyDefined[i][2] = (sizeInBytes + 3) / 4;
{
/************************************************************************
@@ -138,6 +147,7 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
* aValue. If it is not aligned then we start by copying the value to
* tempData and use this as aValue instead.
***********************************************************************/
+ const bool tDistrKey = tAttrInfo->m_distributionKey;
const int attributeSize = sizeInBytes;
const int slack = sizeInBytes & 3;
const int align = UintPtr(aValue) & 7;
@@ -151,18 +161,7 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
}
Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Inc. bits in last word
-
- if (true){ //tArraySize != 0) {
- Uint32 tTupKeyLen = theTupKeyLen;
-
- theTupKeyLen = tTupKeyLen + totalSizeInWords;
- if ((aVariableKeyLen == sizeInBytes) ||
- (aVariableKeyLen == 0)) {
- ;
- } else {
- goto equal_error3;
- }
- }
+ theTupKeyLen += totalSizeInWords;
#if 0
else {
/************************************************************************
@@ -191,26 +190,25 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
* we also set the value in the stored part through putting the
* information in the ATTRINFO signals.
*************************************************************************/
+ OperationType tOpType = theOperationType;
if ((tOpType == InsertRequest) ||
(tOpType == WriteRequest)) {
Uint32 ahValue;
- const Uint32 sz = totalSizeInWords;
- // XXX
- if(m_accessTable == m_currentTable)
- {
- AttributeHeader::init(&ahValue, tAttrId, sz << 2);
- }
- else
- {
- assert(m_accessTable->m_index);
- int attr_id_current_table =
+ if(m_accessTable == m_currentTable) {
+ AttributeHeader::init(&ahValue, tAttrInfo->m_attrId, sizeInBytes);
+ } else {
+ assert(tOpType == WriteRequest && m_accessTable->m_index);
+ // use attrId of primary table column
+ int column_no_current_table =
m_accessTable->m_index->m_columns[tAttrId]->m_keyInfoPos;
- AttributeHeader::init(&ahValue, attr_id_current_table, sz << 2);
+ int attr_id_current_table =
+ m_currentTable->m_columns[column_no_current_table]->m_attrId;
+ AttributeHeader::init(&ahValue, attr_id_current_table, sizeInBytes);
}
insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValue, sz);
+ insertATTRINFOloop((Uint32*)aValue, totalSizeInWords);
}//if
/**************************************************************************
@@ -231,6 +229,19 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
theErrorLine = tErrorLine;
if (tNoKeysDef == 0) {
+
+ // re-order keyinfo if not entered in order
+ if (m_accessTable->m_noOfKeys != 1) {
+ for (Uint32 i = 0; i < m_accessTable->m_noOfKeys; i++) {
+ Uint32 k = theTupleKeyDefined[i][0]; // column_no
+ if (m_accessTable->m_columns[k]->m_keyInfoPos != i) {
+ DBUG_PRINT("info", ("key disorder at %d", i));
+ reorderKEYINFO();
+ break;
+ }
+ }
+ }
+
if (tOpType == UpdateRequest) {
if (tInterpretInd == 1) {
theStatus = GetValue;
@@ -457,11 +468,43 @@ LastWordLabel:
return 0;
}
+void
+NdbOperation::reorderKEYINFO()
+{
+ Uint32 data[4000];
+ getKeyFromTCREQ(data, 4000);
+ Uint32 pos = 1;
+ Uint32 k;
+ for (k = 0; k < m_accessTable->m_noOfKeys; k++) {
+ Uint32 i;
+ for (i = 0; i < m_accessTable->m_columns.size(); i++) {
+ NdbColumnImpl* col = m_accessTable->m_columns[i];
+ if (col->m_pk && col->m_keyInfoPos == k) {
+ Uint32 j;
+ for (j = 0; j < m_accessTable->m_noOfKeys; j++) {
+ if (theTupleKeyDefined[j][0] == i) {
+ Uint32 off = theTupleKeyDefined[j][1] - 1;
+ Uint32 len = theTupleKeyDefined[j][2];
+ assert(off < 4000 && off + len <= 4000);
+ int ret = insertKEYINFO((char*)&data[off], pos, len);
+ assert(ret == 0);
+ pos += len;
+ break;
+ }
+ }
+ assert(j < m_accessTable->m_columns.size());
+ break;
+ }
+ }
+ assert(i < m_accessTable->m_columns.size());
+ }
+}
+
int
NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
{
- assert(m_accessTable != 0 && m_accessTable->m_keyLenInWords != 0);
- assert(m_accessTable->m_keyLenInWords == size);
+ assert(size >= theTupKeyLen && theTupKeyLen > 0);
+ size = theTupKeyLen;
unsigned pos = 0;
while (pos < 8 && pos < size) {
data[pos] = theKEYINFOptr[pos];
@@ -520,7 +563,20 @@ NdbOperation::handle_distribution_key(const Uint64* value, Uint32 len)
continue;
NdbColumnImpl* tAttrInfo = * cols;
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ Uint32 sizeInBytes;
+ switch(tAttrInfo->m_arrayType){
+ default:
+ case NDB_ARRAYTYPE_FIXED:
+ sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ break;
+ case NDB_ARRAYTYPE_SHORT_VAR:
+ sizeInBytes = 1 + *(char*)src;
+ break;
+ case NDB_ARRAYTYPE_MEDIUM_VAR:
+ sizeInBytes = 2 + uint2korr((char*)src);
+ break;
+ }
+
Uint32 currLen = (sizeInBytes + 3) >> 2;
if (tAttrInfo->getDistributionKey())
{
diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp
index 2245707bf65..796be2b14e9 100644
--- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -37,6 +37,7 @@ NdbRecAttr::setup(const class NdbDictionary::Column* col, char* aValue)
{
return setup(&(col->m_impl), aValue);
}
+
int
NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
{
@@ -47,12 +48,9 @@ NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
m_column = anAttrInfo;
theAttrId = anAttrInfo->m_attrId;
- theAttrSize = tAttrSize;
- theArraySize = tArraySize;
+ m_size_in_bytes = tAttrByteSize;
theValue = aValue;
- theNULLind = 0;
- m_nullable = anAttrInfo->m_nullable;
-
+
// check alignment to signal data
// a future version could check alignment per data type as well
@@ -89,7 +87,7 @@ NdbRecAttr::copyout()
char* tRef = (char*)theRef;
char* tValue = theValue;
if (tRef != tValue && tRef != NULL && tValue != NULL) {
- Uint32 n = theAttrSize * theArraySize;
+ Uint32 n = m_size_in_bytes;
while (n-- > 0) {
*tValue++ = *tRef++;
}
@@ -101,12 +99,10 @@ NdbRecAttr::clone() const {
NdbRecAttr * ret = new NdbRecAttr(0);
ret->theAttrId = theAttrId;
- ret->theNULLind = theNULLind;
- ret->theAttrSize = theAttrSize;
- ret->theArraySize = theArraySize;
+ ret->m_size_in_bytes = m_size_in_bytes;
ret->m_column = m_column;
- Uint32 n = theAttrSize * theArraySize;
+ Uint32 n = m_size_in_bytes;
if(n <= 32){
ret->theRef = (char*)&ret->theStorage[0];
ret->theStorageX = 0;
@@ -122,17 +118,19 @@ NdbRecAttr::clone() const {
bool
NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
- const Uint32 n = (theAttrSize * theArraySize + 3) >> 2;
- if(n == sz){
- theNULLind = 0;
+ const Uint32 n = m_size_in_bytes;
+ if(sz)
+ {
if(!copyoutRequired())
- memcpy(theRef, data, 4 * sz);
+ memcpy(theRef, data, sz);
else
- memcpy(theValue, data, theAttrSize * theArraySize);
- return true;
- } else if(sz == 0){
- setNULL();
+ memcpy(theValue, data, sz);
+ m_size_in_bytes= sz;
return true;
+ }
+ else
+ {
+ return setNULL();
}
return false;
}
@@ -178,7 +176,7 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
out << "[NULL]";
return out;
}
-
+
const NdbDictionary::Column* c = r.getColumn();
uint length = c->getLength();
if (length > 1)
@@ -189,196 +187,195 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
if (j > 0)
out << " ";
- switch(r.getType())
- {
- case NdbDictionary::Column::Bigunsigned:
- out << r.u_64_value();
- break;
- case NdbDictionary::Column::Bit:
- out << hex << "H'" << r.u_32_value() << dec;
- break;
- case NdbDictionary::Column::Unsigned:
- out << r.u_32_value();
- break;
- case NdbDictionary::Column::Smallunsigned:
- out << r.u_short_value();
- break;
- case NdbDictionary::Column::Tinyunsigned:
- out << (unsigned) r.u_char_value();
- break;
- case NdbDictionary::Column::Bigint:
- out << r.int64_value();
- break;
- case NdbDictionary::Column::Int:
- out << r.int32_value();
- break;
- case NdbDictionary::Column::Smallint:
- out << r.short_value();
- break;
- case NdbDictionary::Column::Tinyint:
- out << (int) r.char_value();
- break;
- case NdbDictionary::Column::Binary:
- ndbrecattr_print_string(out,"Binary",r.aRef(),r.arraySize());
- j = r.arraySize();
- break;
- case NdbDictionary::Column::Char:
- ndbrecattr_print_string(out,"Char",r.aRef(),r.arraySize());
- j = length;
- break;
- case NdbDictionary::Column::Varchar:
- {
- unsigned len = *(const unsigned char*)r.aRef();
- ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
- j = length;
- }
- break;
- case NdbDictionary::Column::Varbinary:
- {
- unsigned len = *(const unsigned char*)r.aRef();
- ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len);
- j = length;
- }
- break;
- case NdbDictionary::Column::Float:
- out << r.float_value();
- break;
- case NdbDictionary::Column::Double:
- out << r.double_value();
- break;
- case NdbDictionary::Column::Olddecimal:
- {
- short len = 1 + c->getPrecision() + (c->getScale() > 0);
- out.print("%.*s", len, r.aRef());
- }
- break;
- case NdbDictionary::Column::Olddecimalunsigned:
- {
- short len = 0 + c->getPrecision() + (c->getScale() > 0);
- out.print("%.*s", len, r.aRef());
- }
- break;
- case NdbDictionary::Column::Decimal:
- case NdbDictionary::Column::Decimalunsigned:
- goto unknown; // TODO
- break;
+ switch(r.getType()){
+ case NdbDictionary::Column::Bigunsigned:
+ out << r.u_64_value();
+ break;
+ case NdbDictionary::Column::Bit:
+ out << hex << "H'" << r.u_32_value() << dec;
+ break;
+ case NdbDictionary::Column::Unsigned:
+ out << r.u_32_value();
+ break;
+ case NdbDictionary::Column::Smallunsigned:
+ out << r.u_short_value();
+ break;
+ case NdbDictionary::Column::Tinyunsigned:
+ out << (unsigned) r.u_char_value();
+ break;
+ case NdbDictionary::Column::Bigint:
+ out << r.int64_value();
+ break;
+ case NdbDictionary::Column::Int:
+ out << r.int32_value();
+ break;
+ case NdbDictionary::Column::Smallint:
+ out << r.short_value();
+ break;
+ case NdbDictionary::Column::Tinyint:
+ out << (int) r.char_value();
+ break;
+ case NdbDictionary::Column::Binary:
+ j = r.get_size_in_bytes();
+ ndbrecattr_print_string(out,"Binary", r.aRef(), j);
+ break;
+ case NdbDictionary::Column::Char:
+ j = r.get_size_in_bytes();
+ ndbrecattr_print_string(out,"Char", r.aRef(), j);
+ break;
+ case NdbDictionary::Column::Varchar:
+ {
+ unsigned len = *(const unsigned char*)r.aRef();
+ ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
+ j = length;
+ }
+ break;
+ case NdbDictionary::Column::Varbinary:
+ {
+ unsigned len = *(const unsigned char*)r.aRef();
+ ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len);
+ j = length;
+ }
+ break;
+ case NdbDictionary::Column::Float:
+ out << r.float_value();
+ break;
+ case NdbDictionary::Column::Double:
+ out << r.double_value();
+ break;
+ case NdbDictionary::Column::Olddecimal:
+ {
+ short len = 1 + c->getPrecision() + (c->getScale() > 0);
+ out.print("%.*s", len, r.aRef());
+ }
+ break;
+ case NdbDictionary::Column::Olddecimalunsigned:
+ {
+ short len = 0 + c->getPrecision() + (c->getScale() > 0);
+ out.print("%.*s", len, r.aRef());
+ }
+ break;
+ case NdbDictionary::Column::Decimal:
+ case NdbDictionary::Column::Decimalunsigned:
+ goto unknown; // TODO
+ break;
// for dates cut-and-paste from field.cc
- case NdbDictionary::Column::Datetime:
- {
- ulonglong tmp=r.u_64_value();
- long part1,part2,part3;
- part1=(long) (tmp/LL(1000000));
- part2=(long) (tmp - (ulonglong) part1*LL(1000000));
- char buf[40];
- char* pos=(char*) buf+19;
- *pos--=0;
- *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
- *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
- *pos--= ':';
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= ':';
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) part3);
- *pos--= '/';
- *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
- *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
- *pos--= '-';
- *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
- *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
- *pos--= '-';
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
- *pos=(char) ('0'+(char) part3);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Date:
- {
- uint32 tmp=(uint32) uint3korr(r.aRef());
- int part;
- char buf[40];
- char *pos=(char*) buf+10;
- *pos--=0;
- part=(int) (tmp & 31);
- *pos--= (char) ('0'+part%10);
- *pos--= (char) ('0'+part/10);
- *pos--= '-';
- part=(int) (tmp >> 5 & 15);
- *pos--= (char) ('0'+part%10);
- *pos--= (char) ('0'+part/10);
- *pos--= '-';
- part=(int) (tmp >> 9);
- *pos--= (char) ('0'+part%10); part/=10;
- *pos--= (char) ('0'+part%10); part/=10;
- *pos--= (char) ('0'+part%10); part/=10;
- *pos= (char) ('0'+part);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Time:
- {
- long tmp=(long) sint3korr(r.aRef());
- int hour=(uint) (tmp/10000);
- int minute=(uint) (tmp/100 % 100);
- int second=(uint) (tmp % 100);
- char buf[40];
- sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Year:
- {
- uint year = 1900 + r.u_char_value();
- char buf[40];
- sprintf(buf, "%04d", year);
- out << buf;
- }
- break;
- case NdbDictionary::Column::Timestamp:
- {
- time_t time = r.u_32_value();
- out << (uint)time;
- }
- break;
- case NdbDictionary::Column::Blob:
- {
- const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
- out << h->length << ":";
- const unsigned char* p = (const unsigned char*)(h + 1);
- unsigned n = r.arraySize() - sizeof(*h);
- for (unsigned k = 0; k < n && k < h->length; k++)
- out.print("%02X", (int)p[k]);
- j = length;
- }
- break;
- case NdbDictionary::Column::Text:
- {
- const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
- out << h->length << ":";
- const unsigned char* p = (const unsigned char*)(h + 1);
- unsigned n = r.arraySize() - sizeof(*h);
- for (unsigned k = 0; k < n && k < h->length; k++)
- out.print("%c", (int)p[k]);
- j = length;
- }
- break;
- case NdbDictionary::Column::Longvarchar:
- {
- unsigned len = uint2korr(r.aRef());
- ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
- j = length;
- }
- break;
- unknown:
- default: /* no print functions for the rest, just print type */
- out << (int) r.getType();
- j = length;
- if (j > 1)
- out << " " << j << " times";
- break;
- }
+ case NdbDictionary::Column::Datetime:
+ {
+ ulonglong tmp=r.u_64_value();
+ long part1,part2,part3;
+ part1=(long) (tmp/LL(1000000));
+ part2=(long) (tmp - (ulonglong) part1*LL(1000000));
+ char buf[40];
+ char* pos=(char*) buf+19;
+ *pos--=0;
+ *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
+ *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= ':';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) part3);
+ *pos--= '/';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+ *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
+ *pos--= '-';
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+ *pos=(char) ('0'+(char) part3);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Date:
+ {
+ uint32 tmp=(uint32) uint3korr(r.aRef());
+ int part;
+ char buf[40];
+ char *pos=(char*) buf+10;
+ *pos--=0;
+ part=(int) (tmp & 31);
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
+ part=(int) (tmp >> 5 & 15);
+ *pos--= (char) ('0'+part%10);
+ *pos--= (char) ('0'+part/10);
+ *pos--= '-';
+ part=(int) (tmp >> 9);
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos--= (char) ('0'+part%10); part/=10;
+ *pos= (char) ('0'+part);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Time:
+ {
+ long tmp=(long) sint3korr(r.aRef());
+ int hour=(uint) (tmp/10000);
+ int minute=(uint) (tmp/100 % 100);
+ int second=(uint) (tmp % 100);
+ char buf[40];
+ sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Year:
+ {
+ uint year = 1900 + r.u_char_value();
+ char buf[40];
+ sprintf(buf, "%04d", year);
+ out << buf;
+ }
+ break;
+ case NdbDictionary::Column::Timestamp:
+ {
+ time_t time = r.u_32_value();
+ out << (uint)time;
+ }
+ break;
+ case NdbDictionary::Column::Blob:
+ {
+ const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
+ out << h->length << ":";
+ const unsigned char* p = (const unsigned char*)(h + 1);
+ unsigned n = r.get_size_in_bytes() - sizeof(*h);
+ for (unsigned k = 0; k < n && k < h->length; k++)
+ out.print("%02X", (int)p[k]);
+ j = length;
+ }
+ break;
+ case NdbDictionary::Column::Text:
+ {
+ const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
+ out << h->length << ":";
+ const unsigned char* p = (const unsigned char*)(h + 1);
+ unsigned n = r.get_size_in_bytes() - sizeof(*h);
+ for (unsigned k = 0; k < n && k < h->length; k++)
+ out.print("%c", (int)p[k]);
+ j = length;
+ }
+ break;
+ case NdbDictionary::Column::Longvarchar:
+ {
+ unsigned len = uint2korr(r.aRef());
+ ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
+ j = length;
+ }
+ break;
+ unknown:
+ //default: /* no print functions for the rest, just print type */
+ out << (int) r.getType();
+ j = length;
+ if (j > 1)
+ out << " " << j << " times";
+ break;
+ }
}
if (length > 1)
diff --git a/storage/ndb/src/ndbapi/NdbReceiver.cpp b/storage/ndb/src/ndbapi/NdbReceiver.cpp
index df16ae66915..95c2cf10b61 100644
--- a/storage/ndb/src/ndbapi/NdbReceiver.cpp
+++ b/storage/ndb/src/ndbapi/NdbReceiver.cpp
@@ -108,7 +108,7 @@ NdbReceiver::calculate_batch_size(Uint32 key_size,
Uint32 tot_size= (key_size ? (key_size + 32) : 0); //key + signal overhead
NdbRecAttr *rec_attr= theFirstRecAttr;
while (rec_attr != NULL) {
- Uint32 attr_size= rec_attr->attrSize() * rec_attr->arraySize();
+ Uint32 attr_size= rec_attr->getColumn()->getSizeInBytes();
attr_size= ((attr_size + 7) >> 2) << 2; //Even to word + overhead
tot_size+= attr_size;
rec_attr= rec_attr->next();
@@ -211,8 +211,8 @@ NdbReceiver::copyout(NdbReceiver & dstRec){
src = src->next();
while(dst){
- Uint32 len = ((src->theAttrSize * src->theArraySize)+3)/4;
- dst->receive_data((Uint32*)src->aRef(), src->isNULL() ? 0 : len);
+ Uint32 len = src->get_size_in_bytes();
+ dst->receive_data((Uint32*)src->aRef(), len);
src = src->next();
dst = dst->next();
}
@@ -223,29 +223,29 @@ NdbReceiver::copyout(NdbReceiver & dstRec){
int
NdbReceiver::execTRANSID_AI(const Uint32* aDataPtr, Uint32 aLength)
{
- bool ok = true;
NdbRecAttr* currRecAttr = theCurrentRecAttr;
for (Uint32 used = 0; used < aLength ; used++){
AttributeHeader ah(* aDataPtr++);
const Uint32 tAttrId = ah.getAttributeId();
- const Uint32 tAttrSize = ah.getDataSize();
+ const Uint32 tAttrSize = ah.getByteSize();
/**
* Set all results to NULL if not found...
*/
while(currRecAttr && currRecAttr->attrId() != tAttrId){
- ok &= currRecAttr->setNULL();
currRecAttr = currRecAttr->next();
}
- if(ok && currRecAttr && currRecAttr->receive_data(aDataPtr, tAttrSize)){
- used += tAttrSize;
- aDataPtr += tAttrSize;
+ if(currRecAttr && currRecAttr->receive_data(aDataPtr, tAttrSize)){
+ Uint32 add= (tAttrSize + 3) >> 2;
+ used += add;
+ aDataPtr += add;
currRecAttr = currRecAttr->next();
} else {
- ndbout_c("%p: ok: %d tAttrId: %d currRecAttr: %p",
- this,ok, tAttrId, currRecAttr);
+ ndbout_c("%p: tAttrId: %d currRecAttr: %p tAttrSize: %d %d", this,
+ tAttrId, currRecAttr,
+ tAttrSize, currRecAttr->get_size_in_bytes());
currRecAttr = theCurrentRecAttr;
while(currRecAttr != 0){
ndbout_c("%d ", currRecAttr->attrId());
@@ -273,7 +273,7 @@ NdbReceiver::execKEYINFO20(Uint32 info, const Uint32* aDataPtr, Uint32 aLength)
{
NdbRecAttr* currRecAttr = m_rows[m_current_row++];
assert(currRecAttr->attrId() == KEY_ATTR_ID);
- currRecAttr->receive_data(aDataPtr, aLength + 1);
+ currRecAttr->receive_data(aDataPtr, 4*(aLength + 1));
/**
* Save scanInfo in the end of keyinfo
diff --git a/storage/ndb/src/ndbapi/NdbScanOperation.cpp b/storage/ndb/src/ndbapi/NdbScanOperation.cpp
index edc60feaa96..2fcbeec1bf0 100644
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -198,7 +198,7 @@ NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
theSCAN_TABREQ->setSignal(GSN_SCAN_TABREQ);
ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
req->apiConnectPtr = theNdbCon->theTCConPtr;
- req->tableId = m_accessTable->m_tableId;
+ req->tableId = m_accessTable->m_id;
req->tableSchemaVersion = m_accessTable->m_version;
req->storedProcId = 0xFFFF;
req->buddyConPtr = theNdbCon->theBuddyConPtr;
@@ -767,6 +767,7 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
*/
Uint32 reqInfo = req->requestInfo;
ScanTabReq::setKeyinfoFlag(reqInfo, keyInfo);
+ ScanTabReq::setNoDiskFlag(reqInfo, m_no_disk_flag);
req->requestInfo = reqInfo;
for(Uint32 i = 0; i<theParallelism; i++){
@@ -926,8 +927,10 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbTransaction* pTrans)
}
pTrans->theSimpleState = 0;
- const Uint32 len = (tRecAttr->attrSize() * tRecAttr->arraySize() + 3)/4-1;
-
+ assert(tRecAttr->get_size_in_bytes() > 0);
+ assert(tRecAttr->get_size_in_bytes() < 65536);
+ const Uint32 len = (tRecAttr->get_size_in_bytes() + 3)/4-1;
+
newOp->theTupKeyLen = len;
newOp->theOperationType = opType;
if (opType == DeleteRequest) {
@@ -1021,23 +1024,23 @@ NdbIndexScanOperation::~NdbIndexScanOperation(){
int
NdbIndexScanOperation::setBound(const char* anAttrName, int type,
- const void* aValue, Uint32 len)
+ const void* aValue)
{
- return setBound(m_accessTable->getColumn(anAttrName), type, aValue, len);
+ return setBound(m_accessTable->getColumn(anAttrName), type, aValue);
}
int
NdbIndexScanOperation::setBound(Uint32 anAttrId, int type,
- const void* aValue, Uint32 len)
+ const void* aValue)
{
- return setBound(m_accessTable->getColumn(anAttrId), type, aValue, len);
+ return setBound(m_accessTable->getColumn(anAttrId), type, aValue);
}
int
NdbIndexScanOperation::equal_impl(const NdbColumnImpl* anAttrObject,
- const char* aValue,
- Uint32 len){
- return setBound(anAttrObject, BoundEQ, aValue, len);
+ const char* aValue)
+{
+ return setBound(anAttrObject, BoundEQ, aValue);
}
NdbRecAttr*
@@ -1047,7 +1050,7 @@ NdbIndexScanOperation::getValue_impl(const NdbColumnImpl* attrInfo,
return NdbScanOperation::getValue_impl(attrInfo, aValue);
}
- int id = attrInfo->m_attrId; // In "real" table
+ int id = attrInfo->getColumnNo(); // In "real" table
assert(m_accessTable->m_index);
int sz = (int)m_accessTable->m_index->m_key_ids.size();
if(id >= sz || (id = m_accessTable->m_index->m_key_ids[id]) == -1){
@@ -1084,22 +1087,21 @@ NdbIndexScanOperation::getValue_impl(const NdbColumnImpl* attrInfo,
*/
int
NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
- int type, const void* aValue, Uint32 len)
+ int type, const void* aValue)
{
if (theOperationType == OpenRangeScanRequest &&
- (0 <= type && type <= 4) &&
- len <= 8000) {
+ (0 <= type && type <= 4)) {
// insert bound type
Uint32 currLen = theTotalNrOfKeyWordInSignal;
Uint32 remaining = KeyInfo::DataLength - currLen;
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
bool tDistrKey = tAttrInfo->m_distributionKey;
- len = aValue != NULL ? sizeInBytes : 0;
- if (len != sizeInBytes && (len != 0)) {
- setErrorCodeAbort(4209);
- return -1;
- }
+ Uint32 len = 0;
+ if (aValue != NULL)
+ if (! tAttrInfo->get_var_length(aValue, len)) {
+ setErrorCodeAbort(4209);
+ return -1;
+ }
// insert attribute header
Uint32 tIndexAttrId = tAttrInfo->m_attrId;
@@ -1321,10 +1323,11 @@ NdbIndexScanOperation::compare(Uint32 skip, Uint32 cols,
return (r1_null ? -1 : 1) * jdir;
}
const NdbColumnImpl & col = NdbColumnImpl::getImpl(* r1->m_column);
- Uint32 len = r1->theAttrSize * r1->theArraySize;
+ Uint32 len1 = r1->get_size_in_bytes();
+ Uint32 len2 = r2->get_size_in_bytes();
if(!r1_null){
const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(col.m_type);
- int r = (*sqlType.m_cmp)(col.m_cs, d1, len, d2, len, true);
+ int r = (*sqlType.m_cmp)(col.m_cs, d1, len1, d2, len2, true);
if(r){
assert(r != NdbSqlUtil::CmpUnknown);
return r * jdir;
diff --git a/storage/ndb/src/ndbapi/Ndbif.cpp b/storage/ndb/src/ndbapi/Ndbif.cpp
index d68248e6981..6104a97b213 100644
--- a/storage/ndb/src/ndbapi/Ndbif.cpp
+++ b/storage/ndb/src/ndbapi/Ndbif.cpp
@@ -684,6 +684,14 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
case GSN_DROP_EVNT_CONF:
case GSN_DROP_EVNT_REF:
case GSN_LIST_TABLES_CONF:
+ case GSN_CREATE_FILE_REF:
+ case GSN_CREATE_FILE_CONF:
+ case GSN_CREATE_FILEGROUP_REF:
+ case GSN_CREATE_FILEGROUP_CONF:
+ case GSN_DROP_FILE_REF:
+ case GSN_DROP_FILE_CONF:
+ case GSN_DROP_FILEGROUP_REF:
+ case GSN_DROP_FILEGROUP_CONF:
case GSN_WAIT_GCP_CONF:
case GSN_WAIT_GCP_REF:
NdbDictInterface::execSignal(&theDictionary->m_receiver,
@@ -1035,6 +1043,7 @@ void
Ndb::check_send_timeout()
{
NDB_TICKS current_time = NdbTick_CurrentMillisecond();
+ assert(current_time >= the_last_check_time);
if (current_time - the_last_check_time > 1000) {
the_last_check_time = current_time;
Uint32 no_of_sent = theNoOfSentTransactions;
diff --git a/storage/ndb/src/ndbapi/TransporterFacade.cpp b/storage/ndb/src/ndbapi/TransporterFacade.cpp
index 14d76b42285..390a65dd220 100644
--- a/storage/ndb/src/ndbapi/TransporterFacade.cpp
+++ b/storage/ndb/src/ndbapi/TransporterFacade.cpp
@@ -658,7 +658,6 @@ TransporterFacade::TransporterFacade() :
init_cond_wait_queue();
poll_owner = NULL;
theOwnId = 0;
-
theMutexPtr = NdbMutex_Create();
sendPerformedLastInterval = 0;
@@ -674,6 +673,9 @@ TransporterFacade::TransporterFacade() :
theClusterMgr = new ClusterMgr(* this);
+#ifdef API_TRACE
+ apiSignalLog = 0;
+#endif
DBUG_VOID_RETURN;
}
diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c
index e2905e981de..fc166445555 100644
--- a/storage/ndb/src/ndbapi/ndberror.c
+++ b/storage/ndb/src/ndbapi/ndberror.c
@@ -77,6 +77,7 @@ static const char* empty_string = "";
* 1200 - LQH
* 1300 - BACKUP
* 1400 - SUMA
+ * 1500 - LGMAN
* 4000 - API
* 4100 - ""
* 4200 - ""
@@ -177,7 +178,9 @@ ErrorBundle ErrorCodes[] = {
{ 4021, DMEC, TR, "Out of Send Buffer space in NDB API" },
{ 4022, DMEC, TR, "Out of Send Buffer space in NDB API" },
{ 4032, DMEC, TR, "Out of Send Buffer space in NDB API" },
+ { 1501, DMEC, TR, "Out of undo space" },
{ 288, DMEC, TR, "Out of index operations in transaction coordinator (increase MaxNoOfConcurrentIndexOperations)" },
+
/**
* InsufficientSpace
*/
@@ -283,7 +286,7 @@ ErrorBundle ErrorCodes[] = {
{ 897, DMEC, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" },
{ 4256, DMEC, AE, "Must call Ndb::init() before this function" },
{ 4257, DMEC, AE, "Tried to read too much - too many getValue calls" },
-
+
/**
* Scan application errors
*/
@@ -338,8 +341,9 @@ ErrorBundle ErrorCodes[] = {
{ 707, DMEC, SE, "No more table metadata records (increase MaxNoOfTables)" },
{ 708, DMEC, SE, "No more attribute metadata records (increase MaxNoOfAttributes)" },
{ 709, HA_ERR_NO_SUCH_TABLE, SE, "No such table existed" },
+ { 710, DMEC, SE, "Internal: Get by table name not supported, use table id." },
{ 721, HA_ERR_TABLE_EXIST, OE, "Table or index with given name already exists" },
- { 723, DMEC, SE, "No such table existed" },
+ { 723, HA_ERR_NO_SUCH_TABLE, SE, "No such table existed" },
{ 736, DMEC, SE, "Unsupported array size" },
{ 737, HA_WRONG_CREATE_OPTION, SE, "Attribute array size too big" },
{ 738, HA_WRONG_CREATE_OPTION, SE, "Record too big" },
@@ -352,8 +356,27 @@ ErrorBundle ErrorCodes[] = {
{ 771, HA_WRONG_CREATE_OPTION, AE, "Given NODEGROUP doesn't exist in this cluster" },
{ 772, HA_WRONG_CREATE_OPTION, IE, "Given fragmentType doesn't exist" },
{ 749, HA_WRONG_CREATE_OPTION, IE, "Primary Table in wrong state" },
+ { 763, HA_WRONG_CREATE_OPTION, SE, "Invalid undo buffer size" },
+ { 764, HA_WRONG_CREATE_OPTION, SE, "Invalid extent size" },
+ { 765, DMEC, SE, "Out of filegroup records" },
+ { 750, IE, SE, "Invalid file type" },
+ { 751, DMEC, SE, "Out of file records" },
+ { 752, DMEC, SE, "Invalid file format" },
+ { 753, IE, SE, "Invalid filegroup for file" },
+ { 754, IE, SE, "Invalid filegroup version when creating file" },
+ { 755, DMEC, SE, "Invalid tablespace" },
+ { 756, DMEC, SE, "Index on disk column is not supported" },
+ { 757, DMEC, SE, "Varsize bitfield not supported" },
+ { 758, DMEC, SE, "Tablespace has changed" },
+ { 759, DMEC, SE, "Invalid tablespace version " },
+ { 760, DMEC, SE, "File already exists", },
{ 761, DMEC, SE, "Unable to drop table as backup is in progress" },
{ 762, DMEC, SE, "Unable to alter table as backup is in progress" },
+ { 766, DMEC, SE, "Cant drop file, no such file" },
+ { 767, DMEC, SE, "Cant drop filegroup, no such filegroup" },
+ { 768, DMEC, SE, "Cant drop filegroup, filegroup is used" },
+ { 769, DMEC, SE, "Drop undofile not supported, drop logfile group instead" },
+ { 770, DMEC, SE, "Cant drop file, file is used" },
{ 241, HA_ERR_TABLE_DEF_CHANGED, SE, "Invalid schema object version" },
{ 283, HA_ERR_NO_SUCH_TABLE, SE, "Table is being dropped" },
{ 284, HA_ERR_TABLE_DEF_CHANGED, SE, "Table not defined in transaction coordinator" },