diff options
author | Sergei Golubchik <sergii@pisem.net> | 2010-03-15 12:51:23 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2010-03-15 12:51:23 +0100 |
commit | f09ca00e088b316441bb76e97ba097bc9f3da7d3 (patch) | |
tree | 1a557d74018ed9cd073b5aa960bd62421962e73d /storage | |
parent | 2ceaffc4672c62a772890da7761d11f13d3f5ee4 (diff) | |
parent | 71b3e46b0160936596195682a731703900fb4fff (diff) | |
download | mariadb-git-f09ca00e088b316441bb76e97ba097bc9f3da7d3.tar.gz |
merged
Diffstat (limited to 'storage')
36 files changed, 544 insertions, 285 deletions
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 5b67782a868..ad54782996c 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -1490,7 +1490,7 @@ int ha_archive::info(uint flag) stats.create_time= (ulong) file_stat.st_ctime; stats.update_time= (ulong) file_stat.st_mtime; stats.mean_rec_length= stats.records ? - stats.data_file_length / stats.records : table->s->reclength; + ulong(stats.data_file_length / stats.records) : table->s->reclength; stats.max_data_file_length= MAX_FILE_SIZE; } stats.delete_length= 0; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index e06f39c073f..2c74b2f6675 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1783,7 +1783,7 @@ int ha_federatedx::open(const char *name, int mode, uint test_if_locked) int ha_federatedx::close(void) { - int retval, error; + int retval= 0, error; THD *thd= current_thd; DBUG_ENTER("ha_federatedx::close"); diff --git a/storage/ibmdb2i/db2i_constraints.cc b/storage/ibmdb2i/db2i_constraints.cc index 9a96eda1173..1fde0dd3d14 100644 --- a/storage/ibmdb2i/db2i_constraints.cc +++ b/storage/ibmdb2i/db2i_constraints.cc @@ -329,7 +329,7 @@ char* ha_ibmdb2i::get_foreign_key_create_info(void) /* Process the constraint name. */ - info.strncat(STRING_WITH_LEN(" CONSTRAINT ")); + info.strncat(STRING_WITH_LEN(",\n CONSTRAINT ")); convNameForCreateInfo(thd, info, FKCstDef->CstName.Name, FKCstDef->CstName.Len); @@ -398,7 +398,6 @@ char* ha_ibmdb2i::get_foreign_key_create_info(void) if ((i+1) < cstCnt) { - info.strcat(','); tempPtr = (char*)cstHdr + cstHdr->CstLen; cstHdr = (constraint_hdr_t*)(tempPtr); } @@ -671,28 +670,3 @@ uint ha_ibmdb2i::referenced_by_foreign_key(void) } DBUG_RETURN(count); } - - -bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info, - uint table_changes) -{ - DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data"); - uint i; - /* Check that auto_increment value and field definitions were - not changed. */ - if ((info->used_fields & HA_CREATE_USED_AUTO && - info->auto_increment_value != 0) || - table_changes != IS_EQUAL_YES) - DBUG_RETURN(COMPATIBLE_DATA_NO); - /* Check if any fields were renamed. */ - for (i= 0; i < table->s->fields; i++) - { - Field *field= table->field[i]; - if (field->flags & FIELD_IS_RENAMED) - { - DBUG_PRINT("info", ("Field has been renamed, copy table")); - DBUG_RETURN(COMPATIBLE_DATA_NO); - } - } - DBUG_RETURN(COMPATIBLE_DATA_YES); -} diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc index 0fc2d1e83dc..39096be7848 100644 --- a/storage/ibmdb2i/ha_ibmdb2i.cc +++ b/storage/ibmdb2i/ha_ibmdb2i.cc @@ -284,7 +284,7 @@ static int ibmdb2i_init_func(void *p) was_ILE_inited = false; ibmdb2i_hton= (handlerton *)p; VOID(pthread_mutex_init(&ibmdb2i_mutex,MY_MUTEX_INIT_FAST)); - (void) hash_init(&ibmdb2i_open_tables,system_charset_info,32,0,0, + (void) hash_init(&ibmdb2i_open_tables,table_alias_charset,32,0,0, (hash_get_key) ibmdb2i_get_key,0,0); ibmdb2i_hton->state= SHOW_OPTION_YES; diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 42e5166c9e4..3810fefd3cb 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -1740,6 +1740,8 @@ fil_op_write_log( MLOG_FILE_DELETE, or MLOG_FILE_RENAME */ ulint space_id, /* in: space id */ + ulint log_flags, /* in: redo log flags (stored + in the page number field) */ const char* name, /* in: table name in the familiar 'databasename/tablename' format, or the file path in the case of @@ -1760,8 +1762,8 @@ fil_op_write_log( return; } - log_ptr = mlog_write_initial_log_record_for_file_op(type, space_id, 0, - log_ptr, mtr); + log_ptr = mlog_write_initial_log_record_for_file_op( + type, space_id, log_flags, log_ptr, mtr); /* Let us store the strings as null-terminated for easier readability and handling */ @@ -1810,11 +1812,11 @@ fil_op_log_parse_or_replay( not fir completely between ptr and end_ptr */ byte* end_ptr, /* in: buffer end */ ulint type, /* in: the type of this log record */ - ibool do_replay, /* in: TRUE if we want to replay the - operation, and not just parse the log record */ - ulint space_id) /* in: if do_replay is TRUE, the space id of - the tablespace in question; otherwise - ignored */ + ulint space_id, /* in: the space id of the tablespace in + question, or 0 if the log record should + only be parsed but not replayed */ + ulint log_flags) /* in: redo log flags + (stored in the page number parameter) */ { ulint name_len; ulint new_name_len; @@ -1868,7 +1870,7 @@ fil_op_log_parse_or_replay( printf("new name %s\n", new_name); } */ - if (do_replay == FALSE) { + if (!space_id) { return(ptr); } @@ -1917,6 +1919,8 @@ fil_op_log_parse_or_replay( } else if (fil_get_space_id_for_table(name) != ULINT_UNDEFINED) { /* Do nothing */ + } else if (log_flags & MLOG_FILE_FLAG_TEMP) { + /* Temporary table, do nothing */ } else { /* Create the database directory for name, if it does not exist yet */ @@ -2078,7 +2082,7 @@ try_again: to write any log record */ mtr_start(&mtr); - fil_op_write_log(MLOG_FILE_DELETE, id, path, NULL, &mtr); + fil_op_write_log(MLOG_FILE_DELETE, id, 0, path, NULL, &mtr); mtr_commit(&mtr); #endif mem_free(path); @@ -2349,7 +2353,7 @@ retry: mtr_start(&mtr); - fil_op_write_log(MLOG_FILE_RENAME, id, old_name, new_name, + fil_op_write_log(MLOG_FILE_RENAME, id, 0, old_name, new_name, &mtr); mtr_commit(&mtr); } @@ -2525,8 +2529,9 @@ error_exit2: mtr_start(&mtr); - fil_op_write_log(MLOG_FILE_CREATE, *space_id, tablename, - NULL, &mtr); + fil_op_write_log(MLOG_FILE_CREATE, *space_id, + is_temp ? MLOG_FILE_FLAG_TEMP : 0, + tablename, NULL, &mtr); mtr_commit(&mtr); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e2a76758888..08b4d39052a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -40,12 +40,6 @@ have disabled the InnoDB inlining in this file. */ #include "ha_innodb.h" #include <mysql/plugin.h> -#ifndef MYSQL_SERVER -/* 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 pthread_mutex_t LOCK_thread_count; -#endif /* MYSQL_SERVER */ - /** to protect innobase_open_files */ static pthread_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ @@ -2592,57 +2586,150 @@ normalize_table_name( } /************************************************************************ +Get the upper limit of the MySQL integral and floating-point type. */ +static +ulonglong +innobase_get_int_col_max_value( +/*===========================*/ + /* out: maximum allowed value for the field */ + const Field* field) /* in: MySQL field */ +{ + ulonglong max_value = 0; + + switch(field->key_type()) { + /* TINY */ + case HA_KEYTYPE_BINARY: + max_value = 0xFFULL; + break; + case HA_KEYTYPE_INT8: + max_value = 0x7FULL; + break; + /* SHORT */ + case HA_KEYTYPE_USHORT_INT: + max_value = 0xFFFFULL; + break; + case HA_KEYTYPE_SHORT_INT: + max_value = 0x7FFFULL; + break; + /* MEDIUM */ + case HA_KEYTYPE_UINT24: + max_value = 0xFFFFFFULL; + break; + case HA_KEYTYPE_INT24: + max_value = 0x7FFFFFULL; + break; + /* LONG */ + case HA_KEYTYPE_ULONG_INT: + max_value = 0xFFFFFFFFULL; + break; + case HA_KEYTYPE_LONG_INT: + max_value = 0x7FFFFFFFULL; + break; + /* BIG */ + case HA_KEYTYPE_ULONGLONG: + max_value = 0xFFFFFFFFFFFFFFFFULL; + break; + case HA_KEYTYPE_LONGLONG: + max_value = 0x7FFFFFFFFFFFFFFFULL; + break; + case HA_KEYTYPE_FLOAT: + /* We use the maximum as per IEEE754-2008 standard, 2^24 */ + max_value = 0x1000000ULL; + break; + case HA_KEYTYPE_DOUBLE: + /* We use the maximum as per IEEE754-2008 standard, 2^53 */ + max_value = 0x20000000000000ULL; + break; + default: + ut_error; + } + + return(max_value); +} + +/************************************************************************ Set the autoinc column max value. This should only be called once from ha_innobase::open(). Therefore there's no need for a covering lock. */ -ulong +void ha_innobase::innobase_initialize_autoinc() /*======================================*/ { - dict_index_t* index; ulonglong auto_inc; - const char* col_name; - ulint error = DB_SUCCESS; - dict_table_t* innodb_table = prebuilt->table; - - col_name = table->found_next_number_field->field_name; - index = innobase_get_index(table->s->next_number_index); - - /* Execute SELECT MAX(col_name) FROM TABLE; */ - error = row_search_max_autoinc(index, col_name, &auto_inc); + const Field* field = table->found_next_number_field; - if (error == DB_SUCCESS) { + if (field != NULL) { + auto_inc = innobase_get_int_col_max_value(field); + } else { + /* We have no idea what's been passed in to us as the + autoinc column. We set it to the MAX_INT of our table + autoinc type. */ + auto_inc = 0xFFFFFFFFFFFFFFFFULL; - /* At the this stage we dont' know the increment - or the offset, so use default inrement of 1. */ - ++auto_inc; + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Unable to determine the AUTOINC " + "column name\n"); + } - dict_table_autoinc_initialize(innodb_table, auto_inc); + if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { + /* If the recovery level is set so high that writes + are disabled we force the AUTOINC counter to the MAX + value effectively disabling writes to the table. + Secondly, we avoid reading the table in case the read + results in failure due to a corrupted table/index. + + We will not return an error to the client, so that the + tables can be dumped with minimal hassle. If an error + were returned in this case, the first attempt to read + the table would fail and subsequent SELECTs would succeed. */ + } else if (field == NULL) { + my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + } else { + dict_index_t* index; + const char* col_name; + ulonglong read_auto_inc; + ulint err; - } else if (error == DB_RECORD_NOT_FOUND) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: MySQL and InnoDB data " - "dictionaries are out of sync.\n" - "InnoDB: Unable to find the AUTOINC column %s in the " - "InnoDB table %s.\n" - "InnoDB: We set the next AUTOINC column value to the " - "maximum possible value,\n" - "InnoDB: in effect disabling the AUTOINC next value " - "generation.\n" - "InnoDB: You can either set the next AUTOINC value " - "explicitly using ALTER TABLE\n" - "InnoDB: or fix the data dictionary by recreating " - "the table.\n", - col_name, index->table->name); + update_thd(ha_thd()); + col_name = field->field_name; + index = innobase_get_index(table->s->next_number_index); - auto_inc = 0xFFFFFFFFFFFFFFFFULL; + /* Execute SELECT MAX(col_name) FROM TABLE; */ + err = row_search_max_autoinc(index, col_name, &read_auto_inc); - dict_table_autoinc_initialize(innodb_table, auto_inc); + switch (err) { + case DB_SUCCESS: + /* At the this stage we do not know the increment + or the offset, so use a default increment of 1. */ + auto_inc = read_auto_inc + 1; + break; - error = DB_SUCCESS; - } /* else other errors are still fatal */ + case DB_RECORD_NOT_FOUND: + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: MySQL and InnoDB data " + "dictionaries are out of sync.\n" + "InnoDB: Unable to find the AUTOINC column " + "%s in the InnoDB table %s.\n" + "InnoDB: We set the next AUTOINC column " + "value to the maximum possible value,\n" + "InnoDB: in effect disabling the AUTOINC " + "next value generation.\n" + "InnoDB: You can either set the next " + "AUTOINC value explicitly using ALTER TABLE\n" + "InnoDB: or fix the data dictionary by " + "recreating the table.\n", + col_name, index->table->name); + + my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + break; + default: + /* row_search_max_autoinc() should only return + one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */ + ut_error; + } + } - return(ulong(error)); + dict_table_autoinc_initialize(prebuilt->table, auto_inc); } /********************************************************************* @@ -2840,8 +2927,6 @@ retry: /* Only if the table has an AUTOINC column. */ if (prebuilt->table != NULL && table->found_next_number_field != NULL) { - ulint error; - dict_table_autoinc_lock(prebuilt->table); /* Since a table can already be "open" in InnoDB's internal @@ -2850,8 +2935,7 @@ retry: autoinc value from a previous MySQL open. */ if (dict_table_autoinc_read(prebuilt->table) == 0) { - error = innobase_initialize_autoinc(); - ut_a(error == DB_SUCCESS); + innobase_initialize_autoinc(); } dict_table_autoinc_unlock(prebuilt->table); @@ -3672,67 +3756,6 @@ skip_field: } /************************************************************************ -Get the upper limit of the MySQL integral and floating-point type. */ - -ulonglong -ha_innobase::innobase_get_int_col_max_value( -/*========================================*/ - const Field* field) -{ - ulonglong max_value = 0; - - switch(field->key_type()) { - /* TINY */ - case HA_KEYTYPE_BINARY: - max_value = 0xFFULL; - break; - case HA_KEYTYPE_INT8: - max_value = 0x7FULL; - break; - /* SHORT */ - case HA_KEYTYPE_USHORT_INT: - max_value = 0xFFFFULL; - break; - case HA_KEYTYPE_SHORT_INT: - max_value = 0x7FFFULL; - break; - /* MEDIUM */ - case HA_KEYTYPE_UINT24: - max_value = 0xFFFFFFULL; - break; - case HA_KEYTYPE_INT24: - max_value = 0x7FFFFFULL; - break; - /* LONG */ - case HA_KEYTYPE_ULONG_INT: - max_value = 0xFFFFFFFFULL; - break; - case HA_KEYTYPE_LONG_INT: - max_value = 0x7FFFFFFFULL; - break; - /* BIG */ - case HA_KEYTYPE_ULONGLONG: - max_value = 0xFFFFFFFFFFFFFFFFULL; - break; - case HA_KEYTYPE_LONGLONG: - max_value = 0x7FFFFFFFFFFFFFFFULL; - break; - case HA_KEYTYPE_FLOAT: - /* We use the maximum as per IEEE754-2008 standard, 2^24 */ - max_value = 0x1000000ULL; - break; - case HA_KEYTYPE_DOUBLE: - /* We use the maximum as per IEEE754-2008 standard, 2^53 */ - max_value = 0x20000000000000ULL; - break; - default: - ut_error; - } - - return(max_value); -} - -/************************************************************************ This special handling is really to overcome the limitations of MySQL's binlogging. We need to eliminate the non-determinism that will arise in INSERT ... SELECT type of statements, since MySQL binlog only stores the @@ -7421,8 +7444,8 @@ innodb_show_status( mutex_enter_noninline(&srv_monitor_file_mutex); rewind(srv_monitor_file); - srv_printf_innodb_monitor(srv_monitor_file, - &trx_list_start, &trx_list_end); + srv_printf_innodb_monitor(srv_monitor_file, FALSE, + &trx_list_start, &trx_list_end); flen = ftell(srv_monitor_file); os_file_set_eof(srv_monitor_file); diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 6d66b6456fb..bed064d9d84 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -78,9 +78,8 @@ class ha_innobase: public handler ulong innobase_reset_autoinc(ulonglong auto_inc); ulong innobase_get_autoinc(ulonglong* value); ulong innobase_update_autoinc(ulonglong auto_inc); - ulong innobase_initialize_autoinc(); + void innobase_initialize_autoinc(); dict_index_t* innobase_get_index(uint keynr); - ulonglong innobase_get_int_col_max_value(const Field* field); /* Init values for the class: */ public: diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 6b8fd4b03d5..251d6c22547 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -330,11 +330,11 @@ fil_op_log_parse_or_replay( not fir completely between ptr and end_ptr */ byte* end_ptr, /* in: buffer end */ ulint type, /* in: the type of this log record */ - ibool do_replay, /* in: TRUE if we want to replay the - operation, and not just parse the log record */ - ulint space_id); /* in: if do_replay is TRUE, the space id of - the tablespace in question; otherwise - ignored */ + ulint space_id, /* in: the space id of the tablespace in + question, or 0 if the log record should + only be parsed but not replayed */ + ulint log_flags); /* in: redo log flags + (stored in the page number parameter) */ /*********************************************************************** Deletes a single-table tablespace. The tablespace must be cached in the memory cache. */ diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 635724bf5a1..beaf17eda01 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -579,10 +579,15 @@ lock_rec_print( /************************************************************************* Prints info of locks for all transactions. */ -void +ibool lock_print_info_summary( /*====================*/ - FILE* file); /* in: file where to print */ + /* out: FALSE if not able to obtain + kernel mutex and exits without + printing info */ + FILE* file, /* in: file where to print */ + ibool nowait);/* in: whether to wait for the kernel + mutex */ /************************************************************************* Prints info of locks for each transaction. */ diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 2a160d27e0c..a6e2976830b 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -134,6 +134,12 @@ flag value must give the length also! */ #define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in asserts) */ +/* Flags for MLOG_FILE operations (stored in the page number +parameter, called log_flags in the functions). The page number +parameter was initially written as 0. */ +#define MLOG_FILE_FLAG_TEMP 1 /* identifies TEMPORARY TABLE in + MLOG_FILE_CREATE */ + /******************************************************************* Starts a mini-transaction and creates a mini-transaction handle and buffer in the memory buffer given by the caller. */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 67144a41d3d..3dd4bb961f9 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -146,7 +146,8 @@ extern ibool srv_print_innodb_tablespace_monitor; extern ibool srv_print_verbose_log; extern ibool srv_print_innodb_table_monitor; -extern ibool srv_lock_timeout_and_monitor_active; +extern ibool srv_lock_timeout_active; +extern ibool srv_monitor_active; extern ibool srv_error_monitor_active; extern ulong srv_n_spin_wait_rounds; @@ -427,12 +428,21 @@ srv_release_mysql_thread_if_suspended( que_thr_t* thr); /* in: query thread associated with the MySQL OS thread */ /************************************************************************* -A thread which wakes up threads whose lock wait may have lasted too long. -This also prints the info output by various InnoDB monitors. */ +A thread which wakes up threads whose lock wait may have lasted too +long. */ os_thread_ret_t -srv_lock_timeout_and_monitor_thread( -/*================================*/ +srv_lock_timeout_thread( +/*====================*/ + /* out: a dummy parameter */ + void* arg); /* in: a dummy parameter required by + os_thread_create */ +/************************************************************************* +A thread which prints the info output by various InnoDB monitors. */ + +os_thread_ret_t +srv_monitor_thread( +/*===============*/ /* out: a dummy parameter */ void* arg); /* in: a dummy parameter required by os_thread_create */ @@ -449,10 +459,14 @@ srv_error_monitor_thread( /********************************************************************** Outputs to a file the output of the InnoDB Monitor. */ -void +ibool srv_printf_innodb_monitor( /*======================*/ + /* out: FALSE if not all information printed + due to failure to obtain necessary mutex */ FILE* file, /* in: output stream */ + ibool nowait, /* in: whether to wait for kernel + mutex. */ ulint* trx_start, /* out: file position of the start of the list of active transactions */ ulint* trx_end); /* out: file position of the end of diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 80aef45ea35..4cc10931060 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -4192,12 +4192,27 @@ lock_get_n_rec_locks(void) /************************************************************************* Prints info of locks for all transactions. */ -void +ibool lock_print_info_summary( /*====================*/ - FILE* file) /* in: file where to print */ + /* out: FALSE if not able to obtain + kernel mutex and exit without + printing lock info */ + FILE* file, /* in: file where to print */ + ibool nowait) /* in: whether to wait for the kernel + mutex */ { - lock_mutex_enter_kernel(); + + /* if nowait is FALSE, wait on the kernel mutex, + otherwise return immediately if fail to obtain the + mutex. */ + if (!nowait) { + lock_mutex_enter_kernel(); + } else if (mutex_enter_nowait(&kernel_mutex)) { + fputs("FAIL TO OBTAIN KERNEL MUTEX, " + "SKIP LOCK INFO PRINTING\n", file); + return(FALSE); + } if (lock_deadlock_found) { fputs("------------------------\n" @@ -4231,6 +4246,7 @@ lock_print_info_summary( "Total number of lock structs in row lock hash table %lu\n", (ulong) lock_get_n_rec_locks()); #endif /* PRINT_NUM_OF_LOCK_STRUCTS */ + return(TRUE); } /************************************************************************* diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c index b10c348b24d..3300997112b 100644 --- a/storage/innobase/log/log0log.c +++ b/storage/innobase/log/log0log.c @@ -3045,7 +3045,7 @@ loop: if (srv_fast_shutdown < 2 && (srv_error_monitor_active - || srv_lock_timeout_and_monitor_active)) { + || srv_lock_timeout_active || srv_monitor_active)) { mutex_exit(&kernel_mutex); diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index aef58b7b576..5d309768064 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -939,8 +939,7 @@ recv_parse_or_apply_log_rec_body( case MLOG_FILE_CREATE: case MLOG_FILE_RENAME: case MLOG_FILE_DELETE: - ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE, - ULINT_UNDEFINED); + ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, 0, 0); break; default: ptr = NULL; @@ -1938,8 +1937,8 @@ loop: point to the datadir we should use there */ if (NULL == fil_op_log_parse_or_replay( - body, end_ptr, type, TRUE, - space)) { + body, end_ptr, type, + space, page_no)) { fprintf(stderr, "InnoDB: Error: file op" " log record of type %lu" diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 4fcb1fbf9f2..f7156403247 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -3245,19 +3245,13 @@ check_next_foreign: "END;\n" , FALSE, trx); - if (err != DB_SUCCESS) { - ut_a(err == DB_OUT_OF_FILE_SPACE); - - err = DB_MUST_GET_MORE_FILE_SPACE; - - row_mysql_handle_errors(&err, trx, NULL, NULL); - - ut_error; - } else { + switch (err) { ibool is_path; const char* name_or_path; mem_heap_t* heap; + case DB_SUCCESS: + heap = mem_heap_create(200); /* Clone the name, in case it has been allocated @@ -3322,7 +3316,27 @@ check_next_foreign: } mem_heap_free(heap); + break; + + case DB_TOO_MANY_CONCURRENT_TRXS: + /* Cannot even find a free slot for the + the undo log. We can directly exit here + and return the DB_TOO_MANY_CONCURRENT_TRXS + error. */ + break; + + case DB_OUT_OF_FILE_SPACE: + err = DB_MUST_GET_MORE_FILE_SPACE; + + row_mysql_handle_errors(&err, trx, NULL, NULL); + + /* Fall through to raise error */ + + default: + /* No other possible error returns */ + ut_error; } + funct_exit: trx_commit_for_mysql(trx); diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index 71e74ab848b..26ea7958d0d 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -64,7 +64,8 @@ ulint srv_fatal_semaphore_wait_threshold = 600; in microseconds, in order to reduce the lagging of the purge thread. */ ulint srv_dml_needed_delay = 0; -ibool srv_lock_timeout_and_monitor_active = FALSE; +ibool srv_lock_timeout_active = FALSE; +ibool srv_monitor_active = FALSE; ibool srv_error_monitor_active = FALSE; const char* srv_main_thread_op_info = ""; @@ -122,6 +123,16 @@ ulint srv_log_file_size = ULINT_MAX; /* size in database pages */ ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */ ulong srv_flush_log_at_trx_commit = 1; +/* Maximum number of times allowed to conditionally acquire +mutex before switching to blocking wait on the mutex */ +#define MAX_MUTEX_NOWAIT 20 + +/* Check whether the number of failed nonblocking mutex +acquisition attempts exceeds maximum allowed value. If so, +srv_printf_innodb_monitor() will request mutex acquisition +with mutex_enter(), which will wait until it gets the mutex. */ +#define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT) + byte srv_latin1_ordering[256] /* The sort order table of the latin1 character set. The following table is the MySQL order as of Feb 10th, 2002 */ @@ -1626,10 +1637,13 @@ srv_refresh_innodb_monitor_stats(void) /********************************************************************** Outputs to a file the output of the InnoDB Monitor. */ -void +ibool srv_printf_innodb_monitor( /*======================*/ + /* out: FALSE if not all information printed + due to failure to obtain necessary mutex */ FILE* file, /* in: output stream */ + ibool nowait, /* in: whether to wait for the mutex. */ ulint* trx_start, /* out: file position of the start of the list of active transactions */ ulint* trx_end) /* out: file position of the end of @@ -1638,6 +1652,7 @@ srv_printf_innodb_monitor( double time_elapsed; time_t current_time; ulint n_reserved; + ibool ret; mutex_enter(&srv_innodb_monitor_mutex); @@ -1682,24 +1697,31 @@ srv_printf_innodb_monitor( mutex_exit(&dict_foreign_err_mutex); - lock_print_info_summary(file); - if (trx_start) { - long t = ftell(file); - if (t < 0) { - *trx_start = ULINT_UNDEFINED; - } else { - *trx_start = (ulint) t; + /* Only if lock_print_info_summary proceeds correctly, + before we call the lock_print_info_all_transactions + to print all the lock information. */ + ret = lock_print_info_summary(file, nowait); + + if (ret) { + if (trx_start) { + long t = ftell(file); + if (t < 0) { + *trx_start = ULINT_UNDEFINED; + } else { + *trx_start = (ulint) t; + } } - } - lock_print_info_all_transactions(file); - if (trx_end) { - long t = ftell(file); - if (t < 0) { - *trx_end = ULINT_UNDEFINED; - } else { - *trx_end = (ulint) t; + lock_print_info_all_transactions(file); + if (trx_end) { + long t = ftell(file); + if (t < 0) { + *trx_end = ULINT_UNDEFINED; + } else { + *trx_end = (ulint) t; + } } } + fputs("--------\n" "FILE I/O\n" "--------\n", file); @@ -1804,6 +1826,8 @@ srv_printf_innodb_monitor( "============================\n", file); mutex_exit(&srv_innodb_monitor_mutex); fflush(file); + + return(ret); } /********************************************************************** @@ -1883,26 +1907,23 @@ srv_export_innodb_status(void) } /************************************************************************* -A thread which wakes up threads whose lock wait may have lasted too long. -This also prints the info output by various InnoDB monitors. */ +A thread prints the info output by various InnoDB monitors. */ os_thread_ret_t -srv_lock_timeout_and_monitor_thread( -/*================================*/ +srv_monitor_thread( +/*===============*/ /* out: a dummy parameter */ void* arg __attribute__((unused))) /* in: a dummy parameter required by os_thread_create */ { - srv_slot_t* slot; double time_elapsed; time_t current_time; time_t last_table_monitor_time; time_t last_tablespace_monitor_time; time_t last_monitor_time; - ibool some_waits; - double wait_time; - ulint i; + ulint mutex_skipped; + ibool last_srv_print_monitor; #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Lock timeout thread starts, id %lu\n", @@ -1913,13 +1934,15 @@ srv_lock_timeout_and_monitor_thread( last_table_monitor_time = time(NULL); last_tablespace_monitor_time = time(NULL); last_monitor_time = time(NULL); + mutex_skipped = 0; + last_srv_print_monitor = srv_print_innodb_monitor; loop: - srv_lock_timeout_and_monitor_active = TRUE; + srv_monitor_active = TRUE; - /* When someone is waiting for a lock, we wake up every second - and check if a timeout has passed for a lock wait */ + /* Wake up every 5 seconds to see if we need to print + monitor information. */ - os_thread_sleep(1000000); + os_thread_sleep(5000000); current_time = time(NULL); @@ -1929,14 +1952,40 @@ loop: last_monitor_time = time(NULL); if (srv_print_innodb_monitor) { - srv_printf_innodb_monitor(stderr, NULL, NULL); + /* Reset mutex_skipped counter everytime + srv_print_innodb_monitor changes. This is to + ensure we will not be blocked by kernel_mutex + for short duration information printing, + such as requested by sync_array_print_long_waits() */ + if (!last_srv_print_monitor) { + mutex_skipped = 0; + last_srv_print_monitor = TRUE; + } + + if (!srv_printf_innodb_monitor(stderr, + MUTEX_NOWAIT(mutex_skipped), + NULL, NULL)) { + mutex_skipped++; + } else { + /* Reset the counter */ + mutex_skipped = 0; + } + } else { + last_srv_print_monitor = FALSE; } + if (srv_innodb_status) { mutex_enter(&srv_monitor_file_mutex); rewind(srv_monitor_file); - srv_printf_innodb_monitor(srv_monitor_file, NULL, - NULL); + if (!srv_printf_innodb_monitor(srv_monitor_file, + MUTEX_NOWAIT(mutex_skipped), + NULL, NULL)) { + mutex_skipped++; + } else { + mutex_skipped = 0; + } + os_file_set_eof(srv_monitor_file); mutex_exit(&srv_monitor_file_mutex); } @@ -1989,6 +2038,56 @@ loop: } } + if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) { + goto exit_func; + } + + if (srv_print_innodb_monitor + || srv_print_innodb_lock_monitor + || srv_print_innodb_tablespace_monitor + || srv_print_innodb_table_monitor) { + goto loop; + } + + srv_monitor_active = FALSE; + + goto loop; + +exit_func: + srv_monitor_active = FALSE; + + /* We count the number of threads in os_thread_exit(). A created + thread should always use that to exit and not use return() to exit. */ + + os_thread_exit(NULL); + + OS_THREAD_DUMMY_RETURN; +} + +/************************************************************************* +A thread which wakes up threads whose lock wait may have lasted too long. */ + +os_thread_ret_t +srv_lock_timeout_thread( +/*====================*/ + /* out: a dummy parameter */ + void* arg __attribute__((unused))) + /* in: a dummy parameter required by + os_thread_create */ +{ + srv_slot_t* slot; + ibool some_waits; + double wait_time; + ulint i; + +loop: + /* When someone is waiting for a lock, we wake up every second + and check if a timeout has passed for a lock wait */ + + os_thread_sleep(1000000); + + srv_lock_timeout_active = TRUE; + mutex_enter(&kernel_mutex); some_waits = FALSE; @@ -2033,17 +2132,11 @@ loop: goto exit_func; } - if (some_waits || srv_print_innodb_monitor - || srv_print_innodb_lock_monitor - || srv_print_innodb_tablespace_monitor - || srv_print_innodb_table_monitor) { + if (some_waits) { goto loop; } - /* No one was waiting for a lock and no monitor was active: - suspend this thread */ - - srv_lock_timeout_and_monitor_active = FALSE; + srv_lock_timeout_active = FALSE; #if 0 /* The following synchronisation is disabled, since @@ -2053,7 +2146,7 @@ loop: goto loop; exit_func: - srv_lock_timeout_and_monitor_active = FALSE; + srv_lock_timeout_active = FALSE; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index 4f261d1171b..d117ff16608 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -87,8 +87,8 @@ static os_file_t files[1000]; static mutex_t ios_mutex; static ulint ios; -static ulint n[SRV_MAX_N_IO_THREADS + 5]; -static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5]; +static ulint n[SRV_MAX_N_IO_THREADS + 6]; +static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6]; /* We use this mutex to test the return value of pthread_mutex_trylock on successful locking. HP-UX does NOT return 0, though Linux et al do. */ @@ -1596,15 +1596,20 @@ innobase_start_or_create_for_mysql(void) /* fprintf(stderr, "Max allowed record size %lu\n", page_get_free_space_of_empty() / 2); */ - /* Create the thread which watches the timeouts for lock waits - and prints InnoDB monitor info */ + /* Create the thread which watches the timeouts for lock + waits */ - os_thread_create(&srv_lock_timeout_and_monitor_thread, NULL, + os_thread_create(&srv_lock_timeout_thread, NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); /* Create the thread which warns of long semaphore waits */ os_thread_create(&srv_error_monitor_thread, NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); + + /* Create the thread which prints InnoDB monitor info */ + os_thread_create(&srv_monitor_thread, NULL, + thread_ids + 4 + SRV_MAX_N_IO_THREADS); + srv_was_started = TRUE; srv_is_being_started = FALSE; diff --git a/storage/innodb_plugin/CMakeLists.txt b/storage/innodb_plugin/CMakeLists.txt index 7900d1629dd..36e157ae736 100644 --- a/storage/innodb_plugin/CMakeLists.txt +++ b/storage/innodb_plugin/CMakeLists.txt @@ -83,4 +83,4 @@ SET(INNODB_PLUGIN_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) #Disable storage engine, as we are using XtraDB -#MYSQL_STORAGE_ENGINE(INNOBASE) +#MYSQL_STORAGE_ENGINE(INNODB_PLUGIN) diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index b51e9186fe4..47b8203091c 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -110,9 +110,6 @@ extern "C" { # 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; #if MYSQL_VERSION_ID < 50124 /* this is defined in mysql_priv.h inside #ifdef MYSQL_SERVER diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 4da650a5f00..459edc45a94 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -3316,11 +3316,11 @@ static struct st_mysql_sys_var* system_variables[]= { MYSQL_SYSVAR(force_start_after_recovery_failures), MYSQL_SYSVAR(group_commit), MYSQL_SYSVAR(group_commit_interval), - MYSQL_SYSVAR(page_checksum), MYSQL_SYSVAR(log_dir_path), MYSQL_SYSVAR(log_file_size), MYSQL_SYSVAR(log_purge_type), MYSQL_SYSVAR(max_sort_file_size), + MYSQL_SYSVAR(page_checksum), MYSQL_SYSVAR(pagecache_age_threshold), MYSQL_SYSVAR(pagecache_buffer_size), MYSQL_SYSVAR(pagecache_division_limit), diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 5b0a2ac8884..0e9e5caafbf 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -169,6 +169,8 @@ my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key) MARIA_KEY org_key; DBUG_ENTER("_ma_ck_delete"); + LINT_INIT_STRUCT(org_key); + save_key_data= key->data; if (share->now_transactional) { diff --git a/storage/maria/ma_key_recover.h b/storage/maria/ma_key_recover.h index 4b4198f3008..b580433c99a 100644 --- a/storage/maria/ma_key_recover.h +++ b/storage/maria/ma_key_recover.h @@ -63,7 +63,6 @@ extern my_bool write_hook_for_undo_key_insert(enum translog_record_type type, extern my_bool write_hook_for_undo_key_delete(enum translog_record_type type, TRN *trn, MARIA_HA *tbl_info, LSN *lsn, void *hook_arg); -void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn); my_bool _ma_log_prefix(MARIA_PAGE *page, uint changed_length, int move_length); my_bool _ma_log_suffix(MARIA_PAGE *page, uint org_length, diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 73a2737b223..476b091594e 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -1457,6 +1457,7 @@ LSN translog_get_file_max_lsn_stored(uint32 file) { LOGHANDLER_FILE_INFO info; + LINT_INIT_STRUCT(info); File fd= open_logfile_by_number_no_cache(file); if ((fd < 0) || (translog_read_file_header(&info, fd) | my_close(fd, MYF(MY_WME)))) diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index 54361b8ee3b..acbee2a6f07 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -64,6 +64,15 @@ void _ma_page_setup(MARIA_PAGE *page, MARIA_HA *info, share->base.key_reflength : 0); } +#ifdef IDENTICAL_PAGES_AFTER_RECOVERY +void page_cleanup(MARIA_SHARE *share, MARIA_PAGE *page) +{ + uint length= page->size; + DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE); + bzero(page->buff + length, share->block_size - length); +} +#endif + /** Fetch a key-page in memory @@ -102,8 +111,10 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, if (lock != PAGECACHE_LOCK_LEFT_UNLOCKED) { - DBUG_ASSERT(lock == PAGECACHE_LOCK_WRITE); - page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + DBUG_ASSERT(lock == PAGECACHE_LOCK_WRITE || PAGECACHE_LOCK_READ); + page_link.unlock= (lock == PAGECACHE_LOCK_WRITE ? + PAGECACHE_LOCK_WRITE_UNLOCK : + PAGECACHE_LOCK_READ_UNLOCK); page_link.changed= 0; push_dynamic(&info->pinned_pages, (void*) &page_link); page->link_offset= info->pinned_pages.elements-1; @@ -209,14 +220,7 @@ my_bool _ma_write_keypage(MARIA_PAGE *page, enum pagecache_page_lock lock, } #endif -#ifdef IDENTICAL_PAGES_AFTER_RECOVERY - { - uint length= page->size; - DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE); - bzero(buff + length, block_size - length); - } -#endif - + page_cleanup(share, page); res= pagecache_write(share->pagecache, &share->kfile, (pgcache_page_no_t) (page->pos / block_size), diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c index 9e529aca666..daf1fd5a60c 100644 --- a/storage/maria/ma_rkey.c +++ b/storage/maria/ma_rkey.c @@ -82,6 +82,9 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data, rw_rdlock(&keyinfo->root_lock); nextflag= maria_read_vec[search_flag] | key.flag; + if (search_flag != HA_READ_KEY_EXACT || + ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME)) + nextflag|= SEARCH_SAVE_BUFF; switch (keyinfo->key_alg) { #ifdef HAVE_RTREE_KEYS diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index 77d9f22184d..d48749b1629 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -18,6 +18,10 @@ #include "ma_fulltext.h" #include "m_ctype.h" +static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, + uint32 nextflag, register my_off_t pos, + MARIA_PINNED_PAGE **res_page_link, + uchar **res_page_buff); static my_bool _ma_get_prev_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *keypos); @@ -57,7 +61,51 @@ int _ma_check_index(MARIA_HA *info, int inx) */ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, - register my_off_t pos) + my_off_t pos) +{ + int error; + MARIA_PINNED_PAGE *page_link; + uchar *page_buff; + + info->page_changed= 1; /* If page not saved */ + if (!(error= _ma_search_no_save(info, key, nextflag, pos, &page_link, + &page_buff))) + { + if (nextflag & SEARCH_SAVE_BUFF) + { + bmove512(info->keyread_buff, page_buff, info->s->block_size); + + /* Save position for a possible read next / previous */ + info->int_keypos= info->keyread_buff + (ulonglong) info->int_keypos; + info->int_maxpos= info->keyread_buff + (ulonglong) info->int_maxpos; + info->int_keytree_version= key->keyinfo->version; + info->last_search_keypage= info->last_keypage; + info->page_changed= 0; + info->keyread_buff_used= 0; + } + } + _ma_unpin_all_pages(info, LSN_IMPOSSIBLE); + return (error); +} + +/** + @breif Search after row by a key + + ret_page_link Will contain pointer to page where we found key + + @note + Position to row is stored in info->lastpos + + @return + @retval 0 ok (key found) + @retval -1 Not found + @retval 1 If one should continue search on higher level +*/ + +static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, + uint32 nextflag, register my_off_t pos, + MARIA_PINNED_PAGE **res_page_link, + uchar **res_page_buff) { my_bool last_key_not_used; int error,flag; @@ -66,6 +114,7 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, uchar lastkey[MARIA_MAX_KEY_BUFF]; MARIA_KEYDEF *keyinfo= key->keyinfo; MARIA_PAGE page; + MARIA_PINNED_PAGE *page_link; DBUG_ENTER("_ma_search"); DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu", (ulong) pos, nextflag, (ulong) info->cur_row.lastpos)); @@ -81,10 +130,11 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, } if (_ma_fetch_keypage(&page, info, keyinfo, pos, - PAGECACHE_LOCK_LEFT_UNLOCKED, - DFLT_INIT_HITS, info->keyread_buff, - test(!(nextflag & SEARCH_SAVE_BUFF)))) + PAGECACHE_LOCK_READ, DFLT_INIT_HITS, 0, 0)) goto err; + page_link= dynamic_element(&info->pinned_pages, + info->pinned_pages.elements-1, + MARIA_PINNED_PAGE*); DBUG_DUMP("page", page.buff, page.size); flag= (*keyinfo->bin_search)(key, &page, nextflag, &keypos, lastkey, @@ -98,8 +148,9 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, if (flag) { - if ((error= _ma_search(info, key, nextflag, - _ma_kpos(nod_flag,keypos))) <= 0) + if ((error= _ma_search_no_save(info, key, nextflag, + _ma_kpos(nod_flag,keypos), + res_page_link, res_page_buff)) <= 0) DBUG_RETURN(error); if (flag >0) @@ -118,26 +169,15 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME || (key->flag & SEARCH_PART_KEY) || info->s->base.born_transactional)) { - if ((error= _ma_search(info, key, (nextflag | SEARCH_FIND) & - ~(SEARCH_BIGGER | SEARCH_SMALLER | SEARCH_LAST), - _ma_kpos(nod_flag,keypos))) >= 0 || + if ((error= _ma_search_no_save(info, key, (nextflag | SEARCH_FIND) & + ~(SEARCH_BIGGER | SEARCH_SMALLER | + SEARCH_LAST), + _ma_kpos(nod_flag,keypos), + res_page_link, res_page_buff)) >= 0 || my_errno != HA_ERR_KEY_NOT_FOUND) DBUG_RETURN(error); - info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in mem */ } } - if (pos != info->last_keypage) - { - uchar *old_buff= page.buff; - if (_ma_fetch_keypage(&page, info, keyinfo, pos, - PAGECACHE_LOCK_LEFT_UNLOCKED,DFLT_INIT_HITS, - info->keyread_buff, - test(!(nextflag & SEARCH_SAVE_BUFF)))) - goto err; - /* Restore position if page buffer moved */ - keypos= page.buff + (keypos - old_buff); - maxpos= page.buff + (maxpos - old_buff); - } info->last_key.keyinfo= keyinfo; if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0) @@ -172,16 +212,15 @@ int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag, } info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key); info->cur_row.trid= _ma_trid_from_key(&info->last_key); - /* Save position for a possible read next / previous */ - info->int_keypos= info->keyread_buff + (keypos - page.buff); - info->int_maxpos= info->keyread_buff + (maxpos - page.buff); - info->int_nod_flag=nod_flag; - info->int_keytree_version=keyinfo->version; - info->last_search_keypage=info->last_keypage; - info->page_changed=0; - /* Set marker that buffer was used (Marker for mi_search_next()) */ - info->keyread_buff_used= (info->keyread_buff != page.buff); + /* Store offset to key */ + info->int_keypos= (uchar*) (keypos - page.buff); + info->int_maxpos= (uchar*) (maxpos - page.buff); + info->int_nod_flag= nod_flag; + info->last_keypage= pos; + *res_page_link= page_link; + *res_page_buff= page.buff; + DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos)); DBUG_RETURN(0); @@ -190,7 +229,7 @@ err: info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed=1; DBUG_RETURN (-1); -} /* _ma_search */ +} /* diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 20304618229..3b9ca46899f 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -587,6 +587,12 @@ my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, my_off_t *root) /* Search after a position for a key and store it there + TODO: + Change this to use pagecache directly instead of creating a copy + of the page. To do this, we must however change write-key-on-page + algorithm to not overwrite the buffer but instead store any overflow + key in a separate buffer. + @return @retval -1 error @retval 0 ok diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 1d60beece6b..29eb32a4fb2 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -979,6 +979,11 @@ extern ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from); #define page_store_info(share, page) \ _ma_store_keypage_flag((share), (page)->buff, (page)->flag); \ _ma_store_page_used((share), (page)->buff, (page)->size); +#ifdef IDENTICAL_PAGES_AFTER_RECOVERY +void page_cleanup(MARIA_SHARE *share, MARIA_PAGE *page) +#else +#define page_cleanup(A,B) while (0) +#endif extern MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr, uchar *key, const uchar *record, @@ -1197,7 +1202,7 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info, my_bool log_incomplete); my_bool _ma_reenable_logging_for_table(MARIA_HA *info, my_bool flush_pages); my_bool write_log_record_for_bulk_insert(MARIA_HA *info); - +void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn); #define MARIA_NO_CRC_NORMAL_PAGE 0xffffffff #define MARIA_NO_CRC_BITMAP_PAGE 0xfffffffe diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index 5e550b9dff5..aa209e082e0 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -45,7 +45,7 @@ static int ft_add_stopword(const char *w) { FT_STOPWORD sw; return !w || - (((sw.len= (uint) strlen(sw.pos=w)) >= ft_min_word_len) && + (((sw.len= (uint) strlen(sw.pos=(const uchar *)w)) >= ft_min_word_len) && (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL)); } diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 1b92d64d529..d5ce941bf75 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -192,6 +192,13 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, options|= HA_OPTION_CHECKSUM; min_pack_length++; } + /* + Don't set HA_OPTION_NULL_FIELDS if no checksums, as this flag makes + that file incompatible with MySQL. This is ok, as this flag is only + used if one specifics table level checksums. + */ + if (!(options & HA_OPTION_CHECKSUM)) + options&= ~HA_OPTION_NULL_FIELDS; if (flags & HA_CREATE_DELAY_KEY_WRITE) options|= HA_OPTION_DELAY_KEY_WRITE; if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index 37523a9acca..a3c700794f9 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1493,20 +1493,54 @@ static int _mi_read_rnd_mempack_record(MI_INFO*, uchar *,my_off_t, my_bool); my_bool _mi_memmap_file(MI_INFO *info) { MYISAM_SHARE *share=info->s; + my_bool eom; + DBUG_ENTER("mi_memmap_file"); if (!info->s->file_map) { + my_off_t data_file_length= share->state.state.data_file_length; + + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + eom= data_file_length > myisam_mmap_size - myisam_mmap_used - MEMMAP_EXTRA_MARGIN; + if (!eom) + myisam_mmap_used+= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } + else + eom= data_file_length > myisam_mmap_size - MEMMAP_EXTRA_MARGIN; + + if (eom) + { + DBUG_PRINT("warning", ("File is too large for mmap")); + DBUG_RETURN(0); + } if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) < share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN) { DBUG_PRINT("warning",("File isn't extended for memmap")); + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } DBUG_RETURN(0); } if (mi_dynmap_file(info, share->state.state.data_file_length + MEMMAP_EXTRA_MARGIN)) + { + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } DBUG_RETURN(0); + } } info->opt_flag|= MEMMAP_USED; info->read_record= share->read_record= _mi_read_mempack_record; @@ -1519,6 +1553,13 @@ void _mi_unmap_file(MI_INFO *info) { VOID(my_munmap((char*) info->s->file_map, (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN)); + + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= info->s->mmaped_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } } diff --git a/storage/myisam/mi_static.c b/storage/myisam/mi_static.c index a3ba785a94f..27485e101ff 100644 --- a/storage/myisam/mi_static.c +++ b/storage/myisam/mi_static.c @@ -40,7 +40,7 @@ ulong myisam_concurrent_insert= 0; my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_data_pointer_size=4; - +ulonglong myisam_mmap_size= SIZE_T_MAX, myisam_mmap_used= 0; static int always_valid(const char *filename __attribute__((unused))) { diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index f2528f2ec60..6ad23154b45 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -735,10 +735,12 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, } end=page+length-key_ref_length; + DBUG_ASSERT(page < end); *key='\0'; length=0; lastpos=page; - while (page < end) + + do { prevpos=lastpos; lastpos=page; last_length=length; @@ -749,7 +751,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); } - } + } while (page < end); + *return_key_length=last_length; *after_key=lastpos; DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx end: 0x%lx", diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 48e5d92a9a9..7eb7089f38c 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -392,7 +392,6 @@ struct st_myisam_info #define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1))) #define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32)) -#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */ #define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */ #define PACK_TYPE_SPACE_FIELDS 2 diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 9be80dab4eb..0d4ab20a834 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -382,7 +382,7 @@ static MI_INFO *myisammrg_attach_children_callback(void *callback_param) my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; } DBUG_PRINT("myrg", ("MyISAM handle: 0x%lx my_errno: %d", - (long) myisam, my_errno)); + my_errno ? NULL : (long) myisam, my_errno)); err: DBUG_RETURN(my_errno ? NULL : myisam); diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c index f010ce93fe3..ce07b99c611 100644 --- a/storage/xtradb/btr/btr0cur.c +++ b/storage/xtradb/btr/btr0cur.c @@ -3233,7 +3233,7 @@ btr_estimate_number_of_different_key_vals( ulint matched_bytes; ib_int64_t n_recs = 0; ib_int64_t* n_diff; - ib_int64_t* n_not_nulls; + ib_int64_t* n_not_nulls= 0; ullint n_sample_pages; /* number of pages to sample */ ulint not_empty_flag = 0; ulint total_external_size = 0; |