diff options
author | unknown <tomas@poseidon.ndb.mysql.com> | 2005-10-06 10:54:07 +0200 |
---|---|---|
committer | unknown <tomas@poseidon.ndb.mysql.com> | 2005-10-06 10:54:07 +0200 |
commit | d04832d195aba5badc42310eaa69c628a4a183bd (patch) | |
tree | cbe58ba165511396b212afaa1654a226d8ae88a4 /storage | |
parent | 282855e90bf052e2cf126adfaada61924cd8dd41 (diff) | |
parent | 3c2dca475dfa91c95f2488831fafacacaf852347 (diff) | |
download | mariadb-git-d04832d195aba5badc42310eaa69c628a4a183bd.tar.gz |
Merge
BitKeeper/etc/ignore:
auto-union
BUILD/autorun.sh:
Auto merged
BitKeeper/deleted/.del-bdb.vcproj~ed8534936e40cefb:
Auto merged
BitKeeper/deleted/.del-heap.vcproj~70c0cc1d680a51c1:
Auto merged
BitKeeper/deleted/.del-innobase.vcproj~71e1de81f11138bf:
Auto merged
BitKeeper/deleted/.del-myisam.vcproj~32bb9e4a163fcb5a:
Auto merged
BitKeeper/deleted/.del-myisammrg.vcproj~6534e59acbfbb63:
Auto merged
BitKeeper/deleted/.del-mysqld.vcproj~703886a28862bb2:
Auto merged
Makefile.am:
Auto merged
client/mysqltest.c:
Auto merged
include/my_global.h:
Auto merged
include/mysql_com.h:
Auto merged
mysql-test/mysql-test-run.pl:
Auto merged
mysql-test/r/ndb_alter_table.result:
Auto merged
mysql-test/r/ps_6bdb.result:
Auto merged
mysql-test/r/ps_7ndb.result:
Auto merged
mysql-test/t/query_cache.test:
Auto merged
mysys/default.c:
Auto merged
scripts/make_win_src_distribution.sh:
Auto merged
scripts/mysql_create_system_tables.sh:
Auto merged
scripts/mysql_fix_privilege_tables.sql:
Auto merged
sql/Makefile.am:
Auto merged
sql/field.cc:
Auto merged
sql/ha_berkeley.cc:
Auto merged
sql/ha_berkeley.h:
Auto merged
sql/ha_federated.cc:
Auto merged
sql/ha_heap.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/ha_innodb.h:
Auto merged
sql/ha_myisam.cc:
Auto merged
sql/ha_myisammrg.cc:
Auto merged
sql/ha_ndbcluster.h:
Auto merged
sql/handler.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item_subselect.cc:
Auto merged
sql/log.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/opt_sum.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sp.cc:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/sql_acl.h:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_delete.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_load.cc:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_select.h:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/table.h:
Auto merged
sql/unireg.cc:
Auto merged
storage/innobase/buf/buf0buf.c:
Auto merged
storage/innobase/buf/buf0flu.c:
Auto merged
storage/innobase/data/data0data.c:
Auto merged
storage/innobase/dict/dict0dict.c:
Auto merged
storage/innobase/include/btr0btr.h:
Auto merged
storage/innobase/include/data0type.ic:
Auto merged
storage/innobase/include/dict0dict.h:
Auto merged
storage/innobase/include/dict0mem.h:
Auto merged
storage/innobase/include/mem0mem.h:
Auto merged
storage/innobase/include/mem0mem.ic:
Auto merged
storage/innobase/include/os0file.h:
Auto merged
storage/innobase/include/row0mysql.h:
Auto merged
storage/innobase/include/trx0trx.h:
Auto merged
storage/innobase/include/ut0mem.h:
Auto merged
storage/innobase/mem/mem0mem.c:
Auto merged
storage/innobase/os/os0file.c:
Auto merged
storage/innobase/os/os0proc.c:
Auto merged
storage/innobase/rem/rem0rec.c:
Auto merged
storage/innobase/row/row0ins.c:
Auto merged
storage/innobase/row/row0mysql.c:
Auto merged
storage/innobase/srv/srv0start.c:
Auto merged
storage/innobase/trx/trx0sys.c:
Auto merged
storage/innobase/trx/trx0trx.c:
Auto merged
storage/innobase/ut/ut0mem.c:
Auto merged
storage/myisam/ft_boolean_search.c:
Auto merged
storage/myisam/mi_check.c:
Auto merged
storage/myisam/mi_dbug.c:
Auto merged
storage/myisam/mi_delete.c:
Auto merged
storage/myisam/mi_delete_all.c:
Auto merged
storage/myisam/mi_key.c:
Auto merged
storage/myisam/mi_open.c:
Auto merged
storage/myisam/mi_rkey.c:
Auto merged
storage/myisam/mi_search.c:
Auto merged
storage/myisam/mi_test1.c:
Auto merged
storage/myisam/mi_update.c:
Auto merged
storage/myisam/mi_write.c:
Auto merged
storage/myisam/myisamchk.c:
Auto merged
storage/myisam/myisamdef.h:
Auto merged
storage/myisam/myisampack.c:
Auto merged
storage/myisam/sp_key.c:
Auto merged
storage/myisammrg/myrg_rkey.c:
Auto merged
storage/ndb/include/kernel/GlobalSignalNumbers.h:
Auto merged
storage/ndb/include/kernel/signaldata/ApiVersion.hpp:
Auto merged
storage/ndb/include/kernel/signaldata/EventReport.hpp:
Auto merged
storage/ndb/include/kernel/signaldata/StopReq.hpp:
Auto merged
storage/ndb/include/mgmapi/ndb_logevent.h:
Auto merged
storage/ndb/include/ndbapi/NdbBlob.hpp:
Auto merged
storage/ndb/include/ndbapi/NdbIndexOperation.hpp:
Auto merged
storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp:
Auto merged
storage/ndb/include/ndbapi/NdbOperation.hpp:
Auto merged
storage/ndb/include/ndbapi/NdbRecAttr.hpp:
Auto merged
storage/ndb/include/ndbapi/NdbTransaction.hpp:
Auto merged
storage/ndb/src/common/util/SimpleProperties.cpp:
Auto merged
storage/ndb/src/kernel/blocks/backup/Backup.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp:
Auto merged
storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp:
Auto merged
storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp:
Auto merged
storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp:
Auto merged
storage/ndb/src/mgmapi/ndb_logevent.cpp:
Auto merged
storage/ndb/src/mgmclient/CommandInterpreter.cpp:
Auto merged
storage/ndb/src/mgmsrv/Config.cpp:
Auto merged
storage/ndb/src/mgmsrv/Config.hpp:
Auto merged
storage/ndb/src/mgmsrv/ConfigInfo.cpp:
Auto merged
storage/ndb/src/mgmsrv/InitConfigFileParser.cpp:
Auto merged
storage/ndb/src/mgmsrv/InitConfigFileParser.hpp:
Auto merged
storage/ndb/src/mgmsrv/MgmtSrvr.hpp:
Auto merged
storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp:
Auto merged
storage/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp:
Auto merged
storage/ndb/src/mgmsrv/Services.cpp:
Auto merged
storage/ndb/src/mgmsrv/Services.hpp:
Auto merged
storage/ndb/src/mgmsrv/main.cpp:
Auto merged
storage/ndb/src/ndbapi/NdbApiSignal.cpp:
Auto merged
storage/ndb/src/ndbapi/NdbApiSignal.hpp:
Auto merged
storage/ndb/src/ndbapi/NdbBlob.cpp:
Auto merged
storage/ndb/src/ndbapi/NdbImpl.hpp:
Auto merged
storage/ndb/src/ndbapi/NdbRecAttr.cpp:
Auto merged
storage/ndb/src/ndbapi/NdbUtil.cpp:
Auto merged
storage/ndb/src/ndbapi/NdbUtil.hpp:
Auto merged
storage/ndb/src/ndbapi/Ndbif.cpp:
Auto merged
storage/ndb/src/ndbapi/Ndblist.cpp:
Auto merged
storage/ndb/src/ndbapi/ObjectMap.hpp:
Auto merged
storage/ndb/test/include/NDBT_Test.hpp:
Auto merged
storage/ndb/test/ndbapi/bank/BankLoad.cpp:
Auto merged
storage/ndb/test/ndbapi/testOIBasic.cpp:
Auto merged
storage/ndb/test/src/HugoCalculator.cpp:
Auto merged
storage/ndb/test/src/NDBT_Test.cpp:
Auto merged
storage/ndb/test/src/NdbBackup.cpp:
Auto merged
storage/ndb/test/src/NdbRestarts.cpp:
Auto merged
storage/ndb/tools/ndb_condig.cpp:
Auto merged
storage/ndb/tools/restore/Restore.cpp:
Auto merged
storage/ndb/tools/restore/consumer_restore.cpp:
Auto merged
support-files/mysql.spec.sh:
Auto merged
configure.in:
merge
BUILD/SETUP.sh:
merge
BitKeeper/deleted/.del-mysql.sln~f2120278f8a437be:
SCCS merged
libmysqld/Makefile.am:
merge
sql/ha_ndbcluster.cc:
merge
sql/handler.h:
merge
sql/mysqld.cc:
merge
sql/opt_range.cc:
merge
sql/slave.cc:
merge
sql/slave.h:
e
merge
sql/sql_parse.cc:
merge
sql/table.cc:
merge
sql/examples/ha_tina.cc:
merge
sql/examples/ha_tina.h:
merge
sql/share/errmsg.txt:
merge
storage/ndb/include/ndbapi/Ndb.hpp:
merge
storage/ndb/src/common/debugger/EventLogger.cpp:
merge
storage/ndb/src/kernel/blocks/dbdict/Makefile.am:
merge
storage/ndb/src/mgmsrv/MgmtSrvr.cpp:
merge
storage/ndb/src/ndbapi/Ndbinit.cpp:
SCCS merged
Diffstat (limited to 'storage')
89 files changed, 2204 insertions, 2468 deletions
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index aa3aef7f97c..3a3b64dd51b 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -321,7 +321,9 @@ buf_page_is_corrupted( fprintf(stderr, " InnoDB: Error: page %lu log sequence number %lu %lu\n" "InnoDB: is in the future! Current system log sequence number %lu %lu.\n" -"InnoDB: Your database may be corrupt.\n", +"InnoDB: Your database may be corrupt or you may have copied the InnoDB\n" +"InnoDB: tablespace but not the InnoDB log files. See\n" +"http://dev.mysql.com/doc/mysql/en/backing-up.html for more information.\n", (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET), (ulong) ut_dulint_get_high( mach_read_from_8(read_buf + FIL_PAGE_LSN)), diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index ffb16790b2d..e39d1ae0a71 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -230,7 +230,7 @@ buf_flush_buffered_writes(void) ulint len2; ulint i; - if (trx_doublewrite == NULL) { + if (!srv_use_doublewrite_buf || trx_doublewrite == NULL) { os_aio_simulated_wake_handler_threads(); return; @@ -503,7 +503,7 @@ buf_flush_write_block_low( #endif buf_flush_init_for_writing(block->frame, block->newest_modification, block->space, block->offset); - if (!trx_doublewrite) { + if (!srv_use_doublewrite_buf || !trx_doublewrite) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, (void*)block->frame, (void*)block); diff --git a/storage/innobase/data/data0data.c b/storage/innobase/data/data0data.c index 194213a04e1..19304a7a8e1 100644 --- a/storage/innobase/data/data0data.c +++ b/storage/innobase/data/data0data.c @@ -561,12 +561,12 @@ dtuple_convert_big_rec( } /* We do not store externally fields which are smaller than - DICT_MAX_COL_PREFIX_LEN */ + DICT_MAX_INDEX_COL_LEN */ - ut_a(DICT_MAX_COL_PREFIX_LEN > REC_1BYTE_OFFS_LIMIT); + ut_a(DICT_MAX_INDEX_COL_LEN > REC_1BYTE_OFFS_LIMIT); if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10 - + DICT_MAX_COL_PREFIX_LEN) { + + DICT_MAX_INDEX_COL_LEN) { /* Cannot shorten more */ mem_heap_free(heap); @@ -588,10 +588,10 @@ dtuple_convert_big_rec( dfield = dtuple_get_nth_field(entry, longest_i); vector->fields[n_fields].field_no = longest_i; - ut_a(dfield->len > DICT_MAX_COL_PREFIX_LEN); + ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN); vector->fields[n_fields].len = dfield->len - - DICT_MAX_COL_PREFIX_LEN; + - DICT_MAX_INDEX_COL_LEN; vector->fields[n_fields].data = mem_heap_alloc(heap, vector->fields[n_fields].len); diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index 5eee57c250b..fb95ffbd80c 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -1625,7 +1625,7 @@ dict_index_add_col( variable-length fields, so that the extern flag can be embedded in the length word. */ - if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) { + if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) { field->fixed_len = 0; } @@ -2189,7 +2189,7 @@ dict_foreign_error_report( dict_foreign_error_report_low(file, fk->foreign_table_name); fputs(msg, file); fputs(" Constraint:\n", file); - dict_print_info_on_foreign_key_in_create_format(file, NULL, fk); + dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE); if (fk->foreign_index) { fputs("\nThe index in the foreign key in table is ", file); ut_print_name(file, NULL, fk->foreign_index->name); @@ -4330,9 +4330,10 @@ CREATE TABLE. */ void dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /* in: file where to print */ - trx_t* trx, /* in: transaction */ - dict_foreign_t* foreign)/* in: foreign key constraint */ + FILE* file, /* in: file where to print */ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + ibool add_newline) /* in: whether to add a newline */ { const char* stripped_id; ulint i; @@ -4345,7 +4346,16 @@ dict_print_info_on_foreign_key_in_create_format( stripped_id = foreign->id; } - fputs(",\n CONSTRAINT ", file); + putc(',', file); + + if (add_newline) { + /* SHOW CREATE TABLE wants constraints each printed nicely + on its own line, while error messages want no newlines + inserted. */ + fputs("\n ", file); + } + + fputs(" CONSTRAINT ", file); ut_print_name(file, trx, stripped_id); fputs(" FOREIGN KEY (", file); @@ -4447,7 +4457,7 @@ dict_print_info_on_foreign_keys( while (foreign != NULL) { if (create_table_format) { dict_print_info_on_foreign_key_in_create_format( - file, trx, foreign); + file, trx, foreign, TRUE); } else { ulint i; fputs("; (", file); diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 1f3a32fa70c..d28b0b129a1 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -23,16 +23,6 @@ special big record storage structure */ #define BTR_PAGE_MAX_REC_SIZE (UNIV_PAGE_SIZE / 2 - 200) -/* Maximum key size in a B-tree: the records on non-leaf levels must be -shorter than this */ - -#define BTR_PAGE_MAX_KEY_SIZE 1024 - -/* If data in page drops below this limit, we try to compress it. -NOTE! The value has to be > 2 * BTR_MAX_KEY_SIZE */ - -#define BTR_COMPRESS_LIMIT (UNIV_PAGE_SIZE / 4 + 1); - /* Latching modes for the search function (in btr0cur.*) */ #define BTR_SEARCH_LEAF RW_S_LATCH #define BTR_MODIFY_LEAF RW_X_LATCH diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index 06d45dd5501..d4a7b3c64b8 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -420,7 +420,7 @@ dtype_get_fixed_size( } /*************************************************************************** -Returns the size of a fixed size data type, 0 if not a fixed size type. */ +Returns the minimum size of a data type. */ UNIV_INLINE ulint dtype_get_min_size( diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index a1232acdca7..5215d51cabe 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -375,9 +375,10 @@ CREATE TABLE. */ void dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /* in: file where to print */ - trx_t* trx, /* in: transaction */ - dict_foreign_t* foreign);/* in: foreign key constraint */ + FILE* file, /* in: file where to print */ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + ibool add_newline); /* in: whether to add a newline */ /************************************************************************ Displays the names of the index and the table. */ void diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index ff6c4ec9b28..7eec86d0bcb 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -152,12 +152,12 @@ struct dict_col_struct{ in some of the functions below */ }; -/* DICT_MAX_COL_PREFIX_LEN is measured in bytes. Starting from 4.1.6, we -set max col prefix len to < 3 * 256, so that one can create a column prefix -index on 255 characters of a TEXT field also in the UTF-8 charset. In that -charset, a character may take at most 3 bytes. */ +/* DICT_MAX_INDEX_COL_LEN is measured in bytes and is the max index column +length + 1. Starting from 4.1.6, we set it to < 3 * 256, so that one can +create a column prefix index on 255 characters of a TEXT field also in the +UTF-8 charset. In that charset, a character may take at most 3 bytes. */ -#define DICT_MAX_COL_PREFIX_LEN 768 +#define DICT_MAX_INDEX_COL_LEN 768 /* Data structure for a field in an index */ struct dict_field_struct{ @@ -169,12 +169,12 @@ struct dict_field_struct{ prefix in bytes in a MySQL index of type, e.g., INDEX (textcol(25)); must be smaller than - DICT_MAX_COL_PREFIX_LEN; NOTE that + DICT_MAX_INDEX_COL_LEN; NOTE that in the UTF-8 charset, MySQL sets this to 3 * the prefix len in UTF-8 chars */ ulint fixed_len; /* 0 or the fixed length of the column if smaller than - DICT_MAX_COL_PREFIX_LEN */ + DICT_MAX_INDEX_COL_LEN */ ulint fixed_offs; /* offset to the field, or ULINT_UNDEFINED if it is not fixed within the record (due to preceding diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index 87afdb8f91c..3768e93c03e 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -99,8 +99,7 @@ heap freeing. */ /********************************************************************* NOTE: Use the corresponding macros instead of this function. Creates a memory heap which allocates memory from dynamic space. For debugging -purposes, takes also the file name and line as argument in the debug -version. */ +purposes, takes also the file name and line as argument. */ UNIV_INLINE mem_heap_t* mem_heap_create_func( diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 8c87c884d78..28562f7c9f8 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -371,8 +371,7 @@ mem_heap_free_top( /********************************************************************* NOTE: Use the corresponding macros instead of this function. Creates a memory heap which allocates memory from dynamic space. For debugging -purposes, takes also the file name and line as argument in the debug -version. */ +purposes, takes also the file name and line as argument. */ UNIV_INLINE mem_heap_t* mem_heap_create_func( diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index adbc4afafd2..224fd59a76b 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -432,6 +432,17 @@ os_file_read( offset */ ulint n); /* in: number of bytes to read */ /*********************************************************************** +Rewind file to its start, read at most size - 1 bytes from it to str, and +NUL-terminate str. All errors are silently ignored. This function is +mostly meant to be used with temporary files. */ + +void +os_file_read_string( +/*================*/ + FILE* file, /* in: file to read from */ + char* str, /* in: buffer where to read */ + ulint size); /* in: size of buffer */ +/*********************************************************************** Requests a synchronous positioned read operation. This function does not do any error handling. In case of error it returns FALSE. */ diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index a61705b90be..b5da4634d98 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -335,8 +335,14 @@ int row_create_index_for_mysql( /*=======================*/ /* out: error number or DB_SUCCESS */ - dict_index_t* index, /* in: index defintion */ - trx_t* trx); /* in: transaction handle */ + dict_index_t* index, /* in: index definition */ + trx_t* trx, /* in: transaction handle */ + const ulint* field_lengths); /* in: if not NULL, must contain + dict_index_get_n_fields(index) + actual field lengths for the + index columns, which are + then checked for not being too + large. */ /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 5dbf003594f..0dc82893ad1 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -56,6 +56,22 @@ void trx_search_latch_release_if_reserved( /*=================================*/ trx_t* trx); /* in: transaction */ +/********************************************************************** +Set detailed error message for the transaction. */ +void +trx_set_detailed_error( +/*===================*/ + trx_t* trx, /* in: transaction struct */ + const char* msg); /* in: detailed error message */ +/***************************************************************** +Set detailed error message for the transaction from a file. Note that the +file is rewinded before reading from it. */ + +void +trx_set_detailed_error_from_file( +/*=============================*/ + trx_t* trx, /* in: transaction struct */ + FILE* file); /* in: file to read message from */ /******************************************************************** Retrieves the error_info field from a trx. */ @@ -205,7 +221,7 @@ trx_recover_for_mysql( XID* xid_list, /* in/out: prepared transactions */ ulint len); /* in: number of slots in xid_list */ /*********************************************************************** -This function is used to commit one X/Open XA distributed transaction +This function is used to find one X/Open XA distributed transaction which is in the prepared state */ trx_t * trx_get_trx_by_xid( @@ -649,6 +665,9 @@ struct trx_struct{ trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log records which are currently processed by a rollback operation */ + /*------------------------------*/ + char detailed_error[256]; /* detailed error message for last + error, or empty. */ }; #define TRX_MAX_N_THREADS 32 /* maximum number of concurrent diff --git a/storage/innobase/include/ut0mem.h b/storage/innobase/include/ut0mem.h index 74357f6bf13..b9bbe0b5c92 100644 --- a/storage/innobase/include/ut0mem.h +++ b/storage/innobase/include/ut0mem.h @@ -119,6 +119,31 @@ int ut_strcmp(const void* str1, const void* str2); /************************************************************************** +Copies up to size - 1 characters from the NUL-terminated string src to +dst, NUL-terminating the result. Returns strlen(src), so truncation +occurred if the return value >= size. */ + +ulint +ut_strlcpy( +/*=======*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size); /* in: size of destination buffer */ + +/************************************************************************** +Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last +(size - 1) bytes of src, not the first. */ + +ulint +ut_strlcpy_rev( +/*===========*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size); /* in: size of destination buffer */ + +/************************************************************************** Compute strlen(ut_strcpyq(str, q)). */ UNIV_INLINE ulint diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c index 85f0119d02a..daf78008d45 100644 --- a/storage/innobase/mem/mem0mem.c +++ b/storage/innobase/mem/mem0mem.c @@ -187,9 +187,7 @@ mem_heap_create_block( } block->magic_n = MEM_BLOCK_MAGIC_N; - ut_memcpy(&(block->file_name), file_name + ut_strlen(file_name) - 7, - 7); - block->file_name[7]='\0'; + ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name)); block->line = line; #ifdef MEM_PERIODIC_CHECK diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 9c87b59f018..20a3303d12d 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -2249,6 +2249,29 @@ error_handling: } /*********************************************************************** +Rewind file to its start, read at most size - 1 bytes from it to str, and +NUL-terminate str. All errors are silently ignored. This function is +mostly meant to be used with temporary files. */ + +void +os_file_read_string( +/*================*/ + FILE* file, /* in: file to read from */ + char* str, /* in: buffer where to read */ + ulint size) /* in: size of buffer */ +{ + size_t flen; + + if (size == 0) { + return; + } + + rewind(file); + flen = fread(str, 1, size - 1, file); + str[flen] = '\0'; +} + +/*********************************************************************** Requests a synchronous write operation. */ ibool diff --git a/storage/innobase/os/os0proc.c b/storage/innobase/os/os0proc.c index 167aed93de7..24bb007e504 100644 --- a/storage/innobase/os/os0proc.c +++ b/storage/innobase/os/os0proc.c @@ -292,6 +292,9 @@ os_awe_allocate_physical_mem( return(TRUE); #else + UT_NOT_USED(n_megabytes); + UT_NOT_USED(page_info); + return(FALSE); #endif } @@ -349,6 +352,8 @@ os_awe_allocate_virtual_mem_window( return(ptr); #else + UT_NOT_USED(size); + return(NULL); #endif } @@ -476,6 +481,10 @@ os_awe_map_physical_mem_to_window( return(TRUE); #else + UT_NOT_USED(ptr); + UT_NOT_USED(n_mem_pages); + UT_NOT_USED(page_info); + return(FALSE); #endif } diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index fbc33aea669..9480c978755 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -621,7 +621,7 @@ rec_set_nth_field_extern_bit_new( if (field->fixed_len) { /* fixed-length fields cannot be external (Fixed-length fields longer than - DICT_MAX_COL_PREFIX_LEN will be treated as + DICT_MAX_INDEX_COL_LEN will be treated as variable-length ones in dict_index_add_col().) */ ut_ad(i != ith); continue; diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 75d8117a73e..5e833372299 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -579,6 +579,32 @@ row_ins_cascade_calc_update_vec( } /************************************************************************* +Set detailed error message associated with foreign key errors for +the given transaction. */ +static +void +row_ins_set_detailed( +/*=================*/ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign) /* in: foreign key constraint */ +{ + + FILE* tf = os_file_create_tmpfile(); + + if (tf) { + ut_print_name(tf, trx, foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format(tf, trx, + foreign, FALSE); + + trx_set_detailed_error_from_file(trx, tf); + + fclose(tf); + } else { + trx_set_detailed_error(trx, "temp file creation failed"); + } +} + +/************************************************************************* Reports a foreign key error associated with an update or a delete of a parent table index entry. */ static @@ -598,6 +624,8 @@ row_ins_foreign_report_err( FILE* ef = dict_foreign_err_file; trx_t* trx = thr_get_trx(thr); + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -607,7 +635,8 @@ row_ins_foreign_report_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign); + dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + TRUE); putc('\n', ef); fputs(errstr, ef); fputs(" in parent table, in index ", ef); @@ -648,7 +677,9 @@ row_ins_foreign_report_add_err( child table */ { FILE* ef = dict_foreign_err_file; - + + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -657,7 +688,8 @@ row_ins_foreign_report_add_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign); + dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + TRUE); fputs("\nTrying to add in child table, in index ", ef); ut_print_name(ef, trx, foreign->foreign_index->name); if (entry) { @@ -1224,6 +1256,9 @@ run_again: if (check_table == NULL || check_table->ibd_file_missing) { if (check_ref) { FILE* ef = dict_foreign_err_file; + + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -1233,7 +1268,7 @@ run_again: ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, - trx, foreign); + trx, foreign, TRUE); fputs("\nTrying to add to index ", ef); ut_print_name(ef, trx, foreign->foreign_index->name); fputs(" tuple:\n", ef); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 26aae117d1d..82f7daf2ed8 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -1973,13 +1973,20 @@ row_create_index_for_mysql( /*=======================*/ /* out: error number or DB_SUCCESS */ dict_index_t* index, /* in: index definition */ - trx_t* trx) /* in: transaction handle */ + trx_t* trx, /* in: transaction handle */ + const ulint* field_lengths) /* in: if not NULL, must contain + dict_index_get_n_fields(index) + actual field lengths for the + index columns, which are + then checked for not being too + large. */ { ind_node_t* node; mem_heap_t* heap; que_thr_t* thr; ulint err; ulint i, j; + ulint len; #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); @@ -2018,10 +2025,16 @@ row_create_index_for_mysql( } } - /* Check also that prefix_len < DICT_MAX_COL_PREFIX_LEN */ + /* Check also that prefix_len and actual length + < DICT_MAX_INDEX_COL_LEN */ + + len = dict_index_get_nth_field(index, i)->prefix_len; - if (dict_index_get_nth_field(index, i)->prefix_len - >= DICT_MAX_COL_PREFIX_LEN) { + if (field_lengths) { + len = ut_max(len, field_lengths[i]); + } + + if (len >= DICT_MAX_INDEX_COL_LEN) { err = DB_TOO_BIG_RECORD; goto error_handling; diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index 325b0a109cf..e5151ebf631 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -1540,7 +1540,7 @@ NetWare. */ #endif sync_order_checks_on = TRUE; - if (srv_use_doublewrite_buf && trx_doublewrite == NULL) { + if (trx_doublewrite == NULL) { /* Create the doublewrite buffer to a new tablespace */ trx_sys_create_doublewrite_buf(); diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index bf48c30e942..23f1dc40d00 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -126,22 +126,6 @@ trx_doublewrite_init( } /******************************************************************** -Frees the doublewrite buffer. */ -static -void -trx_doublewrite_free(void) -/*======================*/ -{ - mutex_free(&(trx_doublewrite->mutex)); - - mem_free(trx_doublewrite->buf_block_arr); - ut_free(trx_doublewrite->write_buf_unaligned); - - mem_free(trx_doublewrite); - trx_doublewrite = NULL; -} - -/******************************************************************** Marks the trx sys header when we have successfully upgraded to the >= 4.1.x multiple tablespace format. */ @@ -529,9 +513,6 @@ trx_sys_doublewrite_init_or_restore_pages( fil_flush_file_spaces(FIL_TABLESPACE); - if (!srv_use_doublewrite_buf) - trx_doublewrite_free(); - leave_func: ut_free(unaligned_read_buf); } diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 078befb81d2..090057f5d46 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -52,6 +52,32 @@ trx_start_if_not_started_noninline( trx_start_if_not_started(trx); } +/***************************************************************** +Set detailed error message for the transaction. */ + +void +trx_set_detailed_error( +/*===================*/ + trx_t* trx, /* in: transaction struct */ + const char* msg) /* in: detailed error message */ +{ + ut_strlcpy(trx->detailed_error, msg, sizeof(trx->detailed_error)); +} + +/***************************************************************** +Set detailed error message for the transaction from a file. Note that the +file is rewinded before reading from it. */ + +void +trx_set_detailed_error_from_file( +/*=============================*/ + trx_t* trx, /* in: transaction struct */ + FILE* file) /* in: file to read message from */ +{ + os_file_read_string(file, trx->detailed_error, + sizeof(trx->detailed_error)); +} + /******************************************************************** Retrieves the error_info field from a trx. */ @@ -130,6 +156,7 @@ trx_create( trx->undo_no_arr = NULL; trx->error_state = DB_SUCCESS; + trx->detailed_error[0] = '\0'; trx->sess = sess; trx->que_state = TRX_QUE_RUNNING; diff --git a/storage/innobase/ut/ut0mem.c b/storage/innobase/ut/ut0mem.c index 3e8fd79a739..47b1e24e5e1 100644 --- a/storage/innobase/ut/ut0mem.c +++ b/storage/innobase/ut/ut0mem.c @@ -343,6 +343,54 @@ ut_free_all_mem(void) } /************************************************************************** +Copies up to size - 1 characters from the NUL-terminated string src to +dst, NUL-terminating the result. Returns strlen(src), so truncation +occurred if the return value >= size. */ + +ulint +ut_strlcpy( +/*=======*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size) /* in: size of destination buffer */ +{ + ulint src_size = strlen(src); + + if (size != 0) { + ulint n = ut_min(src_size, size - 1); + + memcpy(dst, src, n); + dst[n] = '\0'; + } + + return(src_size); +} + +/************************************************************************** +Like ut_strlcpy, but if src doesn't fit in dst completely, copies the last +(size - 1) bytes of src, not the first. */ + +ulint +ut_strlcpy_rev( +/*===========*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size) /* in: size of destination buffer */ +{ + ulint src_size = strlen(src); + + if (size != 0) { + ulint n = ut_min(src_size, size - 1); + + memcpy(dst, src + src_size - n, n + 1); + } + + return(src_size); +} + +/************************************************************************** Make a quoted copy of a NUL-terminated string. Leading and trailing quotes will not be included; only embedded quotes will be escaped. See also ut_strlenq() and ut_memcpyq(). */ diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 078853bad19..563abf9f0cf 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -510,7 +510,8 @@ static int _ftb_check_phrase(const byte *s0, const byte *e0, for (;;) { n_word= (FT_WORD *)phrase_element->data; - if (my_strnncoll(cs, h_word.pos, h_word.len, n_word->pos, n_word->len)) + if (my_strnncoll(cs, (const uchar *) h_word.pos, h_word.len, + (const uchar *) n_word->pos, n_word->len)) break; if (! (phrase_element= phrase_element->next)) DBUG_RETURN(1); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index ee64f9b9979..074a1b23686 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -80,6 +80,7 @@ void myisamchk_init(MI_CHECK *param) param->start_check_pos=0; param->max_record_length= LONGLONG_MAX; param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE; + param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; } /* Check the status flags for the table */ @@ -559,10 +560,11 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ha_checksum *key_checksum, uint level) { int flag; - uint used_length,comp_flag,nod_flag,key_length=0,not_used; + uint used_length,comp_flag,nod_flag,key_length=0; uchar key[MI_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos; my_off_t next_page,record; char llbuff[22]; + uint diff_pos; DBUG_ENTER("chk_index"); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); @@ -620,7 +622,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, } if ((*keys)++ && (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length, - comp_flag, ¬_used)) >=0) + comp_flag, &diff_pos)) >=0) { DBUG_DUMP("old",(byte*) info->lastkey, info->lastkey_length); DBUG_DUMP("new",(byte*) key, key_length); @@ -636,11 +638,11 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, { if (*keys != 1L) /* not first_key */ { - uint diff; - ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY, - SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, - &diff); - param->unique_count[diff-1]++; + if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) + ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY, + SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, + &diff_pos); + param->unique_count[diff_pos-1]++; } } (*key_checksum)+= mi_byte_checksum((byte*) key, @@ -1090,7 +1092,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) "Keypointers and record positions doesn't match"); error=1; } - else if (param->glob_crc != info->s->state.checksum && + else if (param->glob_crc != info->state->checksum && (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))) { @@ -1386,7 +1388,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, info->state->data_file_length=sort_param.max_pos; } if (param->testflag & T_CALC_CHECKSUM) - share->state.checksum=param->glob_crc; + info->state->checksum=param->glob_crc; if (!(param->testflag & T_SILENT)) { @@ -2014,7 +2016,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, sort_param.sort_info=&sort_info; sort_param.fix_datafile= (my_bool) (! rep_quick); sort_param.master =1; - + del=info->state->del; param->glob_crc=0; if (param->testflag & T_CALC_CHECKSUM) @@ -2154,7 +2156,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, my_errno); } if (param->testflag & T_CALC_CHECKSUM) - share->state.checksum=param->glob_crc; + info->state->checksum=param->glob_crc; if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0))) mi_check_print_warning(param, @@ -2575,7 +2577,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, my_errno); } if (param->testflag & T_CALC_CHECKSUM) - share->state.checksum=param->glob_crc; + info->state->checksum=param->glob_crc; if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0))) mi_check_print_warning(param, @@ -3250,9 +3252,10 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE, &diff_pos); - ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, - (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, - &diff_pos); + if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) + ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, + (uchar*) a, USE_WHOLE_KEY, + SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, &diff_pos); sort_param->unique[diff_pos-1]++; } else @@ -3805,7 +3808,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename) (*org_info)->s->state.create_time=share.state.create_time; (*org_info)->s->state.unique=(*org_info)->this_unique= share.state.unique; - (*org_info)->s->state.checksum=share.state.checksum; + (*org_info)->state->checksum=info.state->checksum; (*org_info)->state->del=info.state->del; (*org_info)->s->state.dellink=share.state.dellink; (*org_info)->state->empty=info.state->empty; @@ -3989,9 +3992,10 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, unique[0]= (#different values of {keypart1}) - 1 unique[1]= (#different values of {keypart2,keypart1} tuple) - unique[0] - 1 ... - Here we assume that NULL != NULL (see SEARCH_NULL_ARE_NOT_EQUAL). The - 'unique' array is collected in one sequential scan through the entire + The 'unique' array is collected in one sequential scan through the entire index. This is done in two places: in chk_index() and in sort_key_write(). + Statistics collection may consider NULLs as either equal or unequal (see + SEARCH_NULL_ARE_NOT_EQUAL, MI_STATS_METHOD_*). Output is an array: rec_per_key_part[k] = diff --git a/storage/myisam/mi_dbug.c b/storage/myisam/mi_dbug.c index e782d21afe7..ddc8a403a33 100644 --- a/storage/myisam/mi_dbug.c +++ b/storage/myisam/mi_dbug.c @@ -40,12 +40,12 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, end= key+ keyseg->length; if (keyseg->flag & HA_NULL_PART) { - if (!*key) + /* A NULL value is encoded by a 1-byte flag. Zero means NULL. */ + if (! *(key++)) { fprintf(stream,"NULL"); continue; } - key++; } switch (keyseg->type) { diff --git a/storage/myisam/mi_delete.c b/storage/myisam/mi_delete.c index 60a07254e82..62ca7f8ff61 100644 --- a/storage/myisam/mi_delete.c +++ b/storage/myisam/mi_delete.c @@ -93,7 +93,7 @@ int mi_delete(MI_INFO *info,const byte *record) if ((*share->delete_record)(info)) goto err; /* Remove record from database */ - info->s->state.checksum-=info->checksum; + info->state->checksum-=info->checksum; info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED; info->state->records--; diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c index 3033249886f..a30abb95070 100644 --- a/storage/myisam/mi_delete_all.c +++ b/storage/myisam/mi_delete_all.c @@ -41,7 +41,7 @@ int mi_delete_all_rows(MI_INFO *info) info->state->key_file_length=share->base.keystart; info->state->data_file_length=0; info->state->empty=info->state->key_empty=0; - state->checksum=0; + info->state->checksum=0; for (i=share->base.max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; ) state->key_del[i]= HA_OFFSET_ERROR; diff --git a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c index ae50900a190..4cabfc91197 100644 --- a/storage/myisam/mi_key.c +++ b/storage/myisam/mi_key.c @@ -358,7 +358,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, byte *blob_ptr; DBUG_ENTER("_mi_put_key_in_record"); - blob_ptr= info->lastkey2; /* Place to put blob parts */ + blob_ptr= (byte*) info->lastkey2; /* Place to put blob parts */ key=(byte*) info->lastkey; /* KEy that was read */ key_end=key+info->lastkey_length; for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++) diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 82663e0c318..955d55cf765 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -199,7 +199,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d", len,MI_BASE_INFO_SIZE)) } - disk_pos=my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base); + disk_pos= (char*) + my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base); share->state.state_length=base_pos; if (!(open_flags & HA_OPEN_FOR_REPAIR) && @@ -822,7 +823,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite) mi_sizestore(ptr,state->state.empty); ptr +=8; mi_sizestore(ptr,state->state.key_empty); ptr +=8; mi_int8store(ptr,state->auto_increment); ptr +=8; - mi_int8store(ptr,(ulonglong) state->checksum);ptr +=8; + mi_int8store(ptr,(ulonglong) state->state.checksum);ptr +=8; mi_int4store(ptr,state->process); ptr +=4; mi_int4store(ptr,state->unique); ptr +=4; mi_int4store(ptr,state->status); ptr +=4; @@ -863,7 +864,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite) } -char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) +uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) { uint i,keys,key_parts,key_blocks; memcpy_fixed(&state->header,ptr, sizeof(state->header)); @@ -884,7 +885,7 @@ char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) state->state.empty = mi_sizekorr(ptr); ptr +=8; state->state.key_empty= mi_sizekorr(ptr); ptr +=8; state->auto_increment=mi_uint8korr(ptr); ptr +=8; - state->checksum=(ha_checksum) mi_uint8korr(ptr); ptr +=8; + state->state.checksum=(ha_checksum) mi_uint8korr(ptr); ptr +=8; state->process= mi_uint4korr(ptr); ptr +=4; state->unique = mi_uint4korr(ptr); ptr +=4; state->status = mi_uint4korr(ptr); ptr +=4; @@ -974,7 +975,7 @@ uint mi_base_info_write(File file, MI_BASE_INFO *base) } -char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base) +uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base) { base->keystart = mi_sizekorr(ptr); ptr +=8; base->max_data_file_length = mi_sizekorr(ptr); ptr +=8; diff --git a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c index 635a7eb2c48..575a5e34488 100644 --- a/storage/myisam/mi_rkey.c +++ b/storage/myisam/mi_rkey.c @@ -31,8 +31,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, HA_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; DBUG_ENTER("mi_rkey"); - DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d", - info,inx,search_flag)); + DBUG_PRINT("enter", ("base: %p buf: %p inx: %d search_flag: %d", + info, buf, inx, search_flag)); if ((inx = _mi_check_index(info,inx)) < 0) DBUG_RETURN(my_errno); @@ -56,9 +56,12 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, { if (key_len == 0) key_len=USE_WHOLE_KEY; + /* Save the packed key for later use in the second buffer of lastkey. */ key_buff=info->lastkey+info->s->base.max_key_length; pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (uchar*) key, key_len, &last_used_keyseg); + /* Save packed_key_length for use by the MERGE engine. */ + info->pack_key_length= pack_key_length; DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg, key_buff, pack_key_length);); } diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c index b7360dba7f3..185f196a814 100644 --- a/storage/myisam/mi_search.c +++ b/storage/myisam/mi_search.c @@ -915,11 +915,21 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, reg1 HA_KEYSEG *keyseg; uchar *start_key,*page,*page_end,*from,*from_end; uint length,tmp; + DBUG_ENTER("_mi_get_binary_pack_key"); page= *page_pos; page_end=page+MI_MAX_KEY_BUFF+1; start_key=key; + /* + Keys are compressed the following way: + + prefix length Packed length of prefix for the prev key. (1 or 3 bytes) + for each key segment: + [is null] Null indicator if can be null (1 byte, zero means null) + [length] Packed length if varlength (1 or 3 bytes) + pointer Reference to the data file (last_keyseg->length). + */ get_key_length(length,page); if (length) { @@ -930,7 +940,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, DBUG_DUMP("key",(char*) *page_pos,16); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; - return 0; /* Wrong key */ + DBUG_RETURN(0); /* Wrong key */ } from=key; from_end=key+length; } @@ -992,12 +1002,12 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, DBUG_PRINT("error",("Error when unpacking key")); mi_print_error(keyinfo->share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; - return 0; /* Error */ + DBUG_RETURN(0); /* Error */ } memcpy((byte*) key,(byte*) from,(size_t) length); *page_pos= from+length; } - return((uint) (key-start_key)+keyseg->length); + DBUG_RETURN((uint) (key-start_key)+keyseg->length); } diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c index 5727c699469..60225ccc7f3 100644 --- a/storage/myisam/mi_test1.c +++ b/storage/myisam/mi_test1.c @@ -237,7 +237,7 @@ static int run_test(const char *filename) pos=HA_OFFSET_ERROR; } if (found != row_count) - printf("Found %ld of %ld rows\n", found,row_count); + printf("Found %ld of %ld rows\n", (ulong) found, (ulong) row_count); } if (!silent) @@ -303,7 +303,8 @@ static int run_test(const char *filename) if ((error=mi_rrnd(file,read_record,i == 1 ? 0L : HA_OFFSET_ERROR)) == -1) { if (found != row_count-deleted) - printf("Found only %ld of %ld rows\n",found,row_count-deleted); + printf("Found only %ld of %ld rows\n", (ulong) found, + (ulong) (row_count - deleted)); break; } if (!error) diff --git a/storage/myisam/mi_update.c b/storage/myisam/mi_update.c index ab23f2e6da9..86652996afe 100644 --- a/storage/myisam/mi_update.c +++ b/storage/myisam/mi_update.c @@ -162,7 +162,7 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) if (auto_key_changed) update_auto_increment(info,newrec); if (share->calc_checksum) - share->state.checksum+=(info->checksum - old_checksum); + info->state->checksum+=(info->checksum - old_checksum); info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | key_changed); diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index c8f9aa84a41..8785adae9a2 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -142,7 +142,7 @@ int mi_write(MI_INFO *info, byte *record) { if ((*share->write_record)(info,record)) goto err; - share->state.checksum+=info->checksum; + info->state->checksum+=info->checksum; } if (share->base.auto_key) update_auto_increment(info,record); diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index 78ae756bf7c..a90495e5fcb 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -67,6 +67,7 @@ static const char *field_pack[]= "no zeros", "blob", "constant", "table-lockup", "always zero","varchar","unique-hash","?","?"}; +static const char *myisam_stats_method_str="nulls_unequal"; static void get_options(int *argc,char * * *argv); static void print_version(void); @@ -155,7 +156,7 @@ enum options_mc { OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE, - OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE + OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD }; static struct my_option my_long_options[] = @@ -336,6 +337,11 @@ static struct my_option my_long_options[] = "Use stopwords from this file instead of built-in list.", (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"stats_method", OPT_STATS_METHOD, + "Specifies how index statistics collection code should threat NULLs. " + "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", + (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -465,6 +471,12 @@ static void usage(void) #include <help_end.h> +const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal", + NullS}; +TYPELIB myisam_stats_method_typelib= { + array_elements(myisam_stats_method_names) - 1, "", + myisam_stats_method_names, NULL}; + /* Read options */ static my_bool @@ -684,6 +696,18 @@ get_one_option(int optid, else check_param.testflag|= T_CALC_CHECKSUM; break; + case OPT_STATS_METHOD: + { + int method; + myisam_stats_method_str= argument; + if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0) + { + fprintf(stderr, "Invalid value of stats_method: %s.\n", argument); + exit(1); + } + check_param.stats_method= (enum_mi_stats_method) (method-1); + break; + } #ifdef DEBUG /* Only useful if debugging */ case OPT_START_CHECK_POS: check_param.start_check_pos= strtoull(argument, NULL, 0); @@ -1237,7 +1261,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name) share->base.raid_chunksize); } if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) - printf("Checksum: %23s\n",llstr(info->s->state.checksum,llbuff)); + printf("Checksum: %23s\n",llstr(info->state->checksum,llbuff)); ; if (share->options & HA_OPTION_DELAY_KEY_WRITE) printf("Keys are only flushed at close\n"); @@ -1552,7 +1576,7 @@ static int mi_sort_records(MI_CHECK *param, old_record_count=info->state->records; info->state->records=0; if (sort_info.new_data_file_type != COMPRESSED_RECORD) - share->state.checksum=0; + info->state->checksum=0; if (sort_record_index(&sort_param,info,keyinfo,share->state.key_root[sort_key], temp_buff, sort_key,new_file,update_index) || diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 82f7fd7360e..87a1b757d88 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -38,6 +38,7 @@ typedef struct st_mi_status_info my_off_t key_empty; /* lost space in indexfile */ my_off_t key_file_length; my_off_t data_file_length; + ha_checksum checksum; } MI_STATUS_INFO; typedef struct st_mi_state_info @@ -75,7 +76,6 @@ typedef struct st_mi_state_info ulong sec_index_changed; /* Updated when new sec_index */ ulong sec_index_used; /* which extra index are in use */ ulonglong key_map; /* Which keys are in use */ - ha_checksum checksum; ulong version; /* timestamp of create */ time_t create_time; /* Time when created database */ time_t recover_time; /* Time for last recover */ @@ -261,6 +261,7 @@ struct st_myisam_info { uint last_rkey_length; /* Last length in mi_rkey() */ enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */ uint save_lastkey_length; + uint pack_key_length; /* For MYISAMMRG */ int errkey; /* Got last error on this key */ int lock_type; /* How database was locked */ int tmp_lock_type; /* When locked by readinfo */ @@ -679,10 +680,10 @@ extern uint read_pack_length(uint version, const uchar *buf, ulong *length); extern uint calc_pack_length(uint version, ulong length); uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite); -char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); +uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead); uint mi_base_info_write(File file, MI_BASE_INFO *base); -char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); +uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); int mi_keyseg_write(File file, const HA_KEYSEG *keyseg); char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg); uint mi_keydef_write(File file, MI_KEYDEF *keydef); diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 3b091cd6ea2..114e80d8f1a 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -2008,7 +2008,7 @@ static char *hexdigits(ulonglong value) static int write_header(PACK_MRG_INFO *mrg,uint head_length,uint trees, my_off_t tot_elements,my_off_t filelength) { - byte *buff=file_buffer.pos; + byte *buff= (byte*) file_buffer.pos; bzero(buff,HEAD_LENGTH); memcpy_fixed(buff,myisam_pack_file_magic,4); @@ -2024,7 +2024,7 @@ static int write_header(PACK_MRG_INFO *mrg,uint head_length,uint trees, if (test_only) return 0; VOID(my_seek(file_buffer.file,0L,MY_SEEK_SET,MYF(0))); - return my_write(file_buffer.file,file_buffer.pos,HEAD_LENGTH, + return my_write(file_buffer.file,(const byte *) file_buffer.pos,HEAD_LENGTH, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; } @@ -2472,7 +2472,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) { if (flush_buffer((ulong) max_calc_length + (ulong) max_pack_length)) break; - record_pos=file_buffer.pos; + record_pos= (byte*) file_buffer.pos; file_buffer.pos+=max_pack_length; for (start_pos=record, count= huff_counts; count < end_count ; count++) { @@ -2795,7 +2795,8 @@ static char *make_old_name(char *new_name, char *old_name) static void init_file_buffer(File file, pbool read_buffer) { file_buffer.file=file; - file_buffer.buffer=my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE),MYF(MY_WME)); + file_buffer.buffer= (uchar*) my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE), + MYF(MY_WME)); file_buffer.end=file_buffer.buffer+ALIGN_SIZE(RECORD_CACHE_SIZE)-8; file_buffer.pos_in_file=0; error_on_write=0; @@ -2837,7 +2838,8 @@ static int flush_buffer(ulong neaded_length) file_buffer.pos_in_file+=length; if (test_only) return 0; - if (error_on_write|| my_write(file_buffer.file,file_buffer.buffer, + if (error_on_write|| my_write(file_buffer.file, + (const byte*) file_buffer.buffer, length, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) { @@ -2850,13 +2852,13 @@ static int flush_buffer(ulong neaded_length) { char *tmp; neaded_length+=256; /* some margin */ - tmp=my_realloc(file_buffer.buffer, neaded_length,MYF(MY_WME)); + tmp= my_realloc((char*) file_buffer.buffer, neaded_length,MYF(MY_WME)); if (!tmp) return 1; file_buffer.pos= ((uchar*) tmp + (ulong) (file_buffer.pos - file_buffer.buffer)); - file_buffer.buffer=tmp; - file_buffer.end=tmp+neaded_length-8; + file_buffer.buffer= (uchar*) tmp; + file_buffer.end= (uchar*) (tmp+neaded_length-8); } return 0; } @@ -2965,7 +2967,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->state.key_root[key]= HA_OFFSET_ERROR; for (key=0 ; key < share->state.header.max_block_size ; key++) share->state.key_del[key]= HA_OFFSET_ERROR; - share->state.checksum=crc; /* Save crc here */ + isam_file->state->checksum=crc; /* Save crc here */ share->changed=1; /* Force write of header */ share->state.open_count=0; share->global_changed=0; @@ -3001,7 +3003,7 @@ static int save_state_mrg(File file,PACK_MRG_INFO *mrg,my_off_t new_length, state.dellink= HA_OFFSET_ERROR; state.version=(ulong) time((time_t*) 0); mi_clear_all_keys_active(state.key_map); - state.checksum=crc; + state.state.checksum=crc; if (isam_file->s->base.keys) isamchk_neaded=1; state.changed=STATE_CHANGED | STATE_NOT_ANALYZED; /* Force check of table */ diff --git a/storage/myisam/sp_key.c b/storage/myisam/sp_key.c index 1d43f89cba9..77cecdc0931 100644 --- a/storage/myisam/sp_key.c +++ b/storage/myisam/sp_key.c @@ -142,7 +142,7 @@ static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims, { if ((*wkb) > end - 8) return -1; - get_double(&ord, *wkb); + get_double(&ord, (const byte*) *wkb); (*wkb)+= 8; if (ord < *mbr) float8store((char*) mbr, ord); diff --git a/storage/myisammrg/myrg_rkey.c b/storage/myisammrg/myrg_rkey.c index a85ef6a3b5e..f87b264081e 100644 --- a/storage/myisammrg/myrg_rkey.c +++ b/storage/myisammrg/myrg_rkey.c @@ -44,11 +44,12 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, MYRG_TABLE *table; MI_INFO *mi; int err; + DBUG_ENTER("myrg_rkey"); LINT_INIT(key_buff); LINT_INIT(pack_key_length); if (_myrg_init_queue(info,inx,search_flag)) - return my_errno; + DBUG_RETURN(my_errno); for (table=info->open_tables ; table != info->end_table ; table++) { @@ -57,8 +58,9 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, if (table == info->open_tables) { err=mi_rkey(mi,0,inx,key,key_len,search_flag); + /* Get the saved packed key and packed key length. */ key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length; - pack_key_length=mi->last_rkey_length; + pack_key_length=mi->pack_key_length; } else { @@ -71,17 +73,22 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, { if (err == HA_ERR_KEY_NOT_FOUND) continue; - return err; + DBUG_PRINT("exit", ("err: %d", err)); + DBUG_RETURN(err); } /* adding to queue */ queue_insert(&(info->by_key),(byte *)table); } + DBUG_PRINT("info", ("tables with matches: %u", info->by_key.elements)); if (!info->by_key.elements) - return HA_ERR_KEY_NOT_FOUND; + DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; mi->once_flags|= RRND_PRESERVE_LASTINX; - return _myrg_mi_read_record(mi,buf); + DBUG_PRINT("info", ("using table no: %d", + info->current_table - info->open_tables + 1)); + DBUG_DUMP("result key", (byte*) mi->lastkey, mi->lastkey_length); + DBUG_RETURN(_myrg_mi_read_record(mi,buf)); } diff --git a/storage/ndb/include/kernel/GlobalSignalNumbers.h b/storage/ndb/include/kernel/GlobalSignalNumbers.h index 141e7392250..2cecd109ac1 100644 --- a/storage/ndb/include/kernel/GlobalSignalNumbers.h +++ b/storage/ndb/include/kernel/GlobalSignalNumbers.h @@ -554,7 +554,6 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_STATISTICS_CONF 454 #define GSN_START_ORD 455 -/* 456 unused */ /* 457 unused */ #define GSN_EVENT_SUBSCRIBE_REQ 458 @@ -830,14 +829,6 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_656 -/** - * Management server - */ -#define GSN_MGM_LOCK_CONFIG_REQ 657 -#define GSN_MGM_LOCK_CONFIG_REP 658 -#define GSN_MGM_UNLOCK_CONFIG_REQ 659 -#define GSN_MGM_UNLOCK_CONFIG_REP 660 - #define GSN_UTIL_CREATE_LOCK_REQ 132 #define GSN_UTIL_CREATE_LOCK_REF 133 #define GSN_UTIL_CREATE_LOCK_CONF 188 @@ -894,6 +885,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_RESUME_REQ 682 #define GSN_STOP_REQ 443 #define GSN_STOP_REF 444 +#define GSN_STOP_CONF 456 #define GSN_API_VERSION_REQ 697 #define GSN_API_VERSION_CONF 698 diff --git a/storage/ndb/include/kernel/signaldata/ApiVersion.hpp b/storage/ndb/include/kernel/signaldata/ApiVersion.hpp index 28281e7d186..a3774c9fba6 100644 --- a/storage/ndb/include/kernel/signaldata/ApiVersion.hpp +++ b/storage/ndb/include/kernel/signaldata/ApiVersion.hpp @@ -49,12 +49,11 @@ class ApiVersionConf { */ friend class MgmtSrv; public: - STATIC_CONST( SignalLength = 3 ); + STATIC_CONST( SignalLength = 4 ); Uint32 senderRef; Uint32 nodeId; //api node id Uint32 version; // Version of API node - - + Uint32 inet_addr; }; #endif diff --git a/storage/ndb/include/kernel/signaldata/StopReq.hpp b/storage/ndb/include/kernel/signaldata/StopReq.hpp index ea453ae115d..8e6a0b90a91 100644 --- a/storage/ndb/include/kernel/signaldata/StopReq.hpp +++ b/storage/ndb/include/kernel/signaldata/StopReq.hpp @@ -67,6 +67,13 @@ public: static bool getStopAbort(const Uint32 & requestInfo); }; +struct StopConf +{ + STATIC_CONST( SignalLength = 2 ); + Uint32 senderData; + Uint32 nodeState; +}; + class StopRef { /** @@ -86,7 +93,8 @@ public: OK = 0, NodeShutdownInProgress = 1, SystemShutdownInProgress = 2, - NodeShutdownWouldCauseSystemCrash = 3 + NodeShutdownWouldCauseSystemCrash = 3, + TransactionAbortFailed = 4 }; public: diff --git a/storage/ndb/include/mgmapi/ndb_logevent.h b/storage/ndb/include/mgmapi/ndb_logevent.h index f3f9d04e6d0..b0c14f91c4c 100644 --- a/storage/ndb/include/mgmapi/ndb_logevent.h +++ b/storage/ndb/include/mgmapi/ndb_logevent.h @@ -148,9 +148,9 @@ extern "C" { /** NDB_MGM_EVENT_CATEGORY_INFO */ NDB_LE_InfoEvent = 49, - /* GREP */ - NDB_LE_GrepSubscriptionInfo = 52, - NDB_LE_GrepSubscriptionAlert = 53, + /* SINGLE USER */ + NDB_LE_SingleUser = 52, + /* NDB_LE_ UNUSED = 53, */ /** NDB_MGM_EVENT_CATEGORY_BACKUP */ NDB_LE_BackupStarted = 54, @@ -607,6 +607,11 @@ extern "C" { unsigned backup_id; unsigned error; } BackupAborted; + /** Log event data @ref NDB_LE_SingleUser */ + struct { + unsigned type; + unsigned node_id; + } SingleUser; #ifndef DOXYGEN_FIX }; #else diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp index cae2c4653e6..f8337d4b281 100644 --- a/storage/ndb/include/ndbapi/Ndb.hpp +++ b/storage/ndb/include/ndbapi/Ndb.hpp @@ -986,10 +986,10 @@ class NdbBlob; class NdbReceiver; class TransporterFacade; class PollGuard; +template <class T> struct Ndb_free_list_t; typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*); - #if defined NDB_OSE /** * Default time to wait for response after request has been sent to @@ -1473,8 +1473,20 @@ public: */ NdbTransaction* hupp( NdbTransaction* ); Uint32 getReference() const { return theMyRef;} + + struct Free_list_usage + { + const char * m_name; + Uint32 m_created; + Uint32 m_free; + Uint32 m_sizeof; + }; + + Free_list_usage * get_free_list_usage(Free_list_usage*); #endif + + /***************************************************************************** * These are service routines used by the other classes in the NDBAPI. ****************************************************************************/ @@ -1650,22 +1662,8 @@ private: class NdbDictionaryImpl* theDictionary; class NdbEventBuffer* theEventBuffer; - NdbTransaction* theConIdleList; // First connection in idle list. - - NdbOperation* theOpIdleList; // First operation in the idle list. - - NdbIndexScanOperation* theScanOpIdleList; // First scan operation in the idle list. - NdbIndexOperation* theIndexOpIdleList; // First index operation in the idle list. NdbTransaction* theTransactionList; NdbTransaction** theConnectionArray; - NdbRecAttr* theRecAttrIdleList; - NdbApiSignal* theSignalIdleList; // First signal in idlelist. - NdbLabel* theLabelList; // First label descriptor in list - NdbBranch* theBranchList; // First branch descriptor in list - NdbSubroutine* theSubroutineList; // First subroutine descriptor in - NdbCall* theCallList; // First call descriptor in list - NdbReceiver* theScanList; - NdbBlob* theNdbBlobIdleList; Uint32 theMyRef; // My block reference Uint32 theNode; // The node number of our node diff --git a/storage/ndb/include/ndbapi/NdbBlob.hpp b/storage/ndb/include/ndbapi/NdbBlob.hpp index 271287b765c..cb0caafe34f 100644 --- a/storage/ndb/include/ndbapi/NdbBlob.hpp +++ b/storage/ndb/include/ndbapi/NdbBlob.hpp @@ -277,7 +277,7 @@ private: // for keeping in lists NdbBlob* theNext; // initialization - NdbBlob(); + NdbBlob(Ndb*); void init(); void release(); // classify operations @@ -329,6 +329,10 @@ private: int getOperationType() const; friend class NdbOut& operator<<(NdbOut&, const NdbBlob&); #endif + + void next(NdbBlob* obj) { theNext= obj;} + NdbBlob* next() { return theNext;} + friend struct Ndb_free_list_t<NdbBlob>; }; #endif diff --git a/storage/ndb/include/ndbapi/NdbIndexOperation.hpp b/storage/ndb/include/ndbapi/NdbIndexOperation.hpp index 3de6835238e..a8a15978568 100644 --- a/storage/ndb/include/ndbapi/NdbIndexOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbIndexOperation.hpp @@ -181,6 +181,7 @@ private: // Private attributes const NdbIndexImpl* m_theIndex; + friend struct Ndb_free_list_t<NdbIndexOperation>; }; #endif diff --git a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp index fd7e9f2d05c..dea0a079d4a 100644 --- a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp @@ -168,9 +168,10 @@ private: int compare(Uint32 key, Uint32 cols, const NdbReceiver*, const NdbReceiver*); Uint32 m_sort_columns; - Uint32 m_this_bound_start; Uint32 * m_first_bound_word; + + friend struct Ndb_free_list_t<NdbIndexScanOperation>; }; #endif diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index fca610772cc..1035c642c97 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -22,6 +22,7 @@ #include "NdbError.hpp" #include "NdbReceiver.hpp" #include "NdbDictionary.hpp" +#include "Ndb.hpp" class Ndb; class NdbApiSignal; @@ -756,8 +757,6 @@ protected: /****************************************************************************** * These are the methods used to create and delete the NdbOperation objects. *****************************************************************************/ - NdbOperation(Ndb* aNdb); - virtual ~NdbOperation(); bool needReply(); /****************************************************************************** @@ -769,6 +768,8 @@ protected: int init(const class NdbTableImpl*, NdbTransaction* aCon); void initInterpreter(); + NdbOperation(Ndb* aNdb); + virtual ~NdbOperation(); void next(NdbOperation*); // Set next pointer NdbOperation* next(); // Get next pointer public: @@ -965,6 +966,8 @@ protected: * IgnoreError on connection level. */ Int8 m_abortOption; + + friend struct Ndb_free_list_t<NdbOperation>; }; #ifdef NDB_NO_DROPPED_SIGNAL diff --git a/storage/ndb/include/ndbapi/NdbRecAttr.hpp b/storage/ndb/include/ndbapi/NdbRecAttr.hpp index 50de4f3277e..3607a64f3b3 100644 --- a/storage/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp @@ -17,7 +17,8 @@ #ifndef NdbRecAttr_H #define NdbRecAttr_H -#include <NdbDictionary.hpp> +#include "NdbDictionary.hpp" +#include "Ndb.hpp" class NdbOperation; @@ -248,7 +249,6 @@ public: const NdbRecAttr* next() const; #endif private: - NdbRecAttr(); Uint32 attrId() const; /* Get attribute id */ bool setNULL(); /* Set NULL indicator */ @@ -258,6 +258,7 @@ private: void release(); /* Release memory if allocated */ void init(); /* Initialise object when allocated */ + NdbRecAttr(Ndb*); void next(NdbRecAttr* aRecAttr); NdbRecAttr* next(); @@ -280,6 +281,8 @@ private: Uint32 theAttrSize; Uint32 theArraySize; const NdbDictionary::Column* m_column; + + friend struct Ndb_free_list_t<NdbRecAttr>; }; #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL diff --git a/storage/ndb/include/ndbapi/NdbTransaction.hpp b/storage/ndb/include/ndbapi/NdbTransaction.hpp index 2e102b104d8..a6ba6a11c4d 100644 --- a/storage/ndb/include/ndbapi/NdbTransaction.hpp +++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp @@ -18,8 +18,9 @@ #define NdbTransaction_H #include <ndb_types.h> -#include <NdbError.hpp> -#include <NdbDictionary.hpp> +#include "NdbError.hpp" +#include "NdbDictionary.hpp" +#include "Ndb.hpp" class NdbTransaction; class NdbOperation; @@ -581,9 +582,7 @@ private: /************************************************************************** * These are the create and delete methods of this class. * **************************************************************************/ - NdbTransaction(Ndb* aNdb); - ~NdbTransaction(); void init(); // Initialize connection object for new transaction @@ -807,6 +806,7 @@ private: void define_scan_op(NdbIndexScanOperation*); friend class HugoOperations; + friend struct Ndb_free_list_t<NdbTransaction>; }; #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL diff --git a/storage/ndb/src/common/debugger/EventLogger.cpp b/storage/ndb/src/common/debugger/EventLogger.cpp index 06345695107..36796e700b4 100644 --- a/storage/ndb/src/common/debugger/EventLogger.cpp +++ b/storage/ndb/src/common/debugger/EventLogger.cpp @@ -669,6 +669,27 @@ void getTextBackupAborted(QQQQ) { theData[3]); } +void getTextSingleUser(QQQQ) { + switch (theData[1]) + { + case 0: + BaseString::snprintf(m_text, m_text_len, "Entering single user mode"); + break; + case 1: + BaseString::snprintf(m_text, m_text_len, + "Entered single user mode " + "Node %d has exclusive access", theData[2]); + break; + case 2: + BaseString::snprintf(m_text, m_text_len,"Exiting single user mode"); + break; + default: + BaseString::snprintf(m_text, m_text_len, + "Unknown single user report %d", theData[1]); + break; + } +} + #if 0 BaseString::snprintf(m_text, m_text_len, @@ -753,6 +774,9 @@ const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = { ROW(InfoEvent, LogLevel::llInfo, 2, Logger::LL_INFO ), ROW(EventBufferStatus, LogLevel::llInfo, 7, Logger::LL_INFO ), + //Single User + ROW(SingleUser, LogLevel::llInfo, 7, Logger::LL_INFO ), + // Backup ROW(BackupStarted, LogLevel::llBackup, 7, Logger::LL_INFO ), ROW(BackupCompleted, LogLevel::llBackup, 7, Logger::LL_INFO ), diff --git a/storage/ndb/src/common/util/SimpleProperties.cpp b/storage/ndb/src/common/util/SimpleProperties.cpp index c25aaea491a..c9251c6a854 100644 --- a/storage/ndb/src/common/util/SimpleProperties.cpp +++ b/storage/ndb/src/common/util/SimpleProperties.cpp @@ -51,11 +51,12 @@ SimpleProperties::Writer::add(const char * value, int len){ union { Uint32 lastWord; char lastBytes[4]; - }; - memcpy(lastBytes, + } tmp; + tmp.lastWord =0 ; + memcpy(tmp.lastBytes, value + putLen*4, len - putLen*4); - return putWord(lastWord); + return putWord(tmp.lastWord); } bool diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.cpp b/storage/ndb/src/kernel/blocks/backup/Backup.cpp index 063e36a775f..cbffd6bcb6b 100644 --- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp @@ -3262,6 +3262,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) req->requestInfo = 0; req->savePointId = 0; req->tableId = table.tableId; + ScanFragReq::setReadCommittedFlag(req->requestInfo, 1); ScanFragReq::setLockMode(req->requestInfo, 0); ScanFragReq::setHoldLockFlag(req->requestInfo, 0); ScanFragReq::setKeyinfoFlag(req->requestInfo, 0); diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index a09ee0472a4..7ec3bde41e8 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -3255,8 +3255,8 @@ Dbdict::alterTable_backup_mutex_locked(Signal* signal, lreq->gci = tablePtr.p->gciTableCreated; lreq->requestType = AlterTabReq::AlterTablePrepare; - sendSignal(rg, GSN_ALTER_TAB_REQ, signal, - AlterTabReq::SignalLength, JBB); + sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal, + AlterTabReq::SignalLength, JBB); } void Dbdict::alterTableRef(Signal * signal, @@ -3740,8 +3740,8 @@ Dbdict::execALTER_TAB_CONF(Signal * signal){ lreq->gci = gci; lreq->requestType = AlterTabReq::AlterTableCommit; - sendSignal(rg, GSN_ALTER_TAB_REQ, signal, - AlterTabReq::SignalLength, JBB); + sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal, + AlterTabReq::SignalLength, JBB); } } else { diff --git a/storage/ndb/src/kernel/blocks/dbdict/Makefile.am b/storage/ndb/src/kernel/blocks/dbdict/Makefile.am index 0c22e06b855..367e3cf203b 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Makefile.am +++ b/storage/ndb/src/kernel/blocks/dbdict/Makefile.am @@ -1,12 +1,20 @@ -#SUBDIRS = printSchemafile - 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 +LDADD += \ + $(top_builddir)/storage/ndb/src/common/util/libgeneral.la \ + $(top_builddir)/storage/ndb/src/common/portlib/libportlib.la \ + $(top_builddir)/dbug/libdbug.a \ + $(top_builddir)/mysys/libmysys.a \ + $(top_builddir)/strings/libmystrings.a + # 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 9858744a61d..f73654fd9d5 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp @@ -1,14 +1,3 @@ -#if 0 -make -f Makefile -f - printSchemaFile <<'_eof_' -printSchemaFile: printSchemaFile.cpp SchemaFile.hpp - $(CXXCOMPILE) -o $@ $@.cpp -L../../../common/util/.libs -lgeneral -ifneq ($(MYSQL_HOME),) - ln -sf `pwd`/$@ $(MYSQL_HOME)/bin/$@ -endif -_eof_ -exit $? -#endif - /* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify @@ -36,14 +25,19 @@ exit $? static const char* progname = 0; static bool allflag = false; static bool checkonly = false; -static int xitcode = 0; +static bool equalcontents = false; +static bool okquiet = false; static void usage() { - ndbout << "Usage " << progname - << " [-ac]" - << " P0.SchemaLog" << endl; + ndbout + << "Usage: " << progname << " [-aceq]" << " file ..." << endl + << "-a print also unused slots" << endl + << "-c check only (return status 1 on error)" << endl + << "-e check also that the files have identical contents" << endl + << "-q no output if file is ok" << endl + << "Example: " << progname << " -ceq ndb_*_fs/D[12]/DBDICT/P0.SchemaLog" << endl; } static void @@ -57,53 +51,78 @@ fill(const char * buf, int mod) } } -static void +static const char* +version(Uint32 v) +{ + static char buf[40]; + sprintf(buf, "%d.%d.%d", v >> 16, (v >> 8) & 0xFF, v & 0xFF); + return buf; +} + +static int print_head(const char * filename, const SchemaFile * sf) { + int retcode = 0; + if (! checkonly) { ndbout << "----- Schemafile: " << filename << " -----" << endl; - ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %d.%d.%d FileSize: %d", + ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %s FileSize: %d", sizeof(sf->Magic), sf->Magic, sf->ByteOrder, - sf->NdbVersion >> 16, - (sf->NdbVersion >> 8) & 0xFF, - sf->NdbVersion & 0xFF, + version(sf->NdbVersion), sf->FileSize); } + + if (memcmp(sf->Magic, "NDBSCHMA", sizeof(sf->Magic) != 0)) { + ndbout << filename << ": invalid header magic" << endl; + retcode = 1; + } + + if ((sf->NdbVersion >> 16) < 4 || (sf->NdbVersion >> 16) > 9) { + ndbout << filename << ": impossible version " << hex << sf->NdbVersion << endl; + retcode = 1; + } + + return retcode; } -static void -print_old(const char * filename, const SchemaFile * sf) +static int +print_old(const char * filename, const SchemaFile * sf, Uint32 sz) { - print_head(filename, sf); + int retcode = 0; + + if (print_head(filename, sf) != 0) + retcode = 1; for (Uint32 i = 0; i < sf->NoOfTableEntries; i++) { SchemaFile::TableEntry_old te = sf->TableEntries_old[i]; if (allflag || (te.m_tableState != SchemaFile::INIT && te.m_tableState != SchemaFile::DROP_TABLE_COMMITTED)) { - ndbout << "Table " << i << ":" - << " State = " << te.m_tableState - << " version = " << table_version_major(te.m_tableVersion) << - << "(" << table_version_minor(te.m_tableVersion) << ")" - << " type = " << te.m_tableType - << " noOfPages = " << te.m_noOfPages - << " gcp: " << te.m_gcp << endl; + if (! checkonly) + ndbout << "Table " << i << ":" + << " State = " << te.m_tableState + << " version = " << te.m_tableVersion + << " type = " << te.m_tableType + << " noOfPages = " << te.m_noOfPages + << " gcp: " << te.m_gcp << endl; } } + return retcode; } -static void +static int print(const char * filename, const SchemaFile * xsf, Uint32 sz) { int retcode = 0; - print_head(filename, xsf); + if (print_head(filename, xsf) != 0) + retcode = 1; assert(sizeof(SchemaFile) == NDB_SF_PAGE_SIZE); if (xsf->FileSize != sz || xsf->FileSize % NDB_SF_PAGE_SIZE != 0) { - ndbout << "***** invalid FileSize " << xsf->FileSize << endl; + ndbout << filename << ": invalid FileSize " << xsf->FileSize << endl; retcode = 1; } Uint32 noOfPages = xsf->FileSize / NDB_SF_PAGE_SIZE; @@ -112,19 +131,23 @@ print(const char * filename, const SchemaFile * xsf, Uint32 sz) ndbout << "----- Page: " << n << " (" << noOfPages << ") -----" << endl; } const SchemaFile * sf = &xsf[n]; + if (memcmp(sf->Magic, xsf->Magic, sizeof(sf->Magic)) != 0) { + ndbout << filename << ": page " << n << " invalid magic" << endl; + retcode = 1; + } if (sf->FileSize != xsf->FileSize) { - ndbout << "***** page " << n << " FileSize changed to " << sf->FileSize << "!=" << xsf->FileSize << endl; + ndbout << filename << ": page " << n << " FileSize changed to " << sf->FileSize << "!=" << xsf->FileSize << endl; retcode = 1; } Uint32 cs = 0; for (Uint32 j = 0; j < NDB_SF_PAGE_SIZE_IN_WORDS; j++) cs ^= ((const Uint32*)sf)[j]; if (cs != 0) { - ndbout << "***** page " << n << " invalid CheckSum" << endl; + ndbout << filename << ": page " << n << " invalid CheckSum" << endl; retcode = 1; } if (sf->NoOfTableEntries != NDB_SF_PAGE_ENTRIES) { - ndbout << "***** page " << n << " invalid NoOfTableEntries " << sf->NoOfTableEntries << endl; + ndbout << filename << ": page " << n << " invalid NoOfTableEntries " << sf->NoOfTableEntries << endl; retcode = 1; } for (Uint32 i = 0; i < NDB_SF_PAGE_ENTRIES; i++) { @@ -142,31 +165,41 @@ print(const char * filename, const SchemaFile * xsf, Uint32 sz) << " gcp: " << te.m_gcp << endl; } if (te.m_unused[0] != 0 || te.m_unused[1] != 0 || te.m_unused[2] != 0) { - ndbout << "***** entry " << j << " garbage in m_unused[3]" << endl; + ndbout << filename << ": entry " << j << " garbage in m_unused[3]" << endl; retcode = 1; } } } - if (retcode != 0) - xitcode = 1; - else if (checkonly) - ndbout << "ok: " << filename << endl; + return retcode; } NDB_COMMAND(printSchemafile, "printSchemafile", "printSchemafile", "Prints a schemafile", 16384) { progname = argv[0]; + int exitcode = 0; - while (argv[1][0] == '-') { + while (argc > 1 && argv[1][0] == '-') { if (strchr(argv[1], 'a') != 0) allflag = true; if (strchr(argv[1], 'c') != 0) checkonly = true; + if (strchr(argv[1], 'e') != 0) + equalcontents = true; + if (strchr(argv[1], 'q') != 0) + okquiet = true; + if (strchr(argv[1], 'h') != 0 || strchr(argv[1], '?') != 0) { + usage(); + return 0; + } argc--, argv++; } + const char * prevfilename = 0; + Uint32 * prevbuf = 0; + Uint32 prevbytes = 0; + while (argc > 1) { const char * filename = argv[1]; argc--, argv++; @@ -174,8 +207,9 @@ NDB_COMMAND(printSchemafile, struct stat sbuf; const int res = stat(filename, &sbuf); if (res != 0) { - ndbout << "Could not find file: \"" << filename << "\"" << endl; - return 1; + ndbout << filename << ": not found errno=" << errno << endl; + exitcode = 1; + continue; } const Uint32 bytes = sbuf.st_size; @@ -183,25 +217,56 @@ NDB_COMMAND(printSchemafile, FILE * f = fopen(filename, "rb"); if (f == 0) { - ndbout << "Failed to open file" << endl; + ndbout << filename << ": open failed errno=" << errno << endl; delete [] buf; - return 1; + exitcode = 1; + continue; } Uint32 sz = fread(buf, 1, bytes, f); fclose(f); if (sz != bytes) { - ndbout << "Failure while reading file" << endl; + ndbout << filename << ": read failed errno=" << errno << endl; + delete [] buf; + exitcode = 1; + continue; + } + + if (sz < 32) { + ndbout << filename << ": too short (no header)" << endl; delete [] buf; - return 1; + exitcode = 1; + continue; } SchemaFile* sf = (SchemaFile *)&buf[0]; + int ret; if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) - print_old(filename, sf); + ret = print_old(filename, sf, sz); else - print(filename, sf, sz); - delete [] buf; + ret = print(filename, sf, sz); + + if (ret != 0) { + ndbout << filename << ": check failed" + << " version=" << version(sf->NdbVersion) << endl; + exitcode = 1; + } else if (! okquiet) { + ndbout << filename << ": ok" + << " version=" << version(sf->NdbVersion) << endl; + } + + if (equalcontents && prevfilename != 0) { + if (prevbytes != bytes || memcmp(prevbuf, buf, bytes) != 0) { + ndbout << filename << ": differs from " << prevfilename << endl; + exitcode = 1; + } + } + + prevfilename = filename; + delete [] prevbuf; + prevbuf = buf; + prevbytes = bytes; } - return xitcode; + delete [] prevbuf; + return exitcode; } diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index 9631a2b2e9b..65a61174596 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -1004,8 +1004,19 @@ Dbtup::read_pseudo(Uint32 attrId, Uint32* outBuffer){ return 1; case AttributeHeader::FRAGMENT_MEMORY: { - Uint64 tmp= fragptr.p->noOfPages; - tmp*= 32768; + Uint64 tmp = 0; + tmp += fragptr.p->noOfPages; + { + /** + * Each fragment is split into 2...get #pages from other as well + */ + Uint32 twin = fragptr.p->fragmentId ^ 1; + FragrecordPtr twinPtr; + getFragmentrec(twinPtr, twin, tabptr.p); + ndbrequire(twinPtr.p != 0); + tmp += twinPtr.p->noOfPages; + } + tmp *= 32768; memcpy(outBuffer,&tmp,8); } return 2; diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index a943ea3c3c9..f4b0a7774d8 100644 --- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -1975,6 +1975,11 @@ Ndbcntr::execRESUME_REQ(Signal* signal){ //ResumeRef * const ref = (ResumeRef *)&signal->theData[0]; jamEntry(); + + signal->theData[0] = NDB_LE_SingleUser; + signal->theData[1] = 2; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); + //Uint32 senderData = req->senderData; //BlockReference senderRef = req->senderRef; NodeState newState(NodeState::SL_STARTED); @@ -2013,12 +2018,11 @@ Ndbcntr::execSTOP_REQ(Signal* signal){ return; } - if(c_stopRec.stopReq.senderRef != 0 && !singleuser){ - jam(); + if(c_stopRec.stopReq.senderRef != 0){ /** * Requested a system shutdown */ - if(StopReq::getSystemStop(req->requestInfo)){ + if(!singleuser && StopReq::getSystemStop(req->requestInfo)){ jam(); sendSignalWithDelay(reference(), GSN_STOP_REQ, signal, 100, StopReq::SignalLength); @@ -2040,23 +2044,28 @@ Ndbcntr::execSTOP_REQ(Signal* signal){ c_stopRec.stopReq = * req; c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); - if(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo) && !singleuser) { - jam(); - if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){ - ((Configuration&)theConfiguration).stopOnError(false); - } - } if(!singleuser) { + if(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)) { + jam(); + if(StopReq::getPerformRestart(c_stopRec.stopReq.requestInfo)){ + ((Configuration&)theConfiguration).stopOnError(false); + } + } if(!c_stopRec.checkNodeFail(signal)){ jam(); return; } + signal->theData[0] = NDB_LE_NDBStopStarted; + signal->theData[1] = StopReq::getSystemStop(c_stopRec.stopReq.requestInfo) ? 1 : 0; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); } - - signal->theData[0] = NDB_LE_NDBStopStarted; - signal->theData[1] = StopReq::getSystemStop(c_stopRec.stopReq.requestInfo) ? 1 : 0; - sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); - + else + { + signal->theData[0] = NDB_LE_SingleUser; + signal->theData[1] = 0; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); + } + NodeState newState(NodeState::SL_STOPPING_1, StopReq::getSystemStop(c_stopRec.stopReq.requestInfo)); @@ -2138,9 +2147,11 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){ stopReq.senderRef = 0; - NodeState newState(NodeState::SL_STARTED); - - cntr.updateNodeState(signal, newState); + if (cntr.getNodeState().startLevel != NodeState::SL_SINGLEUSER) + { + NodeState newState(NodeState::SL_STARTED); + cntr.updateNodeState(signal, newState); + } signal->theData[0] = NDB_LE_NDBStopAborted; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB); @@ -2236,12 +2247,24 @@ void Ndbcntr::execABORT_ALL_CONF(Signal* signal){ jamEntry(); if(c_stopRec.stopReq.singleuser) { jam(); + NodeState newState(NodeState::SL_SINGLEUSER); newState.setSingleUser(true); newState.setSingleUserApi(c_stopRec.stopReq.singleUserApi); updateNodeState(signal, newState); c_stopRec.stopInitiatedTime = NdbTick_CurrentMillisecond(); + StopConf * const stopConf = (StopConf *)&signal->theData[0]; + stopConf->senderData = c_stopRec.stopReq.senderData; + stopConf->nodeState = (Uint32) NodeState::SL_SINGLEUSER; + sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_CONF, signal, StopConf::SignalLength, JBB); + + c_stopRec.stopReq.senderRef = 0; // the command is done + + signal->theData[0] = NDB_LE_SingleUser; + signal->theData[1] = 1; + signal->theData[2] = c_stopRec.stopReq.singleUserApi; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); } else { @@ -2259,7 +2282,13 @@ void Ndbcntr::execABORT_ALL_CONF(Signal* signal){ void Ndbcntr::execABORT_ALL_REF(Signal* signal){ jamEntry(); - ndbrequire(false); + AbortAllRef *abortAllRef = (AbortAllRef *)&signal->theData[0]; + AbortAllRef::ErrorCode errorCode = (AbortAllRef::ErrorCode) abortAllRef->errorCode; + + StopRef * const stopRef = (StopRef *)&signal->theData[0]; + stopRef->senderData = c_stopRec.stopReq.senderData; + stopRef->errorCode = StopRef::TransactionAbortFailed; + sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB); } void diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index 75cb92b98c1..4d7ed288592 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -2016,6 +2016,8 @@ Qmgr::execAPI_VERSION_REQ(Signal * signal) { else conf->version = 0; conf->nodeId = nodeId; + struct in_addr in= globalTransporterRegistry.get_connect_address(nodeId); + conf->inet_addr= in.s_addr; sendSignal(senderRef, GSN_API_VERSION_CONF, diff --git a/storage/ndb/src/mgmapi/ndb_logevent.cpp b/storage/ndb/src/mgmapi/ndb_logevent.cpp index a5ffb302c22..5fb83e58c6c 100644 --- a/storage/ndb/src/mgmapi/ndb_logevent.cpp +++ b/storage/ndb/src/mgmapi/ndb_logevent.cpp @@ -297,6 +297,8 @@ struct Ndb_logevent_body_row ndb_logevent_body[]= { ROW( BackupAborted, "backup_id", 2, backup_id), ROW( BackupAborted, "error", 3, error), + ROW( SingleUser, "type", 1, type), + ROW( SingleUser, "node_id", 2, node_id), { NDB_LE_ILLEGAL_TYPE, 0, 0, 0, 0, 0} }; diff --git a/storage/ndb/src/mgmclient/CommandInterpreter.cpp b/storage/ndb/src/mgmclient/CommandInterpreter.cpp index 0a9b4e4a956..1e32ba65c6b 100644 --- a/storage/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/storage/ndb/src/mgmclient/CommandInterpreter.cpp @@ -1369,9 +1369,8 @@ CommandInterpreter::executeEnterSingleUser(char* parameters) ndbout_c("Entering single user mode for node %d failed", nodeId); printError(); } else { - ndbout_c("Entering single user mode"); - ndbout_c("Access will be granted for API node %d only.", nodeId); - ndbout_c("Use ALL STATUS to see when single user mode has been entered."); + ndbout_c("Single user mode entered"); + ndbout_c("Access is granted for API node %d only.", nodeId); } } @@ -1384,7 +1383,7 @@ CommandInterpreter::executeExitSingleUser(char* parameters) printError(); } else { ndbout_c("Exiting single user mode in progress."); - ndbout_c("Use ALL STATUS to see when single user mode has been exited."); + ndbout_c("Use ALL STATUS or SHOW to see when single user mode has been exited."); } } diff --git a/storage/ndb/src/mgmsrv/Config.cpp b/storage/ndb/src/mgmsrv/Config.cpp index 5ff9cbe04ad..6ff5fb789f0 100644 --- a/storage/ndb/src/mgmsrv/Config.cpp +++ b/storage/ndb/src/mgmsrv/Config.cpp @@ -179,90 +179,3 @@ void Config::printConfigFile(NdbOut &out) const { } #endif } - -Uint32 -Config::getGenerationNumber() const { -#if 0 - Uint32 ret; - const Properties *prop = NULL; - - get("SYSTEM", &prop); - - if(prop != NULL) - if(prop->get("ConfigGenerationNumber", &ret)) - return ret; - - return 0; -#else - return 0; -#endif -} - -int -Config::setGenerationNumber(Uint32 gen) { -#if 0 - Properties *prop = NULL; - - getCopy("SYSTEM", &prop); - - if(prop != NULL) { - MGM_REQUIRE(prop->put("ConfigGenerationNumber", gen, true)); - MGM_REQUIRE(put("SYSTEM", prop, true)); - return 0; - } - return -1; -#else - return -1; -#endif -} - -bool -Config::change(const BaseString §ion, - const BaseString ¶m, - const BaseString &value) { -#if 0 - const char *name; - Properties::Iterator it(this); - - for(name = it.first(); name != NULL; name = it.next()) { - Properties *prop = NULL; - if(strcasecmp(section.c_str(), name) == 0) { - getCopy(name, &prop); - if(prop == NULL) /* doesn't exist */ - return false; - if(value == "") { - prop->remove(param.c_str()); - put(section.c_str(), prop, true); - } else { - PropertiesType t; - if(!prop->getTypeOf(param.c_str(), &t)) /* doesn't exist */ - return false; - switch(t) { - case PropertiesType_Uint32: - long val; - char *ep; - errno = 0; - val = strtol(value.c_str(), &ep, 0); - if(value.length() == 0 || *ep != '\0') /* not a number */ - return false; - if(errno == ERANGE) - return false; - prop->put(param.c_str(), (unsigned int)val, true); - put(section.c_str(), prop, true); - break; - case PropertiesType_char: - prop->put(param.c_str(), value.c_str(), true); - put(section.c_str(), prop, true); - break; - default: - return false; - } - } - break; - } - } - return true; -#else - return false; -#endif -} diff --git a/storage/ndb/src/mgmsrv/Config.hpp b/storage/ndb/src/mgmsrv/Config.hpp index b5e1e17b027..8e16ddf1810 100644 --- a/storage/ndb/src/mgmsrv/Config.hpp +++ b/storage/ndb/src/mgmsrv/Config.hpp @@ -60,16 +60,6 @@ public: printConfigFile(ndb); } - Uint32 getGenerationNumber() const; - int setGenerationNumber(Uint32); - - /** Change configuration - */ - bool change(const BaseString §ion, - const BaseString ¶m, - const BaseString &value); - - /** * Info */ diff --git a/storage/ndb/src/mgmsrv/ConfigInfo.cpp b/storage/ndb/src/mgmsrv/ConfigInfo.cpp index 4e96047e54d..a870c395bd2 100644 --- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp @@ -241,6 +241,9 @@ struct DepricationTransform { static const DepricationTransform f_deprication[] = { { DB_TOKEN, "Discless", "Diskless", 0, 1 }, + { DB_TOKEN, "Id", "nodeid", 0, 1 }, + { API_TOKEN, "Id", "nodeid", 0, 1 }, + { MGM_TOKEN, "Id", "nodeid", 0, 1 }, { 0, 0, 0, 0, 0} }; @@ -405,9 +408,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { 0, 0 }, { - CFG_NODE_ID, + KEY_INTERNAL, "Id", DB_TOKEN, + "", + ConfigInfo::CI_DEPRICATED, + false, + ConfigInfo::CI_INT, + MANDATORY, + "1", + STR_VALUE(MAX_NODES) }, + + { + CFG_NODE_ID, + "nodeid", + DB_TOKEN, "Number identifying the database node ("DB_TOKEN_PRINT")", ConfigInfo::CI_USED, false, @@ -1244,9 +1259,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { 0, 0 }, { - CFG_NODE_ID, + KEY_INTERNAL, "Id", API_TOKEN, + "", + ConfigInfo::CI_DEPRICATED, + false, + ConfigInfo::CI_INT, + MANDATORY, + "1", + STR_VALUE(MAX_NODES) }, + + { + CFG_NODE_ID, + "nodeid", + API_TOKEN, "Number identifying application node ("API_TOKEN_PRINT")", ConfigInfo::CI_USED, false, @@ -1375,9 +1402,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { 0, 0 }, { - CFG_NODE_ID, + KEY_INTERNAL, "Id", MGM_TOKEN, + "", + ConfigInfo::CI_DEPRICATED, + false, + ConfigInfo::CI_INT, + MANDATORY, + "1", + STR_VALUE(MAX_NODES) }, + + { + CFG_NODE_ID, + "nodeid", + MGM_TOKEN, "Number identifying the management server node ("MGM_TOKEN_PRINT")", ConfigInfo::CI_USED, false, @@ -2516,14 +2555,14 @@ bool transformNode(InitConfigFileParser::Context & ctx, const char * data){ Uint32 id; - if(!ctx.m_currentSection->get("Id", &id)){ + if(!ctx.m_currentSection->get("nodeid", &id) && !ctx.m_currentSection->get("Id", &id)){ Uint32 nextNodeId= 1; ctx.m_userProperties.get("NextNodeId", &nextNodeId); id= nextNodeId; while (ctx.m_userProperties.get("AllocatedNodeId_", id, &id)) id++; ctx.m_userProperties.put("NextNodeId", id+1, true); - ctx.m_currentSection->put("Id", id); + ctx.m_currentSection->put("nodeid", id); #if 0 ctx.reportError("Mandatory parameter Id missing from section " "[%s] starting at line: %d", @@ -2531,7 +2570,7 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){ return false; #endif } else if(ctx.m_userProperties.get("AllocatedNodeId_", id, &id)) { - ctx.reportError("Duplicate Id in section " + ctx.reportError("Duplicate nodeid in section " "[%s] starting at line: %d", ctx.fname, ctx.m_sectionLineno); return false; @@ -3356,6 +3395,7 @@ transform(InitConfigFileParser::Context & ctx, PropertiesType oldType; require(ctx.m_currentSection->getTypeOf(oldName, &oldType)); ConfigInfo::Type newType = ctx.m_info->getType(ctx.m_currentInfo, newName); + if(!((oldType == PropertiesType_Uint32 || oldType == PropertiesType_Uint64) && (newType == ConfigInfo::CI_INT || newType == ConfigInfo::CI_INT64 || newType == ConfigInfo::CI_BOOL))){ ndbout << "oldType: " << (int)oldType << ", newType: " << (int)newType << endl; diff --git a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp index 822e10c89aa..94f07ab0ca1 100644 --- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp +++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp @@ -31,8 +31,10 @@ static void require(bool v) { if(!v) abort();} //**************************************************************************** // Ctor / Dtor //**************************************************************************** -InitConfigFileParser::InitConfigFileParser(){ +InitConfigFileParser::InitConfigFileParser(FILE * out) +{ m_info = new ConfigInfo(); + m_errstream = out ? out : stdout; } InitConfigFileParser::~InitConfigFileParser() { @@ -42,11 +44,12 @@ InitConfigFileParser::~InitConfigFileParser() { //**************************************************************************** // Read Config File //**************************************************************************** -InitConfigFileParser::Context::Context(const ConfigInfo * info) +InitConfigFileParser::Context::Context(const ConfigInfo * info, FILE * out) : m_userProperties(true), m_configValues(1000, 20) { m_config = new Properties(true); m_defaults = new Properties(true); + m_errstream = out; } InitConfigFileParser::Context::~Context(){ @@ -61,10 +64,10 @@ Config * InitConfigFileParser::parseConfig(const char * filename) { FILE * file = fopen(filename, "r"); if(file == 0){ - ndbout << "Error opening file: " << filename << endl; + fprintf(m_errstream, "Error opening file: %s\n", filename); return 0; } - + Config * ret = parseConfig(file); fclose(file); return ret; @@ -75,7 +78,7 @@ InitConfigFileParser::parseConfig(FILE * file) { char line[MAX_LINE_LENGTH]; - Context ctx(m_info); + Context ctx(m_info, m_errstream); ctx.m_lineno = 0; ctx.m_currentSection = 0; @@ -160,6 +163,13 @@ InitConfigFileParser::parseConfig(FILE * file) { ctx.reportError("Could not store section of configuration file."); return 0; } + + return run_config_rules(ctx); +} + +Config* +InitConfigFileParser::run_config_rules(Context& ctx) +{ for(size_t i = 0; ConfigInfo::m_ConfigRules[i].m_configRule != 0; i++){ ctx.type = InitConfigFileParser::Undefined; ctx.m_currentSection = 0; @@ -267,10 +277,10 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) } if (status == ConfigInfo::CI_DEPRICATED) { const char * desc = m_info->getDescription(ctx.m_currentInfo, fname); - if(desc){ + if(desc && desc[0]){ ctx.reportWarning("[%s] %s is depricated, use %s instead", ctx.fname, fname, desc); - } else { + } else if (desc == 0){ ctx.reportWarning("[%s] %s is depricated", ctx.fname, fname); } } @@ -571,8 +581,9 @@ InitConfigFileParser::Context::reportError(const char * fmt, ...){ va_start(ap, fmt); if (fmt != 0) BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap); - ndbout << "Error line " << m_lineno << ": " << buf << endl; va_end(ap); + fprintf(m_errstream, "Error line %d: %s\n", + m_lineno, buf); //m_currentSection->print(); } @@ -585,6 +596,354 @@ InitConfigFileParser::Context::reportWarning(const char * fmt, ...){ va_start(ap, fmt); if (fmt != 0) BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap); - ndbout << "Warning line " << m_lineno << ": " << buf << endl; va_end(ap); + fprintf(m_errstream, "Warning line %d: %s\n", + m_lineno, buf); +} + +#include <my_sys.h> +#include <my_getopt.h> + +static int order = 1; +static +my_bool +parse_mycnf_opt(int, const struct my_option * opt, char * value) +{ + if(opt->comment) + ((struct my_option *)opt)->app_type++; + else + ((struct my_option *)opt)->app_type = order++; + return 0; +} + +bool +InitConfigFileParser::store_in_properties(Vector<struct my_option>& options, + InitConfigFileParser::Context& ctx, + const char * name) +{ + for(unsigned i = 0; i<options.size(); i++) + { + if(options[i].comment && + options[i].app_type && + strcmp(options[i].comment, name) == 0) + { + Uint64 value_int; + switch(options[i].var_type){ + case GET_INT: + value_int = *(Uint32*)options[i].value; + break; + case GET_LL: + value_int = *(Uint64*)options[i].value; + break; + case GET_STR: + ctx.m_currentSection->put(options[i].name, (char*)options[i].value); + continue; + default: + abort(); + } + + const char * fname = options[i].name; + if (!m_info->verify(ctx.m_currentInfo, fname, value_int)) { + ctx.reportError("Illegal value %lld for parameter %s.\n" + "Legal values are between %Lu and %Lu", + value_int, fname, + m_info->getMin(ctx.m_currentInfo, fname), + m_info->getMax(ctx.m_currentInfo, fname)); + return false; + } + if (options[i].var_type == GET_INT) + ctx.m_currentSection->put(options[i].name, (Uint32)value_int); + else + ctx.m_currentSection->put(options[i].name, value_int); + } + } + return true; } + +bool +InitConfigFileParser::handle_mycnf_defaults(Vector<struct my_option>& options, + InitConfigFileParser::Context& ctx, + const char * name) +{ + strcpy(ctx.fname, name); + ctx.type = InitConfigFileParser::DefaultSection; + ctx.m_currentSection = new Properties(true); + ctx.m_userDefaults = NULL; + require((ctx.m_currentInfo = m_info->getInfo(ctx.fname)) != 0); + require((ctx.m_systemDefaults = m_info->getDefaults(ctx.fname)) != 0); + if(store_in_properties(options, ctx, name)) + return storeSection(ctx); + return false; +} + +static +int +load_defaults(Vector<struct my_option>& options, const char* groups[]) +{ + int argc = 1; + const char * argv[] = { "ndb_mgmd", 0, 0, 0, 0 }; + BaseString file; + BaseString extra_file; + BaseString group_suffix; + + const char *save_file = defaults_file; + char *save_extra_file = defaults_extra_file; + const char *save_group_suffix = defaults_group_suffix; + + if (defaults_file) + { + file.assfmt("--defaults-file=%s", defaults_file); + argv[argc++] = file.c_str(); + } + + if (defaults_extra_file) + { + extra_file.assfmt("--defaults-extra-file=%s", defaults_extra_file); + argv[argc++] = extra_file.c_str(); + } + + if (defaults_group_suffix) + { + group_suffix.assfmt("--defaults-group-suffix=%s", defaults_group_suffix); + argv[argc++] = group_suffix.c_str(); + } + + char ** tmp = (char**)argv; + int ret = load_defaults("my", groups, &argc, &tmp); + + defaults_file = save_file; + defaults_extra_file = save_extra_file; + defaults_group_suffix = save_group_suffix; + + if (ret == 0) + { + return handle_options(&argc, &tmp, options.getBase(), parse_mycnf_opt); + } + + return ret; +} + +bool +InitConfigFileParser::load_mycnf_groups(Vector<struct my_option> & options, + InitConfigFileParser::Context& ctx, + const char * name, + const char *groups[]) +{ + unsigned i; + Vector<struct my_option> copy; + for(i = 0; i<options.size(); i++) + { + if(options[i].comment && strcmp(options[i].comment, name) == 0) + { + options[i].app_type = 0; + copy.push_back(options[i]); + } + } + + struct my_option end; + bzero(&end, sizeof(end)); + copy.push_back(end); + + if (load_defaults(copy, groups)) + return false; + + return store_in_properties(copy, ctx, name); +} + +Config * +InitConfigFileParser::parse_mycnf() +{ + int i; + Config * res = 0; + Vector<struct my_option> options; + for(i = 0; i<ConfigInfo::m_NoOfParams; i++) + { + if (strcmp(ConfigInfo::m_ParamInfo[i]._section, "DB") == 0 || + strcmp(ConfigInfo::m_ParamInfo[i]._section, "API") == 0 || + strcmp(ConfigInfo::m_ParamInfo[i]._section, "MGM") == 0) + { + struct my_option opt; + bzero(&opt, sizeof(opt)); + const ConfigInfo::ParamInfo& param = ConfigInfo::m_ParamInfo[i]; + switch(param._type){ + case ConfigInfo::CI_BOOL: + opt.value = (gptr*)malloc(sizeof(int)); + opt.var_type = GET_INT; + break; + case ConfigInfo::CI_INT: + opt.value = (gptr*)malloc(sizeof(int)); + opt.var_type = GET_INT; + break; + case ConfigInfo::CI_INT64: + opt.value = (gptr*)malloc(sizeof(Int64)); + opt.var_type = GET_LL; + break; + case ConfigInfo::CI_STRING: + opt.value = (gptr*)malloc(sizeof(char *)); + opt.var_type = GET_STR; + break; + default: + continue; + } + opt.name = param._fname; + opt.id = 256; + opt.app_type = 0; + opt.arg_type = REQUIRED_ARG; + opt.comment = param._section; + options.push_back(opt); + } + } + + struct my_option *ndbd, *ndb_mgmd, *mysqld, *api; + + /** + * Add ndbd, ndb_mgmd, api/mysqld + */ + { + struct my_option opt; + bzero(&opt, sizeof(opt)); + opt.name = "ndbd"; + opt.id = 256; + opt.value = (gptr*)malloc(sizeof(char*)); + opt.var_type = GET_STR; + opt.arg_type = REQUIRED_ARG; + options.push_back(opt); + ndbd = &options.back(); + + opt.name = "ndb_mgmd"; + opt.id = 256; + opt.value = (gptr*)malloc(sizeof(char*)); + opt.var_type = GET_STR; + opt.arg_type = REQUIRED_ARG; + options.push_back(opt); + ndb_mgmd = &options.back(); + + opt.name = "mysqld"; + opt.id = 256; + opt.value = (gptr*)malloc(sizeof(char*)); + opt.var_type = GET_STR; + opt.arg_type = REQUIRED_ARG; + options.push_back(opt); + mysqld = &options.back(); + + opt.name = "api"; + opt.id = 256; + opt.value = (gptr*)malloc(sizeof(char*)); + opt.var_type = GET_STR; + opt.arg_type = REQUIRED_ARG; + options.push_back(opt); + api = &options.back(); + + bzero(&opt, sizeof(opt)); + options.push_back(opt); + } + + + Context ctx(m_info, m_errstream); + const char *groups[]= { "cluster_config", 0 }; + if (load_defaults(options, groups)) + goto end; + + ctx.m_lineno = 0; + if(!handle_mycnf_defaults(options, ctx, "DB")) + goto end; + if(!handle_mycnf_defaults(options, ctx, "API")) + goto end; + if(!handle_mycnf_defaults(options, ctx, "MGM")) + goto end; + + { + struct sect { struct my_option* src; const char * name; } sections[] = + { + { ndb_mgmd, "MGM" } + ,{ ndbd, "DB" } + ,{ mysqld, "API" } + ,{ api, "API" } + ,{ 0, 0 }, { 0, 0 } + }; + + for(i = 0; sections[i].src; i++) + { + for(int j = i + 1; sections[j].src; j++) + { + if (sections[j].src->app_type < sections[i].src->app_type) + { + sect swap = sections[i]; + sections[i] = sections[j]; + sections[j] = swap; + } + } + } + + ctx.type = InitConfigFileParser::Section; + ctx.m_sectionLineno = ctx.m_lineno; + for(i = 0; sections[i].src; i++) + { + if (sections[i].src->app_type) + { + strcpy(ctx.fname, sections[i].name); + BaseString str(*(char**)sections[i].src->value); + Vector<BaseString> list; + str.split(list, ","); + + const char * defaults_groups[] = { 0, 0, 0 }; + for(unsigned j = 0; j<list.size(); j++) + { + BaseString group_idx; + BaseString group_host; + group_idx.assfmt("%s.%s.%d", groups[0], + sections[i].src->name, j + 1); + group_host.assfmt("%s.%s.%s", groups[0], + sections[i].src->name, list[j].c_str()); + defaults_groups[0] = group_idx.c_str(); + if(list[j].length()) + defaults_groups[1] = group_host.c_str(); + else + defaults_groups[1] = 0; + + ctx.m_currentSection = new Properties(true); + ctx.m_userDefaults = getSection(ctx.fname, ctx.m_defaults); + require((ctx.m_currentInfo = m_info->getInfo(ctx.fname)) != 0); + require((ctx.m_systemDefaults = m_info->getDefaults(ctx.fname))!= 0); + ctx.m_currentSection->put("HostName", list[j].c_str()); + if(!load_mycnf_groups(options, ctx, sections[i].name, + defaults_groups)) + goto end; + + if(!storeSection(ctx)) + goto end; + } + } + } + } + + res = run_config_rules(ctx); + +end: + for(i = 0; options[i].name; i++) + free(options[i].value); + + return res; +} + +template class Vector<struct my_option>; + +#if 0 +struct my_option +{ + const char *name; /* Name of the option */ + int id; /* unique id or short option */ + const char *comment; /* option comment, for autom. --help */ + gptr *value; /* The variable value */ + gptr *u_max_value; /* The user def. max variable value */ + const char **str_values; /* Pointer to possible values */ + ulong var_type; + enum get_opt_arg_type arg_type; + longlong def_value; /* Default value */ + longlong min_value; /* Min allowed value */ + longlong max_value; /* Max allowed value */ + longlong sub_size; /* Subtract this from given value */ + long block_size; /* Value should be a mult. of this */ + int app_type; /* To be used by an application */ +}; +#endif diff --git a/storage/ndb/src/mgmsrv/InitConfigFileParser.hpp b/storage/ndb/src/mgmsrv/InitConfigFileParser.hpp index 1ea0a094ccd..616fd5a62fb 100644 --- a/storage/ndb/src/mgmsrv/InitConfigFileParser.hpp +++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.hpp @@ -34,11 +34,12 @@ class ConfigInfo; * object if the config file has correct syntax and semantic. */ class InitConfigFileParser { + FILE * m_errstream; public: /** * Constructor */ - InitConfigFileParser(); + InitConfigFileParser(FILE * errstream = stdout); ~InitConfigFileParser(); /** @@ -50,6 +51,7 @@ public: */ Config * parseConfig(FILE * file); Config * parseConfig(const char * filename); + Config * parse_mycnf(); /** * Parser context struct @@ -60,7 +62,7 @@ public: * Context = Which section in init config file we are currently parsing */ struct Context { - Context(const ConfigInfo *); + Context(const ConfigInfo *, FILE * out); ~Context(); ContextSectionType type; ///< Section type (e.g. default section,section) @@ -82,6 +84,7 @@ public: ConfigValuesFactory m_configValues; // public: + FILE * m_errstream; void reportError(const char * msg, ...); void reportWarning(const char * msg, ...); }; @@ -122,6 +125,21 @@ private: * Information about parameters (min, max values etc) */ ConfigInfo* m_info; + + bool handle_mycnf_defaults(Vector<struct my_option>& options, + InitConfigFileParser::Context& ctx, + const char * name); + + bool load_mycnf_groups(Vector<struct my_option> & options, + InitConfigFileParser::Context& ctx, + const char * name, + const char *groups[]); + + bool store_in_properties(Vector<struct my_option>& options, + InitConfigFileParser::Context& ctx, + const char * name); + + Config* run_config_rules(Context& ctx); }; #endif // InitConfigFileParser_H diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp index 82e1d24d045..fedaea6a06c 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -66,6 +66,16 @@ #define DEBUG(x) #endif +#define INIT_SIGNAL_SENDER(ss,nodeId) \ + SignalSender ss(theFacade); \ + ss.lock(); /* lock will be released on exit */ \ + {\ + int result = okToSendTo(nodeId, true);\ + if (result != 0) {\ + return result;\ + }\ + } + extern int global_flag_send_heartbeat_now; extern int g_no_nodeid_checks; extern my_bool opt_core; @@ -89,55 +99,6 @@ MgmtSrvr::logLevelThread_C(void* m) return 0; } -void * -MgmtSrvr::signalRecvThread_C(void *m) -{ - MgmtSrvr *mgm = (MgmtSrvr*)m; - mgm->signalRecvThreadRun(); - return 0; -} - -class SigMatch -{ -public: - int gsn; - void (MgmtSrvr::* function)(NdbApiSignal *signal); - - SigMatch() { gsn = 0; function = NULL; }; - - SigMatch(int _gsn, - void (MgmtSrvr::* _function)(NdbApiSignal *signal)) { - gsn = _gsn; - function = _function; - }; - - bool check(NdbApiSignal *signal) { - if(signal->readSignalNumber() == gsn) - return true; - return false; - }; - -}; - -void -MgmtSrvr::signalRecvThreadRun() -{ - Vector<SigMatch> siglist; - siglist.push_back(SigMatch(GSN_MGM_LOCK_CONFIG_REQ, - &MgmtSrvr::handle_MGM_LOCK_CONFIG_REQ)); - siglist.push_back(SigMatch(GSN_MGM_UNLOCK_CONFIG_REQ, - &MgmtSrvr::handle_MGM_UNLOCK_CONFIG_REQ)); - - while(!_isStopThread) { - SigMatch *handler = NULL; - NdbApiSignal *signal = NULL; - if(m_signalRecvQueue.waitFor(siglist, &handler, &signal, DEFAULT_TIMEOUT)) { - if(handler->function != 0) - (this->*handler->function)(signal); - } - } -} - extern EventLogger g_eventLogger; static NdbOut& @@ -425,15 +386,12 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server, _isStopThread = false; _logLevelThread = NULL; _logLevelThreadSleep = 500; - m_signalRecvThread = NULL; theFacade = 0; m_newConfig = NULL; if (config_filename) m_configFilename.assign(config_filename); - else - m_configFilename.assign("config.ini"); m_nextConfigGenerationNumber = 0; @@ -468,7 +426,7 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server, _config= readConfig(); if (_config == 0) { ndbout << "Unable to read config file" << endl; - require(false); + exit(-1); } } @@ -649,12 +607,6 @@ MgmtSrvr::start(BaseString &error_string) "MgmtSrvr_Loglevel", NDB_THREAD_PRIO_LOW); - m_signalRecvThread = NdbThread_Create(signalRecvThread_C, - (void **)this, - 32768, - "MgmtSrvr_Service", - NDB_THREAD_PRIO_LOW); - DBUG_RETURN(true); } @@ -663,10 +615,6 @@ MgmtSrvr::start(BaseString &error_string) //**************************************************************************** MgmtSrvr::~MgmtSrvr() { - while (theSignalIdleList != NULL) { - freeSignal(); - } - if(theFacade != 0){ theFacade->stop_instance(); delete theFacade; @@ -694,10 +642,6 @@ MgmtSrvr::~MgmtSrvr() NdbThread_Destroy(&_logLevelThread); } - if (m_signalRecvThread != NULL) { - NdbThread_WaitFor(m_signalRecvThread, &res); - NdbThread_Destroy(&m_signalRecvThread); - } if (m_config_retriever) delete m_config_retriever; } @@ -705,21 +649,21 @@ MgmtSrvr::~MgmtSrvr() //**************************************************************************** //**************************************************************************** -int MgmtSrvr::okToSendTo(NodeId processId, bool unCond) +int MgmtSrvr::okToSendTo(NodeId nodeId, bool unCond) { - if(processId == 0) + if(nodeId == 0) return 0; - if (getNodeType(processId) != NDB_MGM_NODE_TYPE_NDB) + if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_NDB) return WRONG_PROCESS_TYPE; // Check if we have contact with it if(unCond){ - if(theFacade->theClusterMgr->getNodeInfo(processId).connected) + if(theFacade->theClusterMgr->getNodeInfo(nodeId).connected) return 0; return NO_CONTACT_WITH_PROCESS; } - if (theFacade->get_node_alive(processId) == 0) { + if (theFacade->get_node_alive(nodeId) == 0) { return NO_CONTACT_WITH_PROCESS; } else { return 0; @@ -740,241 +684,454 @@ void report_unknown_signal(SimpleSignal *signal) ****************************************************************************/ int -MgmtSrvr::start(int processId) +MgmtSrvr::start(int nodeId) { - int result; - - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - StartOrd* const startOrd = CAST_PTR(StartOrd, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, CMVMI, GSN_START_ORD, StartOrd::SignalLength); + INIT_SIGNAL_SENDER(ss,nodeId); + SimpleSignal ssig; + StartOrd* const startOrd = CAST_PTR(StartOrd, ssig.getDataPtrSend()); + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_START_ORD, StartOrd::SignalLength); startOrd->restartInfo = 0; - result = sendSignal(processId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; +} + +/***************************************************************************** + * Version handling + *****************************************************************************/ + +int +MgmtSrvr::versionNode(int nodeId, Uint32 &version, const char **address) +{ + version= 0; + if (getOwnNodeId() == nodeId) + { + /** + * If we're inquiring about our own node id, + * We know what version we are (version implies connected for mgm) + * but would like to find out from elsewhere what address they're using + * to connect to us. This means that secondary mgm servers + * can list ip addresses for mgm servers. + * + * If we don't get an address (i.e. no db nodes), + * we get the address from the configuration. + */ + sendVersionReq(nodeId, version, address); + version= NDB_VERSION; + if(!*address) + { + ndb_mgm_configuration_iterator + iter(*_config->m_configValues, CFG_SECTION_NODE); + unsigned tmp= 0; + for(iter.first();iter.valid();iter.next()) + { + if(iter.get(CFG_NODE_ID, &tmp)) require(false); + if((unsigned)nodeId!=tmp) + continue; + if(iter.get(CFG_NODE_HOST, address)) require(false); + break; + } + } } - + else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB) + { + ClusterMgr::Node node= theFacade->theClusterMgr->getNodeInfo(nodeId); + if(node.connected) + version= node.m_info.m_version; + *address= get_connect_address(nodeId); + } + else if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API || + getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM) + { + return sendVersionReq(nodeId, version, address); + } + + return 0; +} + +int +MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address) +{ + SignalSender ss(theFacade); + ss.lock(); + + SimpleSignal ssig; + ApiVersionReq* req = CAST_PTR(ApiVersionReq, ssig.getDataPtrSend()); + req->senderRef = ss.getOwnRef(); + req->nodeId = v_nodeId; + ssig.set(ss, TestOrd::TraceAPI, QMGR, GSN_API_VERSION_REQ, + ApiVersionReq::SignalLength); + + int do_send = 1; + NodeId nodeId; + + while (1) + { + if (do_send) + { + bool next; + nodeId = 0; + + while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true && + okToSendTo(nodeId, true) != 0); + + const ClusterMgr::Node &node= + theFacade->theClusterMgr->getNodeInfo(nodeId); + if(next && node.m_state.startLevel != NodeState::SL_STARTED) + { + NodeId tmp=nodeId; + while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true && + okToSendTo(nodeId, true) != 0); + if(!next) + nodeId= tmp; + } + + if(!next) return NO_CONTACT_WITH_DB_NODES; + + if (ss.sendSignal(nodeId, &ssig) != SEND_OK) { + return SEND_OR_RECEIVE_FAILED; + } + do_send = 0; + } + + SimpleSignal *signal = ss.waitFor(); + + int gsn = signal->readSignalNumber(); + switch (gsn) { + case GSN_API_VERSION_CONF: { + const ApiVersionConf * const conf = + CAST_CONSTPTR(ApiVersionConf, signal->getDataPtr()); + assert(conf->nodeId == v_nodeId); + version = conf->version; + struct in_addr in; + in.s_addr= conf->inet_addr; + *address= inet_ntoa(in); + return 0; + } + case GSN_NF_COMPLETEREP:{ + const NFCompleteRep * const rep = + CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr()); + if (rep->failedNodeId == nodeId) + do_send = 1; // retry with other node + continue; + } + case GSN_NODE_FAILREP:{ + const NodeFailRep * const rep = + CAST_CONSTPTR(NodeFailRep, signal->getDataPtr()); + if (NodeBitmask::get(rep->theNodes,nodeId)) + do_send = 1; // retry with other node + continue; + } + default: + report_unknown_signal(signal); + return SEND_OR_RECEIVE_FAILED; + } + break; + } // while(1) + return 0; } -/** - * Restart one database node +/* + * Common method for handeling all STOP_REQ signalling that + * is used by Stopping, Restarting and Single user commands */ -int -MgmtSrvr::restartNode(int processId, bool nostart, - bool initalStart, bool abort, - StopCallback callback, void * anyData) + +int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, + NodeBitmask &stoppedNodes, + Uint32 singleUserNodeId, + bool abort, + bool stop, + bool restart, + bool nostart, + bool initialStart) { - int result; + stoppedNodes.clear(); - if(m_stopRec.singleUserMode) - return 5060; + SignalSender ss(theFacade); + ss.lock(); // lock will be released on exit - if(m_stopRec.inUse){ - return 5029; - } - - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } + SimpleSignal ssig; + StopReq* const stopReq = CAST_PTR(StopReq, ssig.getDataPtrSend()); + ssig.set(ss, TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength); - StopReq* const stopReq = CAST_PTR(StopReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength); - stopReq->requestInfo = 0; - StopReq::setSystemStop(stopReq->requestInfo, false); - StopReq::setPerformRestart(stopReq->requestInfo, true); - StopReq::setNoStart(stopReq->requestInfo, nostart); - StopReq::setInitialStart(stopReq->requestInfo, initalStart); - StopReq::setStopAbort(stopReq->requestInfo, abort); - stopReq->singleuser = 0; stopReq->apiTimeout = 5000; stopReq->transactionTimeout = 1000; stopReq->readOperationTimeout = 1000; stopReq->operationTimeout = 1000; stopReq->senderData = 12; - stopReq->senderRef = _ownReference; - - m_stopRec.singleUserMode = false; - m_stopRec.sentCount = 1; - m_stopRec.reply = 0; - m_stopRec.nodeId = processId; - m_stopRec.anyData = anyData; - m_stopRec.callback = callback; - m_stopRec.inUse = true; - - if(callback == NULL){ - Uint32 timeOut = 0; - timeOut += stopReq->apiTimeout; - timeOut += stopReq->transactionTimeout; - timeOut += stopReq->readOperationTimeout; - timeOut += stopReq->operationTimeout; - timeOut *= 3; - result = sendRecSignal(processId, WAIT_STOP, signal, true, timeOut); - } else { - result = sendSignal(processId, NO_WAIT, signal, true); + stopReq->senderRef = ss.getOwnRef(); + if (singleUserNodeId) + { + stopReq->singleuser = 1; + stopReq->singleUserApi = singleUserNodeId; + StopReq::setSystemStop(stopReq->requestInfo, false); + StopReq::setPerformRestart(stopReq->requestInfo, false); + StopReq::setStopAbort(stopReq->requestInfo, false); } - - if (result == -1 && theWaitState != WAIT_NODEFAILURE) { - m_stopRec.inUse = false; - return SEND_OR_RECEIVE_FAILED; + else + { + stopReq->singleuser = 0; + StopReq::setSystemStop(stopReq->requestInfo, stop); + StopReq::setPerformRestart(stopReq->requestInfo, restart); + StopReq::setStopAbort(stopReq->requestInfo, abort); + StopReq::setNoStart(stopReq->requestInfo, nostart); + StopReq::setInitialStart(stopReq->requestInfo, initialStart); } - if(callback == 0){ - m_stopRec.inUse = false; - return m_stopRec.reply; - } else { - return 0; + // send the signals + NodeBitmask nodes; + if (nodeId) + { + { + int r; + if((r = okToSendTo(nodeId, true)) != 0) + return r; + } + { + if (ss.sendSignal(nodeId, &ssig) != SEND_OK) + return SEND_OR_RECEIVE_FAILED; + } + nodes.set(nodeId); } + else + while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) + { + if(okToSendTo(nodeId, true) == 0) + { + SendStatus result = ss.sendSignal(nodeId, &ssig); + if (result == SEND_OK) + nodes.set(nodeId); + } + } + + // now wait for the replies + int error = 0; + while (!nodes.isclear()) + { + SimpleSignal *signal = ss.waitFor(); + int gsn = signal->readSignalNumber(); + switch (gsn) { + case GSN_STOP_REF:{ + const StopRef * const ref = CAST_CONSTPTR(StopRef, signal->getDataPtr()); + const NodeId nodeId = refToNode(signal->header.theSendersBlockRef); +#ifdef VM_TRACE + ndbout_c("Node %d refused stop", nodeId); +#endif + assert(nodes.get(nodeId)); + nodes.clear(nodeId); + error = translateStopRef(ref->errorCode); + break; + } + case GSN_STOP_CONF:{ + const StopConf * const ref = CAST_CONSTPTR(StopConf, signal->getDataPtr()); + const NodeId nodeId = refToNode(signal->header.theSendersBlockRef); +#ifdef VM_TRACE + ndbout_c("Node %d single user mode", nodeId); +#endif + assert(nodes.get(nodeId)); + assert(singleUserNodeId != 0); + nodes.clear(nodeId); + stoppedNodes.set(nodeId); + break; + } + case GSN_NF_COMPLETEREP:{ + const NFCompleteRep * const rep = + CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr()); +#ifdef VM_TRACE + ndbout_c("Node %d fail completed", rep->failedNodeId); +#endif + break; + } + case GSN_NODE_FAILREP:{ + const NodeFailRep * const rep = + CAST_CONSTPTR(NodeFailRep, signal->getDataPtr()); + NodeBitmask failedNodes; + failedNodes.assign(NodeBitmask::Size, rep->theNodes); +#ifdef VM_TRACE + { + ndbout << "Failed nodes:"; + for (unsigned i = 0; i < 32*NodeBitmask::Size; i++) + if(failedNodes.get(i)) + ndbout << " " << i; + ndbout << endl; + } +#endif + failedNodes.bitAND(nodes); + if (!failedNodes.isclear()) + { + nodes.bitANDC(failedNodes); // clear the failed nodes + if (singleUserNodeId == 0) + stoppedNodes.bitOR(failedNodes); + } + break; + } + default: + report_unknown_signal(signal); +#ifdef VM_TRACE + ndbout_c("Unknown signal %d", gsn); +#endif + return SEND_OR_RECEIVE_FAILED; + } + } + return error; } -/** - * Restart all database nodes +/* + * Stop one node */ -int -MgmtSrvr::restart(bool nostart, bool initalStart, bool abort, - int * stopCount, StopCallback callback, void * anyData) + +int MgmtSrvr::stopNode(int nodeId, bool abort) { - if(m_stopRec.singleUserMode) - return 5060; + NodeBitmask nodes; + return sendSTOP_REQ(nodeId, + nodes, + 0, + abort, + false, + false, + false, + false); +} + +/* + * Perform system shutdown + */ - if(m_stopRec.inUse){ - return 5029; - } - - m_stopRec.singleUserMode = false; - m_stopRec.sentCount = 0; - m_stopRec.reply = 0; - m_stopRec.nodeId = 0; - m_stopRec.anyData = anyData; - m_stopRec.callback = callback; - m_stopRec.inUse = true; - - /** - * Restart all database nodes into idle ("no-started") state - */ - Uint32 timeOut = 0; - NodeId nodeId = 0; +int MgmtSrvr::stop(int * stopCount, bool abort) +{ NodeBitmask nodes; - while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){ - if(okToSendTo(nodeId, true) == 0){ + int ret = sendSTOP_REQ(0, + nodes, + 0, + abort, + true, + false, + false, + false); + if (stopCount) + *stopCount = nodes.count(); + return ret; +} + +/* + * Enter single user mode on all live nodes + */ - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - StopReq* const stopReq = CAST_PTR(StopReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, - StopReq::SignalLength); - - stopReq->requestInfo = 0; - stopReq->singleuser = 0; - StopReq::setSystemStop(stopReq->requestInfo, true); - StopReq::setPerformRestart(stopReq->requestInfo, true); - if (callback == 0) { - // Start node in idle ("no-started") state - StopReq::setNoStart(stopReq->requestInfo, 1); - } else { - StopReq::setNoStart(stopReq->requestInfo, nostart); - } - StopReq::setInitialStart(stopReq->requestInfo, initalStart); - StopReq::setStopAbort(stopReq->requestInfo, abort); - - stopReq->apiTimeout = 5000; - stopReq->transactionTimeout = 1000; - stopReq->readOperationTimeout = 1000; - stopReq->operationTimeout = 1000; - stopReq->senderData = 12; - stopReq->senderRef = _ownReference; - - timeOut += stopReq->apiTimeout; - timeOut += stopReq->transactionTimeout; - timeOut += stopReq->readOperationTimeout; - timeOut += stopReq->operationTimeout; - timeOut *= 3; - - m_stopRec.sentCount++; - int res; - if(callback == 0){ - res = sendSignal(nodeId, WAIT_STOP, signal, true); - } else { - res = sendSignal(nodeId, NO_WAIT, signal, true); - } - - if(res != -1){ - nodes.set(nodeId); - } - } - } - - if(stopCount != 0){ - * stopCount = m_stopRec.sentCount; +int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId) +{ + if (getNodeType(singleUserNodeId) != NDB_MGM_NODE_TYPE_API) + return 5062; + NodeId nodeId = 0; + ClusterMgr::Node node; + while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) + { + node = theFacade->theClusterMgr->getNodeInfo(nodeId); + if((node.m_state.startLevel != NodeState::SL_STARTED) && + (node.m_state.startLevel != NodeState::SL_NOTHING)) + return 5063; } + NodeBitmask nodes; + int ret = sendSTOP_REQ(0, + nodes, + singleUserNodeId, + false, + false, + false, + false, + false); + if (stopCount) + *stopCount = nodes.count(); + return ret; +} + +/* + * Perform node restart + */ - if(m_stopRec.sentCount == 0){ - m_stopRec.inUse = false; - return 0; - } - - if(callback != 0){ - return 0; - } - - theFacade->lock_mutex(); - int waitTime = timeOut/m_stopRec.sentCount; - if (receiveOptimisedResponse(waitTime) != 0) { - m_stopRec.inUse = false; - return -1; - } - +int MgmtSrvr::restartNode(int nodeId, bool nostart, bool initialStart, + bool abort) +{ + NodeBitmask nodes; + return sendSTOP_REQ(nodeId, + nodes, + 0, + abort, + false, + true, + nostart, + initialStart); +} + +/* + * Perform system restart + */ + +int MgmtSrvr::restart(bool nostart, bool initialStart, + bool abort, int * stopCount ) +{ + NodeBitmask nodes; + int ret = sendSTOP_REQ(0, + nodes, + 0, + abort, + true, + true, + true, + initialStart); + + if (ret) + return ret; + + if (stopCount) + *stopCount = nodes.count(); + +#ifdef VM_TRACE + ndbout_c("Stopped %d nodes", nodes.count()); +#endif /** * Here all nodes were correctly stopped, * so we wait for all nodes to be contactable */ - nodeId = 0; + int waitTime = 12000; + NodeId nodeId = 0; NDB_TICKS maxTime = NdbTick_CurrentMillisecond() + waitTime; - while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB) && nodes.get(nodeId)) { + + ndbout_c(" %d", nodes.get(1)); + ndbout_c(" %d", nodes.get(2)); + + while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) { + if (!nodes.get(nodeId)) + continue; enum ndb_mgm_node_status s; s = NDB_MGM_NODE_STATUS_NO_CONTACT; +#ifdef VM_TRACE + ndbout_c("Waiting for %d not started", nodeId); +#endif while (s != NDB_MGM_NODE_STATUS_NOT_STARTED && waitTime > 0) { Uint32 startPhase = 0, version = 0, dynamicId = 0, nodeGroup = 0; Uint32 connectCount = 0; bool system; + const char *address; status(nodeId, &s, &version, &startPhase, - &system, &dynamicId, &nodeGroup, &connectCount); + &system, &dynamicId, &nodeGroup, &connectCount, &address); NdbSleep_MilliSleep(100); waitTime = (maxTime - NdbTick_CurrentMillisecond()); } } - if(nostart){ - m_stopRec.inUse = false; + if(nostart) return 0; - } /** * Now we start all database nodes (i.e. we make them non-idle) * We ignore the result we get from the start command. */ nodeId = 0; - while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB) && nodes.get(nodeId)) { + while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) { + if (!nodes.get(nodeId)) + continue; int result; result = start(nodeId); DEBUG("Starting node " << nodeId << " with result " << result); @@ -983,455 +1140,43 @@ MgmtSrvr::restart(bool nostart, bool initalStart, bool abort, * Maybe the user only wanted to restart a subset of the nodes. * It is also easy for the user to check which nodes have * started and which nodes have not. - * - * if (result != 0) { - * m_stopRec.inUse = false; - * return result; - * } */ } - m_stopRec.inUse = false; return 0; } -/***************************************************************************** - * Version handling - *****************************************************************************/ - -int -MgmtSrvr::versionNode(int processId, bool abort, - VersionCallback callback, void * anyData) -{ - int version; - - if(m_versionRec.inUse) - return OPERATION_IN_PROGRESS; - - m_versionRec.callback = callback; - m_versionRec.inUse = true ; - - if (getOwnNodeId() == processId) - { - version= NDB_VERSION; - } - else if (getNodeType(processId) == NDB_MGM_NODE_TYPE_NDB) - { - ClusterMgr::Node node= theFacade->theClusterMgr->getNodeInfo(processId); - if(node.connected) - version= node.m_info.m_version; - else - version= 0; - } - else if (getNodeType(processId) == NDB_MGM_NODE_TYPE_API || - getNodeType(processId) == NDB_MGM_NODE_TYPE_MGM) - { - return sendVersionReq(processId); - } - else - version= 0; - - if(m_versionRec.callback != 0) - m_versionRec.callback(processId, version, this,0); - m_versionRec.inUse = false ; - - m_versionRec.version[processId]= version; - - return 0; -} - -int -MgmtSrvr::sendVersionReq(int processId) -{ - Uint32 ndbnode=0; - int result; - for(Uint32 i = 0; i<MAX_NODES; i++) { - if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { - if(okToSendTo(i, true) == 0) - { - ndbnode = i; - break; - } - } - } - - if (ndbnode == 0) { - m_versionRec.inUse = false; - if(m_versionRec.callback != 0) - m_versionRec.callback(processId, 0, this,0); - return NO_CONTACT_WITH_CLUSTER; - } - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - m_versionRec.inUse = false; - if(m_versionRec.callback != 0) - m_versionRec.callback(processId, 0, this,0); - return COULD_NOT_ALLOCATE_MEMORY; - } - ApiVersionReq* req = CAST_PTR(ApiVersionReq, signal->getDataPtrSend()); - req->senderRef = _ownReference; - req->nodeId = processId; - - signal->set(TestOrd::TraceAPI, QMGR, GSN_API_VERSION_REQ, - ApiVersionReq::SignalLength); - - - // if(m_versionRec.callback == 0){ - Uint32 timeOut = 0; - timeOut = 10000; - result = sendRecSignal(ndbnode, WAIT_VERSION, signal, true, timeOut); - //} else { - //result = sendSignal(processId, NO_WAIT, signal, true); - // } - - if (result == -1) { - m_versionRec.inUse = false; - if(m_versionRec.callback != 0) - m_versionRec.callback(processId, 0, this,0); - m_versionRec.version[processId] = 0; - return SEND_OR_RECEIVE_FAILED; - } - - m_versionRec.inUse = false; - return 0; -} - -int -MgmtSrvr::version(int * stopCount, bool abort, - VersionCallback callback, void * anyData) -{ - ClusterMgr::Node node; - int version; - - if(m_versionRec.inUse) - return 1; - - m_versionRec.callback = callback; - m_versionRec.inUse = true ; - Uint32 i; - for(i = 0; i<MAX_NODES; i++) { - if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM) { - m_versionRec.callback(i, NDB_VERSION, this,0); - } - } - for(i = 0; i<MAX_NODES; i++) { - if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { - node = theFacade->theClusterMgr->getNodeInfo(i); - version = node.m_info.m_version; - if(theFacade->theClusterMgr->getNodeInfo(i).connected) - m_versionRec.callback(i, version, this,0); - else - m_versionRec.callback(i, 0, this,0); - - } - } - for(i = 0; i<MAX_NODES; i++) { - if (getNodeType(i) == NDB_MGM_NODE_TYPE_API) { - return sendVersionReq(i); - } - } - - return 0; -} - -int -MgmtSrvr::stopNode(int processId, bool abort, StopCallback callback, - void * anyData) - -{ - if(m_stopRec.singleUserMode) - return 5060; - - if(m_stopRec.inUse) - return 5029; - - int result; - - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - StopReq* const stopReq = CAST_PTR(StopReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, StopReq::SignalLength); - - stopReq->requestInfo = 0; - stopReq->singleuser = 0; - StopReq::setPerformRestart(stopReq->requestInfo, false); - StopReq::setSystemStop(stopReq->requestInfo, false); - StopReq::setStopAbort(stopReq->requestInfo, abort); - - stopReq->apiTimeout = 5000; - stopReq->transactionTimeout = 1000; - stopReq->readOperationTimeout = 1000; - stopReq->operationTimeout = 1000; - stopReq->senderData = 12; - stopReq->senderRef = _ownReference; - - m_stopRec.sentCount = 1; - m_stopRec.reply = 0; - m_stopRec.nodeId = processId; - m_stopRec.anyData = anyData; - m_stopRec.callback = callback; - m_stopRec.inUse = true; - - if(callback == NULL){ - Uint32 timeOut = 0; - timeOut += stopReq->apiTimeout; - timeOut += stopReq->transactionTimeout; - timeOut += stopReq->readOperationTimeout; - timeOut += stopReq->operationTimeout; - timeOut *= 3; - result = sendRecSignal(processId, WAIT_STOP, signal, true, timeOut); - } else { - result = sendSignal(processId, NO_WAIT, signal, true); - } - - if (result == -1) { - m_stopRec.inUse = false; - return SEND_OR_RECEIVE_FAILED; - } - - if(callback == 0){ - m_stopRec.inUse = false; - return m_stopRec.reply; - } else { - return 0; - } -} - int -MgmtSrvr::stop(int * stopCount, bool abort, StopCallback callback, - void * anyData) +MgmtSrvr::exitSingleUser(int * stopCount, bool abort) { - if(m_stopRec.singleUserMode) - return 5060; - - if(m_stopRec.inUse){ - return 5029; - } - - m_stopRec.singleUserMode = false; - m_stopRec.sentCount = 0; - m_stopRec.reply = 0; - m_stopRec.nodeId = 0; - m_stopRec.anyData = anyData; - m_stopRec.callback = callback; - m_stopRec.inUse = true; - NodeId nodeId = 0; - Uint32 timeOut = 0; - while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){ - if(okToSendTo(nodeId, true) == 0){ - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - StopReq* const stopReq = CAST_PTR(StopReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, - StopReq::SignalLength); - - stopReq->requestInfo = 0; - stopReq->singleuser = 0; - StopReq::setSystemStop(stopReq->requestInfo, true); - StopReq::setPerformRestart(stopReq->requestInfo, false); - StopReq::setStopAbort(stopReq->requestInfo, abort); - - stopReq->apiTimeout = 5000; - stopReq->transactionTimeout = 1000; - stopReq->readOperationTimeout = 1000; - stopReq->operationTimeout = 1000; - stopReq->senderData = 12; - stopReq->senderRef = _ownReference; - - timeOut += stopReq->apiTimeout; - timeOut += stopReq->transactionTimeout; - timeOut += stopReq->readOperationTimeout; - timeOut += stopReq->operationTimeout; - timeOut *= 3; - - m_stopRec.sentCount++; - if(callback == 0) - sendSignal(nodeId, WAIT_STOP, signal, true); - else - sendSignal(nodeId, NO_WAIT, signal, true); - } - } - - if(stopCount != 0) - * stopCount = m_stopRec.sentCount; - - if(m_stopRec.sentCount > 0){ - if(callback == 0){ - theFacade->lock_mutex(); - receiveOptimisedResponse(timeOut / m_stopRec.sentCount); - } else { - return 0; - } - } - - m_stopRec.inUse = false; - return m_stopRec.reply; -} - -/***************************************************************************** - * Single user mode - ****************************************************************************/ - -int -MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId, - EnterSingleCallback callback, void * anyData) -{ - if(m_stopRec.singleUserMode) { - return 5060; - } - - if (getNodeType(singleUserNodeId) != NDB_MGM_NODE_TYPE_API) { - return 5062; - } - ClusterMgr::Node node; - - for(Uint32 i = 0; i<MAX_NODES; i++) { - if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { - node = theFacade->theClusterMgr->getNodeInfo(i); - if((node.m_state.startLevel != NodeState::SL_STARTED) && - (node.m_state.startLevel != NodeState::SL_NOTHING)) { - return 5063; - } - } - } - - if(m_stopRec.inUse){ - return 5029; - } - - if(singleUserNodeId == 0) - return 1; - m_stopRec.singleUserMode = true; - m_stopRec.sentCount = 0; - m_stopRec.reply = 0; - m_stopRec.nodeId = 0; - m_stopRec.anyData = anyData; - m_stopRec.callback = callback; - m_stopRec.inUse = true; - - NodeId nodeId = 0; - Uint32 timeOut = 0; - while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){ - if(okToSendTo(nodeId, true) == 0){ - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - StopReq* const stopReq = CAST_PTR(StopReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, NDBCNTR, GSN_STOP_REQ, - StopReq::SignalLength); - - stopReq->requestInfo = 0; - stopReq->singleuser = 1; - stopReq->singleUserApi = singleUserNodeId; - StopReq::setSystemStop(stopReq->requestInfo, false); - StopReq::setPerformRestart(stopReq->requestInfo, false); - StopReq::setStopAbort(stopReq->requestInfo, false); - - stopReq->apiTimeout = 5000; - stopReq->transactionTimeout = 1000; - stopReq->readOperationTimeout = 1000; - stopReq->operationTimeout = 1000; - stopReq->senderData = 12; - stopReq->senderRef = _ownReference; - timeOut += stopReq->apiTimeout; - timeOut += stopReq->transactionTimeout; - timeOut += stopReq->readOperationTimeout; - timeOut += stopReq->operationTimeout; - timeOut *= 3; - - m_stopRec.sentCount++; - if(callback == 0) - sendSignal(nodeId, WAIT_STOP, signal, true); - else - sendSignal(nodeId, NO_WAIT, signal, true); - } - } - - if(stopCount != 0) - * stopCount = m_stopRec.sentCount; + int count = 0; - if(callback == 0){ - m_stopRec.inUse = false; - return 0; - // return m_stopRec.reply; - } else { - return 0; - } + SignalSender ss(theFacade); + ss.lock(); // lock will be released on exit - m_stopRec.inUse = false; - return m_stopRec.reply; -} + SimpleSignal ssig; + ResumeReq* const resumeReq = + CAST_PTR(ResumeReq, ssig.getDataPtrSend()); + ssig.set(ss,TestOrd::TraceAPI, NDBCNTR, GSN_RESUME_REQ, + ResumeReq::SignalLength); + resumeReq->senderData = 12; + resumeReq->senderRef = ss.getOwnRef(); -int -MgmtSrvr::exitSingleUser(int * stopCount, bool abort, - ExitSingleCallback callback, void * anyData) -{ - m_stopRec.sentCount = 0; - m_stopRec.reply = 0; - m_stopRec.nodeId = 0; - m_stopRec.anyData = anyData; - m_stopRec.callback = callback; - m_stopRec.inUse = true; - - NodeId nodeId = 0; while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){ if(okToSendTo(nodeId, true) == 0){ - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - ResumeReq* const resumeReq = - CAST_PTR(ResumeReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, NDBCNTR, GSN_RESUME_REQ, - StopReq::SignalLength); - resumeReq->senderData = 12; - resumeReq->senderRef = _ownReference; - - m_stopRec.sentCount++; - if(callback == 0) - sendSignal(nodeId, WAIT_STOP, signal, true); - else - sendSignal(nodeId, NO_WAIT, signal, true); + SendStatus result = ss.sendSignal(nodeId, &ssig); + if (result == SEND_OK) + count++; } } - m_stopRec.singleUserMode = false; - if(stopCount != 0) - * stopCount = m_stopRec.sentCount; - + * stopCount = count; - if(callback == 0){ - m_stopRec.inUse = false; - return m_stopRec.reply; - } else { - return 0; - } - - m_stopRec.inUse = false; - return m_stopRec.reply; + return 0; } - /***************************************************************************** * Status ****************************************************************************/ @@ -1439,32 +1184,32 @@ MgmtSrvr::exitSingleUser(int * stopCount, bool abort, #include <ClusterMgr.hpp> int -MgmtSrvr::status(int processId, +MgmtSrvr::status(int nodeId, ndb_mgm_node_status * _status, Uint32 * version, Uint32 * _phase, bool * _system, Uint32 * dynamic, Uint32 * nodegroup, - Uint32 * connectCount) + Uint32 * connectCount, + const char **address) { - if (getNodeType(processId) == NDB_MGM_NODE_TYPE_API || - getNodeType(processId) == NDB_MGM_NODE_TYPE_MGM) { - if(versionNode(processId, false,0,0) ==0) - * version = m_versionRec.version[processId]; - else - * version = 0; + if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_API || + getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM) { + versionNode(nodeId, *version, address); + } else { + *address= get_connect_address(nodeId); } const ClusterMgr::Node node = - theFacade->theClusterMgr->getNodeInfo(processId); + theFacade->theClusterMgr->getNodeInfo(nodeId); if(!node.connected){ * _status = NDB_MGM_NODE_STATUS_NO_CONTACT; return 0; } - if (getNodeType(processId) == NDB_MGM_NODE_TYPE_NDB) { + if (getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB) { * version = node.m_info.m_version; } @@ -1527,67 +1272,81 @@ MgmtSrvr::status(int processId, } int -MgmtSrvr::setEventReportingLevelImpl(int processId, +MgmtSrvr::setEventReportingLevelImpl(int nodeId, const EventSubscribeReq& ll) { - - int result = okToSendTo(processId, true); - if (result != 0) { - return result; - } - - NdbApiSignal signal(_ownReference); + INIT_SIGNAL_SENDER(ss,nodeId); + SimpleSignal ssig; EventSubscribeReq * dst = - CAST_PTR(EventSubscribeReq, signal.getDataPtrSend()); - - * dst = ll; - - signal.set(TestOrd::TraceAPI, CMVMI, GSN_EVENT_SUBSCRIBE_REQ, - EventSubscribeReq::SignalLength); - - theFacade->lock_mutex(); - send(&signal, processId, NODE_TYPE_DB); - theFacade->unlock_mutex(); - + CAST_PTR(EventSubscribeReq, ssig.getDataPtrSend()); + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_EVENT_SUBSCRIBE_REQ, + EventSubscribeReq::SignalLength); + *dst = ll; + + send(ss,ssig,nodeId,NODE_TYPE_DB); + +#if 0 + while (1) + { + SimpleSignal *signal = ss.waitFor(); + int gsn = signal->readSignalNumber(); + switch (gsn) { + case GSN_EVENT_SUBSCRIBE_CONF:{ + break; + } + case GSN_EVENT_SUBSCRIBE_REF:{ + return SEND_OR_RECEIVE_FAILED; + } + case GSN_NF_COMPLETEREP:{ + const NFCompleteRep * const rep = + CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr()); + if (rep->failedNodeId == nodeId) + return SEND_OR_RECEIVE_FAILED; + break; + } + case GSN_NODE_FAILREP:{ + const NodeFailRep * const rep = + CAST_CONSTPTR(NodeFailRep, signal->getDataPtr()); + if (NodeBitmask::get(rep->theNodes,nodeId)) + return SEND_OR_RECEIVE_FAILED; + break; + } + default: + report_unknown_signal(signal); + return SEND_OR_RECEIVE_FAILED; + } + + } +#endif return 0; } //**************************************************************************** //**************************************************************************** int -MgmtSrvr::setNodeLogLevelImpl(int processId, const SetLogLevelOrd & ll) +MgmtSrvr::setNodeLogLevelImpl(int nodeId, const SetLogLevelOrd & ll) { - int result = okToSendTo(processId, true); - if (result != 0) { - return result; - } + INIT_SIGNAL_SENDER(ss,nodeId); - NdbApiSignal signal(_ownReference); - - SetLogLevelOrd * dst = CAST_PTR(SetLogLevelOrd, signal.getDataPtrSend()); - - * dst = ll; - - signal.set(TestOrd::TraceAPI, CMVMI, GSN_SET_LOGLEVELORD, - SetLogLevelOrd::SignalLength); + SimpleSignal ssig; + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_SET_LOGLEVELORD, + SetLogLevelOrd::SignalLength); + SetLogLevelOrd* const dst = CAST_PTR(SetLogLevelOrd, ssig.getDataPtrSend()); + *dst = ll; - theFacade->lock_mutex(); - theFacade->sendSignalUnCond(&signal, processId); - theFacade->unlock_mutex(); - - return 0; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } int -MgmtSrvr::send(NdbApiSignal* signal, Uint32 node, Uint32 node_type){ +MgmtSrvr::send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type){ Uint32 max = (node == 0) ? MAX_NODES : node + 1; for(; node < max; node++){ while(nodeTypes[node] != (int)node_type && node < max) node++; if(nodeTypes[node] != (int)node_type) break; - theFacade->sendSignalUnCond(signal, node); + ss.sendSignal(node, &ssig); } return 0; } @@ -1596,34 +1355,21 @@ MgmtSrvr::send(NdbApiSignal* signal, Uint32 node, Uint32 node_type){ //**************************************************************************** int -MgmtSrvr::insertError(int processId, int errorNo) +MgmtSrvr::insertError(int nodeId, int errorNo) { if (errorNo < 0) { return INVALID_ERROR_NUMBER; } - int result; - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } + INIT_SIGNAL_SENDER(ss,nodeId); - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - TamperOrd* const tamperOrd = CAST_PTR(TamperOrd, signal->getDataPtrSend()); + SimpleSignal ssig; + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TAMPER_ORD, + TamperOrd::SignalLength); + TamperOrd* const tamperOrd = CAST_PTR(TamperOrd, ssig.getDataPtrSend()); tamperOrd->errorNo = errorNo; - signal->set(TestOrd::TraceAPI, CMVMI, GSN_TAMPER_ORD, - TamperOrd::SignalLength); - - result = sendSignal(processId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - return 0; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } @@ -1632,37 +1378,23 @@ MgmtSrvr::insertError(int processId, int errorNo) //**************************************************************************** int -MgmtSrvr::setTraceNo(int processId, int traceNo) +MgmtSrvr::setTraceNo(int nodeId, int traceNo) { if (traceNo < 0) { return INVALID_TRACE_NUMBER; } - int result; - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } + INIT_SIGNAL_SENDER(ss,nodeId); - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - TestOrd* const testOrd = CAST_PTR(TestOrd, signal->getDataPtrSend()); + SimpleSignal ssig; + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); + TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend()); testOrd->clear(); - // Assume TRACE command causes toggling. Not really defined... ? TODO testOrd->setTraceCommand(TestOrd::Toggle, (TestOrd::TraceSpecification)traceNo); - signal->set(TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); - result = sendSignal(processId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - - return 0; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } //**************************************************************************** @@ -1681,14 +1413,10 @@ MgmtSrvr::getBlockNumber(const BaseString &blockName) //**************************************************************************** int -MgmtSrvr::setSignalLoggingMode(int processId, LogMode mode, +MgmtSrvr::setSignalLoggingMode(int nodeId, LogMode mode, const Vector<BaseString>& blocks) { - int result; - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } + INIT_SIGNAL_SENDER(ss,nodeId); // Convert from MgmtSrvr format... @@ -1723,12 +1451,10 @@ MgmtSrvr::setSignalLoggingMode(int processId, LogMode mode, return -1; } - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } + SimpleSignal ssig; + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); - TestOrd* const testOrd = CAST_PTR(TestOrd, signal->getDataPtrSend()); + TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend()); testOrd->clear(); if (blocks.size() == 0 || blocks[0] == "ALL") { @@ -1738,78 +1464,44 @@ MgmtSrvr::setSignalLoggingMode(int processId, LogMode mode, for(unsigned i = 0; i < blocks.size(); i++){ int blockNumber = getBlockNumber(blocks[i]); if (blockNumber == -1) { - releaseSignal(signal); return INVALID_BLOCK_NAME; } testOrd->addSignalLoggerCommand(blockNumber, command, logSpec); } // for } // else - - signal->set(TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); - result = sendSignal(processId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - return 0; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } - /***************************************************************************** * Signal tracing *****************************************************************************/ -int MgmtSrvr::startSignalTracing(int processId) +int MgmtSrvr::startSignalTracing(int nodeId) { - int result; - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - + INIT_SIGNAL_SENDER(ss,nodeId); - TestOrd* const testOrd = CAST_PTR(TestOrd, signal->getDataPtrSend()); + SimpleSignal ssig; + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); + + TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend()); testOrd->clear(); testOrd->setTestCommand(TestOrd::On); - signal->set(TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); - result = sendSignal(processId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - - return 0; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } int -MgmtSrvr::stopSignalTracing(int processId) +MgmtSrvr::stopSignalTracing(int nodeId) { - int result; - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } + INIT_SIGNAL_SENDER(ss,nodeId); - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } - - TestOrd* const testOrd = CAST_PTR(TestOrd, signal->getDataPtrSend()); + SimpleSignal ssig; + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); + TestOrd* const testOrd = CAST_PTR(TestOrd, ssig.getDataPtrSend()); testOrd->clear(); testOrd->setTestCommand(TestOrd::Off); - signal->set(TestOrd::TraceAPI, CMVMI, GSN_TEST_ORD, TestOrd::SignalLength); - result = sendSignal(processId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - - return 0; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } @@ -1818,7 +1510,7 @@ MgmtSrvr::stopSignalTracing(int processId) *****************************************************************************/ int -MgmtSrvr::dumpState(int processId, const char* args) +MgmtSrvr::dumpState(int nodeId, const char* args) { // Convert the space separeted args // string to an int array @@ -1840,29 +1532,20 @@ MgmtSrvr::dumpState(int processId, const char* args) } } - return dumpState(processId, args_array, numArgs); + return dumpState(nodeId, args_array, numArgs); } int -MgmtSrvr::dumpState(int processId, const Uint32 args[], Uint32 no) +MgmtSrvr::dumpState(int nodeId, const Uint32 args[], Uint32 no) { - int result; - - result = okToSendTo(processId, true); - if (result != 0) { - return result; - } - - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } + INIT_SIGNAL_SENDER(ss,nodeId); const Uint32 len = no > 25 ? 25 : no; + SimpleSignal ssig; DumpStateOrd * const dumpOrd = - CAST_PTR(DumpStateOrd, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, CMVMI, GSN_DUMP_STATE_ORD, len); + CAST_PTR(DumpStateOrd, ssig.getDataPtrSend()); + ssig.set(ss,TestOrd::TraceAPI, CMVMI, GSN_DUMP_STATE_ORD, len); for(Uint32 i = 0; i<25; i++){ if (i < len) dumpOrd->args[i] = args[i]; @@ -1870,12 +1553,7 @@ MgmtSrvr::dumpState(int processId, const Uint32 args[], Uint32 no) dumpOrd->args[i] = 0; } - result = sendSignal(processId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - - return 0; + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } @@ -1906,42 +1584,18 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal) int gsn = signal->readSignalNumber(); switch (gsn) { - case GSN_API_VERSION_CONF: { - if (theWaitState == WAIT_VERSION) { - const ApiVersionConf * const conf = - CAST_CONSTPTR(ApiVersionConf, signal->getDataPtr()); - if(m_versionRec.callback != 0) - m_versionRec.callback(conf->nodeId, conf->version, this, 0); - else { - m_versionRec.version[conf->nodeId]=conf->version; - } - } else return; - theWaitState = NO_WAIT; - } - break; - case GSN_EVENT_SUBSCRIBE_CONF: break; - + case GSN_EVENT_SUBSCRIBE_REF: + break; case GSN_EVENT_REP: eventReport(signal->getDataPtr()); break; - case GSN_STOP_REF:{ - const StopRef * const ref = CAST_CONSTPTR(StopRef, signal->getDataPtr()); - const NodeId nodeId = refToNode(signal->theSendersBlockRef); - handleStopReply(nodeId, ref->errorCode); - return; - } + case GSN_NF_COMPLETEREP: break; - - case GSN_MGM_LOCK_CONFIG_REP: - case GSN_MGM_LOCK_CONFIG_REQ: - case GSN_MGM_UNLOCK_CONFIG_REP: - case GSN_MGM_UNLOCK_CONFIG_REQ: { - m_signalRecvQueue.receive(new NdbApiSignal(*signal)); + case GSN_NODE_FAILREP: break; - } default: g_eventLogger.error("Unknown signal received. SignalNumber: " @@ -1956,75 +1610,6 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal) } } -/** - * A database node was either stopped or there was some error - */ -void -MgmtSrvr::handleStopReply(NodeId nodeId, Uint32 errCode) -{ - /** - * If we are in single user mode and get a stop reply from a - * DB node, then we have had a node crash. - * If all DB nodes are gone, and we are still in single user mode, - * the set m_stopRec.singleUserMode = false; - */ - if(m_stopRec.singleUserMode) { - ClusterMgr::Node node; - bool failure = true; - for(Uint32 i = 0; i<MAX_NODES; i++) { - if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) { - node = theFacade->theClusterMgr->getNodeInfo(i); - if((node.m_state.startLevel == NodeState::SL_NOTHING)) - failure = true; - else - failure = false; - } - } - if(failure) { - m_stopRec.singleUserMode = false; - } - } - if(m_stopRec.inUse == false) - return; - - if(!(m_stopRec.nodeId == 0 || m_stopRec.nodeId == nodeId)) - goto error; - - if(m_stopRec.sentCount <= 0) - goto error; - - if(!(theWaitState == WAIT_STOP || m_stopRec.callback != 0)) - goto error; - - if(errCode != 0) - m_stopRec.reply = translateStopRef(errCode); - - m_stopRec.sentCount --; - if(m_stopRec.sentCount == 0){ - if(theWaitState == WAIT_STOP){ - theWaitState = NO_WAIT; - NdbCondition_Signal(theMgmtWaitForResponseCondPtr); - return; - } - if(m_stopRec.callback != 0){ - m_stopRec.inUse = false; - StopCallback callback = m_stopRec.callback; - m_stopRec.callback = NULL; - (* callback)(m_stopRec.nodeId, - m_stopRec.anyData, - m_stopRec.reply); - return; - } - } - return; - - error: - if(errCode != 0){ - g_eventLogger.error("Unexpected signal received. SignalNumber: %i from %d", - GSN_STOP_REF, nodeId); - } -} - void MgmtSrvr::handleStatus(NodeId nodeId, bool alive, bool nfComplete) { @@ -2040,16 +1625,8 @@ MgmtSrvr::handleStatus(NodeId nodeId, bool alive, bool nfComplete) rep->setEventType(NDB_LE_Connected); if(nfComplete) { - handleStopReply(nodeId, 0); DBUG_VOID_RETURN; } - - if(theWaitNode == nodeId && - theWaitState != NO_WAIT && theWaitState != WAIT_STOP) - { - theWaitState = WAIT_NODEFAILURE; - NdbCondition_Signal(theMgmtWaitForResponseCondPtr); - } } rep->setNodeId(_ownNodeId); @@ -2401,6 +1978,7 @@ MgmtSrvr::eventReport(const Uint32 * theData) /*************************************************************************** * Backup ***************************************************************************/ + int MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) { @@ -2415,7 +1993,6 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) if(!next) return NO_CONTACT_WITH_DB_NODES; SimpleSignal ssig; - BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend()); ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ, BackupReq::SignalLength); @@ -2430,8 +2007,7 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) while (1) { if (do_send) { - SendStatus result = ss.sendSignal(nodeId, &ssig); - if (result != SEND_OK) { + if (ss.sendSignal(nodeId, &ssig) != SEND_OK) { return SEND_OR_RECEIVE_FAILED; } if (waitCompleted == 0) @@ -2533,13 +2109,13 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) return SEND_OR_RECEIVE_FAILED; } } - - return 0; } int MgmtSrvr::abortBackup(Uint32 backupId) { + SignalSender ss(theFacade); + bool next; NodeId nodeId = 0; while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true && @@ -2549,44 +2125,17 @@ MgmtSrvr::abortBackup(Uint32 backupId) return NO_CONTACT_WITH_DB_NODES; } - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - return COULD_NOT_ALLOCATE_MEMORY; - } + SimpleSignal ssig; - AbortBackupOrd* ord = CAST_PTR(AbortBackupOrd, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, BACKUP, GSN_ABORT_BACKUP_ORD, - AbortBackupOrd::SignalLength); + AbortBackupOrd* ord = CAST_PTR(AbortBackupOrd, ssig.getDataPtrSend()); + ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_ABORT_BACKUP_ORD, + AbortBackupOrd::SignalLength); ord->requestType = AbortBackupOrd::ClientAbort; ord->senderData = 19; ord->backupId = backupId; - int result = sendSignal(nodeId, NO_WAIT, signal, true); - if (result == -1) { - return SEND_OR_RECEIVE_FAILED; - } - - return 0; -} - - -NodeId -MgmtSrvr::getPrimaryNode() const { -#if 0 - Uint32 tmp; - const Properties *prop = NULL; - - getConfig()->get("SYSTEM", &prop); - if(prop == NULL) - return 0; - - prop->get("PrimaryMGMNode", &tmp); - - return tmp; -#else - return 0; -#endif + return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; } @@ -2739,7 +2288,6 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value, NdbMutex_Unlock(m_configMutex); return 0; } - int MgmtSrvr::setConnectionDbParameter(int node1, int node2, @@ -2874,10 +2422,6 @@ int MgmtSrvr::set_connect_string(const char *str) } -template class Vector<SigMatch>; -#if __SUNPRO_CC != 0x560 -template bool SignalQueue::waitFor<SigMatch>(Vector<SigMatch>&, SigMatch**, NdbApiSignal**, unsigned); -#endif template class MutexVector<unsigned short>; template class MutexVector<Ndb_mgmd_event_service::Event_listener>; diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp index e43a0ff4149..d61c0ce8db7 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -22,15 +22,17 @@ #include <NdbCondition.h> #include <mgmapi.h> - +#include <NdbTCP.h> +#include <ConfigRetriever.hpp> #include <Vector.hpp> #include <NodeBitmask.hpp> #include <signaldata/ManagementServer.hpp> -#include "SignalQueue.hpp" #include <ndb_version.h> #include <EventLogger.hpp> #include <signaldata/EventSubscribeReq.hpp> +#include <SignalSender.hpp> + /** * @desc Block number for Management server. * @todo This should probably be somewhere else. I don't know where atm. @@ -200,51 +202,26 @@ public: ~MgmtSrvr(); - int status(int processId, - ndb_mgm_node_status * status, + /** + * Get status on a node. + * address may point to a common area (e.g. from inet_addr) + * There is no gaurentee that it is preserved across calls. + * Copy the string if you are not going to use it immediately. + */ + int status(int nodeId, + ndb_mgm_node_status * status, Uint32 * version, Uint32 * phase, bool * systemShutdown, Uint32 * dynamicId, Uint32 * nodeGroup, - Uint32 * connectCount); + Uint32 * connectCount, + const char **address); // All the functions below may return any of this error codes: // NO_CONTACT_WITH_PROCESS, PROCESS_NOT_CONFIGURED, WRONG_PROCESS_TYPE, // COULD_NOT_ALLOCATE_MEMORY, SEND_OR_RECEIVE_FAILED - - typedef void (* StopCallback)(int nodeId, void * anyData, int errorCode); - - typedef void (* VersionCallback)(int nodeId, int version, - void * anyData, int errorCode); - - - typedef void (* EnterSingleCallback)(int nodeId, void * anyData, - int errorCode); - typedef void (* ExitSingleCallback)(int nodeId, void * anyData, - int errorCode); - - /** - * Lock configuration - */ - int lockConf(); - - /** - * Unlock configuration, and commit it if commit is true - */ - int unlockConf(bool commit); - - /** - * Commit new configuration - */ - int commitConfig(); - - /** - * Rollback configuration - */ - int rollbackConfig(); - /** * Save a configuration to permanent storage */ @@ -273,12 +250,12 @@ public: * @param processId: Id of the DB process to stop * @return 0 if succeeded, otherwise: as stated above, plus: */ - int stopNode(int nodeId, bool abort = false, StopCallback = 0, void *any= 0); + int stopNode(int nodeId, bool abort = false); /** * Stop the system */ - int stop(int * cnt = 0, bool abort = false, StopCallback = 0, void *any = 0); + int stop(int * cnt = 0, bool abort = false); /** * print version info about a node @@ -286,27 +263,18 @@ public: * @param processId: Id of the DB process to stop * @return 0 if succeeded, otherwise: as stated above, plus: */ - int versionNode(int nodeId, bool abort = false, - VersionCallback = 0, void *any= 0); + int versionNode(int nodeId, Uint32 &version, const char **address); /** - * print version info about all node in the system - */ - int version(int * cnt = 0, bool abort = false, - VersionCallback = 0, void *any = 0); - - /** * Maintenance on the system */ - int enterSingleUser(int * cnt = 0, Uint32 singleuserNodeId = 0, - EnterSingleCallback = 0, void *any = 0); + int enterSingleUser(int * cnt = 0, Uint32 singleuserNodeId = 0); /** * Resume from maintenance on the system */ - int exitSingleUser(int * cnt = 0, bool abort = false, - ExitSingleCallback = 0, void *any = 0); + int exitSingleUser(int * cnt = 0, bool abort = false); /** * Start DB process. @@ -320,15 +288,14 @@ public: * @param processId: Id of the DB process to start */ int restartNode(int processId, bool nostart, bool initialStart, - bool abort = false, - StopCallback = 0, void * anyData = 0); + bool abort = false); /** * Restart the system */ int restart(bool nostart, bool initialStart, bool abort = false, - int * stopCount = 0, StopCallback = 0, void * anyData = 0); + int * stopCount = 0); struct BackupEvent { enum Event { @@ -478,13 +445,6 @@ public: const Config * getConfig() const; /** - * Change configuration paramter - */ - bool changeConfig(const BaseString §ion, - const BaseString ¶m, - const BaseString &value); - - /** * Returns the node count for the specified node type. * * @param type The node type. @@ -493,11 +453,6 @@ public: int getNodeCount(enum ndb_mgm_node_type type) const; /** - * Returns the nodeId of the management master - */ - NodeId getPrimaryNode() const; - - /** * Returns the port number. * @return port number. */ @@ -523,8 +478,17 @@ public: private: //************************************************************************** - int setEventReportingLevel(int processId, LogLevel::EventCategory, Uint32); - + int send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type); + + int sendSTOP_REQ(NodeId nodeId, + NodeBitmask &stoppedNodes, + Uint32 singleUserNodeId, + bool abort, + bool stop, + bool restart, + bool nostart, + bool initialStart); + /** * Check if it is possible to send a signal to a (DB) process * @@ -588,9 +552,6 @@ private: // Returns: - //************************************************************************** - void handle_MGM_LOCK_CONFIG_REQ(NdbApiSignal *signal); - void handle_MGM_UNLOCK_CONFIG_REQ(NdbApiSignal *signal); - //************************************************************************** // Specific signal handling data //************************************************************************** @@ -614,59 +575,8 @@ private: enum WaitSignalType { NO_WAIT, // We don't expect to receive any signal WAIT_SET_VAR, // Accept SET_VAR_CONF and SET_VAR_REF - WAIT_SUBSCRIBE_CONF, // Accept event subscription confirmation - WAIT_STOP, - WAIT_BACKUP_STARTED, - WAIT_BACKUP_COMPLETED, - WAIT_VERSION, - WAIT_NODEFAILURE + WAIT_SUBSCRIBE_CONF // Accept event subscription confirmation }; - - /** - * Get an unused signal - * @return A signal if succeeded, NULL otherwise - */ - NdbApiSignal* getSignal(); - - /** - * Add a signal to the list of unused signals - * @param signal: The signal to add - */ - void releaseSignal(NdbApiSignal* signal); - - /** - * Remove a signal from the list of unused signals and delete - * the memory for it. - */ - void freeSignal(); - - /** - * Send a signal - * @param processId: Id of the receiver process - * @param waitState: State denoting a set of signals we accept to receive - * @param signal: The signal to send - * @return 0 if succeeded, -1 otherwise - */ - int sendSignal(Uint16 processId, WaitSignalType waitState, - NdbApiSignal* signal, bool force = false); - - /** - * Send a signal and wait for an answer signal - * @param processId: Id of the receiver process - * @param waitState: State denoting a set of signals we accept to receive. - * @param signal: The signal to send - * @return 0 if succeeded, -1 otherwise (for example failed to send or - * failed to receive expected signal). - */ - int sendRecSignal(Uint16 processId, WaitSignalType waitState, - NdbApiSignal* signal, bool force = false, - int waitTime = WAIT_FOR_RESPONSE_TIMEOUT); - - /** - * Wait for a signal to arrive. - * @return 0 if signal arrived, -1 otherwise - */ - int receiveOptimisedResponse(int waitTime); /** * This function is called from "outside" of MgmtSrvr @@ -677,7 +587,7 @@ private: static void signalReceivedNotification(void* mgmtSrvr, NdbApiSignal* signal, struct LinearSectionPtr ptr[3]); - + /** * Called from "outside" of MgmtSrvr when a DB process has died. * @param mgmtSrvr: The MgmtSrvr object wreceiveOptimisedResponsehich @@ -714,31 +624,7 @@ private: class TransporterFacade * theFacade; - class SignalQueue m_signalRecvQueue; - - struct StopRecord { - StopRecord(){ inUse = false; callback = 0; singleUserMode = false;} - bool inUse; - bool singleUserMode; - int sentCount; - int reply; - int nodeId; - void * anyData; - StopCallback callback; - }; - StopRecord m_stopRec; - - struct VersionRecord { - VersionRecord(){ inUse = false; callback = 0;} - bool inUse; - Uint32 version[MAX_NODES]; - VersionCallback callback; - }; - VersionRecord m_versionRec; - int sendVersionReq( int processId); - - - void handleStopReply(NodeId nodeId, Uint32 errCode); + int sendVersionReq( int processId, Uint32 &version, const char **address); int translateStopRef(Uint32 errCode); bool _isStopThread; @@ -759,14 +645,8 @@ private: static void *logLevelThread_C(void *); void logLevelThreadRun(); - struct NdbThread *m_signalRecvThread; - static void *signalRecvThread_C(void *); - void signalRecvThreadRun(); - Config *_props; - int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type); - ConfigRetriever *m_config_retriever; }; diff --git a/storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp b/storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp index 6c4b4e9ae3c..e56643a3d7e 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp @@ -23,228 +23,6 @@ #include <ConfigRetriever.hpp> #include <ndb_version.h> -void -MgmtSrvr::handle_MGM_LOCK_CONFIG_REQ(NdbApiSignal *signal) { - NodeId sender = refToNode(signal->theSendersBlockRef); - const MgmLockConfigReq * const req = CAST_CONSTPTR(MgmLockConfigReq, signal->getDataPtr()); - - NdbApiSignal *reply = getSignal(); - if(signal == NULL) - return; /** @todo handle allocation failure */ - - reply->set(TestOrd::TraceAPI, - MGMSRV, - GSN_MGM_LOCK_CONFIG_REP, - MgmLockConfigRep::SignalLength); - - MgmLockConfigRep *lockRep = CAST_PTR(MgmLockConfigRep, reply->getDataPtrSend()); - - lockRep->errorCode = MgmLockConfigRep::UNKNOWN_ERROR; - - if(req->newConfigGeneration < m_nextConfigGenerationNumber) { - lockRep->errorCode = MgmLockConfigRep::GENERATION_MISMATCH; - goto done; - } - NdbMutex_Lock(m_configMutex); - - m_nextConfigGenerationNumber = req->newConfigGeneration+1; - - lockRep->errorCode = MgmLockConfigRep::OK; - - done: - sendSignal(sender, NO_WAIT, reply, true); - NdbMutex_Unlock(m_configMutex); - return; -} - -void -MgmtSrvr::handle_MGM_UNLOCK_CONFIG_REQ(NdbApiSignal *signal) { - NodeId sender = refToNode(signal->theSendersBlockRef); - const MgmUnlockConfigReq * const req = CAST_CONSTPTR(MgmUnlockConfigReq, signal->getDataPtr()); - MgmUnlockConfigRep *unlockRep; - - NdbApiSignal *reply = getSignal(); - if(signal == NULL) - goto error; /** @todo handle allocation failure */ - - reply->set(TestOrd::TraceAPI, - MGMSRV, - GSN_MGM_UNLOCK_CONFIG_REP, - MgmUnlockConfigRep::SignalLength); - - unlockRep = CAST_PTR(MgmUnlockConfigRep, reply->getDataPtrSend()); - - unlockRep->errorCode = MgmUnlockConfigRep::UNKNOWN_ERROR; - - - NdbMutex_Lock(m_configMutex); - - if(req->commitConfig == 1) { - m_newConfig = fetchConfig(); - commitConfig(); - } else - rollbackConfig(); - - unlockRep->errorCode = MgmUnlockConfigRep::OK; - - sendSignal(sender, NO_WAIT, reply, true); - error: - NdbMutex_Unlock(m_configMutex); - return; -} - - -/** - * Prepare all MGM nodes for configuration changes - * - * @returns 0 on success, or -1 on failure - */ -int -MgmtSrvr::lockConf() { - int result = -1; - MgmLockConfigReq* lockReq; - NodeId node = 0; - - /* Check if this is the master node */ - if(getPrimaryNode() != _ownNodeId) - goto done; - - if(NdbMutex_Trylock(m_configMutex) != 0) - return -1; - - m_newConfig = new Config(*_config); /* copy the existing config */ - _config = m_newConfig; - - m_newConfig = new Config(*_config); - - m_nextConfigGenerationNumber++; - - /* Make sure the new configuration _always_ is at least one step older */ - if(m_nextConfigGenerationNumber < m_newConfig->getGenerationNumber()+1) - m_nextConfigGenerationNumber = _config->getGenerationNumber()+1; - - m_newConfig->setGenerationNumber(m_nextConfigGenerationNumber); - - node = 0; - while(getNextNodeId(&node, NDB_MGM_NODE_TYPE_MGM)) { - if(node != _ownNodeId) { - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - result = COULD_NOT_ALLOCATE_MEMORY; - goto done; - } - - lockReq = CAST_PTR(MgmLockConfigReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, - MGMSRV, - GSN_MGM_LOCK_CONFIG_REQ, - MgmLockConfigReq::SignalLength); - - lockReq->newConfigGeneration = m_nextConfigGenerationNumber; - - result = sendSignal(node, NO_WAIT, signal, true); - - NdbApiSignal *reply = - m_signalRecvQueue.waitFor(GSN_MGM_LOCK_CONFIG_REP, 0); - - if(reply == NULL) { - /** @todo handle timeout/error */ - ndbout << __FILE__ << ":" << __LINE__ << endl; - result = -1; - goto done; - } - - } - } - - done: - NdbMutex_Unlock(m_configMutex); - return result; -} - -/** - * Unlocks configuration - * - * @returns 0 on success, ! 0 on error - */ -int -MgmtSrvr::unlockConf(bool commit) { - int result = -1; - MgmUnlockConfigReq* unlockReq; - NodeId node = 0; - - /* Check if this is the master node */ - if(getPrimaryNode() != _ownNodeId) - goto done; - - errno = 0; - if(NdbMutex_Lock(m_configMutex) != 0) - return -1; - - if(commit) - commitConfig(); - else - rollbackConfig(); - - node = 0; - while(getNextNodeId(&node, NDB_MGM_NODE_TYPE_MGM)) { - if(node != _ownNodeId) { - NdbApiSignal* signal = getSignal(); - if (signal == NULL) { - result = COULD_NOT_ALLOCATE_MEMORY; - goto done; - } - - unlockReq = CAST_PTR(MgmUnlockConfigReq, signal->getDataPtrSend()); - signal->set(TestOrd::TraceAPI, - MGMSRV, - GSN_MGM_UNLOCK_CONFIG_REQ, - MgmUnlockConfigReq::SignalLength); - unlockReq->commitConfig = commit; - - result = sendSignal(node, NO_WAIT, signal, true); - - NdbApiSignal *reply = - m_signalRecvQueue.waitFor(GSN_MGM_UNLOCK_CONFIG_REP, 0); - - if(reply == NULL) { - /** @todo handle timeout/error */ - result = -1; - goto done; - } - - } - } - - done: - NdbMutex_Unlock(m_configMutex); - return result; -} - -/** - * Commit the new configuration - */ -int -MgmtSrvr::commitConfig() { - int ret = saveConfig(m_newConfig); - delete _config; - _config = m_newConfig; - m_newConfig = NULL; - ndbout << "commit " << ret << endl; - return ret; -} - -/** - * Rollback to the old configuration - */ -int -MgmtSrvr::rollbackConfig() { - delete m_newConfig; - m_newConfig = NULL; - ndbout << "rollback" << endl; - return saveConfig(_config); -} - /** * Save a configuration to the running configuration file */ @@ -274,7 +52,15 @@ Config * MgmtSrvr::readConfig() { Config *conf; InitConfigFileParser parser; - conf = parser.parseConfig(m_configFilename.c_str()); + if (m_configFilename.length()) + { + conf = parser.parseConfig(m_configFilename.c_str()); + } + else + { + ndbout_c("Reading cluster configuration using my.cnf"); + conf = parser.parse_mycnf(); + } return conf; } @@ -288,12 +74,3 @@ MgmtSrvr::fetchConfig() { } return 0; } - -bool -MgmtSrvr::changeConfig(const BaseString §ion, - const BaseString ¶m, - const BaseString &value) { - if(m_newConfig == NULL) - return false; - return m_newConfig->change(section, param, value); -} diff --git a/storage/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp b/storage/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp index f93948abc75..c99936e1861 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp @@ -20,123 +20,3 @@ // Some kind of reuse should be preferred. //****************************************************************************** -#include "MgmtSrvr.hpp" -#include <NdbApiSignal.hpp> -#include <NdbTick.h> - - -NdbApiSignal* -MgmtSrvr::getSignal() -{ - NdbApiSignal* tSignal; - tSignal = theSignalIdleList; - if (tSignal != NULL){ - NdbApiSignal* tSignalNext = tSignal->next(); - tSignal->next(NULL); - theSignalIdleList = tSignalNext; - return tSignal; - } else - { - tSignal = new NdbApiSignal(_ownReference); - if (tSignal != NULL) - tSignal->next(NULL); - } - return tSignal; -} - - -void -MgmtSrvr::releaseSignal(NdbApiSignal* aSignal) -{ - aSignal->next(theSignalIdleList); - theSignalIdleList = aSignal; -} - - -void -MgmtSrvr::freeSignal() -{ - NdbApiSignal* tSignal = theSignalIdleList; - theSignalIdleList = tSignal->next(); - delete tSignal; -} - - -int -MgmtSrvr::sendSignal(Uint16 aNodeId, - WaitSignalType aWaitState, - NdbApiSignal* aSignal, - bool force) -{ - int tReturnCode; - theFacade->lock_mutex(); - if(force){ - tReturnCode = theFacade->sendSignalUnCond(aSignal, - aNodeId); - } else { - tReturnCode = theFacade->sendSignal(aSignal, - aNodeId); - } - releaseSignal(aSignal); - if (tReturnCode == -1) { - theFacade->unlock_mutex(); - return -1; - } - theWaitState = aWaitState; - theFacade->unlock_mutex(); - return 0; -} - - -int -MgmtSrvr::sendRecSignal(Uint16 aNodeId, - WaitSignalType aWaitState, - NdbApiSignal* aSignal, - bool force, - int waitTime) -{ - int tReturnCode; - theFacade->lock_mutex(); - if(force){ - tReturnCode = theFacade->sendSignalUnCond(aSignal, aNodeId); - } else { - tReturnCode = theFacade->sendSignalUnCond(aSignal, aNodeId); - } - releaseSignal(aSignal); - if (tReturnCode == -1) { - theFacade->unlock_mutex(); - return -1; - } - theWaitState = aWaitState; - theWaitNode = aNodeId; - return receiveOptimisedResponse(waitTime); -} - - -int -MgmtSrvr::receiveOptimisedResponse(int waitTime) -{ - int tResultCode; - theFacade->checkForceSend(_blockNumber); - NDB_TICKS maxTime = NdbTick_CurrentMillisecond() + waitTime; - - while (theWaitState != NO_WAIT && theWaitState != WAIT_NODEFAILURE - && waitTime > 0) { - NdbCondition_WaitTimeout(theMgmtWaitForResponseCondPtr, - theFacade->theMutexPtr, - waitTime); - if(theWaitState == NO_WAIT || theWaitState == WAIT_NODEFAILURE) - break; - waitTime = (maxTime - NdbTick_CurrentMillisecond()); - }//while - - if(theWaitState == NO_WAIT) { - tResultCode = 0; - } else { - tResultCode = -1; - } - theFacade->unlock_mutex(); - return tResultCode; -} - - diff --git a/storage/ndb/src/mgmsrv/Services.cpp b/storage/ndb/src/mgmsrv/Services.cpp index 3992796e304..e2a7c3d0c29 100644 --- a/storage/ndb/src/mgmsrv/Services.cpp +++ b/storage/ndb/src/mgmsrv/Services.cpp @@ -216,21 +216,6 @@ ParserRow<MgmApiSession> commands[] = { MGM_ARG("level", Int, Mandatory, "Severety level"), MGM_ARG("enable", Int, Mandatory, "1=disable, 0=enable, -1=toggle"), - MGM_CMD("config lock", &MgmApiSession::configLock, ""), - - MGM_CMD("config unlock", &MgmApiSession::configUnlock, ""), - MGM_ARG("commit", Int, Mandatory, "Commit changes"), - - MGM_CMD("config change", &MgmApiSession::configChange, ""), - MGM_ARG("section", String, Mandatory, "Section"), - MGM_ARG("parameter", String, Mandatory, "Parameter"), - MGM_ARG("value", String, Mandatory, "Value"), - - MGM_CMD("config lock", &MgmApiSession::configLock, ""), - - MGM_CMD("config unlock", &MgmApiSession::configUnlock, ""), - MGM_ARG("commit", Int, Mandatory, "Commit changes"), - MGM_CMD("set parameter", &MgmApiSession::setParameter, ""), MGM_ARG("node", String, Mandatory, "Node"), MGM_ARG("parameter", String, Mandatory, "Parameter"), @@ -910,8 +895,10 @@ printNodeStatus(OutputStream *output, nodeGroup = 0, connectCount = 0; bool system; - mgmsrv.status(nodeId, &status, &version, &startPhase, - &system, &dynamicId, &nodeGroup, &connectCount); + const char *address= NULL; + mgmsrv.status(nodeId, &status, &version, &startPhase, + &system, &dynamicId, &nodeGroup, &connectCount, + &address); output->println("node.%d.type: %s", nodeId, ndb_mgm_get_node_type_string(type)); @@ -923,7 +910,7 @@ printNodeStatus(OutputStream *output, output->println("node.%d.dynamic_id: %d", nodeId, dynamicId); output->println("node.%d.node_group: %d", nodeId, nodeGroup); output->println("node.%d.connect_count: %d", nodeId, connectCount); - output->println("node.%d.address: %s", nodeId, mgmsrv.get_connect_address(nodeId)); + output->println("node.%d.address: %s", nodeId, address ? address : ""); } } @@ -1192,42 +1179,6 @@ MgmApiSession::setLogFilter(Parser_t::Context &ctx, m_output->println(""); } -void -MgmApiSession::configLock(Parser_t::Context &, - Properties const &) { - int ret = m_mgmsrv.lockConf(); - m_output->println("config lock reply"); - m_output->println("result: %d", ret); - m_output->println(""); -} - -void -MgmApiSession::configUnlock(Parser_t::Context &, - Properties const &args) { - Uint32 commit; - args.get("commit", &commit); - int ret = m_mgmsrv.unlockConf(commit == 1); - m_output->println("config unlock reply"); - m_output->println("result: %d", ret); - m_output->println(""); -} - -void -MgmApiSession::configChange(Parser_t::Context &, - Properties const &args) { - BaseString section, param, value; - args.get("section", section); - args.get("parameter", param); - args.get("value", value); - - int ret = m_mgmsrv.changeConfig(section.c_str(), - param.c_str(), - value.c_str()); - m_output->println("config change reply"); - m_output->println("result: %d", ret); - m_output->println(""); -} - static NdbOut& operator<<(NdbOut& out, const LogLevel & ll) { diff --git a/storage/ndb/src/mgmsrv/Services.hpp b/storage/ndb/src/mgmsrv/Services.hpp index 7d5d8cb9c8c..8672010d66c 100644 --- a/storage/ndb/src/mgmsrv/Services.hpp +++ b/storage/ndb/src/mgmsrv/Services.hpp @@ -83,9 +83,6 @@ public: void setClusterLogLevel(Parser_t::Context &ctx, const class Properties &args); void setLogFilter(Parser_t::Context &ctx, const class Properties &args); - void configLock(Parser_t::Context &ctx, const class Properties &args); - void configUnlock(Parser_t::Context &ctx, const class Properties &args); - void configChange(Parser_t::Context &ctx, const class Properties &args); void setParameter(Parser_t::Context &ctx, const class Properties &args); void setConnectionParameter(Parser_t::Context &ctx, diff --git a/storage/ndb/src/mgmsrv/main.cpp b/storage/ndb/src/mgmsrv/main.cpp index ec20101493e..f0c2ac298a5 100644 --- a/storage/ndb/src/mgmsrv/main.cpp +++ b/storage/ndb/src/mgmsrv/main.cpp @@ -102,6 +102,7 @@ static int opt_daemon; // NOT bool, bool need not be int static int opt_non_interactive; static int opt_interactive; static const char * opt_config_filename= 0; +static int opt_mycnf = 0; struct MgmGlobals { MgmGlobals(); @@ -166,6 +167,10 @@ static struct my_option my_long_options[] = "Don't run as daemon, but don't read from stdin", (gptr*) &opt_non_interactive, (gptr*) &opt_non_interactive, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "mycnf", 256, + "Read cluster config from my.cnf", + (gptr*) &opt_mycnf, (gptr*) &opt_mycnf, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -199,7 +204,7 @@ int main(int argc, char** argv) #endif global_mgmt_server_check = 1; - + const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; load_defaults("my",load_default_groups,&argc,&argv); @@ -217,13 +222,26 @@ int main(int argc, char** argv) opt_daemon= 0; } + if (opt_mycnf && opt_config_filename) + { + ndbout_c("Both --mycnf and -f is not supported"); + return 0; + } + + if (opt_mycnf == 0 && opt_config_filename == 0) + { + struct stat buf; + if (stat("config.ini", &buf) != -1) + opt_config_filename = "config.ini"; + } + glob->socketServer = new SocketServer(); MgmApiService * mapi = new MgmApiService(); glob->mgmObject = new MgmtSrvr(glob->socketServer, - opt_config_filename, - opt_connect_str); + opt_config_filename, + opt_connect_str); if (g_print_full_config) goto the_end; diff --git a/storage/ndb/src/ndbapi/NdbApiSignal.cpp b/storage/ndb/src/ndbapi/NdbApiSignal.cpp index b1671e593e1..94695185224 100644 --- a/storage/ndb/src/ndbapi/NdbApiSignal.cpp +++ b/storage/ndb/src/ndbapi/NdbApiSignal.cpp @@ -62,6 +62,25 @@ NdbApiSignal::NdbApiSignal(BlockReference ref) theNextSignal = 0; } +NdbApiSignal::NdbApiSignal(Ndb* ndb) +{ + BlockReference ref = ndb->theMyRef; + theVerId_signalNumber = 0; // 4 bit ver id - 16 bit gsn + theReceiversBlockNumber = 0; // Only 16 bit blocknum + theSendersBlockRef = refToBlock(ref); + theLength = 0; + theSendersSignalId = 0; + theSignalId = 0; + theTrace = 0; + m_noOfSections = 0; + m_fragmentInfo = 0; + for (int i = 0; i < 25; i++) + theData[i] = 0x13579753; + + setDataPtr(&theData[0]); + theNextSignal = 0; +} + /** * Copy constructor */ diff --git a/storage/ndb/src/ndbapi/NdbApiSignal.hpp b/storage/ndb/src/ndbapi/NdbApiSignal.hpp index 353c575d420..9d04a8594a8 100644 --- a/storage/ndb/src/ndbapi/NdbApiSignal.hpp +++ b/storage/ndb/src/ndbapi/NdbApiSignal.hpp @@ -46,7 +46,8 @@ class NdbApiSignal : public SignalHeader { public: - NdbApiSignal(BlockReference myRef); + NdbApiSignal(Ndb* ndb); + NdbApiSignal(BlockReference ref); NdbApiSignal(const NdbApiSignal &); NdbApiSignal(const SignalHeader &header) : SignalHeader(header), theNextSignal(0), theRealData(0) {}; diff --git a/storage/ndb/src/ndbapi/NdbBlob.cpp b/storage/ndb/src/ndbapi/NdbBlob.cpp index 77ab87ce5c1..28d657f3fe9 100644 --- a/storage/ndb/src/ndbapi/NdbBlob.cpp +++ b/storage/ndb/src/ndbapi/NdbBlob.cpp @@ -141,7 +141,7 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm // initialization -NdbBlob::NdbBlob() +NdbBlob::NdbBlob(Ndb*) { init(); } diff --git a/storage/ndb/src/ndbapi/NdbImpl.hpp b/storage/ndb/src/ndbapi/NdbImpl.hpp index 5e630b54d68..30e0d28a765 100644 --- a/storage/ndb/src/ndbapi/NdbImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbImpl.hpp @@ -32,6 +32,21 @@ #include "NdbDictionaryImpl.hpp" #include "ObjectMap.hpp" +template <class T> +struct Ndb_free_list_t +{ + Ndb_free_list_t(); + ~Ndb_free_list_t(); + + void fill(Ndb*, Uint32 cnt); + T* seize(Ndb*); + void release(T*); + void clear(); + Uint32 get_sizeof() const { return sizeof(T); } + T * m_free_list; + Uint32 m_alloc_cnt, m_free_cnt; +}; + /** * Private parts of the Ndb object (corresponding to Ndb.hpp in public API) */ @@ -66,7 +81,6 @@ public: int m_optimized_node_selection; - BaseString m_dbname; // Database name BaseString m_schemaname; // Schema name @@ -78,6 +92,22 @@ public: m_schemaname.c_str(), table_name_separator); } + /** + * NOTE free lists must be _after_ theNdbObjectIdMap take + * assure that destructors are run in correct order + */ + Ndb_free_list_t<NdbTransaction> theConIdleList; + Ndb_free_list_t<NdbOperation> theOpIdleList; + Ndb_free_list_t<NdbIndexScanOperation> theScanOpIdleList; + Ndb_free_list_t<NdbIndexOperation> theIndexOpIdleList; + Ndb_free_list_t<NdbRecAttr> theRecAttrIdleList; + Ndb_free_list_t<NdbApiSignal> theSignalIdleList; + Ndb_free_list_t<NdbLabel> theLabelList; + Ndb_free_list_t<NdbBranch> theBranchList; + Ndb_free_list_t<NdbSubroutine> theSubroutineList; + Ndb_free_list_t<NdbCall> theCallList; + Ndb_free_list_t<NdbBlob> theNdbBlobIdleList; + Ndb_free_list_t<NdbReceiver> theScanList; }; #ifdef VM_TRACE @@ -152,4 +182,91 @@ enum LockMode { Delete }; +template<class T> +inline +Ndb_free_list_t<T>::Ndb_free_list_t() +{ + m_free_list= 0; + m_alloc_cnt= m_free_cnt= 0; +} + +template<class T> +inline +Ndb_free_list_t<T>::~Ndb_free_list_t() +{ + clear(); +} + +template<class T> +inline +void +Ndb_free_list_t<T>::fill(Ndb* ndb, Uint32 cnt) +{ + if (m_free_list == 0) + { + m_free_cnt++; + m_alloc_cnt++; + m_free_list = new T(ndb); + } + while(m_alloc_cnt < cnt) + { + T* obj= new T(ndb); + if(obj == 0) + return; + + obj->next(m_free_list); + m_free_cnt++; + m_alloc_cnt++; + m_free_list = obj; + } +} + +template<class T> +inline +T* +Ndb_free_list_t<T>::seize(Ndb* ndb) +{ + T* tmp = m_free_list; + if (tmp) + { + m_free_list = (T*)tmp->next(); + tmp->next(NULL); + m_free_cnt--; + return tmp; + } + + if((tmp = new T(ndb))) + { + m_alloc_cnt++; + } + + return tmp; +} + +template<class T> +inline +void +Ndb_free_list_t<T>::release(T* obj) +{ + obj->next(m_free_list); + m_free_list = obj; + m_free_cnt++; +} + + +template<class T> +inline +void +Ndb_free_list_t<T>::clear() +{ + T* obj = m_free_list; + while(obj) + { + T* curr = obj; + obj = (T*)obj->next(); + delete curr; + m_alloc_cnt--; + } +} + #endif diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp index 5e5306fc33a..5201c6c9c04 100644 --- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp @@ -22,7 +22,7 @@ #include "NdbDictionaryImpl.hpp" #include <NdbTCP.h> -NdbRecAttr::NdbRecAttr() +NdbRecAttr::NdbRecAttr(Ndb*) { init(); } @@ -98,7 +98,7 @@ NdbRecAttr::copyout() NdbRecAttr * NdbRecAttr::clone() const { - NdbRecAttr * ret = new NdbRecAttr(); + NdbRecAttr * ret = new NdbRecAttr(0); ret->theAttrId = theAttrId; ret->theNULLind = theNULLind; diff --git a/storage/ndb/src/ndbapi/NdbUtil.cpp b/storage/ndb/src/ndbapi/NdbUtil.cpp index 5c74d251ff9..6019ea675a1 100644 --- a/storage/ndb/src/ndbapi/NdbUtil.cpp +++ b/storage/ndb/src/ndbapi/NdbUtil.cpp @@ -30,8 +30,7 @@ Comment: #include "NdbUtil.hpp" -NdbLabel::NdbLabel() : - theNext(NULL) +NdbLabel::NdbLabel(Ndb*) { } @@ -39,8 +38,7 @@ NdbLabel::~NdbLabel() { } -NdbSubroutine::NdbSubroutine() : - theNext(NULL) +NdbSubroutine::NdbSubroutine(Ndb*) { } @@ -48,9 +46,8 @@ NdbSubroutine::~NdbSubroutine() { } -NdbBranch::NdbBranch() : - theSignal(NULL), - theNext(NULL) +NdbBranch::NdbBranch(Ndb*) : + theSignal(NULL) { } @@ -58,9 +55,8 @@ NdbBranch::~NdbBranch() { } -NdbCall::NdbCall() : - theSignal(NULL), - theNext(NULL) +NdbCall::NdbCall(Ndb*) : + theSignal(NULL) { } diff --git a/storage/ndb/src/ndbapi/NdbUtil.hpp b/storage/ndb/src/ndbapi/NdbUtil.hpp index 80fc15ddd8c..268f6c69e6f 100644 --- a/storage/ndb/src/ndbapi/NdbUtil.hpp +++ b/storage/ndb/src/ndbapi/NdbUtil.hpp @@ -31,44 +31,53 @@ Comment: #include <ndb_global.h> +class Ndb; class NdbApiSignal; class NdbOperation; -class NdbLabel +template<class T> +struct Free_list_element +{ + Free_list_element() { theNext = 0;} + void next(T* obj) { theNext = obj;} + T* next() { return theNext;} + + T* theNext; +}; + +class NdbLabel : public Free_list_element<NdbLabel> { friend class NdbOperation; friend class Ndb; - -private: - NdbLabel(); +public: + NdbLabel(Ndb*); ~NdbLabel(); - NdbLabel* theNext; +private: Uint32 theSubroutine[16]; Uint32 theLabelAddress[16]; Uint32 theLabelNo[16]; }; -class NdbSubroutine +class NdbSubroutine : public Free_list_element<NdbSubroutine> { friend class NdbOperation; friend class Ndb; -private: - NdbSubroutine(); +public: + NdbSubroutine(Ndb*); ~NdbSubroutine(); - NdbSubroutine* theNext; Uint32 theSubroutineAddress[16]; }; -class NdbBranch +class NdbBranch : public Free_list_element<NdbBranch> { friend class NdbOperation; friend class Ndb; -private: - NdbBranch(); +public: + NdbBranch(Ndb*); ~NdbBranch(); NdbApiSignal* theSignal; @@ -76,22 +85,20 @@ private: Uint32 theBranchAddress; Uint32 theBranchLabel; Uint32 theSubroutine; - NdbBranch* theNext; }; -class NdbCall +class NdbCall : public Free_list_element<NdbCall> { friend class NdbOperation; friend class Ndb; -private: - NdbCall(); +public: + NdbCall(Ndb*); ~NdbCall(); NdbApiSignal* theSignal; Uint32 theSignalAddress; Uint32 theSubroutine; - NdbCall* theNext; }; #endif diff --git a/storage/ndb/src/ndbapi/Ndbif.cpp b/storage/ndb/src/ndbapi/Ndbif.cpp index 48608345acd..d68248e6981 100644 --- a/storage/ndb/src/ndbapi/Ndbif.cpp +++ b/storage/ndb/src/ndbapi/Ndbif.cpp @@ -146,15 +146,6 @@ Ndb::init(int aMaxNoOfTransactions) error_handler: ndbout << "error_handler" << endl; releaseTransactionArrays(); - while ( theConIdleList != NULL ) - freeNdbCon(); - while ( theSignalIdleList != NULL ) - freeSignal(); - while (theRecAttrIdleList != NULL) - freeRecAttr(); - while (theOpIdleList != NULL) - freeOperation(); - delete theDictionary; TransporterFacade::instance()->close(theNdbBlockNumber, 0); DBUG_RETURN(-1); diff --git a/storage/ndb/src/ndbapi/Ndbinit.cpp b/storage/ndb/src/ndbapi/Ndbinit.cpp index a742f571a81..bb77a69937b 100644 --- a/storage/ndb/src/ndbapi/Ndbinit.cpp +++ b/storage/ndb/src/ndbapi/Ndbinit.cpp @@ -29,6 +29,10 @@ #include <NdbOut.hpp> #include <NdbSleep.h> #include "ObjectMap.hpp" +#include <NdbIndexScanOperation.hpp> +#include <NdbIndexOperation.hpp> +#include "NdbUtil.hpp" +#include <NdbBlob.hpp> #include "NdbEventOperationImpl.hpp" #include <EventLogger.hpp> @@ -62,20 +66,8 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection, theRemainingStartTransactions= 0; theMaxNoOfTransactions= 0; theMinNoOfEventsToWakeUp= 0; - theConIdleList= NULL; - theOpIdleList= NULL; - theScanOpIdleList= NULL; - theIndexOpIdleList= NULL; theTransactionList= NULL; theConnectionArray= NULL; - theRecAttrIdleList= NULL; - theSignalIdleList= NULL; - theLabelList= NULL; - theBranchList= NULL; - theSubroutineList= NULL; - theCallList= NULL; - theScanList= NULL; - theNdbBlobIdleList= NULL; the_last_check_time= 0; theFirstTransId= 0; theRestartGCI= 0; @@ -160,33 +152,6 @@ Ndb::~Ndb() TransporterFacade::instance()->close(theNdbBlockNumber, theFirstTransId); } -// if (theSchemaConToNdbList != NULL) -// closeSchemaTransaction(theSchemaConToNdbList); - while ( theConIdleList != NULL ) - freeNdbCon(); - while (theOpIdleList != NULL) - freeOperation(); - while (theScanOpIdleList != NULL) - freeScanOperation(); - while (theIndexOpIdleList != NULL) - freeIndexOperation(); - while (theLabelList != NULL) - freeNdbLabel(); - while (theBranchList != NULL) - freeNdbBranch(); - while (theSubroutineList != NULL) - freeNdbSubroutine(); - while (theCallList != NULL) - freeNdbCall(); - while (theScanList != NULL) - freeNdbScanRec(); - while (theNdbBlobIdleList != NULL) - freeNdbBlob(); - while (theRecAttrIdleList != NULL) - freeRecAttr(); - while ( theSignalIdleList != NULL ) - freeSignal(); - releaseTransactionArrays(); delete []theConnectionArray; @@ -242,7 +207,8 @@ NdbImpl::NdbImpl(Ndb_cluster_connection *ndb_cluster_connection, m_ndb_cluster_connection(ndb_cluster_connection->m_impl), m_dictionary(ndb), theCurrentConnectIndex(0), - theNdbObjectIdMap(1024,1024), + theNdbObjectIdMap(ndb_cluster_connection->m_impl.m_transporter_facade->theMutexPtr, + 1024,1024), theNoOfDBnodes(0), m_ev_op(0) { diff --git a/storage/ndb/src/ndbapi/Ndblist.cpp b/storage/ndb/src/ndbapi/Ndblist.cpp index 96d0f4d7de5..f82348fc91d 100644 --- a/storage/ndb/src/ndbapi/Ndblist.cpp +++ b/storage/ndb/src/ndbapi/Ndblist.cpp @@ -75,24 +75,7 @@ Ndb::checkFailedNode() int Ndb::createConIdleList(int aNrOfCon) { - for (int i = 0; i < aNrOfCon; i++) - { - NdbTransaction* tNdbCon = new NdbTransaction(this); - if (tNdbCon == NULL) - { - return -1; - } - if (theConIdleList == NULL) - { - theConIdleList = tNdbCon; - theConIdleList->next(NULL); - } else - { - tNdbCon->next(theConIdleList); - theConIdleList = tNdbCon; - } - tNdbCon->Status(NdbTransaction::NotConnected); - } + theImpl->theConIdleList.fill(this, aNrOfCon); return aNrOfCon; } @@ -108,19 +91,7 @@ Ndb::createConIdleList(int aNrOfCon) int Ndb::createOpIdleList(int aNrOfOp) { - for (int i = 0; i < aNrOfOp; i++){ - NdbOperation* tOp = new NdbOperation(this); - if ( tOp == NULL ){ - return -1; - } - if (theOpIdleList == NULL){ - theOpIdleList = tOp; - theOpIdleList->next(NULL); - } else{ - tOp->next(theOpIdleList); - theOpIdleList = tOp; - } - } + theImpl->theOpIdleList.fill(this, aNrOfOp); return aNrOfOp; } @@ -134,22 +105,7 @@ Ndb::createOpIdleList(int aNrOfOp) NdbBranch* Ndb::getNdbBranch() { - NdbBranch* tNdbBranch; - if ( theBranchList == NULL ) - { - tNdbBranch = new NdbBranch; - if (tNdbBranch == NULL) - { - return NULL; - } - tNdbBranch->theNext = NULL; - } else - { - tNdbBranch = theBranchList; - theBranchList = tNdbBranch->theNext; - tNdbBranch->theNext = NULL; - } - return tNdbBranch; + return theImpl->theBranchList.seize(this); } /*************************************************************************** @@ -162,22 +118,7 @@ Ndb::getNdbBranch() NdbCall* Ndb::getNdbCall() { - NdbCall* tNdbCall; - if ( theCallList == NULL ) - { - tNdbCall = new NdbCall; - if (tNdbCall == NULL) - { - return NULL; - } - tNdbCall->theNext = NULL; - } else - { - tNdbCall = theCallList; - theCallList = tNdbCall->theNext; - tNdbCall->theNext = NULL; - } - return tNdbCall; + return theImpl->theCallList.seize(this); } /*************************************************************************** @@ -190,19 +131,7 @@ Ndb::getNdbCall() NdbTransaction* Ndb::getNdbCon() { - NdbTransaction* tNdbCon; - if ( theConIdleList == NULL ) { - tNdbCon = new NdbTransaction(this); - if (tNdbCon == NULL) { - return NULL; - }//if - tNdbCon->next(NULL); - } else - { - tNdbCon = theConIdleList; - theConIdleList = tNdbCon->next(); - tNdbCon->next(NULL); - } + NdbTransaction* tNdbCon = theImpl->theConIdleList.seize(this); tNdbCon->theMagicNumber = 0x37412619; return tNdbCon; } @@ -217,22 +146,7 @@ Ndb::getNdbCon() NdbLabel* Ndb::getNdbLabel() { - NdbLabel* tNdbLabel; - if ( theLabelList == NULL ) - { - tNdbLabel = new NdbLabel; - if (tNdbLabel == NULL) - { - return NULL; - } - tNdbLabel->theNext = NULL; - } else - { - tNdbLabel = theLabelList; - theLabelList = tNdbLabel->theNext; - tNdbLabel->theNext = NULL; - } - return tNdbLabel; + return theImpl->theLabelList.seize(this); } /*************************************************************************** @@ -246,23 +160,7 @@ Ndb::getNdbLabel() NdbReceiver* Ndb::getNdbScanRec() { - NdbReceiver* tNdbScanRec; - if ( theScanList == NULL ) - { - tNdbScanRec = new NdbReceiver(this); - if (tNdbScanRec == NULL) - { - return NULL; - } - tNdbScanRec->next(NULL); - } else - { - tNdbScanRec = theScanList; - theScanList = tNdbScanRec->next(); - tNdbScanRec->next(NULL); - } - - return tNdbScanRec; + return theImpl->theScanList.seize(this); } /*************************************************************************** @@ -275,22 +173,7 @@ Ndb::getNdbScanRec() NdbSubroutine* Ndb::getNdbSubroutine() { - NdbSubroutine* tNdbSubroutine; - if ( theSubroutineList == NULL ) - { - tNdbSubroutine = new NdbSubroutine; - if (tNdbSubroutine == NULL) - { - return NULL; - } - tNdbSubroutine->theNext = NULL; - } else - { - tNdbSubroutine = theSubroutineList; - theSubroutineList = tNdbSubroutine->theNext; - tNdbSubroutine->theNext = NULL; - } - return tNdbSubroutine; + return theImpl->theSubroutineList.seize(this); } /*************************************************************************** @@ -303,18 +186,7 @@ Remark: Get an operation from theOpIdleList and return the object . NdbOperation* Ndb::getOperation() { - NdbOperation* tOp = theOpIdleList; - if (tOp != NULL ) { - NdbOperation* tOpNext = tOp->next(); - tOp->next(NULL); - theOpIdleList = tOpNext; - return tOp; - } else { - tOp = new NdbOperation(this); - if (tOp != NULL) - tOp->next(NULL); - } - return tOp; + return theImpl->theOpIdleList.seize(this); } /*************************************************************************** @@ -327,18 +199,7 @@ Remark: Get an operation from theScanOpIdleList and return the object . NdbIndexScanOperation* Ndb::getScanOperation() { - NdbIndexScanOperation* tOp = theScanOpIdleList; - if (tOp != NULL ) { - NdbIndexScanOperation* tOpNext = (NdbIndexScanOperation*)tOp->next(); - tOp->next(NULL); - theScanOpIdleList = tOpNext; - return tOp; - } else { - tOp = new NdbIndexScanOperation(this); - if (tOp != NULL) - tOp->next(NULL); - } - return tOp; + return theImpl->theScanOpIdleList.seize(this); } /*************************************************************************** @@ -351,18 +212,7 @@ Remark: Get an operation from theIndexOpIdleList and return the object . NdbIndexOperation* Ndb::getIndexOperation() { - NdbIndexOperation* tOp = theIndexOpIdleList; - if (tOp != NULL ) { - NdbIndexOperation* tOpNext = (NdbIndexOperation*) tOp->next(); - tOp->next(NULL); - theIndexOpIdleList = tOpNext; - return tOp; - } else { - tOp = new NdbIndexOperation(this); - if (tOp != NULL) - tOp->next(NULL); - } - return tOp; + return theImpl->theIndexOpIdleList.seize(this); } /*************************************************************************** @@ -374,21 +224,14 @@ Return Value: Return a reference to a receive attribute object. NdbRecAttr* Ndb::getRecAttr() { - NdbRecAttr* tRecAttr; - tRecAttr = theRecAttrIdleList; - if (tRecAttr != NULL) { - NdbRecAttr* tRecAttrNext = tRecAttr->next(); + NdbRecAttr* tRecAttr = theImpl->theRecAttrIdleList.seize(this); + if (tRecAttr != NULL) + { tRecAttr->init(); - theRecAttrIdleList = tRecAttrNext; return tRecAttr; - } else { - tRecAttr = new NdbRecAttr; - if (tRecAttr == NULL) - return NULL; - tRecAttr->next(NULL); - }//if - tRecAttr->init(); - return tRecAttr; + } + + return NULL; } /*************************************************************************** @@ -400,34 +243,16 @@ Return Value: Return a reference to a signal object. NdbApiSignal* Ndb::getSignal() { - NdbApiSignal* tSignal = theSignalIdleList; - if (tSignal != NULL){ - NdbApiSignal* tSignalNext = tSignal->next(); - tSignal->next(NULL); - theSignalIdleList = tSignalNext; - } else { - tSignal = new NdbApiSignal(theMyRef); -#ifdef POORMANSPURIFY - cnewSignals++; -#endif - if (tSignal != NULL) - tSignal->next(NULL); - } -#ifdef POORMANSPURIFY - cgetSignals++; -#endif - return tSignal; + return theImpl->theSignalIdleList.seize(this); } NdbBlob* Ndb::getNdbBlob() { - NdbBlob* tBlob = theNdbBlobIdleList; - if (tBlob != NULL) { - theNdbBlobIdleList = tBlob->theNext; + NdbBlob* tBlob = theImpl->theNdbBlobIdleList.seize(this); + if(tBlob) + { tBlob->init(); - } else { - tBlob = new NdbBlob; } return tBlob; } @@ -441,8 +266,7 @@ Remark: Add a NdbBranch object into the Branch idlelist. void Ndb::releaseNdbBranch(NdbBranch* aNdbBranch) { - aNdbBranch->theNext = theBranchList; - theBranchList = aNdbBranch; + theImpl->theBranchList.release(aNdbBranch); } /*************************************************************************** @@ -454,8 +278,7 @@ Remark: Add a NdbBranch object into the Branch idlelist. void Ndb::releaseNdbCall(NdbCall* aNdbCall) { - aNdbCall->theNext = theCallList; - theCallList = aNdbCall; + theImpl->theCallList.release(aNdbCall); } /*************************************************************************** @@ -467,9 +290,8 @@ Remark: Add a Connection object into the signal idlelist. void Ndb::releaseNdbCon(NdbTransaction* aNdbCon) { - aNdbCon->next(theConIdleList); aNdbCon->theMagicNumber = 0xFE11DD; - theConIdleList = aNdbCon; + theImpl->theConIdleList.release(aNdbCon); } /*************************************************************************** @@ -481,8 +303,7 @@ Remark: Add a NdbLabel object into the Label idlelist. void Ndb::releaseNdbLabel(NdbLabel* aNdbLabel) { - aNdbLabel->theNext = theLabelList; - theLabelList = aNdbLabel; + theImpl->theLabelList.release(aNdbLabel); } /*************************************************************************** @@ -494,8 +315,7 @@ Remark: Add a NdbScanReceiver object into the Scan idlelist. void Ndb::releaseNdbScanRec(NdbReceiver* aNdbScanRec) { - aNdbScanRec->next(theScanList); - theScanList = aNdbScanRec; + theImpl->theScanList.release(aNdbScanRec); } /*************************************************************************** @@ -507,8 +327,7 @@ Remark: Add a NdbSubroutine object into theSubroutine idlelist. void Ndb::releaseNdbSubroutine(NdbSubroutine* aNdbSubroutine) { - aNdbSubroutine->theNext = theSubroutineList; - theSubroutineList = aNdbSubroutine; + theImpl->theSubroutineList.release(aNdbSubroutine); } /*************************************************************************** @@ -521,16 +340,14 @@ void Ndb::releaseOperation(NdbOperation* anOperation) { if(anOperation->m_tcReqGSN == GSN_TCKEYREQ){ - anOperation->next(theOpIdleList); anOperation->theNdbCon = NULL; anOperation->theMagicNumber = 0xFE11D0; - theOpIdleList = anOperation; + theImpl->theOpIdleList.release(anOperation); } else { assert(anOperation->m_tcReqGSN == GSN_TCINDXREQ); - anOperation->next(theIndexOpIdleList); anOperation->theNdbCon = NULL; anOperation->theMagicNumber = 0xFE11D1; - theIndexOpIdleList = (NdbIndexOperation*)anOperation; + theImpl->theIndexOpIdleList.release((NdbIndexOperation*)anOperation); } } @@ -553,10 +370,9 @@ Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation) } } #endif - aScanOperation->next(theScanOpIdleList); aScanOperation->theNdbCon = NULL; aScanOperation->theMagicNumber = 0xFE11D2; - theScanOpIdleList = aScanOperation; + theImpl->theScanOpIdleList.release(aScanOperation); DBUG_VOID_RETURN; } @@ -570,8 +386,7 @@ void Ndb::releaseRecAttr(NdbRecAttr* aRecAttr) { aRecAttr->release(); - aRecAttr->next(theRecAttrIdleList); - theRecAttrIdleList = aRecAttr; + theImpl->theRecAttrIdleList.release(aRecAttr); } /*************************************************************************** @@ -598,8 +413,7 @@ Ndb::releaseSignal(NdbApiSignal* aSignal) #ifdef POORMANSPURIFY creleaseSignals++; #endif - aSignal->next(theSignalIdleList); - theSignalIdleList = aSignal; + theImpl->theSignalIdleList.release(aSignal); } void @@ -616,162 +430,7 @@ void Ndb::releaseNdbBlob(NdbBlob* aBlob) { aBlob->release(); - aBlob->theNext = theNdbBlobIdleList; - theNdbBlobIdleList = aBlob; -} - -/*************************************************************************** -void freeOperation(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeOperation() -{ - NdbOperation* tOp = theOpIdleList; - theOpIdleList = theOpIdleList->next(); - delete tOp; -} - -/*************************************************************************** -void freeScanOperation(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeScanOperation() -{ - NdbIndexScanOperation* tOp = theScanOpIdleList; - theScanOpIdleList = (NdbIndexScanOperation *)tOp->next(); - delete tOp; -} - -/*************************************************************************** -void freeIndexOperation(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeIndexOperation() -{ - NdbIndexOperation* tOp = theIndexOpIdleList; - theIndexOpIdleList = (NdbIndexOperation *) theIndexOpIdleList->next(); - delete tOp; -} - -/*************************************************************************** -void freeNdbBranch(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeNdbBranch() -{ - NdbBranch* tNdbBranch = theBranchList; - theBranchList = theBranchList->theNext; - delete tNdbBranch; -} - -/*************************************************************************** -void freeNdbCall(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeNdbCall() -{ - NdbCall* tNdbCall = theCallList; - theCallList = theCallList->theNext; - delete tNdbCall; -} - -/*************************************************************************** -void freeNdbScanRec(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeNdbScanRec() -{ - NdbReceiver* tNdbScanRec = theScanList; - theScanList = theScanList->next(); - delete tNdbScanRec; -} - -/*************************************************************************** -void freeNdbCon(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeNdbCon() -{ - NdbTransaction* tNdbCon = theConIdleList; - theConIdleList = theConIdleList->next(); - delete tNdbCon; -} - -/*************************************************************************** -void freeNdbLabel(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeNdbLabel() -{ - NdbLabel* tNdbLabel = theLabelList; - theLabelList = theLabelList->theNext; - delete tNdbLabel; -} - -/*************************************************************************** -void freeNdbSubroutine(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeNdbSubroutine() -{ - NdbSubroutine* tNdbSubroutine = theSubroutineList; - theSubroutineList = theSubroutineList->theNext; - delete tNdbSubroutine; -} - -/*************************************************************************** -void freeRecAttr(); - -Remark: Always release the first item in the free list -***************************************************************************/ -void -Ndb::freeRecAttr() -{ - NdbRecAttr* tRecAttr = theRecAttrIdleList; - theRecAttrIdleList = theRecAttrIdleList->next(); - delete tRecAttr; -} - -/*************************************************************************** -void freeSignal(); - -Remark: Delete a signal object from the signal idlelist. -***************************************************************************/ -void -Ndb::freeSignal() -{ - NdbApiSignal* tSignal = theSignalIdleList; - theSignalIdleList = tSignal->next(); - delete tSignal; -#ifdef POORMANSPURIFY - cfreeSignals++; -#endif -} - -void -Ndb::freeNdbBlob() -{ - NdbBlob* tBlob = theNdbBlobIdleList; - theNdbBlobIdleList = tBlob->theNext; - delete tBlob; + theImpl->theNdbBlobIdleList.release(aBlob); } /**************************************************************************** @@ -826,3 +485,102 @@ Ndb::releaseConnectToNdb(NdbTransaction* a_con) DBUG_VOID_RETURN; } +template<class T> +static +Ndb::Free_list_usage* +update(Ndb::Free_list_usage* curr, + Ndb_free_list_t<T> & list, + const char * name) +{ + curr->m_name = name; + curr->m_created = list.m_alloc_cnt; + curr->m_free = list.m_free_cnt; + curr->m_sizeof = sizeof(T); + return curr; +} + +Ndb::Free_list_usage* +Ndb::get_free_list_usage(Ndb::Free_list_usage* curr) +{ + if (curr == 0) + { + return 0; + } + + if(curr->m_name == 0) + { + update(curr, theImpl->theConIdleList, "NdbTransaction"); + } + else if(!strcmp(curr->m_name, "NdbTransaction")) + { + update(curr, theImpl->theOpIdleList, "NdbOperation"); + } + else if(!strcmp(curr->m_name, "NdbOperation")) + { + update(curr, theImpl->theScanOpIdleList, "NdbIndexScanOperation"); + } + else if(!strcmp(curr->m_name, "NdbIndexScanOperation")) + { + update(curr, theImpl->theIndexOpIdleList, "NdbIndexOperation"); + } + else if(!strcmp(curr->m_name, "NdbIndexOperation")) + { + update(curr, theImpl->theRecAttrIdleList, "NdbRecAttr"); + } + else if(!strcmp(curr->m_name, "NdbRecAttr")) + { + update(curr, theImpl->theSignalIdleList, "NdbApiSignal"); + } + else if(!strcmp(curr->m_name, "NdbApiSignal")) + { + update(curr, theImpl->theLabelList, "NdbLabel"); + } + else if(!strcmp(curr->m_name, "NdbLabel")) + { + update(curr, theImpl->theBranchList, "NdbBranch"); + } + else if(!strcmp(curr->m_name, "NdbBranch")) + { + update(curr, theImpl->theSubroutineList, "NdbSubroutine"); + } + else if(!strcmp(curr->m_name, "NdbSubroutine")) + { + update(curr, theImpl->theCallList, "NdbCall"); + } + else if(!strcmp(curr->m_name, "NdbCall")) + { + update(curr, theImpl->theNdbBlobIdleList, "NdbBlob"); + } + else if(!strcmp(curr->m_name, "NdbBlob")) + { + update(curr, theImpl->theScanList, "NdbReceiver"); + } + else if(!strcmp(curr->m_name, "NdbReceiver")) + { + return 0; + } + else + { + update(curr, theImpl->theConIdleList, "NdbTransaction"); + } + + return curr; +} + +#define TI(T) \ + template Ndb::Free_list_usage* \ + update(Ndb::Free_list_usage*, Ndb_free_list_t<T> &, const char * name);\ + template struct Ndb_free_list_t<T> + +TI(NdbBlob); +TI(NdbCall); +TI(NdbLabel); +TI(NdbBranch); +TI(NdbSubroutine); +TI(NdbApiSignal); +TI(NdbRecAttr); +TI(NdbOperation); +TI(NdbReceiver); +TI(NdbConnection); +TI(NdbIndexOperation); +TI(NdbIndexScanOperation); diff --git a/storage/ndb/src/ndbapi/ObjectMap.hpp b/storage/ndb/src/ndbapi/ObjectMap.hpp index dc2a5046f77..e3db479f677 100644 --- a/storage/ndb/src/ndbapi/ObjectMap.hpp +++ b/storage/ndb/src/ndbapi/ObjectMap.hpp @@ -30,7 +30,7 @@ class NdbObjectIdMap //: NdbLockable { public: STATIC_CONST( InvalidId = ~(Uint32)0 ); - NdbObjectIdMap(Uint32 initalSize = 128, Uint32 expandSize = 10); + NdbObjectIdMap(NdbMutex*, Uint32 initalSize = 128, Uint32 expandSize = 10); ~NdbObjectIdMap(); Uint32 map(void * object); @@ -46,14 +46,16 @@ private: void * m_obj; } * m_map; + NdbMutex * m_mutex; void expand(Uint32 newSize); }; inline -NdbObjectIdMap::NdbObjectIdMap(Uint32 sz, Uint32 eSz) { +NdbObjectIdMap::NdbObjectIdMap(NdbMutex* mutex, Uint32 sz, Uint32 eSz) { m_size = 0; m_firstFree = InvalidId; m_map = 0; + m_mutex = mutex; m_expandSize = eSz; expand(sz); #ifdef DEBUG_OBJECTMAP @@ -126,21 +128,26 @@ NdbObjectIdMap::getObject(Uint32 id){ inline void NdbObjectIdMap::expand(Uint32 incSize){ + NdbMutex_Lock(m_mutex); Uint32 newSize = m_size + incSize; - MapEntry * tmp = (MapEntry*)malloc(newSize * sizeof(MapEntry)); + MapEntry * tmp = (MapEntry*)realloc(m_map, newSize * sizeof(MapEntry)); - if (m_map) { - memcpy(tmp, m_map, m_size * sizeof(MapEntry)); - free((void*)m_map); + if (likely(tmp != 0)) + { + m_map = tmp; + + for(Uint32 i = m_size; i<newSize; i++){ + m_map[i].m_next = i + 1; + } + m_firstFree = m_size; + m_map[newSize-1].m_next = InvalidId; + m_size = newSize; } - m_map = tmp; - - for(Uint32 i = m_size; i<newSize; i++){ - m_map[i].m_next = i + 1; + else + { + ndbout_c("NdbObjectIdMap::expand unable to expand!!"); } - m_firstFree = m_size; - m_map[newSize-1].m_next = InvalidId; - m_size = newSize; + NdbMutex_Unlock(m_mutex); } #endif diff --git a/storage/ndb/tools/ndb_condig.cpp b/storage/ndb/tools/ndb_condig.cpp index 725249a5af5..1b9a771f243 100644 --- a/storage/ndb/tools/ndb_condig.cpp +++ b/storage/ndb/tools/ndb_condig.cpp @@ -23,6 +23,8 @@ #include <my_getopt.h> #include <mysql_version.h> +#include <netdb.h> + #include <NdbOut.hpp> #include <mgmapi.h> #include <mgmapi_configuration.hpp> @@ -40,6 +42,8 @@ static const char * g_type = 0; static const char * g_host = 0; static const char * g_field_delimiter=","; static const char * g_row_delimiter=" "; +static const char * g_config_file = 0; +static int g_mycnf = 0; int g_print_full_config, opt_ndb_shm; my_bool opt_core; @@ -90,6 +94,12 @@ static struct my_option my_long_options[] = { "rows", 'r', "Row separator", (gptr*) &g_row_delimiter, (gptr*) &g_row_delimiter, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "config-file", 256, "Path to config.ini", + (gptr*) &g_config_file, (gptr*) &g_config_file, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "mycnf", 256, "Read config from my.cnf", + (gptr*) &g_mycnf, (gptr*) &g_mycnf, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -124,6 +134,11 @@ struct Match { int m_key; BaseString m_value; + virtual int eval(const Iter&); +}; + +struct HostMatch : public Match +{ virtual int eval(NdbMgmHandle, const Iter&); }; @@ -132,18 +147,21 @@ struct Apply Apply() {} Apply(int val) { m_key = val;} int m_key; - virtual int apply(NdbMgmHandle, const Iter&); + virtual int apply(const Iter&); }; struct NodeTypeApply : public Apply { - virtual int apply(NdbMgmHandle, const Iter&); + virtual int apply(const Iter&); }; static int parse_query(Vector<Apply*>&, int &argc, char**& argv); static int parse_where(Vector<Match*>&, int &argc, char**& argv); -static int eval(NdbMgmHandle, const Iter&, const Vector<Match*>&); -static int apply(NdbMgmHandle, const Iter&, const Vector<Apply*>&); +static int eval(const Iter&, const Vector<Match*>&); +static int apply(const Iter&, const Vector<Apply*>&); +static ndb_mgm_configuration* fetch_configuration(); +static ndb_mgm_configuration* load_configuration(); + int main(int argc, char** argv){ NDB_INIT(argv[0]); @@ -154,51 +172,16 @@ main(int argc, char** argv){ ndb_std_get_one_option))) return -1; - NdbMgmHandle mgm = ndb_mgm_create_handle(); - if(mgm == NULL) { - fprintf(stderr, "Cannot create handle to management server.\n"); - exit(-1); - } + ndb_mgm_configuration * conf = 0; - ndb_mgm_set_error_stream(mgm, stderr); - - if (ndb_mgm_set_connectstring(mgm, g_connectstring)) - { - fprintf(stderr, "* %5d: %s\n", - ndb_mgm_get_latest_error(mgm), - ndb_mgm_get_latest_error_msg(mgm)); - fprintf(stderr, - "* %s", ndb_mgm_get_latest_error_desc(mgm)); - exit(-1); - } + if (g_config_file || g_mycnf) + conf = load_configuration(); + else + conf = fetch_configuration(); - if(ndb_mgm_connect(mgm, try_reconnect-1, 5, 1)) + if (conf == 0) { - fprintf(stderr, "Connect failed"); - fprintf(stderr, " code: %d, msg: %s\n", - ndb_mgm_get_latest_error(mgm), - ndb_mgm_get_latest_error_msg(mgm)); - exit(-1); - } - else if(g_verbose) - { - fprintf(stderr, "Connected to %s:%d\n", - ndb_mgm_get_connected_host(mgm), - ndb_mgm_get_connected_port(mgm)); - } - - ndb_mgm_configuration * conf = ndb_mgm_get_configuration(mgm, 0); - if(conf == 0) - { - fprintf(stderr, "Could not get configuration"); - fprintf(stderr, "code: %d, msg: %s\n", - ndb_mgm_get_latest_error(mgm), - ndb_mgm_get_latest_error_msg(mgm)); - exit(-1); - } - else if(g_verbose) - { - fprintf(stderr, "Fetched configuration\n"); + return -1; } Vector<Apply*> select_list; @@ -224,12 +207,12 @@ main(int argc, char** argv){ iter.first(); for(iter.first(); iter.valid(); iter.next()) { - if(eval(mgm, iter, where_clause)) + if(eval(iter, where_clause)) { if(prev) printf("%s", g_row_delimiter); prev= true; - apply(mgm, iter, select_list); + apply(iter, select_list); } } printf("\n"); @@ -297,9 +280,10 @@ parse_where(Vector<Match*>& where, int &argc, char**& argv) Match m; if(g_host) { - m.m_key = CFG_NODE_HOST; - m.m_value.assfmt("%s", g_host); - where.push_back(new Match(m)); + HostMatch *m = new HostMatch; + m->m_key = CFG_NODE_HOST; + m->m_value.assfmt("%s", g_host); + where.push_back(m); } if(g_type) @@ -323,11 +307,11 @@ template class Vector<Match*>; static int -eval(NdbMgmHandle mgm, const Iter& iter, const Vector<Match*>& where) +eval(const Iter& iter, const Vector<Match*>& where) { for(unsigned i = 0; i<where.size(); i++) { - if(where[i]->eval(mgm, iter) == 0) + if(where[i]->eval(iter) == 0) return 0; } @@ -336,11 +320,11 @@ eval(NdbMgmHandle mgm, const Iter& iter, const Vector<Match*>& where) static int -apply(NdbMgmHandle mgm, const Iter& iter, const Vector<Apply*>& list) +apply(const Iter& iter, const Vector<Apply*>& list) { for(unsigned i = 0; i<list.size(); i++) { - list[i]->apply(mgm, iter); + list[i]->apply(iter); if(i + 1 != list.size()) printf("%s", g_field_delimiter); } @@ -348,19 +332,19 @@ apply(NdbMgmHandle mgm, const Iter& iter, const Vector<Apply*>& list) } int -Match::eval(NdbMgmHandle h, const Iter& iter) +Match::eval(const Iter& iter) { Uint32 val32; Uint64 val64; const char* valc; if (iter.get(m_key, &val32) == 0) { - if(atoi(m_value.c_str()) != val32) + if(atoi(m_value.c_str()) != (int)val32) return 0; } else if(iter.get(m_key, &val64) == 0) { - if(strtoll(m_value.c_str(), (char **)NULL, 10) != val64) + if(strtoll(m_value.c_str(), (char **)NULL, 10) != (long long)val64) return 0; } else if(iter.get(m_key, &valc) == 0) @@ -376,7 +360,41 @@ Match::eval(NdbMgmHandle h, const Iter& iter) } int -Apply::apply(NdbMgmHandle h, const Iter& iter) +HostMatch::eval(NdbMgmHandle h, const Iter& iter) +{ + const char* valc; + + if(iter.get(m_key, &valc) == 0) + { + struct hostent *h1, *h2; + + h1 = gethostbyname(m_value.c_str()); + if (h1 == NULL) { + return 0; + } + + h2 = gethostbyname(valc); + if (h2 == NULL) { + return 0; + } + + if (h1->h_addrtype != h2->h_addrtype) { + return 0; + } + + if (h1->h_length != h2->h_length) + { + return 0; + } + + return 0 == memcmp(h1->h_addr, h2->h_addr, h1->h_length); + } + + return 0; +} + +int +Apply::apply(const Iter& iter) { Uint32 val32; Uint64 val64; @@ -397,7 +415,7 @@ Apply::apply(NdbMgmHandle h, const Iter& iter) } int -NodeTypeApply::apply(NdbMgmHandle h, const Iter& iter) +NodeTypeApply::apply(const Iter& iter) { Uint32 val32; if (iter.get(CFG_TYPE_OF_SECTION, &val32) == 0) @@ -406,3 +424,86 @@ NodeTypeApply::apply(NdbMgmHandle h, const Iter& iter) } return 0; } + +ndb_mgm_configuration* +fetch_configuration() +{ + ndb_mgm_configuration* conf = 0; + NdbMgmHandle mgm = ndb_mgm_create_handle(); + if(mgm == NULL) { + fprintf(stderr, "Cannot create handle to management server.\n"); + return 0; + } + + ndb_mgm_set_error_stream(mgm, stderr); + + if (ndb_mgm_set_connectstring(mgm, g_connectstring)) + { + fprintf(stderr, "* %5d: %s\n", + ndb_mgm_get_latest_error(mgm), + ndb_mgm_get_latest_error_msg(mgm)); + fprintf(stderr, + "* %s", ndb_mgm_get_latest_error_desc(mgm)); + goto noconnect; + } + + if(ndb_mgm_connect(mgm, try_reconnect-1, 5, 1)) + { + fprintf(stderr, "Connect failed"); + fprintf(stderr, " code: %d, msg: %s\n", + ndb_mgm_get_latest_error(mgm), + ndb_mgm_get_latest_error_msg(mgm)); + goto noconnect; + } + else if(g_verbose) + { + fprintf(stderr, "Connected to %s:%d\n", + ndb_mgm_get_connected_host(mgm), + ndb_mgm_get_connected_port(mgm)); + } + + conf = ndb_mgm_get_configuration(mgm, 0); + if(conf == 0) + { + fprintf(stderr, "Could not get configuration"); + fprintf(stderr, "code: %d, msg: %s\n", + ndb_mgm_get_latest_error(mgm), + ndb_mgm_get_latest_error_msg(mgm)); + } + else if(g_verbose) + { + fprintf(stderr, "Fetched configuration\n"); + } + + ndb_mgm_disconnect(mgm); +noconnect: + ndb_mgm_destroy_handle(&mgm); + + return conf; +} + +#include <Config.hpp> + +ndb_mgm_configuration* +load_configuration() +{ + InitConfigFileParser parser(stderr); + if (g_config_file) + { + if (g_verbose) + fprintf(stderr, "Using config.ini : %s", g_config_file); + + Config* conf = parser.parseConfig(g_config_file); + if (conf) + return conf->m_configValues; + } + + if (g_verbose) + fprintf(stderr, "Using my.cnf"); + + Config* conf = parser.parse_mycnf(); + if (conf) + return conf->m_configValues; + + return 0; +} diff --git a/storage/ndb/tools/restore/Restore.cpp b/storage/ndb/tools/restore/Restore.cpp index 6c01b753b43..9efafd19468 100644 --- a/storage/ndb/tools/restore/Restore.cpp +++ b/storage/ndb/tools/restore/Restore.cpp @@ -870,7 +870,7 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){ return ndbout; } - NdbRecAttr tmprec; + NdbRecAttr tmprec(0); tmprec.setup(desc.m_column, (char *)data.void_value); ndbout << tmprec; diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 5786bdac697..552246a4f9e 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -38,7 +38,7 @@ BackupRestore::init() m_cluster_connection = new Ndb_cluster_connection(g_connect_string); if(m_cluster_connection->connect(12, 5, 1) != 0) { - return -1; + return false; } m_ndb = new Ndb(m_cluster_connection); |