summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin/handler
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innodb_plugin/handler')
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc307
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.h25
-rw-r--r--storage/innodb_plugin/handler/handler0alter.cc17
-rw-r--r--storage/innodb_plugin/handler/handler0vars.h69
-rw-r--r--storage/innodb_plugin/handler/win_delay_loader.cc1024
5 files changed, 280 insertions, 1162 deletions
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index 682004407c7..ac710ea2b15 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -72,6 +72,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
/* Include necessary InnoDB headers */
extern "C" {
#include "univ.i"
+#include "buf0lru.h"
#include "btr0sea.h"
#include "os0file.h"
#include "os0thread.h"
@@ -106,7 +107,10 @@ extern "C" {
#include "i_s.h"
#ifndef MYSQL_SERVER
-/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
+# ifndef MYSQL_PLUGIN_IMPORT
+# define MYSQL_PLUGIN_IMPORT /* nothing */
+# endif /* MYSQL_PLUGIN_IMPORT */
+/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count;
@@ -125,6 +129,7 @@ static ulong commit_threads = 0;
static pthread_mutex_t commit_threads_m;
static pthread_cond_t commit_cond;
static pthread_mutex_t commit_cond_m;
+static pthread_mutex_t analyze_mutex;
static bool innodb_inited = 0;
#define INSIDE_HA_INNOBASE_CC
@@ -152,6 +157,10 @@ static ulong innobase_write_io_threads;
static long long innobase_buffer_pool_size, innobase_log_file_size;
+/** Percentage of the buffer pool to reserve for 'old' blocks.
+Connected to buf_LRU_old_ratio. */
+static uint innobase_old_blocks_pct;
+
/* The default values for the following char* start-up parameters
are determined in innobase_init below: */
@@ -166,9 +175,7 @@ file formats in the configuration file, but can only be set to any
of the supported file formats during runtime. */
static char* innobase_file_format_check = NULL;
-/* The following has a misleading name: starting from 4.0.5, this also
-affects Windows: */
-static char* innobase_unix_file_flush_method = NULL;
+static char* innobase_file_flush_method = NULL;
/* Below we have boolean-valued start-up parameters, and their default
values */
@@ -214,15 +221,19 @@ static void free_share(INNOBASE_SHARE *share);
static int innobase_close_connection(handlerton *hton, THD* thd);
static int innobase_commit(handlerton *hton, THD* thd, bool all);
static int innobase_rollback(handlerton *hton, THD* thd, bool all);
-static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
+static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
void *savepoint);
static int innobase_savepoint(handlerton *hton, THD* thd, void *savepoint);
-static int innobase_release_savepoint(handlerton *hton, THD* thd,
+static int innobase_release_savepoint(handlerton *hton, THD* thd,
void *savepoint);
static handler *innobase_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root);
+/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
+system primary index. */
+static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
+
/** @brief Initialize the default value of innodb_commit_concurrency.
Once InnoDB is running, the innodb_commit_concurrency must not change
@@ -492,10 +503,10 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
{"buffer_pool_pages_total",
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
- {"buffer_pool_read_ahead_rnd",
- (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
- {"buffer_pool_read_ahead_seq",
- (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
+ {"buffer_pool_read_ahead",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG},
+ {"buffer_pool_read_ahead_evicted",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG},
{"buffer_pool_read_requests",
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
{"buffer_pool_reads",
@@ -865,17 +876,14 @@ convert_error_code_to_mysql(
return(ER_PRIMARY_CANT_HAVE_NULL);
case DB_TOO_MANY_CONCURRENT_TRXS:
- /* Once MySQL add the appropriate code to errmsg.txt then
- we can get rid of this #ifdef. NOTE: The code checked by
- the #ifdef is the suggested name for the error condition
- and the actual error code name could very well be different.
- This will require some monitoring, ie. the status
- of this request on our part.*/
-#ifdef ER_TOO_MANY_CONCURRENT_TRXS
- return(ER_TOO_MANY_CONCURRENT_TRXS);
-#else
+ /* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
+ available in 5.1.38 and later, but the plugin should still
+ work with previous versions of MySQL. */
+#ifdef HA_ERR_TOO_MANY_CONCURRENT_TRXS
+ return(HA_ERR_TOO_MANY_CONCURRENT_TRXS);
+#else /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
return(HA_ERR_RECORD_FILE_FULL);
-#endif
+#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
case DB_UNSUPPORTED:
return(HA_ERR_UNSUPPORTED);
}
@@ -949,7 +957,23 @@ innobase_get_cset_width(
*mbminlen = cs->mbminlen;
*mbmaxlen = cs->mbmaxlen;
} else {
- ut_a(cset == 0);
+ THD* thd = current_thd;
+
+ if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) {
+
+ /* Fix bug#46256: allow tables to be dropped if the
+ collation is not found, but issue a warning. */
+ if ((global_system_variables.log_warnings)
+ && (cset != 0)){
+
+ sql_print_warning(
+ "Unknown collation #%lu.", cset);
+ }
+ } else {
+
+ ut_a(cset == 0);
+ }
+
*mbminlen = *mbmaxlen = 0;
}
}
@@ -2151,7 +2175,7 @@ innobase_change_buffering_inited_ok:
/* --------------------------------------------------*/
- srv_file_flush_method_str = innobase_unix_file_flush_method;
+ srv_file_flush_method_str = innobase_file_flush_method;
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
srv_n_log_files = (ulint) innobase_log_files_in_group;
@@ -2206,6 +2230,9 @@ innobase_change_buffering_inited_ok:
ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci"));
srv_latin1_ordering = my_charset_latin1.sort_order;
+ innobase_old_blocks_pct = buf_LRU_old_ratio_update(
+ innobase_old_blocks_pct, FALSE);
+
innobase_commit_concurrency_init_default();
/* Since we in this module access directly the fields of a trx
@@ -2225,6 +2252,7 @@ innobase_change_buffering_inited_ok:
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&analyze_mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&commit_cond, NULL);
innodb_inited= 1;
#ifdef MYSQL_DYNAMIC_PLUGIN
@@ -2279,6 +2307,7 @@ innobase_end(
pthread_mutex_destroy(&prepare_commit_mutex);
pthread_mutex_destroy(&commit_threads_m);
pthread_mutex_destroy(&commit_cond_m);
+ pthread_mutex_destroy(&analyze_mutex);
pthread_cond_destroy(&commit_cond);
}
@@ -2459,6 +2488,19 @@ retry:
}
}
+ /* The following calls to read the MySQL binary log
+ file name and the position return consistent results:
+ 1) Other InnoDB transactions cannot intervene between
+ these calls as we are holding prepare_commit_mutex.
+ 2) Binary logging of other engines is not relevant
+ to InnoDB as all InnoDB requires is that committing
+ InnoDB transactions appear in the same order in the
+ MySQL binary log as they appear in InnoDB logs.
+ 3) A MySQL log file rotation cannot happen because
+ MySQL protects against this by having a counter of
+ transactions in prepared state and it only allows
+ a rotation when the counter drops to zero. See
+ LOCK_prep_xids and COND_prep_xids in log.cc. */
trx->mysql_log_file_name = mysql_bin_log_file_name();
trx->mysql_log_offset = (ib_int64_t) mysql_bin_log_file_pos();
@@ -2544,6 +2586,8 @@ innobase_rollback(
innobase_release_stat_resources(trx);
+ trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */
+
/* If we had reserved the auto-inc lock for some table (if
we come here to roll back the latest SQL statement) we
release it now before a possibly lengthy rollback */
@@ -3105,7 +3149,7 @@ retry:
if (is_part) {
sql_print_error("Failed to open table %s after "
- "%lu attemtps.\n", norm_name,
+ "%lu attempts.\n", norm_name,
retries);
}
@@ -3704,7 +3748,10 @@ ha_innobase::store_key_val_for_row(
} else if (mysql_type == MYSQL_TYPE_TINY_BLOB
|| mysql_type == MYSQL_TYPE_MEDIUM_BLOB
|| mysql_type == MYSQL_TYPE_BLOB
- || mysql_type == MYSQL_TYPE_LONG_BLOB) {
+ || mysql_type == MYSQL_TYPE_LONG_BLOB
+ /* MYSQL_TYPE_GEOMETRY data is treated
+ as BLOB data in innodb. */
+ || mysql_type == MYSQL_TYPE_GEOMETRY) {
CHARSET_INFO* cs;
ulint key_len;
@@ -5006,6 +5053,11 @@ ha_innobase::index_read(
index = prebuilt->index;
+ if (UNIV_UNLIKELY(index == NULL)) {
+ prebuilt->index_usable = FALSE;
+ DBUG_RETURN(HA_ERR_CRASHED);
+ }
+
/* Note that if the index for which the search template is built is not
necessarily prebuilt->index, but can also be the clustered index */
@@ -5165,6 +5217,7 @@ ha_innobase::change_active_index(
if (UNIV_UNLIKELY(!prebuilt->index)) {
sql_print_warning("InnoDB: change_active_index(%u) failed",
keynr);
+ prebuilt->index_usable = FALSE;
DBUG_RETURN(1);
}
@@ -5628,7 +5681,7 @@ create_table_def(
number fits in one byte in prtype */
push_warning_printf(
(THD*) trx->mysql_thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CANT_CREATE_TABLE,
"In InnoDB, charset-collation codes"
" must be below 256."
@@ -5657,6 +5710,28 @@ create_table_def(
}
}
+ /* First check whether the column to be added has a
+ system reserved name. */
+ if (dict_col_name_is_reserved(field->field_name)){
+ push_warning_printf(
+ (THD*) trx->mysql_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CANT_CREATE_TABLE,
+ "Error creating table '%s' with "
+ "column name '%s'. '%s' is a "
+ "reserved name. Please try to "
+ "re-create the table with a "
+ "different column name.",
+ table->name, (char*) field->field_name,
+ (char*) field->field_name);
+
+ dict_mem_table_free(table);
+ trx_commit_for_mysql(trx);
+
+ error = DB_ERROR;
+ goto error_ret;
+ }
+
dict_mem_table_add_col(table, table->heap,
(char*) field->field_name,
col_type,
@@ -5670,6 +5745,7 @@ create_table_def(
error = row_create_table_for_mysql(table, trx);
+error_ret:
error = convert_error_code_to_mysql(error, flags, NULL);
DBUG_RETURN(error);
@@ -5708,6 +5784,9 @@ create_index(
n_fields = key->key_parts;
+ /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
+ ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
+
ind_type = 0;
if (key_num == form->s->primary_key) {
@@ -5816,8 +5895,8 @@ create_clustered_index_when_no_primary(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
-
- index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
+ index = dict_mem_index_create(table_name,
+ innobase_index_reserve_name,
0, DICT_CLUSTERED, 0);
error = row_create_index_for_mysql(index, trx, NULL);
@@ -5870,7 +5949,7 @@ create_options_are_valid(
/* Valid value. */
break;
default:
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid"
" KEY_BLOCK_SIZE = %lu."
@@ -5884,7 +5963,7 @@ create_options_are_valid(
/* If KEY_BLOCK_SIZE was specified, check for its
dependencies. */
if (kbs_specified && !srv_file_per_table) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_per_table.");
@@ -5892,7 +5971,7 @@ create_options_are_valid(
}
if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: KEY_BLOCK_SIZE"
" requires innodb_file_format >"
@@ -5916,7 +5995,7 @@ create_options_are_valid(
if (!srv_file_per_table) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_per_table.",
@@ -5928,7 +6007,7 @@ create_options_are_valid(
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ROW_FORMAT=%s"
" requires innodb_file_format >"
@@ -5945,7 +6024,7 @@ create_options_are_valid(
&& form->s->row_type == ROW_TYPE_DYNAMIC) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = DYNAMIC with"
@@ -5969,7 +6048,7 @@ create_options_are_valid(
if (kbs_specified) {
push_warning_printf(
thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: cannot specify"
" ROW_FORMAT = %s with"
@@ -5982,7 +6061,7 @@ create_options_are_valid(
default:
push_warning(thd,
- MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid ROW_FORMAT specifier.");
ret = FALSE;
@@ -6046,13 +6125,15 @@ ha_innobase::create(
1. <database_name>/<table_name>: for normal table creation
2. full path: for temp table creation, or sym link
- When srv_file_per_table is on, check for full path pattern, i.e.
+ When srv_file_per_table is on and mysqld_embedded is off,
+ check for full path pattern, i.e.
X:\dir\..., X is a driver letter, or
\\dir1\dir2\..., UNC path
returns error if it is in full path format, but not creating a temp.
table. Currently InnoDB does not support symbolic link on Windows. */
if (srv_file_per_table
+ && !mysqld_embedded
&& (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
if ((name[1] == ':')
@@ -6243,14 +6324,6 @@ ha_innobase::create(
flags = DICT_TF_COMPACT;
}
- error = create_table_def(trx, form, norm_name,
- create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
- flags);
-
- if (error) {
- goto cleanup;
- }
-
/* Look for a primary key */
primary_key_no= (form->s->primary_key != MAX_KEY ?
@@ -6262,6 +6335,23 @@ ha_innobase::create(
ut_a(primary_key_no == -1 || primary_key_no == 0);
+ /* Check for name conflicts (with reserved name) for
+ any user indices to be created. */
+ if (innobase_index_name_is_reserved(trx, form->key_info,
+ form->s->keys)) {
+ error = -1;
+ goto cleanup;
+ }
+
+ error = create_table_def(trx, form, norm_name,
+ create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
+ flags);
+
+ if (error) {
+ goto cleanup;
+ }
+
+
/* Create the keys */
if (form->s->keys == 0 || primary_key_no == -1) {
@@ -6335,18 +6425,22 @@ ha_innobase::create(
setup at this stage and so we use thd. */
/* We need to copy the AUTOINC value from the old table if
- this is an ALTER TABLE. */
+ this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
+ does a table copy too. */
if (((create_info->used_fields & HA_CREATE_USED_AUTO)
- || thd_sql_command(thd) == SQLCOM_ALTER_TABLE)
- && create_info->auto_increment_value != 0) {
-
- /* Query was ALTER TABLE...AUTO_INCREMENT = x; or
- CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
- definition from the dictionary and get the current value
- of the auto increment field. Set a new value to the
- auto increment field if the value is greater than the
- maximum value in the column. */
+ || thd_sql_command(thd) == SQLCOM_ALTER_TABLE
+ || thd_sql_command(thd) == SQLCOM_CREATE_INDEX)
+ && create_info->auto_increment_value > 0) {
+
+ /* Query was one of :
+ CREATE TABLE ...AUTO_INCREMENT = x; or
+ ALTER TABLE...AUTO_INCREMENT = x; or
+ CREATE INDEX x on t(...);
+ Find out a table definition from the dictionary and get
+ the current value of the auto increment field. Set a new
+ value to the auto increment field if the value is greater
+ than the maximum value in the column. */
auto_inc_value = create_info->auto_increment_value;
@@ -7200,9 +7294,15 @@ ha_innobase::analyze(
THD* thd, /*!< in: connection thread handle */
HA_CHECK_OPT* check_opt) /*!< in: currently ignored */
{
+ /* Serialize ANALYZE TABLE inside InnoDB, see
+ Bug#38996 Race condition in ANALYZE TABLE */
+ pthread_mutex_lock(&analyze_mutex);
+
/* Simply call ::info() with all the flags */
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+ pthread_mutex_unlock(&analyze_mutex);
+
return(0);
}
@@ -7797,8 +7897,9 @@ ha_innobase::external_lock(
{
ulong const binlog_format= thd_binlog_format(thd);
ulong const tx_isolation = thd_tx_isolation(ha_thd());
- if (tx_isolation <= ISO_READ_COMMITTED &&
- binlog_format == BINLOG_FORMAT_STMT)
+ if (tx_isolation <= ISO_READ_COMMITTED
+ && binlog_format == BINLOG_FORMAT_STMT
+ && thd_binlog_filter_ok(thd))
{
char buf[256];
my_snprintf(buf, sizeof(buf),
@@ -8446,6 +8547,7 @@ ha_innobase::store_lock(
&& isolation_level != TRX_ISO_SERIALIZABLE
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
&& (sql_command == SQLCOM_INSERT_SELECT
+ || sql_command == SQLCOM_REPLACE_SELECT
|| sql_command == SQLCOM_UPDATE
|| sql_command == SQLCOM_CREATE_TABLE)) {
@@ -8453,10 +8555,11 @@ ha_innobase::store_lock(
option set or this session is using READ COMMITTED
isolation level and isolation level of the transaction
is not set to serializable and MySQL is doing
- INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
- CREATE ... SELECT... without FOR UPDATE or
- IN SHARE MODE in select, then we use consistent
- read for select. */
+ INSERT INTO...SELECT or REPLACE INTO...SELECT
+ or UPDATE ... = (SELECT ...) or CREATE ...
+ SELECT... without FOR UPDATE or IN SHARE
+ MODE in select, then we use consistent read
+ for select. */
prebuilt->select_lock_type = LOCK_NONE;
prebuilt->stored_select_lock_type = LOCK_NONE;
@@ -8676,6 +8779,7 @@ ha_innobase::get_auto_increment(
AUTOINC counter after attempting to insert the row. */
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
ulonglong need;
+ ulonglong current;
ulonglong next_value;
ulonglong col_max_value;
@@ -8684,11 +8788,12 @@ ha_innobase::get_auto_increment(
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
+ current = *first_value > col_max_value ? autoinc : *first_value;
need = *nb_reserved_values * increment;
/* Compute the last value in the interval */
next_value = innobase_next_autoinc(
- *first_value, need, offset, col_max_value);
+ current, need, offset, col_max_value);
prebuilt->autoinc_last_value = next_value;
@@ -9612,6 +9717,25 @@ innodb_adaptive_hash_index_update(
}
}
+/****************************************************************//**
+Update the system variable innodb_old_blocks_pct using the "saved"
+value. This function is registered as a callback with MySQL. */
+static
+void
+innodb_old_blocks_pct_update(
+/*=========================*/
+ THD* thd, /*!< in: thread handle */
+ struct st_mysql_sys_var* var, /*!< in: pointer to
+ system variable */
+ void* var_ptr,/*!< out: where the
+ formal string goes */
+ const void* save) /*!< in: immediate result
+ from check function */
+{
+ innobase_old_blocks_pct = buf_LRU_old_ratio_update(
+ *static_cast<const uint*>(save), TRUE);
+}
+
/*************************************************************//**
Check if it is a valid value of innodb_change_buffering. This function is
registered as a callback with MySQL.
@@ -9685,6 +9809,49 @@ static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
return 0;
}
+/***********************************************************************
+This function checks each index name for a table against reserved
+system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
+this function pushes an warning message to the client, and returns true. */
+extern "C" UNIV_INTERN
+bool
+innobase_index_name_is_reserved(
+/*============================*/
+ /* out: true if an index name
+ matches the reserved name */
+ const trx_t* trx, /* in: InnoDB transaction handle */
+ const KEY* key_info, /* in: Indexes to be created */
+ ulint num_of_keys) /* in: Number of indexes to
+ be created. */
+{
+ const KEY* key;
+ uint key_num; /* index number */
+
+ for (key_num = 0; key_num < num_of_keys; key_num++) {
+ key = &key_info[key_num];
+
+ if (innobase_strcasecmp(key->name,
+ innobase_index_reserve_name) == 0) {
+ /* Push warning to mysql */
+ push_warning_printf((THD*) trx->mysql_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WRONG_NAME_FOR_INDEX,
+ "Cannot Create Index with name "
+ "'%s'. The name is reserved "
+ "for the system default primary "
+ "index.",
+ innobase_index_reserve_name);
+
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
+ innobase_index_reserve_name);
+
+ return(true);
+ }
+ }
+
+ return(false);
+}
+
static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
@@ -9753,7 +9920,7 @@ static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
" or 2 (write at commit, flush once per second).",
NULL, NULL, 1, 0, 2, 0);
-static MYSQL_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
+static MYSQL_SYSVAR_STR(flush_method, innobase_file_flush_method,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"With which method to flush data.", NULL, NULL, NULL);
@@ -9849,7 +10016,7 @@ static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
NULL, NULL, 500L, 1L, ~0L, 0);
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
"Number of file I/O threads in InnoDB.",
NULL, NULL, 4, 4, 64, 0);
@@ -9888,6 +10055,18 @@ static MYSQL_SYSVAR_LONG(mirrored_log_groups, innobase_mirrored_log_groups,
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
NULL, NULL, 1, 1, 10, 0);
+static MYSQL_SYSVAR_UINT(old_blocks_pct, innobase_old_blocks_pct,
+ PLUGIN_VAR_RQCMDARG,
+ "Percentage of the buffer pool to reserve for 'old' blocks.",
+ NULL, innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0);
+
+static MYSQL_SYSVAR_UINT(old_blocks_time, buf_LRU_old_threshold_ms,
+ PLUGIN_VAR_RQCMDARG,
+ "Move blocks to the 'new' end of the buffer pool if the first access"
+ " was at least this many milliseconds ago."
+ " The timeout is disabled if 0 (the default).",
+ NULL, NULL, 0, 0, UINT_MAX32, 0);
+
static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"How many files at the maximum InnoDB keeps open at the same time.",
@@ -9986,6 +10165,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(adaptive_flushing),
MYSQL_SYSVAR(max_purge_lag),
MYSQL_SYSVAR(mirrored_log_groups),
+ MYSQL_SYSVAR(old_blocks_pct),
+ MYSQL_SYSVAR(old_blocks_time),
MYSQL_SYSVAR(open_files),
MYSQL_SYSVAR(rollback_on_timeout),
MYSQL_SYSVAR(stats_on_metadata),
diff --git a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h
index cc98003f8ff..4779651ee27 100644
--- a/storage/innodb_plugin/handler/ha_innodb.h
+++ b/storage/innodb_plugin/handler/ha_innodb.h
@@ -257,6 +257,13 @@ int thd_binlog_format(const MYSQL_THD thd);
@param all TRUE <=> rollback main transaction.
*/
void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
+
+/**
+ Check if binary logging is filtered for thread's current db.
+ @param thd Thread handle
+ @retval 1 the query is not filtered, 0 otherwise.
+*/
+bool thd_binlog_filter_ok(const MYSQL_THD thd);
}
typedef struct trx_struct trx_t;
@@ -282,3 +289,21 @@ trx_t*
innobase_trx_allocate(
/*==================*/
MYSQL_THD thd); /*!< in: user thread handle */
+
+
+/*********************************************************************//**
+This function checks each index name for a table against reserved
+system default primary index name 'GEN_CLUST_INDEX'. If a name
+matches, this function pushes an warning message to the client,
+and returns true. */
+extern "C"
+bool
+innobase_index_name_is_reserved(
+/*============================*/
+ /* out: true if the index name
+ matches the reserved name */
+ const trx_t* trx, /* in: InnoDB transaction handle */
+ const KEY* key_info, /* in: Indexes to be created */
+ ulint num_of_keys); /* in: Number of indexes to
+ be created. */
+
diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc
index d1f64a1985c..37aed06b28a 100644
--- a/storage/innodb_plugin/handler/handler0alter.cc
+++ b/storage/innodb_plugin/handler/handler0alter.cc
@@ -628,7 +628,7 @@ ha_innobase::add_index(
ulint num_created = 0;
ibool dict_locked = FALSE;
ulint new_primary;
- ulint error;
+ int error;
DBUG_ENTER("ha_innobase::add_index");
ut_a(table);
@@ -656,14 +656,18 @@ ha_innobase::add_index(
innodb_table = indexed_table
= dict_table_get(prebuilt->table->name, FALSE);
- /* Check that index keys are sensible */
-
- error = innobase_check_index_keys(key_info, num_of_keys);
+ /* Check if the index name is reserved. */
+ if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
+ error = -1;
+ } else {
+ /* Check that index keys are sensible */
+ error = innobase_check_index_keys(key_info, num_of_keys);
+ }
if (UNIV_UNLIKELY(error)) {
err_exit:
mem_heap_free(heap);
- trx_general_rollback_for_mysql(trx, FALSE, NULL);
+ trx_general_rollback_for_mysql(trx, NULL);
trx_free_for_mysql(trx);
trx_commit_for_mysql(prebuilt->trx);
DBUG_RETURN(error);
@@ -801,7 +805,7 @@ error_handling:
alter table t drop index b, add index (b);
The fix will have to parse the SQL and note that the index
- being added has the same name as the the one being dropped and
+ being added has the same name as the one being dropped and
ignore that in the dup index check.*/
//dict_table_check_for_dup_indexes(prebuilt->table);
#endif
@@ -863,6 +867,7 @@ error_handling:
indexed_table->n_mysql_handles_opened++;
error = row_merge_drop_table(trx, innodb_table);
+ innodb_table = indexed_table;
goto convert_error;
case DB_TOO_BIG_RECORD:
diff --git a/storage/innodb_plugin/handler/handler0vars.h b/storage/innodb_plugin/handler/handler0vars.h
deleted file mode 100644
index e0f8f75e34d..00000000000
--- a/storage/innodb_plugin/handler/handler0vars.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2008, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*******************************************************************//**
-@file handler/handler0vars.h
-This file contains accessor functions for dynamic plugin on Windows.
-***********************************************************************/
-
-#if defined __WIN__ && defined MYSQL_DYNAMIC_PLUGIN
-/*******************************************************************//**
-This is a list of externals that can not be resolved by delay loading.
-They have to be resolved indirectly via their addresses in the .map file.
-All of them are external variables. */
-extern CHARSET_INFO* wdl_my_charset_bin;
-extern CHARSET_INFO* wdl_my_charset_latin1;
-extern CHARSET_INFO* wdl_my_charset_filename;
-extern CHARSET_INFO** wdl_system_charset_info;
-extern CHARSET_INFO** wdl_default_charset_info;
-extern CHARSET_INFO** wdl_all_charsets;
-extern system_variables* wdl_global_system_variables;
-extern char* wdl_mysql_real_data_home;
-extern char** wdl_mysql_data_home;
-extern char** wdl_tx_isolation_names;
-extern char** wdl_binlog_format_names;
-extern char* wdl_reg_ext;
-extern pthread_mutex_t* wdl_LOCK_thread_count;
-extern key_map* wdl_key_map_full;
-extern MY_TMPDIR* wdl_mysql_tmpdir_list;
-extern bool* wdl_mysqld_embedded;
-extern uint* wdl_lower_case_table_names;
-extern ulong* wdl_specialflag;
-extern int* wdl_my_umask;
-
-#define my_charset_bin (*wdl_my_charset_bin)
-#define my_charset_latin1 (*wdl_my_charset_latin1)
-#define my_charset_filename (*wdl_my_charset_filename)
-#define system_charset_info (*wdl_system_charset_info)
-#define default_charset_info (*wdl_default_charset_info)
-#define all_charsets (wdl_all_charsets)
-#define global_system_variables (*wdl_global_system_variables)
-#define mysql_real_data_home (wdl_mysql_real_data_home)
-#define mysql_data_home (*wdl_mysql_data_home)
-#define tx_isolation_names (wdl_tx_isolation_names)
-#define binlog_format_names (wdl_binlog_format_names)
-#define reg_ext (wdl_reg_ext)
-#define LOCK_thread_count (*wdl_LOCK_thread_count)
-#define key_map_full (*wdl_key_map_full)
-#define mysql_tmpdir_list (*wdl_mysql_tmpdir_list)
-#define mysqld_embedded (*wdl_mysqld_embedded)
-#define lower_case_table_names (*wdl_lower_case_table_names)
-#define specialflag (*wdl_specialflag)
-#define my_umask (*wdl_my_umask)
-
-#endif
diff --git a/storage/innodb_plugin/handler/win_delay_loader.cc b/storage/innodb_plugin/handler/win_delay_loader.cc
deleted file mode 100644
index 9b92f6a9cf2..00000000000
--- a/storage/innodb_plugin/handler/win_delay_loader.cc
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2008, 2009, Innobase Oy. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
-
-*****************************************************************************/
-
-/*******************************************************************//**
-@file handler/win_delay_loader.cc
-This file contains functions that implement the delay loader on Windows.
-
-This is a customized version of delay loader with limited functionalities.
-It does not support:
-
-* (manual) unloading
-* multiple delay loaded DLLs
-* multiple loading of the same DLL
-
-This delay loader is used only by the InnoDB plugin. Other components (DLLs)
-can still use the default delay loader, provided by MSVC.
-
-Several acronyms used by Microsoft:
- * IAT: import address table
- * INT: import name table
- * RVA: Relative Virtual Address
-
-See http://msdn.microsoft.com/en-us/magazine/bb985992.aspx for details of
-PE format.
-***********************************************************************/
-#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# include <delayimp.h>
-# include <mysql_priv.h>
-
-extern "C" {
-# include "univ.i"
-# include "hash0hash.h"
-}
-
-/*******************************************************************//**
-This following contains a list of externals that can not be resolved by
-delay loading. They have to be resolved indirectly via their addresses
-in the .map file. All of them are external variables. */
-CHARSET_INFO* wdl_my_charset_bin;
-CHARSET_INFO* wdl_my_charset_latin1;
-CHARSET_INFO* wdl_my_charset_filename;
-CHARSET_INFO** wdl_system_charset_info;
-CHARSET_INFO** wdl_default_charset_info;
-CHARSET_INFO** wdl_all_charsets;
-system_variables* wdl_global_system_variables;
-char* wdl_mysql_real_data_home;
-char** wdl_mysql_data_home;
-char** wdl_tx_isolation_names;
-char** wdl_binlog_format_names;
-char* wdl_reg_ext;
-pthread_mutex_t* wdl_LOCK_thread_count;
-key_map* wdl_key_map_full;
-MY_TMPDIR* wdl_mysql_tmpdir_list;
-bool* wdl_mysqld_embedded;
-uint* wdl_lower_case_table_names;
-ulong* wdl_specialflag;
-int* wdl_my_umask;
-
-/*******************************************************************//**
-The preferred load-address defined in PE (portable executable format). */
-#if defined(_M_IA64)
-#pragma section(".base", long, read)
-extern "C"
-__declspec(allocate(".base"))
-const IMAGE_DOS_HEADER __ImageBase;
-#else
-extern "C"
-const IMAGE_DOS_HEADER __ImageBase;
-#endif
-
-/*******************************************************************//**
-A template function for converting a relative address (RVA) to an
-absolute address (VA). This is due to the pointers in the delay
-descriptor (ImgDelayDescr in delayimp.h) have been changed from
-VAs to RVAs to work on both 32- and 64-bit platforms.
-@return absolute virtual address */
-template <class X>
-X PFromRva(
-/*=======*/
- RVA rva) /*!< in: relative virtual address */
-{
- return X(PBYTE(&__ImageBase) + rva);
-}
-
-/*******************************************************************//**
-Convert to the old format for convenience. The structure as well as its
-element names follow the definition of ImgDelayDescr in delayimp.h. */
-struct InternalImgDelayDescr
-{
- DWORD grAttrs; /*!< attributes */
- LPCSTR szName; /*!< pointer to dll name */
- HMODULE* phmod; /*!< address of module handle */
- PImgThunkData pIAT; /*!< address of the IAT */
- PCImgThunkData pINT; /*!< address of the INT */
- PCImgThunkData pBoundIAT; /*!< address of the optional bound IAT */
- PCImgThunkData pUnloadIAT; /*!< address of optional copy of
- original IAT */
- DWORD dwTimeStamp; /*!< 0 if not bound,
- otherwise date/time stamp of DLL
- bound to (Old BIND) */
-};
-
-typedef struct map_hash_chain_struct map_hash_chain_t;
-
-struct map_hash_chain_struct {
- char* symbol; /*!< pointer to a symbol */
- ulint value; /*!< address of the symbol */
- map_hash_chain_t* next; /*!< pointer to the next cell
- in the same folder. */
- map_hash_chain_t* chain; /*!< a linear chain used for
- cleanup. */
-};
-
-static HMODULE my_hmod = 0;
-static struct hash_table_struct* m_htbl = NULL ;
-static map_hash_chain_t* chain_header = NULL;
-static ibool wdl_init = FALSE;
-const ulint MAP_HASH_CELLS_NUM = 10000;
-
-#ifndef DBUG_OFF
-/*******************************************************************//**
-In the dynamic plugin, it is required to call the following dbug functions
-in the server:
- _db_pargs_
- _db_doprnt_
- _db_enter_
- _db_return_
- _db_dump_
-
-The plugin will get those function pointers during the initialization. */
-typedef void (__cdecl* pfn_db_enter_)(
- const char* _func_,
- const char* _file_,
- uint _line_,
- const char** _sfunc_,
- const char** _sfile_,
- uint* _slevel_,
- char***);
-
-typedef void (__cdecl* pfn_db_return_)(
- uint _line_,
- const char** _sfunc_,
- const char** _sfile_,
- uint* _slevel_);
-
-typedef void (__cdecl* pfn_db_pargs_)(
- uint _line_,
- const char* keyword);
-
-typedef void (__cdecl* pfn_db_doprnt_)(
- const char* format,
- ...);
-
-typedef void (__cdecl* pfn_db_dump_)(
- uint _line_,
- const char* keyword,
- const unsigned char* memory,
- size_t length);
-
-static pfn_db_enter_ wdl_db_enter_;
-static pfn_db_return_ wdl_db_return_;
-static pfn_db_pargs_ wdl_db_pargs_;
-static pfn_db_doprnt_ wdl_db_doprnt_;
-static pfn_db_dump_ wdl_db_dump_;
-#endif /* !DBUG_OFF */
-
-/*************************************************************//**
-Creates a hash table with >= n array cells. The actual number of cells is
-chosen to be a prime number slightly bigger than n.
-
-This is the same function as hash_create in hash0hash.c, except the
-memory allocation. This function is invoked before the engine is
-initialized, and buffer pools are not ready yet.
-@return own: created hash table */
-static
-hash_table_t*
-wdl_hash_create(
-/*============*/
- ulint n) /*!< in: number of array cells */
-{
- hash_cell_t* array;
- ulint prime;
- hash_table_t* table;
-
- prime = ut_find_prime(n);
-
- table = (hash_table_t*) malloc(sizeof(hash_table_t));
- if (table == NULL) {
- return(NULL);
- }
-
- array = (hash_cell_t*) malloc(sizeof(hash_cell_t) * prime);
- if (array == NULL) {
- free(table);
- return(NULL);
- }
-
- table->array = array;
- table->n_cells = prime;
- table->n_mutexes = 0;
- table->mutexes = NULL;
- table->heaps = NULL;
- table->heap = NULL;
- table->magic_n = HASH_TABLE_MAGIC_N;
-
- /* Initialize the cell array */
- hash_table_clear(table);
-
- return(table);
-}
-
-/*************************************************************//**
-Frees a hash table. */
-static
-void
-wdl_hash_table_free(
-/*================*/
- hash_table_t* table) /*!< in, own: hash table */
-{
- ut_a(table != NULL);
- ut_a(table->mutexes == NULL);
-
- free(table->array);
- free(table);
-}
-
-/*******************************************************************//**
-Function for calculating the count of imports given the base of the IAT.
-@return number of imports */
-static
-ulint
-wdl_import_count(
-/*=============*/
- PCImgThunkData pitd_base) /*!< in: base of the IAT */
-{
- ulint ret = 0;
- PCImgThunkData pitd = pitd_base;
-
- while (pitd->u1.Function) {
- pitd++;
- ret++;
- }
-
- return(ret);
-}
-
-/*******************************************************************//**
-Read Mapfile to a hashtable for faster access
-@return TRUE if the mapfile is loaded successfully. */
-static
-ibool
-wdl_load_mapfile(
-/*=============*/
- const char* filename) /*!< in: name of the mapfile. */
-{
- FILE* fp;
- const size_t nSize = 256;
- char tmp_buf[nSize];
- char* func_name;
- char* func_addr;
- ulint load_addr = 0;
- ibool valid_load_addr = FALSE;
-#ifdef _WIN64
- const char* tmp_string = " Preferred load address is %16llx";
-#else
- const char* tmp_string = " Preferred load address is %08x";
-#endif
-
- fp = fopen(filename, "r");
- if (fp == NULL) {
-
- return(FALSE);
- }
-
- /* Check whether to create the hashtable */
- if (m_htbl == NULL) {
-
- m_htbl = wdl_hash_create(MAP_HASH_CELLS_NUM);
-
- if (m_htbl == NULL) {
-
- fclose(fp);
- return(FALSE);
- }
- }
-
- /* Search start of symbol list and get the preferred load address */
- while (fgets(tmp_buf, sizeof(tmp_buf), fp)) {
-
- if (sscanf(tmp_buf, tmp_string, &load_addr) == 1) {
-
- valid_load_addr = TRUE;
- }
-
- if (strstr(tmp_buf, "Rva+Base") != NULL) {
-
- break;
- }
- }
-
- if (valid_load_addr == FALSE) {
-
- /* No "Preferred load address", the map file is wrong. */
- fclose(fp);
- return(FALSE);
- }
-
- /* Read symbol list */
- while (fgets(tmp_buf, sizeof(tmp_buf), fp))
- {
- map_hash_chain_t* map_cell;
- ulint map_fold;
-
- if (*tmp_buf == 0) {
-
- continue;
- }
-
- func_name = strtok(tmp_buf, " ");
- func_name = strtok(NULL, " ");
- func_addr = strtok(NULL, " ");
-
- if (func_name && func_addr) {
-
- ut_snprintf(tmp_buf, nSize, "0x%s", func_addr);
- if (*func_name == '_') {
-
- func_name++;
- }
-
- map_cell = (map_hash_chain_t*)
- malloc(sizeof(map_hash_chain_t));
- if (map_cell == NULL) {
- return(FALSE);
- }
-
- /* Chain all cells together */
- map_cell->chain = chain_header;
- chain_header = map_cell;
-
- map_cell->symbol = strdup(func_name);
- map_cell->value = (ulint) _strtoui64(tmp_buf, NULL, 0)
- - load_addr;
- map_fold = ut_fold_string(map_cell->symbol);
-
- HASH_INSERT(map_hash_chain_t,
- next,
- m_htbl,
- map_fold,
- map_cell);
- }
- }
-
- fclose(fp);
-
- return(TRUE);
-}
-
-/*************************************************************//**
-Cleanup.during DLL unload */
-static
-void
-wdl_cleanup(void)
-/*=============*/
-{
- while (chain_header != NULL) {
- map_hash_chain_t* tmp;
-
- tmp = chain_header->chain;
- free(chain_header->symbol);
- free(chain_header);
- chain_header = tmp;
- }
-
- if (m_htbl != NULL) {
-
- wdl_hash_table_free(m_htbl);
- }
-}
-
-/*******************************************************************//**
-Load the mapfile mysqld.map.
-@return the module handle */
-static
-HMODULE
-wdl_get_mysqld_mapfile(void)
-/*========================*/
-{
- char file_name[MAX_PATH];
- char* ext;
- ulint err;
-
- if (my_hmod == 0) {
-
- size_t nSize = MAX_PATH - strlen(".map") -1;
-
- /* First find out the name of current executable */
- my_hmod = GetModuleHandle(NULL);
- if (my_hmod == 0) {
-
- return(my_hmod);
- }
-
- err = GetModuleFileName(my_hmod, file_name, nSize);
- if (err == 0) {
-
- my_hmod = 0;
- return(my_hmod);
- }
-
- ext = strrchr(file_name, '.');
- if (ext != NULL) {
-
- *ext = 0;
- strcat(file_name, ".map");
-
- err = wdl_load_mapfile(file_name);
- if (err == 0) {
-
- my_hmod = 0;
- }
- } else {
-
- my_hmod = 0;
- }
- }
-
- return(my_hmod);
-}
-
-/*******************************************************************//**
-Retrieves the address of an exported function. It follows the convention
-of GetProcAddress().
-@return address of exported function. */
-static
-FARPROC
-wdl_get_procaddr_from_map(
-/*======================*/
- HANDLE m_handle, /*!< in: module handle */
- const char* import_proc) /*!< in: procedure name */
-{
- map_hash_chain_t* hash_chain;
- ulint map_fold;
-
- map_fold = ut_fold_string(import_proc);
- HASH_SEARCH(
- next,
- m_htbl,
- map_fold,
- map_hash_chain_t*,
- hash_chain,
- ,
- (ut_strcmp(hash_chain->symbol, import_proc) == 0));
-
- if (hash_chain == NULL) {
-
-#ifdef _WIN64
- /* On Win64, the leading '_' may not be taken out. In this
- case, search again without the leading '_'. */
- if (*import_proc == '_') {
-
- import_proc++;
- }
-
- map_fold = ut_fold_string(import_proc);
- HASH_SEARCH(
- next,
- m_htbl,
- map_fold,
- map_hash_chain_t*,
- hash_chain,
- ,
- (ut_strcmp(hash_chain->symbol, import_proc) == 0));
-
- if (hash_chain == NULL) {
-#endif
- if (wdl_init == TRUE) {
-
- sql_print_error(
- "InnoDB: the procedure pointer of %s"
- " is not found.",
- import_proc);
- }
-
- return(0);
-#ifdef _WIN64
- }
-#endif
- }
-
- return((FARPROC) ((ulint) m_handle + hash_chain->value));
-}
-
-/*******************************************************************//**
-Retrieves the address of an exported variable.
-Note: It does not follow the Windows call convention FARPROC.
-@return address of exported variable. */
-static
-void*
-wdl_get_varaddr_from_map(
-/*=====================*/
- HANDLE m_handle, /*!< in: module handle */
- const char* import_variable) /*!< in: variable name */
-{
- map_hash_chain_t* hash_chain;
- ulint map_fold;
-
- map_fold = ut_fold_string(import_variable);
- HASH_SEARCH(
- next,
- m_htbl,
- map_fold,
- map_hash_chain_t*,
- hash_chain,
- ,
- (ut_strcmp(hash_chain->symbol, import_variable) == 0));
-
- if (hash_chain == NULL) {
-
-#ifdef _WIN64
- /* On Win64, the leading '_' may not be taken out. In this
- case, search again without the leading '_'. */
- if (*import_variable == '_') {
-
- import_variable++;
- }
-
- map_fold = ut_fold_string(import_variable);
- HASH_SEARCH(
- next,
- m_htbl,
- map_fold,
- map_hash_chain_t*,
- hash_chain,
- ,
- (ut_strcmp(hash_chain->symbol, import_variable) == 0));
-
- if (hash_chain == NULL) {
-#endif
- if (wdl_init == TRUE) {
-
- sql_print_error(
- "InnoDB: the variable address of %s"
- " is not found.",
- import_variable);
- }
-
- return(0);
-#ifdef _WIN64
- }
-#endif
- }
-
- return((void*) ((ulint) m_handle + hash_chain->value));
-}
-
-/*******************************************************************//**
-Bind all unresolved external variables from the MySQL executable.
-@return TRUE if successful */
-static
-bool
-wdl_get_external_variables(void)
-/*============================*/
-{
- HMODULE hmod = wdl_get_mysqld_mapfile();
-
- if (hmod == 0) {
-
- return(FALSE);
- }
-
-#define GET_SYM(sym, var, type) \
- var = (type*) wdl_get_varaddr_from_map(hmod, sym); \
- if (var == NULL) return(FALSE)
-#ifdef _WIN64
-#define GET_SYM2(sym1, sym2, var, type) \
- var = (type*) wdl_get_varaddr_from_map(hmod, sym1); \
- if (var == NULL) return(FALSE)
-#else
-#define GET_SYM2(sym1, sym2, var, type) \
- var = (type*) wdl_get_varaddr_from_map(hmod, sym2); \
- if (var == NULL) return(FALSE)
-#endif // (_WIN64)
-#define GET_C_SYM(sym, type) GET_SYM(#sym, wdl_##sym, type)
-#define GET_PROC_ADDR(sym) \
- wdl##sym = (pfn##sym) wdl_get_procaddr_from_map(hmod, #sym)
-
- GET_C_SYM(my_charset_bin, CHARSET_INFO);
- GET_C_SYM(my_charset_latin1, CHARSET_INFO);
- GET_C_SYM(my_charset_filename, CHARSET_INFO);
- GET_C_SYM(default_charset_info, CHARSET_INFO*);
- GET_C_SYM(all_charsets, CHARSET_INFO*);
- GET_C_SYM(my_umask, int);
-
- GET_SYM("?global_system_variables@@3Usystem_variables@@A",
- wdl_global_system_variables, struct system_variables);
- GET_SYM("?mysql_real_data_home@@3PADA",
- wdl_mysql_real_data_home, char);
- GET_SYM("?reg_ext@@3PADA", wdl_reg_ext, char);
- GET_SYM("?LOCK_thread_count@@3U_RTL_CRITICAL_SECTION@@A",
- wdl_LOCK_thread_count, pthread_mutex_t);
- GET_SYM("?key_map_full@@3V?$Bitmap@$0EA@@@A",
- wdl_key_map_full, key_map);
- GET_SYM("?mysql_tmpdir_list@@3Ust_my_tmpdir@@A",
- wdl_mysql_tmpdir_list, MY_TMPDIR);
- GET_SYM("?mysqld_embedded@@3_NA",
- wdl_mysqld_embedded, bool);
- GET_SYM("?lower_case_table_names@@3IA",
- wdl_lower_case_table_names, uint);
- GET_SYM("?specialflag@@3KA", wdl_specialflag, ulong);
-
- GET_SYM2("?system_charset_info@@3PEAUcharset_info_st@@EA",
- "?system_charset_info@@3PAUcharset_info_st@@A",
- wdl_system_charset_info, CHARSET_INFO*);
- GET_SYM2("?mysql_data_home@@3PEADEA",
- "?mysql_data_home@@3PADA",
- wdl_mysql_data_home, char*);
- GET_SYM2("?tx_isolation_names@@3PAPEBDA",
- "?tx_isolation_names@@3PAPBDA",
- wdl_tx_isolation_names, char*);
- GET_SYM2("?binlog_format_names@@3PAPEBDA",
- "?binlog_format_names@@3PAPBDA",
- wdl_binlog_format_names, char*);
-
-#ifndef DBUG_OFF
- GET_PROC_ADDR(_db_enter_);
- GET_PROC_ADDR(_db_return_);
- GET_PROC_ADDR(_db_pargs_);
- GET_PROC_ADDR(_db_doprnt_);
- GET_PROC_ADDR(_db_dump_);
-
- /* If any of the dbug functions is not available, just make them
- all invalid. This is the case when working with a non-debug
- version of the server. */
- if (wdl_db_enter_ == NULL || wdl_db_return_ == NULL
- || wdl_db_pargs_ == NULL || wdl_db_doprnt_ == NULL
- || wdl_db_dump_ == NULL) {
-
- wdl_db_enter_ = NULL;
- wdl_db_return_ = NULL;
- wdl_db_pargs_ = NULL;
- wdl_db_doprnt_ = NULL;
- wdl_db_dump_ = NULL;
- }
-#endif /* !DBUG_OFF */
-
- wdl_init = TRUE;
- return(TRUE);
-
-#undef GET_SYM
-#undef GET_SYM2
-#undef GET_C_SYM
-#undef GET_PROC_ADDR
-}
-
-/*******************************************************************//**
-The DLL Delayed Loading Helper Function for resolving externals.
-
-The function may fail due to one of the three reasons:
-
-* Invalid parameter, which happens if the attributes in pidd aren't
- specified correctly.
-* Failed to load the map file mysqld.map.
-* Failed to find an external name in the map file mysqld.map.
-
-Note: this function is called by run-time as well as __HrLoadAllImportsForDll.
-So, it has to follow Windows call convention.
-@return the address of the imported function */
-extern "C"
-FARPROC WINAPI
-__delayLoadHelper2(
-/*===============*/
- PCImgDelayDescr pidd, /*!< in: a const pointer to a
- ImgDelayDescr, see delayimp.h. */
- FARPROC* iat_entry) /*!< in/out: A pointer to the slot in
- the delay load import address table
- to be updated with the address of the
- imported function. */
-{
- ulint iIAT, iINT;
- HMODULE hmod;
- PCImgThunkData pitd;
- FARPROC fun = NULL;
-
- /* Set up data used for the hook procs */
- InternalImgDelayDescr idd = {
- pidd->grAttrs,
- PFromRva<LPCSTR>(pidd->rvaDLLName),
- PFromRva<HMODULE*>(pidd->rvaHmod),
- PFromRva<PImgThunkData>(pidd->rvaIAT),
- PFromRva<PCImgThunkData>(pidd->rvaINT),
- PFromRva<PCImgThunkData>(pidd->rvaBoundIAT),
- PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT),
- pidd->dwTimeStamp
- };
-
- DelayLoadInfo dli = {
- sizeof(DelayLoadInfo),
- pidd,
- iat_entry,
- idd.szName,
- {0},
- 0,
- 0,
- 0
- };
-
- /* Check the Delay Load Attributes, log an error of invalid
- parameter, which happens if the attributes in pidd are not
- specified correctly. */
- if ((idd.grAttrs & dlattrRva) == 0) {
-
- sql_print_error("InnoDB: invalid parameter for delay loader.");
- return(0);
- }
-
- hmod = *idd.phmod;
-
- /* Calculate the index for the IAT entry in the import address table.
- The INT entries are ordered the same as the IAT entries so the
- calculation can be done on the IAT side. */
- iIAT = (PCImgThunkData) iat_entry - idd.pIAT;
- iINT = iIAT;
-
- pitd = &(idd.pINT[iINT]);
-
- dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal);
-
- if (dli.dlp.fImportByName) {
-
- dli.dlp.szProcName = (LPCSTR) (PFromRva<PIMAGE_IMPORT_BY_NAME>
- ((RVA) ((UINT_PTR) pitd->u1.AddressOfData))->Name);
- } else {
-
- dli.dlp.dwOrdinal = (ulint) IMAGE_ORDINAL(pitd->u1.Ordinal);
- }
-
- /* Now, load the mapfile, if it has not been done yet */
- if (hmod == 0) {
-
- hmod = wdl_get_mysqld_mapfile();
- }
-
- if (hmod == 0) {
- /* LoadLibrary failed. */
- PDelayLoadInfo rgpdli[1] = {&dli};
-
- dli.dwLastError = ::GetLastError();
-
- sql_print_error(
- "InnoDB: failed to load mysqld.map with error %d.",
- dli.dwLastError);
-
- return(0);
- }
-
- /* Store the library handle. */
- idd.phmod = &hmod;
-
- /* Go for the procedure now. */
- dli.hmodCur = hmod;
-
- if (pidd->rvaBoundIAT && pidd->dwTimeStamp) {
-
- /* Bound imports exist, check the timestamp from the target
- image */
- PIMAGE_NT_HEADERS pinh;
-
- pinh = (PIMAGE_NT_HEADERS) ((byte*) hmod
- + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew);
-
- if (pinh->Signature == IMAGE_NT_SIGNATURE
- && pinh->FileHeader.TimeDateStamp == idd.dwTimeStamp
- && (DWORD) hmod == pinh->OptionalHeader.ImageBase) {
-
- /* We have a decent address in the bound IAT. */
- fun = (FARPROC) (UINT_PTR)
- idd.pBoundIAT[iIAT].u1.Function;
-
- if (fun) {
-
- *iat_entry = fun;
- return(fun);
- }
- }
- }
-
- fun = wdl_get_procaddr_from_map(hmod, dli.dlp.szProcName);
-
- if (fun == 0) {
-
- return(0);
- }
-
- *iat_entry = fun;
- return(fun);
-}
-
-/*******************************************************************//**
-Unload a DLL that was delay loaded. This function is called by run-time.
-@return TRUE is returned if the DLL is found and the IAT matches the
-original one. */
-extern "C"
-BOOL WINAPI
-__FUnloadDelayLoadedDLL2(
-/*=====================*/
- LPCSTR module_name) /*!< in: DLL name */
-{
- return(TRUE);
-}
-
-/**************************************************************//**
-Load all imports from a DLL that was specified with the /delayload linker
-option.
-Note: this function is called by run-time. So, it has to follow Windows call
-convention.
-@return S_OK if the DLL matches, otherwise ERROR_MOD_NOT_FOUND is returned. */
-extern "C"
-HRESULT WINAPI
-__HrLoadAllImportsForDll(
-/*=====================*/
- LPCSTR module_name) /*!< in: DLL name */
-{
- PIMAGE_NT_HEADERS img;
- PCImgDelayDescr pidd;
- IMAGE_DATA_DIRECTORY* image_data;
- LPCSTR current_module;
- HRESULT ret = ERROR_MOD_NOT_FOUND;
- HMODULE hmod = (HMODULE) &__ImageBase;
-
- img = (PIMAGE_NT_HEADERS) ((byte*) hmod
- + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew);
- image_data =
- &img->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
-
- /* Scan the delay load IAT/INT for the DLL */
- if (image_data->Size) {
-
- pidd = PFromRva<PCImgDelayDescr>(image_data->VirtualAddress);
-
- /* Check all of the listed DLLs we want to load. */
- while (pidd->rvaDLLName) {
-
- current_module = PFromRva<LPCSTR>(pidd->rvaDLLName);
-
- if (stricmp(module_name, current_module) == 0) {
-
- /* Found it, break out with pidd and
- current_module set appropriately */
- break;
- }
-
- /* To the next delay import descriptor */
- pidd++;
- }
-
- if (pidd->rvaDLLName) {
-
- /* Found a matching DLL, now process it. */
- FARPROC* iat_entry;
- size_t count;
-
- iat_entry = PFromRva<FARPROC*>(pidd->rvaIAT);
- count = wdl_import_count((PCImgThunkData) iat_entry);
-
- /* now load all the imports from the DLL */
- while (count > 0) {
-
- /* No need to check the return value */
- __delayLoadHelper2(pidd, iat_entry);
- iat_entry++;
- count--;
- }
-
- ret = S_OK;
- }
- }
-
- return ret;
-}
-
-/**************************************************************//**
-The main function of a DLL
-@return TRUE if the call succeeds */
-BOOL
-WINAPI
-DllMain(
-/*====*/
- HINSTANCE hinstDLL, /*!< in: handle to the DLL module */
- DWORD fdwReason, /*!< Reason code that indicates why the
- DLL entry-point function is being
- called.*/
- LPVOID lpvReserved) /*!< in: additional parameter based on
- fdwReason */
-{
- BOOL success = TRUE;
-
- switch (fdwReason) {
-
- case DLL_PROCESS_ATTACH:
- success = wdl_get_external_variables();
- break;
-
- case DLL_PROCESS_DETACH:
- wdl_cleanup();
- break;
- }
-
- return(success);
-}
-
-#ifndef DBUG_OFF
-/**************************************************************//**
-Process entry point to user function. It makes the call to _db_enter_
-in mysqld.exe. The DBUG functions are defined in my_dbug.h. */
-extern "C" UNIV_INTERN
-void
-_db_enter_(
- const char* _func_, /*!< in: current function name */
- const char* _file_, /*!< in: current file name */
- uint _line_, /*!< in: current source line number */
- const char** _sfunc_, /*!< out: previous _func_ */
- const char** _sfile_, /*!< out: previous _file_ */
- uint* _slevel_, /*!< out: previous nesting level */
- char*** _sframep_) /*!< out: previous frame pointer */
-{
- if (wdl_db_enter_ != NULL) {
-
- wdl_db_enter_(_func_, _file_, _line_, _sfunc_, _sfile_,
- _slevel_, _sframep_);
- }
-}
-
-/**************************************************************//**
-Process exit from user function. It makes the call to _db_return_()
-in the server. */
-extern "C" UNIV_INTERN
-void
-_db_return_(
- uint _line_, /*!< in: current source line number */
- const char** _sfunc_, /*!< out: previous _func_ */
- const char** _sfile_, /*!< out: previous _file_ */
- uint* _slevel_) /*!< out: previous level */
-{
- if (wdl_db_return_ != NULL) {
-
- wdl_db_return_(_line_, _sfunc_, _sfile_, _slevel_);
- }
-}
-
-/**************************************************************//**
-Log arguments for subsequent use. It makes the call to _db_pargs_()
-in the server. */
-extern "C" UNIV_INTERN
-void
-_db_pargs_(
- uint _line_, /*!< in: current source line number */
- const char* keyword) /*!< in: keyword for current macro */
-{
- if (wdl_db_pargs_ != NULL) {
-
- wdl_db_pargs_(_line_, keyword);
- }
-}
-
-/**************************************************************//**
-Handle print of debug lines. It saves the text into a buffer first,
-then makes the call to _db_doprnt_() in the server. The text is
-truncated to the size of buffer. */
-extern "C" UNIV_INTERN
-void
-_db_doprnt_(
- const char* format, /*!< in: the format string */
- ...) /*!< in: list of arguments */
-{
- va_list argp;
- char buffer[512];
-
- if (wdl_db_doprnt_ != NULL) {
-
- va_start(argp, format);
- /* it is ok to ignore the trunction. */
- _vsnprintf(buffer, sizeof(buffer), format, argp);
- wdl_db_doprnt_(buffer);
- va_end(argp);
- }
-}
-
-/**************************************************************//**
-Dump a string in hex. It makes the call to _db_dump_() in the server. */
-extern "C" UNIV_INTERN
-void
-_db_dump_(
- uint _line_, /*!< in: current source line
- number */
- const char* keyword, /*!< in: keyword list */
- const unsigned char* memory, /*!< in: memory to dump */
- size_t length) /*!< in: bytes to dump */
-{
- if (wdl_db_dump_ != NULL) {
-
- wdl_db_dump_(_line_, keyword, memory, length);
- }
-}
-
-#endif /* !DBUG_OFF */
-#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */