diff options
author | unknown <jonas@perch.ndb.mysql.com> | 2005-11-07 12:19:28 +0100 |
---|---|---|
committer | unknown <jonas@perch.ndb.mysql.com> | 2005-11-07 12:19:28 +0100 |
commit | ee740746aff3c5163adfff481bc4cf70c37728f5 (patch) | |
tree | 2cb53178c95e7d8d6578018e169c2d71bb1fdbcb | |
parent | 8a224ed85a8794743472f3611830349dc490aabc (diff) | |
download | mariadb-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''
229 files changed, 35889 insertions, 18655 deletions
diff --git a/configure.in b/configure.in index 5a8d7a114ce..e7f0bafc489 100644 --- a/configure.in +++ b/configure.in @@ -1864,7 +1864,8 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \ sighold sigset sigthreadmask \ snprintf socket stpcpy strcasecmp strerror strsignal strnlen strpbrk strstr strtol \ - strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr) + strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr \ + posix_fallocate) # # diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index e80c3594ee8..e2a7132081d 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -181,7 +181,7 @@ fi # Edit file system path and ports in config file if [ $initial_ndb ] ; then - rm -f $fs_ndb/ndb_* 2>&1 | cat > /dev/null + rm -rf $fs_ndb/ndb_* 2>&1 | cat > /dev/null sed \ -e s,"CHOOSE_MaxNoOfOrderedIndexes","$ndb_no_ord",g \ -e s,"CHOOSE_MaxNoOfConcurrentOperations","$ndb_con_op",g \ diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result index e766a25b111..84dbe975a59 100644 --- a/mysql-test/r/ndb_alter_table.result +++ b/mysql-test/r/ndb_alter_table.result @@ -34,13 +34,13 @@ col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null, col6 int not null, to_be_deleted int) ENGINE=ndbcluster; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 NDBCLUSTER 10 Dynamic 0 0 # # 0 # 1 # # # latin1_swedish_ci NULL # +t1 NDBCLUSTER 10 Dynamic 0 # # # 0 # 1 # # # latin1_swedish_ci NULL # SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO; insert into t1 values (0,4,3,5,"PENDING",1,7),(NULL,4,3,5,"PENDING",1,7),(31,4,3,5,"PENDING",1,7), (7,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7), (100,4,3,5,"PENDING",1,7), (99,4,3,5,"PENDING",1,7), (8,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 NDBCLUSTER 10 Dynamic 9 96 # # 0 # 102 # # # latin1_swedish_ci NULL # +t1 NDBCLUSTER 10 Dynamic 9 # # # 0 # 102 # # # latin1_swedish_ci NULL # select * from t1 order by col1; col1 col2 col3 col4 col5 col6 to_be_deleted 0 4 3 5 PENDING 1 7 @@ -60,7 +60,7 @@ change column col2 fourth varchar(30) not null after col3, modify column col6 int not null first; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 NDBCLUSTER 10 Dynamic 9 152 # # 0 # 102 # # # latin1_swedish_ci NULL # +t1 NDBCLUSTER 10 Dynamic 9 # # # 0 # 102 # # # latin1_swedish_ci NULL # select * from t1 order by col1; col6 col1 col3 fourth col4 col4_5 col5 col7 col8 1 0 3 4 5 PENDING 0000-00-00 00:00:00 @@ -75,7 +75,7 @@ col6 col1 col3 fourth col4 col4_5 col5 col7 col8 insert into t1 values (2, NULL,4,3,5,99,"PENDING","EXTRA",'2004-01-01 00:00:00'); show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 NDBCLUSTER 10 Dynamic 10 152 # # 0 # 103 # # # latin1_swedish_ci NULL # +t1 NDBCLUSTER 10 Dynamic 10 # # # 0 # 103 # # # latin1_swedish_ci NULL # select * from t1 order by col1; col6 col1 col3 fourth col4 col4_5 col5 col7 col8 1 0 3 4 5 PENDING 0000-00-00 00:00:00 diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index 762e3b14c1a..813e37e8892 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -146,8 +146,8 @@ Handler_discover 1 flush tables; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t6 MyISAM 10 Fixed 1 260 # # # 0 NULL # # NULL # NULL # -t7 NDBCLUSTER 10 Fixed 1 276 # # # 0 NULL # # NULL # NULL # +t6 MyISAM 10 Fixed 1 # # # # 0 NULL # # NULL # NULL # +t7 NDBCLUSTER 10 Fixed 1 # # # # 0 NULL # # NULL # NULL # show status like 'handler_discover%'; Variable_name Value Handler_discover 2 diff --git a/mysql-test/r/ndb_partition_key.result b/mysql-test/r/ndb_partition_key.result index 9cc7147bd77..c06ca5219f2 100644 --- a/mysql-test/r/ndb_partition_key.result +++ b/mysql-test/r/ndb_partition_key.result @@ -57,10 +57,10 @@ Number of primary keys: 3 Length of frm data: # TableStatus: Retrieved -- Attributes -- -a Int PRIMARY KEY -b Char(10;latin1_bin) PRIMARY KEY DISTRIBUTION KEY -c Int PRIMARY KEY -d Int NULL +a Int PRIMARY KEY AT=FIXED ST=MEMORY +b Char(10;latin1_bin) PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY +c Int PRIMARY KEY AT=FIXED ST=MEMORY +d Int NULL AT=FIXED ST=MEMORY -- Indexes -- PRIMARY KEY(a, b, c) - UniqueHashIndex diff --git a/mysql-test/r/ndb_restore.result b/mysql-test/r/ndb_restore.result index c8b28bd345d..d86d0bdb58b 100644 --- a/mysql-test/r/ndb_restore.result +++ b/mysql-test/r/ndb_restore.result @@ -126,26 +126,6 @@ create table t7 engine=myisam as select * from t7_c; create table t8 engine=myisam as select * from t8_c; create table t9 engine=myisam as select * from t9_c; drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; -show tables; -Tables_in_test -t1 -t2 -t3 -t4 -t5 -t6 -t7 -t8 -t9 -t8_c -t9_c -t1_c -t7_c -t6_c -t5_c -t4_c -t3_c -t2_c select count(*) from t1; count(*) 5 diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 357f658a296..75ab245a352 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -56,12 +56,12 @@ col3 varchar (20) not null, col4 varchar(4) not null, col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null, col6 int not null, to_be_deleted int) ENGINE=ndbcluster; ---replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 # +--replace_column 6 # 7 # 8 # 10 # 12 # 13 # 14 # 18 # show table status; SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO; insert into t1 values (0,4,3,5,"PENDING",1,7),(NULL,4,3,5,"PENDING",1,7),(31,4,3,5,"PENDING",1,7), (7,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7), (100,4,3,5,"PENDING",1,7), (99,4,3,5,"PENDING",1,7), (8,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7); ---replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 # +--replace_column 6 # 7 # 8 # 10 # 12 # 13 # 14 # 18 # show table status; select * from t1 order by col1; alter table t1 @@ -70,11 +70,11 @@ add column col7 varchar(30) not null after col5, add column col8 datetime not null, drop column to_be_deleted, change column col2 fourth varchar(30) not null after col3, modify column col6 int not null first; ---replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 # +--replace_column 6 # 7 # 8 # 10 # 12 # 13 # 14 # 18 # show table status; select * from t1 order by col1; insert into t1 values (2, NULL,4,3,5,99,"PENDING","EXTRA",'2004-01-01 00:00:00'); ---replace_column 7 # 8 # 10 # 12 # 13 # 14 # 18 # +--replace_column 6 # 7 # 8 # 10 # 12 # 13 # 14 # 18 # show table status; select * from t1 order by col1; delete from t1; diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index 6bbb1c2f2f2..7192cc89a07 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -177,7 +177,7 @@ show status like 'handler_discover%'; flush tables; system rm var/master-data/test/t7.frm ; ---replace_column 7 # 8 # 9 # 12 # 13 # 15 # 18 # +--replace_column 6 # 7 # 8 # 9 # 12 # 13 # 15 # 18 # show table status; show status like 'handler_discover%'; @@ -543,6 +543,6 @@ create table t10 ( insert into t10 values (1, 'kalle'); ---exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB` >> $NDB_TOOLS_OUTPUT 2>&1 || true +--exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB | while read a b c d e f g; do echo $g; done` >> $NDB_TOOLS_OUTPUT 2>&1 || true # End of 4.1 tests diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test index 8f9b5787ff5..6075c7369ad 100644 --- a/mysql-test/t/ndb_restore.test +++ b/mysql-test/t/ndb_restore.test @@ -148,7 +148,8 @@ drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; --exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT --exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT -show tables; +# random output order?? +#show tables; select count(*) from t1; select count(*) from t1_c; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index fc31f4854ab..bde26176316 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -31,6 +31,7 @@ #include "ha_ndbcluster.h" #include <ndbapi/NdbApi.hpp> #include <ndbapi/NdbScanFilter.hpp> +#include <../util/Bitmask.hpp> #include <ndbapi/NdbIndexStat.hpp> // options from from mysqld.cc @@ -566,7 +567,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans) { err= dict->getNdbError(); DBUG_PRINT("info", ("Table not found, error: %d", err.code)); - if (err.code != 709) + if (err.code != 709 && err.code != 723) DBUG_RETURN(1); } DBUG_PRINT("info", ("Table exists but must have changed")); @@ -666,8 +667,7 @@ bool ha_ndbcluster::set_hidden_key(NdbOperation *ndb_op, uint fieldnr, const byte *field_ptr) { DBUG_ENTER("set_hidden_key"); - DBUG_RETURN(ndb_op->equal(fieldnr, (char*)field_ptr, - NDB_HIDDEN_PRIMARY_KEY_LENGTH) != 0); + DBUG_RETURN(ndb_op->equal(fieldnr, (char*)field_ptr) != 0); } @@ -729,12 +729,10 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, { DBUG_PRINT("info", ("field is NULL")); // Set value to NULL - DBUG_RETURN((ndb_op->setValue(fieldnr, - (char*)NULL, pack_len) != 0)); + DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL) != 0)); } // Common implementation for most field types - DBUG_RETURN(ndb_op->setValue(fieldnr, - (char*)field_ptr, pack_len) != 0); + DBUG_RETURN(ndb_op->setValue(fieldnr, (char*)field_ptr) != 0); } else // if (field->type() == MYSQL_TYPE_BIT) { @@ -745,17 +743,16 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, DBUG_ASSERT(pack_len <= 8); if (field->is_null(row_offset)) // Set value to NULL - DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL, pack_len) != 0)); + DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL) != 0)); DBUG_PRINT("info", ("bit field")); DBUG_DUMP("value", (char*)&bits, pack_len); #ifdef WORDS_BIGENDIAN if (pack_len < 5) { - DBUG_RETURN(ndb_op->setValue(fieldnr, - ((char*)&bits)+4, pack_len) != 0); + DBUG_RETURN(ndb_op->setValue(fieldnr, ((char*)&bits)+4) != 0); } #endif - DBUG_RETURN(ndb_op->setValue(fieldnr, (char*)&bits, pack_len) != 0); + DBUG_RETURN(ndb_op->setValue(fieldnr, (char*)&bits) != 0); } } // Blob type @@ -3941,11 +3938,40 @@ int ha_ndbcluster::create(const char *name, field->pack_length())); if ((my_errno= create_ndb_column(col, field, info))) DBUG_RETURN(my_errno); + + if ( +#ifdef NDB_DISKDATA + info->store_on_disk || +#else + getenv("NDB_DEFAULT_DISK")) +#endif + col.setStorageType(NdbDictionary::Column::StorageTypeDisk); + else + col.setStorageType(NdbDictionary::Column::StorageTypeMemory); + tab.addColumn(col); if (col.getPrimaryKey()) pk_length += (field->pack_length() + 3) / 4; } - + + KEY* key_info; + for (i= 0, key_info= form->key_info; i < form->s->keys; i++, key_info++) + { + KEY_PART_INFO *key_part= key_info->key_part; + KEY_PART_INFO *end= key_part + key_info->key_parts; + for (; key_part != end; key_part++) + tab.getColumn(key_part->fieldnr-1)->setStorageType( + NdbDictionary::Column::StorageTypeMemory); + } + +#ifdef NDB_DISKDATA + if (info->store_on_disk) + if (info->tablespace) + tab.setTablespace(info->tablespace); + else + tab.setTablespace("DEFAULT-TS"); +#endif + // No primary key, create shadow key as 64 bit, auto increment if (form->s->primary_key == MAX_KEY) { @@ -4126,7 +4152,6 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) if (!(orig_tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); } - m_table= (void *)orig_tab; // Change current database to that of target table set_dbname(to); @@ -4236,7 +4261,6 @@ int ha_ndbcluster::drop_table() DBUG_ENTER("drop_table"); DBUG_PRINT("enter", ("Deleting %s", m_tabname)); - release_metadata(); if (dict->dropTable(m_tabname)) ERR_RETURN(dict->getNdbError()); @@ -4561,7 +4585,7 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name, if (!(tab= dict->getTable(name))) { const NdbError err= dict->getNdbError(); - if (err.code == 709) + if (err.code == 709 || err.code == 723) DBUG_RETURN(-1); ERR_RETURN(err); } @@ -4608,7 +4632,7 @@ int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name if (!(tab= dict->getTable(name))) { const NdbError err= dict->getNdbError(); - if (err.code == 709) + if (err.code == 709 || err.code == 723) DBUG_RETURN(0); ERR_RETURN(err); } @@ -4675,7 +4699,7 @@ int ndbcluster_drop_database(const char *path) if (ha_ndbcluster::delete_table(0, ndb, full_path, dbname, tabname)) { const NdbError err= dict->getNdbError(); - if (err.code != 709) + if (err.code != 709 && err.code != 723) { ERR_PRINT(err); ret= ndb_to_mysql_error(&err); @@ -5019,7 +5043,6 @@ bool ndbcluster_init() (void) hash_init(&ndbcluster_open_tables,system_charset_info,32,0,0, (hash_get_key) ndbcluster_get_key,0,0); pthread_mutex_init(&ndbcluster_mutex,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&LOCK_ndb_util_thread, MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_ndb_util_thread, NULL); @@ -8165,7 +8188,6 @@ static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length) DBUG_VOID_RETURN; } - bool ha_ndbcluster::check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes) { @@ -8192,4 +8214,224 @@ bool ha_ndbcluster::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +#ifdef NDB_DISKDATA +bool set_up_tablespace(st_alter_tablespace *info, + NdbDictionary::Tablespace *ndb_ts) +{ + ndb_ts->setName(info->tablespace_name); + ndb_ts->setExtentSize(info->extent_size); + ndb_ts->setDefaultLogfileGroup(info->logfile_group_name); + return false; +} + +bool set_up_datafile(st_alter_tablespace *info, + NdbDictionary::Datafile *ndb_df) +{ + if (info->max_size > 0) + { + my_error(ER_TABLESPACE_AUTO_EXTEND_ERROR, MYF(0)); + return true; + } + ndb_df->setPath(info->data_file_name); + ndb_df->setSize(info->initial_size); + ndb_df->setTablespace(info->tablespace_name); + return false; +} + +bool set_up_logfile_group(st_alter_tablespace *info, + NdbDictionary::LogfileGroup *ndb_lg) +{ + ndb_lg->setName(info->logfile_group_name); + ndb_lg->setUndoBufferSize(info->undo_buffer_size); + return false; +} + +bool set_up_undofile(st_alter_tablespace *info, + NdbDictionary::Undofile *ndb_uf) +{ + ndb_uf->setPath(info->undo_file_name); + ndb_uf->setSize(info->initial_size); + ndb_uf->setLogfileGroup(info->logfile_group_name); + return false; +} + +int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info) +{ + Ndb *ndb; + NDBDICT *dict; + int error; + DBUG_ENTER("ha_ndbcluster::alter_tablespace"); + if (check_ndb_connection()) + { + DBUG_RETURN(my_errno= HA_ERR_NO_CONNECTION); + } + ndb= get_ndb(); + dict= ndb->getDictionary(); + switch (info->ts_cmd_type){ + case (CREATE_TABLESPACE): + { + NdbDictionary::Tablespace ndb_ts; + NdbDictionary::Datafile ndb_df; + if (set_up_tablespace(info, &ndb_ts)) + { + DBUG_RETURN(1); + } + if (set_up_datafile(info, &ndb_df)) + { + DBUG_RETURN(1); + } + if (error= dict->createTablespace(ndb_ts)) + { + DBUG_PRINT("error", ("createTablespace returned %d", error)); + my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "TABLESPACE"); + DBUG_RETURN(1); + } + DBUG_PRINT("info", ("Successfully created Tablespace")); + if (error= dict->createDatafile(ndb_df)) + { + DBUG_PRINT("error", ("createDatafile returned %d", error)); + my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "DATAFILE"); + DBUG_RETURN(1); + } + break; + } + case (ALTER_TABLESPACE): + { + if (info->ts_alter_tablespace_type == ALTER_TABLESPACE_ADD_FILE) + { + NdbDictionary::Datafile ndb_df; + if (set_up_datafile(info, &ndb_df)) + { + DBUG_RETURN(1); + } + if (error= dict->createDatafile(ndb_df)) + { + DBUG_PRINT("error", ("createDatafile returned %d", error)); + my_error(ER_ALTER_TABLESPACE_FAILED, MYF(0), "CREATE DATAFILE"); + DBUG_RETURN(1); + } + } + else if(info->ts_alter_tablespace_type == ALTER_TABLESPACE_DROP_FILE) + { + NdbDictionary::Datafile df = dict->getDatafile(0, + info->data_file_name); + if (strcmp(df.getPath(), info->data_file_name) == 0) + { + if (error= dict->dropDatafile(df)) + { + DBUG_PRINT("error", ("createDatafile returned %d", error)); + my_error(ER_ALTER_TABLESPACE_FAILED, MYF(0), " DROP DATAFILE"); + DBUG_RETURN(1); + } + } + else + { + DBUG_PRINT("error", ("No such datafile")); + my_error(ER_ALTER_TABLESPACE_FAILED, MYF(0), " NO SUCH FILE"); + DBUG_RETURN(1); + } + } + else + { + DBUG_PRINT("error", ("Unsupported alter tablespace: %d", + info->ts_alter_tablespace_type)); + DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + } + break; + } + case (CREATE_LOGFILE_GROUP): + { + NdbDictionary::LogfileGroup ndb_lg; + NdbDictionary::Undofile ndb_uf; + if (info->undo_file_name == NULL) + { + /* + REDO files in LOGFILE GROUP not supported yet + */ + DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + } + if (set_up_logfile_group(info, &ndb_lg)) + { + DBUG_RETURN(1); + } + if (error= dict->createLogfileGroup(ndb_lg)) + { + DBUG_PRINT("error", ("createLogfileGroup returned %d", error)); + my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "LOGFILE GROUP"); + DBUG_RETURN(1); + } + DBUG_PRINT("info", ("Successfully created Logfile Group")); + if (set_up_undofile(info, &ndb_uf)) + { + DBUG_RETURN(1); + } + if (error= dict->createUndofile(ndb_uf)) + { + DBUG_PRINT("error", ("createUndofile returned %d", error)); + my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "UNDOFILE"); + DBUG_RETURN(1); + } + break; + } + case (ALTER_LOGFILE_GROUP): + { + if (info->undo_file_name == NULL) + { + /* + REDO files in LOGFILE GROUP not supported yet + */ + DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + } + NdbDictionary::Undofile ndb_uf; + if (set_up_undofile(info, &ndb_uf)) + { + DBUG_RETURN(1); + } + if (error= dict->createUndofile(ndb_uf)) + { + DBUG_PRINT("error", ("createUndofile returned %d", error)); + my_error(ER_ALTER_TABLESPACE_FAILED, MYF(0), "CREATE UNDOFILE"); + DBUG_RETURN(1); + } + break; + } + case (DROP_TABLESPACE): + { + if (error= dict->dropTablespace( + dict->getTablespace(info->tablespace_name))) + { + DBUG_PRINT("error", ("dropTablespace returned %d", error)); + my_error(ER_DROP_TABLESPACE_FAILED, MYF(0), "TABLESPACE"); + DBUG_RETURN(1); + } + break; + } + case (DROP_LOGFILE_GROUP): + { + if (error= dict->dropLogfileGroup(dict->getLogfileGroup(info->logfile_group_name))) + { + DBUG_PRINT("error", ("dropLogfileGroup returned %d", error)); + my_error(ER_DROP_TABLESPACE_FAILED, MYF(0), "LOGFILE GROUP"); + DBUG_RETURN(1); + } + break; + } + case (CHANGE_FILE_TABLESPACE): + { + DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + } + case (ALTER_ACCESS_MODE_TABLESPACE): + { + DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + } + default: + { + DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + } + } + DBUG_RETURN(FALSE); +} + +#endif /* NDB_DISKDATA */ + #endif /* HAVE_NDBCLUSTER_DB */ diff --git a/storage/ndb/include/kernel/AttributeDescriptor.hpp b/storage/ndb/include/kernel/AttributeDescriptor.hpp index 2fe7c9f0973..d6cdba5009a 100644 --- a/storage/ndb/include/kernel/AttributeDescriptor.hpp +++ b/storage/ndb/include/kernel/AttributeDescriptor.hpp @@ -23,16 +23,19 @@ class AttributeDescriptor { friend class Dbacc; friend class Dbtup; friend class Dbtux; + friend class Dblqh; friend class SimulatedBlock; -private: +public: static void setType(Uint32 &, Uint32 type); static void setSize(Uint32 &, Uint32 size); - static void setArray(Uint32 &, Uint32 arraySize); + static void setArrayType(Uint32 &, Uint32 arrayType); + static void setArraySize(Uint32 &, Uint32 arraySize); static void setNullable(Uint32 &, Uint32 nullable); static void setDKey(Uint32 &, Uint32 dkey); static void setPrimaryKey(Uint32 &, Uint32 dkey); static void setDynamic(Uint32 &, Uint32 dynamicInd); + static void setDiskBased(Uint32 &, Uint32 val); static Uint32 getType(const Uint32 &); static Uint32 getSize(const Uint32 &); @@ -44,6 +47,9 @@ private: static Uint32 getDKey(const Uint32 &); static Uint32 getPrimaryKey(const Uint32 &); static Uint32 getDynamic(const Uint32 &); + static Uint32 getDiskBased(const Uint32 &); + + Uint32 m_data; }; /** @@ -78,6 +84,7 @@ private: #define AD_SIZE_IN_WORDS_OFFSET (31) #define AD_SIZE_IN_WORDS_SHIFT (5) +#define AD_DISK_SHIFT (11) #define AD_NULLABLE_SHIFT (12) #define AD_DISTR_KEY_SHIFT (13) #define AD_PRIMARY_KEY (14) @@ -89,57 +96,67 @@ private: inline void AttributeDescriptor::setType(Uint32 & desc, Uint32 type){ - ASSERT_MAX(type, AD_TYPE_MASK, "AttributeDescriptor::setType"); + assert(type <= AD_TYPE_MASK); desc |= (type << AD_TYPE_SHIFT); } inline void AttributeDescriptor::setSize(Uint32 & desc, Uint32 size){ - ASSERT_MAX(size, AD_SIZE_MASK, "AttributeDescriptor::setSize"); + assert(size <= AD_SIZE_MASK); desc |= (size << AD_SIZE_SHIFT); } inline void -AttributeDescriptor::setArray(Uint32 & desc, Uint32 size){ - ASSERT_MAX(size, AD_ARRAY_SIZE_MASK, "AttributeDescriptor::setArray"); - desc |= (size << AD_ARRAY_SIZE_SHIFT); - if(size <= 1){ - desc |= (size << AD_ARRAY_TYPE_SHIFT); - } else { - desc |= (2 << AD_ARRAY_TYPE_SHIFT); - } +AttributeDescriptor::setArrayType(Uint32 & desc, Uint32 arrayType){ + assert(arrayType <= AD_ARRAY_TYPE_MASK); + desc |= (arrayType << AD_ARRAY_TYPE_SHIFT); +} + +inline +void +AttributeDescriptor::setArraySize(Uint32 & desc, Uint32 arraySize){ + assert(arraySize <= AD_ARRAY_SIZE_MASK); + desc |= (arraySize << AD_ARRAY_SIZE_SHIFT); } inline void AttributeDescriptor::setNullable(Uint32 & desc, Uint32 nullable){ - ASSERT_BOOL(nullable, "AttributeDescriptor::setNullable"); + assert(nullable <= 1); desc |= (nullable << AD_NULLABLE_SHIFT); } inline void AttributeDescriptor::setDKey(Uint32 & desc, Uint32 dkey){ - ASSERT_BOOL(dkey, "AttributeDescriptor::setDKey"); + assert(dkey <= 1); desc |= (dkey << AD_DISTR_KEY_SHIFT); } inline void AttributeDescriptor::setPrimaryKey(Uint32 & desc, Uint32 dkey){ - ASSERT_BOOL(dkey, "AttributeDescriptor::setPrimaryKey"); + assert(dkey <= 1); desc |= (dkey << AD_PRIMARY_KEY); } inline void AttributeDescriptor::setDynamic(Uint32 & desc, Uint32 dynamic){ - ASSERT_BOOL(dynamic, "AttributeDescriptor::setDynamic"); + assert(dynamic <= 1); desc |= (dynamic << AD_DYNAMIC); } +inline +void +AttributeDescriptor::setDiskBased(Uint32 & desc, Uint32 val) +{ + assert(val <= 1); + desc |= (val << AD_DISK_SHIFT); +} + /** * Getters */ @@ -206,4 +223,14 @@ AttributeDescriptor::getDynamic(const Uint32 & desc){ return (desc >> AD_DYNAMIC) & 1; } +inline +Uint32 +AttributeDescriptor::getDiskBased(const Uint32 & desc) +{ + return (desc >> AD_DISK_SHIFT) & 1; +} + +class NdbOut& +operator<<(class NdbOut&, const AttributeDescriptor&); + #endif diff --git a/storage/ndb/include/kernel/AttributeHeader.hpp b/storage/ndb/include/kernel/AttributeHeader.hpp index a14e5ac4319..a636499a50f 100644 --- a/storage/ndb/include/kernel/AttributeHeader.hpp +++ b/storage/ndb/include/kernel/AttributeHeader.hpp @@ -42,6 +42,7 @@ public: STATIC_CONST( FRAGMENT_MEMORY= 0xFFF9 ); STATIC_CONST( RECORDS_IN_RANGE = 0xFFF8 ); + STATIC_CONST( DISK_REF = 0xFFF7 ); // NOTE: in 5.1 ctors and init take size in bytes diff --git a/storage/ndb/include/kernel/BlockNumbers.h b/storage/ndb/include/kernel/BlockNumbers.h index 49b5842ac4e..769af924490 100644 --- a/storage/ndb/include/kernel/BlockNumbers.h +++ b/storage/ndb/include/kernel/BlockNumbers.h @@ -45,6 +45,10 @@ #define DBUTIL 0x100 #define SUMA 0x101 #define DBTUX 0x102 +#define TSMAN 0x103 +#define LGMAN 0x104 +#define PGMAN 0x105 +#define RESTORE 0x106 const BlockReference BACKUP_REF = numberToRef(BACKUP, 0); const BlockReference DBTC_REF = numberToRef(DBTC, 0); @@ -61,9 +65,13 @@ const BlockReference TRIX_REF = numberToRef(TRIX, 0); const BlockReference DBUTIL_REF = numberToRef(DBUTIL, 0); const BlockReference SUMA_REF = numberToRef(SUMA, 0); const BlockReference DBTUX_REF = numberToRef(DBTUX, 0); +const BlockReference TSMAN_REF = numberToRef(TSMAN, 0); +const BlockReference LGMAN_REF = numberToRef(LGMAN, 0); +const BlockReference PGMAN_REF = numberToRef(PGMAN, 0); +const BlockReference RESTORE_REF = numberToRef(RESTORE, 0); const BlockNumber MIN_BLOCK_NO = BACKUP; -const BlockNumber MAX_BLOCK_NO = DBTUX; +const BlockNumber MAX_BLOCK_NO = RESTORE; const BlockNumber NO_OF_BLOCKS = (MAX_BLOCK_NO - MIN_BLOCK_NO + 1); /** diff --git a/storage/ndb/include/kernel/GlobalSignalNumbers.h b/storage/ndb/include/kernel/GlobalSignalNumbers.h index 2cecd109ac1..745e2daaca7 100644 --- a/storage/ndb/include/kernel/GlobalSignalNumbers.h +++ b/storage/ndb/include/kernel/GlobalSignalNumbers.h @@ -23,7 +23,7 @@ * * When adding a new signal, remember to update MAX_GSN and SignalNames.cpp */ -const GlobalSignalNumber MAX_GSN = 712; +const GlobalSignalNumber MAX_GSN = 730; struct GsnName { GlobalSignalNumber gsn; @@ -124,30 +124,34 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; */ #define GSN_ACC_ABORTCONF 67 -/* 68 unused */ -/* 69 unused */ +/* 68 not unused */ +/* 69 not unused */ /* 70 unused */ #define GSN_ACC_ABORTREQ 71 #define GSN_ACC_CHECK_SCAN 72 #define GSN_ACC_COMMITCONF 73 #define GSN_ACC_COMMITREQ 74 -#define GSN_ACC_CONTOPCONF 75 -#define GSN_ACC_CONTOPREQ 76 -#define GSN_ACC_LCPCONF 77 -#define GSN_ACC_LCPREF 78 -#define GSN_ACC_LCPREQ 79 -#define GSN_ACC_LCPSTARTED 80 +/* 75 unused */ +/* 76 unused */ + +/* 79 unused */ +/* 78 unused */ +/* 77 unused */ + +/* 80 unused */ #define GSN_ACC_OVER_REC 81 -#define GSN_ACC_SAVE_PAGES 83 +/* 83 unused */ #define GSN_ACC_SCAN_INFO 84 #define GSN_ACC_SCAN_INFO24 85 #define GSN_ACC_SCANCONF 86 #define GSN_ACC_SCANREF 87 #define GSN_ACC_SCANREQ 88 -#define GSN_ACC_SRCONF 89 -#define GSN_ACC_SRREF 90 -#define GSN_ACC_SRREQ 91 + +#define GSN_RESTORE_LCP_REQ 91 +#define GSN_RESTORE_LCP_REF 90 +#define GSN_RESTORE_LCP_CONF 89 + #define GSN_ACC_TO_CONF 92 #define GSN_ACC_TO_REF 93 #define GSN_ACC_TO_REQ 94 @@ -331,7 +335,9 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_DIVERIFYREQ 241 #define GSN_ENABLE_COMORD 242 #define GSN_END_LCPCONF 243 +#define GSN_END_LCP_CONF 243 #define GSN_END_LCPREQ 244 +#define GSN_END_LCP_REQ 244 #define GSN_END_TOCONF 245 #define GSN_END_TOREQ 246 #define GSN_EVENT_REP 247 @@ -372,21 +378,24 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_GCP_SAVEREF 282 #define GSN_GCP_SAVEREQ 283 #define GSN_GCP_TCFINISHED 284 -#define GSN_SR_FRAGIDCONF 285 -#define GSN_SR_FRAGIDREF 286 -#define GSN_SR_FRAGIDREQ 287 + +/* 285 unused */ +/* 286 unused */ +/* 287 unused */ #define GSN_GETGCICONF 288 #define GSN_GETGCIREQ 289 #define GSN_HOT_SPAREREP 290 #define GSN_INCL_NODECONF 291 #define GSN_INCL_NODEREF 292 #define GSN_INCL_NODEREQ 293 -#define GSN_LCP_FRAGIDCONF 294 -#define GSN_LCP_FRAGIDREF 295 -#define GSN_LCP_FRAGIDREQ 296 -#define GSN_LCP_HOLDOPCONF 297 -#define GSN_LCP_HOLDOPREF 298 -#define GSN_LCP_HOLDOPREQ 299 + +#define GSN_LCP_PREPARE_REQ 296 +#define GSN_LCP_PREPARE_REF 295 +#define GSN_LCP_PREPARE_CONF 294 + +/* 297 unused */ +/* 298 unused */ +/* 299 unused */ #define GSN_SHRINKCHECK2 301 #define GSN_GET_SCHEMA_INFOREQ 302 /* 303 not unused */ @@ -518,16 +527,18 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_TUP_ATTRINFO 418 #define GSN_TUP_COMMITREQ 419 /* 420 unused */ -#define GSN_TUP_LCPCONF 421 -#define GSN_TUP_LCPREF 422 -#define GSN_TUP_LCPREQ 423 -#define GSN_TUP_LCPSTARTED 424 -#define GSN_TUP_PREPLCPCONF 425 -#define GSN_TUP_PREPLCPREF 426 -#define GSN_TUP_PREPLCPREQ 427 -#define GSN_TUP_SRCONF 428 -#define GSN_TUP_SRREF 429 -#define GSN_TUP_SRREQ 430 + +/* 421 unused */ +/* 422 unused */ +/* 423 unused */ + +/* 424 unused */ +/* 425 unused */ +/* 426 unused */ +/* 427 unused */ +/* 428 unused */ +/* 429 unused */ +/* 430 unused */ #define GSN_TUPFRAGCONF 431 #define GSN_TUPFRAGREF 432 #define GSN_TUPFRAGREQ 433 @@ -850,12 +861,12 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_CREATE_SUBID_REF 662 #define GSN_CREATE_SUBID_CONF 663 -#define GSN_664 -#define GSN_665 -#define GSN_666 -#define GSN_667 -#define GSN_668 -#define GSN_669 +/* used 664 */ +/* used 665 */ +/* used 666 */ +/* used 667 */ +/* used 668 */ +/* used 669 */ /* * TUX @@ -932,4 +943,42 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_ACC_LOCKREQ 711 #define GSN_READ_PSEUDO_REQ 712 +/** + * Filegroup + */ +#define GSN_CREATE_FILEGROUP_REQ 713 +#define GSN_CREATE_FILEGROUP_REF 714 +#define GSN_CREATE_FILEGROUP_CONF 715 + +#define GSN_CREATE_FILE_REQ 716 +#define GSN_CREATE_FILE_REF 717 +#define GSN_CREATE_FILE_CONF 718 + +#define GSN_DROP_FILEGROUP_REQ 719 +#define GSN_DROP_FILEGROUP_REF 720 +#define GSN_DROP_FILEGROUP_CONF 721 + +#define GSN_DROP_FILE_REQ 722 +#define GSN_DROP_FILE_REF 723 +#define GSN_DROP_FILE_CONF 724 + +#define GSN_CREATE_OBJ_REQ 725 +#define GSN_CREATE_OBJ_REF 726 +#define GSN_CREATE_OBJ_CONF 727 + +#define GSN_DROP_OBJ_REQ 728 +#define GSN_DROP_OBJ_REF 729 +#define GSN_DROP_OBJ_CONF 730 + +#define GSN_ALLOC_EXTENT_REQ 68 +#define GSN_FREE_EXTENT_REQ 69 + +#define GSN_DICT_COMMIT_REQ 664 +#define GSN_DICT_COMMIT_REF 665 +#define GSN_DICT_COMMIT_CONF 666 + +#define GSN_DICT_ABORT_REQ 667 +#define GSN_DICT_ABORT_REF 668 +#define GSN_DICT_ABORT_CONF 669 + #endif diff --git a/storage/ndb/include/kernel/kernel_types.h b/storage/ndb/include/kernel/kernel_types.h index e16e61471e7..9b2178c4c84 100644 --- a/storage/ndb/include/kernel/kernel_types.h +++ b/storage/ndb/include/kernel/kernel_types.h @@ -18,6 +18,7 @@ #define NDB_KERNEL_TYPES_H #include <ndb_types.h> +#include "ndb_limits.h" typedef Uint16 NodeId; typedef Uint16 BlockNumber; @@ -36,6 +37,37 @@ enum Operation_t { #endif }; +/** + * 32k page + */ +struct GlobalPage { + union { + Uint32 data[GLOBAL_PAGE_SIZE/sizeof(Uint32)]; + Uint32 nextPool; + }; +}; + +struct Local_key +{ + Uint32 m_page_no; + Uint16 m_page_idx; + Uint16 m_file_no; + + bool isNull() const { return m_page_no == RNIL; } + void setNull() { m_page_no= RNIL; m_file_no= m_page_idx= ~0;} + + Uint32 ref() const { return (m_page_no << MAX_TUPLES_BITS) | m_page_idx ;} + + Local_key& operator= (Uint32 ref) { + m_page_no =ref >> MAX_TUPLES_BITS; + m_page_idx = ref & MAX_TUPLES_PER_PAGE; + return *this; + } +}; + +class NdbOut& +operator<<(class NdbOut&, const struct Local_key&); + inline Uint32 table_version_major(Uint32 ver) diff --git a/storage/ndb/include/kernel/ndb_limits.h b/storage/ndb/include/kernel/ndb_limits.h index 9baec7d69dc..11c429463ef 100644 --- a/storage/ndb/include/kernel/ndb_limits.h +++ b/storage/ndb/include/kernel/ndb_limits.h @@ -125,6 +125,17 @@ */ #define MAX_XFRM_MULTIPLY 8 /* max expansion when normalizing */ +/** + * Disk data + */ +#define MAX_FILES_PER_FILEGROUP 1024 + +/** + * Page size in global page pool + */ +#define GLOBAL_PAGE_SIZE 32768 +#define GLOBAL_PAGE_SIZE_WORDS 8192 + /* * Long signals */ diff --git a/storage/ndb/include/kernel/signaldata/AlterTable.hpp b/storage/ndb/include/kernel/signaldata/AlterTable.hpp index 16c9eb204c9..572e97afbd6 100644 --- a/storage/ndb/include/kernel/signaldata/AlterTable.hpp +++ b/storage/ndb/include/kernel/signaldata/AlterTable.hpp @@ -62,18 +62,22 @@ private: /* n = Changed name + f = Changed frm 1111111111222222222233 01234567890123456789012345678901 - n------------------------------- + nf------------------------------ */ #define NAME_SHIFT (0) +#define FRM_SHIFT (1) /** * Getters and setters */ static Uint8 getNameFlag(const UintR & changeMask); static void setNameFlag(UintR & changeMask, Uint32 nameFlg); + static Uint8 getFrmFlag(const UintR & changeMask); + static void setFrmFlag(UintR & changeMask, Uint32 frmFlg); }; inline @@ -88,6 +92,18 @@ AlterTableReq::setNameFlag(UintR & changeMask, Uint32 nameFlg){ changeMask |= (nameFlg << NAME_SHIFT); } +inline +Uint8 +AlterTableReq::getFrmFlag(const UintR & changeMask){ + return (Uint8)((changeMask >> FRM_SHIFT) & 1); +} + +inline +void +AlterTableReq::setFrmFlag(UintR & changeMask, Uint32 frmFlg){ + changeMask |= (frmFlg << FRM_SHIFT); +} + class AlterTableRef { /** diff --git a/storage/ndb/include/kernel/signaldata/AttrInfo.hpp b/storage/ndb/include/kernel/signaldata/AttrInfo.hpp index c87470db8b0..82c24059e56 100644 --- a/storage/ndb/include/kernel/signaldata/AttrInfo.hpp +++ b/storage/ndb/include/kernel/signaldata/AttrInfo.hpp @@ -36,6 +36,7 @@ class AttrInfo { friend class Dbtc; friend class Dblqh; friend class NdbScanOperation; + friend class Restore; friend bool printATTRINFO(FILE *, const Uint32 *, Uint32, Uint16); diff --git a/storage/ndb/include/kernel/signaldata/BackupImpl.hpp b/storage/ndb/include/kernel/signaldata/BackupImpl.hpp index 298440ad377..ae6bfee6fe1 100644 --- a/storage/ndb/include/kernel/signaldata/BackupImpl.hpp +++ b/storage/ndb/include/kernel/signaldata/BackupImpl.hpp @@ -30,6 +30,7 @@ class DefineBackupReq { * Reciver(s) */ friend class Backup; + friend class Dblqh; friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16); public: @@ -74,7 +75,8 @@ class DefineBackupRef { * Sender(s) */ friend class Backup; - + friend class Dblqh; + /** * Reciver(s) */ @@ -107,7 +109,8 @@ class DefineBackupConf { * Sender(s) */ friend class Backup; - + friend class Dblqh; + /** * Reciver(s) */ @@ -210,6 +213,7 @@ class BackupFragmentReq { * Reciver(s) */ friend class Backup; + friend class Dblqh; friend bool printBACKUP_FRAGMENT_REQ(FILE *, const Uint32 *, Uint32, Uint16); public: @@ -228,6 +232,7 @@ class BackupFragmentRef { * Sender(s) */ friend class Backup; + friend class Dblqh; /** * Reciver(s) @@ -250,6 +255,7 @@ class BackupFragmentConf { * Sender(s) */ friend class Backup; + friend class Dblqh; /** * Reciver(s) diff --git a/storage/ndb/include/kernel/signaldata/CreateFilegroup.hpp b/storage/ndb/include/kernel/signaldata/CreateFilegroup.hpp new file mode 100644 index 00000000000..810f9cdfd03 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/CreateFilegroup.hpp @@ -0,0 +1,198 @@ +/* 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 CREATE_FILEGROUP_HPP +#define CREATE_FILEGROUP_HPP + +#include "SignalData.hpp" + +struct CreateFilegroupReq { + /** + * Sender(s) / Reciver(s) + */ + friend class NdbDictInterface; + friend class Dbdict; + + /** + * For printing + */ + friend bool printCREATE_FILEGROUP_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 3 ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 objType; + SECTION( FILEGROUP_INFO = 0 ); +}; + +struct CreateFilegroupRef { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printCREATE_FILEGROUP_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 7 ); + + enum ErrorCode { + NoError = 0, + Busy = 701, + NotMaster = 702, + NoMoreObjectRecords = 710, + InvalidFormat = 740, + OutOfFilegroupRecords = 765, + InvalidExtentSize = 764, + InvalidUndoBufferSize = 763, + NoSuchLogfileGroup = 767, + InvalidFilegroupVersion = 768 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 masterNodeId; + Uint32 errorCode; + Uint32 errorLine; + Uint32 errorKey; + Uint32 status; +}; + +struct CreateFilegroupConf { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printCREATE_FILEGROUP_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 filegroupId; + Uint32 filegroupVersion; +}; + +struct CreateFileReq { + /** + * Sender(s) / Reciver(s) + */ + friend class NdbDictInterface; + friend class Dbdict; + friend class Tsman; + + /** + * For printing + */ + friend bool printCREATE_FILE_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 objType; + Uint32 requestInfo; + + enum RequstInfo + { + ForceCreateFile = 0x1 + }; + + SECTION( FILE_INFO = 0 ); +}; + +struct CreateFileRef { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printCREATE_FILE_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 7 ); + + enum ErrorCode { + NoError = 0, + Busy = 701, + NotMaster = 702, + NoMoreObjectRecords = 710, + InvalidFormat = 752, + NoSuchFilegroup = 753, + InvalidFilegroupVersion = 754, + FilenameAlreadyExists = 760, + OutOfFileRecords = 751, + InvalidFileType = 750 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 masterNodeId; + Uint32 errorCode; + Uint32 errorLine; + Uint32 errorKey; + Uint32 status; +}; + +struct CreateFileConf { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class Ndbcntr; + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printCREATE_FILE_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 fileId; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/CreateFilegroupImpl.hpp b/storage/ndb/include/kernel/signaldata/CreateFilegroupImpl.hpp new file mode 100644 index 00000000000..2062ec3e345 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/CreateFilegroupImpl.hpp @@ -0,0 +1,193 @@ +/* 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 CREATE_FILEGROUP_IMPL_HPP +#define CREATE_FILEGROUP_IMPL_HPP + +#include "SignalData.hpp" + +struct CreateFilegroupImplReq { + /** + * Sender(s) / Reciver(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printCREATE_FILEGROUP_IMPL_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( TablespaceLength = 6 ); + STATIC_CONST( LogfileGroupLength = 5 ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 filegroup_id; + Uint32 filegroup_version; + + union { + struct { + Uint32 extent_size; + Uint32 logfile_group_id; + } tablespace; + struct { + Uint32 buffer_size; // In pages + } logfile_group; + }; +}; + +struct CreateFilegroupImplRef { + /** + * Sender(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printCREATE_FILEGROUP_IMPL_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 3 ); + + enum ErrorCode { + NoError = 0, + FilegroupAlreadyExists = 1, + OutOfFilegroupRecords = 2, + OutOfLogBufferMemory = 3 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; +}; + +struct CreateFilegroupImplConf { + /** + * Sender(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printCREATE_FILEGROUP_IMPL_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 2 ); + + Uint32 senderData; + Uint32 senderRef; +}; + +struct CreateFileImplReq { + /** + * Sender(s) / Reciver(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printCREATE_FILE_IMPL_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( DatafileLength = 9 ); + STATIC_CONST( UndofileLength = 8 ); + STATIC_CONST( CommitLength = 6 ); + STATIC_CONST( AbortLength = 6 ); + SECTION( FILENAME = 0 ); + + enum RequestInfo { + Create = 0x1, + CreateForce = 0x2, + Open = 0x4, + Commit = 0x8, + Abort = 0x10 + }; + + Uint32 senderData; + Uint32 senderRef; + + Uint32 requestInfo; + Uint32 file_id; + Uint32 filegroup_id; + Uint32 filegroup_version; + Uint32 file_size_hi; + Uint32 file_size_lo; + + union { + struct { + Uint32 extent_size; + } tablespace; + }; +}; + +struct CreateFileImplRef { + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printCREATE_FILE_IMPL_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 5 ); + + enum ErrorCode { + NoError = 0, + InvalidFilegroup = 1, + InvalidFilegroupVersion = 2, + FileNoAlreadyExists = 3, + OutOfFileRecords = 4, + FileError = 5, + InvalidFileMetadata = 6, + OutOfMemory = 7, + FileReadError = 8, + FilegroupNotOnline = 9 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; + Uint32 fsErrCode; + Uint32 osErrCode; +}; + +struct CreateFileImplConf { + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + + /** + * For printing + */ + friend bool printCREATE_FILE_IMPL_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + + Uint32 senderData; + Uint32 senderRef; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/CreateIndx.hpp b/storage/ndb/include/kernel/signaldata/CreateIndx.hpp index a9dc653f349..2ba63d6ec69 100644 --- a/storage/ndb/include/kernel/signaldata/CreateIndx.hpp +++ b/storage/ndb/include/kernel/signaldata/CreateIndx.hpp @@ -193,6 +193,7 @@ public: NoError = 0, Busy = 701, NotMaster = 702, + IndexOnDiskAttributeError = 756, TriggerNotFound = 4238, TriggerExists = 4239, IndexNameTooLong = 4241, diff --git a/storage/ndb/include/kernel/signaldata/CreateObj.hpp b/storage/ndb/include/kernel/signaldata/CreateObj.hpp new file mode 100644 index 00000000000..ce267b85dac --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/CreateObj.hpp @@ -0,0 +1,107 @@ +/* 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 CREATE_OBJ_HPP +#define CREATE_OBJ_HPP + +#include "DictObjOp.hpp" +#include "SignalData.hpp" + +/** + * CreateObj + * + * Implemenatation of CreateObj + */ +struct CreateObjReq { + /** + * Sender(s) / Reciver(s) + */ + friend class Dbdict; + + /** + * For printing + */ + friend bool printCREATE_OBJ_REQ(FILE*, const Uint32*, Uint32, Uint16); + +public: + STATIC_CONST( SignalLength = 10 ); + STATIC_CONST( GSN = GSN_CREATE_OBJ_REQ ); + +private: + Uint32 op_key; + Uint32 senderRef; + Uint32 senderData; + Uint32 requestInfo; + + Uint32 clientRef; + Uint32 clientData; + + Uint32 objId; + Uint32 objType; + Uint32 objVersion; + Uint32 gci; + + SECTION( DICT_OBJ_INFO = 0 ); +}; + +struct CreateObjRef { + /** + * Sender(s) / Reciver(s) + */ + friend class Dbdict; + friend class SafeCounter; + + /** + * For printing + */ + friend bool printCREATE_OBJ_REF(FILE *, const Uint32 *, Uint32, Uint16); + + STATIC_CONST( SignalLength = 6 ); + STATIC_CONST( GSN = GSN_CREATE_OBJ_REF ); + + enum ErrorCode { + NF_FakeErrorREF = 255 + }; + + + Uint32 senderRef; + Uint32 senderData; + Uint32 errorCode; + Uint32 errorLine; + Uint32 errorKey; + Uint32 errorStatus; +}; + +struct CreateObjConf { + /** + * Sender(s) / Reciver(s) + */ + friend class Dbdict; + + /** + * For printing + */ + friend bool printCREATE_OBJ_CONF(FILE *, const Uint32 *, Uint32, Uint16); + +public: + STATIC_CONST( SignalLength = 2 ); + +private: + Uint32 senderRef; + Uint32 senderData; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/CreateTable.hpp b/storage/ndb/include/kernel/signaldata/CreateTable.hpp index 481b323fdb0..44a95469b38 100644 --- a/storage/ndb/include/kernel/signaldata/CreateTable.hpp +++ b/storage/ndb/include/kernel/signaldata/CreateTable.hpp @@ -91,7 +91,11 @@ public: RecordTooBig = 738, InvalidPrimaryKeySize = 739, NullablePrimaryKey = 740, - InvalidCharset = 743 + InvalidCharset = 743, + InvalidTablespace = 755, + VarsizeBitfieldNotSupported = 757, + NotATablespace = 758, + InvalidTablespaceVersion = 759 }; private: diff --git a/storage/ndb/include/kernel/signaldata/DictObjOp.hpp b/storage/ndb/include/kernel/signaldata/DictObjOp.hpp new file mode 100644 index 00000000000..daa8447998a --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/DictObjOp.hpp @@ -0,0 +1,104 @@ +/* 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 DICT_OBJ_OP_HPP +#define DICT_OBJ_OP_HPP + +struct DictObjOp { + + enum RequestType { + Prepare = 0, // Prepare create obj + Commit = 1, // Commit create obj + Abort = 2 // Prepare failed, drop instead + }; + + enum State { + Defined = 0, + Preparing = 1, + Prepared = 2, + Committing = 3, + Committed = 4, + Aborting = 5, + Aborted = 6 + }; +}; + +struct DictCommitReq +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 op_key; + + STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( GSN = GSN_DICT_COMMIT_REQ ); +}; + +struct DictCommitRef +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; + enum ErrorCode + { + NF_FakeErrorREF = 1 + }; + STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( GSN = GSN_DICT_COMMIT_REF ); +}; + +struct DictCommitConf +{ + Uint32 senderData; + Uint32 senderRef; + + STATIC_CONST( SignalLength = 2 ); + STATIC_CONST( GSN = GSN_DICT_COMMIT_CONF ); +}; + +struct DictAbortReq +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 op_key; + + STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( GSN = GSN_DICT_ABORT_REQ ); +}; + +struct DictAbortRef +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; + enum ErrorCode + { + NF_FakeErrorREF = 1 + }; + STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( GSN = GSN_DICT_ABORT_REF ); +}; + +struct DictAbortConf +{ + Uint32 senderData; + Uint32 senderRef; + + STATIC_CONST( SignalLength = 2 ); + STATIC_CONST( GSN = GSN_DICT_ABORT_CONF ); +}; + + +#endif diff --git a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp index 10f4fce57e8..4b5a9bef884 100644 --- a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp +++ b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp @@ -21,8 +21,8 @@ #include <AttributeDescriptor.hpp> #include <SimpleProperties.hpp> #include <ndb_limits.h> -#include <trigger_definitions.h> #include <NdbSqlUtil.hpp> +#include <ndb_global.h> #ifndef my_decimal_h @@ -90,9 +90,9 @@ public: CopyTable = 3, // Between DICT's ReadTableFromDiskSR = 4, // Local in DICT GetTabInfoConf = 5, - AlterTableFromAPI = 6 + AlterTableFromAPI = 6 }; - + enum KeyValues { TableName = 1, // String, Mandatory TableId = 2, //Mandatory between DICT's otherwise not allowed @@ -120,6 +120,8 @@ public: FragmentCount = 128, // No of fragments in table (!fragment replicas) FragmentDataLen = 129, FragmentData = 130, // CREATE_FRAGMENTATION reply + TablespaceId = 131, + TablespaceVersion = 132, TableEnd = 999, AttributeName = 1000, // String, Mandatory @@ -128,7 +130,7 @@ public: AttributeSize = 1003, //Default DictTabInfo::a32Bit AttributeArraySize = 1005, //Default 1 AttributeKeyFlag = 1006, //Default noKey - AttributeStorage = 1007, //Default MainMemory + AttributeStorageType = 1007, //Default NDB_STORAGETYPE_MEMORY AttributeNullableFlag = 1008, //Default NotNullable AttributeDKey = 1010, //Default NotDKey AttributeExtType = 1013, //Default ExtUnsigned @@ -136,7 +138,8 @@ public: AttributeExtScale = 1015, //Default 0 AttributeExtLength = 1016, //Default 0 AttributeAutoIncrement = 1017, //Default false - AttributeDefaultValue = 1018, //Default value (printable string) + AttributeDefaultValue = 1018, //Default value (printable string), + AttributeArrayType = 1019, //Default NDB_ARRAYTYPE_FIXED AttributeEnd = 1999 // }; // ---------------------------------------------------------------------- @@ -169,11 +172,17 @@ public: UniqueOrderedIndex = 5, OrderedIndex = 6, // constant 10 hardcoded in Dbdict.cpp - HashIndexTrigger = 10 + TriggerType::SECONDARY_INDEX, - SubscriptionTrigger = 10 + TriggerType::SUBSCRIPTION, - ReadOnlyConstraint = 10 + TriggerType::READ_ONLY_CONSTRAINT, - IndexTrigger = 10 + TriggerType::ORDERED_INDEX + HashIndexTrigger = 11, + SubscriptionTrigger = 16, + ReadOnlyConstraint = 17, + IndexTrigger = 18, + + Tablespace = 20, ///< Tablespace + LogfileGroup = 21, ///< Logfile group + Datafile = 22, ///< Datafile + Undofile = 23 ///< Undofile }; + static inline bool isTable(int tableType) { return @@ -212,7 +221,28 @@ public: tableType == UniqueOrderedIndex || tableType == OrderedIndex; } + static inline bool + isTrigger(int tableType) { + return + tableType == HashIndexTrigger || + tableType == SubscriptionTrigger || + tableType == ReadOnlyConstraint || + tableType == IndexTrigger; + } + static inline bool + isFilegroup(int tableType) { + return + tableType == Tablespace || + tableType == LogfileGroup; + } + static inline bool + isFile(int tableType) { + return + tableType == Datafile|| + tableType == Undofile; + } + // Object state for translating from/to API enum ObjectState { StateUndefined = 0, @@ -255,7 +285,6 @@ public: Uint32 MaxLoadFactor; Uint32 KeyLength; Uint32 FragmentType; - Uint32 TableStorage; Uint32 TableType; Uint32 TableVersion; Uint32 IndexState; @@ -263,6 +292,8 @@ public: Uint32 UpdateTriggerId; Uint32 DeleteTriggerId; Uint32 CustomTriggerId; + Uint32 TablespaceId; + Uint32 TablespaceVersion; Uint32 FrmLen; char FrmData[MAX_FRM_DATA_SIZE]; Uint32 FragmentCount; @@ -319,6 +350,7 @@ public: Uint32 AttributeType; // for osu 4.1->5.0.x Uint32 AttributeSize; Uint32 AttributeArraySize; + Uint32 AttributeArrayType; Uint32 AttributeKeyFlag; Uint32 AttributeNullableFlag; Uint32 AttributeDKey; @@ -327,6 +359,7 @@ public: Uint32 AttributeExtScale; Uint32 AttributeExtLength; Uint32 AttributeAutoIncrement; + Uint32 AttributeStorageType; char AttributeDefaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE]; void init(); @@ -463,8 +496,9 @@ public: fprintf(out, "AttributeType = %d\n", AttributeType); fprintf(out, "AttributeSize = %d\n", AttributeSize); fprintf(out, "AttributeArraySize = %d\n", AttributeArraySize); + fprintf(out, "AttributeArrayType = %d\n", AttributeArrayType); fprintf(out, "AttributeKeyFlag = %d\n", AttributeKeyFlag); - fprintf(out, "AttributeStorage = %d\n", AttributeStorage); + fprintf(out, "AttributeStorageType = %d\n", AttributeStorageType); fprintf(out, "AttributeNullableFlag = %d\n", AttributeNullableFlag); fprintf(out, "AttributeDKey = %d\n", AttributeDKey); fprintf(out, "AttributeGroup = %d\n", AttributeGroup); @@ -502,20 +536,134 @@ private: Uint32 tabInfoData[DataLength]; public: - enum Depricated + enum Depricated { AttributeDGroup = 1009, //Default NotDGroup AttributeStoredInd = 1011, //Default NotStored + TableStorageVal = 14, //Disk storage specified per attribute SecondTableId = 17, //Mandatory between DICT's otherwise not allowed FragmentKeyTypeVal = 16 //Default PrimaryKey }; - - enum Unimplemented + + enum Unimplemented { - TableStorageVal = 14, //Default StorageType::MainMemory ScanOptimised = 15, //Default updateOptimised AttributeGroup = 1012 //Default 0 }; }; +#define DFGIMAP(x, y, z) \ + { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::Uint32Value, 0, (~0), 0 } + +#define DFGIMAP2(x, y, z, u, v) \ + { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::Uint32Value, u, v, 0 } + +#define DFGIMAPS(x, y, z, u, v) \ + { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::StringValue, u, v, 0 } + +#define DFGIMAPB(x, y, z, u, v, l) \ + { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::BinaryValue, u, v, \ + offsetof(x, l) } + +#define DFGIBREAK(x) \ + { DictFilegroupInfo::x, 0, SimpleProperties::InvalidValue, 0, 0, 0 } + +struct DictFilegroupInfo { + enum KeyValues { + FilegroupName = 1, + FilegroupType = 2, + FilegroupId = 3, + FilegroupVersion = 4, + + /** + * File parameters + */ + FileName = 100, + FileType = 101, + FileId = 102, + FileNo = 103, // Per Filegroup + FileFGroupId = 104, + FileFGroupVersion = 105, + FileSizeHi = 106, + FileSizeLo = 107, + FileFreeExtents = 108, + FileEnd = 199, // + + /** + * Tablespace parameters + */ + TS_ExtentSize = 1000, // specified in bytes + TS_LogfileGroupId = 1001, + TS_LogfileGroupVersion = 1002, + TS_GrowLimit = 1003, // In bytes + TS_GrowSizeHi = 1004, + TS_GrowSizeLo = 1005, + TS_GrowPattern = 1006, + TS_GrowMaxSize = 1007, + + /** + * Logfile group parameters + */ + LF_UndoBufferSize = 2005, // In bytes + LF_UndoGrowLimit = 2000, // In bytes + LF_UndoGrowSizeHi = 2001, + LF_UndoGrowSizeLo = 2002, + LF_UndoGrowPattern = 2003, + LF_UndoGrowMaxSize = 2004 + }; + + // FragmentType constants + enum FileTypeValues { + Datafile = 0, + Undofile = 1 + //, Redofile + }; + + struct GrowSpec { + Uint32 GrowLimit; + Uint32 GrowSizeHi; + Uint32 GrowSizeLo; + char GrowPattern[PATH_MAX]; + Uint32 GrowMaxSize; + }; + + // Table data interpretation + struct Filegroup { + char FilegroupName[MAX_TAB_NAME_SIZE]; + Uint32 FilegroupType; // ObjType + Uint32 FilegroupId; + Uint32 FilegroupVersion; + + union { + Uint32 TS_ExtentSize; + Uint32 LF_UndoBufferSize; + }; + Uint32 TS_LogfileGroupId; + Uint32 TS_LogfileGroupVersion; + union { + GrowSpec TS_DataGrow; + GrowSpec LF_UndoGrow; + }; + //GrowSpec LF_RedoGrow; + void init(); + }; + static const Uint32 MappingSize; + static const SimpleProperties::SP2StructMapping Mapping[]; + + struct File { + char FileName[PATH_MAX]; + Uint32 FileType; + Uint32 FileNo; + Uint32 FileId; + Uint32 FilegroupId; + Uint32 FilegroupVersion; + Uint32 FileSizeHi; + Uint32 FileSizeLo; + Uint32 FileFreeExtents; + void init(); + }; + static const Uint32 FileMappingSize; + static const SimpleProperties::SP2StructMapping FileMapping[]; +}; + #endif diff --git a/storage/ndb/include/kernel/signaldata/DropFilegroup.hpp b/storage/ndb/include/kernel/signaldata/DropFilegroup.hpp new file mode 100644 index 00000000000..70ca21c203b --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/DropFilegroup.hpp @@ -0,0 +1,191 @@ +/* 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 DROP_FILEGROUP_HPP +#define DROP_FILEGROUP_HPP + +#include "SignalData.hpp" + +struct DropFilegroupReq { + /** + * Sender(s) / Reciver(s) + */ + friend class NdbDictInterface; + friend class Dbdict; + friend class Tsman; + + /** + * For printing + */ + friend bool printDROP_FILEGROUP_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + STATIC_CONST( GSN = GSN_DROP_FILEGROUP_REQ ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 filegroup_id; + Uint32 filegroup_version; +}; + +struct DropFilegroupRef { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class Ndbcntr; + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printDROP_FILEGROUP_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 7 ); + STATIC_CONST( GSN = GSN_DROP_FILEGROUP_REF ); + + enum ErrorCode { + NoError = 0, + Busy = 701, + NotMaster = 702, + NoSuchFilegroup = 767, + FilegroupInUse = 768 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 masterNodeId; + Uint32 errorCode; + Uint32 errorLine; + Uint32 errorKey; + +}; + +struct DropFilegroupConf { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class Ndbcntr; + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printDROP_FILEGROUP_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + STATIC_CONST( GSN = GSN_DROP_FILEGROUP_CONF ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 filegroupId; + Uint32 filegroupVersion; +}; + +struct DropFileReq { + /** + * Sender(s) / Reciver(s) + */ + friend class NdbDictInterface; + friend class Dbdict; + friend class Tsman; + + /** + * For printing + */ + friend bool printDROP_FILE_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + STATIC_CONST( GSN = GSN_DROP_FILE_REQ ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 file_id; + Uint32 file_version; +}; + +struct DropFileRef { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class Ndbcntr; + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printDROP_FILE_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 7 ); + STATIC_CONST( GSN = GSN_DROP_FILE_REF ); + + enum ErrorCode { + NoError = 0, + Busy = 701, + NoSuchFile = 766, + DropUndoFileNotSupported = 769 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 masterNodeId; + Uint32 errorCode; + Uint32 errorLine; + Uint32 errorKey; + +}; + +struct DropFileConf { + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Sender(s) / Reciver(s) + */ + friend class Ndbcntr; + friend class NdbDictInterface; + + /** + * For printing + */ + friend bool printDROP_FILE_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 4 ); + STATIC_CONST( GSN = GSN_DROP_FILE_CONF ); + + Uint32 senderData; + Uint32 senderRef; + Uint32 fileId; + Uint32 fileVersion; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/DropFilegroupImpl.hpp b/storage/ndb/include/kernel/signaldata/DropFilegroupImpl.hpp new file mode 100644 index 00000000000..fd61f5ebc45 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/DropFilegroupImpl.hpp @@ -0,0 +1,171 @@ +/* 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 DROP_FILEGROUP_IMPL_HPP +#define DROP_FILEGROUP_IMPL_HPP + +#include "SignalData.hpp" + +struct DropFilegroupImplReq { + /** + * Sender(s) / Reciver(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printDROP_FILEGROUP_IMPL_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 5 ); + + enum RequestInfo { + Prepare = 0x1, + Commit = 0x2, + Abort = 0x4 + }; + + Uint32 senderData; + Uint32 senderRef; + + Uint32 requestInfo; + Uint32 filegroup_id; + Uint32 filegroup_version; +}; + +struct DropFilegroupImplRef { + /** + * Sender(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printDROP_FILEGROUP_IMPL_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 3 ); + + enum ErrorCode { + NoError = 0, + NoSuchFilegroup = 767, + InvalidFilegroupVersion = 767, + FilegroupInUse = 768 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; +}; + +struct DropFilegroupImplConf { + /** + * Sender(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printDROP_FILEGROUP_IMPL_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 2 ); + + Uint32 senderData; + Uint32 senderRef; +}; + +struct DropFileImplReq { + /** + * Sender(s) / Reciver(s) + */ + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printDROP_FILE_IMPL_REQ(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 6 ); + + enum RequestInfo { + Prepare = 0x1, + Commit = 0x2, + Abort = 0x4 + }; + + Uint32 senderData; + Uint32 senderRef; + + Uint32 requestInfo; + Uint32 file_id; + Uint32 filegroup_id; + Uint32 filegroup_version; +}; + +struct DropFileImplRef { + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + /** + * For printing + */ + friend bool printDROP_FILE_IMPL_REF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 5 ); + + enum ErrorCode { + NoError = 0, + InvalidFilegroup = 767, + InvalidFilegroupVersion = 767, + NoSuchFile = 766, + FileInUse = 770 + }; + + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; + Uint32 fsErrCode; + Uint32 osErrCode; +}; + +struct DropFileImplConf { + friend class Dbdict; + friend class Tsman; + friend class Lgman; + + + /** + * For printing + */ + friend bool printDROP_FILE_IMPL_CONF(FILE*, const Uint32*, Uint32, Uint16); + + STATIC_CONST( SignalLength = 2 ); + + Uint32 senderData; + Uint32 senderRef; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/DropObj.hpp b/storage/ndb/include/kernel/signaldata/DropObj.hpp new file mode 100644 index 00000000000..42fd7191447 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/DropObj.hpp @@ -0,0 +1,118 @@ +/* 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 DROP_OBJ_HPP +#define DROP_OBJ_HPP + +#include "DictObjOp.hpp" +#include "SignalData.hpp" + +struct DropObjReq +{ + /** + * Sender(s) + */ + friend class Dbdict; + + /** + * Receiver(s) + */ + friend class Dbtc; + friend class Dblqh; + friend class Dbacc; + friend class Dbtup; + friend class Dbtux; + friend class Dbdih; + + friend bool printDROP_OBJ_REQ(FILE *, const Uint32 *, Uint32, Uint16); + STATIC_CONST( SignalLength = 9 ); + + Uint32 op_key; + Uint32 objId; + Uint32 objType; + Uint32 objVersion; + + Uint32 senderRef; + Uint32 senderData; + + Uint32 requestInfo; + + Uint32 clientRef; + Uint32 clientData; +}; + +class DropObjConf { + /** + * Sender(s) + */ + friend class Dbtc; + friend class Dblqh; + friend class Dbacc; + friend class Dbtup; + friend class Dbtux; + friend class Dbdih; + + /** + * Receiver(s) + */ + friend class Dbdict; + + friend bool printDROP_OBJ_CONF(FILE *, const Uint32 *, Uint32, Uint16); +public: + STATIC_CONST( SignalLength = 3 ); + +private: + Uint32 senderRef; + Uint32 senderData; + Uint32 objId; +}; + +class DropObjRef { + /** + * Sender(s) + */ + friend class Dbtc; + friend class Dblqh; + friend class Dbacc; + friend class Dbtup; + friend class Dbtux; + friend class Dbdih; + + /** + * Receiver(s) + */ + friend class Dbdict; + + friend bool printDROP_OBJ_REF(FILE *, const Uint32 *, Uint32, Uint16); +public: + STATIC_CONST( SignalLength = 4 ); + + enum ErrorCode { + NoSuchObj = 1, + DropWoPrep = 2, // Calling Drop with first calling PrepDrop + PrepDropInProgress = 3, + DropInProgress = 4, + NF_FakeErrorREF = 5 + }; + +private: + Uint32 senderRef; + Uint32 senderData; + Uint32 objId; + Uint32 errorCode; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp b/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp index bde690e056d..ca38c41e0f4 100644 --- a/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp +++ b/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp @@ -104,6 +104,8 @@ public: CmvmiDumpLongSignalMemory = 2601, CmvmiSetRestartOnErrorInsert = 2602, CmvmiTestLongSigWithDelay = 2603, + + LCPContinue = 5900, // 7000 DIH // 7001 DIH // 7002 DIH @@ -130,7 +132,11 @@ public: // 12000 Tux TuxLogToFile = 12001, TuxSetLogFlags = 12002, - TuxMetaDataJunk = 12009 + TuxMetaDataJunk = 12009, + + DumpTsman = 9000, + DumpLgman = 10000, + DumpPgman = 11000 }; public: diff --git a/storage/ndb/include/kernel/signaldata/Extent.hpp b/storage/ndb/include/kernel/signaldata/Extent.hpp new file mode 100644 index 00000000000..8443a2b3d45 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/Extent.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 NDB_EXTENT_HPP +#define NDB_EXTENT_HPP + +#include "SignalData.hpp" + +struct AllocExtentReq { + /** + * Sender(s) / Reciver(s) + */ + + /** + * For printing + */ + + STATIC_CONST( SignalLength = 3 ); + + enum ErrorCode { + UnmappedExtentPageIsNotImplemented = 1, + NoExtentAvailable = 2 + }; + + union + { + struct + { + Uint32 tablespace_id; + Uint32 table_id; + Uint32 fragment_id; + } request; + struct + { + Uint32 errorCode; + Local_key page_id; + Uint32 page_count; + } reply; + }; +}; + +struct FreeExtentReq { + /** + * Sender(s) / Reciver(s) + */ + + /** + * For printing + */ + + STATIC_CONST( SignalLength = 4 ); + + enum ErrorCode { + UnmappedExtentPageIsNotImplemented = 1 + }; + + union + { + struct + { + Local_key key; + Uint32 table_id; + Uint32 tablespace_id; + } request; + struct + { + Uint32 errorCode; + } reply; + }; +}; + +struct AllocPageReq { + /** + * Sender(s) / Reciver(s) + */ + + /** + * For printing + */ + + STATIC_CONST( SignalLength = 3 ); + + enum ErrorCode { + UnmappedExtentPageIsNotImplemented = 1, + NoPageFree= 2 + }; + + Local_key key; // in out + Uint32 bits; // in out + union + { + struct + { + Uint32 table_id; + Uint32 fragment_id; + Uint32 tablespace_id; + } request; + struct + { + Uint32 errorCode; + } reply; + }; +}; + + +#endif diff --git a/storage/ndb/include/kernel/signaldata/FsCloseReq.hpp b/storage/ndb/include/kernel/signaldata/FsCloseReq.hpp index 10d094fb30b..4ee2f0efd0a 100644 --- a/storage/ndb/include/kernel/signaldata/FsCloseReq.hpp +++ b/storage/ndb/include/kernel/signaldata/FsCloseReq.hpp @@ -30,12 +30,15 @@ class FsCloseReq { */ friend class Ndbfs; // Reciver friend class VoidFs; + friend class Lgman; + friend class Tsman; /** * Sender(s) */ friend class Backup; friend class Dbdict; + friend class Restore; /** * For printing diff --git a/storage/ndb/include/kernel/signaldata/FsConf.hpp b/storage/ndb/include/kernel/signaldata/FsConf.hpp index f66d9feea49..70da2b557de 100644 --- a/storage/ndb/include/kernel/signaldata/FsConf.hpp +++ b/storage/ndb/include/kernel/signaldata/FsConf.hpp @@ -38,7 +38,10 @@ class FsConf { friend class Dbacc; friend class Dbtup; friend class Dbdict; - + friend class Lgman; + friend class Tsman; + friend class Pgman; + friend class Restore; /** * Sender(s) */ @@ -66,10 +69,11 @@ private: */ UintR userPointer; // DATA 0 - /** - * Only used if FSOPENCONF - */ - UintR filePointer; // DATA 1 + // Data 1 + union { + UintR filePointer; // FSOPENCONF + Uint32 bytes_read; // FSREADCONF (when allow partial read) + }; }; diff --git a/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp b/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp index 906bb947128..1ac3ac883cc 100644 --- a/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp +++ b/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp @@ -40,6 +40,9 @@ class FsOpenReq { friend class Dbdict; friend class Ndbcntr; // For initial start... friend class Dbdih; + friend class Lgman; + friend class Tsman; + friend class Restore; /** * For printing @@ -50,8 +53,9 @@ public: /** * Length of signal */ - STATIC_CONST( SignalLength = 7 ); - + STATIC_CONST( SignalLength = 10 ); + SECTION( FILENAME = 0 ); + private: /** @@ -62,7 +66,10 @@ private: UintR userPointer; // DATA 1 UintR fileNumber[4]; // DATA 2 - 5 UintR fileFlags; // DATA 6 - + Uint32 page_size; + Uint32 file_size_hi; + Uint32 file_size_lo; + STATIC_CONST( OM_READONLY = 0 ); STATIC_CONST( OM_WRITEONLY = 1 ); STATIC_CONST( OM_READWRITE = 2 ); @@ -71,7 +78,13 @@ private: STATIC_CONST( OM_SYNC = 0x10 ); STATIC_CONST( OM_CREATE = 0x100 ); STATIC_CONST( OM_TRUNCATE = 0x200 ); + STATIC_CONST( OM_AUTOSYNC = 0x400 ); + STATIC_CONST( OM_CREATE_IF_NONE = 0x0400 ); + STATIC_CONST( OM_INIT = 0x0800 ); // + STATIC_CONST( OM_CHECK_SIZE = 0x1000 ); + STATIC_CONST( OM_DIRECT = 0x2000 ); + enum Suffixes { S_DATA = 0, S_FRAGLOG = 1, @@ -115,6 +128,15 @@ private: static void v2_setSequence(Uint32 fileNumber[], Uint32 no); static void v2_setNodeId(Uint32 fileNumber[], Uint32 no); static void v2_setCount(Uint32 fileNumber[], Uint32 no); + + /** + * V4 - LCP + */ + static Uint32 v5_getLcpNo(const Uint32 fileNumber[]); + static Uint32 v5_getTableId(const Uint32 fileNumber[]); + + static void v5_setLcpNo(Uint32 fileNumber[], Uint32 no); + static void v5_setTableId(Uint32 fileNumber[], Uint32 no); }; /** @@ -154,8 +176,19 @@ private: * * 1111111111222222222233 * 01234567890123456789012345678901 - * ppppppppddddddddssssssssvvvvvvvv + * ssssssssvvvvvvvv + * + * -- v3 -- + * File number[0] = Table + * File number[1] = LcpNo + * File number[2] = + * File number[3] = + * v = version 24 - 31 + * s = v1_suffix 16 - 23 * + * 1111111111222222222233 + * 01234567890123456789012345678901 + * ssssssssvvvvvvvv */ inline Uint32 FsOpenReq::getVersion(const Uint32 fileNumber[]){ @@ -262,6 +295,26 @@ void FsOpenReq::v2_setCount(Uint32 fileNumber[], Uint32 val){ fileNumber[2] = val; } +/****************/ +inline +Uint32 FsOpenReq::v5_getTableId(const Uint32 fileNumber[]){ + return fileNumber[0]; +} + +inline +void FsOpenReq::v5_setTableId(Uint32 fileNumber[], Uint32 val){ + fileNumber[0] = val; +} + +inline +Uint32 FsOpenReq::v5_getLcpNo(const Uint32 fileNumber[]){ + return fileNumber[1]; +} + +inline +void FsOpenReq::v5_setLcpNo(Uint32 fileNumber[], Uint32 val){ + fileNumber[1] = val; +} #endif diff --git a/storage/ndb/include/kernel/signaldata/FsReadWriteReq.hpp b/storage/ndb/include/kernel/signaldata/FsReadWriteReq.hpp index 6e4fa4d260e..c2825a77b21 100644 --- a/storage/ndb/include/kernel/signaldata/FsReadWriteReq.hpp +++ b/storage/ndb/include/kernel/signaldata/FsReadWriteReq.hpp @@ -35,12 +35,16 @@ class FsReadWriteReq { */ friend class Ndbfs; friend class VoidFs; + friend class AsyncFile; /** * Sender(s) */ friend class Dbdict; - + friend class Lgman; + friend class Tsman; + friend class Pgman; + friend class Restore; /** * For printing @@ -55,12 +59,14 @@ public: fsFormatListOfPairs=0, fsFormatArrayOfPages=1, fsFormatListOfMemPages=2, + fsFormatGlobalPage=3, fsFormatMax }; /** * Length of signal */ + STATIC_CONST( FixedLength = 6 ); private: @@ -100,6 +106,8 @@ private: static NdbfsFormatType getFormatFlag(const UintR & opFlag); static void setFormatFlag(UintR & opFlag, Uint8 flag); + static Uint32 getPartialReadFlag(UintR opFlag); + static void setPartialReadFlag(UintR & opFlag, Uint32 flag); }; /** @@ -118,6 +126,7 @@ private: #define FORMAT_MASK (0x0F) +#define PARTIAL_READ_SHIFT (5) inline Uint8 @@ -145,8 +154,18 @@ FsReadWriteReq::setFormatFlag(UintR & opFlag, Uint8 flag){ opFlag |= flag; } +inline +void +FsReadWriteReq::setPartialReadFlag(UintR & opFlag, Uint32 flag){ + ASSERT_BOOL(flag, "FsReadWriteReq::setSyncFlag"); + opFlag |= (flag << PARTIAL_READ_SHIFT); +} - +inline +Uint32 +FsReadWriteReq::getPartialReadFlag(UintR opFlag){ + return (opFlag >> PARTIAL_READ_SHIFT) & 1; +} #endif diff --git a/storage/ndb/include/kernel/signaldata/FsRef.hpp b/storage/ndb/include/kernel/signaldata/FsRef.hpp index a0e1dc55dae..1ae515050dd 100644 --- a/storage/ndb/include/kernel/signaldata/FsRef.hpp +++ b/storage/ndb/include/kernel/signaldata/FsRef.hpp @@ -33,9 +33,14 @@ * RECIVER: */ struct FsRef { - /** - * Enum type for errorCode - */ + + friend bool printFSREF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo); + + /** + * Enum type for errorCode + */ + STATIC_CONST( FS_ERR_BIT = 0x8000 ); + enum NdbfsErrorCodeType { fsErrNone=0, fsErrEnvironmentError=NDBD_EXIT_AFS_ENVIRONMENT, @@ -47,6 +52,9 @@ struct FsRef { fsErrNoMoreResources=NDBD_EXIT_AFS_NO_MORE_RESOURCES, fsErrFileDoesNotExist=NDBD_EXIT_AFS_NO_SUCH_FILE, fsErrReadUnderflow = NDBD_EXIT_AFS_READ_UNDERFLOW, + fsErrFileExists = FS_ERR_BIT | 12, + fsErrInvalidFileSize = FS_ERR_BIT | 13, + fsErrOutOfMemory = FS_ERR_BIT | 14, fsErrMax }; /** @@ -89,7 +97,4 @@ FsRef::setErrorCode(UintR & errorcode, UintR errorcodetype){ errorcode = errorcodetype; } - - - #endif diff --git a/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp b/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp index 6b223cab119..07144b672b6 100644 --- a/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp +++ b/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp @@ -86,6 +86,7 @@ public: InvalidTableId = 709, TableNotDefined = 723, TableNameTooLong = 702, + NoFetchByName = 710, Busy = 701 }; }; @@ -105,14 +106,19 @@ class GetTabInfoConf { friend bool printGET_TABINFO_CONF(FILE *, const Uint32 *, Uint32, Uint16); public: - STATIC_CONST( SignalLength = 4 ); + STATIC_CONST( SignalLength = 6 ); SECTION( DICT_TAB_INFO = 0 ); public: Uint32 senderData; Uint32 tableId; Uint32 gci; // For table - Uint32 totalLen; // In words + union { + Uint32 totalLen; // In words + Uint32 freeExtents; + }; + Uint32 tableType; + Uint32 senderRef; }; #endif diff --git a/storage/ndb/include/kernel/signaldata/KeyInfo.hpp b/storage/ndb/include/kernel/signaldata/KeyInfo.hpp index 686f3ae053d..d3274714f21 100644 --- a/storage/ndb/include/kernel/signaldata/KeyInfo.hpp +++ b/storage/ndb/include/kernel/signaldata/KeyInfo.hpp @@ -27,6 +27,7 @@ class KeyInfo { friend class NdbOperation; friend class NdbScanOperation; friend class NdbIndexScanOperation; + friend class Restore; /** * Reciver(s) diff --git a/storage/ndb/include/kernel/signaldata/LCP.hpp b/storage/ndb/include/kernel/signaldata/LCP.hpp index 7d3fb71ae7e..ade9f17c138 100644 --- a/storage/ndb/include/kernel/signaldata/LCP.hpp +++ b/storage/ndb/include/kernel/signaldata/LCP.hpp @@ -81,7 +81,10 @@ class LcpFragOrd { * Sender(s) */ friend class Dbdih; - + friend class Lgman; + friend class Pgman; + friend class Dbtup; + /** * Sender(s) / Receiver(s) */ @@ -151,4 +154,66 @@ private: Uint32 lcpId; }; +struct LcpPrepareReq +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 lcpNo; + Uint32 tableId; + Uint32 fragmentId; + Uint32 lcpId; + Uint32 backupPtr; + Uint32 backupId; + + STATIC_CONST( SignalLength = 8 ); +}; + +struct LcpPrepareRef +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 tableId; + Uint32 fragmentId; + Uint32 errorCode; + + STATIC_CONST( SignalLength = 5 ); +}; + +struct LcpPrepareConf +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 tableId; + Uint32 fragmentId; + + STATIC_CONST( SignalLength = 4 ); +}; + +struct EndLcpReq +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 backupPtr; + Uint32 backupId; + + STATIC_CONST( SignalLength = 4 ); +}; + +struct EndLcpRef +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; + + STATIC_CONST( SignalLength = 3 ); +}; + +struct EndLcpConf +{ + Uint32 senderData; + Uint32 senderRef; + + STATIC_CONST( SignalLength = 2 ); +}; + #endif diff --git a/storage/ndb/include/kernel/signaldata/LgmanContinueB.hpp b/storage/ndb/include/kernel/signaldata/LgmanContinueB.hpp new file mode 100644 index 00000000000..b9bc1856800 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/LgmanContinueB.hpp @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef LGMAN_CONTINUEB_H +#define LGMAN_CONTINUEB_H + +#include "SignalData.hpp" + +struct LgmanContinueB { + + enum { + CUT_LOG_TAIL = 0 + ,FILTER_LOG = 1 + ,FLUSH_LOG = 2 + ,PROCESS_LOG_BUFFER_WAITERS = 3 + ,FIND_LOG_HEAD = 4 + ,EXECUTE_UNDO_RECORD = 5 + ,READ_UNDO_LOG = 6 + ,STOP_UNDO_LOG = 7 + ,PROCESS_LOG_SYNC_WAITERS = 8 + ,FORCE_LOG_SYNC = 9 + ,DROP_FILEGROUP = 10 + }; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/LqhFrag.hpp b/storage/ndb/include/kernel/signaldata/LqhFrag.hpp index 13dfafcc653..2c4e1fc9e72 100644 --- a/storage/ndb/include/kernel/signaldata/LqhFrag.hpp +++ b/storage/ndb/include/kernel/signaldata/LqhFrag.hpp @@ -104,7 +104,7 @@ class LqhFragReq { friend bool printLQH_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16); public: - STATIC_CONST( SignalLength = 25 ); + STATIC_CONST( SignalLength = 19 ); enum RequestInfo { CreateInRunning = 0x8000000, @@ -116,27 +116,27 @@ private: Uint32 senderRef; Uint32 fragmentId; Uint32 requestInfo; - Uint32 tableId; - Uint32 localKeyLength; Uint32 maxLoadFactor; Uint32 minLoadFactor; Uint32 kValue; - Uint32 lh3DistrBits; - Uint32 lh3PageBits; - Uint32 noOfAttributes; - Uint32 noOfNullAttributes; - Uint32 noOfPagesToPreAllocate; Uint32 schemaVersion; - Uint32 keyLength; Uint32 nextLCP; - Uint32 noOfKeyAttr; Uint32 noOfNewAttr; // noOfCharsets in upper half - Uint32 checksumIndicator; - Uint32 noOfAttributeGroups; - Uint32 GCPIndicator; Uint32 startGci; Uint32 tableType; // DictTabInfo::TableType Uint32 primaryTableId; // table of index or RNIL + Uint32 tablespace_id; // RNIL for MM table + Uint16 tableId; + Uint16 localKeyLength; + Uint16 lh3DistrBits; + Uint16 lh3PageBits; + Uint16 noOfAttributes; + Uint16 noOfNullAttributes; + Uint16 noOfPagesToPreAllocate; + Uint16 keyLength; + Uint16 noOfKeyAttr; + Uint8 checksumIndicator; + Uint8 GCPIndicator; }; class LqhFragConf { diff --git a/storage/ndb/include/kernel/signaldata/LqhKey.hpp b/storage/ndb/include/kernel/signaldata/LqhKey.hpp index e937180e3f7..cc9f1dacef4 100644 --- a/storage/ndb/include/kernel/signaldata/LqhKey.hpp +++ b/storage/ndb/include/kernel/signaldata/LqhKey.hpp @@ -29,7 +29,8 @@ class LqhKeyReq { * Sender(s) */ friend class Dbtc; - + friend class Restore; + /** * For printing */ @@ -95,6 +96,7 @@ private: static UintR getReturnedReadLenAIFlag(const UintR & requestInfo); static UintR getApplicationAddressFlag(const UintR & requestInfo); static UintR getMarkerFlag(const UintR & requestInfo); + static UintR getNoDiskFlag(const UintR & requestInfo); /** * Setters @@ -124,6 +126,7 @@ private: static void setReturnedReadLenAIFlag(UintR & requestInfo, UintR val); static void setApplicationAddressFlag(UintR & requestInfo, UintR val); static void setMarkerFlag(UintR & requestInfo, UintR val); + static void setNoDiskFlag(UintR & requestInfo, UintR val); }; /** @@ -142,11 +145,12 @@ private: * c = Same client and tc - 1 Bit (27) * u = Read Len Return Ind - 1 Bit (28) * m = Commit ack marker - 1 Bit (29) - * - = Unused - 2 Bits (30-31) + * x = No disk usage - 1 Bit (30) + * - = Unused - 2 Bit (31) * * 1111111111222222222233 * 01234567890123456789012345678901 - * kkkkkkkkkklltttpdisooorraaacum-- + * kkkkkkkkkklltttpdisooorraaacumx- */ #define RI_KEYLEN_SHIFT (0) @@ -168,6 +172,7 @@ private: #define RI_SAME_CLIENT_SHIFT (27) #define RI_RETURN_AI_SHIFT (28) #define RI_MARKER_SHIFT (29) +#define RI_NODISK_SHIFT (30) /** * Scan Info @@ -464,11 +469,25 @@ LqhKeyReq::getMarkerFlag(const UintR & requestInfo){ return (requestInfo >> RI_MARKER_SHIFT) & 1; } +inline +void +LqhKeyReq::setNoDiskFlag(UintR & requestInfo, UintR val){ + ASSERT_BOOL(val, "LqhKeyReq::setNoDiskFlag"); + requestInfo |= (val << RI_NODISK_SHIFT); +} + +inline +UintR +LqhKeyReq::getNoDiskFlag(const UintR & requestInfo){ + return (requestInfo >> RI_NODISK_SHIFT) & 1; +} + class LqhKeyConf { /** * Reciver(s) */ friend class Dbtc; + friend class Restore; /** * Sender(s) diff --git a/storage/ndb/include/kernel/signaldata/PgmanContinueB.hpp b/storage/ndb/include/kernel/signaldata/PgmanContinueB.hpp new file mode 100644 index 00000000000..9a8beff0448 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/PgmanContinueB.hpp @@ -0,0 +1,36 @@ +/* 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_CONTINUEB_H +#define PGMAN_CONTINUEB_H + +#include "SignalData.hpp" + +class PgmanContinueB { + /** + * Sender(s)/Reciver(s) + */ + friend class Pgman; +private: + enum { + STATS_LOOP = 0, + BUSY_LOOP = 1, + CLEANUP_LOOP = 2, + LCP_LOOP = 3 + }; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/RestoreContinueB.hpp b/storage/ndb/include/kernel/signaldata/RestoreContinueB.hpp new file mode 100644 index 00000000000..837f7df29a8 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/RestoreContinueB.hpp @@ -0,0 +1,38 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef RESTORE_CONTINUEB_H +#define RESTORE_CONTINUEB_H + +#include "SignalData.hpp" + +class RestoreContinueB { + /** + * Sender(s)/Reciver(s) + */ + friend class Restore; + friend bool printCONTINUEB_RESTORE(FILE * output, const Uint32 * theData, Uint32 len); +private: + enum { + START_FILE_THREAD = 0, + BUFFER_UNDERFLOW = 1, + BUFFER_FULL_SCAN = 2, + BUFFER_FULL_FRAG_COMPLETE = 3, + BUFFER_FULL_META = 4 + }; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/RestoreImpl.hpp b/storage/ndb/include/kernel/signaldata/RestoreImpl.hpp new file mode 100644 index 00000000000..01e4dad4b2a --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/RestoreImpl.hpp @@ -0,0 +1,66 @@ +/* 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_SIGNAL_DATA_HPP +#define RESTORE_SIGNAL_DATA_HPP + +#include "SignalData.hpp" + +struct RestoreLcpReq +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 lcpNo; + Uint32 tableId; + Uint32 fragmentId; + Uint32 lcpId; + STATIC_CONST( SignalLength = 6 ); +}; + +struct RestoreLcpRef +{ + Uint32 senderData; + Uint32 senderRef; + Uint32 errorCode; + Uint32 extra[1]; + STATIC_CONST( SignalLength = 3 ); + + enum ErrorCode + { + OK = 0, + NoFileRecord = 1, + OutOfDataBuffer = 2, + OutOfReadBufferPages = 3, + InvalidFileFormat = 4 + }; +}; + +struct RestoreLcpConf +{ + Uint32 senderData; + Uint32 senderRef; + STATIC_CONST( SignalLength = 2 ); +}; + +struct RestoreContinueB { + + enum { + RESTORE_NEXT = 0, + READ_FILE = 1 + }; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/ScanFrag.hpp b/storage/ndb/include/kernel/signaldata/ScanFrag.hpp index f21a3eef7ac..3c767c7f69c 100644 --- a/storage/ndb/include/kernel/signaldata/ScanFrag.hpp +++ b/storage/ndb/include/kernel/signaldata/ScanFrag.hpp @@ -60,6 +60,7 @@ public: static Uint32 getTupScanFlag(const Uint32 & requestInfo); static Uint32 getAttrLen(const Uint32 & requestInfo); static Uint32 getScanPrio(const Uint32 & requestInfo); + static Uint32 getNoDiskFlag(const Uint32 & requestInfo); static void setLockMode(Uint32 & requestInfo, Uint32 lockMode); static void setHoldLockFlag(Uint32 & requestInfo, Uint32 holdLock); @@ -70,6 +71,7 @@ public: static void setTupScanFlag(Uint32 & requestInfo, Uint32 tupScan); static void setAttrLen(Uint32 & requestInfo, Uint32 attrLen); static void setScanPrio(Uint32& requestInfo, Uint32 prio); + static void setNoDiskFlag(Uint32& requestInfo, Uint32 val); }; class KeyInfo20 { @@ -196,6 +198,7 @@ public: * Request Info * * a = Length of attrinfo - 16 Bits (16-31) + * d = No disk - 1 Bit 4 * l = Lock Mode - 1 Bit 5 * h = Hold lock - 1 Bit 7 * k = Keyinfo - 1 Bit 8 @@ -207,11 +210,12 @@ public: * * 1111111111222222222233 * 01234567890123456789012345678901 - * lxhkrztppppaaaaaaaaaaaaaaaa + * dlxhkrztppppaaaaaaaaaaaaaaaa */ #define SF_LOCK_MODE_SHIFT (5) #define SF_LOCK_MODE_MASK (1) +#define SF_NO_DISK_SHIFT (4) #define SF_HOLD_LOCK_SHIFT (7) #define SF_KEYINFO_SHIFT (8) #define SF_READ_COMMITTED_SHIFT (9) @@ -344,6 +348,19 @@ ScanFragReq::setAttrLen(UintR & requestInfo, UintR val){ inline Uint32 +ScanFragReq::getNoDiskFlag(const Uint32 & requestInfo){ + return (requestInfo >> SF_NO_DISK_SHIFT) & 1; +} + +inline +void +ScanFragReq::setNoDiskFlag(UintR & requestInfo, UintR val){ + ASSERT_BOOL(val, "ScanFragReq::setNoDiskFlag"); + requestInfo |= (val << SF_NO_DISK_SHIFT); +} + +inline +Uint32 KeyInfo20::setScanInfo(Uint32 opNo, Uint32 scanNo){ ASSERT_MAX(opNo, 1023, "KeyInfo20::setScanInfo"); ASSERT_MAX(scanNo, 255, "KeyInfo20::setScanInfo"); diff --git a/storage/ndb/include/kernel/signaldata/ScanTab.hpp b/storage/ndb/include/kernel/signaldata/ScanTab.hpp index 8cb282270ff..0435665ef2d 100644 --- a/storage/ndb/include/kernel/signaldata/ScanTab.hpp +++ b/storage/ndb/include/kernel/signaldata/ScanTab.hpp @@ -85,6 +85,7 @@ private: static Uint8 getKeyinfoFlag(const UintR & requestInfo); static Uint16 getScanBatch(const UintR & requestInfo); static Uint8 getDistributionKeyFlag(const UintR & requestInfo); + static UintR getNoDiskFlag(const UintR & requestInfo); /** * Set:ers for requestInfo @@ -100,6 +101,7 @@ private: static void setKeyinfoFlag(UintR & requestInfo, Uint32 flag); static void setScanBatch(Uint32& requestInfo, Uint32 sz); static void setDistributionKeyFlag(Uint32& requestInfo, Uint32 flag); + static void setNoDiskFlag(UintR & requestInfo, UintR val); }; /** @@ -115,10 +117,11 @@ private: x = Range Scan (TUX) - 1 Bit 15 b = Scan batch - 10 Bit 16-25 (max 1023) d = Distribution key flag + n = No disk flag 1111111111222222222233 01234567890123456789012345678901 - ppppppppl hcktzxbbbbbbbbbb + pppppppplnhcktzxbbbbbbbbbb */ #define PARALLELL_SHIFT (0) @@ -150,6 +153,8 @@ private: #define SCAN_DISTR_KEY_SHIFT (26) +#define SCAN_NODISK_SHIFT (9) + inline Uint8 ScanTabReq::getParallelism(const UintR & requestInfo){ @@ -287,6 +292,19 @@ ScanTabReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){ requestInfo |= (flag << SCAN_DISTR_KEY_SHIFT); } +inline +UintR +ScanTabReq::getNoDiskFlag(const UintR & requestInfo){ + return (requestInfo >> SCAN_NODISK_SHIFT) & 1; +} + +inline +void +ScanTabReq::setNoDiskFlag(UintR & requestInfo, Uint32 flag){ + ASSERT_BOOL(flag, "TcKeyReq::setNoDiskFlag"); + requestInfo |= (flag << SCAN_NODISK_SHIFT); +} + /** * * SENDER: Dbtc diff --git a/storage/ndb/include/kernel/signaldata/StartFragReq.hpp b/storage/ndb/include/kernel/signaldata/StartFragReq.hpp index ab17a147195..eb547d97472 100644 --- a/storage/ndb/include/kernel/signaldata/StartFragReq.hpp +++ b/storage/ndb/include/kernel/signaldata/StartFragReq.hpp @@ -32,9 +32,8 @@ class StartFragReq { public: STATIC_CONST( SignalLength = 19 ); - friend bool printSTART_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16); + friend bool printSTART_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16); -private: Uint32 userPtr; Uint32 userRef; Uint32 lcpNo; diff --git a/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp b/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp index d7c11ca773c..a37f3811b25 100644 --- a/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp +++ b/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp @@ -127,8 +127,6 @@ private: static Uint8 getSimpleFlag(const UintR & requestInfo); static Uint8 getDirtyFlag(const UintR & requestInfo); static Uint8 getInterpretedFlag(const UintR & requestInfo); - static Uint8 getDistributionGroupFlag(const UintR & requestInfo); - static Uint8 getDistributionGroupTypeFlag(const UintR & requestInfo); static Uint8 getDistributionKeyFlag(const UintR & requestInfo); static Uint8 getScanIndFlag(const UintR & requestInfo); static Uint8 getOperationType(const UintR & requestInfo); @@ -137,6 +135,7 @@ private: static Uint16 getKeyLength(const UintR & requestInfo); static Uint8 getAIInTcKeyReq(const UintR & requestInfo); static Uint8 getExecutingTrigger(const UintR & requestInfo); + static UintR getNoDiskFlag(const UintR & requestInfo); /** * Get:ers for scanInfo @@ -156,8 +155,6 @@ private: static void setSimpleFlag(UintR & requestInfo, Uint32 flag); static void setDirtyFlag(UintR & requestInfo, Uint32 flag); static void setInterpretedFlag(UintR & requestInfo, Uint32 flag); - static void setDistributionGroupFlag(UintR & requestInfo, Uint32 flag); - static void setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag); static void setDistributionKeyFlag(UintR & requestInfo, Uint32 flag); static void setScanIndFlag(UintR & requestInfo, Uint32 flag); static void setExecuteFlag(UintR & requestInfo, Uint32 flag); @@ -166,6 +163,7 @@ private: static void setKeyLength(UintR & requestInfo, Uint32 len); static void setAIInTcKeyReq(UintR & requestInfo, Uint32 len); static void setExecutingTrigger(UintR & requestInfo, Uint32 flag); + static void setNoDiskFlag(UintR & requestInfo, UintR val); /** * Set:ers for scanInfo @@ -184,29 +182,27 @@ private: d = Dirty Indicator - 1 Bit 0 e = Scan Indicator - 1 Bit 14 f = Execute fired trigger - 1 Bit 19 - g = Distribution Group Ind- 1 Bit 1 i = Interpreted Indicator - 1 Bit 15 k = Key length - 12 Bits -> Max 4095 (Bit 20 - 31) o = Operation Type - 3 Bits -> Max 7 (Bit 5-7) l = Execute - 1 Bit 10 p = Simple Indicator - 1 Bit 8 s = Start Indicator - 1 Bit 11 - t = Distribution GroupType- 1 Bit 3 y = Commit Type - 2 Bit 12-13 + n = No disk flag - 1 Bit 1 1111111111222222222233 01234567890123456789012345678901 - dgbtcooop lsyyeiaaafkkkkkkkkkkkk + dnb cooop lsyyeiaaafkkkkkkkkkkkk */ +#define TCKEY_NODISK_SHIFT (1) #define COMMIT_SHIFT (4) #define START_SHIFT (11) #define SIMPLE_SHIFT (8) #define DIRTY_SHIFT (0) #define EXECUTE_SHIFT (10) #define INTERPRETED_SHIFT (15) -#define DISTR_GROUP_SHIFT (1) -#define DISTR_GROUP_TYPE_SHIFT (3) #define DISTR_KEY_SHIFT (2) #define SCAN_SHIFT (14) @@ -305,18 +301,6 @@ TcKeyReq::getInterpretedFlag(const UintR & requestInfo){ inline Uint8 -TcKeyReq::getDistributionGroupFlag(const UintR & requestInfo){ - return (Uint8)((requestInfo >> DISTR_GROUP_SHIFT) & 1); -} - -inline -Uint8 -TcKeyReq::getDistributionGroupTypeFlag(const UintR & requestInfo){ - return (Uint8)((requestInfo >> DISTR_GROUP_TYPE_SHIFT) & 1); -} - -inline -Uint8 TcKeyReq::getDistributionKeyFlag(const UintR & requestInfo){ return (Uint8)((requestInfo >> DISTR_KEY_SHIFT) & 1); } @@ -415,22 +399,6 @@ TcKeyReq::setInterpretedFlag(UintR & requestInfo, Uint32 flag){ inline void -TcKeyReq::setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag){ - ASSERT_BOOL(flag, "TcKeyReq::setDistributionGroupTypeFlag"); - requestInfo &= ~(1 << DISTR_GROUP_TYPE_SHIFT); - requestInfo |= (flag << DISTR_GROUP_TYPE_SHIFT); -} - -inline -void -TcKeyReq::setDistributionGroupFlag(UintR & requestInfo, Uint32 flag){ - ASSERT_BOOL(flag, "TcKeyReq::setDistributionGroupFlag"); - requestInfo &= ~(1 << DISTR_GROUP_SHIFT); - requestInfo |= (flag << DISTR_GROUP_SHIFT); -} - -inline -void TcKeyReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){ ASSERT_BOOL(flag, "TcKeyReq::setDistributionKeyFlag"); requestInfo &= ~(1 << DISTR_KEY_SHIFT); @@ -544,5 +512,18 @@ TcKeyReq::setAttrinfoLen(UintR & anAttrLen, Uint16 aiLen){ anAttrLen |= aiLen; } +inline +UintR +TcKeyReq::getNoDiskFlag(const UintR & requestInfo){ + return (requestInfo >> TCKEY_NODISK_SHIFT) & 1; +} + +inline +void +TcKeyReq::setNoDiskFlag(UintR & requestInfo, Uint32 flag){ + ASSERT_BOOL(flag, "TcKeyReq::setNoDiskFlag"); + requestInfo &= ~(1 << TCKEY_NODISK_SHIFT); + requestInfo |= (flag << TCKEY_NODISK_SHIFT); +} #endif diff --git a/storage/ndb/include/kernel/signaldata/TsmanContinueB.hpp b/storage/ndb/include/kernel/signaldata/TsmanContinueB.hpp new file mode 100644 index 00000000000..862cd8d3ee9 --- /dev/null +++ b/storage/ndb/include/kernel/signaldata/TsmanContinueB.hpp @@ -0,0 +1,37 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef TSMAN_CONTINUEB_H +#define TSMAN_CONTINUEB_H + +#include "SignalData.hpp" + +class TsmanContinueB { + /** + * Sender(s)/Reciver(s) + */ + friend class Tsman; +private: + enum { + LOAD_EXTENT_PAGES = 0, + SCAN_TABLESPACE_EXTENT_HEADERS = 1, + SCAN_DATAFILE_EXTENT_HEADERS = 2, + END_LCP = 3, + RELEASE_EXTENT_PAGES = 4 + }; +}; + +#endif diff --git a/storage/ndb/include/kernel/signaldata/TupFrag.hpp b/storage/ndb/include/kernel/signaldata/TupFrag.hpp index 8acb3d28bd6..53581dec56d 100644 --- a/storage/ndb/include/kernel/signaldata/TupFrag.hpp +++ b/storage/ndb/include/kernel/signaldata/TupFrag.hpp @@ -30,7 +30,7 @@ class TupFragReq { friend class Dblqh; friend class Dbtup; public: - STATIC_CONST( SignalLength = 14 ); + STATIC_CONST( SignalLength = 15 ); private: Uint32 userPtr; Uint32 userRef; @@ -39,6 +39,7 @@ private: Uint32 noOfAttr; Uint32 fragId; Uint32 todo[8]; + Uint32 tablespaceid; }; class TupFragConf { diff --git a/storage/ndb/include/kernel/signaldata/TupKey.hpp b/storage/ndb/include/kernel/signaldata/TupKey.hpp index ffd57d81e64..0706d057d94 100644 --- a/storage/ndb/include/kernel/signaldata/TupKey.hpp +++ b/storage/ndb/include/kernel/signaldata/TupKey.hpp @@ -36,7 +36,7 @@ class TupKeyReq { friend bool printTUPKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo); public: - STATIC_CONST( SignalLength = 18 ); + STATIC_CONST( SignalLength = 16 ); private: @@ -45,14 +45,11 @@ private: */ Uint32 connectPtr; Uint32 request; - Uint32 tableRef; - Uint32 fragId; Uint32 keyRef1; Uint32 keyRef2; Uint32 attrBufLen; Uint32 opRef; Uint32 applRef; - Uint32 schemaVersion; Uint32 storedProcedure; Uint32 transId1; Uint32 transId2; @@ -61,6 +58,7 @@ private: Uint32 coordinatorTC; Uint32 tcOpIndex; Uint32 savePointId; + Uint32 disk_page; }; class TupKeyConf { diff --git a/storage/ndb/include/kernel/signaldata/TuxMaint.hpp b/storage/ndb/include/kernel/signaldata/TuxMaint.hpp index 4518f0531ea..9bc62bb9aa2 100644 --- a/storage/ndb/include/kernel/signaldata/TuxMaint.hpp +++ b/storage/ndb/include/kernel/signaldata/TuxMaint.hpp @@ -40,7 +40,7 @@ public: NoMemError = 902 }; STATIC_CONST( SignalLength = 8 ); -private: + /* * Error code set by TUX. Zero means no error. */ @@ -56,12 +56,15 @@ private: * and version number. */ Uint32 pageId; - Uint32 pageOffset; + Uint32 pageIndex; Uint32 tupVersion; /* * Operation code and flags. */ Uint32 opInfo; + + Uint32 tupFragPtrI; + Uint32 fragPageId; }; #endif diff --git a/storage/ndb/include/kernel/trigger_definitions.h b/storage/ndb/include/kernel/trigger_definitions.h index 11410654a15..25ec9730c49 100644 --- a/storage/ndb/include/kernel/trigger_definitions.h +++ b/storage/ndb/include/kernel/trigger_definitions.h @@ -19,6 +19,7 @@ #include <ndb_global.h> #include "ndb_limits.h" +#include <signaldata/DictTabInfo.hpp> #ifndef MIN #define MIN(x,y) (((x)<(y))?(x):(y)) @@ -32,16 +33,17 @@ struct TriggerType { enum Value { - CONSTRAINT = 0, - SECONDARY_INDEX = 1, - FOREIGN_KEY = 2, - SCHEMA_UPGRADE = 3, - API_TRIGGER = 4, - SQL_TRIGGER = 5, - SUBSCRIPTION = 6, - READ_ONLY_CONSTRAINT = 7, - ORDERED_INDEX = 8, - SUBSCRIPTION_BEFORE = 9 + //CONSTRAINT = 0, + SECONDARY_INDEX = DictTabInfo::HashIndexTrigger, + //FOREIGN_KEY = 2, + //SCHEMA_UPGRADE = 3, + //API_TRIGGER = 4, + //SQL_TRIGGER = 5, + SUBSCRIPTION = DictTabInfo::SubscriptionTrigger, + READ_ONLY_CONSTRAINT = DictTabInfo::ReadOnlyConstraint, + ORDERED_INDEX = DictTabInfo::IndexTrigger, + + SUBSCRIPTION_BEFORE = 9 // Only used by TUP/SUMA, should be REMOVED!! }; }; diff --git a/storage/ndb/include/ndb_constants.h b/storage/ndb/include/ndb_constants.h index c292880749b..0626fcb7bf3 100644 --- a/storage/ndb/include/ndb_constants.h +++ b/storage/ndb/include/ndb_constants.h @@ -68,5 +68,21 @@ #define NDB_TYPE_DECIMALUNSIGNED 30 #define NDB_TYPE_MAX 31 + + +/* + * Attribute array type. + */ + +#define NDB_ARRAYTYPE_FIXED 0 /* 0 length bytes */ +#define NDB_ARRAYTYPE_SHORT_VAR 1 /* 1 length bytes */ +#define NDB_ARRAYTYPE_MEDIUM_VAR 2 /* 2 length bytes */ + +/* + * Attribute storage type. + */ + +#define NDB_STORAGETYPE_MEMORY 0 +#define NDB_STORAGETYPE_DISK 1 #endif diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp index d820759b935..954dcc62a22 100644 --- a/storage/ndb/include/ndbapi/NdbDictionary.hpp +++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp @@ -106,7 +106,11 @@ public: HashIndexTrigger = 7, ///< Index maintenance, internal IndexTrigger = 8, ///< Index maintenance, internal SubscriptionTrigger = 9,///< Backup or replication, internal - ReadOnlyConstraint = 10 ///< Trigger, internal + ReadOnlyConstraint = 10,///< Trigger, internal + Tablespace = 20, ///< Tablespace + LogfileGroup = 21, ///< Logfile group + Datafile = 22, ///< Datafile + Undofile = 23 ///< Undofile }; /** @@ -155,7 +159,8 @@ public: }; class Table; // forward declaration - + class Tablespace; // forward declaration + /** * @class Column * @brief Represents a column in an NDB Cluster table @@ -212,6 +217,34 @@ public: Timestamp = NDB_TYPE_TIMESTAMP ///< Unix time }; + /* + * Array type specifies internal attribute format. + * + * - ArrayTypeFixed is stored as fixed number of bytes. This type + * is fastest to access but can waste space. + * + * - ArrayTypeVar is stored as variable number of bytes with a fixed + * overhead of 2 bytes. + * + * Default is ArrayTypeVar for Var* types and ArrayTypeFixed for + * others. The default is normally ok. + */ + enum ArrayType { + ArrayTypeFixed = NDB_ARRAYTYPE_FIXED, // 0 length bytes + ArrayTypeShortVar = NDB_ARRAYTYPE_SHORT_VAR, // 1 length bytes + ArrayTypeMediumVar = NDB_ARRAYTYPE_MEDIUM_VAR // 2 length bytes + }; + + /* + * Storage type specifies whether attribute is stored in memory or + * on disk. Default is memory. Disk attributes are potentially + * much slower to access and cannot be indexed in version 5.1. + */ + enum StorageType { + StorageTypeMemory = NDB_STORAGETYPE_MEMORY, + StorageTypeDisk = NDB_STORAGETYPE_DISK + }; + /** * @name General * @{ @@ -238,6 +271,10 @@ public: */ int getColumnNo() const; +#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL + int getAttrId() const; +#endif + /** * Check if column is equal to some other column * @param column Column to compare with @@ -331,6 +368,9 @@ public: inline bool getDistributionKey() const { return getPartitionKey(); }; #endif + ArrayType getArrayType() const; + StorageType getStorageType() const; + /** @} *******************************************************************/ @@ -439,6 +479,9 @@ public: { setPartitionKey(enable); }; #endif + void setArrayType(ArrayType type); + void setStorageType(StorageType type); + /** @} *******************************************************************/ #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL @@ -456,6 +499,7 @@ public: static const Column * COMMIT_COUNT; static const Column * ROW_SIZE; static const Column * RANGE_NO; + static const Column * DISK_REF; static const Column * RECORDS_IN_RANGE; int getSizeInBytes() const; @@ -704,6 +748,10 @@ public: */ void setMaxLoadFactor(int); + void setTablespace(const char * name); + void setTablespace(const class Tablespace &); + const char * getTablespace() const; + /** * Get table object type */ @@ -1122,6 +1170,158 @@ public: Event(NdbEventImpl&); }; + struct AutoGrowSpecification { + Uint32 min_free; + Uint64 max_size; + Uint64 file_size; + const char * filename_pattern; + }; + + /** + * @class LogfileGroup + */ + class LogfileGroup : public Object { + public: + LogfileGroup(); + virtual ~LogfileGroup(); + + void setName(const char * name); + const char* getName() const; + + void setUndoBufferSize(Uint32 sz); + Uint32 getUndoBufferSize() const; + + void setAutoGrowSpecification(const AutoGrowSpecification&); + const AutoGrowSpecification& getAutoGrowSpecification() const; + + /** + * Get object status + */ + virtual Object::Status getObjectStatus() const; + + /** + * Get object version + */ + virtual int getObjectVersion() const; + + private: + friend class NdbDictionaryImpl; + friend class NdbLogfileGroupImpl; + class NdbLogfileGroupImpl & m_impl; + LogfileGroup(NdbLogfileGroupImpl&); + }; + + /** + * @class Tablespace + */ + class Tablespace : public Object { + public: + Tablespace(); + virtual ~Tablespace(); + + void setName(const char * name); + const char* getName() const; + + void setExtentSize(Uint32 sz); + Uint32 getExtentSize() const; + + void setAutoGrowSpecification(const AutoGrowSpecification&); + const AutoGrowSpecification& getAutoGrowSpecification() const; + + void setDefaultLogfileGroup(const char * name); + void setDefaultLogfileGroup(const class LogfileGroup&); + const char * getDefaultLogfileGroup() const; + + /** + * Get object status + */ + virtual Object::Status getObjectStatus() const; + + /** + * Get object version + */ + virtual int getObjectVersion() const; + + private: + friend class NdbTablespaceImpl; + class NdbTablespaceImpl & m_impl; + Tablespace(NdbTablespaceImpl&); + }; + + class Datafile : public Object { + public: + Datafile(); + virtual ~Datafile(); + + void setPath(const char * name); + const char* getPath() const; + + void setSize(Uint64); + Uint64 getSize() const; + Uint64 getFree() const; + + void setTablespace(const char * name); + void setTablespace(const class Tablespace &); + const char * getTablespace() const; + + void setNode(Uint32 nodeId); + Uint32 getNode() const; + + Uint32 getFileNo() const; + + /** + * Get object status + */ + virtual Object::Status getObjectStatus() const; + + /** + * Get object version + */ + virtual int getObjectVersion() const; + + private: + friend class NdbDatafileImpl; + class NdbDatafileImpl & m_impl; + Datafile(NdbDatafileImpl&); + }; + + class Undofile : public Object { + public: + Undofile(); + virtual ~Undofile(); + + void setPath(const char * path); + const char* getPath() const; + + void setSize(Uint64); + Uint64 getSize() const; + Uint64 getFree() const; + + void setLogfileGroup(const char * name); + void setLogfileGroup(const class LogfileGroup &); + const char * getLogfileGroup() const; + + void setNode(Uint32 nodeId); + Uint32 getNode() const; + + Uint32 getFileNo() const; + + /** + * Get object status + */ + virtual Object::Status getObjectStatus() const; + + /** + * Get object version + */ + virtual int getObjectVersion() const; + + private: + friend class NdbUndofileImpl; + class NdbUndofileImpl & m_impl; + Undofile(NdbUndofileImpl&); + }; + /** * @class Dictionary * @brief Dictionary for defining and retreiving meta data @@ -1356,6 +1556,30 @@ public: /** @} *******************************************************************/ + /** @} *******************************************************************/ + /** + * @name Disk data objects + * @{ + */ + + int createLogfileGroup(const LogfileGroup &); + int dropLogfileGroup(const LogfileGroup&); + LogfileGroup getLogfileGroup(const char * name); + + int createTablespace(const Tablespace &); + int dropTablespace(const Tablespace&); + Tablespace getTablespace(const char * name); + + int createDatafile(const Datafile &, bool overwrite_existing = false); + int dropDatafile(const Datafile&); + Datafile getDatafile(Uint32 node, const char * path); + + int createUndofile(const Undofile &, bool overwrite_existing = false); + int dropUndofile(const Undofile&); + Undofile getUndofile(Uint32 node, const char * path); + + /** @} *******************************************************************/ + protected: Dictionary(Ndb & ndb); ~Dictionary(); diff --git a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp index dea0a079d4a..f7ab16b1b46 100644 --- a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp @@ -112,17 +112,23 @@ public: * @param attr Attribute name, alternatively: * @param type Type of bound * @param value Pointer to bound value, 0 for NULL - * @param len Value length in bytes. - * Fixed per datatype and can be omitted * @return 0 if successful otherwise -1 + * + * @note See comment under equal() about data format and length. */ - int setBound(const char* attr, int type, const void* value, Uint32 len = 0); +#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED + int setBound(const char* attr, int type, const void* value, Uint32 len); +#endif + int setBound(const char* attr, int type, const void* value); /** * Define bound on index key in range scan using index column id. * See the other setBound() method for details. */ - int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len = 0); +#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED + int setBound(Uint32 anAttrId, int type, const void* aValue, Uint32 len); +#endif + int setBound(Uint32 anAttrId, int type, const void* aValue); /** * Reset bounds and put operation in list that will be @@ -155,11 +161,11 @@ private: NdbIndexScanOperation(Ndb* aNdb); virtual ~NdbIndexScanOperation(); - int setBound(const NdbColumnImpl*, int type, const void* aValue, Uint32 len); + int setBound(const NdbColumnImpl*, int type, const void* aValue); int insertBOUNDS(Uint32 * data, Uint32 sz); Uint32 getKeyFromSCANTABREQ(Uint32* data, Uint32 size); - virtual int equal_impl(const NdbColumnImpl*, const char*, Uint32); + virtual int equal_impl(const NdbColumnImpl*, const char*); virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*); void fix_get_values(); @@ -174,4 +180,20 @@ private: friend struct Ndb_free_list_t<NdbIndexScanOperation>; }; +inline +int +NdbIndexScanOperation::setBound(const char* attr, int type, const void* value, + Uint32 len) +{ + return setBound(attr, type, value); +} + +inline +int +NdbIndexScanOperation::setBound(Uint32 anAttrId, int type, const void* value, + Uint32 len) +{ + return setBound(anAttrId, type, value); +} + #endif diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index 1035c642c97..c403b2c3438 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -251,28 +251,27 @@ public: * @note There are 10 versions of equal() with * slightly different parameters. * - * @note When using equal() with a string (char *) as - * second argument, the string needs to be padded with - * zeros in the following sense: - * @code - * // Equal needs strings to be padded with zeros - * strncpy(buf, str, sizeof(buf)); - * NdbOperation->equal("Attr1", buf); - * @endcode - * - * + * @note If attribute has fixed size, value must include all bytes. + * In particular a Char must be native-blank padded. + * If attribute has variable size, value must start with + * 1 or 2 little-endian length bytes (2 if Long*). * * @param anAttrName Attribute name * @param aValue Attribute value. - * @param len Attribute length expressed in bytes. * @return -1 if unsuccessful. */ - int equal(const char* anAttrName, const char* aValue, Uint32 len = 0); - int equal(const char* anAttrName, Uint32 aValue); +#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED + int equal(const char* anAttrName, const char* aValue, Uint32 len); +#endif + int equal(const char* anAttrName, const char* aValue); int equal(const char* anAttrName, Int32 aValue); + int equal(const char* anAttrName, Uint32 aValue); int equal(const char* anAttrName, Int64 aValue); int equal(const char* anAttrName, Uint64 aValue); - int equal(Uint32 anAttrId, const char* aValue, Uint32 len = 0); +#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED + int equal(Uint32 anAttrId, const char* aValue, Uint32 len); +#endif + int equal(Uint32 anAttrId, const char* aValue); int equal(Uint32 anAttrId, Int32 aValue); int equal(Uint32 anAttrId, Uint32 aValue); int equal(Uint32 anAttrId, Int64 aValue); @@ -349,28 +348,34 @@ public: * * @note There are 14 versions of NdbOperation::setValue with * slightly different parameters. + * + * @note See note under equal() about value format and length. * * @param anAttrName Name (or Id) of attribute. * @param aValue Attribute value to set. - * @param len Attribute length expressed in bytes. * @return -1 if unsuccessful. */ - virtual int setValue(const char* anAttrName, const char* aValue, - Uint32 len = 0); - virtual int setValue(const char* anAttrName, Int32 aValue); - virtual int setValue(const char* anAttrName, Uint32 aValue); - virtual int setValue(const char* anAttrName, Uint64 aValue); - virtual int setValue(const char* anAttrName, Int64 aValue); - virtual int setValue(const char* anAttrName, float aValue); - virtual int setValue(const char* anAttrName, double aValue); - - virtual int setValue(Uint32 anAttrId, const char* aValue, Uint32 len = 0); - virtual int setValue(Uint32 anAttrId, Int32 aValue); - virtual int setValue(Uint32 anAttrId, Uint32 aValue); - virtual int setValue(Uint32 anAttrId, Uint64 aValue); - virtual int setValue(Uint32 anAttrId, Int64 aValue); - virtual int setValue(Uint32 anAttrId, float aValue); - virtual int setValue(Uint32 anAttrId, double aValue); +#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED + int setValue(const char* anAttrName, const char* aValue, Uint32 len); +#endif + int setValue(const char* anAttrName, const char* aValue); + int setValue(const char* anAttrName, Int32 aValue); + int setValue(const char* anAttrName, Uint32 aValue); + int setValue(const char* anAttrName, Int64 aValue); + int setValue(const char* anAttrName, Uint64 aValue); + int setValue(const char* anAttrName, float aValue); + int setValue(const char* anAttrName, double aValue); + +#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED + int setValue(Uint32 anAttrId, const char* aValue, Uint32 len); +#endif + int setValue(Uint32 anAttrId, const char* aValue); + int setValue(Uint32 anAttrId, Int32 aValue); + int setValue(Uint32 anAttrId, Uint32 aValue); + int setValue(Uint32 anAttrId, Int64 aValue); + int setValue(Uint32 anAttrId, Uint64 aValue); + int setValue(Uint32 anAttrId, float aValue); + int setValue(Uint32 anAttrId, double aValue); /** * This method replaces getValue/setValue for blobs. It creates @@ -835,9 +840,9 @@ protected: * These are support methods only used locally in this class. ******************************************************************************/ - virtual int equal_impl(const NdbColumnImpl*,const char* aValue, Uint32 len); + virtual int equal_impl(const NdbColumnImpl*,const char* aValue); virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char* aValue = 0); - int setValue(const NdbColumnImpl* anAttrObject, const char* aValue, Uint32 len); + int setValue(const NdbColumnImpl* anAttrObject, const char* aValue); NdbBlob* getBlobHandle(NdbTransaction* aCon, const NdbColumnImpl* anAttrObject); int incValue(const NdbColumnImpl* anAttrObject, Uint32 aValue); int incValue(const NdbColumnImpl* anAttrObject, Uint64 aValue); @@ -856,6 +861,7 @@ protected: int insertKEYINFO(const char* aValue, Uint32 aStartPosition, Uint32 aKeyLenInByte); + void reorderKEYINFO(); virtual void setErrorCode(int aErrorCode); virtual void setErrorCodeAbort(int aErrorCode); @@ -951,6 +957,7 @@ protected: Uint8 theDirtyIndicator; // Indicator of whether dirty operation Uint8 theInterpretIndicator; // Indicator of whether interpreted operation Int8 theDistrKeyIndicator_; // Indicates whether distr. key is used + Uint8 m_no_disk_flag; Uint16 m_tcReqGSN; Uint16 m_keyInfoGSN; @@ -1086,6 +1093,13 @@ NdbOperation::NdbCon(NdbTransaction* aNdbCon) inline int +NdbOperation::equal(const char* anAttrName, const char* aValue, Uint32 len) +{ + return equal(anAttrName, aValue); +} + +inline +int NdbOperation::equal(const char* anAttrName, Int32 aPar) { return equal(anAttrName, (const char*)&aPar, (Uint32)4); @@ -1114,6 +1128,13 @@ NdbOperation::equal(const char* anAttrName, Uint64 aPar) inline int +NdbOperation::equal(Uint32 anAttrId, const char* aValue, Uint32 len) +{ + return equal(anAttrId, aValue); +} + +inline +int NdbOperation::equal(Uint32 anAttrId, Int32 aPar) { return equal(anAttrId, (const char*)&aPar, (Uint32)4); @@ -1142,6 +1163,13 @@ NdbOperation::equal(Uint32 anAttrId, Uint64 aPar) inline int +NdbOperation::setValue(const char* anAttrName, const char* aValue, Uint32 len) +{ + return setValue(anAttrName, aValue); +} + +inline +int NdbOperation::setValue(const char* anAttrName, Int32 aPar) { return setValue(anAttrName, (const char*)&aPar, (Uint32)4); @@ -1184,6 +1212,13 @@ NdbOperation::setValue(const char* anAttrName, double aPar) inline int +NdbOperation::setValue(Uint32 anAttrId, const char* aValue, Uint32 len) +{ + return setValue(anAttrId, aValue); +} + +inline +int NdbOperation::setValue(Uint32 anAttrId, Int32 aPar) { return setValue(anAttrId, (const char*)&aPar, (Uint32)4); diff --git a/storage/ndb/include/ndbapi/NdbRecAttr.hpp b/storage/ndb/include/ndbapi/NdbRecAttr.hpp index 3607a64f3b3..5d9b0832e18 100644 --- a/storage/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp @@ -97,25 +97,9 @@ public: /** * Get attribute (element) size in bytes. * - * @note For arrays, the method only gives the size of an element. - * The total attribute size is calculated by - * multiplying this value with the value - * returned by NdbRecAttr::arraySize. - * - * @return Attribute size in 32 bit unsigned int. */ - Uint32 attrSize() const ; + Uint32 get_size_in_bytes() const { return m_size_in_bytes; } - /** - * Get array size of attribute. - * For variable-sized arrays this method returns the - * size of the attribute read. - * - * @return array size in 32 unsigned int. - */ - Uint32 arraySize() const ; - Uint32 getLength() const ; - /** @} *********************************************************************/ /** * @name Getting stored value @@ -252,7 +236,8 @@ private: Uint32 attrId() const; /* Get attribute id */ bool setNULL(); /* Set NULL indicator */ - void setUNDEFINED(); /* Set UNDEFINED indicator */ + void setUNDEFINED(); // + bool receive_data(const Uint32*, Uint32); void release(); /* Release memory if allocated */ @@ -275,11 +260,8 @@ private: NdbRecAttr* theNext; /* Next pointer */ Uint32 theAttrId; /* The attribute id */ - - int theNULLind; - bool m_nullable; - Uint32 theAttrSize; - Uint32 theArraySize; + + Int32 m_size_in_bytes; const NdbDictionary::Column* m_column; friend struct Ndb_free_list_t<NdbRecAttr>; @@ -300,19 +282,6 @@ NdbRecAttr::getColumn() const { } inline -Uint32 -NdbRecAttr::attrSize() const { - return theAttrSize; -} - -inline -Uint32 -NdbRecAttr::arraySize() const -{ - return theArraySize; -} - -inline Int32 NdbRecAttr::int32_value() const { @@ -373,7 +342,6 @@ NdbRecAttr::init() theRef = 0; theNext = 0; theAttrId = 0xFFFF; - theNULLind = -1; } inline @@ -422,22 +390,22 @@ inline bool NdbRecAttr::setNULL() { - theNULLind = 1; - return m_nullable; + m_size_in_bytes= 0; + return true; } inline -void -NdbRecAttr::setUNDEFINED() +int +NdbRecAttr::isNULL() const { - theNULLind = -1; + return m_size_in_bytes == 0 ? 1 : (m_size_in_bytes > 0 ? 0 : -1); } inline -int -NdbRecAttr::isNULL() const +void +NdbRecAttr::setUNDEFINED() { - return theNULLind; + m_size_in_bytes= -1; } class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &); diff --git a/storage/ndb/include/util/BaseString.hpp b/storage/ndb/include/util/BaseString.hpp index 02a6a3b3e66..5b99bb008a4 100644 --- a/storage/ndb/include/util/BaseString.hpp +++ b/storage/ndb/include/util/BaseString.hpp @@ -47,6 +47,9 @@ public: /** @brief Checks if the string is empty */ bool empty() const; + /** @brief Clear a string */ + void clear(); + /** @brief Convert to uppercase */ BaseString& ndb_toupper(); @@ -206,6 +209,15 @@ BaseString::empty() const return m_len == 0; } +inline void +BaseString::clear() +{ + delete[] m_chr; + m_chr = new char[1]; + m_chr[0] = 0; + m_len = 0; +} + inline BaseString& BaseString::ndb_toupper() { for(unsigned i = 0; i < length(); i++) diff --git a/storage/ndb/include/util/Bitmask.hpp b/storage/ndb/include/util/Bitmask.hpp index ade57a5ee57..1ec956daac2 100644 --- a/storage/ndb/include/util/Bitmask.hpp +++ b/storage/ndb/include/util/Bitmask.hpp @@ -62,6 +62,9 @@ public: */ static void clear(unsigned size, Uint32 data[]); + static Uint32 getWord(unsigned size, Uint32 data[], unsigned word_pos); + static void setWord(unsigned size, Uint32 data[], + unsigned word_pos, Uint32 new_word); /** * isclear - Check if all bits are clear. This is faster * than checking count() == 0. @@ -204,6 +207,21 @@ BitmaskImpl::clear(unsigned size, Uint32 data[]) } } +inline +Uint32 +BitmaskImpl::getWord(unsigned size, Uint32 data[], unsigned word_pos) +{ + return data[word_pos]; +} + +inline void +BitmaskImpl::setWord(unsigned size, Uint32 data[], + unsigned word_pos, Uint32 new_word) +{ + data[word_pos] = new_word; + return; +} + inline bool BitmaskImpl::isclear(unsigned size, const Uint32 data[]) { @@ -431,6 +449,12 @@ public: void clear(); /** + * Get and set words of bits + */ + Uint32 getWord(unsigned word_pos); + void setWord(unsigned word_pos, Uint32 new_word); + + /** * isclear - Check if all bits are clear. This is faster * than checking count() == 0. */ @@ -632,6 +656,20 @@ BitmaskPOD<size>::clear() } template <unsigned size> +inline Uint32 +BitmaskPOD<size>::getWord(unsigned word_pos) +{ + return BitmaskImpl::getWord(size, rep.data, word_pos); +} + +template <unsigned size> +inline void +BitmaskPOD<size>::setWord(unsigned word_pos, Uint32 new_word) +{ + BitmaskImpl::setWord(size, rep.data, word_pos, new_word); +} + +template <unsigned size> inline bool BitmaskPOD<size>::isclear(const Uint32 data[]) { diff --git a/storage/ndb/include/util/UtilBuffer.hpp b/storage/ndb/include/util/UtilBuffer.hpp index f43fc960a16..f97f5175dce 100644 --- a/storage/ndb/include/util/UtilBuffer.hpp +++ b/storage/ndb/include/util/UtilBuffer.hpp @@ -84,9 +84,11 @@ public: len = 0; } - int length() const { return len; }; + int length() const { return len; } - void *get_data() const { return data; }; + void *get_data() const { return data; } + + bool empty () const { return len == 0; } private: void *data; /* Pointer to data storage */ size_t len; /* Size of the stored data */ 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, ©InOperPtr, @@ -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(®AttrPtr->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(®AttrPtr->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, ®OperPtr.p->m_tuple_location, regTabPtr.p); + + if(regOperPtr.p->op_struct.op_type != ZDELETE) + { + Tuple_header *copy= (Tuple_header*) + c_undo_buffer.get_ptr(®OperPtr.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, ®OperPtr->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(®OperPtr->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(®OperPtr->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(®OperPtr.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, ®OperPtr.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, ®OperPtr.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], ©AttrBufPtr.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, ®OperPtr->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, ®OperPtr->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, ®OperPtr->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*)©PagePtr.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(®OperPtr.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, + ®OperPtr.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], + ®OperPtr.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, + ®OperPtr.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 (®FragPtr.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 (®FragPtr.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, ¬_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(®AttrPtr.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(®OperPtr->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, ®OperPtr->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(©_pos_array[0], regTabPtr); + init_var_pos_array(©_pos_array[0], + ©_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" }, diff --git a/storage/ndb/test/include/HugoCalculator.hpp b/storage/ndb/test/include/HugoCalculator.hpp index 03de46cd7ea..05cc2d218a4 100644 --- a/storage/ndb/test/include/HugoCalculator.hpp +++ b/storage/ndb/test/include/HugoCalculator.hpp @@ -31,7 +31,8 @@ class HugoCalculator { public: HugoCalculator(const NdbDictionary::Table& tab); Int32 calcValue(int record, int attrib, int updates) const; - const char* calcValue(int record, int attrib, int updates, char* buf, int len) const; + const char* calcValue(int record, int attrib, int updates, char* buf, + int len, Uint32* real_len) const; int verifyRowValues(NDBT_ResultRow* const pRow) const; int getIdValue(NDBT_ResultRow* const pRow) const; diff --git a/storage/ndb/test/include/HugoTransactions.hpp b/storage/ndb/test/include/HugoTransactions.hpp index dd6f6c0dd3b..5c987a576bc 100644 --- a/storage/ndb/test/include/HugoTransactions.hpp +++ b/storage/ndb/test/include/HugoTransactions.hpp @@ -33,7 +33,8 @@ public: int batch = 512, bool allowConstraintViolation = true, int doSleep = 0, - bool oneTrans = false); + bool oneTrans = false, + int updateValue = 0); int scanReadRecords(Ndb*, int records, diff --git a/storage/ndb/test/include/NDBT_Table.hpp b/storage/ndb/test/include/NDBT_Table.hpp index 500ac7c0e39..93dc5a1b994 100644 --- a/storage/ndb/test/include/NDBT_Table.hpp +++ b/storage/ndb/test/include/NDBT_Table.hpp @@ -29,7 +29,8 @@ public: int _length = 1, bool _pk = false, bool _nullable = false, - CHARSET_INFO *cs= 0): + CHARSET_INFO *cs= 0, + NdbDictionary::Column::StorageType storage = NdbDictionary::Column::StorageTypeMemory): NdbDictionary::Column(_name) { assert(_name != 0); @@ -42,6 +43,7 @@ public: { setCharset(cs); } + setStorageType(storage); } }; diff --git a/storage/ndb/test/include/NDBT_Tables.hpp b/storage/ndb/test/include/NDBT_Tables.hpp index fb0df8aa35b..4a5886502e1 100644 --- a/storage/ndb/test/include/NDBT_Tables.hpp +++ b/storage/ndb/test/include/NDBT_Tables.hpp @@ -23,13 +23,15 @@ #include <NdbDictionary.hpp> #include <NDBT_Table.hpp> -typedef int (* NDBT_CreateTableHook)(Ndb*, NdbDictionary::Table&, int when); +typedef int (* NDBT_CreateTableHook)(Ndb*, NdbDictionary::Table&, int when, + void* arg); class NDBT_Tables { public: static int createTable(Ndb* pNdb, const char* _name, bool _temp = false, - bool existsOK = false, NDBT_CreateTableHook = 0); + bool existsOK = false, NDBT_CreateTableHook = 0, + void* arg = 0); static int createAllTables(Ndb* pNdb, bool _temp, bool existsOK = false); static int createAllTables(Ndb* pNdb); diff --git a/storage/ndb/test/include/NDBT_Test.hpp b/storage/ndb/test/include/NDBT_Test.hpp index 62579cbfd6b..a22aa6e53bf 100644 --- a/storage/ndb/test/include/NDBT_Test.hpp +++ b/storage/ndb/test/include/NDBT_Test.hpp @@ -41,6 +41,7 @@ public: NDBT_Context(Ndb_cluster_connection&); ~NDBT_Context(); const NdbDictionary::Table* getTab(); + const NdbDictionary::Table** getTables(); int getNumTables() const; const char * getTableName(int) const; NDBT_TestSuite* getSuite(); @@ -82,6 +83,7 @@ public: bool setDbProperty(const char*, Uint32); void setTab(const NdbDictionary::Table*); + void addTab(const NdbDictionary::Table*); void setRemoteMgm(char * mgm); /** @@ -105,7 +107,7 @@ private: void setCase(NDBT_TestCase*); void setNumRecords(int); void setNumLoops(int); - const NdbDictionary::Table* tab; + Vector<const NdbDictionary::Table*> tables; NDBT_TestSuite* suite; NDBT_TestCase* testcase; Ndb* ndb; @@ -337,6 +339,7 @@ public: // to control the behaviour of the testsuite void setCreateTable(bool); // Create table before test func is called void setCreateAllTables(bool); // Create all tables before testsuite is executed + void setRunAllTables(bool); // Run once with all tables // Prints the testsuite, testcases and teststeps void printExecutionTree(); @@ -356,9 +359,10 @@ public: // Returns true if timing info should be printed bool timerIsOn(); - int addTest(NDBT_TestCase* pTest); + // Table create tweaks + int createHook(Ndb*, NdbDictionary::Table&, int when); Vector<BaseString> m_tables_in_test; private: int executeOne(Ndb_cluster_connection&, @@ -382,6 +386,9 @@ private: int timer; NdbTimer testSuiteTimer; bool createTable; + bool diskbased; + bool runonce; + const char* tsname; bool createAllTables; }; diff --git a/storage/ndb/test/include/NdbRestarter.hpp b/storage/ndb/test/include/NdbRestarter.hpp index 19a88b4f8ad..85c3f92f9ee 100644 --- a/storage/ndb/test/include/NdbRestarter.hpp +++ b/storage/ndb/test/include/NdbRestarter.hpp @@ -65,6 +65,8 @@ public: int getRandomNodeOtherNodeGroup(int nodeId, int randomNumber); int getRandomNotMasterNodeId(int randomNumber); + NdbMgmHandle handle; + protected: int waitClusterState(ndb_mgm_node_status _status, @@ -87,7 +89,6 @@ protected: bool connected; BaseString addr; - NdbMgmHandle handle; ndb_mgm_configuration * m_config; protected: ndb_mgm_configuration * getConfig(); diff --git a/storage/ndb/test/include/NdbSchemaOp.hpp b/storage/ndb/test/include/NdbSchemaOp.hpp index 1edbc155643..92a57fcf02a 100644 --- a/storage/ndb/test/include/NdbSchemaOp.hpp +++ b/storage/ndb/test/include/NdbSchemaOp.hpp @@ -71,11 +71,11 @@ }; /** * Indicate whether the attribute should be stored on disk or not + * Only for legacy createAttribute(). */ enum StorageMode { - MMBased = 0, ///< Main memory - DiskBased = 1, ///< Disk (Not yet supported.) - NoStorageTypeDef ///< Used for debugging only + MMBased = NDB_STORAGETYPE_MEMORY, + DiskBased = NDB_STORAGETYPE_DISK }; /** diff --git a/storage/ndb/test/ndbapi/create_tab.cpp b/storage/ndb/test/ndbapi/create_tab.cpp index b35c8655236..4177b63bb8b 100644 --- a/storage/ndb/test/ndbapi/create_tab.cpp +++ b/storage/ndb/test/ndbapi/create_tab.cpp @@ -22,7 +22,27 @@ #include <getarg.h> - +static int g_diskbased = 0; +static const char* g_tsname = 0; + +static int +g_create_hook(Ndb* ndb, NdbDictionary::Table& tab, int when, void* arg) +{ + if (when == 0) { + if (g_diskbased) { + for (int i = 0; i < tab.getNoOfColumns(); i++) { + NdbDictionary::Column* col = tab.getColumn(i); + if (! col->getPrimaryKey()) { + col->setStorageType(NdbDictionary::Column::StorageTypeDisk); + } + } + } + if (g_tsname != NULL) { + tab.setTablespace(g_tsname); + } + } + return 0; +} int main(int argc, const char** argv){ ndb_init(); @@ -32,13 +52,16 @@ int main(int argc, const char** argv){ int _all = 0; int _print = 0; const char* _connectstr = NULL; + int _diskbased = 0; + const char* _tsname = NULL; struct getargs args[] = { - { "all", 'a', arg_flag, &_all, "Create/print all tables" }, - { "print", 'p', arg_flag, &_print, "Print table(s) instead of creating it"}, - { "temp", 't', arg_flag, &_temp, "Temporary table", "temp" }, - { "connstr", 'c', arg_string, &_connectstr, "connect string", - "How to connect to NDB"}, + { "all", 'a', arg_flag, &_all, "Create/print all tables", 0 }, + { "print", 'p', arg_flag, &_print, "Print table(s) instead of creating it", 0}, + { "temp", 't', arg_flag, &_temp, "Temporary table", 0 }, + { "connstr", 'c', arg_string, &_connectstr, "Connect string", "cs" }, + { "diskbased", 0, arg_flag, &_diskbased, "Store attrs on disk if possible", 0 }, + { "tsname", 0, arg_string, &_tsname, "Tablespace name", "ts" }, { "usage", '?', arg_flag, &_help, "Print help", "" } }; int num_args = sizeof(args) / sizeof(args[0]); @@ -59,6 +82,9 @@ int main(int argc, const char** argv){ return NDBT_ProgramExit(NDBT_WRONGARGS); } + g_diskbased = _diskbased; + g_tsname = _tsname; + int res = 0; if(_print){ /** @@ -98,7 +124,8 @@ int main(int argc, const char** argv){ int tmp; for(int i = optind; i<argc; i++){ ndbout << "Trying to create " << argv[i] << endl; - if((tmp = NDBT_Tables::createTable(&MyNdb, argv[i], _temp)) != 0) + if((tmp = NDBT_Tables::createTable(&MyNdb, argv[i], _temp, false, + g_create_hook)) != 0) res = tmp; } } @@ -109,5 +136,3 @@ int main(int argc, const char** argv){ else return NDBT_ProgramExit(NDBT_OK); } - - diff --git a/storage/ndb/test/ndbapi/flexBench.cpp b/storage/ndb/test/ndbapi/flexBench.cpp index abddecfdc40..d272b09e5dc 100644 --- a/storage/ndb/test/ndbapi/flexBench.cpp +++ b/storage/ndb/test/ndbapi/flexBench.cpp @@ -775,12 +775,12 @@ static void* flexBenchThread(void* pArg) (char *)longKeyAttrValue[count - 1][i], tSizeOfLongPK*4); } else - pOps[countTables]->equal((char*)attrName[0], + pOps[countTables]->equal((Uint32)0, (char*)&attrRefValue[nRefLocalOpOffset]); if (tType == stInsert || tType == stUpdate){ for (int ca = 1; ca < loopCountAttributes; ca++){ - pOps[countTables]->setValue((char*)attrName[ca], + pOps[countTables]->setValue((Uint32)ca, (char*)&attrRefValue[nRefLocalOpOffset + tAttributeSize*ca]); }//for } else if (tType == stRead || stVerify == tType) { @@ -788,7 +788,7 @@ static void* flexBenchThread(void* pArg) loopCountAttributes * countTables ; for (int ca = 1; ca < loopCountAttributes; ca++) { - tTmp = pOps[countTables]->getValue((char*)attrName[ca], + tTmp = pOps[countTables]->getValue((Uint32)ca, (char*)&attrValue[nTableOffset + tAttributeSize*ca]); }//for } else if (stVerifyDelete == tType) { @@ -802,7 +802,7 @@ static void* flexBenchThread(void* pArg) int nTableOffset = tAttributeSize * loopCountAttributes * countTables ; - tTmp = pOps[countTables]->getValue((char*)attrName[0], + tTmp = pOps[countTables]->getValue((Uint32)0, (char*)&attrValue[nTableOffset]); } }//if diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp index dd5846f0d62..0176db8d4fd 100644 --- a/storage/ndb/test/ndbapi/testDict.cpp +++ b/storage/ndb/test/ndbapi/testDict.cpp @@ -1469,6 +1469,99 @@ runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runCreateLogfileGroup(NDBT_Context* ctx, NDBT_Step* step){ + Ndb* pNdb = GETNDB(step); + NdbDictionary::LogfileGroup lg; + lg.setName("DEFAULT-LG"); + lg.setUndoBufferSize(8*1024*1024); + + int res; + res = pNdb->getDictionary()->createLogfileGroup(lg); + if(res != 0){ + g_err << "Failed to create logfilegroup:" + << endl << pNdb->getDictionary()->getNdbError() << endl; + return NDBT_FAILED; + } + + NdbDictionary::Undofile uf; + uf.setPath("undofile01.dat"); + uf.setSize(5*1024*1024); + uf.setLogfileGroup("DEFAULT-LG"); + + res = pNdb->getDictionary()->createUndofile(uf); + if(res != 0){ + g_err << "Failed to create undofile:" + << endl << pNdb->getDictionary()->getNdbError() << endl; + return NDBT_FAILED; + } + + uf.setPath("undofile02.dat"); + uf.setSize(5*1024*1024); + uf.setLogfileGroup("DEFAULT-LG"); + + res = pNdb->getDictionary()->createUndofile(uf); + if(res != 0){ + g_err << "Failed to create undofile:" + << endl << pNdb->getDictionary()->getNdbError() << endl; + return NDBT_FAILED; + } + + return NDBT_OK; +} + +int +runCreateTablespace(NDBT_Context* ctx, NDBT_Step* step){ + Ndb* pNdb = GETNDB(step); + NdbDictionary::Tablespace lg; + lg.setName("DEFAULT-TS"); + lg.setExtentSize(1024*1024); + lg.setDefaultLogfileGroup("DEFAULT-LG"); + + int res; + res = pNdb->getDictionary()->createTablespace(lg); + if(res != 0){ + g_err << "Failed to create tablespace:" + << endl << pNdb->getDictionary()->getNdbError() << endl; + return NDBT_FAILED; + } + + NdbDictionary::Datafile uf; + uf.setPath("datafile01.dat"); + uf.setSize(10*1024*1024); + uf.setTablespace("DEFAULT-TS"); + + res = pNdb->getDictionary()->createDatafile(uf); + if(res != 0){ + g_err << "Failed to create datafile:" + << endl << pNdb->getDictionary()->getNdbError() << endl; + return NDBT_FAILED; + } + + return NDBT_OK; +} +int +runCreateDiskTable(NDBT_Context* ctx, NDBT_Step* step){ + Ndb* pNdb = GETNDB(step); + + NdbDictionary::Table tab = *ctx->getTab(); + tab.setTablespace("DEFAULT-TS"); + + for(Uint32 i = 0; i<tab.getNoOfColumns(); i++) + if(!tab.getColumn(i)->getPrimaryKey()) + tab.getColumn(i)->setStorageType(NdbDictionary::Column::StorageTypeDisk); + + int res; + res = pNdb->getDictionary()->createTable(tab); + if(res != 0){ + g_err << "Failed to create table:" + << endl << pNdb->getDictionary()->getNdbError() << endl; + return NDBT_FAILED; + } + + return NDBT_OK; +} + int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){ static int acclst[] = { 3001 }; static int tuplst[] = { 4007, 4008, 4009, 4010, 4011, 4012 }; @@ -1647,6 +1740,15 @@ TESTCASE("DictionaryPerf", ""){ INITIALIZER(runTestDictionaryPerf); } +TESTCASE("CreateLogfileGroup", ""){ + INITIALIZER(runCreateLogfileGroup); +} +TESTCASE("CreateTablespace", ""){ + INITIALIZER(runCreateTablespace); +} +TESTCASE("CreateDiskTable", ""){ + INITIALIZER(runCreateDiskTable); +} TESTCASE("FailAddFragment", "Fail add fragment or attribute in ACC or TUP or TUX\n"){ INITIALIZER(runFailAddFragment); diff --git a/storage/ndb/test/ndbapi/testLcp.cpp b/storage/ndb/test/ndbapi/testLcp.cpp index 8bfc7ccf9b9..69789b0191f 100644 --- a/storage/ndb/test/ndbapi/testLcp.cpp +++ b/storage/ndb/test/ndbapi/testLcp.cpp @@ -3,9 +3,13 @@ #include <NdbApi.hpp> #include <NdbRestarter.hpp> #include <HugoOperations.hpp> +#include <HugoTransactions.hpp> #include <UtilTransactions.hpp> #include <signaldata/DumpStateOrd.hpp> +#include <getarg.h> +#include <InputStream.hpp> + struct CASE { bool start_row; @@ -13,29 +17,37 @@ struct CASE bool curr_row; const char * op1; const char * op2; + const char * op3; int val; }; -static CASE g_ops[] = +static CASE g_op_types[] = { - { false, true, false, "INSERT", 0, 0 }, - { false, true, false, "INSERT", "UPDATE", 0 }, - { false, false, false, "INSERT", "DELETE", 0 }, - { true, true, false, "UPDATE", 0, 0 }, - { true, true, false, "UPDATE", "UPDATE", 0 }, - { true, false, false, "UPDATE", "DELETE", 0 }, - { true, false, false, "DELETE", 0, 0 }, - { true, true, false, "DELETE", "INSERT", 0 } + { false, true, false, "INS", 0, 0, 0 }, // 0x001 a + { true, true, false, "UPD", 0, 0, 0 }, // 0x002 d + { true, false, false, "DEL", 0, 0, 0 }, // 0x004 g + + { false, true, false, "INS", "UPD", 0, 0 }, // 0x008 b + { false, false, false, "INS", "DEL", 0, 0 }, // 0x010 c + { true, true, false, "UPD", "UPD", 0, 0 }, // 0x020 e + { true, false, false, "UPD", "DEL", 0, 0 }, // 0x040 f + { true, true, false, "DEL", "INS", 0, 0 }, // 0x080 h + + { false, true, false, "INS", "DEL", "INS", 0 }, // 0x100 i + { true, false, false, "DEL", "INS", "DEL", 0 } // 0x200 j }; -const size_t OP_COUNT = (sizeof(g_ops)/sizeof(g_ops[0])); +const size_t OP_COUNT = (sizeof(g_op_types)/sizeof(g_op_types[0])); static Ndb* g_ndb = 0; +static CASE* g_ops; static Ndb_cluster_connection *g_cluster_connection= 0; -static CASE* g_cases; static HugoOperations* g_hugo_ops; - -static int g_rows = 1000; +static int g_use_ops = 1 | 2 | 4; +static int g_cases = 0x1; +static int g_case_loop = 2; +static int g_rows = 10; static int g_setup_tables = 1; +static int g_one_op_at_a_time = 0; static const char * g_tablename = "T1"; static const NdbDictionary::Table* g_table = 0; static NdbRestarter g_restarter; @@ -45,9 +57,9 @@ static int parse_args(int argc, char** argv); static int connect_ndb(); static int drop_all_tables(); static int load_table(); -static int pause_lcp(); +static int pause_lcp(int error); static int do_op(int row); -static int continue_lcp(int error); +static int continue_lcp(int error = 0); static int commit(); static int restart(); static int validate(); @@ -56,9 +68,10 @@ static int validate(); int main(int argc, char ** argv){ - + ndb_init(); require(!init_ndb(argc, argv)); - require(!parse_args(argc, argv)); + if(parse_args(argc, argv)) + return -1; require(!connect_ndb()); if(g_setup_tables){ @@ -77,48 +90,97 @@ main(int argc, char ** argv){ require(g_hugo_ops = new HugoOperations(* g_table)); require(!g_hugo_ops->startTransaction(g_ndb)); - g_cases= new CASE[g_rows]; - require(!load_table()); + g_ops= new CASE[g_rows]; - g_info << "Performing all ops wo/ inteference of LCP" << endl; - - g_info << "Testing pre LCP operations, ZLCP_OP_WRITE_RT_BREAK" << endl; - g_info << " where ZLCP_OP_WRITE_RT_BREAK is finished before SAVE_PAGES" - << endl; - require(!pause_lcp()); - size_t j; - for(j = 0; j<g_rows; j++){ - require(!do_op(j)); - } - require(!continue_lcp(5900)); - require(!commit()); - require(!restart()); - require(!validate()); - - g_info << "Testing pre LCP operations, ZLCP_OP_WRITE_RT_BREAK" << endl; - g_info << " where ZLCP_OP_WRITE_RT_BREAK is finished after SAVE_PAGES" - << endl; - require(!load_table()); - require(!pause_lcp()); - for(j = 0; j<g_rows; j++){ - require(!do_op(j)); - } - require(!continue_lcp(5901)); - require(!commit()); - require(!restart()); - require(!validate()); - - g_info << "Testing pre LCP operations, undo-ed at commit" << endl; - require(!load_table()); - require(!pause_lcp()); - for(j = 0; j<g_rows; j++){ - require(!do_op(j)); + const int use_ops = g_use_ops; + for(size_t i = 0; i<OP_COUNT; i++) + { + if(g_one_op_at_a_time){ + while(i < OP_COUNT && (use_ops & (1 << i)) == 0) i++; + if(i == OP_COUNT) + break; + ndbout_c("-- loop\noperation: %c use_ops: %x", 'a'+i, use_ops); + g_use_ops = (1 << i); + } else { + i = OP_COUNT - 1; + } + + size_t test_case = 0; + if((1 << test_case++) & g_cases) + { + for(size_t tl = 0; tl<g_case_loop; tl++){ + g_info << "Performing all ops wo/ inteference of LCP" << endl; + + g_info << "Testing pre LCP operations, ZLCP_OP_WRITE_RT_BREAK" << endl; + g_info << " where ZLCP_OP_WRITE_RT_BREAK is " + " finished before SAVE_PAGES" << endl; + require(!load_table()); + require(!pause_lcp(5900)); + for(size_t j = 0; j<g_rows; j++){ + require(!do_op(j)); + } + require(!continue_lcp(5900)); + require(!commit()); + require(!pause_lcp(5900)); + require(!restart()); + require(!validate()); + } + } + + if((1 << test_case++) & g_cases) + { + for(size_t tl = 0; tl<g_case_loop; tl++){ + g_info << "Testing pre LCP operations, ZLCP_OP_WRITE_RT_BREAK" << endl; + g_info << " where ZLCP_OP_WRITE_RT_BREAK is finished after SAVE_PAGES" + << endl; + require(!load_table()); + require(!pause_lcp(5901)); + for(size_t j = 0; j<g_rows; j++){ + require(!do_op(j)); + } + require(!continue_lcp(5901)); + require(!commit()); + require(!pause_lcp(5900)); + require(!restart()); + require(!validate()); + } + } + + if((1 << test_case++) & g_cases) + { + for(size_t tl = 0; tl<g_case_loop; tl++){ + g_info << "Testing pre LCP operations, undo-ed at commit" << endl; + require(!load_table()); + require(!pause_lcp(5902)); + for(size_t j = 0; j<g_rows; j++){ + require(!do_op(j)); + } + require(!continue_lcp(5902)); + require(!commit()); + require(!continue_lcp(5903)); + require(!pause_lcp(5900)); + require(!restart()); + require(!validate()); + } + } + + if((1 << test_case++) & g_cases) + { + for(size_t tl = 0; tl<g_case_loop; tl++){ + g_info << "Testing prepared during LCP and committed after" << endl; + require(!load_table()); + require(!pause_lcp(5904)); // Start LCP, but don't save pages + for(size_t j = 0; j<g_rows; j++){ + require(!do_op(j)); + } + require(!continue_lcp(5904)); // Start ACC save pages + require(!pause_lcp(5900)); // Next LCP + require(!commit()); + require(!restart()); + require(!validate()); + } + } } - require(!continue_lcp(5902)); - require(!commit()); - require(!continue_lcp(5903)); - require(!restart()); - require(!validate()); } static int init_ndb(int argc, char** argv) @@ -129,6 +191,58 @@ static int init_ndb(int argc, char** argv) static int parse_args(int argc, char** argv) { + size_t i; + char * ops= 0, *cases=0; + struct getargs args[] = { + { "records", 0, arg_integer, &g_rows, "Number of records", "records" }, + { "operations", 'o', arg_string, &ops, "Operations [a-h]", 0 }, + { "1", '1', arg_flag, &g_one_op_at_a_time, "One op at a time", 0 }, + { "0", '0', arg_negative_flag, &g_one_op_at_a_time, "All ops at once", 0 }, + { "cases", 'c', arg_string, &cases, "Cases [a-c]", 0 }, + { 0, 't', arg_flag, &g_setup_tables, "Create table", 0 }, + { 0, 'u', arg_negative_flag, &g_setup_tables, "Dont create table", 0 } + }; + + int optind= 0; + const int num_args = sizeof(args)/sizeof(args[0]); + if(getarg(args, num_args, argc, (const char**)argv, &optind)) { + arg_printusage(args, num_args, argv[0], " tabname1\n"); + ndbout_c("\n -- Operations [a-%c] = ", 'a'+OP_COUNT-1); + for(i = 0; i<OP_COUNT; i++){ + ndbout_c("\t%c = %s %s", + 'a'+i, g_op_types[i].op1, + g_op_types[i].op2 ? g_op_types[i].op2 : ""); + } + return -1; + } + + if(ops != 0){ + g_use_ops = 0; + char * s = ops; + while(* s) + g_use_ops |= (1 << ((* s++) - 'a')); + } + + if(cases != 0){ + g_cases = 0; + char * s = cases; + while(* s) + g_cases |= (1 << ((* s++) - 'a')); + } + + ndbout_c("table: %s", g_tablename); + printf("operations: "); + for(i = 0; i<OP_COUNT; i++) + if(g_use_ops & (1 << i)) + printf("%c", 'a'+i); + printf("\n"); + + printf("test cases: "); + for(i = 0; i<3; i++) + if(g_cases & (1 << i)) + printf("%c", '1'+i); + printf("\n"); + printf("-------------\n"); return 0; } @@ -141,10 +255,11 @@ static int connect_ndb() } g_ndb = new Ndb(g_cluster_connection, "TEST_DB"); - g_ndb->init(); + g_ndb->init(256); if(g_ndb->waitUntilReady(30) == 0){ - int args[] = { DumpStateOrd::DihMaxTimeBetweenLCP }; - return g_restarter.dumpStateAllNodes(args, 1); + return 0; +// int args[] = { DumpStateOrd::DihMaxTimeBetweenLCP }; +// return g_restarter.dumpStateAllNodes(args, 1); } return -1; } @@ -211,77 +326,165 @@ static int load_table() HugoOperations ops(* g_table); require(!ops.startTransaction(g_ndb)); + size_t op = 0; + size_t rows = 0; + size_t uncommitted = 0; + bool prepared = false; for(size_t i = 0; i<g_rows; i++){ - g_cases[i] = g_ops[ i % OP_COUNT]; - if(g_cases[i].start_row){ - g_cases[i].curr_row = true; - g_cases[i].val = rand(); - require(!ops.pkInsertRecord(g_ndb, i, 1, g_cases[i].val)); + for(op %= OP_COUNT; !((1 << op) & g_use_ops); op = (op + 1) % OP_COUNT); + g_ops[i] = g_op_types[op++]; + if(g_ops[i].start_row){ + g_ops[i].curr_row = true; + g_ops[i].val = rand(); + require(!ops.pkInsertRecord(g_ndb, i, 1, g_ops[i].val)); + uncommitted++; + } else { + g_ops[i].curr_row = false; } - if((i+1) % 100 == 0){ + if(uncommitted >= 100){ require(!ops.execute_Commit(g_ndb)); require(!ops.getTransaction()->restart()); + rows += uncommitted; + uncommitted = 0; } } - if((g_rows+1) % 100 != 0) + if(uncommitted) require(!ops.execute_Commit(g_ndb)); + + require(!ops.closeTransaction(g_ndb)); + rows += uncommitted; + g_info << "Inserted " << rows << " rows" << endl; return 0; } -static int pause_lcp() +static int pause_lcp(int error) { - return 0; + int nodes = g_restarter.getNumDbNodes(); + + int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_INFO, 0 }; + int fd = ndb_mgm_listen_event(g_restarter.handle, filter); + require(fd >= 0); + require(!g_restarter.insertErrorInAllNodes(error)); + int dump[] = { DumpStateOrd::DihStartLcpImmediately }; + require(!g_restarter.dumpStateAllNodes(dump, 1)); + + char *tmp; + char buf[1024]; + SocketInputStream in(fd, 1000); + int count = 0; + do { + tmp = in.gets(buf, 1024); + if(tmp) + { + int id; + if(sscanf(tmp, "%*[^:]: LCP: %d ", &id) == 1 && id == error && + --nodes == 0){ + close(fd); + return 0; + } + } + } while(count++ < 30); + + close(fd); + return -1; } static int do_op(int row) { HugoOperations & ops = * g_hugo_ops; - if(strcmp(g_cases[row].op1, "INSERT") == 0){ - require(!g_cases[row].curr_row); - g_cases[row].curr_row = true; - g_cases[row].val = rand(); - require(!ops.pkInsertRecord(g_ndb, row, 1, g_cases[row].val)); - } else if(strcmp(g_cases[row].op1, "UPDATE") == 0){ - require(g_cases[row].curr_row); - g_cases[row].val = rand(); - require(!ops.pkUpdateRecord(g_ndb, row, 1, g_cases[row].val)); - } else if(strcmp(g_cases[row].op1, "DELETE") == 0){ - require(g_cases[row].curr_row); - g_cases[row].curr_row = false; + if(strcmp(g_ops[row].op1, "INS") == 0){ + require(!g_ops[row].curr_row); + g_ops[row].curr_row = true; + g_ops[row].val = rand(); + require(!ops.pkInsertRecord(g_ndb, row, 1, g_ops[row].val)); + } else if(strcmp(g_ops[row].op1, "UPD") == 0){ + require(g_ops[row].curr_row); + g_ops[row].val = rand(); + require(!ops.pkUpdateRecord(g_ndb, row, 1, g_ops[row].val)); + } else if(strcmp(g_ops[row].op1, "DEL") == 0){ + require(g_ops[row].curr_row); + g_ops[row].curr_row = false; require(!ops.pkDeleteRecord(g_ndb, row, 1)); } require(!ops.execute_NoCommit(g_ndb)); - if(g_cases[row].op2 == 0){ - } else if(strcmp(g_cases[row].op2, "INSERT") == 0){ - require(!g_cases[row].curr_row); - g_cases[row].curr_row = true; - g_cases[row].val = rand(); - require(!ops.pkInsertRecord(g_ndb, row, 1, g_cases[row].val)); - } else if(strcmp(g_cases[row].op2, "UPDATE") == 0){ - require(g_cases[row].curr_row); - g_cases[row].val = rand(); - require(!ops.pkUpdateRecord(g_ndb, row, 1, g_cases[row].val)); - } else if(strcmp(g_cases[row].op2, "DELETE") == 0){ - require(g_cases[row].curr_row); - g_cases[row].curr_row = false; + if(g_ops[row].op2 == 0){ + } else if(strcmp(g_ops[row].op2, "INS") == 0){ + require(!g_ops[row].curr_row); + g_ops[row].curr_row = true; + g_ops[row].val = rand(); + require(!ops.pkInsertRecord(g_ndb, row, 1, g_ops[row].val)); + } else if(strcmp(g_ops[row].op2, "UPD") == 0){ + require(g_ops[row].curr_row); + g_ops[row].val = rand(); + require(!ops.pkUpdateRecord(g_ndb, row, 1, g_ops[row].val)); + } else if(strcmp(g_ops[row].op2, "DEL") == 0){ + require(g_ops[row].curr_row); + g_ops[row].curr_row = false; require(!ops.pkDeleteRecord(g_ndb, row, 1)); } - if(g_cases[row].op2 != 0) + if(g_ops[row].op2 != 0) require(!ops.execute_NoCommit(g_ndb)); + + if(g_ops[row].op3 == 0){ + } else if(strcmp(g_ops[row].op3, "INS") == 0){ + require(!g_ops[row].curr_row); + g_ops[row].curr_row = true; + g_ops[row].val = rand(); + require(!ops.pkInsertRecord(g_ndb, row, 1, g_ops[row].val)); + } else if(strcmp(g_ops[row].op3, "UPD") == 0){ + require(g_ops[row].curr_row); + g_ops[row].val = rand(); + require(!ops.pkUpdateRecord(g_ndb, row, 1, g_ops[row].val)); + } else if(strcmp(g_ops[row].op3, "DEL") == 0){ + require(g_ops[row].curr_row); + g_ops[row].curr_row = false; + require(!ops.pkDeleteRecord(g_ndb, row, 1)); + } + + if(g_ops[row].op3 != 0) + require(!ops.execute_NoCommit(g_ndb)); + return 0; } static int continue_lcp(int error) { - error = 0; - if(g_restarter.insertErrorInAllNodes(error) == 0){ - int args[] = { DumpStateOrd::DihStartLcpImmediately }; - return g_restarter.dumpStateAllNodes(args, 1); + int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_INFO, 0 }; + int fd = -1; + if(error){ + fd = ndb_mgm_listen_event(g_restarter.handle, filter); + require(fd >= 0); } - return -1; + + int args[] = { DumpStateOrd::LCPContinue }; + if(g_restarter.dumpStateAllNodes(args, 1) != 0) + return -1; + + if(error){ + char *tmp; + char buf[1024]; + SocketInputStream in(fd, 1000); + int count = 0; + int nodes = g_restarter.getNumDbNodes(); + do { + tmp = in.gets(buf, 1024); + if(tmp) + { + int id; + if(sscanf(tmp, "%*[^:]: LCP: %d ", &id) == 1 && id == error && + --nodes == 0){ + close(fd); + return 0; + } + } + } while(count++ < 30); + + close(fd); + } + return 0; } static int commit() @@ -297,6 +500,7 @@ static int commit() static int restart() { g_info << "Restarting cluster" << endl; + g_hugo_ops->closeTransaction(g_ndb); disconnect_ndb(); delete g_hugo_ops; @@ -315,17 +519,25 @@ static int validate() { HugoOperations ops(* g_table); for(size_t i = 0; i<g_rows; i++){ - require(g_cases[i].curr_row == g_cases[i].end_row); + require(g_ops[i].curr_row == g_ops[i].end_row); require(!ops.startTransaction(g_ndb)); ops.pkReadRecord(g_ndb, i, 1); int res = ops.execute_Commit(g_ndb); - if(g_cases[i].curr_row){ - require(res == 0 && ops.verifyUpdatesValue(g_cases[i].val) == 0); + if(g_ops[i].curr_row){ + require(res == 0 && ops.verifyUpdatesValue(g_ops[i].val) == 0); } else { require(res == 626); } ops.closeTransaction(g_ndb); } + + for(size_t j = 0; j<10; j++){ + UtilTransactions clear(* g_table); + require(!clear.clearTable(g_ndb)); + + HugoTransactions trans(* g_table); + require(trans.loadTable(g_ndb, 1024) == 0); + } return 0; } diff --git a/storage/ndb/test/ndbapi/testOIBasic.cpp b/storage/ndb/test/ndbapi/testOIBasic.cpp index 942ee2ec966..a752b9995f0 100644 --- a/storage/ndb/test/ndbapi/testOIBasic.cpp +++ b/storage/ndb/test/ndbapi/testOIBasic.cpp @@ -4237,8 +4237,7 @@ readverifyfull(Par par) CHK(scanreadtable(par) == 0); // once more via tup scan par.m_tupscan = true; - if (NDB_VERSION < MAKE_VERSION(5, 1, 0)) //TODO - CHK(scanreadtable(par) == 0); + CHK(scanreadtable(par) == 0); } // each thread scans different indexes for (unsigned i = 0; i < tab.m_itabs; i++) { @@ -4614,20 +4613,29 @@ tbuild(Par par) RUNSTEP(par, createtable, ST); RUNSTEP(par, invalidatetable, MT); for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { - if (par.m_slno % 2 == 0) { + if (par.m_slno % 3 == 0) { RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); RUNSTEP(par, pkinsert, MT); + RUNSTEP(par, pkupdate, MT); + } else if (par.m_slno % 3 == 1) { + RUNSTEP(par, pkinsert, MT); + RUNSTEP(par, createindex, ST); + RUNSTEP(par, invalidateindex, MT); + RUNSTEP(par, pkupdate, MT); } else { RUNSTEP(par, pkinsert, MT); + RUNSTEP(par, pkupdate, MT); RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); } - RUNSTEP(par, pkupdate, MT); - RUNSTEP(par, readverifyfull, MT); - RUNSTEP(par, pkdelete, MT); RUNSTEP(par, readverifyfull, MT); - RUNSTEP(par, dropindex, ST); + // leave last one alone e.g. to continue manually + if (par.m_slno + 1 < par.m_subloop) { + RUNSTEP(par, pkdelete, MT); + RUNSTEP(par, readverifyfull, MT); + RUNSTEP(par, dropindex, ST); + } } return 0; } diff --git a/storage/ndb/test/ndbapi/testPartitioning.cpp b/storage/ndb/test/ndbapi/testPartitioning.cpp index 0b88896566b..2607d18967e 100644 --- a/storage/ndb/test/ndbapi/testPartitioning.cpp +++ b/storage/ndb/test/ndbapi/testPartitioning.cpp @@ -35,7 +35,7 @@ run_drop_table(NDBT_Context* ctx, NDBT_Step* step) static int -add_distribution_key(Ndb*, NdbDictionary::Table& tab, int when) +add_distribution_key(Ndb*, NdbDictionary::Table& tab, int when, void* arg) { switch(when){ case 0: // Before @@ -70,8 +70,16 @@ add_distribution_key(Ndb*, NdbDictionary::Table& tab, int when) BaseString name; name.assfmt("PK_DK_%d", dks); col.setName(name.c_str()); - col.setType(NdbDictionary::Column::Unsigned); - col.setLength(1); + if((rand() % 100) > 50) + { + col.setType(NdbDictionary::Column::Unsigned); + col.setLength(1); + } + else + { + col.setType(NdbDictionary::Column::Varbinary); + col.setLength(1+(rand() % 25)); + } col.setNullable(false); col.setPrimaryKey(true); col.setDistributionKey(true); @@ -348,8 +356,9 @@ run_startHint(NDBT_Context* ctx, NDBT_Step* step) int sz = tab->getColumn(j)->getSizeInBytes(); int aligned_size = 4 * ((sz + 3) >> 2); memset(pos, 0, aligned_size); - dummy.calcValue(i, j, 0, pos, sz); - pos += aligned_size; + Uint32 real_size; + dummy.calcValue(i, j, 0, pos, sz, &real_size); + pos += (real_size + 3) & ~3; } } // Now we have the pk diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 8b44594a9b5..ca4cc10f8cd 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -81,23 +81,23 @@ args: -n UpdateAndRead max-time: 500 cmd: testBasic -args: -n PkReadAndLocker T6 +args: -n PkReadAndLocker T6 D1 D2 max-time: 500 cmd: testBasic -args: -n PkReadAndLocker2 T6 +args: -n PkReadAndLocker2 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n PkReadUpdateAndLocker T6 +args: -n PkReadUpdateAndLocker T6 D1 D2 max-time: 500 cmd: testBasic -args: -n ReadWithLocksAndInserts T6 +args: -n ReadWithLocksAndInserts T6 D1 D2 max-time: 500 cmd: testBasic -args: -n PkInsertTwice T1 T6 T10 +args: -n PkInsertTwice T1 T6 T10 D1 D2 max-time: 1500 cmd: testBasic @@ -109,79 +109,79 @@ args: -n Fill T6 max-time: 500 cmd: testBasic -args: -n NoCommitSleep T6 +args: -n NoCommitSleep T6 D1 D2 max-time: 500 cmd: testBasic -args: -n NoCommit626 T6 +args: -n NoCommit626 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n NoCommitAndClose T6 +args: -n NoCommitAndClose T6 D1 D2 max-time: 500 cmd: testBasic -args: -n Commit626 T6 +args: -n Commit626 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n CommitTry626 T6 +args: -n CommitTry626 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n CommitAsMuch626 T6 +args: -n CommitAsMuch626 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n NoCommit626 T6 +args: -n NoCommit626 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n NoCommitRollback626 T1 T6 +args: -n NoCommitRollback626 T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n Commit630 T1 T6 +args: -n Commit630 T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n CommitTry630 T1 T6 +args: -n CommitTry630 T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n CommitAsMuch630 T1 T6 +args: -n CommitAsMuch630 T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n NoCommit630 T1 T6 +args: -n NoCommit630 T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n NoCommitRollback630 T1 T6 +args: -n NoCommitRollback630 T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n NoCommitAndClose T1 T6 +args: -n NoCommitAndClose T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n RollbackUpdate T1 T6 +args: -n RollbackUpdate T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n RollbackDeleteMultiple T1 T6 +args: -n RollbackDeleteMultiple T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n ImplicitRollbackDelete T1 T6 +args: -n ImplicitRollbackDelete T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n CommitDelete T1 T6 +args: -n CommitDelete T1 T6 D1 D2 max-time: 500 cmd: testBasic -args: -n RollbackNothing T1 T6 +args: -n RollbackNothing T1 T6 D1 D2 max-time: 500 cmd: testBasicAsynch @@ -201,11 +201,11 @@ args: -n PkDeleteAsynch max-time: 500 cmd: testBasic -args: -n MassiveRollback T1 T6 T13 +args: -n MassiveRollback T1 T6 T13 D1 D2 max-time: 500 cmd: testBasic -args: -n MassiveRollback2 T1 T6 T13 +args: -n MassiveRollback2 T1 T6 T13 D1 D2 max-time: 500 cmd: testTimeout @@ -231,7 +231,7 @@ args: -n ScanUpdate max-time: 500 cmd: testScan -args: -n ScanUpdate2 T6 +args: -n ScanUpdate2 T6 D1 D2 max-time: 500 cmd: testScan @@ -239,47 +239,47 @@ args: -n ScanDelete max-time: 500 cmd: testScan -args: -n ScanDelete2 T10 +args: -n ScanDelete2 T10 D1 D2 max-time: 500 cmd: testScan -args: -n ScanUpdateAndScanRead T6 +args: -n ScanUpdateAndScanRead T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadAndLocker T6 +args: -n ScanReadAndLocker T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadAndPkRead T6 +args: -n ScanReadAndPkRead T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanRead488 -l 10 T6 +args: -n ScanRead488 -l 10 T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanRead488O -l 10 T6 +args: -n ScanRead488O -l 10 T6 D1 D2 max-time: 1000 cmd: testScan -args: -n ScanRead488_Mixed -l 10 T6 +args: -n ScanRead488_Mixed -l 10 T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanRead488Timeout -l 10 T6 +args: -n ScanRead488Timeout -l 10 T6 D1 D2 max-time: 600 cmd: testScan -args: -n ScanRead40 -l 100 T2 +args: -n ScanRead40 -l 100 T2 D1 D2 max-time: 1800 cmd: testScan -args: -n ScanRead100 -l 100 T1 +args: -n ScanRead100 -l 100 T1 D1 D2 max-time: 600 cmd: testScan -args: -n ScanRead40 -l 100 T1 +args: -n ScanRead40 -l 100 T1 D1 D2 max-time: 1800 cmd: testScan @@ -291,123 +291,123 @@ args: -n ScanRead40RandomTable -l 1000 T2 max-time: 500 cmd: testScan -args: -n ScanWithLocksAndInserts T6 +args: -n ScanWithLocksAndInserts T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadAbort T6 +args: -n ScanReadAbort T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadAbort15 T6 +args: -n ScanReadAbort15 T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadAbort240 T6 +args: -n ScanReadAbort240 T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanUpdateAbort16 T6 +args: -n ScanUpdateAbort16 T6 D1 D2 max-time: 3600 cmd: testScan -args: -n ScanReadRestart T1 T6 T13 +args: -n ScanReadRestart T1 T6 T13 D1 D2 max-time: 500 cmd: testScan -args: -n ScanUpdateRestart T6 +args: -n ScanUpdateRestart T6 D1 D2 max-time: 500 cmd: testScan -args: -n CheckGetValue T6 +args: -n CheckGetValue T6 D1 D2 max-time: 500 cmd: testScan -args: -n CloseWithoutStop T6 +args: -n CloseWithoutStop T6 D1 D2 max-time: 500 cmd: testScan -args: -n NextScanWhenNoMore T6 +args: -n NextScanWhenNoMore T6 D1 D2 max-time: 500 cmd: testScan -args: -n ExecuteScanWithoutOpenScan T6 +args: -n ExecuteScanWithoutOpenScan T6 D1 D2 max-time: 500 cmd: testScan -args: -n OnlyOpenScanOnce T6 +args: -n OnlyOpenScanOnce T6 D1 D2 max-time: 500 cmd: testScan -args: -n OnlyOneOpInScanTrans T6 +args: -n OnlyOneOpInScanTrans T6 D1 D2 max-time: 500 cmd: testScan -args: -n OnlyOneOpBeforeOpenScan T6 +args: -n OnlyOneOpBeforeOpenScan T6 D1 D2 max-time: 500 cmd: testScan -args: -n OnlyOneScanPerTrans T6 +args: -n OnlyOneScanPerTrans T6 D1 D2 max-time: 500 cmd: testScan -args: -n NoCloseTransaction T6 +args: -n NoCloseTransaction T6 D1 D2 max-time: 500 cmd: testScan -args: -n CheckInactivityTimeOut T6 +args: -n CheckInactivityTimeOut T6 D1 D2 max-time: 500 cmd: testScan -args: -n CheckInactivityBeforeClose T6 +args: -n CheckInactivityBeforeClose T6 D1 D2 max-time: 500 cmd: testScan -args: -n CheckAfterTerror T6 +args: -n CheckAfterTerror T6 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadError5021 T1 +args: -n ScanReadError5021 T1 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReaderror5022 T1 +args: -n ScanReaderror5022 T1 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadError5023 T1 +args: -n ScanReadError5023 T1 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadError5024 T1 +args: -n ScanReadError5024 T1 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadError5025 T1 +args: -n ScanReadError5025 T1 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadError5030 T1 +args: -n ScanReadError5030 T1 D1 D2 max-time: 500 cmd: testScan -args: -n InsertDelete T1 T6 +args: -n InsertDelete T1 T6 D1 D2 max-time: 500 cmd: testScan -args: -n CheckAfterTerror T1 +args: -n CheckAfterTerror T1 D1 D2 max-time: 500 cmd: testScan -args: -n ScanReadWhileNodeIsDown T1 +args: -n ScanReadWhileNodeIsDown T1 D1 D2 max-time: 500 cmd: testScan -args: -n ScanRestart T1 +args: -n ScanRestart T1 D1 D2 max-time: 500 cmd: testScan -args: -l 100 -n Scan-bug8262 T7 +args: -l 100 -n Scan-bug8262 T7 D1 D2 max-time: 500 cmd: testScan @@ -425,7 +425,7 @@ args: -n CreateAndDropWithData max-time: 1500 cmd: testDict -args: -n CreateAndDropDuring T6 T10 +args: -n CreateAndDropDuring T6 T10 D1 D2 max-time: 1500 cmd: testDict @@ -510,23 +510,23 @@ args: -n GetValueInUpdate T6 max-time: 500 cmd: testNdbApi -args: -n UpdateWithoutKeys T6 +args: -n UpdateWithoutKeys T6 D1 D2 max-time: 500 cmd: testNdbApi -args: -n UpdateWithoutValues T6 +args: -n UpdateWithoutValues T6 D1 D2 max-time: 500 cmd: testNdbApi -args: -n ReadWithoutGetValue +args: -n ReadWithoutGetValue D1 D2 max-time: 500 cmd: testNdbApi -args: -n Bug_11133 T1 +args: -n Bug_11133 T1 D1 D2 max-time: 500 cmd: testNdbApi -args: -n Scan_4006 T1 +args: -n Scan_4006 T1 D1 D2 #max-time: 500 #cmd: testInterpreter @@ -582,6 +582,14 @@ args: -n SR1 T8 max-time: 1500 cmd: testSystemRestart +args: -n SR1 D1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR1 D2 + +max-time: 1500 +cmd: testSystemRestart args: -n SR2 T1 max-time: 1500 @@ -594,6 +602,14 @@ args: -n SR2 T7 max-time: 1500 cmd: testSystemRestart +args: -n SR2 D1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR2 D2 + +max-time: 1500 +cmd: testSystemRestart args: -n SR_UNDO T1 max-time: 1500 diff --git a/storage/ndb/test/src/HugoCalculator.cpp b/storage/ndb/test/src/HugoCalculator.cpp index d4d7ca2f95f..06aab5b8669 100644 --- a/storage/ndb/test/src/HugoCalculator.cpp +++ b/storage/ndb/test/src/HugoCalculator.cpp @@ -77,7 +77,8 @@ HugoCalculator::calcValue(int record, int updates) const { Int32 i; - calcValue(record, attrib, updates, (char*)&i, sizeof(i)); + Uint32 j; + calcValue(record, attrib, updates, (char*)&i, sizeof(i), &j); return i; } @@ -94,10 +95,12 @@ HugoCalculator::calcValue(int record, int attrib, int updates, char* buf, - int len) const { + int len, + Uint32 *outlen) const { Uint64 seed; const NdbDictionary::Column* attr = m_tab.getColumn(attrib); Uint32 val; + * outlen = len; do { if (attrib == m_idCol) @@ -128,9 +131,13 @@ HugoCalculator::calcValue(int record, val = myRand(&seed); if(attr->getNullable() && (((val >> 16) & 255) > 220)) + { + * outlen = 0; return NULL; + } int pos= 0; + char* dst= buf; switch(attr->getType()){ case NdbDictionary::Column::Tinyint: case NdbDictionary::Column::Tinyunsigned: @@ -172,34 +179,45 @@ HugoCalculator::calcValue(int record, break; case NdbDictionary::Column::Varbinary: case NdbDictionary::Column::Varchar: - case NdbDictionary::Column::Text: - case NdbDictionary::Column::Char: + len = 1 + (myRand(&seed) % (len - 1)); + assert(len < 256); + * outlen = len + 1; + * buf = len; + dst++; + goto write_char; case NdbDictionary::Column::Longvarchar: case NdbDictionary::Column::Longvarbinary: + len = 1 + (myRand(&seed) % (len - 2)); + assert(len < 65536); + * outlen = len + 2; + int2store(buf, len); + dst += 2; +write_char: + case NdbDictionary::Column::Char: { char* ptr= (char*)&val; while(len >= 4) { len -= 4; - buf[pos++] = base64_table[ptr[0] & 0x3f]; - buf[pos++] = base64_table[ptr[1] & 0x3f]; - buf[pos++] = base64_table[ptr[2] & 0x3f]; - buf[pos++] = base64_table[ptr[3] & 0x3f]; + dst[pos++] = base64_table[ptr[0] & 0x3f]; + dst[pos++] = base64_table[ptr[1] & 0x3f]; + dst[pos++] = base64_table[ptr[2] & 0x3f]; + dst[pos++] = base64_table[ptr[3] & 0x3f]; val= myRand(&seed); } for(; len; len--, pos++) - buf[pos] = base64_table[ptr[len] & 0x3f]; + dst[pos] = base64_table[ptr[len] & 0x3f]; pos--; break; } case NdbDictionary::Column::Blob: case NdbDictionary::Column::Undefined: + case NdbDictionary::Column::Text: abort(); break; } - return buf; } @@ -216,9 +234,9 @@ HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{ for (int i = 0; i<m_tab.getNoOfColumns(); i++){ if (i != m_updatesCol && id != m_idCol) { const NdbDictionary::Column* attr = m_tab.getColumn(i); - Uint32 len = attr->getSizeInBytes(); + Uint32 len = attr->getSizeInBytes(), real_len; char buf[8000]; - const char* res = calcValue(id, i, updates, buf, len); + const char* res = calcValue(id, i, updates, buf, len, &real_len); if (res == NULL){ if (!pRow->attributeStore(i)->isNULL()){ g_err << "|- NULL ERROR: expected a NULL but the column was not null" << endl; @@ -226,7 +244,16 @@ HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{ result = -1; } } else{ - if (memcmp(res, pRow->attributeStore(i)->aRef(), len) != 0){ + if (real_len != pRow->attributeStore(i)->get_size_in_bytes()) + { + g_err << "|- Invalid data found in attribute " << i << ": \"" + << "Length of expected=" << real_len << endl + << "Lenght of read=" + << pRow->attributeStore(i)->get_size_in_bytes() << endl; + result= -1; + } + else if (memcmp(res, pRow->attributeStore(i)->aRef(), real_len) != 0) + { g_err << "Column: " << attr->getName() << endl; const char* buf2 = pRow->attributeStore(i)->aRef(); for (Uint32 j = 0; j < len; j++) @@ -244,7 +271,7 @@ HugoCalculator::verifyRowValues(NDBT_ResultRow* const pRow) const{ << "\" != \"" << res << "\"" << endl << "Length of expected=" << (unsigned)strlen(res) << endl << "Lenght of read=" - << (unsigned)strlen(pRow->attributeStore(i)->aRef()) << endl; + << pRow->attributeStore(i)->get_size_in_bytes() << endl; g_err << "|- The row: \"" << (* pRow) << "\"" << endl; result = -1; } diff --git a/storage/ndb/test/src/HugoOperations.cpp b/storage/ndb/test/src/HugoOperations.cpp index 6cd40179205..84ea88388dc 100644 --- a/storage/ndb/test/src/HugoOperations.cpp +++ b/storage/ndb/test/src/HugoOperations.cpp @@ -516,8 +516,9 @@ int HugoOperations::equalForAttr(NdbOperation* pOp, int len = attr->getSizeInBytes(); char buf[8000]; memset(buf, 0, sizeof(buf)); - return pOp->equal( attr->getName(), - calc.calcValue(rowId, attrId, 0, buf, len)); + Uint32 real_len; + const char * value = calc.calcValue(rowId, attrId, 0, buf, len, &real_len); + return pOp->equal( attr->getName(), value, real_len); } int HugoOperations::setValueForAttr(NdbOperation* pOp, @@ -530,8 +531,10 @@ int HugoOperations::setValueForAttr(NdbOperation* pOp, int len = attr->getSizeInBytes(); char buf[8000]; memset(buf, 0, sizeof(buf)); - return pOp->setValue( attr->getName(), - calc.calcValue(rowId, attrId, updateId, buf, len)); + Uint32 real_len; + const char * value = calc.calcValue(rowId, attrId, + updateId, buf, len, &real_len); + return pOp->setValue( attr->getName(), value, real_len); } int diff --git a/storage/ndb/test/src/HugoTransactions.cpp b/storage/ndb/test/src/HugoTransactions.cpp index b8614369f2d..74aab2aa55a 100644 --- a/storage/ndb/test/src/HugoTransactions.cpp +++ b/storage/ndb/test/src/HugoTransactions.cpp @@ -518,7 +518,8 @@ HugoTransactions::loadTable(Ndb* pNdb, int batch, bool allowConstraintViolation, int doSleep, - bool oneTrans){ + bool oneTrans, + int value){ int check, a; int retryAttempt = 0; int retryMax = 5; @@ -573,7 +574,7 @@ HugoTransactions::loadTable(Ndb* pNdb, } } - if(pkInsertRecord(pNdb, c, batch) != NDBT_OK) + if(pkInsertRecord(pNdb, c, batch, value) != NDBT_OK) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); diff --git a/storage/ndb/test/src/NDBT_ResultRow.cpp b/storage/ndb/test/src/NDBT_ResultRow.cpp index 09e6b8a383c..4552c6741f9 100644 --- a/storage/ndb/test/src/NDBT_ResultRow.cpp +++ b/storage/ndb/test/src/NDBT_ResultRow.cpp @@ -95,10 +95,19 @@ BaseString NDBT_ResultRow::c_str() const { str.append(buf); }else{ Uint32* p = (Uint32*)data[i]->aRef(); - Uint32 sizeInBytes = data[i]->attrSize() * data[i]->arraySize(); + Uint32 sizeInBytes = data[i]->get_size_in_bytes(); for (Uint32 j = 0; j < sizeInBytes; j+=(sizeof(Uint32))){ str.append("H'"); - sprintf(buf, "%.8x", *p); + if (j + 4 < sizeInBytes) + { + sprintf(buf, "%.8x", *p); + } + else + { + Uint32 tmp = 0; + memcpy(&tmp, p, sizeInBytes - j); + sprintf(buf, "%.8x", tmp); + } p++; str.append(buf); if ((j + sizeof(Uint32)) < sizeInBytes) diff --git a/storage/ndb/test/src/NDBT_Tables.cpp b/storage/ndb/test/src/NDBT_Tables.cpp index ce4c49b3c75..3cbd3fb305e 100644 --- a/storage/ndb/test/src/NDBT_Tables.cpp +++ b/storage/ndb/test/src/NDBT_Tables.cpp @@ -142,7 +142,7 @@ NDBT_Attribute T7Attribs[] = { NDBT_Attribute("PK1", NdbDictionary::Column::Unsigned, 1, true), NDBT_Attribute("PK2", NdbDictionary::Column::Unsigned, 1, true), NDBT_Attribute("PK3", NdbDictionary::Column::Unsigned, 1, true), - NDBT_Attribute("PK4", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("PK4", NdbDictionary::Column::Varbinary, 123, true), NDBT_Attribute("ATTR1", NdbDictionary::Column::Unsigned), NDBT_Attribute("ATTR2", NdbDictionary::Column::Unsigned), NDBT_Attribute("ATTR3", NdbDictionary::Column::Unsigned), @@ -173,8 +173,8 @@ static const NDBT_Attribute T8Attribs[] = { NDBT_Attribute("PERSON_ID", NdbDictionary::Column::Unsigned, 1, true), - NDBT_Attribute("NAME", NdbDictionary::Column::Char, 257), - NDBT_Attribute("ADRESS", NdbDictionary::Column::Char, 513), + NDBT_Attribute("NAME", NdbDictionary::Column::Varbinary, 255), + NDBT_Attribute("ADRESS", NdbDictionary::Column::Longvarbinary, 513), NDBT_Attribute("POSTADRESS", NdbDictionary::Column::Char, 1173), NDBT_Attribute("VALUE", NdbDictionary::Column::Unsigned), @@ -383,6 +383,35 @@ static NDBT_Table I3("I3", sizeof(I3_Cols)/sizeof(NDBT_Attribute), I3_Cols ); // ,I3_Indexes); +/* D1 */ +static +const +NDBT_Attribute D1Attribs[] = { + NDBT_Attribute("KOL1", NdbDictionary::Column::Unsigned, 1, true), + NDBT_Attribute("KOL2", NdbDictionary::Column::Unsigned, 1, false, false, 0, NdbDictionary::Column::StorageTypeDisk), + NDBT_Attribute("KOL3", NdbDictionary::Column::Unsigned), + NDBT_Attribute("KOL4", NdbDictionary::Column::Char, 233, false, true, 0, NdbDictionary::Column::StorageTypeDisk), + NDBT_Attribute("KOL5", NdbDictionary::Column::Unsigned), +}; +static +const +NDBT_Table D1("D1", sizeof(D1Attribs)/sizeof(NDBT_Attribute), D1Attribs); + +static +const +NDBT_Attribute D2Attribs[] = { + NDBT_Attribute("KOL1", NdbDictionary::Column::Varbinary, 127, true), + NDBT_Attribute("KOL2", NdbDictionary::Column::Unsigned, 1, false, false, 0, NdbDictionary::Column::StorageTypeDisk), + NDBT_Attribute("KOL3", NdbDictionary::Column::Unsigned), + NDBT_Attribute("KOL4", NdbDictionary::Column::Varbinary, 133), + NDBT_Attribute("KOL5", NdbDictionary::Column::Char, 199, false, true, 0, NdbDictionary::Column::StorageTypeDisk), + NDBT_Attribute("KOL6", NdbDictionary::Column::Bit, 21, false, false, 0, NdbDictionary::Column::StorageTypeDisk), +}; +static +const +NDBT_Table D2("D2", sizeof(D2Attribs)/sizeof(NDBT_Attribute), D2Attribs); + + // Define array with pointer to all tables static const @@ -404,7 +433,8 @@ NDBT_Table *test_tables[]= &T14, &I1, &I2, - &I3 + &I3, + &D1, &D2 }; struct NDBT_IndexList { @@ -818,10 +848,113 @@ NDBT_Tables::createAllTables(Ndb* pNdb){ return createAllTables(pNdb, false); } +static int -NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, - bool existsOk, NDBT_CreateTableHook f){ +create_default_tablespace(Ndb* pNdb) +{ + NdbDictionary::Dictionary* pDict = pNdb->getDictionary(); + + int res; + NdbDictionary::LogfileGroup lg = pDict->getLogfileGroup("DEFAULT-LG"); + if (strcmp(lg.getName(), "DEFAULT-LG") != 0) + { + lg.setName("DEFAULT-LG"); + lg.setUndoBufferSize(8*1024*1024); + res = pDict->createLogfileGroup(lg); + if(res != 0){ + g_err << "Failed to create logfilegroup:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + { + NdbDictionary::Undofile uf = pDict->getUndofile(0, "undofile01.dat"); + if (strcmp(uf.getPath(), "undofile01.dat") != 0) + { + uf.setPath("undofile01.dat"); + uf.setSize(32*1024*1024); + uf.setLogfileGroup("DEFAULT-LG"); + + res = pDict->createUndofile(uf, true); + if(res != 0){ + g_err << "Failed to create undofile:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + } + { + NdbDictionary::Undofile uf = pDict->getUndofile(0, "undofile02.dat"); + if (strcmp(uf.getPath(), "undofile02.dat") != 0) + { + uf.setPath("undofile02.dat"); + uf.setSize(32*1024*1024); + uf.setLogfileGroup("DEFAULT-LG"); + + res = pDict->createUndofile(uf, true); + if(res != 0){ + g_err << "Failed to create undofile:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + } + NdbDictionary::Tablespace ts = pDict->getTablespace("DEFAULT-TS"); + if (strcmp(ts.getName(), "DEFAULT-TS") != 0) + { + ts.setName("DEFAULT-TS"); + ts.setExtentSize(1024*1024); + ts.setDefaultLogfileGroup("DEFAULT-LG"); + + res = pDict->createTablespace(ts); + if(res != 0){ + g_err << "Failed to create tablespace:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + { + NdbDictionary::Datafile df = pDict->getDatafile(0, "datafile01.dat"); + if (strcmp(df.getPath(), "datafile01.dat") != 0) + { + df.setPath("datafile01.dat"); + df.setSize(64*1024*1024); + df.setTablespace("DEFAULT-TS"); + + res = pDict->createDatafile(df, true); + if(res != 0){ + g_err << "Failed to create datafile:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + } + + { + NdbDictionary::Datafile df = pDict->getDatafile(0, "datafile02.dat"); + if (strcmp(df.getPath(), "datafile02.dat") != 0) + { + df.setPath("datafile02.dat"); + df.setSize(64*1024*1024); + df.setTablespace("DEFAULT-TS"); + + res = pDict->createDatafile(df, true); + if(res != 0){ + g_err << "Failed to create datafile:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + } + + return NDBT_OK; +} + +int +NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, + bool existsOk, NDBT_CreateTableHook f, void* arg) +{ const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name); if (tab == NULL){ ndbout << "Could not create table " << _name @@ -834,21 +967,31 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, do { NdbDictionary::Table tmpTab(* tab); tmpTab.setStoredTable(_temp ? 0 : 1); - if(f != 0 && f(pNdb, tmpTab, 0)) + if(f != 0 && f(pNdb, tmpTab, 0, arg)) { ndbout << "Failed to create table" << endl; return NDBT_FAILED; - } + } +loop: r = pNdb->getDictionary()->createTable(tmpTab); if(r == -1){ + if(pNdb->getDictionary()->getNdbError().code == 723) + { + if (create_default_tablespace(pNdb) == 0) + { + goto loop; + } + } if(!existsOk){ - ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl; + ndbout << "Error0: " << pNdb->getDictionary()->getNdbError() << endl; + break; } if(pNdb->getDictionary()->getNdbError().code != 721){ ndbout << "Error: " << pNdb->getDictionary()->getNdbError() << endl; break; } + r = 0; } @@ -887,7 +1030,7 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp, } } } - if(f != 0 && f(pNdb, tmpTab, 1)) + if(f != 0 && f(pNdb, tmpTab, 1, arg)) { ndbout << "Failed to create table" << endl; return NDBT_FAILED; diff --git a/storage/ndb/test/src/NDBT_Test.cpp b/storage/ndb/test/src/NDBT_Test.cpp index 4cd9df8e538..701c9912373 100644 --- a/storage/ndb/test/src/NDBT_Test.cpp +++ b/storage/ndb/test/src/NDBT_Test.cpp @@ -31,7 +31,6 @@ NDBT_Context::NDBT_Context(Ndb_cluster_connection& con) : m_cluster_connection(con) { - tab = NULL; suite = NULL; testcase = NULL; ndb = NULL; @@ -58,8 +57,8 @@ NDBT_Context::~NDBT_Context(){ } const NdbDictionary::Table* NDBT_Context::getTab(){ - assert(tab != NULL); - return tab; + assert(tables.size()); + return tables[0]; } NDBT_TestSuite* NDBT_Context::getSuite(){ @@ -225,8 +224,25 @@ bool NDBT_Context::setDbProperty(const char*, Uint32){ } void NDBT_Context::setTab(const NdbDictionary::Table* ptab){ - assert(ptab != NULL); - tab = ptab; + tables.clear(); + tables.push_back(ptab); + tables.push_back(0); +} + +void NDBT_Context::addTab(const NdbDictionary::Table* ptab){ + if(tables.size()) + tables.back() = ptab; + else + tables.push_back(ptab); + + tables.push_back(0); +} + + +const NdbDictionary::Table** +NDBT_Context::getTables() +{ + return tables.getBase(); } void NDBT_Context::setSuite(NDBT_TestSuite* psuite){ @@ -751,6 +767,8 @@ NDBT_TestSuite::NDBT_TestSuite(const char* pname):name(pname){ records = 0; loops = 0; createTable = true; + diskbased = false; + tsname = NULL; createAllTables = false; } @@ -766,6 +784,9 @@ void NDBT_TestSuite::setCreateTable(bool _flag){ createTable = _flag; } +void NDBT_TestSuite::setRunAllTables(bool _flag){ + runonce = _flag; +} void NDBT_TestSuite::setCreateAllTables(bool _flag){ createAllTables = _flag; } @@ -780,6 +801,14 @@ int NDBT_TestSuite::addTest(NDBT_TestCase* pTest){ return 0; } +static int +g_create_hook(Ndb* ndb, NdbDictionary::Table& tab, int when, void* arg) +{ + NDBT_TestSuite* ts = (NDBT_TestSuite*)arg; + return ts->createHook(ndb, tab, when); +} + + int NDBT_TestSuite::executeAll(Ndb_cluster_connection& con, const char* _testname){ @@ -796,14 +825,84 @@ int NDBT_TestSuite::executeAll(Ndb_cluster_connection& con, ndbout << name << " started [" << getDate() << "]" << endl; - testSuiteTimer.doStart(); - for (int t=0; t < NDBT_Tables::getNumTables(); t++){ - const NdbDictionary::Table* ptab = NDBT_Tables::getTable(t); - ndbout << "|- " << ptab->getName() << endl; - execute(con, &ndb, ptab, _testname); + if(!runonce) + { + testSuiteTimer.doStart(); + for (int t=0; t < NDBT_Tables::getNumTables(); t++){ + const NdbDictionary::Table* ptab = NDBT_Tables::getTable(t); + ndbout << "|- " << ptab->getName() << endl; + execute(con, &ndb, ptab, _testname); + } + testSuiteTimer.doStop(); + } + else + { + NdbDictionary::Dictionary* pDict= ndb.getDictionary(); + for (unsigned i = 0; i < tests.size(); i++){ + if (_testname != NULL && strcasecmp(tests[i]->getName(), _testname) != 0) + continue; + + + tests[i]->initBeforeTest(); + ctx = new NDBT_Context(con); + + Uint32 t; + for (t=0; t < (Uint32)NDBT_Tables::getNumTables(); t++) + { + const NdbDictionary::Table* pTab = NDBT_Tables::getTable(t); + const NdbDictionary::Table* pTab2 = pDict->getTable(pTab->getName()); + + if(pTab2 != 0 && pDict->dropTable(pTab->getName()) != 0) + { + numTestsFail++; + numTestsExecuted++; + g_err << "ERROR0: Failed to drop table " << pTab->getName() << endl; + tests[i]->saveTestResult(pTab, FAILED_TO_CREATE); + continue; + } + + if (NDBT_Tables::createTable(&ndb, pTab->getName(), false, false, + g_create_hook, this) != 0) { + numTestsFail++; + numTestsExecuted++; + g_err << "ERROR1: Failed to create table " << pTab->getName() + << pDict->getNdbError() << endl; + tests[i]->saveTestResult(pTab, FAILED_TO_CREATE); + continue; + } + pTab2 = pDict->getTable(pTab->getName()); + + ctx->addTab(pTab2); + } + + ctx->setNumRecords(records); + ctx->setNumLoops(loops); + if(remote_mgm != NULL) + ctx->setRemoteMgm(remote_mgm); + ctx->setSuite(this); + + const NdbDictionary::Table** tables= ctx->getTables(); + + result = tests[i]->execute(ctx); + tests[i]->saveTestResult(tables[0], result); + if (result != NDBT_OK) + numTestsFail++; + else + numTestsOk++; + numTestsExecuted++; + + if(result == NDBT_OK) + { + for(t = 0; tables[t] != 0; t++) + { + pDict->dropTable(tables[t]->getName()); + } + } + + delete ctx; + } } - testSuiteTimer.doStop(); return reportAllTables(_testname); } @@ -839,6 +938,25 @@ NDBT_TestSuite::executeOne(Ndb_cluster_connection& con, } } +int +NDBT_TestSuite::createHook(Ndb* ndb, NdbDictionary::Table& tab, int when) +{ + if (when == 0) { + if (diskbased) { + for (int i = 0; i < tab.getNoOfColumns(); i++) { + NdbDictionary::Column* col = tab.getColumn(i); + if (! col->getPrimaryKey()) { + col->setStorageType(NdbDictionary::Column::StorageTypeDisk); + } + } + } + if (tsname != NULL) { + tab.setTablespace(tsname); + } + } + return 0; +} + void NDBT_TestSuite::execute(Ndb_cluster_connection& con, Ndb* ndb, const NdbDictionary::Table* pTab, const char* _testname){ @@ -873,7 +991,8 @@ void NDBT_TestSuite::execute(Ndb_cluster_connection& con, continue; } - if(NDBT_Tables::createTable(ndb, pTab->getName()) != 0){ + if (NDBT_Tables::createTable(ndb, pTab->getName(), false, false, + g_create_hook, this) != 0) { numTestsFail++; numTestsExecuted++; g_err << "ERROR1: Failed to create table " << pTab->getName() diff --git a/storage/ndb/test/src/UtilTransactions.cpp b/storage/ndb/test/src/UtilTransactions.cpp index eabd22f3a17..4d220a4f77a 100644 --- a/storage/ndb/test/src/UtilTransactions.cpp +++ b/storage/ndb/test/src/UtilTransactions.cpp @@ -175,7 +175,7 @@ UtilTransactions::clearTable3(Ndb* pNdb, return NDBT_FAILED; failed: - closeTransaction(pNdb); + if(pTrans != 0) closeTransaction(pNdb); ERR(err); return (err.code != 0 ? err.code : NDBT_FAILED); } @@ -322,7 +322,7 @@ UtilTransactions::addRowToInsert(Ndb* pNdb, // Set all attributes for (int a = 0; a < tab.getNoOfColumns(); a++){ NdbRecAttr* r = row.attributeStore(a); - int sz = r->attrSize() * r->arraySize(); + int sz = r->get_size_in_bytes(); if (pInsOp->setValue(tab.getColumn(a)->getName(), r->aRef(), sz) != 0) { @@ -1422,7 +1422,7 @@ loop: } } - pTrans->close(); pTrans= 0; + closeTransaction(pNdb); g_info << row_count << " rows compared" << endl; { @@ -1442,11 +1442,7 @@ error: { g_err << err << endl; NdbSleep_MilliSleep(50); - if(pTrans != 0) - { - pTrans->close(); - pTrans= 0; - } + closeTransaction(pNdb); if(cmp.getTransaction()) cmp.closeTransaction(pNdb); @@ -1459,7 +1455,8 @@ error: } close: - if(pTrans != 0) pTrans->close(); + closeTransaction(pNdb); return return_code; } + diff --git a/storage/ndb/test/tools/hugoLoad.cpp b/storage/ndb/test/tools/hugoLoad.cpp index 1a229169650..2982e75cbf1 100644 --- a/storage/ndb/test/tools/hugoLoad.cpp +++ b/storage/ndb/test/tools/hugoLoad.cpp @@ -27,14 +27,15 @@ int main(int argc, const char** argv){ ndb_init(); int _records = 0; - const char* _tabname = NULL; int _help = 0; int _batch = 512; + int _loops = -1; const char* db = 0; struct getargs args[] = { { "records", 'r', arg_integer, &_records, "Number of records", "recs" }, { "batch", 'b', arg_integer, &_batch, "Number of operations in each transaction", "batch" }, + { "loops", 'l', arg_integer, &_loops, "Number of loops", "" }, { "database", 'd', arg_string, &db, "Database", "" }, { "usage", '?', arg_flag, &_help, "Print help", "" } }; @@ -53,7 +54,7 @@ int main(int argc, const char** argv){ arg_printusage(args, num_args, argv[0], desc); return NDBT_ProgramExit(NDBT_WRONGARGS); } - _tabname = argv[optind]; + // Connect to Ndb Ndb_cluster_connection con; @@ -72,18 +73,33 @@ int main(int argc, const char** argv){ while(MyNdb.waitUntilReady() != 0) ndbout << "Waiting for ndb to become ready..." << endl; - // Check if table exists in db - const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname); - if(pTab == NULL){ - ndbout << " Table " << _tabname << " does not exist!" << endl; - return NDBT_ProgramExit(NDBT_WRONGARGS); - } - - HugoTransactions hugoTrans(*pTab); - if (hugoTrans.loadTable(&MyNdb, - _records, - _batch) != 0){ - return NDBT_ProgramExit(NDBT_FAILED); + for(Uint32 i = optind; i<argc; i++) + { + const char* _tabname = argv[i]; + // Check if table exists in db + const NdbDictionary::Table* pTab = + NDBT_Table::discoverTableFromDb(&MyNdb, _tabname); + if(pTab == NULL){ + ndbout << " Table " << _tabname << " does not exist!" << endl; + return NDBT_ProgramExit(NDBT_WRONGARGS); + } + + HugoTransactions hugoTrans(*pTab); +loop: + if (hugoTrans.loadTable(&MyNdb, + _records, + _batch, + true, 0, false, _loops) != 0){ + return NDBT_ProgramExit(NDBT_FAILED); + } + + if(_loops > 0) + { + hugoTrans.clearTable(&MyNdb); + //hugoTrans.pkDelRecords(&MyNdb, _records); + _loops--; + goto loop; + } } return NDBT_ProgramExit(NDBT_OK); diff --git a/storage/ndb/test/tools/hugoPkReadRecord.cpp b/storage/ndb/test/tools/hugoPkReadRecord.cpp index c60a994c7d4..d0d46511487 100644 --- a/storage/ndb/test/tools/hugoPkReadRecord.cpp +++ b/storage/ndb/test/tools/hugoPkReadRecord.cpp @@ -119,60 +119,7 @@ int main(int argc, const char** argv) for (i = 0; i < table->getNoOfColumns(); i++) { NdbRecAttr* a = data[i]; - switch(a->getType()) - { - case NdbDictionary::Column::Char: - case NdbDictionary::Column::Varchar: - case NdbDictionary::Column::Binary: - case NdbDictionary::Column::Varbinary: - { - if (_hex) - { - char* b = a->aRef(); - for (int j = 0; j < a->arraySize(); j++) - { - //ndbout_c("%x", b[j]); - g_info << hex << b[j] << "[" << dec << j << "]"; - } - } - else - { - g_info << "\"" - << a->aRef() << "\""; - } - g_info << " "; - } - break; - - case NdbDictionary::Column::Int: - case NdbDictionary::Column::Unsigned: - { - g_info << a->int32_value() << " "; - } - break; - - case NdbDictionary::Column::Bigint: - case NdbDictionary::Column::Bigunsigned: - { - g_info << a->int64_value() << " "; - } - break; - - case NdbDictionary::Column::Float: - { - g_info << a->float_value() << " "; - } - break; - - case NdbDictionary::Column::Undefined: - default: - { - g_info << "Undefined!!! "; - } - break; - - } // case - g_info << " "; + ndbout << (* a) << " "; } // for g_info << endl; } // if (conn diff --git a/storage/ndb/test/tools/hugoScanUpdate.cpp b/storage/ndb/test/tools/hugoScanUpdate.cpp index 6960fa44b96..07807b254ee 100644 --- a/storage/ndb/test/tools/hugoScanUpdate.cpp +++ b/storage/ndb/test/tools/hugoScanUpdate.cpp @@ -35,6 +35,7 @@ int main(int argc, const char** argv){ int _ver2 = 0; const char* _tabname = NULL, *db = 0; int _help = 0; + int abort= 0; struct getargs args[] = { { "loops", 'l', arg_integer, &_loops, "number of times to run this program(0=infinite loop)", "loops" }, @@ -42,6 +43,7 @@ int main(int argc, const char** argv){ { "records", 'r', arg_integer, &_records, "Number of records", "recs" }, { "ver2", '2', arg_flag, &_ver2, "Use version 2 of scanUpdateRecords", "" }, { "ver2", '1', arg_negative_flag, &_ver2, "Use version 1 of scanUpdateRecords (default)", "" }, + { "abort", 'a', arg_integer, &abort, "Abort probability", "" }, { "usage", '?', arg_flag, &_help, "Print help", "" }, { "database", 'd', arg_string, &db, "Database", "" } }; @@ -88,14 +90,14 @@ int main(int argc, const char** argv){ ndbout << i << ": "; if (_ver2 == 0){ res = hugoTrans.scanUpdateRecords(&MyNdb, - _records, - 0, - _parallelism); + _records, + abort % 101, + _parallelism); } else{ res = hugoTrans.scanUpdateRecords2(&MyNdb, - _records, - 0, - _parallelism); + _records, + abort % 101, + _parallelism); } if (res != NDBT_OK ){ return NDBT_ProgramExit(NDBT_FAILED); @@ -103,6 +105,6 @@ int main(int argc, const char** argv){ i++; //NdbSleep_MilliSleep(300); } - + return NDBT_ProgramExit(NDBT_OK); } diff --git a/storage/ndb/tools/desc.cpp b/storage/ndb/tools/desc.cpp index be0f6942db5..06accb591bf 100644 --- a/storage/ndb/tools/desc.cpp +++ b/storage/ndb/tools/desc.cpp @@ -19,6 +19,13 @@ #include <NDBT.hpp> #include <NdbApi.hpp> +void desc_AutoGrowSpecification(struct NdbDictionary::AutoGrowSpecification ags); +int desc_logfilegroup(Ndb *myndb, char* name); +int desc_undofile(Ndb *myndb, char* name); +int desc_datafile(Ndb *myndb, char* name); +int desc_tablespace(Ndb *myndb,char* name); +int desc_table(Ndb *myndb,char* name); + NDB_STD_OPTS_VARS; static const char* _dbname = "TEST_DB"; @@ -74,46 +81,171 @@ int main(int argc, char** argv){ ERR(MyNdb.getNdbError()); return NDBT_ProgramExit(NDBT_FAILED); } - - const NdbDictionary::Dictionary * dict= MyNdb.getDictionary(); - for (int i = 0; i < argc; i++) { - NDBT_Table* pTab = (NDBT_Table*)dict->getTable(argv[i]); - if (pTab != 0){ - ndbout << (* pTab) << endl; - - NdbDictionary::Dictionary::List list; - if (dict->listIndexes(list, argv[i]) != 0){ - ndbout << argv[i] << ": " << dict->getNdbError() << endl; - return NDBT_ProgramExit(NDBT_FAILED); - } - - ndbout << "-- Indexes -- " << endl; - ndbout << "PRIMARY KEY("; - unsigned j; - for (j= 0; (int)j < pTab->getNoOfPrimaryKeys(); j++) - { - const NdbDictionary::Column * col = pTab->getColumn(pTab->getPrimaryKey(j)); - ndbout << col->getName(); - if ((int)j < pTab->getNoOfPrimaryKeys()-1) - ndbout << ", "; - } - ndbout << ") - UniqueHashIndex" << endl; - - for (j= 0; j < list.count; j++) { - NdbDictionary::Dictionary::List::Element& elt = list.elements[j]; - const NdbDictionary::Index *pIdx = dict->getIndex(elt.name, argv[i]); - if (!pIdx){ - ndbout << argv[i] << ": " << dict->getNdbError() << endl; - return NDBT_ProgramExit(NDBT_FAILED); - } - - ndbout << (*pIdx) << endl; - } - ndbout << endl; - } + + NdbDictionary::Dictionary * dict= MyNdb.getDictionary(); + for(int i= 0; i<argc;i++) + { + if(desc_table(&MyNdb,argv[i])) + ; + else if(desc_tablespace(&MyNdb,argv[i])) + ; + else if(desc_logfilegroup(&MyNdb,argv[i])) + ; + else if(desc_datafile(&MyNdb, argv[i])) + ; + else if(desc_undofile(&MyNdb, argv[i])) + ; else - ndbout << argv[i] << ": " << dict->getNdbError() << endl; + ndbout << "No such object: " << argv[i] << endl << endl; } - + return NDBT_ProgramExit(NDBT_OK); } + +void desc_AutoGrowSpecification(struct NdbDictionary::AutoGrowSpecification ags) +{ + ndbout << "AutoGrow.min_free: " << ags.min_free << endl; + ndbout << "AutoGrow.max_size: " << ags.max_size << endl; + ndbout << "AutoGrow.file_size: " << ags.file_size << endl; + ndbout << "AutoGrow.filename_pattern: " << ags.filename_pattern << endl; +} + +int desc_logfilegroup(Ndb *myndb, char* name) +{ + NdbDictionary::Dictionary *dict= myndb->getDictionary(); + assert(dict); + NdbDictionary::LogfileGroup lfg= dict->getLogfileGroup(name); + NdbError err= dict->getNdbError(); + if(err.classification!=ndberror_cl_none) + return 0; + + ndbout << "Type: LogfileGroup" << endl; + ndbout << "Name: " << lfg.getName() << endl; + ndbout << "UndoBuffer size: " << lfg.getUndoBufferSize() << endl; + ndbout << "Version: " << lfg.getObjectVersion() << endl; + + desc_AutoGrowSpecification(lfg.getAutoGrowSpecification()); + + ndbout << endl; + + return 1; +} + +int desc_tablespace(Ndb *myndb, char* name) +{ + NdbDictionary::Dictionary *dict= myndb->getDictionary(); + assert(dict); + NdbDictionary::Tablespace ts= dict->getTablespace(name); + NdbError err= dict->getNdbError(); + if(err.classification!=ndberror_cl_none) + return 0; + + ndbout << "Type: Tablespace" << endl; + ndbout << "Name: " << ts.getName() << endl; + ndbout << "Object Version: " << ts.getObjectVersion() << endl; + ndbout << "Extent Size: " << ts.getExtentSize() << endl; + ndbout << "Default Logfile Group: " << ts.getDefaultLogfileGroup() << endl; + ndbout << endl; + return 1; +} + +int desc_undofile(Ndb *myndb, char* name) +{ + NdbDictionary::Dictionary *dict= myndb->getDictionary(); + assert(dict); + NdbDictionary::Undofile uf= dict->getUndofile(0, name); + NdbError err= dict->getNdbError(); + if(err.classification!=ndberror_cl_none) + return 0; + + ndbout << "Type: Undofile" << endl; + ndbout << "Name: " << name << endl; + ndbout << "Path: " << uf.getPath() << endl; + ndbout << "Size: " << uf.getSize() << endl; + ndbout << "Free: " << uf.getFree() << endl; + + ndbout << "Logfile Group: " << uf.getLogfileGroup() << endl; + + /** FIXME: are these needed, the functions aren't there + but the prototypes are... + + ndbout << "Node: " << uf.getNode() << endl; + + ndbout << "Number: " << uf.getFileNo() << endl; + */ + + ndbout << endl; + + return 1; +} + +int desc_datafile(Ndb *myndb, char* name) +{ + NdbDictionary::Dictionary *dict= myndb->getDictionary(); + assert(dict); + NdbDictionary::Datafile df= dict->getDatafile(0, name); + NdbError err= dict->getNdbError(); + if(err.classification!=ndberror_cl_none) + return 0; + + ndbout << "Type: Datafile" << endl; + ndbout << "Name: " << name << endl; + ndbout << "Path: " << df.getPath() << endl; + ndbout << "Size: " << df.getSize() << endl; + ndbout << "Free: " << df.getFree() << endl; + + ndbout << "Tablespace: " << df.getTablespace() << endl; + + /** FIXME: are these needed, the functions aren't there + but the prototypes are... + + ndbout << "Node: " << uf.getNode() << endl; + + ndbout << "Number: " << uf.getFileNo() << endl; + */ + + ndbout << endl; + + return 1; +} + +int desc_table(Ndb *myndb, char* name) +{ + NdbDictionary::Dictionary * dict= myndb->getDictionary(); + NDBT_Table* pTab = (NDBT_Table*)dict->getTable(name); + if (!pTab) + return 0; + + ndbout << (* pTab) << endl; + + NdbDictionary::Dictionary::List list; + if (dict->listIndexes(list, name) != 0){ + ndbout << name << ": " << dict->getNdbError() << endl; + return NDBT_ProgramExit(NDBT_FAILED); + } + + ndbout << "-- Indexes -- " << endl; + ndbout << "PRIMARY KEY("; + unsigned j; + for (j= 0; (int)j < pTab->getNoOfPrimaryKeys(); j++) + { + const NdbDictionary::Column * col= pTab->getColumn(pTab->getPrimaryKey(j)); + ndbout << col->getName(); + if ((int)j < pTab->getNoOfPrimaryKeys()-1) + ndbout << ", "; + } + ndbout << ") - UniqueHashIndex" << endl; + for (j= 0; j < list.count; j++) { + NdbDictionary::Dictionary::List::Element& elt = list.elements[j]; + const NdbDictionary::Index *pIdx = dict->getIndex(elt.name, name); + if (!pIdx){ + ndbout << name << ": " << dict->getNdbError() << endl; + return NDBT_ProgramExit(NDBT_FAILED); + } + + ndbout << (*pIdx) << endl; + } + ndbout << endl; + + return 1; +} diff --git a/storage/ndb/tools/listTables.cpp b/storage/ndb/tools/listTables.cpp index fa078f7d351..49a58122c61 100644 --- a/storage/ndb/tools/listTables.cpp +++ b/storage/ndb/tools/listTables.cpp @@ -113,8 +113,20 @@ list(const char * tabname, case NdbDictionary::Object::ReadOnlyConstraint: strcpy(type, "ReadOnlyConstraint"); break; + case NdbDictionary::Object::Tablespace: + strcpy(type, "Tablespace"); + break; + case NdbDictionary::Object::LogfileGroup: + strcpy(type, "LogfileGroup"); + break; + case NdbDictionary::Object::Datafile: + strcpy(type, "Datafile"); + break; + case NdbDictionary::Object::Undofile: + strcpy(type, "Undofile"); + break; default: - sprintf(type, "%d", (int)elt.type); + sprintf(type, "%d", (int)elt.type); break; } char state[100]; diff --git a/storage/ndb/tools/restore/Restore.cpp b/storage/ndb/tools/restore/Restore.cpp index 9efafd19468..cdba4a63824 100644 --- a/storage/ndb/tools/restore/Restore.cpp +++ b/storage/ndb/tools/restore/Restore.cpp @@ -331,7 +331,9 @@ RestoreDataIterator::getNextTuple(int & res) res = -1; return NULL; } - + + //if (m_currentTable->getTableId() >= 2) { for (uint ii=0; ii<dataLenBytes; ii+=4) ndbout << "*" << hex << *(Uint32*)( (char*)_buf_ptr+ii ); ndbout << endl; } + Uint32 *buf_ptr = (Uint32*)_buf_ptr, *ptr = buf_ptr; ptr += m_currentTable->m_nullBitmaskSize; Uint32 i; @@ -347,6 +349,7 @@ RestoreDataIterator::getNextTuple(int & res) attr_data->null = false; attr_data->void_value = ptr; + attr_data->size = 4*sz; if(!Twiddle(attr_desc, attr_data)) { @@ -368,7 +371,10 @@ RestoreDataIterator::getNextTuple(int & res) attr_data->null = false; attr_data->void_value = ptr; + attr_data->size = 4*sz; + //if (m_currentTable->getTableId() >= 2) { ndbout << "fix i=" << i << " off=" << ptr-buf_ptr << " attrId=" << attrId << endl; } + if(!Twiddle(attr_desc, attr_data)) { res = -1; @@ -378,13 +384,27 @@ RestoreDataIterator::getNextTuple(int & res) ptr += sz; } + // init to NULL for(i = 0; i < m_currentTable->m_variableAttribs.size(); i++){ const Uint32 attrId = m_currentTable->m_variableAttribs[i]->attrId; AttributeData * attr_data = m_tuple.getData(attrId); + + attr_data->null = true; + attr_data->void_value = NULL; + } + + while (ptr + 2 < buf_ptr + dataLength) { + typedef BackupFormat::DataFile::VariableData VarData; + VarData * data = (VarData *)ptr; + Uint32 sz = ntohl(data->Sz); + Uint32 attrId = ntohl(data->Id); // column_no + + AttributeData * attr_data = m_tuple.getData(attrId); const AttributeDesc * attr_desc = m_tuple.getDesc(attrId); - if(attr_desc->m_column->getNullable()){ + // just a reminder - remove when backwards compat implemented + if(false && attr_desc->m_column->getNullable()){ const Uint32 ind = attr_desc->m_nullBitIndex; if(BitmaskImpl::get(m_currentTable->m_nullBitmaskSize, buf_ptr,ind)){ @@ -393,32 +413,29 @@ RestoreDataIterator::getNextTuple(int & res) continue; } } - - assert(ptr < buf_ptr + dataLength); - - typedef BackupFormat::DataFile::VariableData VarData; - VarData * data = (VarData *)ptr; - Uint32 sz = ntohl(data->Sz); - Uint32 id = ntohl(data->Id); - assert(id == attrId); attr_data->null = false; attr_data->void_value = &data->Data[0]; + attr_data->size = sz; + + //if (m_currentTable->getTableId() >= 2) { ndbout << "var off=" << ptr-buf_ptr << " attrId=" << attrId << endl; } /** * Compute array size */ - const Uint32 arraySize = (4 * sz) / (attr_desc->size / 8); - assert(arraySize >= attr_desc->arraySize); + const Uint32 arraySize = sz / (attr_desc->size / 8); + assert(arraySize <= attr_desc->arraySize); if(!Twiddle(attr_desc, attr_data, attr_desc->arraySize)) { res = -1; return NULL; } - - ptr += (sz + 2); + + ptr += ((sz + 3) >> 2) + 2; } + assert(ptr == buf_ptr + dataLength); + m_count ++; res = 0; return &m_tuple; @@ -706,16 +723,20 @@ void TableS::createAttr(NdbDictionary::Column *column) return; } - if(!d->m_column->getNullable()) + if (d->m_column->getArrayType() == NDB_ARRAYTYPE_FIXED && + ! d->m_column->getNullable()) { m_fixedAttribs.push_back(d); return; } - /* Nullable attr*/ - d->m_nullBitIndex = m_noOfNullable; - m_noOfNullable++; - m_nullBitmaskSize = (m_noOfNullable + 31) / 32; + // just a reminder - does not solve backwards compat + if (backupVersion < MAKE_VERSION(5,1,0)) + { + d->m_nullBitIndex = m_noOfNullable; + m_noOfNullable++; + m_nullBitmaskSize = (m_noOfNullable + 31) / 32; + } m_variableAttribs.push_back(d); } // TableS::createAttr @@ -872,6 +893,7 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){ NdbRecAttr tmprec(0); tmprec.setup(desc.m_column, (char *)data.void_value); + tmprec.receive_data((Uint32*)data.void_value, data.size); ndbout << tmprec; return ndbout; diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 552246a4f9e..620e4702b15 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -341,11 +341,11 @@ void BackupRestore::tuple_a(restore_callback_t *cb) int size = attr_desc->size; int arraySize = attr_desc->arraySize; char * dataPtr = attr_data->string_value; - Uint32 length = (size * arraySize) / 8; - + Uint32 length = attr_data->size; + if (j == 0 && tup.getTable()->have_auto_inc(i)) tup.getTable()->update_max_auto_val(dataPtr,size); - + if (attr_desc->m_column->getPrimaryKey()) { if (j == 1) continue; diff --git a/storage/ndb/tools/select_all.cpp b/storage/ndb/tools/select_all.cpp index baa18db1ebd..b9d29db2082 100644 --- a/storage/ndb/tools/select_all.cpp +++ b/storage/ndb/tools/select_all.cpp @@ -43,6 +43,9 @@ static const char* _delimiter = "\t"; static int _unqualified, _header, _parallelism, _useHexFormat, _lock, _order, _descending; +static int _tup = 0; +static int _dumpDisk = 0; + static struct my_option my_long_options[] = { NDB_STD_OPTS("ndb_desc"), @@ -70,6 +73,12 @@ static struct my_option my_long_options[] = { "delimiter", 'D', "Column delimiter", (gptr*) &_delimiter, (gptr*) &_delimiter, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "disk", 256, "Dump disk ref", + (gptr*) &_dumpDisk, (gptr*) &_dumpDisk, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "tupscan", 't', "Scan in tup order", + (gptr*) &_tup, (gptr*) &_tup, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; static void usage() @@ -232,7 +241,8 @@ int scanReadRecords(Ndb* pNdb, break; case 0: default: - rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel); + rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, + _tup ? NdbScanOperation::SF_TupScan : 0, parallel); break; } if( rs != 0 ){ @@ -292,14 +302,24 @@ int scanReadRecords(Ndb* pNdb, } } - for(int a = 0; a<pTab->getNoOfColumns(); a++){ - if((row->attributeStore(a) = - pOp->getValue(pTab->getColumn(a)->getName())) == 0) { + bool disk= false; + for(int a = 0; a<pTab->getNoOfColumns(); a++) + { + const NdbDictionary::Column* col = pTab->getColumn(a); + if(col->getStorageType() == NdbDictionary::Column::StorageTypeDisk) + disk= true; + + if((row->attributeStore(a) = pOp->getValue(col)) == 0) + { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return -1; } } + + NdbRecAttr * disk_ref= 0; + if(_dumpDisk && disk) + disk_ref = pOp->getValue(NdbDictionary::Column::DISK_REF); check = pTrans->execute(NdbTransaction::NoCommit); if( check == -1 ) { @@ -317,7 +337,12 @@ int scanReadRecords(Ndb* pNdb, } if (headers) - row->header(ndbout) << endl; + row->header(ndbout); + + if (disk_ref) + ndbout << "\tDISK_REF"; + + ndbout << endl; int eof; int rows = 0; @@ -325,18 +350,27 @@ int scanReadRecords(Ndb* pNdb, while(eof == 0){ rows++; - + if (useHexFormat) { - ndbout.setHexFormat(1) << (*row) << endl; + ndbout.setHexFormat(1) << (*row); } else { - ndbout << (*row) << endl; + ndbout << (*row); } - + + if(disk_ref) + { + ndbout << "\t"; + ndbout << "[ m_file_no: " << *(Uint16*)(disk_ref->aRef()+6) + << " m_page: " << disk_ref->u_32_value() + << " m_page_idx: " << *(Uint16*)(disk_ref->aRef() + 4) << " ]"; + } + + ndbout << endl; eof = pOp->nextResult(); } if (eof == -1) { const NdbError err = pTrans->getNdbError(); - + if (err.status == NdbError::TemporaryError){ pNdb->closeTransaction(pTrans); NdbSleep_MilliSleep(50); @@ -347,11 +381,11 @@ int scanReadRecords(Ndb* pNdb, pNdb->closeTransaction(pTrans); return -1; } - + pNdb->closeTransaction(pTrans); - + ndbout << rows << " rows returned" << endl; - + return 0; } return -1; |